Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I do a changeset based merge instead of file-by-file based merge with Mercurial?

When performing a merge with Mercurial, it wants to merge conflicting files one at a time which just isn't a productive workflow on large merge sets. Instead, what I would like to do is merge the entire changesets of both heads (like using kdiff3 to diff 2 heads). To me that sounds straightforward but I can't figure out how to achieve it.

So far, the closest I can get is to go through the merge the usual way, leave all the conflicts unresolved (a file at a time...), and then hg vdiff -rHead1 -rHead2 - but vdiff (using kdiff3) doesn't seem to have options for passing the tool an output dir (the current working dir) and instead launches with the output dir as a tempdir (possibly -o is the answer?).

Let me put it another way - I want to use kdiff to merge two heads into my working directory. I want the results in my working dir to be my merge that I can commit.

I must be missing something obvious, I can't be the only one who wants to do this.

like image 529
jsaylor Avatar asked Apr 29 '09 22:04

jsaylor


People also ask

How do I merge two branches in Mercurial?

First, we need to move back into the main branch, which is accomplished using the “hg update” command. Then, we run the “merge”command, specifying the name of the branch we'd like to merge from. Finally, we commit the changes. The changes are now present in the main branch.

How do I merge commits in Mercurial?

Once the commits are in draft, run the hg histedit rev-id command, specifying the earliest draft commit. This will open the history edit function in your terminal, allowing you to fold the commit messages into one. Select a commit to use as the one into which the others will be squashed.

How do you pull in Mercurial?

Pull changes from the Mercurial upstream (Pull)From the main menu, choose Hg | Mercurial | Pull. Specify the required URL address of the source remote repository.


1 Answers

I came up with a solution that achieves what I want but I still feel like it's a kludge.

  • Start with an empty working dir with 2 heads: Mine and Theirs.
  • Update working dir to Mine:
    hg update [My head's rev here]
  • Perform a merge, but fail all files that Merc can't handle automatically without launching a merge tool and keep "My" files when in conflict:
    hg --config "ui.merge=internal:fail" merge

See https://www.mercurial-scm.org/wiki/TipsAndTricks#head-9f405488b6d3b3d092a09aafa28db515ba44c742 for how-to merge/fail details.

Now I've got a working dir with as much as auto could figure out, but any outstanding files still untouched from Mine. (Use hg resolve -l to see the Mercurial's resolution status of current files)

  • Now I can vdiff my working dir against the Theirs head which gives me the high level, changeset-to-changeset merge that I was looking for.

hg vdiff -r [Theirs head's rev here]

Note: If you're using WinMerge for your vdiffs , then make sure it has an /r switch as an option which will do a subdirectory compare and - if WinMerge config is set to use Tree-View - will give a great tree comparison. From Mercurial.ini:

[extdiff]
cmd.vdiff = C:\Program Files\WinMerge\WinMergeU.exe
opts.vdiff = /e /ub /r /dl other /dr local

Now I can work the entire directory which includes the unresolved files and make project wide changes as necessary (ie. maybe resolving one file requires additional changes in another).

  • When done use resolve to mark all files resolved for Merc and then commit.
    hg resolve -m

Whew! Here's hoping this helps someone else!

like image 128
jsaylor Avatar answered Oct 21 '22 12:10

jsaylor