void.pointer
void.pointer

Reputation: 26345

`git show` giving confusing results on merge commits

I have always understood git show to never show a diff on a merge commit. Probably for the same reason git log -p doesn't show a diff on merge commits. However, I am able to create two reproducible scenarios: A merge commit that does produce a diff with git show and one that does not. I would like to understand why the behavior of git show is different between these scenarios.

First, here is a script I ran which creates the repository required to observe the two scenarios above:

#!/usr/bin/env bash
set -ex

git init test_repo
cd test_repo

# master (commit 1)
printf "one\n" > file.txt
git add file.txt
git commit -m one

# master (commit 2)
printf "two\n" >> file.txt
git commit -am two

# master (commit 3)
printf "three\n" >> file.txt
git commit -am three

# topic1 (commit 1)
git checkout -b topic1 @^
printf "four\n" >> file.txt
git commit -am four

# merge topic1 to master (commit 4)
git checkout master
git merge - || true # conflict
printf "one\ntwo\nthree\nfour\n" > file.txt
git add file.txt
git commit --no-edit
git tag merge1 # tag so we can refer to it in examples

# master (commit 5)
printf "five\n" >> file.txt
git commit -am five

# topic2 (commit 1)
git checkout -b topic2
printf "six\n" >> file.txt
git commit -am six

# merge topic2 to master (commit 6)
git checkout master
git merge --no-edit - # no conflict
git tag merge2 # tag so we can refer to it in examples

Scenario 1: git show shows a diff:

$ cd test_repo
$ git show merge1
commit cb7aba11aed80917e3fac64e60aef3fe0a27e5de (tag: merge1)
Merge: 75bae65 5f63df7
Author: John Doe <[email protected]>
Date:   Wed Jun 19 14:05:34 2019 -0500

    Merge branch 'topic1'

    # Conflicts:
    #       file.txt

diff --cc file.txt
index 4cb29ea,87a123c..f384549
--- file.txt
+++ file.txt
@@@ -1,3 -1,3 +1,4 @@@
  one
  two
 +three
+ four

Scenario 2: git show does not show a diff:

$ cd test_repo
$ git show merge2
commit 5f37be9b563afc9c9f43ad04198d80809e6fc13a (HEAD -> master, tag: merge2)
Merge: 6f4cf36 bde33e8
Author: John Doe <[email protected]>
Date:   Wed Jun 19 14:05:34 2019 -0500

    Merge branch 'topic2'

The main difference between the two scenarios (e.g. merge1 and merge2) is that merge2^ refers to the merge base of topic2 and master (before the merge) and merge1^ is a unique, non-merge commit. I'm not sure if this intermediate commit being between the merge base and the merge commit matters, but I can't think of anything else it could be. Can anyone explain this difference in behavior?

What I expect is that git show merge1 does not show a diff. As far as I am concerned, git show merge2 output is correct, and git show merge1 is incorrect (buggy).

Git version is 2.22.0 on Windows.

Upvotes: 1

Views: 44

Answers (2)

torek
torek

Reputation: 488003

git show produces combined diffs by default. (This is an improvement over git log -p, which, for merge commits, produces no diffs at all by default!)

Combined diffs are documented—somewhat poorly in my opinion—in two separate sections that show up in several of the various git diff command manual pages. Here are the two critical sections from the git diff-tree documentation:

The first section, near the bottom, has this caveat:

Note that combined diff lists only files which were modified from all parents.

This should probably be boldface, 18-point font, and/or blinking and not quite so far from the second section that tells you how to read the output. (The -p description has its own section between these two. Also, the first section is talking about the mode-line stuff, but the fact that many files are omitted entirely applies to the second section, it's just not mentioned in the second section.)

I think the goal here is to make the default git show output show you where someone might have had to do conflict resolution. That's usually a good idea, but sometimes you really want git show -m, which just shows one diff against the first parent, and then a second diff against the second parent.

Upvotes: 2

eftshift0
eftshift0

Reputation: 30174

git show will show diff stuff if there was a conflict resolution.

Upvotes: 0

Related Questions