1

I have two mercurial repositories, generic and specific, which is a clone of the first repo:

$ hg glog -R generic 
@  changeset:   0:d516ded3bf0a
   summary:     generic project commit

$ hg glog -R specific 
@  changeset:   3:5f7b2efea94b
|  summary:     added another specific project change
o  changeset:   2:e2ad52001bcf
|  summary:     added generic project change (backport)
o  changeset:   1:a4220a2c7a80
|  summary:     added specific project change
o  changeset:   0:d516ded3bf0a
   summary:     generic project commit

Now I want to backport changeset 2 in specific to generic. I don't want to add changesets 1 and 3, just cs 2 (cherry-pick). It seems there are two alternatives: transplant and graft. transplant would be ok because it allows to move patches from another repository (in my case from specific to generic) but it's limited in merge capabilities. On the other hand, graft would provide smarter merge but doesn't support grafting from another repo (only between branches of the same).

The goal is to add only changeset 2 in specific to generic. This is how I proceeded, without success.

$ cd specific
$ hg up 0 # the common ancestor
$ hg branch backport-cs2
$ hg graft 2

$ hg glog
@  changeset:   4:1405acc4a121
|  branch:      backport-cs2
|  tag:         tip
|  parent:      0:d516ded3bf0a
|  summary:     added generic project change (backport)
|
| o  changeset:   3:5f7b2efea94b
| |  summary:     added another specific project change
| |
| o  changeset:   2:e2ad52001bcf
| |  summary:     added generic project change (backport)
| |
| o  changeset:   1:a4220a2c7a80
|/   summary:     added specific project change
|
o  changeset:   0:d516ded3bf0a
   summary:     generic project commit

So far so good. The last step is to pull the branch backport-cs2 of specific into the default branch of generic.

$ cd ../generic
$ hg pull -b backport-cs2 ../specific
$ hg glog 
o  changeset:   1:1405acc4a121
|  branch:      backport-cs2
|  tag:         tip
|  summary:     added generic project change (backport)
|
@  changeset:   0:d516ded3bf0a
   summary:     generic project commit

Now in generic there is the changeset I want, but it's in a new branch while I'd like to have it in default. Any suggestion how to do that? Ideas for a better approach to backporting are appreciated as well.

Paolo
  • 16,171
  • 20
  • 78
  • 110

1 Answers1

1

In general what you're doing is hard because it's not a very good idea. If these projects really have that much in common they should have more in common than just changeset zero. Ideally specific would, for example, merge in the default of 'generic' regularly -- that's a very common pattern. It's possible to have 'specific' be extremely customized, or have 1000s of files that 'generic' doesn't have, or 100s of filed deleted, and the merge in will still be just great. It's hard to do that bidirectionally, but if you've going 'generic' to 'default' you should work to keep that frequently mergeable.

As an example within a company it's not uncommon to have a repository called something like 'skel' that includes all the project boiler plate and you start of new projects as a clone of 'skel'. When someone updates 'skel', say alters the terms of use file or something, you can merge skel into your project just fine, even if your project has gone from 8 files to 8000 -- merge still works.

That said, if you can't do that you should just use transplant. Using graft makes for easier merges only because it can take recent common ancestors into account, and makes, especially, subsequent grafts easier. None of that applies when you're just hanging it off of the first changeset -- I suspect your merges will be identical to those of the transplant case and transplant at least includes some metadata that makes transplanting the same changeset twice kick up a warning.

That said if you really want to go the route above just skip the hg branch backport-cs2 line. When you graft you'll just be creating a new head on the default branch in specific which is totally fine, and then when you do your pull you'll get a new head on default in 'specific' and then you can merge it in and it'll be on the branch you want -- but don't do that. Use merges as intended or just use transplant if you can't.

Ry4an Brase
  • 77,054
  • 6
  • 143
  • 167