开发者

mercurial collaboration results in multiple commits of the same changes when using central repository

I've been using mercurial with a central repository. As two or more of us work on changes we commit locally. At some point we push these changes back to the central repository.

The problem comes in when I do a pull. Often there are files that were modified and pushed by another developer and those come down to my repository with a pull. I am then required to merge, which shows me t开发者_高级运维he difference between my local repository and the files that were committed.

What bothers me is that I have to merge and commit. That gets pushed back up to the central server which appears to have committed the same changes twice, once as me as a merge and once as a changeset from the other developer.

Is there some way in mercurial to update my repository and have files that I haven't touched just be updated rather than recording the exact same change twice, once from the original developer and once in my merge?

This question seems to raise the same point, but doesn't provide an answer to my question: Why is mercurial dumb when merging? How can I make pulling/merging changes simpler?


Mercurial works in terms of changesets and revisions.

A changeset is a snapshot of the changes that went into making a revision.

If you were to succeed in only updating the files that were changed, when you pulled, you wouldn't have an actual revision in your working folder, you would have a bastard revision, and only you and your machine would know how that came to be. Someone else that pulls at a different time would get a different bastard revision, and they wouldn't line up.

So no, Mercurial is designed to work exactly like you say it does, except that it doesn't really show the changes as happening twice, there must be something you're doing wrong if it appears to do that.

In other words, if I change something, and commit, then I pull down your changes, do a merge, and commit that, the merge commit would only contain any changes I have to do in order to resolve the merge. If the merge was automatic, no conflicts that needed to be resolved, it would look like you're just committing an empty changesets, with two parents.

Now, there are ways to mitigate all the branches, you can use rebase for instance.

What would happen is the following:

central: 1---2---3---4

local:   1---2---3---4

You change something

central: 1---2---3---4

local:   1---2---3---4---5

Someone else changes something, and push:

central: 1---2---3---4---5'--6'

local:   1---2---3---4---5

(I use ' after the 5 to show that while it is revision number 5 in that repository, it's not the same as revision number 5 in the other repository.)

Then when you pull, it looks like this:

central: 1---2---3---4---5'--6'  <-- corresponds to these <--+
                                                             |
local:   1---2---3---4---5                                   |
                      \                                      |
                       6'---7'   <-- note that these gets renumbered

Then you rebase 5 to be on top of 7', and you get this:

local:   1---2---3---4---6'--7'--5

if needs be, a merge happens when you rebase, if you have done conflicting changes. After the rebase, you can push. It basically makes your revision history look like you took turns working.


The short answer is "don't worry about it". It looks to you like the change that person did is again done by you in a subsequent merge, but that's just because 'diff' doesn't have a great way to show merges in any VCS. The change is theirs, the combination is yours, and the whole thing works out. Two people suing a DVCS end up with a history that looks like a braided rope, and that's okay.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜