Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to merge to get rid of head with Mercurial command line, like I can do with TortoiseHg?

My question is this:

  • If I have two heads (branches with changes) in my Mercurial repository, and I'd like to get rid of one of them, but discard all the changes from that branch instead of merging them into the other, and I can't strip out those changesets so I have to merge, how can I do that with the command line client?

If I have two heads in my Mercurial repository, and use TortoiseHg as my client, the repository might look like this:

two heads

Then I can get rid of the test2 head by doing a merge and discarding. First I would update to the head I'd like to keep (test3 in this case, which in the image above is already the current parent of my working folder). Then I would right-click and select "Merge with...":

merge with...

and in the dialog that pops up I would choose to discard the changes from the merge target (ie. the branch I'd like to discard all the changes from):

merge dialog

After this merge has gone through, all the changes in the test2 head has been discarded, and I can commit. The head has now disappeared, but the changeset is still part of history.

My question is this: How can I do the same thing using only the command line client? I can't find any matching options to the hg merge command:

 hg merge [-P] [-f] [[-r] REV]  merge working directory with another revision  ... snipped text  options:   -f --force       force a merge with outstanding changes  -t --tool VALUE  specify merge tool  -r --rev REV     revision to merge  -P --preview     review revisions to merge (no merge is performed)     --mq          operate on patch repository  use "hg -v help merge" to show global options 

Edit: debugsetparents worked nicely:

 hg debugsetparents . 1 hg commit -m "merged to get rid of changeset #1" 

Edit: Attempt to use the --tool internal:local according to one of the answers:

@echo off  setlocal if exist repo rd /s /q repo hg init repo cd repo  rem revision 0 echo >test1.txt hg commit -m "test1" --addremove  rem revision 1 echo >test2.txt hg commit -m "test2" --addremove  rem revision 2 hg update 0 echo >test3.txt hg commit -m "test3" --addremove  rem now let's get rid of change in revision 1 with merge hg merge --tool internal:local -r 1 hg commit -m "merged"  dir 

output of execution:

 [C:\Temp] :test adding test1.txt adding test2.txt 0 files updated, 0 files merged, 1 files removed, 0 files unresolved adding test3.txt created new head 1 files updated, 0 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit)   Volume in drive C is unlabeled      Serial number is 0e17:6aba  Directory of  C:\Temp\repo\*  16.11.2010  20:05             . 16.11.2010  20:05             .. 16.11.2010  20:05             .hg 16.11.2010  20:05              13  test1.txt 16.11.2010  20:05              13  test2.txt 16.11.2010  20:05              13  test3.txt                 39 bytes in 3 files and 3 dirs    12 288 bytes allocated     66 600 316 928 bytes free 

Here the changes introduced in the 2nd changeset (the one with revision number 1), is now present in the merged changeset. This is not what i wanted.

like image 969
Lasse V. Karlsen Avatar asked Nov 16 '10 18:11

Lasse V. Karlsen


People also ask

How do you merge Heads in Mercurial?

To start a merge between the two heads, we use the hg merge command. We resolve the contents of hello. c This updates the working directory so that it contains changes from both heads, which is reflected in both the output of hg parents and the contents of hello.


Video Answer


2 Answers

According to TortoiseHG's source, when you check Discard all changes from merge target (other) revision, it uses the hg debugsetparents command:

hg debugsetparents REV1 [REV2]  manually set the parents of the current working directory      This is useful for writing repository conversion tools, but should be used with care.      Returns 0 on success.  use "hg -v help debugsetparents" to show global options 

To use:

    hg up <revision-to-keep>     hg debugsetparents <revision-to-keep> <revision-to-throw-away>     hg commit -m "Merge to discard ..." 
like image 121
jamessan Avatar answered Nov 05 '22 03:11

jamessan


If you don't want to use debugsetparents, you can manually revert to the changeset you want to keep before committing:

hg merge --tool internal:local -r HEAD_YOU_WANT_TO_DISCARD hg revert -r 'tip^' hg commit 

Note, however, that this technique is not necessarily the best approach. You may be better off just closing the head:

hg up HEAD_YOU_WANT_TO_DISCARD hg commit --close-branch 

The documentation here is a little misleading; this only closes the specific head, not the entire branch.

like image 24
Kevin Avatar answered Nov 05 '22 04:11

Kevin