Changeset Evolution For Mercurial
Changeset evolution (or just evolution) lets developers modify existing changesets in a controlled and collaborative fashion. It attempts to take the best of mq and pbranch.
Background
Key Points
- Changesets are regular Mercurial changesets, much like with applied mq patches, and unlike pbranch’s inter-branch diffs.
- Changes to changesets are tracked, somewhat like with pbranch or versioned mq.
- Evolution integrates with bookmarks to name particular patches. This is like mq’s patch names, or pbranch’s branch names.
- Conflict resolution relies fully on Mercurial’s merge and rebase mechanisms, much as with pbranch. This applies both to conflicts when you’re rebasing your own changesets, as well as when merging diverging updates to the same changeset by multiple developers.
- Changesets can transition seamlessly from a tentative to a frozen state (for instance when accepted upstream), much like with mq, and notably different from pbranch.
- No history is ever rewritten (except optionally during garbage collection). Instead, we simply hide old versions of changesets (by default). This is like git’s reflog.
Implementation Notes
- Changesets are replaced by newer versions. Older versions are then by default hidden from
hg logetc. - Prior to being replaced, changesets are updated by descendant changesets. The change descriptions of the updating changesets serve as the changelog for the evolution of a specific changeset.
- Updateing changesets ensure we always commit first, and only then start rewiring things. This should make things robust and interruptible (when merge conflicts arise, for instance).
- Older changesets could be garbage-collected eventually.
- Information about updates and replacements is kept in
.hg/evolution/, in a separate file per nodeid which replaces or updates another changeset. This information would have to travel between repos via pushkey (so it is garbage-collectable).