How to get 3-way merge in GIT on non-conflict merges?
Asked Answered
A

2

5

How to disable auto-merging in GIT?

The purpose is to have the same behaviour as for conflict merges resolution in automatic merges during invocation of command chain:

$ git fetch
$ git merge some_branch
$ git mergetool

The last command leads us to 3-way merge of files in case of merge conflicts. I would like to have an easy way of performing the same 3-way merge on files without conflict merges.

I couldn't find any solution on the internet, is there any?

I've some workarounds in mind, but it would prefer to avoid it.

Thanks in advance,

Aleks

Ayana answered 25/6, 2010 at 23:23 Comment(0)
K
6

For changes that were made only on one side or the other, you can prevent automatic merges by unsetting the merge attribute (see gitattributes under “Performing a three-way merge”). A merge made for a pathname that lacks the merge attribute (or has it set to “binary”) will leave the version from the current branch in the working tree and leave the index entry for the pathname in a conflicted state.

If you want to encourage everyone to work this way, you can put in into a .gitattributes file and commit it. If you only want to do this for yourself, you can put it in an uncommited .gitattributes files or put it in your repository's $GIT_DIR/info/attributes file (which you could add/remove/rename at will to enable/disable the attribute).

#    repository/.git/info/attributes
# OR
#    .gitattributes
* -merge

If an identical change is made on both sides, even this configuration will not cause a conflict.

Keverne answered 26/6, 2010 at 5:19 Comment(3)
Thanks Chris, it was exactly what I was looking for. Nevertheless few people from my team who were looking for the solution like me have said, and I couldn't argue with them in this case, that it would be nice to have an option during merge to get such a behaviour (e.g. as one of the value for -s in git-merge). Rationale behind this that man git-merge is one of the first places when most of people would search for this option. RegardsAyana
do you know a way to do the automatic merge by demand when you configured the * -merge?Pow
@damian: For purely interactive use, just temporarily comment-out your * -merge line and use git checkout -m -- path/to/file. If you want the scriptable way though, you will need to use git merge-index git-merge-one-file -- path/to/file, or roll your own invocation of git merge-file.Keverne
A
5

The trick is, the way git solves merges is:

  • always based on a 3-way merges (since the graph of commits allows to get a common ancestor very easily)
  • always seamlessly except for conflict (where the process gets assisted by you)

So even if you define a merge driver, it won't kick in unless there is a conflict of some sort.


The first setting to try is to define a merge attribute Unset

Unset

Take the version from the current branch as the tentative merge result, and declare that the merge has conflicts. This is suitable for binary files that does not have a well-defined merge semantics.

You would write in a .gitattributes file

 * -merge

, and see if that is enough to trigger the mergetool on all merged files.


One reason this "unset" feature is not directly an option of git merge, is that:

Trying to unset the 3-way merge at the file level is not part of that merge process (which, again, reason at the tree level).
So it is more suited as an attribute which can be set for a specific set of files.

Augustinaaugustine answered 26/6, 2010 at 5:16 Comment(1)
Er, you don’t actually write “merge=Unset”. Unset is a state, the syntax for “Unset” is “-merge”. The top of the manpage explains the state vs. syntax (though not in a manner that is easily scannable).Keverne

© 2022 - 2024 — McMap. All rights reserved.