9

I'm new with Mercurial and I'm still trying to establish a workflow.

I clone a remote repository. I then make changes and commits to my local repository. I would like to push a clean revision history. I don't want to push some revisions that may only muddy the remote repository (e.g. typo rename of methods, adding of javadoc, removing whitespaces, etc). Is this possible?

Thank you!

Paul
  • 588
  • 1
  • 4
  • 16
  • Do you wish to completely avoid pushing some changes or having a 'clean' history while keeping all your changes? – Cédric Rup Sep 14 '11 at 09:25
  • I want to avoid pushing some changes. I want to push only the relevant ones – Paul Sep 14 '11 at 09:29
  • Might be possible, but as each commit only contains 'diffs', you may loose things. I'm worried when you talk about renames of methods – Cédric Rup Sep 14 '11 at 09:55
  • I'm talking simply about minor typo renames like from "execte" to "execute" for example. No changes on its intent. – Paul Sep 14 '11 at 10:39
  • 1
    Another example: I create a new method called "execute". Commit #1. Made some changes. Commit #2. I then renamed the method to "run". Commit #3. I changed my mind, renamed it back to "execute". Commit #4. I don't want to push commit #3 because it does not make sense. – Paul Sep 14 '11 at 10:55

4 Answers4

8

Indeed there are cases when it makes sense to prune/strip/polish changesets or to separate private/in-progress and public/ready changes. Here are some suggestion how to handle this with Mercurial:

  1. If you made a series of small commits (which is a good thing), but you prefer to publish them as one changeset (which makes sense if you committed - possibly contradicting - snapshot changesets), use the collapse extension:

    $ hg collapse -r <first-ref>:<last-ref> # both revs including
    
  2. If you just have changes you want to keep private while others you want to publish, either (a) use mercurial queues for you private changes or (b) commit you private-only changes in an own branch (named, bookmarked, or cloned) and regularly merge it with the public branch. The latter requires you to switch between branches quite often if you commit private and public changes alternating.


UPDATE

To illustrate option 2.b, consider this graph of changesets:

0--1--4--5---8--9   <= public/stable branch
    \     \
     2--3--6--7     <= private/dev branch

This means you've made changes 2 and 3 on the dev branch. Then you did some work on the stable branch (revisions 4 and 5). These changes also make sense in dev, so you merge them into dev (revision 6). Finally you make another experimental change in dev (revision 7) and some ready-to-publish improvements in stable (revisions 8 and 9). You can now publish (i.e. push to the remote repository) the changes made in stable, by running

$ hg push -r 9     # or `-r stable` if the branch is named or bookmarked as such

All private changes will stay local!

Note that if you plan to polish your private commits later (e.g. collapse them to one changeset), you must not merge in the stable branch (collapse cannot work across merges). Instead, rebase you private changes whenever you want them to be in sync with the latest changes in stable.

Oben Sonne
  • 9,893
  • 2
  • 40
  • 61
  • 1
    In option 2b, after I merge from my own private branch into a new "stable" branch, will the revision history from my private branch be pushed to the remote repository too? – Paul Sep 14 '11 at 12:03
  • 1
    You should merge the stable branch into the private one (not vice versa), i.e. update to your private branch, run `hg merge stable` and commit the merge. Now the merge is part of the private branch and won't be published when pushing the stable branch (e.g. `hg push -r stable` or `hg push -r `). – Oben Sonne Sep 14 '11 at 12:19
  • Concerning merge directions, see also: [Differences merging repository A->B vs B->A](http://stackoverflow.com/q/5594731/151299). – Oben Sonne Sep 14 '11 at 12:21
  • Oben, I get your point, but I also need to push changes to the remote repository. My issue here is to be able to push some changes, but not some revisions that I've done on my private branch. – Paul Sep 14 '11 at 13:49
2

This is more a question about revision control systems in general than about mercurial. Personally I would push everything, what you're suggesting kinda goes against versioning systems purposes.

However if you want to read more about hg workflows, try having a look at this guide or this wiki.

You could also be interested in the rollback command, that enables you to fix the latest commit.

edit: the option I would go for is to keep two branches: one identical to the remote repository where you commit only "official" changes, and one where you merge new official commits and make additional private commits.

Riccardo T.
  • 8,907
  • 5
  • 38
  • 78
  • 3
    "what you're suggesting kinda goes against versioning systems purposes": OTOH, git has a lot of tools for "rewriting history" and cherry-picking and cleaning up private commits into publishable versions. – Thilo Sep 14 '11 at 09:53
  • 1
    It's absolutely true, that's why I wrote "personally" :) Git tools for rebasing, cherry-picking and so on doesn't really destroy or change anything, the old commits are still recoverable for a quite long time. However he's not talking about little changes for publishable version, he spoke of avoiding to push method renamings, javadoc... theyre quite important changes. – Riccardo T. Sep 14 '11 at 10:08
  • 1
    You can have a look at this [guide on branches](http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/) in order to choose. – Riccardo T. Sep 14 '11 at 12:26
1

If all the parasitic changes have been made at last, you can simply strip them.

If not, you can try to use the Patch Queue to remove the unnecessary commits:

  • Import your changes one by one to MQ and unapply the patches
  • Delete the patches that match the changes you don't want
  • reapply the remaining patches

This will work for small commits. Please if you try this, do it on a clone of your local repo to avoid loss.

Also, take care not to alter an already 'shared' (pushed) history.

Cédric Rup
  • 15,468
  • 3
  • 39
  • 30
0

Histedit also can be usable and more easy (than MQ) solution for editing history

muxator
  • 348
  • 3
  • 8
Lazy Badger
  • 94,711
  • 9
  • 78
  • 110