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