git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Git alias syntax help

From
Jeff King <peff@peff.net>
Date
Jan 14, 2020, 22:28 UTC
Message-ID
<20200114222802.GC3957260@coredump.intra.peff.net>
In-Reply-To
<CAHMHMxWpLAnj3w8DGLMFbfy-A-pBjDxNdMeiM-fyuu-gnZyg+Q@mail.gmail.com>
On Tue, Jan 14, 2020 at 05:21:20PM +0200, Σταύρος Ντέντος wrote:
Show 8 quoted lines
> 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.

Show 10 quoted lines
> 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
Previous: Σταύρος ΝτέντοςNext: Σταύρος Ντέντος
Message 2 of 5 in “Git alias syntax help”
  1. Σταύρος ΝτέντοςJan 14, 2020
  2. Jeff KingJan 14, 2020
  3. Σταύρος ΝτέντοςJan 14, 2020
  4. Jeff KingJan 15, 2020
  5. Philip OakleyMar 28, 2020

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.