You want to keep a detailed history in your repo, but you want to have (and be able to export) an idealized history that only contains "reasonable" revsets, right? I can sympathize.
Solution 1: Use tags to mark interesting points in the history, and learn to ignore all the messy bits between them.
Solution 2: Use two branches and merge. Do your development in branch default
, and keep a parallel branch release
. (You could call it clean
, but in effect you are managing releases). Whenever default
is in a stable state that you want to checkpoint, switch to branch release
and merge into it the current state of default
-- in batches, if you wish. If you never commit anything directly to release
, there will never be a merge conflict.
(original branch) --o--o--o--o--o--o--o (default)
\ \ \
r ... ... --r--------r (release)
Result: You can update to any revision of release
and expect a functioning state. You can run hg log -r release
and you will only see the chosen checkpoints. You can examine the full log to see how everything happened. Drawbacks: Because the release
branch depends on default
, you can't push it to another repo without bringing default
with it. Also hg glog -r release
will look weird because of the repeated merges.
Solution 3: Use named branches as above, but use the rebase
extension instead of merging. It has an option to copy, rather than move outright, the rebased changesets; and it has an option --collapse
that will convert a set of revisions into a single one. Whenever you have a set of revisions r1:tip
you want to finalize, copy them from default
to release
as follows:
hg rebase --source r1 --dest release --keep --collapse
This pushes ONE revision at the head of release
that is equivalent to the entire changeset from r1 to the head of default
. The --keep
option makes it a copy, not a destructive rewrite. The advantage is that the release
branch looks just as you wanted: nice and clean, and you can push it without dragging the default branch with it. The disadvantage is that you cannot relate its stages to the revisions in default
, so I'd recommend method 2 unless you really have to hide the intermediate revisions. (Also: it's not as easy to squash your history in multiple batches, since rebase will move/copy all descendants of the "source" revision.)
All of these require you to do some extra work. This is inevitable, since mercurial has no way of knowing which revsets you'd like to squash.