Reputation: 7944
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).
Upvotes: 23
Views: 354
Reputation: 19025
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.
Upvotes: 1