Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to push, without creating new heads, after creating multi-head branch, rebase and several merges

Tags:

mercurial

I did a series of dumb steps with my local copy of our shared repository, and I'm looking for a way how to fix it. The steps are:

  • I used bookmarks to have multiple heads of a development branch, that other people use:

    -o---o---o-----o---   <- dev branch
      \----1----1------   <- another head of the dev branch,
                             where I committed stuff
    
  • I created a new branch, still local, some time later

      /---------------x   <- new branch
    -o---o---o-----o---   <- dev branch
      \----1----1------   <- another head of the dev branch,
                             where I committed stuff
    
  • for one head, that contains only my code, I did a rebase on another branch

                       /-1'--1'--  <- rebase
      /---------------x            <- new branch
    -o---o---o-----o---            <- dev branch
      \----1----1------            <- another head of the dev branch,
                                      where I committed stuff
    
  • then, I merged the rebase, and then, a couple of commits later, I merged default

                       ----------d-\      <-default
                                    \
                       /-1'--1'\     \
      /---------------x--------x--x-x-x-- <- new branch 
    -o---o---o-----o---         
      \----1----1------         
    

Now, I wanted to push my new branch to the server (hg push --new-branch -b newBranch), but I get abort: push creates new remote head, since commits 1' belong to dev branch.

What is the right thing to do? I would like to avoid creating this additional head.

Update:

Per request, this is the output of hg heads:

changeset:   839:f2033d695fcd  <- want to push this
branch:      newBranch
tag:         tip
user:        me
date:        Wed Oct 31 13:05:51 2012 +0100

changeset:   826:7fde19d7f467
branch:      devBranch
user:        my-collegue
date:        Tue Oct 23 14:59:42 2012 +0200

changeset:   820:23853bbf68df  <- the part after rebase that got merged
branch:      devBranch
user:        me
date:        Mon Oct 22 15:36:26 2012 +0200

changeset:   807:899344cfb145  <- obsolete (branch with 1's)
branch:      devBranch
parent:      711:454f29c03fb1
user:        me
date:        Mon Oct 22 15:36:26 2012 +0200

changeset:   712:d5e8a62a7f5f  <- default, needs to stay
parent:      648:2bbcc01aa191
user:        me
date:        Wed Aug 22 16:21:09 2012 +0200
like image 894
Nikola Knezevic Avatar asked Oct 31 '12 10:10

Nikola Knezevic


2 Answers

You can push only the one head you're interested in mercurial. For you that would mean doing:

hg push -r f2033d695fcd

If the destination repo has been updated you need to pull, merge, and re-push:

hg pull
hg up -r <remote head>
hg merge -r f2033d695fcd
hg ci
hg push
like image 87
Stephen Rasku Avatar answered Nov 07 '22 23:11

Stephen Rasku


I solved the problem, without pushing another head to the repo, and without merging 23853bbf68df onto newBranch. This is probably not the cleanest way to do it, but I will leave it as a reference. In a nutshell, I reconstructed the whole branch by taking all commits and re-applying them.

First, I killed the newBranch'es head 899344cfb145, by using strip on the first diverging revision I did:

hg strip -r 646 

Then, I produced email patches (couldn't play with mq) for all commits that are in newBranch, since it's inception:

hg export -g -r 797:808 -r 810 -r 815:822 -r 824:830 -o "%n-%m.patch"
  • 797:808 are the patches in newBranch that were in the rebased part of devBranch (1' commits from the original figure).
  • 810 and 815:822 are other patchs in newBranch. 811:814 belong to a different branch, so I had to exclude those.
  • 823 is a merge commit with default, so I skipped this one.
  • 824:830 are all the commits after the merge with default.

Now, I imported these patches on a new head of newBranch:

hg up -r 796
# there are 29 patches, applying till merge
hg import --bypass {01..21}*.patch
hg up tip
hg merge default
hg ci -m 'merging in default'
hg import --bypass {22..28}*.patch

Finally, I just stripped of the original head of newBranch.

hg strip -r 797

This may not work in every situation. During the merge, I had to resolve some conflicts, too, but pretty benign. Hope this helps someone.

like image 1
Nikola Knezevic Avatar answered Nov 07 '22 21:11

Nikola Knezevic