On Tue, Jan 14, 2020 at 05:21:20PM +0200, Σταύρος Ντέντος wrote: > I am having an issue with git-aliases - specifically, the intricacies > involved in their syntax. > > In general, the syntax is confusing to me, especially when it is > _wise_ to use quotes inside a `!sh` alias. > e.g. which one would be the correct one > new = "!f() { : git log ; git log \"${1}@{1}..${1}@{0}\" \"$@\" ; } ; f" > new = !f() { : git log ; git log "${1}@{1}..${1}@{0}" "$@" ; } ; f Only the first one is correct. In addition to the quotes in the second one being eaten by the config parser, the unquoted semicolon starts a comment. > The alias confusing me is more specifically this: > https://git.wiki.kernel.org/index.php/Aliases#simple_diff_ignoring_line_number_changes > > diffsort = !sh -c 'git diff "$@" | grep "^[+-]" | sort --key=1.2 | uniq -u -s1' > > The output of: > $ colordiff -su <(git diffsort HEAD^..HEAD) <(git diffsort HEAD^^..HEAD^) > Files /dev/fd/63 and /dev/fd/62 are identical > is a little unexpected, since I know for a fact that one of the > referced commits is not a code block moved. The issue here isn't with Git's alias mechanism, but a quirk of how "sh -c" works. You can run with GIT_TRACE to see what we're passing to the shell (though note that your double-quotes don't make it through): $ GIT_TRACE=1 git diffsort HEAD^..HEAD 17:22:47.644542 [pid=3959333] git.c:708 trace: exec: git-diffsort HEAD^..HEAD 17:22:47.644648 [pid=3959333] run-command.c:663 trace: run_command: git-diffsort HEAD^..HEAD 17:22:47.645038 [pid=3959333] run-command.c:663 trace: run_command: 'sh -c '\''git diff $@ | grep ^[+-] | sort --key=1.2 | uniq -u -s1'\''' HEAD^..HEAD 17:22:47.650319 [pid=3959336] git.c:439 trace: built-in: git diff The problem is that "sh -c" takes the first non-option argument as $0, not $1. For example: $ sh -c 'echo 0=$0, @=$@' foo bar baz 0=foo, @=bar baz You can add any extra string there to become $0, like: diffsort = "!sh -c 'git diff \"$@\" | grep \"^[+-]\" | sort --key=1.2 | uniq -u -s1' --" which will do what you want. You can use whatever string you like, since you know that your "-c" snippet does not ever look at $0. -Peff