59

I want to move a changeset from one branch to another. Basically, I currently have:

A -> B -> C -> D # default branch

And I want:

A # default branch
 \-> B -> C -> D # some_new_branch

Where some_new_branch does not exist yet. I am used to git, so I guess there is a simple "mercurial" way I am missing.

jk.
  • 13,817
  • 5
  • 37
  • 50
David Cournapeau
  • 78,318
  • 8
  • 63
  • 70
  • 2
    It probably depends on what you mean by "branch". Mercurial has many different branching strategies, which you should try to acquaint yourself with: http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/ – Dan Mar 28 '10 at 16:59
  • 1
    Similar question: [Mercurial move changes to a new branch](http://stackoverflow.com/q/4665549) – Oben Sonne Apr 29 '12 at 19:22
  • 1
    Possible duplicate of [Mercurial move changes to a new branch](http://stackoverflow.com/questions/4665549/mercurial-move-changes-to-a-new-branch) – PhoneixS Mar 10 '16 at 10:16

4 Answers4

70

One way is to export a patch for B,C,D; update to A; branch; apply patch:

hg export -o patch B C D
hg update A
hg branch branchname
hg import patch

To remove B,C,D from the default branch, use the mq extension's strip command.

Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
  • In a project we decided not to include a feature in the next release, which was already part of the default branch - I used your solution to create a new branch with the changesets related to this feature. Instead of stripping the changesets, I reverted the default branch to the state before the implementation started. – Michael Schmeißer Oct 18 '12 at 09:59
  • This is for before those have been pushed to default, I assume? – NoBugs Jan 01 '14 at 06:46
  • Yes, any editing of history is too late if shared the original history has been pushed. You'd have to edit all copies of the history, which may not be practical or possible. – Mark Tolonen Jan 01 '14 at 18:04
  • 1
    I might have used to strip extension wrong, but when I tried to `hg strip B` I also lost the newly created branch information from the imported commits and they ended back on default. It helped when I stripped before making a new branch and importing. – kerma Aug 05 '16 at 09:13
  • Works, thanks! If you have more revisions for the export is better to use a syntax like this: hg export -o patch -r B:D – quick Aug 18 '17 at 09:16
11

Sounds a bit like a cherry-pick operation in git. The Transplant Extension may be what you're looking for.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
crazyscot
  • 11,819
  • 2
  • 39
  • 40
8

With Mercurial Queue:

# mark revisions as draft in case they were already shared
#hg phase --draft --force B:D
# make changesets a patch queue commits
# (patches are stored .hg/patches)
hg qimport -r B:D
# pop changesets from current branch
hg qpop -a
# 
hg branch some_new_branch
# push changesets to new branch
hg qpush -a
# and make them commits
hg qfinish -a

Without comments:

hg qimport -r B:D
hg qpop -a
hg branch some_new_branch
hg qpush -a
hg qfinish -a
anatoly techtonik
  • 19,847
  • 9
  • 124
  • 140
  • You still need to strip moved changesets, if for example they were published on Bitbucket (in its webinterface in "Settings" -> "Strip changesets"). Other case, they will come in branch, they were moved, after first pull. – Vasiliy Toporov Jul 04 '15 at 14:25
8

Alternative to transplant or patch, you could use graft.

hg update A
hg branch branchname
hg graft -D "B:D"
hg strip B

Note that changing history is bad practice. You should strip only if you haven't pushed yet. Otherwise, you could still backout your changes.

Kbii
  • 185
  • 1
  • 3
  • 11