views:

271

answers:

2

Note: The scenario I describe here is not answered in Stack Overflow: Completely manual Mercurial merge.

I will explain my query with an example. Assume I start off a Mercurial repository to design a car:

C:\Car$ dir
Car.cpp
Car.h

I work on the design of Car for quite a while and the repository looks like:

r0-r1-...-r100-(default)

At some point in time I branch default to SolarCarBranch to work on a solar powered car in parallel:

C:\SolarCar$ dir
Car.cpp
Car.h
Solar.cpp
Solar.h

After some more time, the repository looks like:

r0-r1-...-r100-...-r200-(default)
            \--r101-...-r201-(SolarCarBranch)

How do I merge SolarCarBranch back to default?

Take note of the following complications in the merge I want:

  1. I should be able to continue work on both default and SolarCarBranch after the merge.
  2. There might be fuel efficiency fixes in Car.cpp and Car.h in SolarCarBranch that I want pulled into default, however I do not want all the changes in those files. So, I want to cherry pick the changes I want to be included in default during the merge (aka manual merge).
  3. I do not want Solar.cpp and Solar.h appearing in default. The world may not yet be ready for a solar powered car. ;-)

What I have learned:

  1. This is possible by a hg merge SolarCarBranch
  2. This can be achieved by setting kdiff3.premerge=False in Mercurial.ini
  3. I do not know how to achieve this since premerge=False still merges/copies Solar.cpp and Solar.h into default without asking me for permission.
+2  A: 

Your first condition, to be able to continue work on both branches, is satisfied by simply not closing the branch (which you do with the --close-branch option to hg commit).

You can cherry pick changesets to merge using the Transplant extension. This will let you choose only specific changesets to merge into default.

The third condition is satisfied by the the idea that provided you don't mix changes to both your regular car and your solar powered car in the same commit, you can pull changesets back from the solar branch with impunity, and not have to worry about mixing your car types.

You might want to look at the internal option flags in the merge configuration docs too.

gavinb
sounds like cherry-picking is what is required to me
jk
really? I dont' think cherry picking is necessary. So long as pre-merge is off you still get control over the adding of every change on a chunk-by-chunk or line-by-line basis. Cherry picking is just short hand for not having to manually reject the changes in some csets, but you can always say "no" to them. I'd really advise against the Transplant extension because then you have the same changes in your repo twice with two different hash-ids.
Ry4an
@Ry4an I had thought of suggesting the manual commit as you describe, but `transplant` seemed to be easier when I was writing it up. But your explanation convinced me it is the better option, especially your point about having the same changeset with two different hashes. So I upvoted your answer, and suggest to the OP it be accepted.
gavinb
thanks, @gavinb. You, sir, are a class act.
Ry4an
+3  A: 

You're really close and you don't need to resort to Transplant (yuck) or cherry picking in general. Turning off premerge is the first step, and then just remove the files you don't want in the main branch after merging but before committing. You'll only have to do it once.

Here's a setup:

o  changeset:   3:343d531512a3
|  branch:      solar
|  tag:         tip
|  parent:      1:cb26642f8db5
|  user:        Ry4an Brase <[email protected]>
|  date:        Wed Mar 10 11:16:48 2010 -0600
|  files:       afile
|  description:
|  solar-change
|
|
| @  changeset:   2:c5d14e34db07
| |  parent:      0:56465175b2fc
| |  user:        Ry4an Brase <[email protected]>
| |  date:        Wed Mar 10 11:05:44 2010 -0600
| |  files:       other-main-file
| |  description:
| |  moremain
| |
| |
o |  changeset:   1:cb26642f8db5
|/   branch:      solar
|    user:        Ry4an Brase <[email protected]>
|    date:        Wed Mar 10 11:04:32 2010 -0600
|    files:       solar-only
|    description:
|    solar-initial
|
|
o  changeset:   0:56465175b2fc
   user:        Ry4an Brase <[email protected]>
   date:        Wed Mar 10 11:04:14 2010 -0600
   files:       afile
   description:
   initial

You can see that changeset 1 adds a file to the solar branch -- a file we don't want in default. While changeset 3 tweaks a file that also exists in main, afile, and we want to manually control whether or not that change happens.

So do hg update default ; hg merge -r solar. The merge tool will pop up for afile and we decide line-by-line or chunk-by-chunk if we want those changes. After saving do a hg stat:

% hg stat
M afile
M solar-only

And we see that solar-only is queued up for commiting in default. Just remove it (with if).

% hg rm -f solar-only

Now hg stat shows it as removed:

% hg stat
M afile
R solar-only

and when we commit we'll have what we want in the new changeset.

Ry4an
Removing those files! How did I miss that! Thanks so much! :-)
Ashwin