Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git: see changes on their branch since last merge on merge conflict

Tags:

git

git-merge

I thought that my scenario should be fairly common, and there must be a simpler way of doing what I do. Suppose there are two branches, current and next, for two lines of development. next at this stage receives all changes from the current branch. Being maintainer of the next branch I am syncing the changes (as necessary for alpha releases) like this:

$ git co origin/next -b next
$ git merge origin/current

Some files changed their format on the next, and every change to these few files made since the last sync-merge results in a conflict. To resolve this conflict, I need to see the changes on the current branch since the previous merge. Usually many files have changed, but only 1 or 2 files like those I mentioned are conflicting.

Example

Suppose that the file baz.dat on the current branch contains words in square brackets, like

[real]
[programmers]
[use]
[pascal]

On the next branch, the syntax change demands that the words be surrounded with colons instead

:real:
:programmers:
:use:
:pascal:

A change on the current branch has added a line to the file:

[real]
[programmers]
[don't]
[use]
[pascal]

Every time a merge conflict results in the following diff merge marks:

<<<<<<< ours
:real:
:programmers:
:use:
:pascal:
=======
[real]
[programmers]
[don't]
[use]
[pascal]
>>>>>>>> theirs

Whole file content deleted and replaced, because it, in a sense, is.

Similarly, just git diff shows all incoming, "their" lines as deleted and "our" lines as added:

$ git diff
<usual unified diff preamble>
+  :real:
... more lines with "+ " (our new) or " -" (their deleted) mark, 
 - [pascal]

What I am looking for

A way to see what changed on the current ("their") branch since I last merged, so I can manually incorporate the change into the next ("our") branch

$ git diff --magically-from-merge-point --theirs
<usual unified diff preamble>
+ [don't]

In other words, I want to see in this example case that only one line was added, so I can insert it in the new format as well.

(My real case is a change in a domain-specific language, but it essentially very similar to this trivial example).

Current solution

What I am resorting to do is a rather unwieldy series of commands:

$ git status 
. . . .
      both modified:   foo/bar/baz.dat <== copy/paste every conflict filename
$ git diff `git merge-base HEAD origin/current`..origin/current -- foo/bar/baz.dat

This shows what I want, but rather complex, and I construct and type it every time. It is easy enough to script in bash, but before I do that I want to ask is there a simpler way to see the conflicting changes from merge base? I. e.

(next)$ git merge origin/current
. . . 
CONFLICT (content): foo/bar/baz.dat
(next|MERGING)$ git diff --magic-switch

and diff would show changes only for conflicting files as a delta between the merge base and the point of merge (which I would, in the ideal case, further restrict with e. g. --magic-switch --theirs)

Does such a magic switch exist? Looks like I am missing something obvious!

like image 904
kkm Avatar asked Oct 16 '25 14:10

kkm


1 Answers

git mergetool will open the conflicting files, one by one, in your diff editor of choice (meld, vimdiff, kdiff3, winmerge ...), as a 3 way merge between the 3 versions :

  • local : version in the current branch (in your case : next's version)
  • base : version in the merge-base commit
  • remote : version in the merged branch (in your case : origin/current's version)

If you edit + save the central file, git will mark this conflict as solved, an stage what you saved in the index.


If your merge halted due to conflict, git stores a ref to the merged commit in .git/MERGE_HEAD. This means that you can use the string "MERGE_HEAD" as a valid reference in git commands :

git log -1 MERGE_HEAD            # view last commit on the merged branch
git merge-base MERGE_HEAD HEAD   # no need for the name of the branch

You can then build a simpler alias :

theirs = 'git diff $(git merge-base MERGE_HEAD HEAD) MERGE_HEAD'
# usage :
git theirs                  # complete diff between 'base' and 'theirs'
git theirs -w -- this/file  # you can add any option you would pass to 'git diff'
like image 128
LeGEC Avatar answered Oct 18 '25 06:10

LeGEC



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!