user10082400
user10082400

Reputation:

What does `git show` with two nonoption arguments mean?

The manpage of git show says

git show [<options>] [<object>…]

From https://stackoverflow.com/a/7196615

git show some_commit_sha1 -- some_file.c

What does the command mean?

Are both some_commit_sha1 and some_file.c <object> arguments?

Is it the same as

git show -- some_commit_sha1 some_file.c

Thanks.

Upvotes: 1

Views: 105

Answers (1)

torek
torek

Reputation: 489638

They're not both <object> arguments, and the documentation here is not very good. However, git show is a user-oriented ("porcelain") command and using it to pipe to other Git commands is not generally good practice in the first place.

In this particular case, git show <commit> -- <path> winds up invoking the equivalent of git log --no-walk --cc <commit> -- <path>. That is, it first runs the same code as git log --no-walk to produce the log message for that particular commit, formatted according to any format directives (none, so this defaults to --pretty=medium). Then it produces a diff listing, even if the commit is a merge commit—by default, git log does not produce a diff listing for merge commits, hence the --cc option.

The various git diff commands—both the porcelain git diff itself, and the plumbing variants git diff-tree, git diff-files, and git diff-index—all allow you to specify particular pathnames or pathspecs. Normally it's pretty clear whether something is a pathname (e.g., README.txt) or a commit-specifier (e.g., master). There are ambiguous cases, though: what if you have a file named master?

To distinguish pathname / pathspec arguments from commit-specifiers in these ambiguous cases, these commands use the -- convention defined by the POSIX specifications for utility commands (see Guideline 10 in particular). That is:

git diff-tree master -- develop

tells git diff-tree that the commit you want is master and the file you care about is named develop, while:

git diff-tree develop -- master

tells git diff-tree that the commit is develop and the file is master, and:

git diff-tree develop master -- release

tells git diff-tree that the two commits are develop and master in that order, while the file is release. Note that git diff-tree takes up to two <tree-ish> arguments: when given only one such argument, the implication is that the one argument is a commit specifier, and Git should diff the commit's parent(s) against the commit.

Conclusions

  1. For reliability (to avoid getting tripped up by various diff configuration items, such as forced use of color sequences via color.diff=always), the command in the answer to which you linked really should read:

    git diff-tree -p <commit> -- <file> | git apply -R
    

    (the -p option to diff-tree turns on the -r option).

  2. The git show documentation, particularly the synopsis line, is inadequate. An improvement, not necessarily complete, would read:

    git show [<options>] [<object>...] [--] [<path>...]
    

Upvotes: 2

Related Questions