How does Git decide on conflicts?
Git has an internal merge system that is independent of difftool
. Anyway you can specify the merge strategy
using the -s
option, from the manual:
-s <strategy>
--strategy=<strategy>
Use the given merge strategy; can be supplied more than once to specify them in the order they should be tried. If there is no -s option, a built-in list of strategies is used instead (git merge-recursive when merging a single head, git merge-octopus otherwise).
Strategies go from the simple FastForward
to the Octopus
when merging a lot of trees.
Check this answer to see how the different merge
strategies work.
Anyway your scenario is weird. Maybe your IDE is using a different merge strategy, so when it opens it does the merge the right way.
The posting here is the best answer I have seen on git merge strategies. And yes, you can choose which one you want with the -s option
But you question is why does other tools like Visual Studio merge it when git cannot. Visual Studio can have a rather aggressive merge strategy - "the automatic merging feature typically will not use any content from your older version because the default settings of the automatic merge feature favor the most recent file" see here for more information.
To learn more about the Merge Tool that comes with VS 2012, see this posting where Brian Harry dives into how they considered "Minimal conflicts when merging" as a key feature.
As for Perforce, I suspect they have a similar merging strategy - the git to p4 connector must be using the perforce merge strategies to figure out and I am sure they are more aggressive as well.
"ours" might be a similarly aggressive merge strategy in git.
But the long and short of it is that each product is using their own merging strategies and some are more or less aggressive. It depends on your use case and needs which are acceptable.
As Atropo states in his answer,
Git has an internal merge system that is independent of
difftool
.
So Git decides when a change causes a conflict on its own, not by using whatever external diff or merge tools you're using (which probably use their own conflict detection and resolution strategies).
According to VonC's answer to What constitutes a merge conflict in Git? (emphasis mine):
I don't think the merge algorithm has anything special with Git: it is a classic 3-way merge algorithm (not the Codeville one), which can be used with several strategies (default: recurse, or resolve or octopus). The result is a fairly simply merge process which is described here.
Any visualization need is then delegated to third-party merge/diff tools.
The Wikipedia article he links to explains a 3-way merge thusly (emphasis mine):
A three-way merge is performed after an automated difference analysis between a file 'A' and a file 'B' while also considering the origin, or common ancestor, of both files. It is a rough merging method, but really widely applicable since it only requires one common ancestor to reconstruct the changes that are to be merged.
The three-way merge uses the ancestor of the changed files to identify blocks of content that have changed in neither, one, or both of the derived versions. Blocks that have changed in neither are left as they are. Blocks that have changed in only one derivative use that changed version. If a block is changed in both derivatives, the changed version is used if it has the same content on both sides, but if the changes differ, it is marked as a conflict situation and left for the user to resolve.
Three-way merging is implemented by the ubiquitous diff3 program, and was the central innovation that allowed the switch from file-locking based revision control systems to merge-based revision control systems. It is extensively used by the Concurrent Versions System (CVS).
The article also talks about Recursive three-way merges, which I see used in Git a lot:
Widespread use of three-way merge based revision control tools has brought up cases where simple-minded three-way merging causes spurious conflicts and sometimes silently re-enacts reverted changes. Examples of such situations include criss-cross merges and three-way rename conflicts.
The problems of three-way merge arise in situations where two derivative states do not have a unique latest common ancestor (LCA). To deal with these problems, the recursive three-way merge constructs a virtual ancestor by merging the non-unique ancestors first. This technique is used by the Git revision control tool.
Recursive three-way merge can only be used in situations where the tool has knowledge about the total ancestry DAG (directed acyclic graph) of the derivatives to be merged. Consequently, it cannot be used in situations where derivatives or merges do not fully specify their parent(s).
Yes, a number of IDEs and merge tools will do automated conflict resolutions on top of git's own.
As seen in git help merge-file
, git's stock conflict resolution algorithm for text files is fairly simple: diff chunks conflict iff they change neighbouring lines. If git is unable to auto-resolve a conflict in this manner, it will put a text conflict marker in a format that has been standard since the RCS days, and that the IDE can pick up and work on (even if it doesn't know about git):
<<<<<<<< Version identifier 1 Foo ======= Bar >>>>>>>> Version identifier 2
I don't use Visual Studio, but a quick Google tells me that it has an automatic conflict resolution feature. (I use kdiff3 myself, which has its own automatic conflict resolution algorithm)