user451126
user451126

Reputation: 65

Why does mercurial merge committed changes in the working copy?

I've been using Mercurial for a few weeks now and don't understand why when Mercurial comes to merge committed changes from two repositories it does it in the working copy?

Surely the merge could happen without the use of the working copy removing the need to shelf changes etc.

It just doesn't seem necessary to involve the working copy. Am I missing something?

Upvotes: 2

Views: 851

Answers (3)

Geoffrey Zheng
Geoffrey Zheng

Reputation: 6638

There is only one working copy per repository, by definition:

The working directory is the top-level directory in a repository, in which the plain versions of files are available to read, edit and build.

Unless your file system descends from Schrödinger's cat, you cannot have two versions of the same file at the same time, thus you cannot have two working copies.

Nevertheless, it's indeed theoretically possible to use something like a ephemeral clone (per @Ry4an) to act as the working copy of a merge, resolve conflicts there, commit, then make it disappear. You'd get a beautiful merge changeset and your intact working copy.

I can think of several ways to achieve this:

  1. Petition hg team to do it in core
  2. Write an extension to implement the ephemeral clone or some other way
  3. Shelve with a temporary changeset
  4. Shelve with MQ

I would strongly recommend #4, as I would for almost all workflow scenarios. It took me a few good days to grok MQ, but once I did I've never had to turn back.

In an MQ workflow, your working copy is always the current patch. So for the merge situation you would do:

  1. hg qrefresh
  2. hg qpop -a
  3. hg update -r<merge first parent>
  4. hg merge [-r<merge second parent>]
  5. hg commit
  6. hg update qparent
  7. hg qgo <working copy patch>

You don't have to pop all patches in #2. I always do that whenever I need to deal with real changesets to avoid mixing them up with patches.

Solution #3 is really the same as #4, since a patch is a temporary changeset by definition (this is really the only thing you need for understanding MQ). It's just different commands:

  1. hg commit -A
  2. hg update -r<merge first parent>
  3. hg merge [-r<merge second parent>]
  4. hg commit
  5. hg update -r<working copy changeset parent>
  6. hg revert -a -r<working copy changeset>
  7. hg strip <working copy changeset>

If you want to keep the working copy changeset and continue to commit, simply update to it in #5.

From your question it seems like you already know #4 but don't like shelving. I think shelving is good because merging is a fundamentally different task than coding (changing working copy), and shelving makes the context switch explicit and safe.

Upvotes: 3

Ry4an Brase
Ry4an Brase

Reputation: 78350

I didn't write Mercurial, so I can't say why they did it that way, but here are some of the positive results of that decision:

  • you can look over the results of the merge before you commit it
  • you can edit the results of the merge before you commit it
  • you're encouraged to commit frequently

If you really want to do a merge and have stuff in your working dir that you can't bear to commit don't bother with shelve just do:

cd ..
hg clone myrepo myrepo-mergeclone
hg -R myrepo-mergeclone merge
hg -R myrepo-mergeclone push myrepo

On the same file system clone is near instantaneous and uses hardlinks under the covers so it takes up almost no space past that of the temporary working copy.

Upvotes: 3

VonC
VonC

Reputation: 1329692

As mentioned in the chapter "Merge" of HgInit:

The merge command, hg merge, took the two heads and combined them.
Then it left the result in my working directory.
It did not commit it. That gives me a chance to check that the merge is correct.

Such check can include conflicts in merge, that the user has to review:

alt text

In KDiff3, you see four panes

  • The top left is the original file.
  • Top center shows Rose her version.
  • Top right shows Rose my version.
  • The bottom pane is an editor where Rose constructs a merged file with the conflicts resolved.

So you need a working directory (a view for the merge) in order to resolve fully a merge.

Upvotes: 1

Related Questions