akraf
akraf

Reputation: 3255

Show a combined diff of a merge commit, including added files by either parent branch

After doing a merge which includes changes of a coworker, I want to them, to outline wheat each of us changed and how I resolved the conflicts.

The standard way that git displays merges, however, is not adequate for this, because it shows only chunks that each of us modified. So by default, git show MERGE_COMMIT only shows how manual merge conflicts were resolved.

What I need: To see all changes, that happened from the time that the branches diverged, even if there were no merge conflicts, and attribute them to one of the parents.

git show -c and -m are not enough: I figured out that there are the arguments to git diff-tree which are also understood by git show, namely -m, -c, and --cc

Toy example Base commit creates file, branch A adds some lines, branch B adds some lines, one at the same position as A, creating a conflict. Furthermore, both A and B add file_a and file_b, respectively:

git init
# Add content to "file" to modify later
for f in `seq 1 15`; do echo "Line $f" >> file; done
git add file && git commit -m "initial commit"

# Divergent branch A: add "change a" to file and add new file_a
sed -i "s/Line 2/Line 2\nchange a/" file
sed -i "s/Line 10/Line 10\nchange a/" file
echo change a > file_a
git add . && git commit -m "change a"

# Divergent branch B: add "change b" to file and add new file_b
git checkout -b dev master~
sed -i "s/Line 14/Line 14\nchange b/" file
sed -i "s/Line 10/Line 10\nchange b/" file
echo change b > file_b
git add . && git commit -m "change b"

git checkout master
git merge dev
## Auto-merging file
## CONFLICT (content): Merge conflict in file
## Automatic merge failed; fix conflicts and then commit the result.

# Create the union -- remove the conflict markers
sed -i "/^[^Lc].*$/d" file
cat file
## Line 1
## Line 2
## change a
## [...]
## Line 10
## change a
## change b
## [...]
## Line 14
## change b
## Line 15

git add . && git commit -m "Merge 'dev' into 'master'"

The standard option only shows the line where the merge conflict was (two branches modified the same line)

git show HEAD:

[...]
diff --cc file
index 2fe2e63,019eb18..92b6fb7
--- a/file
+++ b/file
@@@ -9,7 -8,7 +9,8 @@@ Line 
  Line 8
  Line 9
  Line 10
 +change a
+ change b
  Line 11
  Line 12
  Line 13

It is a bit better with git show -c HEAD, this shows the other two hunks in file which were resolved automatically:

[...]
diff --combined file
index 2fe2e63,019eb18..92b6fb7
--- a/file
+++ b/file
@@@ -1,6 -1,5 +1,6 @@@
  Line 1
  Line 2
 +change a
  Line 3
  Line 4
  Line 5
@@@ -9,9 -8,10 +9,11 @@@ Line 
  Line 8
  Line 9
  Line 10
 +change a
+ change b
  Line 11
  Line 12
  Line 13
  Line 14
+ change b
  Line 15

What is still missing is file_a and file_b, which do not show up.

Upvotes: 1

Views: 145

Answers (1)

jthill
jthill

Reputation: 60487

git show -c gets you what you want, combined diffs for the ordinary modifications, except it doesn't list the things like adds and deletes where there's no diffs to combine, so (for example) git show -m --oneline --raw first to list all the changes, followed by -c to show combined diffs where that makes sense. Add --diff-filter=m to skip the header if there's no adds/deletes, keeping the two sets non-overlapping.

git show -m --oneline --raw; git show -c --oneline`

or

git show -m --oneline --raw --diff-filter=m; git show -c --oneline

Upvotes: 2

Related Questions