When you define a Git alias with !
in order to have it execute a shell command (rather than the default behavior of passing arguments to git
), Git uses:
- on Unix-like platforms: the default shell,
/bin/sh
- on Windows: the Bash version that comes bundled with Git
Therefore, in order to define a Git alias that executes a PowerShell command, you must invoke PowerShell's CLI explicitly and pass the command to it via the -c
parameter:
Here's a full example; note that it assumes PowerShell Core; for Windows PowerShell, replace pwsh
with powershell
:
# Run from PowerShell
# Define the alias.
# Note the unexpected need to escape " as \" - see below.
git config --global alias.unchanged '! pwsh -noprofile -c \"git ls-files -v | sls -pattern ^h -casesensitive\"'
# Invoke it.
git unchanged
As an aside: Note the awkward need to \
-escape the embedded "
chars., even though they're inside a single-quoted string '...'
- this unfortunate requirement - which seemingly won't be removed for the sake of backward compatibility - is discussed in this GitHub issue.
As for what you tried:
Defining your alias as:
[alias]
unchanged = !git ls-files -v | sls -pattern ^h -casesensitive
means that sh
/ bash
is executing the command, as explained above.
While the command is syntactically valid there, it fails because sls
is looked for as an external program (given that it is neither a sh
/ bash
builtin, nor a user-defined function, nor a sh
/ bash
alias), which doesn't exist ("command not found
").
Only PowerShell knows that sls
is an alias for the Select-String
cmdlet (and even using the latter's actual name wouldn't allow it to be called from outside of PowerShell, given that it is implemented via a PowerShell-specific DLL).
By contrast, git ls-files -v
by itself works in sh
/ bash
as well, because it is a call to git
, an external program (a platform-native executable that any shell can call).