TortoiseHG: cannot partially commit a merge

Roman Boiko picture Roman Boiko · Jul 29, 2010 · Viewed 8.1k times · Source

I tried to merge two heads in Mercurial. After merging, I didn't commit and did some more changes. Then I tried to commit and got the following message:

abort: cannot partially commit a merge (do not specify files or patterns)

I'm using TortoiseHG as visual shell, and Beyond Compare for comparing and merging. And I'm relatively new to all of them.

What should I do to finish commit successfully?

Answer

Martin Geisler picture Martin Geisler · Aug 12, 2010

Mercurial/TortoiseHg is correct in telling you that you should not partially commit a merge. Partial means that you do not commit all files at once.

The underlying reason for this message is that is gives you the wrong results. When you merge two changesets in Mercurial, you are creating a new changeset with two parent changesets. This merge changeset shows others how you want everybody else to combine the two changesets.

Let us imagine that you start with changesets A and B and want to merge them. This creates a graph like this:

... --- [A]
           \
            [M]
           /
... --- [B]

Pretend that we added the line A! to a.txt in the A changeset and that we added B! to b.txt in the B changeset. Just two independent changes that does not conflict. If Mercurial allowed you to do a partial commit, then you could do this:

hg merge
hg commit -m 'Added A!' a.txt  # creates M
hg commit -m 'Added B!' b.txt  # creates M'

and the result is this graph:

... --- [A]
           \
            [M] --- [M']
           /
... --- [B]

If you look at b.txt along the path B, M, M', then you will see that the line with B! was introduced in B, removed in M and reintroduced in M'!

This is not what you want from a merge changeset: a partial merge throws away changes from one branch just to introduce them again in a followup commit. Mercurial trusts you when you create M: it really believes that M contains the correct mix of A and B. In particular, if the B! line is removed in M, then it will remain gone when you merge M with other changesets.

So Mercurial is trying to protect you from creating a bad history by not allowing partial merges.