Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Git keep a record of past merge conflicts?

I'd like to look at the repository history and see what types of merge conflicts have occurred in the past.

I've tried using git log --merges but that just seems to show successful merges.

like image 576
Stu Avatar asked Apr 23 '19 18:04

Stu


People also ask

What happens if you get a conflict during a merge?

Merge conflicts happen when you merge branches that have competing commits, and Git needs your help to decide which changes to incorporate in the final merge. Git can often resolve differences between branches and merge them automatically.

Can you stash merge conflicts?

Yes, we can get merge conflict while applying stash. Let's see it in action. Let's create a file, add some content to it and commit it. Please note we must have a commit before we can use git stash the first time.

Does Git ensures that conflicts never happen?

It however does not prevent you from getting merge conflicts. A merge conflict happens, when the two branches being merged have conflicting file changes (not states), which Git cannot figure out on its own.


1 Answers

Git does not record the merge conflicts, unless you've enabled rerere, but it does record most of the information necessary to recreate them. You can write a script to recreate the merge conflicts, with some caveats... Git doesn't record the merge strategy you used to resolve a merge, so you will have to hope that the default strategies are sensible choices, or do some tweaking to get this to work on your repo.

How It Works

You can enumerate merges with rev-list:

git rev-list --parents --min-parents=2 --all

This is preferable to git log, because the output is suitable for parsing by a script. This will produce a list of merge commits, one per line. The child commit is the first hash and the remaining hashes are parents. For example,

28171e725cc93e8cb85194931e7138c31f980a43 20af81cf6388026ecf0de4eec8783e7a38905ccd 2d77896f5fcc1a9b09f4f099aa6e945e8da86410

Here, the merge is between 20af and 2d77.

Check out the first parent, in detached head:

git checkout -q --detach 20af81cf6388026ecf0de4eec8783e7a38905ccd

Then merge the remaining parents:

git merge -q --no-commit --no-ff 2d77896f5fcc1a9b09f4f099aa6e945e8da86410

The status code of merge will be 1 if there are conflicts, which you can examine. If there is a merge conflict, you will see files with UU in the porcelain status:

git status --porcelain

You can then abort the merge to reset to a state where you can work with the repo:

git merge --abort

Script

I have turned this into a script as a demo. The script must be run on a pristine repository, since it will run a bunch of git checkout and git merge commands.

https://gist.github.com/depp/f1838cf4559f9cde74b9d3052b8abbb0

The script will retry every merge in history using the default strategy, and report the conflicting files.

If you wish, you can easily extend the script to copy out the conflicting files so you can look at the conflicts.

like image 106
Dietrich Epp Avatar answered Sep 28 '22 09:09

Dietrich Epp