I'm studiyng Mercurial but I don't understand how it detects the file conflicts.
When a centralized SCM (as SubVersion) detects a conflit between two versions of a file in my project, it means the version number of mine local file is minor then version number of same file in the remote repository, because another developer (p.e. John Smith) has committed before me (by the same initial version number).
In a decentralized SCM (Mercurial, Git, etc), I haven't a central repository, then:
How Git understands that our files are direct descendant from number version A? The Mercurial/Git/Bazaar/etc has'nt an internal number what identifies: how they understand when a modified file is in conflict or not?
Any conflicts are only detected after you and John Smith communicate with each other (using hg push
and hg pull
) and one of you then want to merge the two lines of work (using hg merge
).
After you pull the change by John Smith into your local repository, the changeset graph might look like this:
... [a] --- [b]
\
`---------- [c]
where you made changeset b
and John Smith made c
, both based on changeset a
. Between a
and b
, you changed the file helloworld.c
and between a
and c
John Smith changed the same file. Mercurial is now able to tell that there might be a potential conflict here (an overlapping edit) and it will tell you when you run hg merge
.
The system is not based on version numbers associated with the files — it's based on the above changeset graph. Concretely, when you merge b
with c
, Mercurial will find the greatest common ancestor, which is a
. It will then look at the manifest (a list of the files (and their version) present in a given changeset) in a
, b
, and c
and notice that the file helloworld.c
existed in three different versions. That tells Mercurial that it needs to do a three-way merge with a
being the base version, and b
and c
being the local and other versions. By default, it tries to do the merge internally, but it will call external merge tools (like KDiff3) if that fails.