Question

I would like to understand which is the better way to realize the workflow I'm going to present with Mercurial. I know how I would do it in Git, which I'm much more confident with, but couldn't find a satisfying way with Mercurial.

The workflow is the following: I want to track an upstream branch, where development work is done by somebody else, and maintain a reasonably small patch branch on top of it. What I would do with Git is the following: every time I want to include some new upstream commit, I rebase my patch branch over the upstream branch (or the relevant commit, BTW), perhaps modify some commit and forcibly push the patch branch to a repository that is shared with my collaborators (I'm aware of the issues with non fast-forward pushes and so are my collaborators; we know how to avoid problems).

I would like to do the same with Mercurial. The main problem is that every time that I push a new head, the previous one doesn't get deleted like it happens with Git (ok, commits are not really deleted, but they practically disappear, since they are not ancestors of any branch anymore; they will be eventually really deleted by git gc and that's ok for me). So my repository remains polluted with a lot of old commits that I don't want anymore. I couldn't find any way to delete them (except perhaps deleting them one by one, but that's not really a solution).

Is there any better way to do this with Mercurial?

In other words, what I would like to do is to automatically delete all commits that are not ancestors of some commit in a predetermined set.

EDIT: since someone is asking for more details, I try to be more precise. I start with this repository:

C <upstream>
|
B
|
A
|

Then I develop some patches on it:

F <patch>
|
E
|
D
|
C <upstream>
|
B
|
A
|

At some point upstream adds some more commits:

F <patch>  I <upstream>
|          |
E          H
|          |
D          G
|          |
C ---------+
|
B
|
A
|

I rebase my patch branch on it, perhaps modify something in the patches and arrive here:

F' <patch>
|
E'
|
D'
|
I <upstream>
|
H
|
G
|
C
|
B
|
A
|

Then I push everything on the remote Mercurial repository:

F' <patch>  F
|           |
E'          E
|           |
D'          D
|           |
I ----------+ <upstream>
|
H
|
G
|
C
|
B
|
A
|

Mercurial doesn't automatically delete the D,E,F head, but I would like it to disappear. I do this pull/rebase/modify/push cycle often and would like to erase old leftover commts that are not relevant anymore. How do I do that?

Thanks.

Was it helpful?

Solution

I know the pain and don't have an automatic solution handy. I try not to let too much cruft accumulate (checked regularly with hg heads -t) and use hg strip to remove unwanted changesets from the repository. Stripping is not done one by one (changeset), instead, if you choose the right changeset, then it's usually just one strip for every rebase cycle, because all of the stripped changeset's descendants get stripped as well – the repository cannot have orphans. Finding the right changeset is a bit tedious, but since usually only a handful of patches is involved, it is not too difficult using hg glog.

OTHER TIPS

If your business-task is

  • Get changes from RepoOne
  • Merge these changes with your mainline
  • Publish merge-results into RepoTwo

you have at least two (dirty thinking without deep testing) ways to do it in more Mercurial-way

Branch-way

  • Maintain your mainline in separate named branch ANYNAME != default (default most probably used by upstream)
  • Have upsteam-repo in paths section of .hgrc in order to be able to pull from it
  • Pull, when needed, from upsteam
  • Merge to ANYNAME, resolve conflicts, if any
  • Commit and push in your repo only ANYNAME branchhg push -b ANYNAME (side-effect: parents of mergeset from upstream will be pushed also)

MQ-way

  • Have MQ extension enabled in your repo
  • Convert your local patches into MQ's patchset (on top of upstream code) in common branch
  • Have upsteam-repo in paths section of .hgrc in order to be able to pull from it
  • Pull, when needed, from upstream
  • Merge patches with upstream
  • For patch-exchange you have two ways
    • if patch-queue was created as repository (hg qinit -c) you can push this repository in addition to "base"
    • Using MQCollab extension on top of MQ will allow you to exchange and synchronize patches with collaborators directly (which have to have also MQ and MQCollab)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top