A post mainly to refer back to when I inevitably forget this. 🙂
Inside its aliases, git supports executing non-git commands.
Since version 1.5.0, Git supports aliases executing non-git commands, by prefixing the value with “!”:
Much like with ‘normal’ git aliases, whatever parameters are passed to the alias are passed along when the alias is expanded.
Starting with version 1.5.3, git supports appending the arguments to commands prefixed with “!”, too.
This is normally a Very Good Thing, since it allows you to alias things like co = checkout and then ‘git co blah’ will do ‘git checkout blah’ without you having to do any parameter parsing/passing yourself.
To see this happen when git is running non-git command (using the ! syntax), we can add a simple test alias like this:
testing = !echo foo && echo arg1=$1 && echo arg2=$2 && echo args=$@ && echo bar
And when calling it with a couple of parameters, we can see that they’re available inside the command, but they’re also added onto the end (as per normal git alias behavior), so our last line isn’t “bar” but instead “bar abc xyz”
There might be other methods that work to get around this, but the only one I’ve run across so far that works fine with msysgit on Windows running in PowerShell is using the “sh” shell intermediary. We’ll invoke sh -c ‘XXX’ – (make sure to include the final dash, or you’ll lose your first passed param)
testing = !sh -c ‘echo foo && echo arg1=$1 && echo arg2=$2 && echo args=$@ && echo bar’ –
With that in place, now we get the behavior we’re hoping for, since we’re passing it explicitly to sh instead – git it still passing the parameters at the end, but now we’re telling sh exactly what to execute.
What’s really sad about this is that, at least in my testing scenario, we’re actually now inside a second shell. Using the debugger flags or procexp or whatever, you can see the actual command line that git executes:
sh -c “sh -c ‘echo foo && echo arg1=$1 && echo arg2=$2 && echo args=$@ && echo bar’ – \”$@\”” “sh -c ‘echo foo && echo arg1=$1 && echo arg2=$2 && echo args=$@ && echo bar’ -” abc xyz
While it’s not as useful IMHO as seeing exactly what is being run from the OS point of view, you might find it helpful to enable GIT_TRACE to see git’s internal tracing to get an idea of how it processes the alias and command.
The particular code path(s) involved are in git’s run-command.c
For instance, the “trace: run_command:” can be found (currently) at line 336)
So, who knows – maybe having to do the sh -c is just working around a bug in this version of msysgit (since they appear to be doing pretty much the same thing). It *does* seem like that version of git might be getting built without WIN32 being defined (likely for good reason, I’m sure, I just can’t tell for sure at the moment).
Certainly it’d be nice if there were a git alias syntax that “opted out” of git passing the arguments at the end of the executed command (for instance foo = !!some $1 | command && here), but AFAICT that doesn’t exist (yet?) so for now, hopefully this will suffice. 🙂