Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I summarise a merge to detect erroneous `git merge -s ours`?

Tags:

Several times in the past, we have had a problem where developers have (either explicitly or effectively) done a git merge -s ours when they shouldn't have, commits have been lost and we have only detected this much later when the cleanup is much more complex and time consuming. Tests didn't fail because the very commits which added the tests were silently reverted along with the code they were testing.

What I would like to do is find or create a tool which summarises a merge, producing an output something like the following with an normal merge:

Lines              Left(2b3c4d) Right(3c4d5e) Common with base   970          930 Unique wrt base    20            50 Unique wrt other   15            45 Unique wrt merge   15            45 Common with merge  995          985 

But in the case where a merge was incorrectly done, reverting out many changes, or where a git merge -s ours was performed, it might result in a report something like:

Lines              Left(2b3c4d) Right(3c4d5e) Common with base   970          930 Unique wrt base    20            50 Unique wrt other   15            45 Unique wrt merge   15             0 !! Common with merge  990          935 Warning: 100% of changes from 3c4d5e are missing from merge commit! 

If this report were run for every commit, we could flag up (through a jenkins job) whenever a merge was a little on the smelly side.

So far I have been playing with git diff --stat, git diff --name-status and git diff --summary but so far none give me quite what I want.

The best I can do so far would result in something like the following for a normal merge:

              base..left   base..right  left..merge  right..merge               f67c4..a9eb4 f67c4..5b592 a9eb4..cb209 5b592..cb209  a    |                    1 +          1 +            b    |       1 +                                    1 +  base |       1 +          1 +          1 +          1 + changed       2            2            2            2 insertions(+) 2            2            2            2 deletions(-)  0            0            0            0 

and for an ours merge:

              base..left   base..right  left..merge  right..merge               f67c4..a9eb4 f67c4..5b592 a9eb4..95637 5b592..95637  a    |                    1 +                       1 -  b    |       1 +                                    1 +  base |       1 +          1 +                       2 +- changed       2            2            0            3 insertions(+) 2            2            0            2 deletions(-)  0            0            0            2 

Note that I don't only want to detect a -s ours merge, I also want to catch the situation where some but not all changes are in the resultant merge. This is a more general case of detecting erronous merges than just checking to one specific cause of lost changes.

Also, this only seems to happen when there are conflicts in the merge, so any method which requires running the merge again automatically would also need to resolve those conflicts automatically too.

Finally, I would like to be able to run this summary utility on a dirty repo, without stashing all of my changes first, hence my current experiments with git diff.

Any suggestions as to how I can get at this sort of information more directly than a script with a lot of parsing and reformatting would be appreciated.

The closest existing questions I can find to this are: Detect a merge made by '-s ours' (but the only answer there doesn't help) and “git merge -s ours” and how to show difference (but there are no answers at all there).

like image 229
Mark Booth Avatar asked Jan 20 '15 17:01

Mark Booth


People also ask

How do you identify a merge conflict?

To see the beginning of the merge conflict in your file, search the file for the conflict marker <<<<<<< . When you open the file in your text editor, you'll see the changes from the HEAD or base branch after the line <<<<<<< HEAD .

How do I fix incorrect merge?

In your case it should suffice to either: merge again the correct branch with your missing changes. revert the merge commit (and only the merge commit) and then merge the current branch that should have been merged in the first place.

How do I resolve merge conflicts in git merge?

Git commands that can help resolve merge conflicts Passing the --merge argument to the git log command will produce a log with a list of commits that conflict between the merging branches. diff helps find differences between states of a repository/files.


1 Answers

I had this exact problem, and ended up writing a tool to detect these types of merges. While I cannot share the actual code (it is technically owned by my employer), the algorithm is very simple: let S1 be the set of all files that have changes between the merge and the merge's second parent. Let S2 be the set of all files that have changes between the merge and the merge base. Subtract S2 from S1, and you are left with the set of files that probably have lost changes due to the merge.

This will not only detect merges made with -s ours, it will also detect botched merges where some, but not all, of the changes in the second parent made it into the merge.

like image 148
David Deutsch Avatar answered Sep 21 '22 01:09

David Deutsch