24

I have a graphlog that looks something like this:

(snip)
  | |
  | o    1) Other Dev: Commit
  | | \
  o | |  2) Me: Commit
/ | | |
| | o |  3) Other Dev: Commits with an error
| |/| |
| o |/   4) Me: Merge and commit
|  /|    
|/  |
o   |    5) Me: Realize there were bugs in the commit and take earlier version to merge with
|   o    6) Other Dev: Fixes error
o /      7) Me: committing some changes
|/
o        8) Me: Merge fixed tip

At (8), everything is as it should be with the exception of the dangling extra head at (4). To get rid of it I have to merge (4) -.-> (8) but, since there is nothing in (4) that I need, I can safely discard all of it's changes. I could do this merge manually file-by-file (and usually this isn't that big a deal) but for my own edification - is there a simple one-line way to say "merge (4) with (8) and always take (8)"?

George Mauer
  • 117,483
  • 131
  • 382
  • 612

1 Answers1

38

Yes. The internal:local builtin merge tool.

$ hg merge 4 --tool internal:local

Similarly there's internal:other that picks the other version of files as the merged version.

Here's an example to clarify what's going on, start off with a repo with a single file:

$ echo a >> a
$ hg ci -Am.
adding a
$ echo a >> a
$ hg ci -Am.

Branch it and put a conflict in a:

$ hg up 0
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo b >> a

Also add another file just in the merged in branch:

$ echo b >> b
$ hg ci -Am.
adding b
created new head

Go back and merge the anonymous head:

$ hg up 1
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ hg merge 2 --tool internal:local
1 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)

Naturally at this point without the merge tool we'd get a conflict on a. But using the merge tool, we're telling Mercurial to take the version of the first parent on every file that the merged with cset has also touched.

$ hg st
M a
M b
$ cat a
a
a
$ cat b
b
Idan K
  • 20,443
  • 10
  • 63
  • 83
  • Beautiful. So to clarify, what's happening here is that you're specifying a custom tool to be used for resolving an merge issues, and you use a built in one that always selects the local version. – George Mauer Sep 19 '11 at 20:06
  • 3
    +1 for a nicely detailed answer. I realise this is an old question, but this results in only merge-conflicts being resolved to "local"... any new files from "b" are still created in the merged changeset. Any way to not have those? Or should they be removed manually (`hg forget ...`)? – icabod May 31 '12 at 09:17
  • To answer my own little query, tortoisehg achieves this with the "use with care" command `debugsetparents`, effectively pretending to perform a merge. Hmm. – icabod May 31 '12 at 09:31
  • 3
    Using `--tool internal:local` didn't work for me, it kept all of the bad changes. TortoiseHg using `debugsetparents` did work. – Joe Kearney Jan 03 '13 at 15:42
  • 12
    This approach will discard changes from the unwanted branch, but it will not discard new files from it. I think the correct answer is the accepted one here: http://stackoverflow.com/questions/4197744/how-to-merge-to-get-rid-of-head-with-mercurial-command-line-like-i-can-do-with – John Hatton Nov 27 '13 at 17:56