TIL about the concept of slots that Git uses for merges

published Dec 24, 2019 01:20   by admin ( last modified Dec 25, 2019 01:54 )

According to an answer on this question: https://stackoverflow.com/questions/50232177/tell-git-to-resolve-conflict-with-a-third-file-which-is-the-answer and to the best of my understanding of that answer, git may use up to four slots in its index (staging area, cache) for a file.

If there is no merge problem, the file you've changed is simply in slot 0 and that's it. If there is a merge problem however:

  • Your version of the file ("ours") is in slot 2,
  • The version it is in conflict with ("theirs") is in slot 3
  • The most recent common ancestor is in slot 1

Your job is then to resolve the conflict within the file in your working tree which now has conflict markers based on these files, and place the resolved version in slot 0, and then git can commit it as per usual.

 

According to another answer by the same author (torek),

https://stackoverflow.com/questions/51977050/restore-a-remote-file-after-solving-a-merge-conflict-using-git

you can get to the contents of a file in a slot like this:

git show :3:path/to/filename

…and then you can store that somewhere. This means that you can save away a conflicting version under a new name, which ought to be good for when you need some kind of conflict resolution when no human is around (or at least no git-human around).

git show :3:path/to/filename > path/to/new-filename

Actually easier is probably to save away the local commit under a new name, and then just remove the original filename

git show :3:path/to/filename > path/to/new-filename

And then git add that and some git reset on path/to/filename.

Automatically create a diverging file instead of merging two versions

Here is a way that could work for that:

Do a git merge

git merge their-branch

If that does not go cleanly, save away the incoming conflicting file with

git show :3:path/to/filename > path/to/new-filename

Then do a

git merge --abort

Then do a git merge again buth with strategy ours:

git merge their-branch -s ours'

Actually, a better method may be to specify a custom mergetool

git mergetool -t /path/to/custom/mergetool

Then that tool can whatever it wants.

According to git docs:

the configured command line will be invoked with $BASE set to the name of a temporary file containing the common base for the merge, if available; $LOCAL set to the name of a temporary file containing the contents of the file on the current branch; $REMOTE set to the name of a temporary file containing the contents of the file to be merged, and $MERGED set to the name of the file to which the merge tool should write the result of the merge resolution.