Using changeset obsoletion with Kallithea

Andrew Shadura andrew at shadura.me
Sun May 29 19:18:40 UTC 2016


On 29/05/16 21:01, Thomas De Schampheleire wrote:
> On Sun, May 29, 2016 at 12:53 PM, Andrew Shadura <andrew at shadura.me> wrote:
>> 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.
> 
> This is an important point that I used to not know: changeset
> evolution does not require Evolve.
> Obsolescence markers are already handled and created by vanilla Mercurial.

>> 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
>>
> 
> What exactly does this bring on top of vanilla Mercurial? And where is
> this setting defined?
> Are you sure it is still relevant with recent versions of Mercurial, say 3.7+ ?

This is definitely still needed in Mercurial 3.7, I have just checked
mercurial/obsolete.py. This setting enables the creation and exchange of
obsolete markers. As I understand it, unless exchange is enabled, you
won't push any markers, and unless creation is enabled, commit --amend,
histedit and rebase use strip to edit history. The markers will still be
interpreted, as I understand it.

> I don't have this setting and use rebase/histedit, and do see obselete
> changes with 'log --hidden'.

>> Optionally, also this, where applicable:
>>
>> [phases]
>> publish = False
> 
> Thanks for writing all this.
> What is the plan with this text, will we publish it somewhere?

I think if my code gets merged, we may add some version of the text
above to the documentation.

-- 
Cheers,
  Andrew


More information about the kallithea-general mailing list