As I understand one of the main advantages of distributed revision control system like Mercurial is that you should not worry about breaking something in your super-important main repo (which is used by quite a lot other developers), and do all you work and researches in your personal remote clone until you understand that everything stable and you can push your work back. And hence I got my question: if it possible to push back not all your changes history (with several revisions which you made for yourself), but only one which is actually diff between your repo and current state of master.
One example:
hg init master-repo; cd master-repo
echo -e 'Important file\nWith Bug!' > file
hg commit -A -m "initial commit"
cd ..; hg clone master-repo hotfix-repo; cd hotfix-repo
echo "fix1" >> file
hg commit -m "first attempt to fix bug"
echo "fix2" >> file
hg commit -m 'Fixed it!'
Now (possibly after pull and merge with newest master-repo' changes) I want to push back only one changeset containing all changes that I've done without my local commits history. One possible solution is to create one more clone then use diff/patch between two clones to extract/apply changes from first one and commit them all at once in second repo. Then do push as in normal case. But is it possible to so using only mercurial commands?
Thanks in forward!
Opinions differ on whether or not it's good to collapse trial-and-error changesets into a single changeset before pushing:
Pros: you avoid having changesets in your history where your test suite fails — those changesets are bad for hg bisect
and add noise.
Con: you cannot collapse changesets that you have published to other repositories — doing so would only rewrite your local changesets and you would then have to clean up the other repositories manually.
Technically, it's perfectly safe to collapse a set of changesets into a single changeset before pushing. You start with
... a --- b --- c --- x --- y --- z
and you rewrite this into
... a --- b --- c --- w
where w
has exactly the same repository state as z
had (but a different parent changeset, obviously). There are no merges here (and hence no merge conflicts) so it cannot fail.
After rewriting, you can pull and merge with the upstream (d
and e
):
... a --- b --- c --- w --- v
\ /
d ----- e
You need an extension to do any kind of history rewriting. Here I would suggest one of:
Collapse extension: as the name implies, this extension is dedicated to collapsing changesets.
Histedit extension: full-fledged history editing, but the fold command let's you collapse changesets.
Rebase extension: this standard extension can move changesets around and collapse them at the same time. In the example above, it would move x --- y --- z
after e
:
... a --- b --- c --- d --- e --- x' --- y' --- z'
You can then optionally collapse x'
to z'
:
... a --- b --- c --- d --- e --- w'
Compared to just collapsing x
to z
, rebasing does involve merges so it can fail.