I've been getting my feet wet in writing git aliases that take arguments. I've seen some people running shell scripts with
[alias]
shAlias = !sh -c \" ... \"
and others running functions with
[alias]
fAlias = "!f() { ... ; }; f"
It seems like (once I get up to speed on Bash — this isn't where I am yet) any of the things I've thought to do would be doable with either form.
In what circumstances is one preferable over the other?
Beyond feasibility, are there processing differences? Memory use / speed / etc?
TL;DR: Use the function approach for the simplest of commands, and switch to an external script once you have any kind of issue with quoting. Just avoid sh -c all together.
We can have a look at the git source. It parses out quotes in a git specific way, executes as a file if the result has no shell metacharacters (including space), or executes the equivalent of execlp("sh", "-c", "result \"$@\"", "result \"$@\"", args...) otherwise.
Based on that, the best way to create an alias is definitely to create an external script and using:
[alias]
myAlias = !/path/to/script
It requires an external file, but in all other ways it's better:
bash code since you ask, while the other forms only allow you to run sh code (the difference is like C++ vs C).git will execve your executable directly.git knowledge needed. It's just a script.Out of your suggestions, the runner up is:
[alias]
fAlias = "!f() { ... ; }; f"
This is less awesome because:
sh, and therefore not use any bash features.git specific escaping is required for quotes.git's escaping, but can generally get by without knowing exactly how it executes the command because you'll just use the function's arguments.The last one is by far the worst:
[alias]
shAlias = !sh -c \" ... \"
It's awful because:
sh.git escaping and also an additional level of sh escaping.sh, how to double-escape that with git, and how git appends "$@" to your command if there are additional arguments, and passes additional parameters as $1, $2. To demonstrate the practical difference, let's say you wanted to make an alias for this command to get the path on a remote server via ssh:
ssh "$1" 'echo "$PATH"'
You can either copy-paste it verbatim to a file, add a shebang, and use:
[alias]
get-remote-path = !/path/to/my/script
Or you can add a bit of git escaping and use the function approach:
[alias]
get-remote-path = "!f() { ssh \"$1\" 'echo \"$PATH\"'; }; f"
Or we can laboriously escape and escape again with the sh -c approach (no, it doesn't work without the last word):
[alias]
get-remote-path = !sh -c 'ssh \"$1\" '\\''echo \"$PATH\"'\\' cthulhu
Clearly, it's better to use a script, or at worst the function approach until you need more complicated commands that you can comfortably quote.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With