Using changeset obsoletion with Kallithea
Andrew Shadura
andrew at shadura.me
Sun May 29 10:53:01 UTC 2016
Hello everyone,
I've been using and advocating use of changeset obsoletion for quite a
while now, and tried to use it when submitting pull requests to
Kallithea as well, but I noticed very few people seem to understand how
it works, and some people seem to be a bit wary about it, so I thought
it may be worth explaining how I use it to others, and when Mads
suggested I do so, I felt motivated enough to write something up on this
topic :)
First of all, I need to admit I do not use Evolve extension, even though
I might benefit from it if I did, but in my opinion it adds to much
automation I don't need at the moment; in any case, obsoletion makes
work with Mercurial much more pleasant even without Evolve.
One thing you need to know about obsoletion to be able to use it is what
an obsoletion marker is. Basically, Mercurial can store a list of
changeset identifiers, sort of a map, which maps "old" changesets to
"new" ones every time you amend some changeset. Every such pair of
changeset identifiers is called an obsoletion marker: it "obsoletes" a
changeset, replacing it with another. Obsoletion markers can be pushed
and pulled, all at once, propagating between repositories. Every
obsoletion marker also stores some metadata: a timestamp and an email of
its author.
The way it works is the following. When you amend a changeset without
using obsoletion, this is what happens:
→ A → B → C ⇒ → A → B ⇒ → A → B → C’
(Mercurial first strips the original changeset, then creates a new one)
With obsoletion, no changesets are stripped. Instead, a new changeset is
created, along with an obsoletion marker:
→ A → B → C ⇒ → A → B ⇢ C
↘ C’
(C’ obsoletes C)
Obsolete changesets become hidden as soon as nothing references them
(including the working directory) provided they're not public. To be
able to see hidden changesets, you need to use --hidden option;
otherwise the changesets will be skipped from the log and other commands
will complain they don't exist.
Obsoletion markers are created automatically by many Mercurial commands,
most notably commit --amend and rebase. You can also manually create
them using an undocumented debugobsolete command.
Obsoletion is very useful in pull request-based workflows. With Git,
when you're submitting another iteration of a pull request, you may just
--force the branch, and the old iteration won't clutter history anymore,
and will be visible only if you know the commit hash — unless someone
garbage collected the repository. With Mercurial, every iteration of the
pull request is forever, unless you nuke the repository or strip extra
branches of history or use bundle repository overlays.
With obsoletion, it is possible to rebase your branch, rewrite the
history in whatever way you like, then push it again to a non-publishing
repository and have your previous iteration disappear from the default
view, while still being available for review from an old iteration of a
pull request. Kallithea doesn't directly support this workflow yet, but
I've written a proof of concept patch which is applied at Ook, so I can
show some examples:
https://kallithea-scm.org/repos/kallithea/pull-request/20
This was an original proposal to support "evolution" of pull requests.
After Mads and Thomas commented on it, I reworked the implementation and
pushed it along with obsoletion markers. The old changeset,
af2c5e101157, became obsoleted, and even though it's still visible in
the pull request, it's no longer possible to pull it or see it in the
changelog unless you specifically ask for it.
https://kallithea-scm.org/repos/kallithea/pull-request/32
This is a second iteration of the PR. If you do to
https://kallithea-scm.org/repos/andrewsh/kallithea/changeset/02257b8abe8d58fad0e10c929505561f5266bfd8
that page says:
Replaced by: 892ee667a841
Preceded by: af2c5e101157
That's because after I've got some comments, I changed the
implementation again, and posted that as
https://kallithea-scm.org/repos/kallithea/pull-request/45
When Mads is happy with the implementation, he can either directly pull
my changeset, if it's based on the right branch head, or he can rebase
it on the current default branch — which may produce obsoletion markers
if he has obsoletion enabled (I know he doesn't). And if it does, when
he pushes to the main repository, and I pull back from it, I'll have my
old implementation automatically obsoleted — and if I don't have it
checked out, it will be automatically replaced by the new changeset.
This helps having cleaner history in the repositories without having
multiheaded hydras we have now (or we don't actually have them, as I'm
cleaning up kallithea-incoming from time to time, but Unity's repository
definitely does, as Bitbucket doesn't support obsoletion).
Oh, and the last thing: how to get that cool thing. Just put this into
your hgrc:
[experimental]
evolution = all
Optionally, also this, where applicable:
[phases]
publish = False
--
Cheers,
Andrew
More information about the kallithea-general
mailing list