14

When merging two branches, many times the merge fails, and I have to resolve the diffs individually.

Some files merge successfully, and I can see the diff:

git diff --staged <merged-file>

The problem is that for unmerged paths, when I try to check the diffs introduced, I see nothing:

git diff <unmerged-file>

But when I try to diff it against the remote master branch, then the diffs appear:

git diff origin/master <unmerged-file>

Why is this happening? Is the merge operation updating my local HEAD or something?
Moreover, when i use git add to mark resolution, they never go into the staging area -- is that the reason why git diff is not showing anything?

Rob Bednark
  • 25,981
  • 23
  • 80
  • 125
Kartik Anand
  • 4,513
  • 5
  • 41
  • 72
  • You might be missing some extra details in your question. What branch are you merging into what branch? In your example, are you in `master`, or you merged `master` into your branch? Upon trying a similar situation myself `diff`ing a conflicted file printed the expected output with the `>>> === <<<` markers. – Maic López Sáenz Mar 14 '14 at 21:24
  • @LopSae I'm merging a development branch into master. Diffing a conflicted file doesn't show anything but the header information. It looks like it know that the diff exists but doesn't know what. – Kartik Anand Mar 16 '14 at 12:59
  • You should add those details to the question itself, including too what you are seeing on your `git diff`. If the file changes you are merging are simple enough you could also add them as part of the description, or create a simplified example to show how to reproduce the issue. – Maic López Sáenz Mar 17 '14 at 02:46

3 Answers3

22

During a merge, the conflicting files are in a special state. There exists multiple entries with the same filename and different blob id's. These are usually three blobs (used for the three way merge) or two blobs (for a simple merge).

Attempt the merge..

$ git merge origin/otherbranch
Merge remote-tracking branch 'origin/otherbranch' into mybranch

Conflicts:
    somefile.txt

Review the files which need merging

$ git diff --name-status --diff-filter=U
U       somefile.txt

or

$ git update-index --refresh
somefile.txt: needs merge

Review the blobs which relate to the file being merged;

$ git ls-files -s somefile.txt
100644 9a0579524e0c7ba9fc9ae18badadaddcad2d598f **1** somefile.txt
100644 1bcff16b6de5ed304a06e643070e40787db1ead8 **2** somefile.txt
100644 6e52271b22f6a6d1150619433551e0fa9094b108 **3** somefile.txt

According to the git-merge man-page. 1 = common ancenstor, 2 = HEAD (ours) and 3 = MERGE_HEAD (theirs)

Show differences

$ git diff 9a0579524e0c7ba9fc9ae18badadaddcad2d598f 6e52271b22f6a6d1150619433551e0fa9094b108
< some differences >

Retrieve the common ancestor..

$ git cat-file blob 9a0579524e0c7ba9fc9ae18badadaddcad2d598f

Checkout version from HEAD

$ git checkout --ours somefile.txt

checkout version from MERGE_HEAD

$ git checkout --theirs somefile.txt

Reset to 'merged' changed

$ git checkout -m somefile.txt

Update:

This has simplified somewhat with the use of <ref>:ID:Filepath eg

git diff :1:somefile.txt :2:somefile.txt

Will give you the difference between the two parents in a merge. 0 represents a completed merge 1 represents a conflicting merge 2/3 represent the two parents of the merge.

If you have a completed merge at a particular commit xxxxxx, you can refer to its parents using xxxxxx^0 (merged file) xxxxxx^1 "left" parent, and xxxxxx^2 "right" parent. Comparing the merged files to its ancestors can be done as follows;

git diff xxxxxx^0:somefile xxxxxx^1:somefile
Dave
  • 3,193
  • 1
  • 16
  • 14
  • 1
    The question has a good amount of detail and it is useful, but does not actually answer the question. – Maic López Sáenz Mar 14 '14 at 21:41
  • @LopSae Yes! exactly, that's why I don't understand if I should give him bounty or not – Kartik Anand Mar 16 '14 at 12:57
  • You are not required to select the most up voted question as the answer, unless you agree that it is indeed the answer. Also by not selecting an answer as accepted (in this case your own) you will have more participation from the community, specially when the bounty is ongoing. – Maic López Sáenz Mar 17 '14 at 02:50
  • @LopSae My question then is, what is the question? If you read the original question, it describes a specific problem and asks "Why is this happening?". It seems the answer selected answers the question "How do I use diff on a merged file", which is obviously easy. – Dave Mar 26 '14 at 21:43
  • This was so useful, thank you so much. When I run `git ls-files -s ` sometimes I get the file with the number `0` and other times, I get only `2` and `3` without 1, what does that mean? – tarekahf Aug 08 '22 at 15:45
  • Also, after you use the git checkout command to choose the correct version, how you can tell later on which version was used? Was it from `ours`, `theirs`, or somewhere else? – tarekahf Aug 08 '22 at 18:20
  • @tarekahf Thats a good question. If commit `xxx` is a merge, you can do `git diff xxx:path/to/file xxx^1:path/to/file`, and `git diff xxx:path/to/file xxx^2:path/to/file` to see how the file differs from its merge parents. The result can help you identify which parent contributed to the current version – Dave Aug 10 '22 at 04:15
8

The only way I'm able to see the changes for conflict files is:

git diff --merge <unmerged-file>
Kartik Anand
  • 4,513
  • 5
  • 41
  • 72
0

You haven't pushed your merged changes to remote branch. Merging only affects local branch. So diff exists between local and remote branch.

Shashwat Kumar
  • 5,159
  • 2
  • 30
  • 66