diff -pruN 11.1.3-1/CHANGELOG 11.1.9-1/CHANGELOG
--- 11.1.3-1/CHANGELOG	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/CHANGELOG	2025-07-25 16:21:02.000000000 +0000
@@ -1,6 +1,76 @@
 Changelog
 =========
 
+11.1.9 -- 2025-07-25
+--------------------
+
+  * compatibility with Mercurial 7.1
+
+topic (1.1.9)
+
+  * compatibility with Mercurial 7.1
+
+11.1.8 -- 2025-03-11
+--------------------
+
+  * compatibility with Mercurial 7.0
+
+topic (1.1.8)
+
+  * compatibility with Mercurial 7.0
+
+11.1.7.post1 -- 2025-02-06
+--------------------------
+
+  * no changes from 11.1.7, only upgraded packaging
+
+11.1.7 -- 2025-02-06
+--------------------
+
+  * evolve: fix version check from 972d98ce3552 for hg 6.8 (issue6958)
+
+  * obslog: also display patch for rebased changesets (requires Mercurial 5.6
+    or newer for in-memory rebase support)
+
+11.1.6 -- 2024-11-27
+--------------------
+
+  * evolve: unrelated parts of splits are no longer considered
+    content-divergent, this is a port of an upstream patch included in hg 6.8.2
+
+  * obshashrange: avoid executing too many DELETE requests at once
+  * obshashrange: reset the cache if too many ranges need to be deleted
+
+topic (1.1.6)
+
+  * stack: when stack base is obsolete, pick any successor, even if at random
+
+11.1.5 -- 2024-10-26
+--------------------
+
+  * compatibility with Mercurial 6.9
+
+  * evolve: check that the evolved revisions are indeed in the repo during
+    abort, fixes an issue when trying to access them during cleanup step
+
+  * docs: update installation instructions due to PEP 668
+  * docs: minor edits and fixes in evolve and topic tutorials
+
+  * tests: more tests related to Python packaging
+
+topic (1.1.5)
+
+  * compatibility with Mercurial 6.9
+
+11.1.4 -- 2024-06-28
+--------------------
+
+  * compatibility with Mercurial 6.8
+
+topic (1.1.4)
+
+  * compatibility with Mercurial 6.8
+
 11.1.3 -- 2024-04-12
 --------------------
 
diff -pruN 11.1.3-1/MANIFEST.in 11.1.9-1/MANIFEST.in
--- 11.1.3-1/MANIFEST.in	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/MANIFEST.in	2025-07-25 16:21:02.000000000 +0000
@@ -29,3 +29,4 @@ prune contrib
 prune debian
 prune .gitlab
 prune hgext3rd/evolve/hack
+prune tests/blacklists
diff -pruN 11.1.3-1/PKG-INFO 11.1.9-1/PKG-INFO
--- 11.1.3-1/PKG-INFO	2024-04-12 19:06:20.000000000 +0000
+++ 11.1.9-1/PKG-INFO	2025-07-25 16:21:08.976573700 +0000
@@ -1,279 +1,350 @@
-Metadata-Version: 1.0
+Metadata-Version: 2.4
 Name: hg-evolve
-Version: 11.1.3
+Version: 11.1.9
 Summary: Flexible evolution of Mercurial history.
 Home-page: https://www.mercurial-scm.org/doc/evolution/
 Author: Pierre-Yves David
 Author-email: pierre-yves.david@ens-lyon.org
+Maintainer: Pierre-Yves David
+Maintainer-email: pierre-yves.david@ens-lyon.org
 License: GPLv2+
-Description: =============================
-        Mutable History For Mercurial
-        =============================
-        
-        Evolve Extension
-        ================
-        
-        This package supplies the evolve extension for Mercurial,
-        
-        **The full implementation of the changeset evolution concept is still in
-        progress.**  Please subscribe to the `evolve-testers mailing list
-        <https://www.mercurial-scm.org/mailman/listinfo/evolve-testers>`_ to stay up to
-        date with changes.
-        
-        This extension:
-        
-        * enables the "`changeset evolution`_" feature of core Mercurial,
-        
-        * provides a set of commands to rewrite history in a distributed way,
-        
-        * issues various warning messages when "troubles" from changeset evolution
-          appear in your repository,
-        
-        * provides an ``hg evolve`` command to deal with such troubles,
-        
-        * improves performance of obsolescence marker exchange and discovery during
-          push and pull.
-        
-        .. _`changeset evolution`: https://www.mercurial-scm.org/wiki/ChangesetEvolution
-        
-        Documentation
-        -------------
-        
-        We recommend reading the documentation first. An online version is available
-        here:
-        
-            https://www.mercurial-scm.org/doc/evolution/
-        
-        Source of the documentation can be found in ``docs/``.
-        
-        How to Install
-        ==============
-        
-        Using Pip
-        ---------
-        
-        You can install the latest released version using pip::
-        
-            $ pip install --user hg-evolve
-        
-        Then enable it in your hgrc::
-        
-            $ hg config --edit # add these two lines:
-            [extensions]
-            evolve =
-        
-        From Source
-        -----------
-        
-        To install a local version from source::
-        
-            $ hg clone https://www.mercurial-scm.org/repo/evolve/
-            $ cd evolve
-            # optionally `hg update <target revision>`
-            $ pip install --user .
-        
-        Then enable it in your hgrc::
-        
-            $ hg config --edit # add these two lines:
-            [extensions]
-            evolve =
-        
-        It's also possible to use evolve without installing it, in which case you will
-        need to provide the full path to ``hgext3rd/evolve/``, for example::
-        
-            [extensions]
-            evolve = ~/evolve/hgext3rd/evolve
-        
-        Pitfalls
-        --------
-        
-        If you get ``"failed to import extension evolve: No module named 'evolve'"``
-        error, there are a couple of things to check:
-        
-        * make sure you gave pip the correct package name (it's hg-evolve),
-        
-        * make sure evolve is installed for the same version of Python that you use for
-          running Mercurial (``hg debuginstall | grep Python``).
-        
-        Extension Purpose
-        =================
-        
-        The goal of this extension is to provide an appropriate place for code and
-        concepts related to `changeset evolution`_ to mature. In this extension we
-        allow hackier code, unlocking quick experimentation and faster iterations.
-        
-        In addition, evolve extension supports a wide range of Mercurial versions,
-        allowing us to reach a larger user base for feedback. The extension is not tied
-        to the Mercurial release cycle and can release new features and bug fixes at a
-        higher rate if necessary.
-        
-        Once a concept is deemed ready, its implementation is moved into core
-        Mercurial. The maturation period helped us to get a clearer picture of what was
-        needed. During the upstreaming process, we can use this clearer picture to
-        clean up the code and upgrade it to an appropriate quality for core Mercurial.
-        
-        Python 3 Support
-        ================
-        
-        Mercurial announced official `support for Python 3`_ starting with its 5.2
-        release. Since 9.3.0, evolve has official support for Python 3.6+.
-        
-        .. _`support for Python 3`: https://www.mercurial-scm.org/wiki/Python3
-        
-        Python 2 Support
-        ================
-        
-        Python 2 is supported by evolve. However, Mercurial 6.2 release dropped support
-        for it, so evolve can work on Python 2 only on earlier versions.
-        
-        Debian packages that are built using Heptapod CI only install files for Python
-        3, because they target current Debian stable.
-        
-        How to Contribute
-        =================
-        
-        Discussion happens in #hg-evolve and #mercurial on libera_ IRC network.
-        
-        .. _libera: https://libera.chat/
-        
-        Bugs are to be reported on the Mercurial's bug tracker (component:
-        `evolution`_).
-        
-        .. _evolution: https://bz.mercurial-scm.org/buglist.cgi?component=evolution&query_format=advanced&resolution=---
-        
-        The recommended way to submit a patch is to create a Merge Request on
-        https://foss.heptapod.net/mercurial/evolve. To do so, create an account and
-        request access. You'll then be able to create a topic-based merge request.
-        
-        Alternatively, you can use the patchbomb extension to send email to `mercurial
-        devel <https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel>`_.
-        Please make sure to use the evolve-ext flag when doing so. You can use a
-        command like this::
-        
-            $ hg email --to mercurial-devel@mercurial-scm.org --flag evolve-ext --rev '<your patches>'
-        
-        For guidelines on the patch description, see the `official Mercurial guideline`_.
-        
-        .. _`official Mercurial guideline`: https://mercurial-scm.org/wiki/ContributingChanges#Patch_descriptions
-        
-        Please don't forget to update and run the tests when you fix a bug or add a
-        feature. To run the tests, you need a working copy of Mercurial, say in
-        $HGSRC::
-        
-            $ cd tests
-            $ python $HGSRC/tests/run-tests.py
-        
-        When certain blocks of code need to cope with API changes in core Mercurial,
-        they should have comments in the ``hg <= x.y (commit hash)`` format. For
-        example, if a function needs another code path because of changes introduced in
-        02802fa87b74 that was first included in Mercurial 5.3, then the comment should
-        be::
-        
-            # hg <= 5.2 (02802fa87b74)
-        
-        See also tests/test-check-compat-strings.t.
-        
-        Branch policy
-        -------------
-        
-        The evolve tests are highly impacted by changes in core Mercurial. To deal with
-        this, we use named branches.
-        
-        There are two main branches: "stable" and "default". Tests on these branches
-        are supposed to pass with the corresponding "default" and "stable" branch from
-        core Mercurial. The documentation is built from the tip of stable.
-        
-        In addition, we have compatibility branches to check tests on older versions of
-        Mercurial. They are the "mercurial-x.y" branches. They are used to apply
-        expected test changes only, no code changes should happen there.
-        
-        Test output changes from a changeset in core should add the following line to
-        their patch description::
-        
-            CORE-TEST-OUTPUT-UPDATE: <changeset hash>
-        
-        Format-source config
-        ====================
-        
-        Format-source helps smooth out the pain of merging after auto-formatting.
-        Follow the installation instructions at the `format-source`_ repo.
-        
-        .. _`format-source`: https://foss.heptapod.net/mercurial/format-source
-        
-        Then update your per-repo config file::
-        
-            $ hg config --local --edit # add these lines:
-            [extensions]
-            formatsource =
-        
-            [format-source]
-            byteify-strings = python3 ~/hg/contrib/byteify-strings.py --dictiter --treat-as-kwargs kwargs opts commitopts TROUBLES --allow-attr-methods
-            byteify-strings:mode.input = file
-            byteify-strings:mode.output = pipe
-        
-        Release Checklist
-        =================
-        
-        * use contrib/merge-test-compat.sh to merge with the test compatibility
-          branches,
-        
-        * make sure the tests are happy on all supported versions,
-        
-        * make sure there is no code difference between the compatibility branches and
-          stable (no diff within hgext3rd/),
-        
-        * update the ``testedwith`` variable for all extensions (remove '.dev0'):
-        
-          - hgext3rd/evolve/metadata.py
-          - hgext3rd/topic/__init__.py
-          - hgext3rd/pullbundle.py
-        
-        * make sure CHANGELOG is up-to-date,
-        
-        * add a date to the CHANGELOG entry for the target version,
-        
-        * update the ``__version__`` field of all relevant extensions:
-        
-          - hgext3rd/evolve/metadata.py
-          - hgext3rd/topic/__init__.py
-          - hgext3rd/pullbundle.py (if touched)
-        
-        * create a new Debian changelog entry:
-        
-          - debchange --newversion x.y.z-1 "new upstream release"
-          - debchange --release
-        
-        * sanity check install and sdist targets of setup.py:
-        
-          - python setup.py install --home=$(mktemp -d)
-          - python setup.py sdist
-        
-        * tag the commit,
-        
-        * move ``@`` bookmark to the new tag,
-        
-        * push and publish the tag,
-        
-        * upload the tarball to PyPI,
-        
-        * build .deb on Heptapod CI for the tagged commit,
-        
-        * make an announcement on evolve-testers@mercurial-scm.org and
-          mercurial@mercurial-scm.org,
-        
-        * bump versions of all extensions and add ``.dev0`` (see existing commits as an
-          example):
-        
-          - hgext3rd/evolve/metadata.py
-          - hgext3rd/topic/__init__.py
-          - hgext3rd/pullbundle.py
-        
-          Version bump rules:
-        
-          - stable branch x.y.z+1.dev0
-          - default branch x.y+1.0.dev0
-        
-        * merge stable into default.
-        
 Keywords: hg mercurial
-Platform: UNKNOWN
+Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4
+Description-Content-Type: text/x-rst
+License-File: COPYING
+Dynamic: author
+Dynamic: author-email
+Dynamic: description
+Dynamic: description-content-type
+Dynamic: home-page
+Dynamic: keywords
+Dynamic: license
+Dynamic: license-file
+Dynamic: maintainer
+Dynamic: maintainer-email
+Dynamic: requires-python
+Dynamic: summary
+
+=============================
+Mutable History For Mercurial
+=============================
+
+Evolve Extension
+================
+
+This package supplies the evolve extension for Mercurial,
+
+**The full implementation of the changeset evolution concept is still in
+progress.**  Please subscribe to the `evolve-testers mailing list
+<https://www.mercurial-scm.org/mailman/listinfo/evolve-testers>`_ to stay up to
+date with changes.
+
+This extension:
+
+* enables the "`changeset evolution`_" feature of core Mercurial,
+
+* provides a set of commands to rewrite history in a distributed way,
+
+* issues various warning messages when "troubles" from changeset evolution
+  appear in your repository,
+
+* provides an ``hg evolve`` command to deal with such troubles,
+
+* improves performance of obsolescence marker exchange and discovery during
+  push and pull.
+
+.. _`changeset evolution`: https://wiki.mercurial-scm.org/ChangesetEvolution
+
+Documentation
+-------------
+
+We recommend reading the documentation first. An online version is available
+here:
+
+    https://www.mercurial-scm.org/doc/evolution/
+
+Source of the documentation can be found in ``docs/``.
+
+How to Install
+==============
+
+Using Pip
+---------
+
+You can install the latest released version using pip::
+
+    $ pip install --user hg-evolve
+
+Note: some distributions have adopted PEP 668 and made using ``pip install
+--user`` more difficult than it should be. One of the cleanest ways around this
+issue is to install both Mercurial and this extension in a separate virtual
+environment. If you don't want to manage the virtual environment manually, you
+can use Pipx.
+
+Using Pipx
+----------
+
+Its documentation explains that "pipx is made specifically for application
+installation", and the idea is that for every application it can create and
+maintain a separate virtual environment and make all executables available on a
+single path (e.g. ~/.local/bin/ on Linux, check ``pipx ensurepath``).
+
+To create a virtual environment for hg and install evolve::
+
+    $ pipx install mercurial
+    $ pipx inject mercurial hg-evolve
+    # or pipx runpip mercurial install hg-evolve
+
+Note: it's recommended to use ``inject`` command to install evolve, but
+sometimes ``runpip`` could be used. On some setups ``inject`` might require
+specifying the full path to the extension in the configuration file, while
+``runpip`` might not.
+
+Using Your Package Manager
+--------------------------
+
+Sometimes your distribution's package manager might have the newest (or recent
+enough) version of the extension. For example, both `Debian`_ and `Ubuntu`_
+currently have a package called ``mercurial-evolve``.  Similarly, other
+distributions might have it packaged, possibly under a slightly different name.
+Try searching your package manager's database or see `this Repology page`_.
+
+.. _`Debian`: https://packages.debian.org/search?keywords=mercurial-evolve&searchon=names&exact=1&suite=all&section=all
+.. _`Ubuntu`: https://packages.ubuntu.com/search?keywords=mercurial-evolve&searchon=names&exact=1&suite=all&section=all
+.. _`this Repology page`: https://repology.org/project/mercurial-evolve/related
+
+From Source
+-----------
+
+To obtain a local version from source::
+
+    $ hg clone https://repo.mercurial-scm.org/evolve
+
+There's no need to compile anything or run ``make``.
+
+This method keeps the extension in its own repo, and you can use it by
+specifying the full path to the ``hgext3rd/evolve/``.
+
+Alternatively, you can install it::
+
+    $ cd evolve
+    # optionally `hg update <target revision>`
+    $ pip install --user .
+
+This should avoid the need to specify the full path to the extension.
+
+Enabling the Extension
+----------------------
+
+After installing the extension, you need to enable it before you can use it.
+
+To do that, edit your hgrc::
+
+    $ hg config --edit # add these two lines:
+    [extensions]
+    evolve =
+
+If you didn't install the extension or Mercurial can't find it on one of the
+default paths, you need to specify the full path to ``hgext3rd/evolve/``::
+
+    [extensions]
+    evolve = ~/evolve/hgext3rd/evolve
+
+Similarly, if you want to enable topic extension, do this::
+
+    $ hg config --edit
+    [extensions]
+    topic =
+    # or
+    topic = ~/evolve/hgext3rd/topic
+
+Pitfalls
+--------
+
+If you get ``"failed to import extension evolve: No module named 'evolve'"``
+error, there are a couple of things to check:
+
+* make sure you gave pip/pipx the correct package name (it's ``hg-evolve``),
+
+* make sure evolve is installed for the same version of Python that you use for
+  running Mercurial (``hg debuginstall | grep Python``),
+
+* try specifying the full path to the ``hgext3rd/evolve/`` directory.
+
+Extension Purpose
+=================
+
+The goal of this extension is to provide an appropriate place for code and
+concepts related to `changeset evolution`_ to mature. In this extension we
+allow hackier code, unlocking quick experimentation and faster iterations.
+
+In addition, evolve extension supports a wide range of Mercurial versions,
+allowing us to reach a larger user base for feedback. The extension is not tied
+to the Mercurial release cycle and can release new features and bug fixes at a
+higher rate if necessary.
+
+Once a concept is deemed ready, its implementation is moved into core
+Mercurial. The maturation period helped us to get a clearer picture of what was
+needed. During the upstreaming process, we can use this clearer picture to
+clean up the code and upgrade it to an appropriate quality for core Mercurial.
+
+Python 3 Support
+================
+
+Mercurial announced official `support for Python 3`_ starting with its 5.2
+release. Since 9.3.0, evolve has official support for Python 3.6+.
+
+.. _`support for Python 3`: https://wiki.mercurial-scm.org/Python3
+
+Python 2 Support
+================
+
+Python 2 is supported by evolve. However, Mercurial 6.2 release dropped support
+for it, so evolve can work on Python 2 only on earlier versions.
+
+Debian packages that are built using Heptapod CI only install files for Python
+3, because they target current Debian stable.
+
+How to Contribute
+=================
+
+Discussion happens in #hg-evolve and #mercurial on libera_ IRC network.
+
+.. _libera: https://libera.chat/
+
+Bugs are to be reported on the Mercurial's bug tracker (component:
+`evolution`_).
+
+.. _evolution: https://bz.mercurial-scm.org/buglist.cgi?component=evolution&query_format=advanced&resolution=---
+
+The recommended way to submit a patch is to create a Merge Request on
+https://foss.heptapod.net/mercurial/evolve. To do so, create an account and
+request access. You'll then be able to create a topic-based merge request.
+
+Alternatively, you can use the patchbomb extension to send email to `mercurial
+devel <https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel>`_.
+Please make sure to use the evolve-ext flag when doing so. You can use a
+command like this::
+
+    $ hg email --to mercurial-devel@mercurial-scm.org --flag evolve-ext --rev '<your patches>'
+
+For guidelines on the patch description, see the `official Mercurial guideline`_.
+
+.. _`official Mercurial guideline`: https://wiki.mercurial-scm.org/ContributingChanges#Patch_descriptions
+
+Please don't forget to update and run the tests when you fix a bug or add a
+feature. To run the tests, you need a working copy of Mercurial, say in
+$HGSRC::
+
+    $ cd tests
+    $ python $HGSRC/tests/run-tests.py
+
+When certain blocks of code need to cope with API changes in core Mercurial,
+they should have comments in the ``hg <= x.y (commit hash)`` format. For
+example, if a function needs another code path because of changes introduced in
+02802fa87b74 that was first included in Mercurial 5.3, then the comment should
+be::
+
+    # hg <= 5.2 (02802fa87b74)
+
+See also tests/test-check-compat-strings.t.
+
+Branch policy
+-------------
+
+The evolve tests are highly impacted by changes in core Mercurial. To deal with
+this, we use named branches.
+
+There are two main branches: "stable" and "default". Tests on these branches
+are supposed to pass with the corresponding "default" and "stable" branch from
+core Mercurial. The documentation is built from the tip of stable.
+
+In addition, we have compatibility branches to check tests on older versions of
+Mercurial. They are the "mercurial-x.y" branches. They are used to apply
+expected test changes only, no code changes should happen there.
+
+Test output changes from a changeset in core should add the following line to
+their patch description::
+
+    CORE-TEST-OUTPUT-UPDATE: <changeset hash>
+
+Format-source config
+====================
+
+Format-source helps smooth out the pain of merging after auto-formatting.
+Follow the installation instructions at the `format-source`_ repo.
+
+.. _`format-source`: https://foss.heptapod.net/mercurial/format-source
+
+Then update your per-repo config file::
+
+    $ hg config --local --edit # add these lines:
+    [extensions]
+    formatsource =
+
+    [format-source]
+    byteify-strings = python3 ~/hg/contrib/byteify-strings.py --dictiter --treat-as-kwargs kwargs opts commitopts TROUBLES --allow-attr-methods
+    byteify-strings:mode.input = file
+    byteify-strings:mode.output = pipe
+
+Release Checklist
+=================
+
+* use contrib/merge-test-compat.sh to merge with the test compatibility
+  branches,
+
+* make sure the tests are happy on all supported versions,
+
+* make sure there is no code difference between the compatibility branches and
+  stable (no diff within hgext3rd/),
+
+* update the ``testedwith`` variable for all extensions (remove '.dev0'):
+
+  - hgext3rd/evolve/metadata.py
+  - hgext3rd/topic/__init__.py
+  - hgext3rd/pullbundle.py
+
+* make sure CHANGELOG is up-to-date,
+
+* add a date to the CHANGELOG entry for the target version,
+
+* update the ``__version__`` field of all relevant extensions:
+
+  - hgext3rd/evolve/metadata.py
+  - hgext3rd/topic/__init__.py
+  - hgext3rd/pullbundle.py (if touched)
+
+* create a new Debian changelog entry:
+
+  - debchange --newversion x.y.z-1 "new upstream release"
+  - debchange --release
+
+* sanity check install and sdist targets of setup.py:
+
+  - python setup.py install --home=$(mktemp -d)
+  - python setup.py sdist
+
+* tag the commit,
+
+* push and publish the tag,
+
+* upload the tarball to PyPI,
+
+* build .deb on Heptapod CI for the tagged commit,
+
+* make an announcement on evolve-testers@mercurial-scm.org and
+  mercurial@mercurial-scm.org,
+
+* bump versions of all extensions and add ``.dev0`` (see existing commits as an
+  example):
+
+  - hgext3rd/evolve/metadata.py
+  - hgext3rd/topic/__init__.py
+  - hgext3rd/pullbundle.py
+
+  Version bump rules:
+
+  - stable branch x.y.z+1.dev0
+  - default branch x.y+1.0.dev0
+
+* merge stable into default.
diff -pruN 11.1.3-1/README.rst 11.1.9-1/README.rst
--- 11.1.3-1/README.rst	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/README.rst	2025-07-25 16:21:02.000000000 +0000
@@ -26,7 +26,7 @@ This extension:
 * improves performance of obsolescence marker exchange and discovery during
   push and pull.
 
-.. _`changeset evolution`: https://www.mercurial-scm.org/wiki/ChangesetEvolution
+.. _`changeset evolution`: https://wiki.mercurial-scm.org/ChangesetEvolution
 
 Documentation
 -------------
@@ -48,44 +48,101 @@ You can install the latest released vers
 
     $ pip install --user hg-evolve
 
-Then enable it in your hgrc::
-
-    $ hg config --edit # add these two lines:
-    [extensions]
-    evolve =
+Note: some distributions have adopted PEP 668 and made using ``pip install
+--user`` more difficult than it should be. One of the cleanest ways around this
+issue is to install both Mercurial and this extension in a separate virtual
+environment. If you don't want to manage the virtual environment manually, you
+can use Pipx.
+
+Using Pipx
+----------
+
+Its documentation explains that "pipx is made specifically for application
+installation", and the idea is that for every application it can create and
+maintain a separate virtual environment and make all executables available on a
+single path (e.g. ~/.local/bin/ on Linux, check ``pipx ensurepath``).
+
+To create a virtual environment for hg and install evolve::
+
+    $ pipx install mercurial
+    $ pipx inject mercurial hg-evolve
+    # or pipx runpip mercurial install hg-evolve
+
+Note: it's recommended to use ``inject`` command to install evolve, but
+sometimes ``runpip`` could be used. On some setups ``inject`` might require
+specifying the full path to the extension in the configuration file, while
+``runpip`` might not.
+
+Using Your Package Manager
+--------------------------
+
+Sometimes your distribution's package manager might have the newest (or recent
+enough) version of the extension. For example, both `Debian`_ and `Ubuntu`_
+currently have a package called ``mercurial-evolve``.  Similarly, other
+distributions might have it packaged, possibly under a slightly different name.
+Try searching your package manager's database or see `this Repology page`_.
+
+.. _`Debian`: https://packages.debian.org/search?keywords=mercurial-evolve&searchon=names&exact=1&suite=all&section=all
+.. _`Ubuntu`: https://packages.ubuntu.com/search?keywords=mercurial-evolve&searchon=names&exact=1&suite=all&section=all
+.. _`this Repology page`: https://repology.org/project/mercurial-evolve/related
 
 From Source
 -----------
 
-To install a local version from source::
+To obtain a local version from source::
+
+    $ hg clone https://repo.mercurial-scm.org/evolve
+
+There's no need to compile anything or run ``make``.
+
+This method keeps the extension in its own repo, and you can use it by
+specifying the full path to the ``hgext3rd/evolve/``.
+
+Alternatively, you can install it::
 
-    $ hg clone https://www.mercurial-scm.org/repo/evolve/
     $ cd evolve
     # optionally `hg update <target revision>`
     $ pip install --user .
 
-Then enable it in your hgrc::
+This should avoid the need to specify the full path to the extension.
+
+Enabling the Extension
+----------------------
+
+After installing the extension, you need to enable it before you can use it.
+
+To do that, edit your hgrc::
 
     $ hg config --edit # add these two lines:
     [extensions]
     evolve =
 
-It's also possible to use evolve without installing it, in which case you will
-need to provide the full path to ``hgext3rd/evolve/``, for example::
+If you didn't install the extension or Mercurial can't find it on one of the
+default paths, you need to specify the full path to ``hgext3rd/evolve/``::
 
     [extensions]
     evolve = ~/evolve/hgext3rd/evolve
 
+Similarly, if you want to enable topic extension, do this::
+
+    $ hg config --edit
+    [extensions]
+    topic =
+    # or
+    topic = ~/evolve/hgext3rd/topic
+
 Pitfalls
 --------
 
 If you get ``"failed to import extension evolve: No module named 'evolve'"``
 error, there are a couple of things to check:
 
-* make sure you gave pip the correct package name (it's hg-evolve),
+* make sure you gave pip/pipx the correct package name (it's ``hg-evolve``),
 
 * make sure evolve is installed for the same version of Python that you use for
-  running Mercurial (``hg debuginstall | grep Python``).
+  running Mercurial (``hg debuginstall | grep Python``),
+
+* try specifying the full path to the ``hgext3rd/evolve/`` directory.
 
 Extension Purpose
 =================
@@ -110,7 +167,7 @@ Python 3 Support
 Mercurial announced official `support for Python 3`_ starting with its 5.2
 release. Since 9.3.0, evolve has official support for Python 3.6+.
 
-.. _`support for Python 3`: https://www.mercurial-scm.org/wiki/Python3
+.. _`support for Python 3`: https://wiki.mercurial-scm.org/Python3
 
 Python 2 Support
 ================
@@ -146,7 +203,7 @@ command like this::
 
 For guidelines on the patch description, see the `official Mercurial guideline`_.
 
-.. _`official Mercurial guideline`: https://mercurial-scm.org/wiki/ContributingChanges#Patch_descriptions
+.. _`official Mercurial guideline`: https://wiki.mercurial-scm.org/ContributingChanges#Patch_descriptions
 
 Please don't forget to update and run the tests when you fix a bug or add a
 feature. To run the tests, you need a working copy of Mercurial, say in
@@ -242,8 +299,6 @@ Release Checklist
 
 * tag the commit,
 
-* move ``@`` bookmark to the new tag,
-
 * push and publish the tag,
 
 * upload the tarball to PyPI,
diff -pruN 11.1.3-1/debian/changelog 11.1.9-1/debian/changelog
--- 11.1.3-1/debian/changelog	2024-05-22 18:53:14.000000000 +0000
+++ 11.1.9-1/debian/changelog	2025-08-11 11:25:22.000000000 +0000
@@ -1,3 +1,10 @@
+mercurial-evolve (11.1.9-1) unstable; urgency=medium
+
+  * Team upload.
+  * New upstream version 11.1.9 (Closes: #1076081, #1076895).
+
+ -- Bastian Germann <bage@debian.org>  Mon, 11 Aug 2025 13:25:22 +0200
+
 mercurial-evolve (11.1.3-1) unstable; urgency=medium
 
   * Team upload.
diff -pruN 11.1.3-1/debian/copyright 11.1.9-1/debian/copyright
--- 11.1.3-1/debian/copyright	2024-02-15 20:59:28.000000000 +0000
+++ 11.1.9-1/debian/copyright	2025-08-11 11:25:22.000000000 +0000
@@ -4,7 +4,7 @@ Source: https://www.mercurial-scm.org/re
 
 Files: *
 Copyright:
- 2011—2022 Pierre-Yves David <pierre-yves.david@octobus.net>
+ 2011—2025 Pierre-Yves David <pierre-yves.david@octobus.net>
            Anton Shestakov <av6@dwimlabs.net>
            Pulkit Goyal <7895pulkit@gmail.com>
            Boris Feld <boris.feld@octobus.net>
diff -pruN 11.1.3-1/debian/watch 11.1.9-1/debian/watch
--- 11.1.3-1/debian/watch	2024-02-15 20:59:28.000000000 +0000
+++ 11.1.9-1/debian/watch	2025-08-11 11:25:22.000000000 +0000
@@ -1,3 +1,3 @@
 version=4
 opts=uversionmangle=s/(rc|a|b|c)/~$1/ \
-https://pypi.debian.net/hg-evolve/hg-evolve@ANY_VERSION@@ARCHIVE_EXT@
+https://pypi.debian.net/hg-evolve/hg[_-]evolve@ANY_VERSION@@ARCHIVE_EXT@
diff -pruN 11.1.3-1/docs/conf.py 11.1.9-1/docs/conf.py
--- 11.1.3-1/docs/conf.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/docs/conf.py	2025-07-25 16:21:02.000000000 +0000
@@ -33,7 +33,7 @@ master_doc = 'index'
 
 # General substitutions.
 project = 'evolve extension for Mercurial'
-copyright = '2010-2014, Pierre-Yves David, Greg Ward, and contributors'
+copyright = '2010-2025, Pierre-Yves David, Greg Ward, and contributors'
 
 # The default replacements for |version| and |release|, also used in various
 # other places throughout the built documents.
@@ -98,7 +98,7 @@ html_theme_path = ['.']
 # The name of an image file (within the static path) to use as favicon of the
 # docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # pixels large.
-html_favicon = 'logo-evolve.ico'
+html_favicon = 'static/logo-evolve.ico'
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
diff -pruN 11.1.3-1/docs/troubles-handling.rst 11.1.9-1/docs/troubles-handling.rst
--- 11.1.3-1/docs/troubles-handling.rst	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/docs/troubles-handling.rst	2025-07-25 16:21:02.000000000 +0000
@@ -1,3 +1,5 @@
+:orphan:
+
 ###########################################################
 Possible troubles in rewriting history and their resolution
 ###########################################################
diff -pruN 11.1.3-1/docs/tutorial/README.rst 11.1.9-1/docs/tutorial/README.rst
--- 11.1.3-1/docs/tutorial/README.rst	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/docs/tutorial/README.rst	2025-07-25 16:21:02.000000000 +0000
@@ -1,3 +1,5 @@
+:orphan:
+
 =============================
 Training supports
 =============================
diff -pruN 11.1.3-1/docs/tutorials/topic-tutorial.t 11.1.9-1/docs/tutorials/topic-tutorial.t
--- 11.1.3-1/docs/tutorials/topic-tutorial.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/docs/tutorials/topic-tutorial.t	2025-07-25 16:21:02.000000000 +0000
@@ -6,12 +6,12 @@ This Mercurial configuration example is
 
 .. Various setup
 
-  $ . "$TESTDIR/testlib/topic_setup.sh"
+  $ . "$TESTDIR/testlib/common.sh" #rest-ignore
   $ cat >> $HGRCPATH << EOF
-  > [experimental]
-  > evolution=all
   > [extensions]
-  > evolve=
+  > evolve =
+  > rebase =
+  > topic =
   > EOF
 
   $ hg init server
@@ -20,7 +20,7 @@ This Mercurial configuration example is
 
   $ cat >> .hg/hgrc << EOF
   > [ui]
-  > user= Shopping Master
+  > user = Shopping Master
   > EOF
 
   $ cat >> shopping << EOF
@@ -43,7 +43,7 @@ This Mercurial configuration example is
   $ cd client
   $ cat >> .hg/hgrc << EOF
   > [ui]
-  > user= Tutorial User
+  > user = Tutorial User
   > EOF
 #if docgraph-ext
   $ . "$TESTDIR/testlib/docgraph_setup.sh" #rest-ignore
@@ -100,7 +100,7 @@ within a topic. Creating a new topic is
   marked working directory as topic: food
 
 Much like a named branch, our topic is active but it does not contain any
-changeset yet:
+changesets yet:
 
   $ hg topics
    * food (0 changesets)
@@ -147,7 +147,7 @@ Our next commit will be part of the acti
 
   $ cat >> shopping << EOF
   > Egg
-  > Suggar
+  > Sugar
   > Vinegar
   > Oil
   > EOF
@@ -157,7 +157,7 @@ Our next commit will be part of the acti
   (see 'hg help topics' for more information)
 
   $ hg log --graph --rev 'topic("food")'
-  @  changeset:   1:13900241408b
+  @  changeset:   1:9e90e00c084b
   |  tag:         tip
   ~  topic:       food
      user:        test
@@ -198,14 +198,14 @@ And future commits will be part of that
   $ hg commit -m "adding fruits"
 
   $ hg log --graph --rev 'topic("food")'
-  @  changeset:   2:287de11b401f
+  @  changeset:   2:a25aaa6b9385
   |  tag:         tip
   |  topic:       food
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding fruits
   |
-  o  changeset:   1:13900241408b
+  o  changeset:   1:9e90e00c084b
   |  topic:       food
   ~  user:        test
      date:        Thu Jan 01 00:00:00 1970 +0000
@@ -268,14 +268,14 @@ Note that ``default`` (name of the branc
 changeset of default without a topic:
 
   $ hg log --graph
-  o  changeset:   2:287de11b401f
+  o  changeset:   2:a25aaa6b9385
   |  tag:         tip
   |  topic:       food
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding fruits
   |
-  o  changeset:   1:13900241408b
+  o  changeset:   1:9e90e00c084b
   |  topic:       food
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
@@ -395,13 +395,13 @@ the latest update from the main server:
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     Adding clothes
   |
-  | o  changeset:   2:287de11b401f
+  | o  changeset:   2:a25aaa6b9385
   | |  topic:       food
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     adding fruits
   | |
-  | @  changeset:   1:13900241408b
+  | @  changeset:   1:9e90e00c084b
   |/   topic:       food
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
@@ -488,21 +488,21 @@ But the topic will see that branch head
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
   $ hg rebase
-  rebasing 1:13900241408b food "adding condiments"
+  rebasing 1:9e90e00c084b food "adding condiments"
   merging shopping
   switching to topic food
-  rebasing 2:287de11b401f food "adding fruits"
+  rebasing 2:a25aaa6b9385 food "adding fruits"
   merging shopping
 
   $ hg log --graph
-  @  changeset:   5:2d50db8b5b4c
+  @  changeset:   5:fec062fcfcfa
   |  tag:         tip
   |  topic:       food
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding fruits
   |
-  o  changeset:   4:4011b46eeb33
+  o  changeset:   4:d3a1ea2a0337
   |  topic:       food
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
@@ -580,9 +580,9 @@ But the topic will see that branch head
 There exists a template keyword named "topic" which can be used
 
   $ hg log -GT "{rev}:{node|short} {topic}\n {desc}"
-  @  5:2d50db8b5b4c food
+  @  5:fec062fcfcfa food
   |   adding fruits
-  o  4:4011b46eeb33 food
+  o  4:d3a1ea2a0337 food
   |   adding condiments
   o  3:6104862e8b84
   |   Adding clothes
@@ -618,13 +618,13 @@ note that it is now devoid of any commit
   s0^ adding fruits (base current)
 
   $ hg log --graph
-  @  changeset:   5:2d50db8b5b4c
+  @  changeset:   5:fec062fcfcfa
   |  tag:         tip
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding fruits
   |
-  o  changeset:   4:4011b46eeb33
+  o  changeset:   4:d3a1ea2a0337
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding condiments
@@ -713,7 +713,7 @@ From there, the topic has been completel
 Keep working within topics
 ==========================
 
-Making sure all your new local commit are made within a topic will help you
+Making sure all your new local commits are made within a topic will help you
 organize your work. It is possible to ensure this through the Mercurial
 configuration.
 
@@ -724,10 +724,10 @@ For this tutorial, we'll add the config
   > topic-mode = enforce
   > EOF
 
-You can also use `hg config --edit` to update your mercurial configuration.
+You can also use `hg config --edit` to update your Mercurial configuration.
 
 
-Once enforcement is turned on. New local commit will be denied if no topic is active.
+Once enforcement is turned on, new local commits will be denied if no topic is active.
 
   $ echo sickle >> shopping
   $ hg commit -m 'Adding sickle'
@@ -764,7 +764,7 @@ tools to the shopping list within a new
   $ echo drill >> shopping
   $ hg commit -m 'Adding drill'
 
-But we are not sure we will actually go to the hardware store, so in the
+But we are not sure if we will actually go to the hardware store, so in the
 meantime, we want to extend the list with drinks. We go back to the official
 default branch and start a new topic:
 
@@ -815,7 +815,7 @@ between them will be attempted by defaul
   nothing to rebase
   [1]
 
-We simulate independant contributions to the repo with this
+We simulate independent contributions to the repo with this
 activity:
 
   $ cd ../server
@@ -832,7 +832,7 @@ activity:
   $ hg commit -m 'add a pair of shoes'
   $ cd ../client
 
-Let's discover what other people did contribute:
+Let's discover what other people have contributed:
 
   $ hg pull
   pulling from $TESTTMP/server (glob)
@@ -841,62 +841,62 @@ Let's discover what other people did con
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 1 files (+1 heads)
-  new changesets f2d6cacc6115:fbff9bc37a43
+  new changesets bbfb218049cd:033bfcc0ecb0
   (run 'hg heads' to see heads)
 
 There are new changes! We can simply use ``hg rebase`` to update our
 changeset on top of the latest:
 
   $ hg log -G
-  o  changeset:   12:fbff9bc37a43
+  o  changeset:   12:033bfcc0ecb0
   |  tag:         tip
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     add a pair of shoes
   |
-  o  changeset:   11:f2d6cacc6115
-  |  parent:      5:2d50db8b5b4c
+  o  changeset:   11:bbfb218049cd
+  |  parent:      5:fec062fcfcfa
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     add a coat
   |
-  | o  changeset:   10:70dfa201ed73
+  | o  changeset:   10:0b8a99ba9213
   | |  topic:       drinks
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     Adding orange juice
   | |
-  | o  changeset:   9:8dfa45bd5e0c
+  | o  changeset:   9:213e97c6cd8a
   |/   topic:       drinks
-  |    parent:      5:2d50db8b5b4c
+  |    parent:      5:fec062fcfcfa
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    summary:     Adding apple juice
   |
-  | @  changeset:   8:34255b455dac
+  | @  changeset:   8:9ef4e4f40a79
   | |  topic:       tools
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     Adding drill
   | |
-  | o  changeset:   7:cffff85af537
+  | o  changeset:   7:c1d9846a234f
   | |  topic:       tools
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     Adding saw
   | |
-  | o  changeset:   6:183984ef46d1
+  | o  changeset:   6:6d6f38ff45f0
   |/   topic:       tools
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    summary:     Adding hammer
   |
-  o  changeset:   5:2d50db8b5b4c
+  o  changeset:   5:fec062fcfcfa
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding fruits
   |
-  o  changeset:   4:4011b46eeb33
+  o  changeset:   4:d3a1ea2a0337
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding condiments
@@ -1055,49 +1055,49 @@ changeset on top of the latest:
 #endif
 
   $ hg rebase
-  rebasing 6:183984ef46d1 tools "Adding hammer"
+  rebasing 6:6d6f38ff45f0 tools "Adding hammer"
   merging shopping
   switching to topic tools
-  rebasing 7:cffff85af537 tools "Adding saw"
+  rebasing 7:c1d9846a234f tools "Adding saw"
   merging shopping
-  rebasing 8:34255b455dac tools "Adding drill"
+  rebasing 8:9ef4e4f40a79 tools "Adding drill"
   merging shopping
 
-But what about the other topic? You can use 'hg topics --verbose' to see
+But what about the other topic? You can use ``hg topics --verbose`` to see
 information about all the topics:
 
   $ hg topics --verbose
      drinks (on branch: default, 2 changesets, 2 behind)
    * tools  (on branch: default, 3 changesets)
 
-The "2 behind" is telling you that there are 2 new changesets over the base of the topic.
+The "2 behind" is telling you that there are 2 new changesets on top of the base of the topic.
 
 Pushing that topic would create a new head, and therefore will be prevented:
 
   $ hg push --rev drinks
   pushing to $TESTTMP/server (glob)
   searching for changes
-  abort: push creates new remote head 70dfa201ed73
+  abort: push creates new remote head 0b8a99ba9213
   (merge or see 'hg help push' for details about pushing new heads)
   [20]
 
 
 Even after a rebase, pushing all active topics at the same time would publish
-them to the default branch, and then mercurial would complain about the
+them to the default branch, and then Mercurial would complain about the
 multiple *public* heads it would create on that branch:
 
   $ hg rebase -b drinks
-  rebasing 9:8dfa45bd5e0c drinks "Adding apple juice"
+  rebasing 9:213e97c6cd8a drinks "Adding apple juice"
   merging shopping
   switching to topic drinks
-  rebasing 10:70dfa201ed73 drinks "Adding orange juice"
+  rebasing 10:0b8a99ba9213 drinks "Adding orange juice"
   merging shopping
   switching to topic tools
 
   $ hg push
   pushing to $TESTTMP/server (glob)
   searching for changes
-  abort: push creates new remote head 4cd7c1591a67
+  abort: push creates new remote head 56656c6d1153
   (merge or see 'hg help push' for details about pushing new heads)
   [20]
 
@@ -1113,7 +1113,7 @@ branch head as we just saw in the previo
   added 2 changesets with 2 changes to 1 files
   2 new obsolescence markers
 
-The published topic has now faded out, and the other is now marked as
+The published topic has now faded out, and the other is now marked as being
 "behind":
 
   $ hg topics --verbose
@@ -1133,7 +1133,7 @@ Working Within Your Stack
 Navigating within your stack
 ----------------------------
 
-As we saw before `stack` displays changesets on your current topic in a clean way:
+As we saw before ``stack`` displays changesets on your current topic in a clean way:
 
   $ hg topics --verbose
    * tools (on branch: default, 3 changesets, 2 behind)
@@ -1146,9 +1146,9 @@ As we saw before `stack` displays change
   s1: Adding hammer
   s0^ add a pair of shoes (base)
 
-You can navigate in your current stack with `previous` and `next`.
+You can navigate in your current stack with ``previous`` and ``next``.
 
-`previous` will bring you back to the parent of the topic head.
+``previous`` will bring you back to the parent of the topic head.
 
   $ hg previous
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -1162,7 +1162,7 @@ You can navigate in your current stack w
   s1: Adding hammer
   s0^ add a pair of shoes (base)
 
-`next` will move you forward to the topic head.
+``next`` will move you forward to the topic head.
 
   $ hg next
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -1176,7 +1176,7 @@ You can navigate in your current stack w
   s1: Adding hammer
   s0^ add a pair of shoes (base)
 
-You can also directly jump to a changeset within your stack with the revset `t#`.
+You can also directly jump to a changeset within your stack with the revset ``s<number>``.
 
   $ hg update s1
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -1209,47 +1209,47 @@ Understanding the current situation with
 it shows too many things:
 
   $ hg log -G -r "s0::"
-  @  changeset:   18:b7509bd417f8
+  @  changeset:   18:2c1a47a5c075
   |  tag:         tip
   |  topic:       tools
-  |  parent:      12:fbff9bc37a43
+  |  parent:      12:033bfcc0ecb0
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     Adding hammer to the shopping list
   |
-  | o  changeset:   17:4cd7c1591a67
+  | o  changeset:   17:9dc8cec494f3
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     Adding orange juice
   | |
-  | o  changeset:   16:20759cb47ff8
-  |/   parent:      12:fbff9bc37a43
+  | o  changeset:   16:9dfd6068e8e7
+  |/   parent:      12:033bfcc0ecb0
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    summary:     Adding apple juice
   |
-  | *  changeset:   15:bb1e6254f532
+  | *  changeset:   15:56656c6d1153
   | |  topic:       tools
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  instability: orphan
   | |  summary:     Adding drill
   | |
-  | *  changeset:   14:d4f97f32f8a1
+  | *  changeset:   14:a0ec1a6dcdce
   | |  topic:       tools
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  instability: orphan
   | |  summary:     Adding saw
   | |
-  | x  changeset:   13:a8ab3599d53d
+  | x  changeset:   13:dcb888ba1623
   |/   topic:       tools
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    reworded using amend as 18:b7509bd417f8
+  |    obsolete:    reworded using amend as 18:2c1a47a5c075
   |    summary:     Adding hammer
   |
-  o  changeset:   12:fbff9bc37a43
+  o  changeset:   12:033bfcc0ecb0
   |  user:        test
   ~  date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     add a pair of shoes
@@ -1364,14 +1364,14 @@ Fortunately stack shows you a better vis
   s1@ Adding hammer to the shopping list (current)
   s0^ add a pair of shoes (base)
 
-It's easy to stabilize the situation, `next` has an `--evolve` option.  It will
-do the necessary relocation of `s2` and `s3` over the new `s1` without having
-to do that rebase by hand.:
+It's easy to stabilize the situation, ``next`` has an ``--evolve`` option
+(turned on by default nowadays). It will do the necessary relocation of `s2`
+and `s3` over the new `s1` without having to do that rebase by hand:
 
   $ hg next --evolve
   move:[s2] Adding saw
   atop:[s1] Adding hammer to the shopping list
-  working directory is now at d5c51ee5762a
+  working directory is now at 7537e3a3cbca
 
   $ hg stack
   ### topic: tools
@@ -1386,7 +1386,7 @@ One more to go:
   $ hg next --evolve
   move:[s3] Adding drill
   atop:[s2] Adding saw
-  working directory is now at bae3758e46bf
+  working directory is now at 9d65331e0dc1
 
   $ hg stack
   ### topic: tools
@@ -1396,41 +1396,41 @@ One more to go:
   s1: Adding hammer to the shopping list
   s0^ add a pair of shoes (base)
 
-Let's take a look at `hg log` once again:
+Let's take a look at ``hg log`` once again:
 
   $ hg log -G -r "s0::"
-  @  changeset:   20:bae3758e46bf
+  @  changeset:   20:9d65331e0dc1
   |  tag:         tip
   |  topic:       tools
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     Adding drill
   |
-  o  changeset:   19:d5c51ee5762a
+  o  changeset:   19:7537e3a3cbca
   |  topic:       tools
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     Adding saw
   |
-  o  changeset:   18:b7509bd417f8
+  o  changeset:   18:2c1a47a5c075
   |  topic:       tools
-  |  parent:      12:fbff9bc37a43
+  |  parent:      12:033bfcc0ecb0
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     Adding hammer to the shopping list
   |
-  | o  changeset:   17:4cd7c1591a67
+  | o  changeset:   17:9dc8cec494f3
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     Adding orange juice
   | |
-  | o  changeset:   16:20759cb47ff8
-  |/   parent:      12:fbff9bc37a43
+  | o  changeset:   16:9dfd6068e8e7
+  |/   parent:      12:033bfcc0ecb0
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    summary:     Adding apple juice
   |
-  o  changeset:   12:fbff9bc37a43
+  o  changeset:   12:033bfcc0ecb0
   |  user:        test
   ~  date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     add a pair of shoes
@@ -1548,61 +1548,61 @@ destination if the topic has two heads.
 completely linear history so it's what we will do.
 
   $ hg log -G
-  @  changeset:   21:f936c6da9d61
+  @  changeset:   21:69ad92f8ff49
   |  tag:         tip
   |  topic:       tools
-  |  parent:      18:b7509bd417f8
+  |  parent:      18:2c1a47a5c075
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     Adding nails
   |
-  | o  changeset:   20:bae3758e46bf
+  | o  changeset:   20:9d65331e0dc1
   | |  topic:       tools
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     Adding drill
   | |
-  | o  changeset:   19:d5c51ee5762a
+  | o  changeset:   19:7537e3a3cbca
   |/   topic:       tools
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    summary:     Adding saw
   |
-  o  changeset:   18:b7509bd417f8
+  o  changeset:   18:2c1a47a5c075
   |  topic:       tools
-  |  parent:      12:fbff9bc37a43
+  |  parent:      12:033bfcc0ecb0
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     Adding hammer to the shopping list
   |
-  | o  changeset:   17:4cd7c1591a67
+  | o  changeset:   17:9dc8cec494f3
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     Adding orange juice
   | |
-  | o  changeset:   16:20759cb47ff8
-  |/   parent:      12:fbff9bc37a43
+  | o  changeset:   16:9dfd6068e8e7
+  |/   parent:      12:033bfcc0ecb0
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    summary:     Adding apple juice
   |
-  o  changeset:   12:fbff9bc37a43
+  o  changeset:   12:033bfcc0ecb0
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     add a pair of shoes
   |
-  o  changeset:   11:f2d6cacc6115
-  |  parent:      5:2d50db8b5b4c
+  o  changeset:   11:bbfb218049cd
+  |  parent:      5:fec062fcfcfa
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     add a coat
   |
-  o  changeset:   5:2d50db8b5b4c
+  o  changeset:   5:fec062fcfcfa
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding fruits
   |
-  o  changeset:   4:4011b46eeb33
+  o  changeset:   4:d3a1ea2a0337
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding condiments
@@ -1777,9 +1777,9 @@ completely linear history so it's what w
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
   $ hg rebase
-  rebasing 19:d5c51ee5762a tools "Adding saw"
+  rebasing 19:7537e3a3cbca tools "Adding saw"
   merging shopping
-  rebasing 20:bae3758e46bf tools "Adding drill"
+  rebasing 20:9d65331e0dc1 tools "Adding drill"
   merging shopping
 
   $ hg stack
@@ -1832,7 +1832,7 @@ We can now share these draft changesets:
   8 new obsolescence markers
 
 Pushing the new topic branch to a non-publishing server did not require
---force. As long as new heads are on their own topic, Mercurial will not
+``--force``. As long as new heads are on their own topic, Mercurial will not
 complain about them.
 
 From another client, we will get them with their topic:
@@ -1847,7 +1847,7 @@ From another client, we will get them wi
   adding file changes
   added 4 changesets with 4 changes to 1 files (+1 heads)
   8 new obsolescence markers
-  new changesets b7509bd417f8:2d084ac00115 (4 drafts)
+  new changesets 2c1a47a5c075:bbb9e269a01a (4 drafts)
   (run 'hg heads' to see heads)
 
   $ hg topics --verbose
@@ -1891,7 +1891,7 @@ And retrieve them from the first client:
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  new changesets 0d409663a1fd (1 drafts)
+  new changesets 71d37f5c73ed (1 drafts)
   (run 'hg update' to get a working copy)
 
   $ hg update
diff -pruN 11.1.3-1/docs/tutorials/tutorial.t 11.1.9-1/docs/tutorials/tutorial.t
--- 11.1.3-1/docs/tutorials/tutorial.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/docs/tutorials/tutorial.t	2025-07-25 16:21:02.000000000 +0000
@@ -1,3 +1,6 @@
+===============
+Evolve Tutorial
+===============
 
 Initial setup
 -------------
@@ -99,11 +102,11 @@ Its first version is shared with the out
   adding file changes
   added 1 changesets with 1 changes to 1 files
 
-Later I add additional item to my list
+Later I add additional items to my list
 
   $ cat >> shopping << EOF
   > Egg
-  > Suggar
+  > Sugar
   > Vinegar
   > Oil
   > EOF
@@ -115,12 +118,12 @@ Later I add additional item to my list
   > EOF
   $ hg commit -m "adding fruit"
 
-This history is very linear
+The history is completely linear so far
 
   $ hg log -G
-  @  d85de4546133 (draft): adding fruit
+  @  4296f0622469 (draft): adding fruit
   |
-  o  4d5dc8187023 (draft): adding condiment
+  o  63ae8c44f4b6 (draft): adding condiment
   |
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
@@ -170,22 +173,22 @@ This history is very linear
       }
 #endif
 
-But a typo was made in Babanas!
+But a typo was made in Bananas!
 
   $ hg export tip
   # HG changeset patch
   # User test
   # Date 0 0
   #      Thu Jan 01 00:00:00 1970 +0000
-  # Node ID d85de4546133030c82d257bbcdd9b1b416d0c31c
-  # Parent  4d5dc81870237d492284826e21840b2ca00e26d1
+  # Node ID 4296f0622469c1527d5dc020cf72bd7732c44c64
+  # Parent  63ae8c44f4b6274d5580b4eea41a87623301c3e9
   adding fruit
   
   diff --git a/shopping b/shopping
   --- a/shopping
   +++ b/shopping
   @@ -9,3 +9,6 @@
-   Suggar
+   Sugar
    Vinegar
    Oil
   +Bananos
@@ -193,12 +196,12 @@ But a typo was made in Babanas!
   +Apple
 
 The faulty changeset is in the "draft" phase because it has not been exchanged with
-the outside. The first one has been exchanged and is "public" (immutable).
+the outside yet. The first one has been exchanged and is "public" (immutable).
 
   $ hg log -G
-  @  d85de4546133 (draft): adding fruit
+  @  4296f0622469 (draft): adding fruit
   |
-  o  4d5dc8187023 (draft): adding condiment
+  o  63ae8c44f4b6 (draft): adding condiment
   |
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
@@ -249,7 +252,7 @@ the outside. The first one has been exch
       }
 #endif
 
-Hopefully. I can use `hg commit --amend` to rewrite my faulty changeset!
+Luckily, I can use `hg commit --amend` to rewrite my faulty changeset!
 
   $ sed -i'' -e s/Bananos/Banana/ shopping
   $ hg diff
@@ -257,7 +260,7 @@ Hopefully. I can use `hg commit --amend`
   --- a/shopping
   +++ b/shopping
   @@ -9,6 +9,6 @@
-   Suggar
+   Sugar
    Vinegar
    Oil
   -Bananos
@@ -266,12 +269,12 @@ Hopefully. I can use `hg commit --amend`
    Apple
   $ hg commit --amend
 
-A new changeset with the right diff replace the wrong one.
+A new changeset with the correct changes replaces the old one.
 
   $ hg log -G
-  @  9d0363b81950 (draft): adding fruit
+  @  6445b365ad1c (draft): adding fruit
   |
-  o  4d5dc8187023 (draft): adding condiment
+  o  63ae8c44f4b6 (draft): adding condiment
   |
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
@@ -326,15 +329,15 @@ A new changeset with the right diff repl
   # User test
   # Date 0 0
   #      Thu Jan 01 00:00:00 1970 +0000
-  # Node ID 9d0363b81950646bc6ad1ec5de8b8197ea586541
-  # Parent  4d5dc81870237d492284826e21840b2ca00e26d1
+  # Node ID 6445b365ad1c4905e7a120e45242d9f4b51ec48f
+  # Parent  63ae8c44f4b6274d5580b4eea41a87623301c3e9
   adding fruit
   
   diff --git a/shopping b/shopping
   --- a/shopping
   +++ b/shopping
   @@ -9,3 +9,6 @@
-   Suggar
+   Sugar
    Vinegar
    Oil
   +Banana
@@ -344,7 +347,7 @@ A new changeset with the right diff repl
 Getting rid of branchy history
 ----------------------------------
 
-While I was working on my list. Someone made a change remotely.
+While I was working on my list, someone made a change remotely.
 
   $ cd ../remote
   $ hg up -q
@@ -369,9 +372,9 @@ I now have a new head. Note that this re
   $ hg log -G
   o  9ca060c80d74 (public): SPAM
   |
-  | @  9d0363b81950 (draft): adding fruit
+  | @  6445b365ad1c (draft): adding fruit
   | |
-  | o  4d5dc8187023 (draft): adding condiment
+  | o  63ae8c44f4b6 (draft): adding condiment
   |/
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
@@ -437,19 +440,19 @@ I now have a new head. Note that this re
 Instead of merging my head with the new one. I'm going to rebase my work
 
   $ hg diff
-  $ hg rebase --dest 9ca060c80d74 --source 4d5dc8187023
-  rebasing 1:4d5dc8187023 "adding condiment"
+  $ hg rebase --dest 9ca060c80d74 --source 63ae8c44f4b6
+  rebasing 1:63ae8c44f4b6 "adding condiment"
   merging shopping
-  rebasing 3:9d0363b81950 "adding fruit"
+  rebasing 3:6445b365ad1c "adding fruit"
   merging shopping
 
 
 My local work is now rebased on the remote one.
 
   $ hg log -G
-  @  41aff6a42b75 (draft): adding fruit
+  @  d300c8f961ce (draft): adding fruit
   |
-  o  dfd3a2d7691e (draft): adding condiment
+  o  723e5a43d6d9 (draft): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -526,31 +529,31 @@ I add new items to my list.
   > EOF
   $ hg ci -m 'transport'
   $ hg log -G
-  @  1125e39fbf21 (draft): transport
+  @  7f938a07ecb2 (draft): transport
   |
-  o  41aff6a42b75 (draft): adding fruit
+  o  d300c8f961ce (draft): adding fruit
   |
-  o  dfd3a2d7691e (draft): adding condiment
+  o  723e5a43d6d9 (draft): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-I have a new commit but I realize that don't want it. (Transport shop list does
-not fit well in my standard shopping list)
+I have a new commit but I realize that don't want it. (Transport shopping list
+does not fit well in my standard shopping list)
 
   $ hg prune . # "." is for working directory parent
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  working directory is now at 41aff6a42b75
+  working directory is now at d300c8f961ce
   1 changesets pruned
 
 The silly changeset is gone.
 
   $ hg log -G
-  @  41aff6a42b75 (draft): adding fruit
+  @  d300c8f961ce (draft): adding fruit
   |
-  o  dfd3a2d7691e (draft): adding condiment
+  o  723e5a43d6d9 (draft): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -629,18 +632,18 @@ We create two changesets.
   > Towel
   > Soap
   > EOF
-  $ hg ci -m 'bathroom stuff' -q # XXX remove the -q
+  $ hg ci -m 'bathroom stuff'
 
   $ sed -i'' -e 's/Spam/Spam Spam Spam/g' shopping
   $ hg ci -m 'SPAM SPAM'
   $ hg log -G
-  @  fac207dec9f5 (draft): SPAM SPAM
+  @  1c877d31b53f (draft): SPAM SPAM
   |
-  o  10b8aeaa8cc8 (draft): bathroom stuff
+  o  d1928babc208 (draft): bathroom stuff
   |
-  o  41aff6a42b75 (draft): adding fruit
+  o  d300c8f961ce (draft): adding fruit
   |
-  o  dfd3a2d7691e (draft): adding condiment
+  o  723e5a43d6d9 (draft): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -649,27 +652,27 @@ We create two changesets.
 
 .. note:: We can't amend changeset 7e82d3f3c2cb or 9ca060c80d74 as they are immutable.
 
- I now want to push to remote all my changes except the bathroom one, which I'm
- not totally happy with yet. To be able to push "SPAM SPAM" I need a version of
- "SPAM SPAM" which is not a child of "bathroom stuff"
+I now want to push to remote all my changes except the bathroom one, which I'm
+not totally happy with yet. To be able to push "SPAM SPAM" I need a version of
+"SPAM SPAM" which is not a child of "bathroom stuff".
 
-You can use the 'grab' alias for that.
+You can use the 'grab' command for that.
 
-.. note: grab is an alias for `hg rebase --dest . --rev <target>; hg up <there>`
+.. note:: `grab` is an alias for `hg rebase --dest . --rev <target>; hg up <result>`
 
-  $ hg up 'p1(10b8aeaa8cc8)' # going on "bathroom stuff" parent
+  $ hg up 'p1(d1928babc208)' # going on "bathroom stuff" parent
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg pick fac207dec9f5 # moving "SPAM SPAM" to the working directory parent
-  picking 9:fac207dec9f5 "SPAM SPAM"
+  $ hg pick 1c877d31b53f # moving "SPAM SPAM" to the working directory parent
+  picking 9:1c877d31b53f "SPAM SPAM"
   merging shopping
   $ hg log -G
-  @  57e9caedbcb8 (draft): SPAM SPAM
+  @  501b33037995 (draft): SPAM SPAM
   |
-  | o  10b8aeaa8cc8 (draft): bathroom stuff
+  | o  d1928babc208 (draft): bathroom stuff
   |/
-  o  41aff6a42b75 (draft): adding fruit
+  o  d300c8f961ce (draft): adding fruit
   |
-  o  dfd3a2d7691e (draft): adding condiment
+  o  723e5a43d6d9 (draft): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -758,7 +761,7 @@ You can use the 'grab' alias for that.
       }
 #endif
 
-We have a new SPAM SPAM version without the bathroom stuff
+We have a new version of "SPAM SPAM" without the bathroom stuff
 
   $ grep Spam shopping  # enough spam
   Spam Spam Spam Spam Spam Spam Spam Spam Spam
@@ -769,8 +772,8 @@ We have a new SPAM SPAM version without
   # User test
   # Date 0 0
   #      Thu Jan 01 00:00:00 1970 +0000
-  # Node ID 57e9caedbcb8575a01c128db9d1bcbd624ef2115
-  # Parent  41aff6a42b7578ec7ec3cb2041633f1ca43cca96
+  # Node ID 501b330379955b6bf194dc99504a477b1f2d3f89
+  # Parent  d300c8f961ceefede93601dbe478c701e2ff5995
   SPAM SPAM
   
   diff --git a/shopping b/shopping
@@ -783,10 +786,10 @@ We have a new SPAM SPAM version without
    Albatross
    Rat (rather a lot)
 
-To make sure I do not push unready changeset by mistake I set the "bathroom
-stuff" changeset in the secret phase.
+To make sure I do not push unfinished changeset by mistake I move the "bathroom
+stuff" changeset to the secret phase.
 
-  $ hg phase --force --secret 10b8aeaa8cc8
+  $ hg phase --force --secret d1928babc208
 
 we can now push our change:
 
@@ -799,20 +802,20 @@ we can now push our change:
   added 3 changesets with 3 changes to 1 files
   5 new obsolescence markers
 
-for simplicity sake we get the bathroom change in line again
+for simplicity's sake we get the bathroom change in line again
 
-  $ hg pick 10b8aeaa8cc8
-  picking 8:10b8aeaa8cc8 "bathroom stuff"
+  $ hg pick d1928babc208
+  picking 8:d1928babc208 "bathroom stuff"
   merging shopping
   $ hg phase --draft .
   $ hg log -G
-  @  4710c0968793 (draft): bathroom stuff
+  @  39b19dc3d1e4 (draft): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -905,26 +908,27 @@ Splitting change
 ------------------
 
 This part is not written yet, but you can use either the `histedit` extension
-of the `uncommit` command to splitting a change.
+or the `uncommit` command to split a change.
 
+#if hg69
   $ hg help uncommit
   hg uncommit [OPTION]... [FILE]...
   
   move changes from parent revision to working directory
   
-      Changes to selected files in the checked out revision appear again as
-      uncommitted changed in the working directory. A new revision without the
-      selected changes is created, becomes the checked out revision, and
-      obsoletes the previous one.
-  
-      The --include option specifies patterns to uncommit. The --exclude option
-      specifies patterns to keep in the commit.
-  
-      The --rev argument let you change the commit file to a content of another
-      revision. It still does not change the content of your file in the working
-      directory.
+  Changes to selected files in the checked out revision appear again as
+  uncommitted changed in the working directory. A new revision without the
+  selected changes is created, becomes the checked out revision, and obsoletes
+  the previous one.
+  
+  The --include option specifies patterns to uncommit. The --exclude option
+  specifies patterns to keep in the commit.
+  
+  The --rev argument let you change the commit file to a content of another
+  revision. It still does not change the content of your file in the working
+  directory.
   
-      Return 0 if changed files are uncommitted.
+  Return 0 if changed files are uncommitted.
   
   options ([+] can be repeated):
   
@@ -942,6 +946,7 @@ of the `uncommit` command to splitting a
    -U --current-user        record the current user as committer
   
   (some details hidden, use --verbose to show complete help)
+#endif
 
 
 The edit command of histedit can be used to split changeset:
@@ -952,6 +957,7 @@ Collapsing change
 
 The tutorial part is not written yet but can use `hg fold`:
 
+#if hg69
   $ hg help fold
   hg fold [OPTION]... [-r] REV...
   
@@ -959,12 +965,12 @@ The tutorial part is not written yet but
   
   fold multiple revisions into a single one
   
-      With --from, folds all the revisions linearly between the given revisions
-      and the parent of the working directory.
+  With --from, folds all the revisions linearly between the given revisions and
+  the parent of the working directory.
   
-      With --exact, folds only the specified revisions while ignoring the parent
-      of the working directory. In this case, the given revisions must form a
-      linear unbroken chain.
+  With --exact, folds only the specified revisions while ignoring the parent of
+  the working directory. In this case, the given revisions must form a linear
+  unbroken chain.
   
   options ([+] can be repeated):
   
@@ -980,6 +986,7 @@ The tutorial part is not written yet but
    -U --current-user record the current user as committer
   
   (some details hidden, use --verbose to show complete help)
+#endif
 
 
 -----------------------
@@ -998,8 +1005,8 @@ behavior where exchanged changeset are a
   $ hg -R ../local/ showconfig phases
   [1]
 
-The localrepo does not have any specific configuration for `phases.publish`. It
-is ``true`` by default.
+The local repo does not have any specific configuration for `phases.publish`.
+It is ``true`` by default.
 
   $ hg pull local
   pulling from $TESTTMP/local (glob)
@@ -1009,16 +1016,16 @@ is ``true`` by default.
   adding file changes
   added 1 changesets with 1 changes to 1 files
   1 new obsolescence markers
-  new changesets 4710c0968793
+  new changesets 39b19dc3d1e4
   (run 'hg update' to get a working copy)
   $ hg log -G
-  o  4710c0968793 (public): bathroom stuff
+  o  39b19dc3d1e4 (public): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   @  9ca060c80d74 (public): SPAM
   |
@@ -1027,16 +1034,16 @@ is ``true`` by default.
 
 We do not want to publish the "bathroom changeset". Let's rollback the last transaction.
 
-.. Warning: Rollback is actually a dangerous kind of internal command that is deprecated and should not be exposed to user. Please forget you read about it until someone fix this tutorial.
+.. warning:: `rollback` is actually a dangerous kind of internal command that is deprecated and should not be exposed to user. Please forget you read about it until someone fix this tutorial.
 
   $ hg rollback
   repository tip rolled back to revision 4 (undo pull)
   $ hg log -G
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   @  9ca060c80d74 (public): SPAM
   |
@@ -1065,16 +1072,16 @@ I can now exchange mutable changeset bet
   adding file changes
   added 1 changesets with 1 changes to 1 files
   1 new obsolescence markers
-  new changesets 4710c0968793 (1 drafts)
+  new changesets 39b19dc3d1e4 (1 drafts)
   (run 'hg update' to get a working copy)
   $ hg log -G
-  o  4710c0968793 (draft): bathroom stuff
+  o  39b19dc3d1e4 (draft): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   @  9ca060c80d74 (public): SPAM
   |
@@ -1086,7 +1093,7 @@ Rebasing unstable change after pull
 
 Remotely someone add a new changeset on top of the mutable "bathroom" on.
 
-  $ hg up 4710c0968793 -q
+  $ hg up 39b19dc3d1e4 -q
   $ cat >> shopping << EOF
   > Giraffe
   > Rhino
@@ -1098,17 +1105,17 @@ Remotely someone add a new changeset on
 But at the same time, locally, this same "bathroom changeset" was updated.
 
   $ cd ../local
-  $ hg up 4710c0968793 -q
+  $ hg up 39b19dc3d1e4 -q
   $ sed -i'' -e 's/... More bathroom stuff to come/Bath Robe/' shopping
   $ hg commit --amend
   $ hg log -G
-  @  682004e81e71 (draft): bathroom stuff
+  @  5486682f4225 (draft): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -1207,24 +1214,24 @@ When we pull from remote again we get an
   adding file changes
   added 1 changesets with 1 changes to 1 files
   1 new orphan changesets
-  new changesets e4e4fa805d92 (1 drafts)
+  new changesets 0609f95eccab (1 drafts)
   (run 'hg update' to get a working copy)
 
 The new changeset "animal" is based on an old changeset of "bathroom". You can
 see both version showing up in the log.
 
   $ hg log -G
-  *  e4e4fa805d92 (draft): animals
+  *  0609f95eccab (draft): animals
   |
-  | @  682004e81e71 (draft): bathroom stuff
+  | @  5486682f4225 (draft): bathroom stuff
   | |
-  x |  4710c0968793 (draft): bathroom stuff
+  x |  39b19dc3d1e4 (draft): bathroom stuff
   |/
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -1342,10 +1349,10 @@ see both version showing up in the log.
       }
 #endif
 
-The older version 75954b8cd933 never ceased to exist in the local repo. It was
+The older version 39b19dc3d1e4 never ceased to exist in the local repo. It was
 just hidden and excluded from pull and push.
 
-.. note:: In hgview there is a nice dotted relation highlighting a44c85f957d3 as a new version of 75954b8cd933. this is not yet ported to ``hg log -G``.
+.. note:: In hgview there is a nice dotted relation highlighting 5486682f4225 as a new version of 39b19dc3d1e4. This is not yet ported to ``hg log -G``.
 
 There is now an **unstable** changeset in this history. Mercurial will refuse to
 share it with the outside:
@@ -1353,20 +1360,20 @@ share it with the outside:
   $ hg push other
   pushing to $TESTTMP/other (glob)
   searching for changes
-  abort: push includes orphan changeset: e4e4fa805d92!
+  abort: push includes orphan changeset: 0609f95eccab!
   (use 'hg evolve' to get a stable history or --force to ignore warnings)
   [255]
  
 
-To resolve this unstable state, you need to rebase bf1b0d202029 onto
-a44c85f957d3. The `hg evolve` command will do this for you.
+To resolve this unstable state, you need to rebase 0609f95eccab onto
+5486682f4225. The `hg evolve` command will do this for you.
 
 It has a --dry-run option to only suggest the next move.
 
   $ hg evolve --dry-run
   move:[13] animals
   atop:[12] bathroom stuff
-  hg rebase -r e4e4fa805d92 -d 682004e81e71
+  hg rebase -r 0609f95eccab -d 5486682f4225
 
 Let's do it
 
@@ -1378,15 +1385,15 @@ Let's do it
 The old version of bathroom is hidden again.
 
   $ hg log -G
-  o  2a2b36e14660 (draft): animals
+  o  3266db1117c9 (draft): animals
   |
-  @  682004e81e71 (draft): bathroom stuff
+  @  5486682f4225 (draft): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -1516,13 +1523,13 @@ changeset.
 Now let's see where we are, and update to the successor.
 
   $ hg parents
-  e4e4fa805d92 (draft): animals
-  working directory parent is obsolete! (e4e4fa805d92)
-  (use 'hg evolve' to update to its successor: 2a2b36e14660)
+  0609f95eccab (draft): animals
+  working directory parent is obsolete! (0609f95eccab)
+  (use 'hg evolve' to update to its successor: 3266db1117c9)
   $ hg evolve
   update:[8] animals
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  working directory is now at 2a2b36e14660
+  working directory is now at 3266db1117c9
 
 Relocating unstable change after prune
 ----------------------------------------------
@@ -1542,20 +1549,20 @@ I'm pulling its work locally.
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  new changesets fc41faf45288 (1 drafts)
+  new changesets fff8c3d068b6 (1 drafts)
   (run 'hg update' to get a working copy)
   $ hg log -G
-  o  fc41faf45288 (draft): SPAM SPAM SPAM
+  o  fff8c3d068b6 (draft): SPAM SPAM SPAM
   |
-  @  2a2b36e14660 (draft): animals
+  @  3266db1117c9 (draft): animals
   |
-  o  682004e81e71 (draft): bathroom stuff
+  o  5486682f4225 (draft): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -1670,9 +1677,9 @@ I'm pulling its work locally.
 
 In the mean time I noticed you can't buy animals in a super market and I prune the animal changeset:
 
-  $ hg prune 2a2b36e14660
+  $ hg prune 3266db1117c9
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  working directory is now at 682004e81e71
+  working directory is now at 5486682f4225
   1 changesets pruned
   1 new orphan changesets
 
@@ -1681,17 +1688,17 @@ The animals changeset is still displayed
 is neither dead or obsolete. My repository is in an unstable state again.
 
   $ hg log -G
-  *  fc41faf45288 (draft): SPAM SPAM SPAM
+  *  fff8c3d068b6 (draft): SPAM SPAM SPAM
   |
-  x  2a2b36e14660 (draft): animals
+  x  3266db1117c9 (draft): animals
   |
-  @  682004e81e71 (draft): bathroom stuff
+  @  5486682f4225 (draft): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -1805,7 +1812,7 @@ is neither dead or obsolete. My reposito
 #endif
 
   $ hg log -r "orphan()"
-  fc41faf45288 (draft): SPAM SPAM SPAM
+  fff8c3d068b6 (draft): SPAM SPAM SPAM
 
 #if docgraph-ext
   $ hg docgraph -r "orphan()" --sphinx-directive --rankdir LR #rest-ignore
@@ -1836,18 +1843,18 @@ changeset.
   move:[15] SPAM SPAM SPAM
   atop:[12] bathroom stuff
   merging shopping
-  working directory is now at e6cfcb672150
+  working directory is now at c33e56ec23a8
 
   $ hg log -G
-  @  e6cfcb672150 (draft): SPAM SPAM SPAM
+  @  c33e56ec23a8 (draft): SPAM SPAM SPAM
   |
-  o  682004e81e71 (draft): bathroom stuff
+  o  5486682f4225 (draft): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
diff -pruN 11.1.3-1/hg_evolve.egg-info/PKG-INFO 11.1.9-1/hg_evolve.egg-info/PKG-INFO
--- 11.1.3-1/hg_evolve.egg-info/PKG-INFO	1970-01-01 00:00:00.000000000 +0000
+++ 11.1.9-1/hg_evolve.egg-info/PKG-INFO	2025-07-25 16:21:08.000000000 +0000
@@ -0,0 +1,350 @@
+Metadata-Version: 2.4
+Name: hg-evolve
+Version: 11.1.9
+Summary: Flexible evolution of Mercurial history.
+Home-page: https://www.mercurial-scm.org/doc/evolution/
+Author: Pierre-Yves David
+Author-email: pierre-yves.david@ens-lyon.org
+Maintainer: Pierre-Yves David
+Maintainer-email: pierre-yves.david@ens-lyon.org
+License: GPLv2+
+Keywords: hg mercurial
+Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4
+Description-Content-Type: text/x-rst
+License-File: COPYING
+Dynamic: author
+Dynamic: author-email
+Dynamic: description
+Dynamic: description-content-type
+Dynamic: home-page
+Dynamic: keywords
+Dynamic: license
+Dynamic: license-file
+Dynamic: maintainer
+Dynamic: maintainer-email
+Dynamic: requires-python
+Dynamic: summary
+
+=============================
+Mutable History For Mercurial
+=============================
+
+Evolve Extension
+================
+
+This package supplies the evolve extension for Mercurial,
+
+**The full implementation of the changeset evolution concept is still in
+progress.**  Please subscribe to the `evolve-testers mailing list
+<https://www.mercurial-scm.org/mailman/listinfo/evolve-testers>`_ to stay up to
+date with changes.
+
+This extension:
+
+* enables the "`changeset evolution`_" feature of core Mercurial,
+
+* provides a set of commands to rewrite history in a distributed way,
+
+* issues various warning messages when "troubles" from changeset evolution
+  appear in your repository,
+
+* provides an ``hg evolve`` command to deal with such troubles,
+
+* improves performance of obsolescence marker exchange and discovery during
+  push and pull.
+
+.. _`changeset evolution`: https://wiki.mercurial-scm.org/ChangesetEvolution
+
+Documentation
+-------------
+
+We recommend reading the documentation first. An online version is available
+here:
+
+    https://www.mercurial-scm.org/doc/evolution/
+
+Source of the documentation can be found in ``docs/``.
+
+How to Install
+==============
+
+Using Pip
+---------
+
+You can install the latest released version using pip::
+
+    $ pip install --user hg-evolve
+
+Note: some distributions have adopted PEP 668 and made using ``pip install
+--user`` more difficult than it should be. One of the cleanest ways around this
+issue is to install both Mercurial and this extension in a separate virtual
+environment. If you don't want to manage the virtual environment manually, you
+can use Pipx.
+
+Using Pipx
+----------
+
+Its documentation explains that "pipx is made specifically for application
+installation", and the idea is that for every application it can create and
+maintain a separate virtual environment and make all executables available on a
+single path (e.g. ~/.local/bin/ on Linux, check ``pipx ensurepath``).
+
+To create a virtual environment for hg and install evolve::
+
+    $ pipx install mercurial
+    $ pipx inject mercurial hg-evolve
+    # or pipx runpip mercurial install hg-evolve
+
+Note: it's recommended to use ``inject`` command to install evolve, but
+sometimes ``runpip`` could be used. On some setups ``inject`` might require
+specifying the full path to the extension in the configuration file, while
+``runpip`` might not.
+
+Using Your Package Manager
+--------------------------
+
+Sometimes your distribution's package manager might have the newest (or recent
+enough) version of the extension. For example, both `Debian`_ and `Ubuntu`_
+currently have a package called ``mercurial-evolve``.  Similarly, other
+distributions might have it packaged, possibly under a slightly different name.
+Try searching your package manager's database or see `this Repology page`_.
+
+.. _`Debian`: https://packages.debian.org/search?keywords=mercurial-evolve&searchon=names&exact=1&suite=all&section=all
+.. _`Ubuntu`: https://packages.ubuntu.com/search?keywords=mercurial-evolve&searchon=names&exact=1&suite=all&section=all
+.. _`this Repology page`: https://repology.org/project/mercurial-evolve/related
+
+From Source
+-----------
+
+To obtain a local version from source::
+
+    $ hg clone https://repo.mercurial-scm.org/evolve
+
+There's no need to compile anything or run ``make``.
+
+This method keeps the extension in its own repo, and you can use it by
+specifying the full path to the ``hgext3rd/evolve/``.
+
+Alternatively, you can install it::
+
+    $ cd evolve
+    # optionally `hg update <target revision>`
+    $ pip install --user .
+
+This should avoid the need to specify the full path to the extension.
+
+Enabling the Extension
+----------------------
+
+After installing the extension, you need to enable it before you can use it.
+
+To do that, edit your hgrc::
+
+    $ hg config --edit # add these two lines:
+    [extensions]
+    evolve =
+
+If you didn't install the extension or Mercurial can't find it on one of the
+default paths, you need to specify the full path to ``hgext3rd/evolve/``::
+
+    [extensions]
+    evolve = ~/evolve/hgext3rd/evolve
+
+Similarly, if you want to enable topic extension, do this::
+
+    $ hg config --edit
+    [extensions]
+    topic =
+    # or
+    topic = ~/evolve/hgext3rd/topic
+
+Pitfalls
+--------
+
+If you get ``"failed to import extension evolve: No module named 'evolve'"``
+error, there are a couple of things to check:
+
+* make sure you gave pip/pipx the correct package name (it's ``hg-evolve``),
+
+* make sure evolve is installed for the same version of Python that you use for
+  running Mercurial (``hg debuginstall | grep Python``),
+
+* try specifying the full path to the ``hgext3rd/evolve/`` directory.
+
+Extension Purpose
+=================
+
+The goal of this extension is to provide an appropriate place for code and
+concepts related to `changeset evolution`_ to mature. In this extension we
+allow hackier code, unlocking quick experimentation and faster iterations.
+
+In addition, evolve extension supports a wide range of Mercurial versions,
+allowing us to reach a larger user base for feedback. The extension is not tied
+to the Mercurial release cycle and can release new features and bug fixes at a
+higher rate if necessary.
+
+Once a concept is deemed ready, its implementation is moved into core
+Mercurial. The maturation period helped us to get a clearer picture of what was
+needed. During the upstreaming process, we can use this clearer picture to
+clean up the code and upgrade it to an appropriate quality for core Mercurial.
+
+Python 3 Support
+================
+
+Mercurial announced official `support for Python 3`_ starting with its 5.2
+release. Since 9.3.0, evolve has official support for Python 3.6+.
+
+.. _`support for Python 3`: https://wiki.mercurial-scm.org/Python3
+
+Python 2 Support
+================
+
+Python 2 is supported by evolve. However, Mercurial 6.2 release dropped support
+for it, so evolve can work on Python 2 only on earlier versions.
+
+Debian packages that are built using Heptapod CI only install files for Python
+3, because they target current Debian stable.
+
+How to Contribute
+=================
+
+Discussion happens in #hg-evolve and #mercurial on libera_ IRC network.
+
+.. _libera: https://libera.chat/
+
+Bugs are to be reported on the Mercurial's bug tracker (component:
+`evolution`_).
+
+.. _evolution: https://bz.mercurial-scm.org/buglist.cgi?component=evolution&query_format=advanced&resolution=---
+
+The recommended way to submit a patch is to create a Merge Request on
+https://foss.heptapod.net/mercurial/evolve. To do so, create an account and
+request access. You'll then be able to create a topic-based merge request.
+
+Alternatively, you can use the patchbomb extension to send email to `mercurial
+devel <https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel>`_.
+Please make sure to use the evolve-ext flag when doing so. You can use a
+command like this::
+
+    $ hg email --to mercurial-devel@mercurial-scm.org --flag evolve-ext --rev '<your patches>'
+
+For guidelines on the patch description, see the `official Mercurial guideline`_.
+
+.. _`official Mercurial guideline`: https://wiki.mercurial-scm.org/ContributingChanges#Patch_descriptions
+
+Please don't forget to update and run the tests when you fix a bug or add a
+feature. To run the tests, you need a working copy of Mercurial, say in
+$HGSRC::
+
+    $ cd tests
+    $ python $HGSRC/tests/run-tests.py
+
+When certain blocks of code need to cope with API changes in core Mercurial,
+they should have comments in the ``hg <= x.y (commit hash)`` format. For
+example, if a function needs another code path because of changes introduced in
+02802fa87b74 that was first included in Mercurial 5.3, then the comment should
+be::
+
+    # hg <= 5.2 (02802fa87b74)
+
+See also tests/test-check-compat-strings.t.
+
+Branch policy
+-------------
+
+The evolve tests are highly impacted by changes in core Mercurial. To deal with
+this, we use named branches.
+
+There are two main branches: "stable" and "default". Tests on these branches
+are supposed to pass with the corresponding "default" and "stable" branch from
+core Mercurial. The documentation is built from the tip of stable.
+
+In addition, we have compatibility branches to check tests on older versions of
+Mercurial. They are the "mercurial-x.y" branches. They are used to apply
+expected test changes only, no code changes should happen there.
+
+Test output changes from a changeset in core should add the following line to
+their patch description::
+
+    CORE-TEST-OUTPUT-UPDATE: <changeset hash>
+
+Format-source config
+====================
+
+Format-source helps smooth out the pain of merging after auto-formatting.
+Follow the installation instructions at the `format-source`_ repo.
+
+.. _`format-source`: https://foss.heptapod.net/mercurial/format-source
+
+Then update your per-repo config file::
+
+    $ hg config --local --edit # add these lines:
+    [extensions]
+    formatsource =
+
+    [format-source]
+    byteify-strings = python3 ~/hg/contrib/byteify-strings.py --dictiter --treat-as-kwargs kwargs opts commitopts TROUBLES --allow-attr-methods
+    byteify-strings:mode.input = file
+    byteify-strings:mode.output = pipe
+
+Release Checklist
+=================
+
+* use contrib/merge-test-compat.sh to merge with the test compatibility
+  branches,
+
+* make sure the tests are happy on all supported versions,
+
+* make sure there is no code difference between the compatibility branches and
+  stable (no diff within hgext3rd/),
+
+* update the ``testedwith`` variable for all extensions (remove '.dev0'):
+
+  - hgext3rd/evolve/metadata.py
+  - hgext3rd/topic/__init__.py
+  - hgext3rd/pullbundle.py
+
+* make sure CHANGELOG is up-to-date,
+
+* add a date to the CHANGELOG entry for the target version,
+
+* update the ``__version__`` field of all relevant extensions:
+
+  - hgext3rd/evolve/metadata.py
+  - hgext3rd/topic/__init__.py
+  - hgext3rd/pullbundle.py (if touched)
+
+* create a new Debian changelog entry:
+
+  - debchange --newversion x.y.z-1 "new upstream release"
+  - debchange --release
+
+* sanity check install and sdist targets of setup.py:
+
+  - python setup.py install --home=$(mktemp -d)
+  - python setup.py sdist
+
+* tag the commit,
+
+* push and publish the tag,
+
+* upload the tarball to PyPI,
+
+* build .deb on Heptapod CI for the tagged commit,
+
+* make an announcement on evolve-testers@mercurial-scm.org and
+  mercurial@mercurial-scm.org,
+
+* bump versions of all extensions and add ``.dev0`` (see existing commits as an
+  example):
+
+  - hgext3rd/evolve/metadata.py
+  - hgext3rd/topic/__init__.py
+  - hgext3rd/pullbundle.py
+
+  Version bump rules:
+
+  - stable branch x.y.z+1.dev0
+  - default branch x.y+1.0.dev0
+
+* merge stable into default.
diff -pruN 11.1.3-1/hg_evolve.egg-info/SOURCES.txt 11.1.9-1/hg_evolve.egg-info/SOURCES.txt
--- 11.1.3-1/hg_evolve.egg-info/SOURCES.txt	1970-01-01 00:00:00.000000000 +0000
+++ 11.1.9-1/hg_evolve.egg-info/SOURCES.txt	2025-07-25 16:21:08.000000000 +0000
@@ -0,0 +1,399 @@
+CHANGELOG
+COPYING
+MANIFEST.in
+README.rst
+setup.cfg
+setup.py
+/builds/mercurial/evolve/hgext3rd/__init__.py
+/builds/mercurial/evolve/hgext3rd/pullbundle.py
+/builds/mercurial/evolve/hgext3rd/evolve/__init__.py
+/builds/mercurial/evolve/hgext3rd/evolve/cmdrewrite.py
+/builds/mercurial/evolve/hgext3rd/evolve/compat.py
+/builds/mercurial/evolve/hgext3rd/evolve/dagutil.py
+/builds/mercurial/evolve/hgext3rd/evolve/debugcmd.py
+/builds/mercurial/evolve/hgext3rd/evolve/depthcache.py
+/builds/mercurial/evolve/hgext3rd/evolve/evolvecmd.py
+/builds/mercurial/evolve/hgext3rd/evolve/exthelper.py
+/builds/mercurial/evolve/hgext3rd/evolve/firstmergecache.py
+/builds/mercurial/evolve/hgext3rd/evolve/genericcaches.py
+/builds/mercurial/evolve/hgext3rd/evolve/headchecking.py
+/builds/mercurial/evolve/hgext3rd/evolve/legacy.py
+/builds/mercurial/evolve/hgext3rd/evolve/metadata.py
+/builds/mercurial/evolve/hgext3rd/evolve/obscache.py
+/builds/mercurial/evolve/hgext3rd/evolve/obsdiscovery.py
+/builds/mercurial/evolve/hgext3rd/evolve/obsexchange.py
+/builds/mercurial/evolve/hgext3rd/evolve/obshashtree.py
+/builds/mercurial/evolve/hgext3rd/evolve/obshistory.py
+/builds/mercurial/evolve/hgext3rd/evolve/revset.py
+/builds/mercurial/evolve/hgext3rd/evolve/rewind.py
+/builds/mercurial/evolve/hgext3rd/evolve/rewriteutil.py
+/builds/mercurial/evolve/hgext3rd/evolve/safeguard.py
+/builds/mercurial/evolve/hgext3rd/evolve/stablerange.py
+/builds/mercurial/evolve/hgext3rd/evolve/stablerangecache.py
+/builds/mercurial/evolve/hgext3rd/evolve/stablesort.py
+/builds/mercurial/evolve/hgext3rd/evolve/state.py
+/builds/mercurial/evolve/hgext3rd/evolve/templatekw.py
+/builds/mercurial/evolve/hgext3rd/evolve/utility.py
+/builds/mercurial/evolve/hgext3rd/evolve/thirdparty/__init__.py
+/builds/mercurial/evolve/hgext3rd/evolve/thirdparty/cbor.py
+/builds/mercurial/evolve/hgext3rd/topic/__init__.py
+/builds/mercurial/evolve/hgext3rd/topic/common.py
+/builds/mercurial/evolve/hgext3rd/topic/compat.py
+/builds/mercurial/evolve/hgext3rd/topic/constants.py
+/builds/mercurial/evolve/hgext3rd/topic/destination.py
+/builds/mercurial/evolve/hgext3rd/topic/discovery.py
+/builds/mercurial/evolve/hgext3rd/topic/evolvebits.py
+/builds/mercurial/evolve/hgext3rd/topic/flow.py
+/builds/mercurial/evolve/hgext3rd/topic/randomname.py
+/builds/mercurial/evolve/hgext3rd/topic/revset.py
+/builds/mercurial/evolve/hgext3rd/topic/server.py
+/builds/mercurial/evolve/hgext3rd/topic/stack.py
+/builds/mercurial/evolve/hgext3rd/topic/topicmap.py
+docs/README
+docs/commands.rst
+docs/concepts.rst
+docs/conf.py
+docs/evolve-faq.rst
+docs/evolve-good-practice.rst
+docs/from-mq.rst
+docs/index.rst
+docs/known-doc-issues.rst
+docs/makefile
+docs/obs-terms.rst
+docs/sharing.rst
+docs/test2rst.py
+docs/troubles-handling.rst
+docs/user-guide.rst
+docs/figures/figure-sg01-ab.svg
+docs/figures/figure-sg02-b.svg
+docs/figures/figure-sg03.svg
+docs/figures/figure-sg04-a.svg
+docs/figures/figure-sg04-b.svg
+docs/figures/figure-sg05.svg
+docs/figures/figure-sg06.svg
+docs/figures/figure-sg07-a.svg
+docs/figures/figure-sg07-b.svg
+docs/figures/figure-sg08-a.svg
+docs/figures/figure-sg08-b.svg
+docs/figures/figure-sg09.svg
+docs/figures/figure-sg10.svg
+docs/figures/figure-ug01.svg
+docs/figures/figure-ug02.svg
+docs/figures/figure-ug03.svg
+docs/figures/figure-ug04.svg
+docs/figures/figure-ug05.svg
+docs/figures/figure-ug06.svg
+docs/figures/figure-ug07.svg
+docs/figures/figure-ug08.svg
+docs/figures/figure-ug09.svg
+docs/figures/figure-ug10.svg
+docs/figures/figure-ug11.svg
+docs/figures/figure-ug12.svg
+docs/figures/hgview-example.png
+docs/static/logo-evolve.svg
+docs/tutorial/README.rst
+docs/tutorial/compile.sh
+docs/tutorial/deploy.sh
+docs/tutorial/draft.md
+docs/tutorial/jquery.sticky-kit.js
+docs/tutorial/prepare.sh
+docs/tutorial/scripts.js
+docs/tutorial/slides.md
+docs/tutorial/standalone.html
+docs/tutorial/style.css
+docs/tutorial/test-training.t
+docs/tutorial/uikit.css
+docs/tutorial/uikit.js
+docs/tutorial/mypandocfilters/graphviz-file.py
+docs/tutorial/mypandocfilters/raw-file.py
+docs/tutorial/testlib/arguments_printer.py
+docs/tutorial/testlib/common.sh
+docs/tutorial/testlib/docgraph_setup.sh
+docs/tutorial/testlib/exchange-obsmarker-util.sh
+docs/tutorial/testlib/push-checkheads-util.sh
+docs/tutorial/testlib/pythonpath.sh
+docs/tutorial/testlib/topic_setup.sh
+docs/tutorials/topic-tutorial.t
+docs/tutorials/tutorial.t
+hg_evolve.egg-info/PKG-INFO
+hg_evolve.egg-info/SOURCES.txt
+hg_evolve.egg-info/dependency_links.txt
+hg_evolve.egg-info/top_level.txt
+hgext3rd/__init__.py
+hgext3rd/pullbundle.py
+hgext3rd/evolve/__init__.py
+hgext3rd/evolve/cmdrewrite.py
+hgext3rd/evolve/compat.py
+hgext3rd/evolve/dagutil.py
+hgext3rd/evolve/debugcmd.py
+hgext3rd/evolve/depthcache.py
+hgext3rd/evolve/evolvecmd.py
+hgext3rd/evolve/exthelper.py
+hgext3rd/evolve/firstmergecache.py
+hgext3rd/evolve/genericcaches.py
+hgext3rd/evolve/headchecking.py
+hgext3rd/evolve/metadata.py
+hgext3rd/evolve/obscache.py
+hgext3rd/evolve/obsdiscovery.py
+hgext3rd/evolve/obsexchange.py
+hgext3rd/evolve/obshashtree.py
+hgext3rd/evolve/obshistory.py
+hgext3rd/evolve/revset.py
+hgext3rd/evolve/rewind.py
+hgext3rd/evolve/rewriteutil.py
+hgext3rd/evolve/safeguard.py
+hgext3rd/evolve/stablerange.py
+hgext3rd/evolve/stablerangecache.py
+hgext3rd/evolve/stablesort.py
+hgext3rd/evolve/state.py
+hgext3rd/evolve/templatekw.py
+hgext3rd/evolve/utility.py
+hgext3rd/evolve/thirdparty/__init__.py
+hgext3rd/evolve/thirdparty/cbor.py
+hgext3rd/topic/README
+hgext3rd/topic/__init__.py
+hgext3rd/topic/common.py
+hgext3rd/topic/compat.py
+hgext3rd/topic/constants.py
+hgext3rd/topic/destination.py
+hgext3rd/topic/discovery.py
+hgext3rd/topic/evolvebits.py
+hgext3rd/topic/flow.py
+hgext3rd/topic/randomname.py
+hgext3rd/topic/revset.py
+hgext3rd/topic/server.py
+hgext3rd/topic/stack.py
+hgext3rd/topic/topicmap.py
+tests/fake-editor.sh
+tests/hghaveaddon.py
+tests/test-amend-merge.t
+tests/test-amend-patch.t
+tests/test-amend.t
+tests/test-cache-corruption.t
+tests/test-check-commit.t
+tests/test-check-compat-strings.t
+tests/test-check-debian.t
+tests/test-check-flake8.t
+tests/test-check-pyflakes.t
+tests/test-check-sdist.t
+tests/test-check-setup-manifest.t
+tests/test-check-tag.t
+tests/test-cmdserver.t
+tests/test-corrupt.t
+tests/test-discovery-hidden-common.t
+tests/test-discovery-obshashrange-cache.t
+tests/test-discovery-obshashrange.t
+tests/test-doctest.py
+tests/test-evolve-abort-orphan.t
+tests/test-evolve-abort-phasediv.t
+tests/test-evolve-content-divergent-basic.t
+tests/test-evolve-content-divergent-case-A1.t
+tests/test-evolve-content-divergent-case-A2.t
+tests/test-evolve-content-divergent-case-A3.t
+tests/test-evolve-content-divergent-case-A4.t
+tests/test-evolve-content-divergent-case-A5.t
+tests/test-evolve-content-divergent-case-B1.t
+tests/test-evolve-content-divergent-corner-cases.t
+tests/test-evolve-content-divergent-first-changeset.t
+tests/test-evolve-content-divergent-interrupted.t
+tests/test-evolve-content-divergent-meta.t
+tests/test-evolve-content-divergent-relocation.t
+tests/test-evolve-content-divergent-stack.t
+tests/test-evolve-content-divergent-user-independent-resolution.t
+tests/test-evolve-continue.t
+tests/test-evolve-cycles.t
+tests/test-evolve-effectflags.t
+tests/test-evolve-extras.t
+tests/test-evolve-inmemory.t
+tests/test-evolve-interrupted.t
+tests/test-evolve-issue5832.t
+tests/test-evolve-issue5881.t
+tests/test-evolve-issue5958.t
+tests/test-evolve-issue5966.t
+tests/test-evolve-issue5967.t
+tests/test-evolve-issue6097.t
+tests/test-evolve-issue6246.t
+tests/test-evolve-issue6648.t
+tests/test-evolve-list.t
+tests/test-evolve-noupdate.t
+tests/test-evolve-obshistory-amend-then-fold.t
+tests/test-evolve-obshistory-amend.t
+tests/test-evolve-obshistory-complex.t
+tests/test-evolve-obshistory-content-divergent.t
+tests/test-evolve-obshistory-fold.t
+tests/test-evolve-obshistory-lots-of-splits.t
+tests/test-evolve-obshistory-phase-divergent.t
+tests/test-evolve-obshistory-prune.t
+tests/test-evolve-obshistory-split.t
+tests/test-evolve-obshistory.t
+tests/test-evolve-order.t
+tests/test-evolve-orphan-corner-cases.t
+tests/test-evolve-orphan-merge.t
+tests/test-evolve-orphan-split.t
+tests/test-evolve-phase-divergence.t
+tests/test-evolve-phase.t
+tests/test-evolve-progress.t
+tests/test-evolve-public-content-divergent-corner-cases.t
+tests/test-evolve-public-content-divergent-discard.t
+tests/test-evolve-public-content-divergent-main.t
+tests/test-evolve-split.t
+tests/test-evolve-stop-orphan.t
+tests/test-evolve-stop-phasediv.t
+tests/test-evolve-templates.t
+tests/test-evolve-topic.t
+tests/test-evolve-wdir.t
+tests/test-evolve.t
+tests/test-exchange-obsmarkers-case-A1.t
+tests/test-exchange-obsmarkers-case-A2.t
+tests/test-exchange-obsmarkers-case-A3.t
+tests/test-exchange-obsmarkers-case-A4.t
+tests/test-exchange-obsmarkers-case-A5.t
+tests/test-exchange-obsmarkers-case-A6.t
+tests/test-exchange-obsmarkers-case-A7.t
+tests/test-exchange-obsmarkers-case-B1.t
+tests/test-exchange-obsmarkers-case-B2.t
+tests/test-exchange-obsmarkers-case-B3.t
+tests/test-exchange-obsmarkers-case-B4.t
+tests/test-exchange-obsmarkers-case-B5.t
+tests/test-exchange-obsmarkers-case-B6.t
+tests/test-exchange-obsmarkers-case-B7.t
+tests/test-exchange-obsmarkers-case-C1.t
+tests/test-exchange-obsmarkers-case-C2.t
+tests/test-exchange-obsmarkers-case-C3.t
+tests/test-exchange-obsmarkers-case-C4.t
+tests/test-exchange-obsmarkers-case-D1.t
+tests/test-exchange-obsmarkers-case-D2.t
+tests/test-exchange-obsmarkers-case-D3.t
+tests/test-exchange-obsmarkers-case-D4.t
+tests/test-extension-isolation.t
+tests/test-fixup.t
+tests/test-fold.t
+tests/test-import.t
+tests/test-issue-5720.t
+tests/test-issue-6028.t
+tests/test-issue6550.t
+tests/test-metaedit.t
+tests/test-namespaces-exchange.t
+tests/test-namespaces-precheck.t
+tests/test-namespaces-reject.t
+tests/test-namespaces-report.t
+tests/test-namespaces.t
+tests/test-next-abort.t
+tests/test-obsconvert.t
+tests/test-obsolete-push.t
+tests/test-obsolete.t
+tests/test-options.t
+tests/test-pick.t
+tests/test-prev-next.t
+tests/test-prune.t
+tests/test-pullbundle.t
+tests/test-push-checkheads-mixed-branch-topic-G1.t
+tests/test-push-checkheads-mixed-branch-topic-G2.t
+tests/test-push-checkheads-mixed-branch-topic-G3.t
+tests/test-push-checkheads-multi-topics-F1.t
+tests/test-push-checkheads-multi-topics-F2.t
+tests/test-push-checkheads-multi-topics-F3.t
+tests/test-push-checkheads-multibranches-E1.t
+tests/test-push-checkheads-multibranches-E2.t
+tests/test-push-checkheads-multibranches-E3.t
+tests/test-push-checkheads-partial-C1.t
+tests/test-push-checkheads-partial-C2.t
+tests/test-push-checkheads-partial-C3.t
+tests/test-push-checkheads-partial-C4.t
+tests/test-push-checkheads-pruned-B1.t
+tests/test-push-checkheads-pruned-B2.t
+tests/test-push-checkheads-pruned-B3.t
+tests/test-push-checkheads-pruned-B4.t
+tests/test-push-checkheads-pruned-B5.t
+tests/test-push-checkheads-pruned-B6.t
+tests/test-push-checkheads-pruned-B7.t
+tests/test-push-checkheads-pruned-B8.t
+tests/test-push-checkheads-supersede-A1.t
+tests/test-push-checkheads-supersede-A2.t
+tests/test-push-checkheads-supersede-A3.t
+tests/test-push-checkheads-supersede-A4.t
+tests/test-push-checkheads-supersede-A5.t
+tests/test-push-checkheads-supersede-A6.t
+tests/test-push-checkheads-supersede-A7.t
+tests/test-push-checkheads-supersede-A8.t
+tests/test-push-checkheads-unpushed-D1.t
+tests/test-push-checkheads-unpushed-D2.t
+tests/test-push-checkheads-unpushed-D3.t
+tests/test-push-checkheads-unpushed-D4.t
+tests/test-push-checkheads-unpushed-D5.t
+tests/test-push-checkheads-unpushed-D6.t
+tests/test-push-checkheads-unpushed-D7.t
+tests/test-rewind.t
+tests/test-share.t
+tests/test-sharing.t
+tests/test-single-head-obsolescence-named-branch-A1.t
+tests/test-single-head-obsolescence-named-branch-A2.t
+tests/test-single-head-obsolescence-named-branch-A3.t
+tests/test-single-head-obsolescence-named-branch-A4.t
+tests/test-single-head-obsolescence-named-branch-A5.t
+tests/test-single-head-obsolescence-topic-B1.t
+tests/test-single-head-obsolescence-topic-B2.t
+tests/test-single-head-obsolescence-topic-B3.t
+tests/test-single-head-obsolescence-topic-B4.t
+tests/test-single-head-obsolescence-topic-B5.t
+tests/test-split.t
+tests/test-sqlite3-permissions.t
+tests/test-stabilize-conflict.t
+tests/test-stabilize-order.t
+tests/test-stablerange-branchpoint.t
+tests/test-stablerange.t
+tests/test-stablesort-branchpoint-criss-cross.t
+tests/test-stablesort-branchpoint.t
+tests/test-stablesort-criss-cross.t
+tests/test-stablesort.t
+tests/test-stack-branch.t
+tests/test-stack-split-s0.t
+tests/test-topic-change.t
+tests/test-topic-debugcb.t
+tests/test-topic-dest.t
+tests/test-topic-flow-publish-bare.t
+tests/test-topic-flow-publish-flag.t
+tests/test-topic-flow-reject-untopiced.t
+tests/test-topic-flow-single-head.t
+tests/test-topic-fold.t
+tests/test-topic-issue6406.t
+tests/test-topic-issue6500.t
+tests/test-topic-issue6841.t
+tests/test-topic-merge.t
+tests/test-topic-mode.t
+tests/test-topic-multiple.t
+tests/test-topic-prev-next.t
+tests/test-topic-push.t
+tests/test-topic-rebase.t
+tests/test-topic-server.t
+tests/test-topic-shell-prompt.t
+tests/test-topic-shelve.t
+tests/test-topic-stack-complex.t
+tests/test-topic-stack-data.t
+tests/test-topic-stack.t
+tests/test-topic-tutorial.t
+tests/test-topic.t
+tests/test-touch.t
+tests/test-tutorial.t
+tests/test-uncommit-interactive.t
+tests/test-uncommit.t
+tests/test-unstability-resolution-result.t
+tests/test-unstable-orphan.t
+tests/test-userguide.t
+tests/test-version-install.t
+tests/test-wireproto-bundle1.t
+tests/test-wireproto.t
+tests/testlib/check-compat-strings.py
+tests/testlib/check-min-versions.py
+tests/testlib/common.sh
+tests/testlib/content-divergence-util.sh
+tests/testlib/docgraph_setup.sh
+tests/testlib/exchange-obsmarker-util.sh
+tests/testlib/map-hg-rev.sh
+tests/testlib/obshistory_setup.sh
+tests/testlib/push-checkheads-util.sh
+tests/testlib/pythonpath.sh
+tests/testlib/random-revs.py
+tests/testlib/retain-extras-ext.py
+tests/testlib/topic_setup.sh
+tests/testlib/update-hg-repo.sh
\ No newline at end of file
diff -pruN 11.1.3-1/hg_evolve.egg-info/dependency_links.txt 11.1.9-1/hg_evolve.egg-info/dependency_links.txt
--- 11.1.3-1/hg_evolve.egg-info/dependency_links.txt	1970-01-01 00:00:00.000000000 +0000
+++ 11.1.9-1/hg_evolve.egg-info/dependency_links.txt	2025-07-25 16:21:08.000000000 +0000
@@ -0,0 +1 @@
+
diff -pruN 11.1.3-1/hg_evolve.egg-info/top_level.txt 11.1.9-1/hg_evolve.egg-info/top_level.txt
--- 11.1.3-1/hg_evolve.egg-info/top_level.txt	1970-01-01 00:00:00.000000000 +0000
+++ 11.1.9-1/hg_evolve.egg-info/top_level.txt	2025-07-25 16:21:08.000000000 +0000
@@ -0,0 +1 @@
+hgext3rd
diff -pruN 11.1.3-1/hgext3rd/evolve/compat.py 11.1.9-1/hgext3rd/evolve/compat.py
--- 11.1.3-1/hgext3rd/evolve/compat.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/hgext3rd/evolve/compat.py	2025-07-25 16:21:02.000000000 +0000
@@ -40,6 +40,14 @@ try:
 except (AttributeError, ImportError):
     mergestate = mergemod.mergestate  # pytype: disable=module-attr
 
+try:
+    from mercurial import mergestate as mergestatemod
+    mergestatemod.memmergestate
+    hasmemmergestate = True
+except (AttributeError, ImportError):
+    # hg <= 5.5 (19590b126764)
+    hasmemmergestate = False
+
 from . import (
     exthelper,
 )
@@ -494,6 +502,89 @@ if 'copied' not in code.co_varnames[:cod
 
     context.overlayworkingctx.markcopied = fixedmarkcopied
 
+# hg <= 6.9 (f071b18e1382)
+# we detect a502f3f389b5 because it's close enough and touches the same code
+def _detect_hit(code):
+    """ detect a502f3f389b5 by inspecting variables of getfile()
+    """
+    return 'hit' in code.co_varnames[code.co_argcount:]
+def _new_tomemctx(tomemctx):
+    """ diving into tomemctx() to find and inspect the nested getfile()
+    """
+    return any(
+        _detect_hit(c) for c in tomemctx.__code__.co_consts
+        if util.safehasattr(c, 'co_varnames')
+    )
+if not _new_tomemctx(context.overlayworkingctx.tomemctx):
+    def fixed_tomemctx(
+        self,
+        text,
+        branch=None,
+        extra=None,
+        date=None,
+        parents=None,
+        user=None,
+        editor=None,
+    ):
+        """Converts this ``overlayworkingctx`` into a ``memctx`` ready to be
+        committed.
+
+        ``text`` is the commit message.
+        ``parents`` (optional) are rev numbers.
+        """
+        # Default parents to the wrapped context if not passed.
+        if parents is None:
+            parents = self.parents()
+            if len(parents) == 1:
+                parents = (parents[0], None)
+
+        # ``parents`` is passed as rev numbers; convert to ``commitctxs``.
+        if parents[1] is None:
+            parents = (self._repo[parents[0]], None)
+        else:
+            parents = (self._repo[parents[0]], self._repo[parents[1]])
+
+        files = self.files()
+
+        def getfile(repo, memctx, path):
+            hit = self._cache.get(path)
+            ### FIXED PART ###
+            if hit is None:
+                return self.filectx(path)
+            ### END FIXED PART ###
+            elif hit[b'exists']:
+                return context.memfilectx(
+                    repo,
+                    memctx,
+                    path,
+                    hit[b'data'],
+                    b'l' in hit[b'flags'],
+                    b'x' in hit[b'flags'],
+                    hit[b'copied'],
+                )
+            else:
+                # Returning None, but including the path in `files`, is
+                # necessary for memctx to register a deletion.
+                return None
+
+        if branch is None:
+            branch = self._wrappedctx.branch()
+
+        return context.memctx(
+            self._repo,
+            parents,
+            text,
+            files,
+            getfile,
+            date=date,
+            extra=extra,
+            user=user,
+            branch=branch,
+            editor=editor,
+        )
+
+    context.overlayworkingctx.tomemctx = fixed_tomemctx
+
 # what we're actually targeting here is e079e001d536
 # hg <= 5.0 (dc3fdd1b5af4)
 try:
diff -pruN 11.1.3-1/hgext3rd/evolve/evolvecmd.py 11.1.9-1/hgext3rd/evolve/evolvecmd.py
--- 11.1.3-1/hgext3rd/evolve/evolvecmd.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/hgext3rd/evolve/evolvecmd.py	2025-07-25 16:21:02.000000000 +0000
@@ -911,12 +911,8 @@ def _rewrite_commit_message_hashes(repo,
     return commitmsg
 
 def use_in_memory_merge(repo):
-    try:
-        from mercurial import mergestate as mergestatemod
-        mergestatemod.memmergestate
-    except (AttributeError, ImportError):
+    if not compat.hasmemmergestate:
         # no in-memory evolve if Mercurial lacks the required code
-        # hg <= 5.5 (19590b126764)
         return False
     config_value = repo.ui.config(b'experimental', b'evolution.in-memory')
     if config_value == b'force':
@@ -1897,10 +1893,10 @@ def abortevolve(ui, repo, evolvestate):
         cleanup = True
         startnode = evolvestate[b'startnode']
         for old, new in evolvestate[b'replacements'].items():
-            if new:
+            if new and new in repo:
                 evolvedctx.append(repo[new])
         for temp in evolvestate[b'temprevs']:
-            if temp:
+            if temp and temp in repo:
                 evolvedctx.append(repo[temp])
         evolvedrevs = [c.rev() for c in evolvedctx]
 
diff -pruN 11.1.3-1/hgext3rd/evolve/headchecking.py 11.1.9-1/hgext3rd/evolve/headchecking.py
--- 11.1.3-1/hgext3rd/evolve/headchecking.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/hgext3rd/evolve/headchecking.py	2025-07-25 16:21:02.000000000 +0000
@@ -25,10 +25,12 @@ eh = exthelper.exthelper()
 @eh.uisetup
 def uisetup(ui):
     extensions.wrapfunction(discovery, '_postprocessobsolete', _postprocessobsolete)
-    code = scmutil.filteredhash.__code__
-    if r'needobsolete' not in code.co_varnames[:code.co_argcount]:
-        # hg <= 6.0 (053a5bf508da)
-        extensions.wrapfunction(scmutil, 'enforcesinglehead', enforcesinglehead)
+    if util.safehasattr(scmutil, 'filteredhash'):
+        # hg <= 6.7 (a03fa40afd01)
+        code = scmutil.filteredhash.__code__
+        if 'needobsolete' not in code.co_varnames[:code.co_argcount]:
+            # hg <= 6.0 (053a5bf508da)
+            extensions.wrapfunction(scmutil, 'enforcesinglehead', enforcesinglehead)
 
 def branchinfo(pushop, repo, node):
     return repo[node].branch()
diff -pruN 11.1.3-1/hgext3rd/evolve/metadata.py 11.1.9-1/hgext3rd/evolve/metadata.py
--- 11.1.3-1/hgext3rd/evolve/metadata.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/hgext3rd/evolve/metadata.py	2025-07-25 16:21:02.000000000 +0000
@@ -5,7 +5,7 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-__version__ = b'11.1.3'
-testedwith = b'4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7'
+__version__ = b'11.1.9'
+testedwith = b'4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1'
 minimumhgversion = b'4.9'
 buglink = b'https://bz.mercurial-scm.org/'
diff -pruN 11.1.3-1/hgext3rd/evolve/obscache.py 11.1.9-1/hgext3rd/evolve/obscache.py
--- 11.1.3-1/hgext3rd/evolve/obscache.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/hgext3rd/evolve/obscache.py	2025-07-25 16:21:02.000000000 +0000
@@ -14,6 +14,7 @@ import struct
 from mercurial import (
     localrepo,
     obsolete,
+    obsutil,
     phases,
     node,
     util,
@@ -462,12 +463,46 @@ def _computeobsoleteset(orig, repo):
         isobs = obscache.get
     return frozenset(r for r in notpublic if isobs(r))
 
+def _computecontentdivergentset(repo):
+    """the set of rev that compete to be the final successors of some revision."""
+    divergent = set()
+    obsstore = repo.obsstore
+    newermap = {}
+    tonode = repo.changelog.node
+    candidates = sorted(obsolete._mutablerevs(repo) - obsolete.getrevs(repo, b"obsolete"))
+    for rev in candidates:
+        node = tonode(rev)
+        mark = obsstore.predecessors.get(node, ())
+        toprocess = set(mark)
+        seen = set()
+        while toprocess:
+            prec = toprocess.pop()[0]
+            if prec in seen:
+                continue  # emergency cycle hanging prevention
+            seen.add(prec)
+            if prec not in newermap:
+                obsutil.successorssets(repo, prec, cache=newermap)
+            newer = [n for n in newermap[prec] if n]
+            # only this condition was changed in hg 6.9
+            # hg <= 6.8 (e68fe567a780)
+            if len(newer) > 1 and any(n for n in newer if node not in n):
+                divergent.add(rev)
+                break
+            toprocess.update(obsstore.predecessors.get(prec, ()))
+    return frozenset(divergent)
+
 @eh.uisetup
 def cachefuncs(ui):
     orig = obsolete.cachefuncs[b'obsolete']
     wrapped = lambda repo: _computeobsoleteset(orig, repo)
     obsolete.cachefuncs[b'obsolete'] = wrapped
 
+    version = tuple(i if i is not None else 0 for i in util.versiontuple(n=3))
+    if version < (6, 8, 2):
+        # e68fe567a780 was just before the 6.8.2 release
+        # hg <= 6.8 (e68fe567a780)
+        obsolete.cachefuncs[b'contentdivergent'] = _computecontentdivergentset
+
 @eh.reposetup
 def setupcache(ui, repo):
 
diff -pruN 11.1.3-1/hgext3rd/evolve/obsdiscovery.py 11.1.9-1/hgext3rd/evolve/obsdiscovery.py
--- 11.1.3-1/hgext3rd/evolve/obsdiscovery.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/hgext3rd/evolve/obsdiscovery.py	2025-07-25 16:21:02.000000000 +0000
@@ -323,8 +323,14 @@ def _affectedby(repo, markers):
 
     return affected_nodes
 
-# if there is that many new obsmarkers, reset without analysing them
+def _chunks(items, size=1024):
+    for i in range(0, len(items), size):
+        yield items[i:i + size]
+
+# reset when there are this many new obsmarkers or affected changesets
 RESET_ABOVE = 10000
+# reset when there are this many affected ranges
+RESET_ABOVE_RANGES = RESET_ABOVE * 10
 
 class _obshashcache(obscache.dualsourcecache):
 
@@ -432,6 +438,14 @@ class _obshashcache(obscache.dualsourcec
                     # always reset for now, the code detecting affect is buggy
                     # so we need to reset more broadly than we would like.
                     try:
+                        if reset:
+                            ranges = [] # no need to compute that
+                        else:
+                            ranges = repo.stablerange.contains(repo, affected)
+                            if RESET_ABOVE_RANGES < len(ranges):
+                                repo.ui.log(b'evoext-cache', b'obshashcache reset - '
+                                            b'too many ranges to purges\n')
+                                reset = True
                         if repo.stablerange._con is None:
                             repo.ui.log(b'evoext-cache', b'obshashcache reset - '
                                         b'underlying stablerange cache unavailable\n')
@@ -441,9 +455,10 @@ class _obshashcache(obscache.dualsourcec
                             self._data.clear()
                         else:
                             ranges = repo.stablerange.contains(repo, affected)
-                            con.executemany(_delete, ranges)
-                            for r in ranges:
-                                self._data.pop(r, None)
+                            for chunk in _chunks(ranges):
+                                con.executemany(_delete, chunk)
+                                for r in chunk:
+                                    self._data.pop(r, None)
                     except (sqlite3.DatabaseError, sqlite3.OperationalError) as exc:
                         repo.ui.log(b'evoext-cache',
                                     b'error while updating obshashrange cache: %s\n'
diff -pruN 11.1.3-1/hgext3rd/evolve/obshistory.py 11.1.9-1/hgext3rd/evolve/obshistory.py
--- 11.1.3-1/hgext3rd/evolve/obshistory.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/hgext3rd/evolve/obshistory.py	2025-07-25 16:21:02.000000000 +0000
@@ -11,6 +11,7 @@ import re
 
 from mercurial import (
     commands,
+    context,
     error,
     graphmod,
     logcmdutil,
@@ -29,6 +30,7 @@ from mercurial.utils import dateutil
 from mercurial.i18n import _
 
 from . import (
+    compat,
     exthelper,
 )
 
@@ -306,27 +308,43 @@ class obsmarker_printer(logcmdutil.chang
         '''
         pass
 
-def patchavailable(node, repo, candidates, successive=True):
-    """ Check if it's possible to get a diff between node and candidates.
+class _NoPatchAvailable(Exception):
+    """small internal exception
+
+    Carries the reason of why we cannot offer a patch to `displaymarkers`.
+
+    XXX: we could raise a more semantic reason and let `displaymarkers` create
+    the message.
+    """
+    def __init__(self, reason):
+        self.reason = reason
+        super(_NoPatchAvailable, self).__init__()
+
+def prepare_patch(repo, node, candidates, successive=True):
+    """ Prepare 2 contexts for a diff between node and one of its candidates.
 
     `candidates` contains nodes, which can be either successors (`successive`
     is True) or predecessors (`successive` is False) of `node`.
+
+    Return a (from_ctx, to_ctx) tuple of contexts. One of these contexts could
+    be a result of in-memory rebase to align it with parents of the other
+    context.
     """
     if node not in repo:
-        return False, b"context is not local"
+        raise _NoPatchAvailable(b"context is not local")
 
     if len(candidates) == 0:
         if successive:
             msg = b"no successors"
         else:
             msg = b"no predecessors"
-        return False, msg
+        raise _NoPatchAvailable(msg)
     elif len(candidates) > 1:
         if successive:
             msg = b"too many successors (%d)"
         else:
             msg = b"too many predecessors (%d)"
-        return False, msg % len(candidates)
+        raise _NoPatchAvailable(msg % len(candidates))
 
     cand = candidates[0]
 
@@ -335,16 +353,69 @@ def patchavailable(node, repo, candidate
             msg = b"successor is unknown locally"
         else:
             msg = b"predecessor is unknown locally"
-        return False, msg
+        raise _NoPatchAvailable(msg)
+
+    node_ctx = repo[node]
+    cand_ctx = repo[cand]
 
     # Check that both node and cand have the same parents
-    nodep1, nodep2 = repo[node].p1(), repo[node].p2()
-    candp1, candp2 = repo[cand].p1(), repo[cand].p2()
+    nodep1, nodep2 = node_ctx.p1(), node_ctx.p2()
+    candp1, candp2 = cand_ctx.p1(), cand_ctx.p2()
 
-    if nodep1 != candp1 or nodep2 != candp2:
-        return False, b"changesets rebased"
+    if not compat.hasmemmergestate and (nodep1 != candp1 or nodep2 != candp2):
+        # we need hg 5.6+ for rebasing cand in-memory to show this diff
+        msg = b"Mercurial 5.6 or newer is required for in-memory rebase"
+        raise _NoPatchAvailable(msg)
+
+    if nodep1 != candp1:
+        # XXX the case when both p1 and p2 changed could be better.
+        #
+        # For simplicity if both parents change, we currently only reflect the
+        # impact on "p1" changeset. This should be improved at some point, but
+        # this is good enough for now.
+        cand_ctx = _rebase_cand(repo, cand_ctx, candp1, nodep1)
+    elif nodep2 != candp2:
+        cand_ctx = _rebase_cand(repo, cand_ctx, candp2, nodep2)
+    if successive:
+        return (node_ctx, cand_ctx)
+    else:
+        return (cand_ctx, node_ctx)
 
-    return True, cand
+
+def _rebase_cand(repo, ctx, old_base, new_base):
+    """return a view of ctx rebased in-memory from old_base to new_base
+
+    This can be used to produce a patch in obslog even when changesets were
+    rebased.
+    """
+    # XXX inspired by the diff.merge feature (mercurial.diffutil.diff_parent).
+    # We should move this logic to core.
+    base = context.overlayworkingctx(repo)
+    base.setbase(ctx)
+    configoverrides = {
+        (b'ui', b'forcemerge'): b'internal:merge3-lie-about-conflicts'
+    }
+    with repo.ui.configoverride(configoverrides, b'obslog-diff'):
+        # hg <= 5.8 (7a430116f639)
+        # this try-finally block can be replaced by ui.silent context manager
+        try:
+            repo.ui.pushbuffer()
+            compat._update(
+                repo,
+                new_base,
+                labels=[
+                    b'predecessor',
+                    b'successor-parent',
+                    b'predecessor-parent',
+                ],
+                force=True,
+                branchmerge=True,
+                wc=base,
+                ancestor=old_base,
+            )
+        finally:
+            repo.ui.popbuffer()
+    return base.tomemctx(text=ctx.description())
 
 def getmarkerdescriptionpatch(repo, basedesc, succdesc):
     # description are stored without final new line,
@@ -677,18 +748,14 @@ def displaymarkers(ui, fm, nodes, marker
 
     # Patch display
     if includediff is True:
-        _patchavailable = patchavailable(node, repo, nodes,
-                                         successive=successive)
-
-        if _patchavailable[0] is True:
-            diffnode = _patchavailable[1]
 
-            if successive:
-                actx = repo[node]
-                bctx = repo[diffnode]
-            else:
-                actx = repo[diffnode]
-                bctx = repo[node]
+        try:
+            actx, bctx = prepare_patch(repo, node, nodes, successive=successive)
+            assert actx is not None
+            assert bctx is not None
+        except _NoPatchAvailable as exc:
+            fm.data(nopatchreason=exc.reason)
+        else:
             # Description patch
             descriptionpatch = getmarkerdescriptionpatch(repo,
                                                          actx.description(),
@@ -717,7 +784,7 @@ def displaymarkers(ui, fm, nodes, marker
             matchfn = scmutil.matchall(repo)
             firstline = True
             linestart = True
-            for chunk, label in patch.diffui(repo, actx.node(), bctx.node(),
+            for chunk, label in patch.diffui(repo, actx, bctx,
                                              matchfn, opts=diffopts):
                 if firstline:
                     ui.write(b'\n')
@@ -728,8 +795,6 @@ def displaymarkers(ui, fm, nodes, marker
                     linestart = True
                 ui.write(chunk, label=label)
             fm.data(patch=ui.popbuffer())
-        else:
-            fm.data(nopatchreason=_patchavailable[1])
 
 def _prepare_hunk(hunk):
     """Drop all information but the username and patch"""
diff -pruN 11.1.3-1/hgext3rd/evolve/rewriteutil.py 11.1.9-1/hgext3rd/evolve/rewriteutil.py
--- 11.1.3-1/hgext3rd/evolve/rewriteutil.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/hgext3rd/evolve/rewriteutil.py	2025-07-25 16:21:02.000000000 +0000
@@ -233,14 +233,6 @@ def reachablefrombookmark(repo, revs, bo
             revs = sorted(revs)
     return repomarks, revs
 
-try:
-    from mercurial import mergestate
-    mergestate.memmergestate
-    hasmemmergestate = True
-except (ImportError, AttributeError):
-    # hg <= 5.5 (19590b126764)
-    hasmemmergestate = False
-
 def rewrite(repo, old, head, newbases, commitopts):
     """Return (nodeid, created) where nodeid is the identifier of the
     changeset generated by the rewrite process, and created is True if
@@ -251,7 +243,7 @@ def rewrite(repo, old, head, newbases, c
     # mergestate and use that. We don't want that to happen, so we'll require
     # users of old Mercurial versions to run `hg touch` etc without
     # mergestate.
-    if not hasmemmergestate:
+    if not compat.hasmemmergestate:
         ms = compat.mergestate.read(repo)
         mergeutil.checkunresolved(ms)
 
diff -pruN 11.1.3-1/hgext3rd/topic/__init__.py 11.1.9-1/hgext3rd/topic/__init__.py
--- 11.1.3-1/hgext3rd/topic/__init__.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/hgext3rd/topic/__init__.py	2025-07-25 16:21:02.000000000 +0000
@@ -238,9 +238,9 @@ colortable = {b'topic.active': b'green',
               b'log.topic': b'green_background',
               }
 
-__version__ = b'1.1.3'
+__version__ = b'1.1.9'
 
-testedwith = b'4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7'
+testedwith = b'4.9 5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.0 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1'
 minimumhgversion = b'4.9'
 buglink = b'https://bz.mercurial-scm.org/'
 
@@ -719,8 +719,8 @@ def reposetup(ui, repo):
             self._topic_namespaces = namespaces
             return namespaces
 
-        def wlock(self, wait=True):
-            wlock = super(topicrepo, self).wlock(wait=wait)
+        def wlock(self, wait=True, **kwargs):
+            wlock = super(topicrepo, self).wlock(wait=wait, **kwargs)
             # we should definitely drop this at some point, but it depends on
             # our own release schedule, not core's, so here's hg 1.0
             # hg <= 1.0 (cfa08c88a5c4)
diff -pruN 11.1.3-1/hgext3rd/topic/discovery.py 11.1.9-1/hgext3rd/topic/discovery.py
--- 11.1.3-1/hgext3rd/topic/discovery.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/hgext3rd/topic/discovery.py	2025-07-25 16:21:02.000000000 +0000
@@ -6,7 +6,6 @@ import weakref
 
 from mercurial.i18n import _
 from mercurial import (
-    branchmap,
     bundle2,
     discovery,
     encoding,
@@ -24,6 +23,12 @@ from . import (
     compat,
 )
 
+try:
+    from mercurial.branching.rev_cache import revbranchcache
+except ImportError:
+    # hg <= 6.8 (f0e07efc199f)
+    from mercurial.branchmap import revbranchcache
+
 urlreq = util.urlreq
 
 @contextlib.contextmanager
@@ -89,9 +94,11 @@ def _headssummary(orig, pushop, *args, *
     else:
         origremotebranchmap = remote.branchmap
     publishednode = [c.node() for c in pushop.outdatedphases]
-    publishedset = repo.revs(b'ancestors(%ln + %ln)',
-                             publishednode,
-                             pushop.remotephases.publicheads)
+    if util.safehasattr(pushop.remotephases, 'publicheads'):
+        # hg <= 6.7 (22cc679a7312)
+        publishedset = repo.revs(b'ancestors(%ln + %ln)', publishednode, pushop.remotephases.publicheads)
+    else:
+        publishedset = repo.revs(b'ancestors(%ln + %ld)', publishednode, pushop.remotephases.public_heads)
 
     publishing = (b'phases' not in remote.listkeys(b'namespaces')
                   or bool(remote.listkeys(b'phases').get(b'publishing', False)))
@@ -240,12 +247,13 @@ def _filter_obsolete_heads(repo, heads):
 #
 # Handle this by doing an extra check for new head creation server side
 def _nbheads(repo):
-    code = scmutil.filteredhash.__code__
-    if r'needobsolete' not in code.co_varnames[:code.co_argcount]:
-        # hg <= 6.0 (053a5bf508da)
-        filterfn = _filter_obsolete_heads
-    else:
-        filterfn = lambda repo, heads: heads
+    filterfn = lambda repo, heads: heads
+    if util.safehasattr(scmutil, 'filteredhash'):
+        # hg <= 6.7 (a03fa40afd01)
+        code = scmutil.filteredhash.__code__
+        if 'needobsolete' not in code.co_varnames[:code.co_argcount]:
+            # hg <= 6.0 (053a5bf508da)
+            filterfn = _filter_obsolete_heads
     data = {}
     for b in repo.branchmap().iterbranches():
         namedbranch, tns, topic = common.parsefqbn(b[0])
@@ -388,10 +396,10 @@ def modsetup(ui):
     extensions.wrapfunction(wireprotov1server, '_capabilities', wireprotocaps)
     wirepeer.branchmaptns = wirepeer.branchmap
     wireprotov1server.wireprotocommand(b'branchmaptns', permission=b'pull')(wireprotobranchmaptns)
-    extensions.wrapfunction(branchmap.revbranchcache, 'branchinfo', wrapbranchinfo)
+    extensions.wrapfunction(revbranchcache, 'branchinfo', wrapbranchinfo)
     # branchinfo method can get replaced by _branchinfo method directly when
     # on-disk revbranchcache is not available, see revbranchcache.__init__()
-    extensions.wrapfunction(branchmap.revbranchcache, '_branchinfo', wrapslowbranchinfo)
+    extensions.wrapfunction(revbranchcache, '_branchinfo', wrapslowbranchinfo)
     # we need a proper wrap b2 part stuff
     extensions.wrapfunction(bundle2, 'handlecheckheads', handlecheckheads)
     bundle2.handlecheckheads.params = frozenset()
diff -pruN 11.1.3-1/hgext3rd/topic/flow.py 11.1.9-1/hgext3rd/topic/flow.py
--- 11.1.3-1/hgext3rd/topic/flow.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/hgext3rd/topic/flow.py	2025-07-25 16:21:02.000000000 +0000
@@ -127,8 +127,13 @@ def wrapphasediscovery(orig, pushop):
     if getattr(pushop, 'publish', False):
         if not pushop.remotephases.publishing:
             unfi = pushop.repo.unfiltered()
-            droots = pushop.remotephases.draftroots
-            revset = b'%ln and (not public() or %ln::)'
+            if util.safehasattr(pushop.remotephases, 'draftroots'):
+                # hg <= 6.7 (22cc679a7312)
+                droots = pushop.remotephases.draftroots
+                revset = b'%ln and (not public() or %ln::)'
+            else:
+                droots = pushop.remotephases.draft_roots
+                revset = b'%ln and (not public() or %ld::)'
             future = list(unfi.set(revset, pushop.futureheads, droots))
             pushop.outdatedphases = future
 
diff -pruN 11.1.3-1/hgext3rd/topic/stack.py 11.1.9-1/hgext3rd/topic/stack.py
--- 11.1.3-1/hgext3rd/topic/stack.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/hgext3rd/topic/stack.py	2025-07-25 16:21:02.000000000 +0000
@@ -181,7 +181,11 @@ class stack(object):
             pt1 = self._repo[b'.']
 
         if pt1.obsolete():
-            pt1 = self._repo[_singlesuccessor(self._repo, pt1)]
+            try:
+                pt1 = self._repo[_singlesuccessor(self._repo, pt1)]
+            except MultipleSuccessorsError as e:
+                # here, taking a random successor is better than failing
+                pt1 = self._repo[e.successorssets[0][-1]]
         revs.insert(0, pt1.rev())
         return revs
 
diff -pruN 11.1.3-1/hgext3rd/topic/topicmap.py 11.1.9-1/hgext3rd/topic/topicmap.py
--- 11.1.3-1/hgext3rd/topic/topicmap.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/hgext3rd/topic/topicmap.py	2025-07-25 16:21:02.000000000 +0000
@@ -38,7 +38,7 @@ def gettopicrepo(repo):
     if not common.hastopicext(repo):
         return repo
     filtername = topicfilter(repo.filtername)
-    if filtername == repo.filtername:
+    if filtername is None or filtername == repo.filtername:
         return repo
     return repo.filtered(filtername)
 
@@ -48,11 +48,10 @@ def _setuptopicfilter(ui):
     # hg <= 4.9 (caebe5e7f4bd)
     partialmap = branchmap.subsettable
 
-    # filter level not affected by topic that we should not override
-
     for plainname in list(funcmap):
         newfilter = topicfilter(plainname)
         if newfilter == plainname:
+            # filter level not affected by topic that we should not override
             continue
 
         def revsfunc(repo, name=plainname):
@@ -94,7 +93,11 @@ def modsetup(ui):
 
 def cgapply(orig, self, repo, *args, **kwargs):
     """make sure a topicmap is used when applying a changegroup"""
-    other = repo.filtered(topicfilter(repo.filtername))
+    newfilter = topicfilter(repo.filtername)
+    if newfilter is None:
+        other = repo
+    else:
+        other = repo.filtered(newfilter)
     return orig(self, other, *args, **kwargs)
 
 def commitstatus(orig, repo, node, branch, bheads=None, tip=None, **opts):
@@ -122,26 +125,36 @@ def commitstatus(orig, repo, node, branc
     return ret
 
 def _wrapbmcache(ui):
-    class topiccache(_topiccache, branchmap.branchcache):
-        pass
-    branchmap.branchcache = topiccache
+    if util.safehasattr(branchmap, 'BranchCacheV2'):
+        class TopicCache(_TopicCacheV2, branchmap.BranchCacheV2):
+            pass
+        branchmap.BranchCacheV2 = TopicCache
 
-    try:
-        # Mercurial 5.0
-        class remotetopiccache(_topiccache, branchmap.remotebranchcache):
+        class remotetopiccache(_TopicCacheV2, branchmap.remotebranchcache):
             pass
         branchmap.remotebranchcache = remotetopiccache
+    else:
+        # hg <= 6.7 (ec640dc9cebd)
+        class topiccache(_topiccache, branchmap.branchcache):
+            pass
+        branchmap.branchcache = topiccache
 
-        def _wrapupdatebmcachemethod(orig, self, repo):
-            # pass in the bound method as the original
-            return _wrapupdatebmcache(orig.__get__(self), repo)
-        extensions.wrapfunction(branchmap.BranchMapCache, 'updatecache', _wrapupdatebmcachemethod)
-    except AttributeError:
-        # hg <= 4.9 (3461814417f3)
-        extensions.wrapfunction(branchmap, 'updatecache', _wrapupdatebmcache)
-        # branchcache in hg <= 4.9 doesn't have load method, instead there's a
-        # module-level function to read on-disk cache and return a branchcache
-        extensions.wrapfunction(branchmap, 'read', _wrapbmread)
+        try:
+            # Mercurial 5.0
+            class remotetopiccache(_topiccache, branchmap.remotebranchcache):
+                pass
+            branchmap.remotebranchcache = remotetopiccache
+
+            def _wrapupdatebmcachemethod(orig, self, repo):
+                # pass in the bound method as the original
+                return _wrapupdatebmcache(orig.__get__(self), repo)
+            extensions.wrapfunction(branchmap.BranchMapCache, 'updatecache', _wrapupdatebmcachemethod)
+        except AttributeError:
+            # hg <= 4.9 (3461814417f3)
+            extensions.wrapfunction(branchmap, 'updatecache', _wrapupdatebmcache)
+            # branchcache in hg <= 4.9 doesn't have load method, instead there's a
+            # module-level function to read on-disk cache and return a branchcache
+            extensions.wrapfunction(branchmap, 'read', _wrapbmread)
 
 def _wrapupdatebmcache(orig, repo):
     previous = getattr(repo, '_autobranchmaptopic', False)
@@ -151,29 +164,38 @@ def _wrapupdatebmcache(orig, repo):
     finally:
         repo._autobranchmaptopic = previous
 
-# needed to prevent reference used for 'super()' call using in branchmap.py to
-# no go into cycle. (yes, URG)
-_oldbranchmap = branchmap.branchcache
-
-@contextlib.contextmanager
-def oldbranchmap():
-    previous = branchmap.branchcache
-    try:
-        branchmap.branchcache = _oldbranchmap
-        yield
-    finally:
-        branchmap.branchcache = previous
+if util.safehasattr(branchmap, 'branchcache') and dict in branchmap.branchcache.__mro__:
+    # hg <= 4.9 (624d6683c705)
+    # let's break infinite recursion in __init__() that uses super()
+    orig = branchmap.branchcache
+
+    @contextlib.contextmanager
+    def oldbranchmap():
+        current = branchmap.branchcache
+        try:
+            branchmap.branchcache = orig
+            yield
+        finally:
+            branchmap.branchcache = current
+else:
+    oldbranchmap = util.nullcontextmanager
+
+if util.safehasattr(branchmap, 'branchcache'):
+    allbccls = (branchmap.branchcache,)
+    if util.safehasattr(branchmap, 'remotebranchcache'):
+        # hg <= 4.9 (eb7ce452e0fb)
+        allbccls = (branchmap.branchcache, branchmap.remotebranchcache)
 
 class _topiccache(object): # combine me with branchmap.branchcache
 
     def __init__(self, *args, **kwargs):
-        # super() call may fail otherwise
         with oldbranchmap():
             super(_topiccache, self).__init__(*args, **kwargs)
         self.phaseshash = None
 
     def copy(self):
         """return an deep copy of the branchcache object"""
+        assert isinstance(self, allbccls)  # help pytype
         entries = compat.bcentries(self)
         args = (entries, self.tipnode, self.tiprev, self.filteredhash,
                 self._closednodes)
@@ -188,6 +210,7 @@ class _topiccache(object): # combine me
         """call branchmap.load(), and then transform branch names to be in the
         new "//" format
         """
+        assert isinstance(self, branchmap.branchcache)  # help pytype
         super(_topiccache, self).load(repo, lineiter)
         entries = compat.bcentries(self)
 
@@ -201,6 +224,7 @@ class _topiccache(object): # combine me
 
         - False when cached tipnode is unknown or if we detect a strip.
         - True when cache is up to date or a subset of current repo."""
+        assert isinstance(self, allbccls)  # help pytype
         valid = super(_topiccache, self).validfor(repo)
         if not valid:
             return False
@@ -237,6 +261,7 @@ class _topiccache(object): # combine me
         missing heads, and a generator of nodes that are strictly a superset of
         heads missing, this function updates self to be correct.
         """
+        assert isinstance(self, allbccls)  # help pytype
         if not istopicfilter(repo.filtername):
             return super(_topiccache, self).update(repo, revgen)
 
@@ -251,6 +276,87 @@ class _topiccache(object): # combine me
         super(_topiccache, self).update(repo, revgen)
         self.phaseshash = _phaseshash(repo, self.tiprev)
 
+class _TopicCacheV2(object): # combine me with branchmap.BranchCacheV2
+
+    def __init__(self, *args, **kwargs):
+        super(_TopicCacheV2, self).__init__(*args, **kwargs)
+        self.phaseshash = None
+
+    def _load_heads(self, repo, lineiter):
+        """call BranchCacheV2._load_heads(), and then transform branch names to
+        be in the new "//" format
+        """
+        assert isinstance(self, branchmap.BranchCacheV2)  # help pytype
+        super(_TopicCacheV2, self)._load_heads(repo, lineiter)
+
+        for branch in tuple(self._entries):
+            formatted = common.formatfqbn(branch=branch)
+            if branch != formatted:
+                self._entries[formatted] = self._entries.pop(branch)
+
+    def validfor(self, repo):
+        """Is the cache content valid regarding a repo
+
+        - False when cached tipnode is unknown or if we detect a strip.
+        - True when cache is up to date or a subset of current repo."""
+        assert isinstance(self, (branchmap.BranchCacheV2, branchmap.remotebranchcache))  # help pytype
+        valid = super(_TopicCacheV2, self).validfor(repo)
+        if not valid:
+            return False
+        elif not istopicfilter(repo.filtername) or self.phaseshash is None:
+            # phasehash at None means this is a branchmap
+            # come from non topic thing
+            return True
+        else:
+            try:
+                valid = self.phaseshash == _phaseshash(repo, self.tiprev)
+                return valid
+            except IndexError:
+                return False
+
+    def write(self, repo):
+        """write cache to disk if it's not topic-only, but first transform
+        cache keys from branches in "//" format into bare branch names
+        """
+        # we expect mutable set to be small enough to be that computing it all
+        # the time will be fast enough
+        if not istopicfilter(repo.filtername):
+            entries = self._entries.copy()
+
+            for formatted in tuple(entries):
+                branch, tns, topic = common.parsefqbn(formatted)
+                if branch != formatted:
+                    entries[branch] = entries.pop(formatted)
+
+            oldentries = self._entries
+            try:
+                self._entries = entries
+                super(_TopicCacheV2, self).write(repo)
+            finally:
+                self._entries = oldentries
+
+    def update(self, repo, revgen):
+        """Given a branchhead cache, self, that may have extra nodes or be
+        missing heads, and a generator of nodes that are strictly a superset of
+        heads missing, this function updates self to be correct.
+        """
+        assert isinstance(self, (branchmap.BranchCacheV2, branchmap.remotebranchcache))  # help pytype
+        if not istopicfilter(repo.filtername):
+            return super(_TopicCacheV2, self).update(repo, revgen)
+
+        # See topic.discovery._headssummary(), where repo.unfiltered gets
+        # overridden to return .filtered('unfiltered-topic'). revbranchcache
+        # only can be created for unfiltered repo (filtername is None), so we
+        # do that here, and this revbranchcache will be cached inside repo.
+        # When we get rid of *-topic filters, then this workaround can be
+        # removed too.
+        repo.unfiltered().revbranchcache()
+
+        super(_TopicCacheV2, self).update(repo, revgen)
+        if util.safehasattr(self, 'tiprev'):
+            # remotebranchcache doesn't have self.tiprev
+            self.phaseshash = _phaseshash(repo, self.tiprev)
+
 def _wrapbmread(orig, repo):
     """call branchmap.read(), and then transform branch names to be in the
     new "//" format
diff -pruN 11.1.3-1/setup.cfg 11.1.9-1/setup.cfg
--- 11.1.3-1/setup.cfg	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/setup.cfg	2025-07-25 16:21:08.977573600 +0000
@@ -1,28 +1,20 @@
 [flake8]
-ignore =
-         #closing bracket does not match indentation of opening bracket's line
-         E123,
-         # closing bracket does not match visual indentation
-         E124,
-         # visually indented line with same indent as next logical line
-         E129,
-         # at least two spaces before inline comment
-         E261,
-         # too many leading '#' for block comment
-         E266,
-         # expected 2 blank lines, found 0
-         E302,
-         # expected 2 blank lines after end of function or class
-         E305,
-         # module level import not at top of file
-         E402,
-         # line too long (82 > 79 characters)
-         E501,
-         # do not assign a lambda expression, use a def
-         E731,
-         # class names should use CapWords convention
-         N801,
-         # line break occurred before a binary operator
-         W503
-builtins=xrange, execfile
+ignore = 
+	E123,
+	E124,
+	E129,
+	E261,
+	E266,
+	E302,
+	E305,
+	E402,
+	E501,
+	E731,
+	N801,
+	W503
+builtins = xrange, execfile
+
+[egg_info]
+tag_build = 
+tag_date = 0
 
diff -pruN 11.1.3-1/setup.py 11.1.9-1/setup.py
--- 11.1.3-1/setup.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/setup.py	2025-07-25 16:21:02.000000000 +0000
@@ -40,6 +40,7 @@ setup(
     url='https://www.mercurial-scm.org/doc/evolution/',
     description='Flexible evolution of Mercurial history.',
     long_description=open(join(dirname(__file__), 'README.rst')).read(),
+    long_description_content_type='text/x-rst',
     keywords='hg mercurial',
     license='GPLv2+',
     packages=py_packages,
diff -pruN 11.1.3-1/tests/hghaveaddon.py 11.1.9-1/tests/hghaveaddon.py
--- 11.1.3-1/tests/hghaveaddon.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/hghaveaddon.py	2025-07-25 16:21:02.000000000 +0000
@@ -29,6 +29,11 @@ def has_check_manifest():
     return hghave.matchoutput('check-manifest --version 2>&1',
                               br'check-manifest version')
 
+@hghave.check("twine", "twine utility for publishing Python packages")
+def has_twine():
+    return hghave.matchoutput('twine --help 2>&1',
+                              br'usage: twine .*\bcheck\b')
+
 @hghave.check("default-cg3", "changegroup3 by default")
 def has_default_changegroup3():
     from mercurial import configitems
diff -pruN 11.1.3-1/tests/test-amend.t 11.1.9-1/tests/test-amend.t
--- 11.1.3-1/tests/test-amend.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-amend.t	2025-07-25 16:21:02.000000000 +0000
@@ -131,6 +131,7 @@ Check that --logfile works
 setting the user after we have performed the test with no username
   $ HGUSER=test
 
+#if hg69
 Check the help
   $ hg amend -h
   hg amend [OPTION]... [FILE]...
@@ -139,18 +140,18 @@ Check the help
   
   combine a changeset with updates and replace it with a new one
   
-      Commits a new changeset incorporating both the changes to the given files
-      and all the changes from the current parent changeset into the repository.
+  Commits a new changeset incorporating both the changes to the given files and
+  all the changes from the current parent changeset into the repository.
   
-      See 'hg commit' for details about committing changes.
+  See 'hg commit' for details about committing changes.
   
-      If you don't specify -m, the parent's message will be reused.
+  If you don't specify -m, the parent's message will be reused.
   
-      If --extract is specified, the behavior of 'hg amend' is reversed: Changes
-      to selected files in the checked out revision appear again as uncommitted
-      changed in the working directory.
+  If --extract is specified, the behavior of 'hg amend' is reversed: Changes to
+  selected files in the checked out revision appear again as uncommitted changed
+  in the working directory.
   
-      Returns 0 on success, 1 if nothing changed.
+  Returns 0 on success, 1 if nothing changed.
   
   options ([+] can be repeated):
   
@@ -175,6 +176,7 @@ Check the help
    -i --interactive         use interactive mode
   
   (some details hidden, use --verbose to show complete help)
+#endif
 
 Check that we abort if --patch and --extract both are used at once
   $ hg amend --patch --extract
diff -pruN 11.1.3-1/tests/test-check-commit.t 11.1.9-1/tests/test-check-commit.t
--- 11.1.3-1/tests/test-check-commit.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-check-commit.t	2025-07-25 16:21:02.000000000 +0000
@@ -1,24 +1,32 @@
 #require test-repo
 
+  $ . "$RUNTESTDIR/helpers-testrepo.sh"
+
 Enable obsolescence to avoid the warning issue when obsmarkers are found
 
   $ cat << EOF >> $HGRCPATH
   > [experimental]
   > evolution = all
-  > [diff]
-  > git = yes
   > EOF
 
 Go back in the hg repo
 
   $ cd $TESTDIR/..
 
-  $ for node in `hg log --rev 'not public() and ::. and not desc("# no-check-commit")' --template '{node|short}\n'`; do
-  >    hg export $node | ${RUNTESTDIR}/../contrib/check-commit > ${TESTTMP}/check-commit.out
-  >    if [ $? -ne 0 ]; then
-  >        echo "Revision $node does not comply with rules"
-  >        echo '------------------------------------------------------'
-  >        cat ${TESTTMP}/check-commit.out
-  >        echo
-  >   fi
-  > done
+  $ REVSET='not public() and ::. and not desc("# no-check-commit")'
+
+  $ mkdir "$TESTTMP/p"
+  $ REVS=`testrepohg log -r "$REVSET" -T.`
+  $ if [ -n "$REVS" ] ; then
+  >   testrepohg export --git -o "$TESTTMP/p/%n-%h" -r "$REVSET"
+  >   for f in `ls "$TESTTMP/p"`; do
+  >      "$RUNTESTDIR/../contrib/check-commit" < "$TESTTMP/p/$f" > "$TESTTMP/check-commit.out"
+  >      if [ $? -ne 0 ]; then
+  >          node="${f##*-}"
+  >          echo "Revision $node does not comply with rules"
+  >          echo '------------------------------------------------------'
+  >          cat ${TESTTMP}/check-commit.out
+  >          echo
+  >     fi
+  >   done
+  > fi
diff -pruN 11.1.3-1/tests/test-check-flake8.t 11.1.9-1/tests/test-check-flake8.t
--- 11.1.3-1/tests/test-check-flake8.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-check-flake8.t	2025-07-25 16:21:02.000000000 +0000
@@ -1,12 +1,14 @@
 #require test-repo flake8
 
+  $ . "$RUNTESTDIR/helpers-testrepo.sh"
+
 Copied from Mercurial core (60ee2593a270)
 
   $ cd "`dirname "$TESTDIR"`"
 
 run flake8 on all tracked files ending in .py or with a python shebang
 
-  $ hg files -0 'set:(**.py or grep("^#!.*python")) - removed()' \
+  $ testrepohg files -0 'set:(**.py or grep("^#!.*python")) - removed()' \
   > -X hgext3rd/evolve/thirdparty \
   > 2>/dev/null \
   > | xargs -0 "$PYTHON" -m flake8
diff -pruN 11.1.3-1/tests/test-check-pyflakes.t 11.1.9-1/tests/test-check-pyflakes.t
--- 11.1.3-1/tests/test-check-pyflakes.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-check-pyflakes.t	2025-07-25 16:21:02.000000000 +0000
@@ -1,12 +1,14 @@
 #require test-repo pyflakes
 
+  $ . "$RUNTESTDIR/helpers-testrepo.sh"
+
 Copied from Mercurial core (60ee2593a270)
 
   $ cd "`dirname "$TESTDIR"`"
 
 run pyflakes on all tracked files ending in .py or with a python shebang
 
-  $ hg files -0 'set:(**.py or grep("^#!.*python")) - removed()' \
+  $ testrepohg files -0 'set:(**.py or grep("^#!.*python")) - removed()' \
   > -X hgext3rd/evolve/thirdparty \
   > 2>/dev/null \
   > | xargs -0 "$PYTHON" -m pyflakes 2>/dev/null
diff -pruN 11.1.3-1/tests/test-check-sdist.t 11.1.9-1/tests/test-check-sdist.t
--- 11.1.3-1/tests/test-check-sdist.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-check-sdist.t	2025-07-25 16:21:02.000000000 +0000
@@ -11,16 +11,17 @@ Archiving to a separate location to avoi
 
 #if test-repo
 
-  $ hg archive "$TESTTMP"/hg-evolve
+  $ . "$RUNTESTDIR/helpers-testrepo.sh"
+  $ testrepohg archive "$TESTTMP"/hg-evolve
   $ cd "$TESTTMP"/hg-evolve
 
 #endif
 
+  $ "$PYTHON" setup.py check --metadata --restructuredtext
+
   $ "$PYTHON" setup.py sdist --dist-dir "$TESTTMP"/dist > /dev/null
-  */dist.py:*: UserWarning: Unknown distribution option: 'python_requires' (glob)
-    warnings.warn(msg)
-  warning: sdist: standard file not found: should have one of README, README.txt (?)
-   (?)
+  */dist.py:*: UserWarning: Unknown distribution option: 'python_requires' (glob) (?)
+    warnings.warn(msg) (?)
   warning: no previously-included files found matching 'docs/tutorial/.netlify'
   warning: no previously-included files found matching '.gitlab-ci.yml'
   warning: no previously-included files found matching '.hg-format-source'
@@ -28,37 +29,43 @@ Archiving to a separate location to avoi
   no previously-included directories found matching 'contrib'
   no previously-included directories found matching 'debian'
   no previously-included directories found matching '.gitlab'
+  no previously-included directories found matching 'tests/blacklists'
   $ cd "$TESTTMP"/dist
 
-  $ find hg-evolve-*.tar.gz -size +800000c
-  hg-evolve-*.tar.gz (glob)
+  $ find hg?evolve-*.tar.gz -size +800000c
+  hg?evolve-*.tar.gz (glob)
 
-  $ tar -tzf hg-evolve-*.tar.gz | sed 's|^hg-evolve-[^/]*/||' | sort > files
-  $ egrep '^tests/test-.*\.(t|py)$' files > test-files
-  $ egrep -v '^tests/test-.*\.(t|py)$' files > other-files
-  $ wc -l other-files
-  148 other-files
-  $ wc -l test-files
-  ??? test-files (glob)
-  $ fgrep debian files
+  $ tar -tzf hg?evolve-*.tar.gz | sed 's|^hg.evolve-[^/]*/||' | sort > ../files
+  $ grep -E '^tests/test-.*\.(t|py)$' ../files > ../test-files
+  $ grep -E -v '^tests/test-.*\.(t|py)$' ../files > ../other-files
+  $ wc -l ../other-files
+  ??? ../other-files (glob)
+  $ wc -l ../test-files
+  ??? ../test-files (glob)
+  $ grep -F debian ../files
   tests/test-check-debian.t
-  $ fgrep __init__.py files
+  $ grep -F __init__.py ../files
   hgext3rd/__init__.py
   hgext3rd/evolve/__init__.py
   hgext3rd/evolve/thirdparty/__init__.py
   hgext3rd/topic/__init__.py
-  $ fgrep common.sh files
+  $ grep -F common.sh ../files
   docs/tutorial/testlib/common.sh
   tests/testlib/common.sh
-  $ fgrep README files
+  $ grep -F README ../files
   README.rst
   docs/README
   docs/tutorial/README.rst
   hgext3rd/topic/README
 
-  $ egrep '(gitlab|contrib|hack|format-source)' files
+  $ grep -E '(gitlab|contrib|hack|format-source)' ../files
   [1]
-  $ fgrep legacy.py files
+  $ grep -F legacy.py ../files
   [1]
-  $ fgrep netlify files
+  $ grep -F netlify ../files
   [1]
+
+#if twine
+  $ twine --no-color check *
+  Checking hg?evolve-*.tar.gz: PASSED (glob)
+#endif
diff -pruN 11.1.3-1/tests/test-check-tag.t 11.1.9-1/tests/test-check-tag.t
--- 11.1.3-1/tests/test-check-tag.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-check-tag.t	2025-07-25 16:21:02.000000000 +0000
@@ -2,38 +2,35 @@
 
 Enable obsolescence to avoid the warning issue when obsmarkers are found
 
-  $ cat << EOF >> $HGRCPATH
-  > [experimental]
-  > evolution = all
-  > EOF
+  $ . "$RUNTESTDIR/helpers-testrepo.sh"
 
   $ cd "$TESTDIR"/..
 
 Checking all non-public tagged revisions up to the current commit, see our
 release checklist for more ideas
 
-  $ for node in `hg log --rev 'tag() and ::. and not public() and not desc("# no-check-commit")' --template '{node|short}\n'`; do
-  >   tags=`hg log --rev $node --template '{tags}\n'`
+  $ for node in `testrepohg log --rev 'tag() and ::. and not public() and not desc("# no-check-commit")' --template '{node|short}\n'`; do
+  >   tags=`testrepohg log --rev $node --template '{tags}\n'`
   >   if echo "$tags" | grep -q ' '; then
   >     echo "Revision $node is tagged multiple times: $tags"
   >   fi
-  >   branch=`hg log --rev $node --template '{branch}\n'`
+  >   branch=`testrepohg log --rev $node --template '{branch}\n'`
   >   if [ "$branch" != "stable" ]; then
   >     echo "Revision $node is not on stable branch: $branch"
   >   fi
   >   # Here we skip:
   >   # - pullbundle because it usually has no changes (so no version bump)
-  >   if hg grep --rev $node '^__version__ = .*\.dev' hgext3rd/evolve/ hgext3rd/topic/; then
+  >   if testrepohg grep --rev $node '^__version__ = .*\.dev' hgext3rd/evolve/ hgext3rd/topic/; then
   >     echo "Versions should not end with .dev at tagged revision $node"
   >   fi
-  >   entry=`hg cat --rev $node CHANGELOG | fgrep "$tags"`
+  >   entry=`testrepohg cat --rev $node CHANGELOG | grep -F "$tags"`
   >   if [ -z "$entry" ]; then
   >     echo "Revision $node has no CHANGELOG entry for $tags"
   >   fi
-  >   if echo "$entry" | egrep -vq ' -- [0-9]{4}-[0-9]{2}-[0-9]{2}'; then
+  >   if echo "$entry" | grep -E -vq ' -- [0-9]{4}-[0-9]{2}-[0-9]{2}'; then
   >     echo "CHANGELOG entry for $tags should have a date in YYYY-MM-DD format: $entry"
   >   fi
-  >   entry=`hg cat --rev $node debian/changelog | fgrep "$tags"`
+  >   entry=`testrepohg cat --rev $node debian/changelog | grep -F "$tags"`
   >   if [ -z "$entry" ]; then
   >     echo "Revision $node has no debian/changelog entry for $tags"
   >   fi
diff -pruN 11.1.3-1/tests/test-doctest.py 11.1.9-1/tests/test-doctest.py
--- 11.1.3-1/tests/test-doctest.py	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-doctest.py	2025-07-25 16:21:02.000000000 +0000
@@ -67,11 +67,15 @@ sys.path.insert(0, cwd)
 if not os.path.isdir(os.path.join(cwd, ".hg")):
     sys.exit(0)
 
-files = subprocess.check_output(
-    "hg files --print0 \"%s\"" % fileset,
-    shell=True,
-    cwd=cwd,
-).split(b'\0')
+files_cmd = 'hg files --print0 "%s"' % fileset
+
+# we prefer system hg for reading the repository, unless we're on python2
+# because then we assume that system hg is too old (this is not always true,
+# but it's an easy check and works well enough for us)
+if ispy3 and 'HGTEST_RESTOREENV':
+    files_cmd = '. $HGTEST_RESTOREENV; ' + files_cmd
+
+files = subprocess.check_output(files_cmd, shell=True, cwd=cwd).split(b'\0')
 
 if sys.version_info[0] >= 3:
     cwd = os.fsencode(cwd)
diff -pruN 11.1.3-1/tests/test-evolve-obshistory-amend-then-fold.t 11.1.9-1/tests/test-evolve-obshistory-amend-then-fold.t
--- 11.1.3-1/tests/test-evolve-obshistory-amend-then-fold.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-evolve-obshistory-amend-then-fold.t	2025-07-25 16:21:02.000000000 +0000
@@ -101,7 +101,13 @@ Check that obslog on head shows a cohere
   |
   x  b7ea6d14e664 (3) B1
   |    folded(description, parent, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000)
-  |      (No patch available, changesets rebased)
+  |      diff -r b7ea6d14e664 -r eb5a0daa2192+ changeset-description
+  |      --- a/changeset-description
+  |      +++ b/changeset-description
+  |      @@ -1,1 +1,1 @@
+  |      -B1
+  |      +C0
+  |
   |
   x  0dec01379d3b (2) B0
        reworded(description) as b7ea6d14e664 using amend by test (Thu Jan 01 00:00:00 1970 +0000)
@@ -154,7 +160,13 @@ Check that obslog on A0 with all option
   |
   x  b7ea6d14e664 (3) B1
   |    folded(description, parent, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000)
-  |      (No patch available, changesets rebased)
+  |      diff -r b7ea6d14e664 -r eb5a0daa2192+ changeset-description
+  |      --- a/changeset-description
+  |      +++ b/changeset-description
+  |      @@ -1,1 +1,1 @@
+  |      -B1
+  |      +C0
+  |
   |
   x  0dec01379d3b (2) B0
        reworded(description) as b7ea6d14e664 using amend by test (Thu Jan 01 00:00:00 1970 +0000)
diff -pruN 11.1.3-1/tests/test-evolve-obshistory-fold.t 11.1.9-1/tests/test-evolve-obshistory-fold.t
--- 11.1.3-1/tests/test-evolve-obshistory-fold.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-evolve-obshistory-fold.t	2025-07-25 16:21:02.000000000 +0000
@@ -93,7 +93,13 @@ Check that with all option, all changese
   |\
   x |  0dec01379d3b (2) B0
    /     folded(description, parent, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000)
-  |        (No patch available, changesets rebased)
+  |        diff -r 0dec01379d3b -r eb5a0daa2192+ changeset-description
+  |        --- a/changeset-description
+  |        +++ b/changeset-description
+  |        @@ -1,1 +1,1 @@
+  |        -B0
+  |        +C0
+  |
   |
   x  471f378eab4c (1) A0
        folded(description, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000)
@@ -116,7 +122,13 @@ the target
   $ hg obslog --hidden 0dec01379d3b --patch --no-origin
   x  0dec01379d3b (2) B0
        folded(description, parent, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000)
-         (No patch available, changesets rebased)
+         diff -r 0dec01379d3b -r eb5a0daa2192+ changeset-description
+         --- a/changeset-description
+         +++ b/changeset-description
+         @@ -1,1 +1,1 @@
+         -B0
+         +C0
+  
   
 Check that with all option, all changesets are shown
   $ hg obslog --hidden --all 0dec01379d3b --patch --no-origin
@@ -124,7 +136,13 @@ Check that with all option, all changese
   |\
   x |  0dec01379d3b (2) B0
    /     folded(description, parent, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000)
-  |        (No patch available, changesets rebased)
+  |        diff -r 0dec01379d3b -r eb5a0daa2192+ changeset-description
+  |        --- a/changeset-description
+  |        +++ b/changeset-description
+  |        @@ -1,1 +1,1 @@
+  |        -B0
+  |        +C0
+  |
   |
   x  471f378eab4c (1) A0
        folded(description, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000)
@@ -148,7 +166,13 @@ Check that obslog on the successor revis
   |\
   x |  0dec01379d3b (2) B0
    /     folded(description, parent, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000)
-  |        (No patch available, changesets rebased)
+  |        diff -r 0dec01379d3b -r eb5a0daa2192+ changeset-description
+  |        --- a/changeset-description
+  |        +++ b/changeset-description
+  |        @@ -1,1 +1,1 @@
+  |        -B0
+  |        +C0
+  |
   |
   x  471f378eab4c (1) A0
        folded(description, content) as eb5a0daa2192 using fold by test (Thu Jan 01 00:00:00 1970 +0000)
diff -pruN 11.1.3-1/tests/test-evolve-obshistory-lots-of-splits.t 11.1.9-1/tests/test-evolve-obshistory-lots-of-splits.t
--- 11.1.3-1/tests/test-evolve-obshistory-lots-of-splits.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-evolve-obshistory-lots-of-splits.t	2025-07-25 16:21:02.000000000 +0000
@@ -194,7 +194,12 @@ Actual test
   $ hg obslog de7290d8b885 --hidden --all --patch
   o  1ae8bc733a14 (4) A0
   |    split(parent, content) from de7290d8b885 using split by test (Thu Jan 01 00:00:00 1970 +0000)
-  |      (No patch available, changesets rebased)
+  |      diff -r 1ae8bc733a14 d
+  |      --- a/d	Thu Jan 01 00:00:00 1970 +0000
+  |      +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  |      @@ -1,1 +0,0 @@
+  |      -45
+  |
   |
   | o  337fec4d2edc (2) A0
   |/     split(parent, content) from de7290d8b885 using split by test (Thu Jan 01 00:00:00 1970 +0000)
@@ -217,11 +222,20 @@ Actual test
   |
   | @  c7f044602e9b (5) A0
   |/     split(parent, content) from de7290d8b885 using split by test (Thu Jan 01 00:00:00 1970 +0000)
-  |        (No patch available, changesets rebased)
   |
   | o  f257fde29c7a (3) A0
   |/     split(parent, content) from de7290d8b885 using split by test (Thu Jan 01 00:00:00 1970 +0000)
-  |        (No patch available, changesets rebased)
+  |        diff -r f257fde29c7a c
+  |        --- a/c	Thu Jan 01 00:00:00 1970 +0000
+  |        +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  |        @@ -1,1 +0,0 @@
+  |        -44
+  |        diff -r f257fde29c7a d
+  |        --- a/d	Thu Jan 01 00:00:00 1970 +0000
+  |        +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  |        @@ -1,1 +0,0 @@
+  |        -45
+  |
   |
   x  de7290d8b885 (1) A0
   
@@ -269,7 +283,6 @@ Actual test
   $ hg obslog c7f044602e9b --patch
   @  c7f044602e9b (5) A0
   |    split(parent, content) from de7290d8b885 using split by test (Thu Jan 01 00:00:00 1970 +0000)
-  |      (No patch available, changesets rebased)
   |
   x  de7290d8b885 (1) A0
   
@@ -365,7 +378,12 @@ Check that obslog on all heads shows a c
   $ hg obslog 2::5 --patch
   o  1ae8bc733a14 (4) A0
   |    split(parent, content) from de7290d8b885 using split by test (Thu Jan 01 00:00:00 1970 +0000)
-  |      (No patch available, changesets rebased)
+  |      diff -r 1ae8bc733a14 d
+  |      --- a/d	Thu Jan 01 00:00:00 1970 +0000
+  |      +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  |      @@ -1,1 +0,0 @@
+  |      -45
+  |
   |
   | o  337fec4d2edc (2) A0
   |/     split(parent, content) from de7290d8b885 using split by test (Thu Jan 01 00:00:00 1970 +0000)
@@ -388,11 +406,20 @@ Check that obslog on all heads shows a c
   |
   | @  c7f044602e9b (5) A0
   |/     split(parent, content) from de7290d8b885 using split by test (Thu Jan 01 00:00:00 1970 +0000)
-  |        (No patch available, changesets rebased)
   |
   | o  f257fde29c7a (3) A0
   |/     split(parent, content) from de7290d8b885 using split by test (Thu Jan 01 00:00:00 1970 +0000)
-  |        (No patch available, changesets rebased)
+  |        diff -r f257fde29c7a c
+  |        --- a/c	Thu Jan 01 00:00:00 1970 +0000
+  |        +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  |        @@ -1,1 +0,0 @@
+  |        -44
+  |        diff -r f257fde29c7a d
+  |        --- a/d	Thu Jan 01 00:00:00 1970 +0000
+  |        +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  |        @@ -1,1 +0,0 @@
+  |        -45
+  |
   |
   x  de7290d8b885 (1) A0
   
@@ -412,7 +439,12 @@ Check that obslog on all heads shows a c
   $ hg obslog 5 --all --patch
   o  1ae8bc733a14 (4) A0
   |    split(parent, content) from de7290d8b885 using split by test (Thu Jan 01 00:00:00 1970 +0000)
-  |      (No patch available, changesets rebased)
+  |      diff -r 1ae8bc733a14 d
+  |      --- a/d	Thu Jan 01 00:00:00 1970 +0000
+  |      +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  |      @@ -1,1 +0,0 @@
+  |      -45
+  |
   |
   | o  337fec4d2edc (2) A0
   |/     split(parent, content) from de7290d8b885 using split by test (Thu Jan 01 00:00:00 1970 +0000)
@@ -435,11 +467,20 @@ Check that obslog on all heads shows a c
   |
   | @  c7f044602e9b (5) A0
   |/     split(parent, content) from de7290d8b885 using split by test (Thu Jan 01 00:00:00 1970 +0000)
-  |        (No patch available, changesets rebased)
   |
   | o  f257fde29c7a (3) A0
   |/     split(parent, content) from de7290d8b885 using split by test (Thu Jan 01 00:00:00 1970 +0000)
-  |        (No patch available, changesets rebased)
+  |        diff -r f257fde29c7a c
+  |        --- a/c	Thu Jan 01 00:00:00 1970 +0000
+  |        +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  |        @@ -1,1 +0,0 @@
+  |        -44
+  |        diff -r f257fde29c7a d
+  |        --- a/d	Thu Jan 01 00:00:00 1970 +0000
+  |        +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  |        @@ -1,1 +0,0 @@
+  |        -45
+  |
   |
   x  de7290d8b885 (1) A0
   
diff -pruN 11.1.3-1/tests/test-evolve-obshistory-split.t 11.1.9-1/tests/test-evolve-obshistory-split.t
--- 11.1.3-1/tests/test-evolve-obshistory-split.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-evolve-obshistory-split.t	2025-07-25 16:21:02.000000000 +0000
@@ -182,7 +182,6 @@ With the all option, it should show all
   | @  f257fde29c7a (3) A0
   |/     split(parent, content) from 471597cad322 using split by test (Thu Jan 01 00:00:00 1970 +0000)
   |        note: testing split
-  |        (No patch available, changesets rebased)
   |
   x  471597cad322 (1) A0
   
@@ -192,7 +191,6 @@ the split one
   @  f257fde29c7a (3) A0
   |    split(parent, content) from 471597cad322 using split by test (Thu Jan 01 00:00:00 1970 +0000)
   |      note: testing split
-  |      (No patch available, changesets rebased)
   |
   x  471597cad322 (1) A0
   
@@ -211,7 +209,6 @@ With the all option, it should show all
   | @  f257fde29c7a (3) A0
   |/     split(parent, content) from 471597cad322 using split by test (Thu Jan 01 00:00:00 1970 +0000)
   |        note: testing split
-  |        (No patch available, changesets rebased)
   |
   x  471597cad322 (1) A0
   
@@ -251,7 +248,6 @@ Check that obslog on both successors aft
   | @  f257fde29c7a (3) A0
   |/     split(parent, content) from 471597cad322 using split by test (Thu Jan 01 00:00:00 1970 +0000)
   |        note: testing split
-  |        (No patch available, changesets rebased)
   |
   x  471597cad322 (1) A0
   
diff -pruN 11.1.3-1/tests/test-evolve-phase-divergence.t 11.1.9-1/tests/test-evolve-phase-divergence.t
--- 11.1.3-1/tests/test-evolve-phase-divergence.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-evolve-phase-divergence.t	2025-07-25 16:21:02.000000000 +0000
@@ -1832,7 +1832,39 @@ to be preserved.
   $ hg obslog --patch
   @  9eebcb77a7e2 (3) phase-divergent update to 3074c7249d20:
   |    rewritten(description, parent, content) from 599454370881 using evolve by test (Thu Jan 01 00:00:00 1970 +0000)
-  |      (No patch available, changesets rebased)
+  |      diff -r 599454370881+ -r 9eebcb77a7e2 changeset-description
+  |      --- a/changeset-description
+  |      +++ b/changeset-description
+  |      @@ -1,1 +1,3 @@
+  |      +phase-divergent update to 3074c7249d20:
+  |      +
+  |       E2
+  |
+  |      diff -r 9eebcb77a7e2 letters
+  |      --- a/letters	Thu Jan 01 00:00:00 1970 +0000
+  |      +++ b/letters	Thu Jan 01 00:00:00 1970 +0000
+  |      @@ -1,7 +1,7 @@
+  |       a
+  |       b
+  |       c
+  |      -D
+  |      +d
+  |       e
+  |       f
+  |       g
+  |      diff -r 9eebcb77a7e2 numbers
+  |      --- a/numbers	Thu Jan 01 00:00:00 1970 +0000
+  |      +++ b/numbers	Thu Jan 01 00:00:00 1970 +0000
+  |      @@ -1,7 +1,7 @@
+  |       1
+  |       2
+  |       3
+  |      -four
+  |      +4
+  |       5
+  |       6
+  |       seven
+  |
   |
   x  599454370881 (2) E2
   |    rewritten(description, content) from 3074c7249d20 using amend by test (Thu Jan 01 00:00:00 1970 +0000)
diff -pruN 11.1.3-1/tests/test-evolve-public-content-divergent-corner-cases.t 11.1.9-1/tests/test-evolve-public-content-divergent-corner-cases.t
--- 11.1.3-1/tests/test-evolve-public-content-divergent-corner-cases.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-evolve-public-content-divergent-corner-cases.t	2025-07-25 16:21:02.000000000 +0000
@@ -382,7 +382,29 @@ Change phase to public for one head:
   |
   | *  e568fd1029bb (4) added c e
   |/     rewritten(description, parent, content) from 9150fe93bec6 using prune by test (Thu Jan 01 00:00:00 1970 +0000)
-  |        (No patch available, changesets rebased)
+  |        diff -r 9150fe93bec6+ -r e568fd1029bb changeset-description
+  |        --- a/changeset-description
+  |        +++ b/changeset-description
+  |        @@ -1,1 +1,1 @@
+  |        -added d
+  |        +added c e
+  |
+  |        diff -r e568fd1029bb c
+  |        --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  |        +++ b/c	Thu Jan 01 00:00:00 1970 +0000
+  |        @@ -0,0 +1,1 @@
+  |        +cfoo
+  |        diff -r e568fd1029bb d
+  |        --- a/d	Thu Jan 01 00:00:00 1970 +0000
+  |        +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  |        @@ -1,1 +0,0 @@
+  |        -d
+  |        diff -r e568fd1029bb e
+  |        --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  |        +++ b/e	Thu Jan 01 00:00:00 1970 +0000
+  |        @@ -0,0 +1,1 @@
+  |        +e
+  |
   |
   x  9150fe93bec6 (3) added d
   
diff -pruN 11.1.3-1/tests/test-evolve-templates.t 11.1.9-1/tests/test-evolve-templates.t
--- 11.1.3-1/tests/test-evolve-templates.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-evolve-templates.t	2025-07-25 16:21:02.000000000 +0000
@@ -1424,7 +1424,7 @@ Diverge one of the split commit
   working directory parent is obsolete! (4a004186e638)
   (use 'hg evolve' to update to its successor: b18bc8331526)
   $ hg commit --amend -m "Add B only"
-  4 new content-divergent changesets
+  2 new content-divergent changesets
 
   $ hg log -G
   @  changeset:   9:0b997eb7ceee
@@ -1445,7 +1445,7 @@ Diverge one of the split commit
   | *  changeset:   7:ba2ed02b0c9a
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  instability: orphan, content-divergent
+  | |  instability: orphan
   | |  summary:     Add A,B,C
   | |
   | x  changeset:   6:4a004186e638
@@ -1455,11 +1455,10 @@ Diverge one of the split commit
   |    obsolete:    reworded using amend as 9:0b997eb7ceee
   |    summary:     Add A,B,C
   |
-  *  changeset:   5:dd800401bd8c
+  o  changeset:   5:dd800401bd8c
   |  parent:      3:f897c6137566
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  instability: content-divergent
   |  summary:     Add A,B,C
   |
   o  changeset:   3:f897c6137566
@@ -1495,7 +1494,7 @@ Check templates
   |      Fate: reworded using amend as 8:b18bc8331526
   |      Fate: reworded using amend as 9:0b997eb7ceee
   |
-  *  dd800401bd8c
+  o  dd800401bd8c
   |
   o  f897c6137566
   |
@@ -1513,7 +1512,7 @@ Check templates
   | x  4a004186e638
   |/     Obsfate: reworded using amend as 8:b18bc8331526; reworded using amend as 9:0b997eb7ceee
   |
-  *  dd800401bd8c
+  o  dd800401bd8c
   |
   o  f897c6137566
   |
@@ -1544,7 +1543,7 @@ Check templates
   |      Fate: reworded using amend as 9:0b997eb7ceee
   |      Origin: split from 4:9bd10a0775e4
   |
-  *  dd800401bd8c
+  o  dd800401bd8c
   |    Predecessors: 4:9bd10a0775e4
   |    semi-colon: 4:9bd10a0775e4
   |    Origin: split from 4:9bd10a0775e4
@@ -1592,7 +1591,7 @@ Check templates
   |/     Obsfate: reworded using amend as 8:b18bc8331526; reworded using amend as 9:0b997eb7ceee
   |      Obsorigin: split from 4:9bd10a0775e4
   |
-  *  dd800401bd8c
+  o  dd800401bd8c
   |    Obsorigin: split from 4:9bd10a0775e4
   |
   | x  9bd10a0775e4
@@ -1620,7 +1619,7 @@ Check templates
   $ hg rebase -r 7 -d 8 --config extensions.rebase=
   rebasing 7:ba2ed02b0c9a "Add A,B,C"
   $ hg tlog
-  *  eceed8f98ffc
+  o  eceed8f98ffc
   |    Predecessors: 4:9bd10a0775e4
   |    semi-colon: 4:9bd10a0775e4
   |    Origin: rewritten using rebase from 4:9bd10a0775e4
@@ -1635,7 +1634,7 @@ Check templates
   |      semi-colon: 4:9bd10a0775e4
   |      Origin: rewritten using amend from 4:9bd10a0775e4
   |
-  *  dd800401bd8c
+  o  dd800401bd8c
   |    Predecessors: 4:9bd10a0775e4
   |    semi-colon: 4:9bd10a0775e4
   |    Origin: split from 4:9bd10a0775e4
@@ -1651,7 +1650,7 @@ Check templates
   o  ea207398892e
   
   $ hg fateoriginlog
-  *  eceed8f98ffc
+  o  eceed8f98ffc
   |    Obsorigin: rewritten using rebase from 4:9bd10a0775e4
   |
   | *  0b997eb7ceee
@@ -1660,7 +1659,7 @@ Check templates
   * |  b18bc8331526
   |/     Obsorigin: rewritten using amend from 4:9bd10a0775e4
   |
-  *  dd800401bd8c
+  o  dd800401bd8c
   |    Obsorigin: split from 4:9bd10a0775e4
   |
   | @  9bd10a0775e4
diff -pruN 11.1.3-1/tests/test-extension-isolation.t 11.1.9-1/tests/test-extension-isolation.t
--- 11.1.3-1/tests/test-extension-isolation.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-extension-isolation.t	2025-07-25 16:21:02.000000000 +0000
@@ -117,34 +117,34 @@ make sure repos don't affect each other
 Check evolve isolation
 -----------------------
 
-  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-no-ext | egrep 'topics|evoext'
+  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-no-ext | grep -E 'topics|evoext'
   [1]
-  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-evo | egrep 'topics|evoext'
+  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-evo | grep -E 'topics|evoext'
     _evoext_getbundle_obscommon
     _evoext_obshashrange_v1
-  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-no-ext | egrep 'topics|evoext'
+  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-no-ext | grep -E 'topics|evoext'
   [1]
 
 Check topic isolation
 ---------------------
 
-  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-no-ext | egrep 'topics|evoext'
+  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-no-ext | grep -E 'topics|evoext'
   [1]
-  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-topic | egrep 'topics|evoext'
+  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-topic | grep -E 'topics|evoext'
     _exttopics_heads
     ext-topics-publish=all
     ext-topics-tns-heads
     topics
     topics-namespaces
-  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-no-ext | egrep 'topics|evoext'
+  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-no-ext | grep -E 'topics|evoext'
   [1]
 
 Check coupled isolation
 -----------------------
 
-  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-no-ext | egrep 'topics|evoext'
+  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-no-ext | grep -E 'topics|evoext'
   [1]
-  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-both | egrep 'topics|evoext'
+  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-both | grep -E 'topics|evoext'
     _evoext_getbundle_obscommon
     _evoext_obshashrange_v1
     _exttopics_heads
@@ -152,19 +152,19 @@ Check coupled isolation
     ext-topics-tns-heads
     topics
     topics-namespaces
-  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-evo | egrep 'topics|evoext'
+  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-evo | grep -E 'topics|evoext'
     _evoext_getbundle_obscommon
     _evoext_obshashrange_v1
-  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-topic | egrep 'topics|evoext'
+  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-topic | grep -E 'topics|evoext'
     _exttopics_heads
     ext-topics-publish=all
     ext-topics-tns-heads
     topics
     topics-namespaces
-  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-evo | egrep 'topics|evoext'
+  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-evo | grep -E 'topics|evoext'
     _evoext_getbundle_obscommon
     _evoext_obshashrange_v1
-  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-no-ext | egrep 'topics|evoext'
+  $ hg debugcapabilities http://$LOCALIP:$HGPORT/repo-no-ext | grep -E 'topics|evoext'
   [1]
 
 Final cleanup
diff -pruN 11.1.3-1/tests/test-fixup.t 11.1.9-1/tests/test-fixup.t
--- 11.1.3-1/tests/test-fixup.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-fixup.t	2025-07-25 16:21:02.000000000 +0000
@@ -12,6 +12,7 @@ Testing `hg fixup` command
   > git = 1
   > EOF
 
+#if hg69
   $ hg help fixup
   hg fixup [OPTION]... [-r] REV
   
@@ -19,22 +20,22 @@ Testing `hg fixup` command
   
   add working directory changes to an arbitrary revision
   
-      A new changeset will be created, superseding the one specified. The new
-      changeset will combine working directory changes with the changes in the
-      target revision.
-  
-      This operation requires the working directory changes to be relocated onto
-      the target revision, which might result in merge conflicts.
-  
-      If fixup is interrupted to manually resolve a conflict, it can be
-      continued with --continue/-c, or aborted with --abort.
-  
-      Note that this command is fairly new and its behavior is still
-      experimental. For example, the working copy will be left on a temporary,
-      obsolete commit containing the fixed-up changes after the operation. This
-      might change in the future.
+  A new changeset will be created, superseding the one specified. The new
+  changeset will combine working directory changes with the changes in the
+  target revision.
+  
+  This operation requires the working directory changes to be relocated onto the
+  target revision, which might result in merge conflicts.
+  
+  If fixup is interrupted to manually resolve a conflict, it can be continued
+  with --continue/-c, or aborted with --abort.
+  
+  Note that this command is fairly new and its behavior is still experimental.
+  For example, the working copy will be left on a temporary, obsolete commit
+  containing the fixed-up changes after the operation. This might change in the
+  future.
   
-      Returns 0 on success, 1 if nothing changed.
+  Returns 0 on success, 1 if nothing changed.
   
   options:
   
@@ -43,6 +44,7 @@ Testing `hg fixup` command
       --abort    abort an interrupted fixup
   
   (some details hidden, use --verbose to show complete help)
+#endif
 
 Simple cases
 ------------
diff -pruN 11.1.3-1/tests/test-pick.t 11.1.9-1/tests/test-pick.t
--- 11.1.3-1/tests/test-pick.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-pick.t	2025-07-25 16:21:02.000000000 +0000
@@ -25,15 +25,15 @@ Test for the pick command
 
   $ hg init repo
   $ cd repo
-  $ hg help pick
+  $ hg help pick | sed 's/^    //'
   hg pick [OPTION]... [-r] REV
   
   aliases: grab
   
   move a commit onto the working directory parent and update to it.
   
-      The resulting changeset will have the current active topic. If there's no
-      active topic set, the resulting changeset will also not have any topic.
+  The resulting changeset will have the current active topic. If there's no
+  active topic set, the resulting changeset will also not have any topic.
   
   options:
   
diff -pruN 11.1.3-1/tests/test-split.t 11.1.9-1/tests/test-split.t
--- 11.1.3-1/tests/test-split.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-split.t	2025-07-25 16:21:02.000000000 +0000
@@ -60,7 +60,7 @@ Creating commits with the number of spli
   examine changes to '_a'?
   (enter ? for help) [Ynesfdaq?] y
   
-  @@ -1,0 +2,1 @@
+  @@ -1,0 +2,1 @@* (glob)
   +change to a
   record change 1/2 to '_a'?
   (enter ? for help) [Ynesfdaq?] y
@@ -188,7 +188,7 @@ Split a revision specified with -r
   examine changes to '_b'?
   (enter ? for help) [Ynesfdaq?] y
   
-  @@ -1,0 +2,1 @@
+  @@ -1,0 +2,1 @@* (glob)
   +change to b
   record change 1/2 to '_b'?
   (enter ? for help) [Ynesfdaq?] y
diff -pruN 11.1.3-1/tests/test-stack-split-s0.t 11.1.9-1/tests/test-stack-split-s0.t
--- 11.1.3-1/tests/test-stack-split-s0.t	1970-01-01 00:00:00.000000000 +0000
+++ 11.1.9-1/tests/test-stack-split-s0.t	2025-07-25 16:21:02.000000000 +0000
@@ -0,0 +1,69 @@
+Testing the case when s0 is obsolete, and has multiple successors that are
+topological heads
+
+  $ . "$TESTDIR/testlib/common.sh"
+
+  $ cat << EOF >> "$HGRCPATH"
+  > [extensions]
+  > evolve =
+  > topic =
+  > EOF
+
+  $ hg init split-s0
+  $ cd split-s0
+
+  $ mkcommit ROOT
+  $ mkcommit A
+
+creating a small stack for the experiment
+
+  $ hg branch cool-stack
+  marked working directory as branch cool-stack
+  (branches are permanent and global, did you want a bookmark?)
+  $ mkcommit J
+  $ mkcommit K
+  $ mkcommit L
+
+right now everything is stable, including s0
+
+  $ hg stack
+  ### target: cool-stack (branch)
+  s3@ L (current)
+  s2: K
+  s1: J
+  s0^ A (base)
+
+destabilize the stack by obsoleting s0 with 2 successors
+
+  $ hg up 'desc(ROOT)' -q
+  $ mkcommit X
+  created new head
+  (consider using topic for lightweight branches. See 'hg help topic')
+  $ hg up 'desc(ROOT)' -q
+  $ mkcommit Y
+  created new head
+  (consider using topic for lightweight branches. See 'hg help topic')
+
+  $ hg prune --split --rev 'desc(A)' --successor 'desc(X)' --successor 'desc(Y)'
+  1 changesets pruned
+  3 new orphan changesets
+
+the 2 successors are 2 different heads (the revset is taken from _singlesuccessor function)
+
+  $ hg log -r 'heads((desc(X)+desc(Y))::(desc(X)+desc(Y)))' -GT '{desc}\n'
+  @  Y
+  |
+  ~
+  o  X
+  |
+  ~
+
+we choose one of the successors for s0, this is better than failing to show the stack at all
+
+  $ hg up 'desc(L)' -q
+  $ hg stack
+  ### target: cool-stack (branch)
+  s3@ L (current orphan)
+  s2$ K (orphan)
+  s1$ J (orphan)
+  s0^ Y (base)
diff -pruN 11.1.3-1/tests/test-topic-flow-publish-flag.t 11.1.9-1/tests/test-topic-flow-publish-flag.t
--- 11.1.3-1/tests/test-topic-flow-publish-flag.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-topic-flow-publish-flag.t	2025-07-25 16:21:02.000000000 +0000
@@ -439,9 +439,12 @@ checking branch format in branchcache on
 
   $ cd $TESTTMP/bare-client/.hg/cache/
   $ grep double branch2* | sort
+  branch2-base:* o double//slash (glob) (hg68 !)
   branch2-immutable:* o double//slash (glob)
+  branch2-served:* o double//slash (glob) (hg68 !)
 
   $ cd $TESTTMP/bare-branch-server/.hg/cache/
   $ grep double branch2* | sort
   branch2-base:* o double//slash (glob)
   branch2-immutable:* o double//slash (glob)
+  branch2-served:* o double//slash (glob) (hg68 !)
diff -pruN 11.1.3-1/tests/test-topic-issue6406.t 11.1.9-1/tests/test-topic-issue6406.t
--- 11.1.3-1/tests/test-topic-issue6406.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-topic-issue6406.t	2025-07-25 16:21:02.000000000 +0000
@@ -53,9 +53,9 @@ https://foss.heptapod.net/mercurial/evol
 
 This is what the help text says about this issue
 
-  $ hg help pick | grep 'active topic'
-      The resulting changeset will have the current active topic. If there's no
-      active topic set, the resulting changeset will also not have any topic.
+  $ hg help pick | grep 'active topic' | sed 's/^    //'
+  The resulting changeset will have the current active topic. If there's no
+  active topic set, the resulting changeset will also not have any topic.
 
 wdir has no active topic: pick should clear topic of the resulting cset
 
diff -pruN 11.1.3-1/tests/test-topic-issue6841.t 11.1.9-1/tests/test-topic-issue6841.t
--- 11.1.3-1/tests/test-topic-issue6841.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-topic-issue6841.t	2025-07-25 16:21:02.000000000 +0000
@@ -43,8 +43,7 @@ cloning via ssh to use wire protocol
 
 on-disk caches are using bare branch names only
 
-  $ f -H .hg/cache/rbc-names-v1
-  .hg/cache/rbc-names-v1:
+  $ f -Hq .hg/cache/rbc-names-v?
   0000: 64 65 66 61 75 6c 74                            |default|
   $ grep topic-foo .hg/cache/*
   [1]
diff -pruN 11.1.3-1/tests/test-topic-tutorial.t 11.1.9-1/tests/test-topic-tutorial.t
--- 11.1.3-1/tests/test-topic-tutorial.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-topic-tutorial.t	2025-07-25 16:21:02.000000000 +0000
@@ -6,12 +6,12 @@ This Mercurial configuration example is
 
 .. Various setup
 
-  $ . "$TESTDIR/testlib/topic_setup.sh"
+  $ . "$TESTDIR/testlib/common.sh" #rest-ignore
   $ cat >> $HGRCPATH << EOF
-  > [experimental]
-  > evolution=all
   > [extensions]
-  > evolve=
+  > evolve =
+  > rebase =
+  > topic =
   > EOF
 
   $ hg init server
@@ -20,7 +20,7 @@ This Mercurial configuration example is
 
   $ cat >> .hg/hgrc << EOF
   > [ui]
-  > user= Shopping Master
+  > user = Shopping Master
   > EOF
 
   $ cat >> shopping << EOF
@@ -43,7 +43,7 @@ This Mercurial configuration example is
   $ cd client
   $ cat >> .hg/hgrc << EOF
   > [ui]
-  > user= Tutorial User
+  > user = Tutorial User
   > EOF
 #if docgraph-ext
   $ . "$TESTDIR/testlib/docgraph_setup.sh" #rest-ignore
@@ -100,7 +100,7 @@ within a topic. Creating a new topic is
   marked working directory as topic: food
 
 Much like a named branch, our topic is active but it does not contain any
-changeset yet:
+changesets yet:
 
   $ hg topics
    * food (0 changesets)
@@ -147,7 +147,7 @@ Our next commit will be part of the acti
 
   $ cat >> shopping << EOF
   > Egg
-  > Suggar
+  > Sugar
   > Vinegar
   > Oil
   > EOF
@@ -157,7 +157,7 @@ Our next commit will be part of the acti
   (see 'hg help topics' for more information)
 
   $ hg log --graph --rev 'topic("food")'
-  @  changeset:   1:13900241408b
+  @  changeset:   1:9e90e00c084b
   |  tag:         tip
   ~  topic:       food
      user:        test
@@ -198,14 +198,14 @@ And future commits will be part of that
   $ hg commit -m "adding fruits"
 
   $ hg log --graph --rev 'topic("food")'
-  @  changeset:   2:287de11b401f
+  @  changeset:   2:a25aaa6b9385
   |  tag:         tip
   |  topic:       food
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding fruits
   |
-  o  changeset:   1:13900241408b
+  o  changeset:   1:9e90e00c084b
   |  topic:       food
   ~  user:        test
      date:        Thu Jan 01 00:00:00 1970 +0000
@@ -268,14 +268,14 @@ Note that ``default`` (name of the branc
 changeset of default without a topic:
 
   $ hg log --graph
-  o  changeset:   2:287de11b401f
+  o  changeset:   2:a25aaa6b9385
   |  tag:         tip
   |  topic:       food
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding fruits
   |
-  o  changeset:   1:13900241408b
+  o  changeset:   1:9e90e00c084b
   |  topic:       food
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
@@ -395,13 +395,13 @@ the latest update from the main server:
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     Adding clothes
   |
-  | o  changeset:   2:287de11b401f
+  | o  changeset:   2:a25aaa6b9385
   | |  topic:       food
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     adding fruits
   | |
-  | @  changeset:   1:13900241408b
+  | @  changeset:   1:9e90e00c084b
   |/   topic:       food
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
@@ -488,21 +488,21 @@ But the topic will see that branch head
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
   $ hg rebase
-  rebasing 1:13900241408b food "adding condiments"
+  rebasing 1:9e90e00c084b food "adding condiments"
   merging shopping
   switching to topic food
-  rebasing 2:287de11b401f food "adding fruits"
+  rebasing 2:a25aaa6b9385 food "adding fruits"
   merging shopping
 
   $ hg log --graph
-  @  changeset:   5:2d50db8b5b4c
+  @  changeset:   5:fec062fcfcfa
   |  tag:         tip
   |  topic:       food
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding fruits
   |
-  o  changeset:   4:4011b46eeb33
+  o  changeset:   4:d3a1ea2a0337
   |  topic:       food
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
@@ -580,9 +580,9 @@ But the topic will see that branch head
 There exists a template keyword named "topic" which can be used
 
   $ hg log -GT "{rev}:{node|short} {topic}\n {desc}"
-  @  5:2d50db8b5b4c food
+  @  5:fec062fcfcfa food
   |   adding fruits
-  o  4:4011b46eeb33 food
+  o  4:d3a1ea2a0337 food
   |   adding condiments
   o  3:6104862e8b84
   |   Adding clothes
@@ -618,13 +618,13 @@ note that it is now devoid of any commit
   s0^ adding fruits (base current)
 
   $ hg log --graph
-  @  changeset:   5:2d50db8b5b4c
+  @  changeset:   5:fec062fcfcfa
   |  tag:         tip
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding fruits
   |
-  o  changeset:   4:4011b46eeb33
+  o  changeset:   4:d3a1ea2a0337
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding condiments
@@ -713,7 +713,7 @@ From there, the topic has been completel
 Keep working within topics
 ==========================
 
-Making sure all your new local commit are made within a topic will help you
+Making sure all your new local commits are made within a topic will help you
 organize your work. It is possible to ensure this through the Mercurial
 configuration.
 
@@ -724,10 +724,10 @@ For this tutorial, we'll add the config
   > topic-mode = enforce
   > EOF
 
-You can also use `hg config --edit` to update your mercurial configuration.
+You can also use `hg config --edit` to update your Mercurial configuration.
 
 
-Once enforcement is turned on. New local commit will be denied if no topic is active.
+Once enforcement is turned on, new local commits will be denied if no topic is active.
 
   $ echo sickle >> shopping
   $ hg commit -m 'Adding sickle'
@@ -764,7 +764,7 @@ tools to the shopping list within a new
   $ echo drill >> shopping
   $ hg commit -m 'Adding drill'
 
-But we are not sure we will actually go to the hardware store, so in the
+But we are not sure if we will actually go to the hardware store, so in the
 meantime, we want to extend the list with drinks. We go back to the official
 default branch and start a new topic:
 
@@ -815,7 +815,7 @@ between them will be attempted by defaul
   nothing to rebase
   [1]
 
-We simulate independant contributions to the repo with this
+We simulate independent contributions to the repo with this
 activity:
 
   $ cd ../server
@@ -832,7 +832,7 @@ activity:
   $ hg commit -m 'add a pair of shoes'
   $ cd ../client
 
-Let's discover what other people did contribute:
+Let's discover what other people have contributed:
 
   $ hg pull
   pulling from $TESTTMP/server (glob)
@@ -841,62 +841,62 @@ Let's discover what other people did con
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 1 files (+1 heads)
-  new changesets f2d6cacc6115:fbff9bc37a43
+  new changesets bbfb218049cd:033bfcc0ecb0
   (run 'hg heads' to see heads)
 
 There are new changes! We can simply use ``hg rebase`` to update our
 changeset on top of the latest:
 
   $ hg log -G
-  o  changeset:   12:fbff9bc37a43
+  o  changeset:   12:033bfcc0ecb0
   |  tag:         tip
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     add a pair of shoes
   |
-  o  changeset:   11:f2d6cacc6115
-  |  parent:      5:2d50db8b5b4c
+  o  changeset:   11:bbfb218049cd
+  |  parent:      5:fec062fcfcfa
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     add a coat
   |
-  | o  changeset:   10:70dfa201ed73
+  | o  changeset:   10:0b8a99ba9213
   | |  topic:       drinks
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     Adding orange juice
   | |
-  | o  changeset:   9:8dfa45bd5e0c
+  | o  changeset:   9:213e97c6cd8a
   |/   topic:       drinks
-  |    parent:      5:2d50db8b5b4c
+  |    parent:      5:fec062fcfcfa
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    summary:     Adding apple juice
   |
-  | @  changeset:   8:34255b455dac
+  | @  changeset:   8:9ef4e4f40a79
   | |  topic:       tools
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     Adding drill
   | |
-  | o  changeset:   7:cffff85af537
+  | o  changeset:   7:c1d9846a234f
   | |  topic:       tools
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     Adding saw
   | |
-  | o  changeset:   6:183984ef46d1
+  | o  changeset:   6:6d6f38ff45f0
   |/   topic:       tools
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    summary:     Adding hammer
   |
-  o  changeset:   5:2d50db8b5b4c
+  o  changeset:   5:fec062fcfcfa
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding fruits
   |
-  o  changeset:   4:4011b46eeb33
+  o  changeset:   4:d3a1ea2a0337
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding condiments
@@ -1055,49 +1055,49 @@ changeset on top of the latest:
 #endif
 
   $ hg rebase
-  rebasing 6:183984ef46d1 tools "Adding hammer"
+  rebasing 6:6d6f38ff45f0 tools "Adding hammer"
   merging shopping
   switching to topic tools
-  rebasing 7:cffff85af537 tools "Adding saw"
+  rebasing 7:c1d9846a234f tools "Adding saw"
   merging shopping
-  rebasing 8:34255b455dac tools "Adding drill"
+  rebasing 8:9ef4e4f40a79 tools "Adding drill"
   merging shopping
 
-But what about the other topic? You can use 'hg topics --verbose' to see
+But what about the other topic? You can use ``hg topics --verbose`` to see
 information about all the topics:
 
   $ hg topics --verbose
      drinks (on branch: default, 2 changesets, 2 behind)
    * tools  (on branch: default, 3 changesets)
 
-The "2 behind" is telling you that there are 2 new changesets over the base of the topic.
+The "2 behind" is telling you that there are 2 new changesets on top of the base of the topic.
 
 Pushing that topic would create a new head, and therefore will be prevented:
 
   $ hg push --rev drinks
   pushing to $TESTTMP/server (glob)
   searching for changes
-  abort: push creates new remote head 70dfa201ed73
+  abort: push creates new remote head 0b8a99ba9213
   (merge or see 'hg help push' for details about pushing new heads)
   [20]
 
 
 Even after a rebase, pushing all active topics at the same time would publish
-them to the default branch, and then mercurial would complain about the
+them to the default branch, and then Mercurial would complain about the
 multiple *public* heads it would create on that branch:
 
   $ hg rebase -b drinks
-  rebasing 9:8dfa45bd5e0c drinks "Adding apple juice"
+  rebasing 9:213e97c6cd8a drinks "Adding apple juice"
   merging shopping
   switching to topic drinks
-  rebasing 10:70dfa201ed73 drinks "Adding orange juice"
+  rebasing 10:0b8a99ba9213 drinks "Adding orange juice"
   merging shopping
   switching to topic tools
 
   $ hg push
   pushing to $TESTTMP/server (glob)
   searching for changes
-  abort: push creates new remote head 4cd7c1591a67
+  abort: push creates new remote head 56656c6d1153
   (merge or see 'hg help push' for details about pushing new heads)
   [20]
 
@@ -1113,7 +1113,7 @@ branch head as we just saw in the previo
   added 2 changesets with 2 changes to 1 files
   2 new obsolescence markers
 
-The published topic has now faded out, and the other is now marked as
+The published topic has now faded out, and the other is now marked as being
 "behind":
 
   $ hg topics --verbose
@@ -1133,7 +1133,7 @@ Working Within Your Stack
 Navigating within your stack
 ----------------------------
 
-As we saw before `stack` displays changesets on your current topic in a clean way:
+As we saw before ``stack`` displays changesets on your current topic in a clean way:
 
   $ hg topics --verbose
    * tools (on branch: default, 3 changesets, 2 behind)
@@ -1146,9 +1146,9 @@ As we saw before `stack` displays change
   s1: Adding hammer
   s0^ add a pair of shoes (base)
 
-You can navigate in your current stack with `previous` and `next`.
+You can navigate in your current stack with ``previous`` and ``next``.
 
-`previous` will bring you back to the parent of the topic head.
+``previous`` will bring you back to the parent of the topic head.
 
   $ hg previous
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -1162,7 +1162,7 @@ You can navigate in your current stack w
   s1: Adding hammer
   s0^ add a pair of shoes (base)
 
-`next` will move you forward to the topic head.
+``next`` will move you forward to the topic head.
 
   $ hg next
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -1176,7 +1176,7 @@ You can navigate in your current stack w
   s1: Adding hammer
   s0^ add a pair of shoes (base)
 
-You can also directly jump to a changeset within your stack with the revset `t#`.
+You can also directly jump to a changeset within your stack with the revset ``s<number>``.
 
   $ hg update s1
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -1209,47 +1209,47 @@ Understanding the current situation with
 it shows too many things:
 
   $ hg log -G -r "s0::"
-  @  changeset:   18:b7509bd417f8
+  @  changeset:   18:2c1a47a5c075
   |  tag:         tip
   |  topic:       tools
-  |  parent:      12:fbff9bc37a43
+  |  parent:      12:033bfcc0ecb0
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     Adding hammer to the shopping list
   |
-  | o  changeset:   17:4cd7c1591a67
+  | o  changeset:   17:9dc8cec494f3
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     Adding orange juice
   | |
-  | o  changeset:   16:20759cb47ff8
-  |/   parent:      12:fbff9bc37a43
+  | o  changeset:   16:9dfd6068e8e7
+  |/   parent:      12:033bfcc0ecb0
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    summary:     Adding apple juice
   |
-  | *  changeset:   15:bb1e6254f532
+  | *  changeset:   15:56656c6d1153
   | |  topic:       tools
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  instability: orphan
   | |  summary:     Adding drill
   | |
-  | *  changeset:   14:d4f97f32f8a1
+  | *  changeset:   14:a0ec1a6dcdce
   | |  topic:       tools
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  instability: orphan
   | |  summary:     Adding saw
   | |
-  | x  changeset:   13:a8ab3599d53d
+  | x  changeset:   13:dcb888ba1623
   |/   topic:       tools
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    reworded using amend as 18:b7509bd417f8
+  |    obsolete:    reworded using amend as 18:2c1a47a5c075
   |    summary:     Adding hammer
   |
-  o  changeset:   12:fbff9bc37a43
+  o  changeset:   12:033bfcc0ecb0
   |  user:        test
   ~  date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     add a pair of shoes
@@ -1364,14 +1364,14 @@ Fortunately stack shows you a better vis
   s1@ Adding hammer to the shopping list (current)
   s0^ add a pair of shoes (base)
 
-It's easy to stabilize the situation, `next` has an `--evolve` option.  It will
-do the necessary relocation of `s2` and `s3` over the new `s1` without having
-to do that rebase by hand.:
+It's easy to stabilize the situation, ``next`` has an ``--evolve`` option
+(turned on by default nowadays). It will do the necessary relocation of `s2`
+and `s3` over the new `s1` without having to do that rebase by hand:
 
   $ hg next --evolve
   move:[s2] Adding saw
   atop:[s1] Adding hammer to the shopping list
-  working directory is now at d5c51ee5762a
+  working directory is now at 7537e3a3cbca
 
   $ hg stack
   ### topic: tools
@@ -1386,7 +1386,7 @@ One more to go:
   $ hg next --evolve
   move:[s3] Adding drill
   atop:[s2] Adding saw
-  working directory is now at bae3758e46bf
+  working directory is now at 9d65331e0dc1
 
   $ hg stack
   ### topic: tools
@@ -1396,41 +1396,41 @@ One more to go:
   s1: Adding hammer to the shopping list
   s0^ add a pair of shoes (base)
 
-Let's take a look at `hg log` once again:
+Let's take a look at ``hg log`` once again:
 
   $ hg log -G -r "s0::"
-  @  changeset:   20:bae3758e46bf
+  @  changeset:   20:9d65331e0dc1
   |  tag:         tip
   |  topic:       tools
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     Adding drill
   |
-  o  changeset:   19:d5c51ee5762a
+  o  changeset:   19:7537e3a3cbca
   |  topic:       tools
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     Adding saw
   |
-  o  changeset:   18:b7509bd417f8
+  o  changeset:   18:2c1a47a5c075
   |  topic:       tools
-  |  parent:      12:fbff9bc37a43
+  |  parent:      12:033bfcc0ecb0
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     Adding hammer to the shopping list
   |
-  | o  changeset:   17:4cd7c1591a67
+  | o  changeset:   17:9dc8cec494f3
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     Adding orange juice
   | |
-  | o  changeset:   16:20759cb47ff8
-  |/   parent:      12:fbff9bc37a43
+  | o  changeset:   16:9dfd6068e8e7
+  |/   parent:      12:033bfcc0ecb0
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    summary:     Adding apple juice
   |
-  o  changeset:   12:fbff9bc37a43
+  o  changeset:   12:033bfcc0ecb0
   |  user:        test
   ~  date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     add a pair of shoes
@@ -1548,61 +1548,61 @@ destination if the topic has two heads.
 completely linear history so it's what we will do.
 
   $ hg log -G
-  @  changeset:   21:f936c6da9d61
+  @  changeset:   21:69ad92f8ff49
   |  tag:         tip
   |  topic:       tools
-  |  parent:      18:b7509bd417f8
+  |  parent:      18:2c1a47a5c075
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     Adding nails
   |
-  | o  changeset:   20:bae3758e46bf
+  | o  changeset:   20:9d65331e0dc1
   | |  topic:       tools
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     Adding drill
   | |
-  | o  changeset:   19:d5c51ee5762a
+  | o  changeset:   19:7537e3a3cbca
   |/   topic:       tools
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    summary:     Adding saw
   |
-  o  changeset:   18:b7509bd417f8
+  o  changeset:   18:2c1a47a5c075
   |  topic:       tools
-  |  parent:      12:fbff9bc37a43
+  |  parent:      12:033bfcc0ecb0
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     Adding hammer to the shopping list
   |
-  | o  changeset:   17:4cd7c1591a67
+  | o  changeset:   17:9dc8cec494f3
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | |  summary:     Adding orange juice
   | |
-  | o  changeset:   16:20759cb47ff8
-  |/   parent:      12:fbff9bc37a43
+  | o  changeset:   16:9dfd6068e8e7
+  |/   parent:      12:033bfcc0ecb0
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    summary:     Adding apple juice
   |
-  o  changeset:   12:fbff9bc37a43
+  o  changeset:   12:033bfcc0ecb0
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     add a pair of shoes
   |
-  o  changeset:   11:f2d6cacc6115
-  |  parent:      5:2d50db8b5b4c
+  o  changeset:   11:bbfb218049cd
+  |  parent:      5:fec062fcfcfa
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     add a coat
   |
-  o  changeset:   5:2d50db8b5b4c
+  o  changeset:   5:fec062fcfcfa
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding fruits
   |
-  o  changeset:   4:4011b46eeb33
+  o  changeset:   4:d3a1ea2a0337
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     adding condiments
@@ -1777,9 +1777,9 @@ completely linear history so it's what w
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
   $ hg rebase
-  rebasing 19:d5c51ee5762a tools "Adding saw"
+  rebasing 19:7537e3a3cbca tools "Adding saw"
   merging shopping
-  rebasing 20:bae3758e46bf tools "Adding drill"
+  rebasing 20:9d65331e0dc1 tools "Adding drill"
   merging shopping
 
   $ hg stack
@@ -1832,7 +1832,7 @@ We can now share these draft changesets:
   8 new obsolescence markers
 
 Pushing the new topic branch to a non-publishing server did not require
---force. As long as new heads are on their own topic, Mercurial will not
+``--force``. As long as new heads are on their own topic, Mercurial will not
 complain about them.
 
 From another client, we will get them with their topic:
@@ -1847,7 +1847,7 @@ From another client, we will get them wi
   adding file changes
   added 4 changesets with 4 changes to 1 files (+1 heads)
   8 new obsolescence markers
-  new changesets b7509bd417f8:2d084ac00115 (4 drafts)
+  new changesets 2c1a47a5c075:bbb9e269a01a (4 drafts)
   (run 'hg heads' to see heads)
 
   $ hg topics --verbose
@@ -1891,7 +1891,7 @@ And retrieve them from the first client:
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  new changesets 0d409663a1fd (1 drafts)
+  new changesets 71d37f5c73ed (1 drafts)
   (run 'hg update' to get a working copy)
 
   $ hg update
diff -pruN 11.1.3-1/tests/test-topic.t 11.1.9-1/tests/test-topic.t
--- 11.1.3-1/tests/test-topic.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-topic.t	2025-07-25 16:21:02.000000000 +0000
@@ -171,45 +171,47 @@
    stack         list all changesets in a topic and other information
   
   (use 'hg help -v topic' to show built-in aliases and global options)
+
+#if hg69
   $ hg help topics
   hg topics [OPTION]... [-r REV]... [TOPIC]
   
   View current topic, set current topic, change topic for a set of revisions, or
   see all topics.
   
-      Clear topic on existing topiced revisions:
+  Clear topic on existing topiced revisions:
   
-        hg topics --rev <related revset> --clear
+    hg topics --rev <related revset> --clear
   
-      Change topic on some revisions:
+  Change topic on some revisions:
   
-        hg topics <newtopicname> --rev <related revset>
+    hg topics <newtopicname> --rev <related revset>
   
-      Clear current topic:
+  Clear current topic:
   
-        hg topics --clear
+    hg topics --clear
   
-      Set current topic:
+  Set current topic:
   
-        hg topics <topicname>
+    hg topics <topicname>
   
-      List of topics:
+  List of topics:
   
-        hg topics
+    hg topics
   
-      List of topics sorted according to their last touched time displaying last
-      touched time and the user who last touched the topic:
+  List of topics sorted according to their last touched time displaying last
+  touched time and the user who last touched the topic:
   
-        hg topics --age
+    hg topics --age
   
-      The active topic (if any) will be prepended with a "*".
+  The active topic (if any) will be prepended with a "*".
   
-      The '--current' flag helps to take active topic into account. For example,
-      if you want to set the topic on all the draft changesets to the active
-      topic, you can do: 'hg topics -r "draft()" --current'
+  The '--current' flag helps to take active topic into account. For example, if
+  you want to set the topic on all the draft changesets to the active topic, you
+  can do: 'hg topics -r "draft()" --current'
   
-      The --verbose version of this command display various information on the
-      state of each topic.
+  The --verbose version of this command display various information on the state
+  of each topic.
   
   options ([+] can be repeated):
   
@@ -221,6 +223,8 @@
    -T --template TEMPLATE display with template
   
   (some details hidden, use --verbose to show complete help)
+#endif
+
   $ hg topics
 
 Test topics interaction with evolution:
diff -pruN 11.1.3-1/tests/test-tutorial.t 11.1.9-1/tests/test-tutorial.t
--- 11.1.3-1/tests/test-tutorial.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-tutorial.t	2025-07-25 16:21:02.000000000 +0000
@@ -1,3 +1,6 @@
+===============
+Evolve Tutorial
+===============
 
 Initial setup
 -------------
@@ -99,11 +102,11 @@ Its first version is shared with the out
   adding file changes
   added 1 changesets with 1 changes to 1 files
 
-Later I add additional item to my list
+Later I add additional items to my list
 
   $ cat >> shopping << EOF
   > Egg
-  > Suggar
+  > Sugar
   > Vinegar
   > Oil
   > EOF
@@ -115,12 +118,12 @@ Later I add additional item to my list
   > EOF
   $ hg commit -m "adding fruit"
 
-This history is very linear
+The history is completely linear so far
 
   $ hg log -G
-  @  d85de4546133 (draft): adding fruit
+  @  4296f0622469 (draft): adding fruit
   |
-  o  4d5dc8187023 (draft): adding condiment
+  o  63ae8c44f4b6 (draft): adding condiment
   |
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
@@ -170,22 +173,22 @@ This history is very linear
       }
 #endif
 
-But a typo was made in Babanas!
+But a typo was made in Bananas!
 
   $ hg export tip
   # HG changeset patch
   # User test
   # Date 0 0
   #      Thu Jan 01 00:00:00 1970 +0000
-  # Node ID d85de4546133030c82d257bbcdd9b1b416d0c31c
-  # Parent  4d5dc81870237d492284826e21840b2ca00e26d1
+  # Node ID 4296f0622469c1527d5dc020cf72bd7732c44c64
+  # Parent  63ae8c44f4b6274d5580b4eea41a87623301c3e9
   adding fruit
   
   diff --git a/shopping b/shopping
   --- a/shopping
   +++ b/shopping
   @@ -9,3 +9,6 @@
-   Suggar
+   Sugar
    Vinegar
    Oil
   +Bananos
@@ -193,12 +196,12 @@ But a typo was made in Babanas!
   +Apple
 
 The faulty changeset is in the "draft" phase because it has not been exchanged with
-the outside. The first one has been exchanged and is "public" (immutable).
+the outside yet. The first one has been exchanged and is "public" (immutable).
 
   $ hg log -G
-  @  d85de4546133 (draft): adding fruit
+  @  4296f0622469 (draft): adding fruit
   |
-  o  4d5dc8187023 (draft): adding condiment
+  o  63ae8c44f4b6 (draft): adding condiment
   |
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
@@ -249,7 +252,7 @@ the outside. The first one has been exch
       }
 #endif
 
-Hopefully. I can use `hg commit --amend` to rewrite my faulty changeset!
+Luckily, I can use `hg commit --amend` to rewrite my faulty changeset!
 
   $ sed -i'' -e s/Bananos/Banana/ shopping
   $ hg diff
@@ -257,7 +260,7 @@ Hopefully. I can use `hg commit --amend`
   --- a/shopping
   +++ b/shopping
   @@ -9,6 +9,6 @@
-   Suggar
+   Sugar
    Vinegar
    Oil
   -Bananos
@@ -266,12 +269,12 @@ Hopefully. I can use `hg commit --amend`
    Apple
   $ hg commit --amend
 
-A new changeset with the right diff replace the wrong one.
+A new changeset with the correct changes replaces the old one.
 
   $ hg log -G
-  @  9d0363b81950 (draft): adding fruit
+  @  6445b365ad1c (draft): adding fruit
   |
-  o  4d5dc8187023 (draft): adding condiment
+  o  63ae8c44f4b6 (draft): adding condiment
   |
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
@@ -326,15 +329,15 @@ A new changeset with the right diff repl
   # User test
   # Date 0 0
   #      Thu Jan 01 00:00:00 1970 +0000
-  # Node ID 9d0363b81950646bc6ad1ec5de8b8197ea586541
-  # Parent  4d5dc81870237d492284826e21840b2ca00e26d1
+  # Node ID 6445b365ad1c4905e7a120e45242d9f4b51ec48f
+  # Parent  63ae8c44f4b6274d5580b4eea41a87623301c3e9
   adding fruit
   
   diff --git a/shopping b/shopping
   --- a/shopping
   +++ b/shopping
   @@ -9,3 +9,6 @@
-   Suggar
+   Sugar
    Vinegar
    Oil
   +Banana
@@ -344,7 +347,7 @@ A new changeset with the right diff repl
 Getting rid of branchy history
 ----------------------------------
 
-While I was working on my list. Someone made a change remotely.
+While I was working on my list, someone made a change remotely.
 
   $ cd ../remote
   $ hg up -q
@@ -369,9 +372,9 @@ I now have a new head. Note that this re
   $ hg log -G
   o  9ca060c80d74 (public): SPAM
   |
-  | @  9d0363b81950 (draft): adding fruit
+  | @  6445b365ad1c (draft): adding fruit
   | |
-  | o  4d5dc8187023 (draft): adding condiment
+  | o  63ae8c44f4b6 (draft): adding condiment
   |/
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
@@ -437,19 +440,19 @@ I now have a new head. Note that this re
 Instead of merging my head with the new one. I'm going to rebase my work
 
   $ hg diff
-  $ hg rebase --dest 9ca060c80d74 --source 4d5dc8187023
-  rebasing 1:4d5dc8187023 "adding condiment"
+  $ hg rebase --dest 9ca060c80d74 --source 63ae8c44f4b6
+  rebasing 1:63ae8c44f4b6 "adding condiment"
   merging shopping
-  rebasing 3:9d0363b81950 "adding fruit"
+  rebasing 3:6445b365ad1c "adding fruit"
   merging shopping
 
 
 My local work is now rebased on the remote one.
 
   $ hg log -G
-  @  41aff6a42b75 (draft): adding fruit
+  @  d300c8f961ce (draft): adding fruit
   |
-  o  dfd3a2d7691e (draft): adding condiment
+  o  723e5a43d6d9 (draft): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -526,31 +529,31 @@ I add new items to my list.
   > EOF
   $ hg ci -m 'transport'
   $ hg log -G
-  @  1125e39fbf21 (draft): transport
+  @  7f938a07ecb2 (draft): transport
   |
-  o  41aff6a42b75 (draft): adding fruit
+  o  d300c8f961ce (draft): adding fruit
   |
-  o  dfd3a2d7691e (draft): adding condiment
+  o  723e5a43d6d9 (draft): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-I have a new commit but I realize that don't want it. (Transport shop list does
-not fit well in my standard shopping list)
+I have a new commit but I realize that don't want it. (Transport shopping list
+does not fit well in my standard shopping list)
 
   $ hg prune . # "." is for working directory parent
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  working directory is now at 41aff6a42b75
+  working directory is now at d300c8f961ce
   1 changesets pruned
 
 The silly changeset is gone.
 
   $ hg log -G
-  @  41aff6a42b75 (draft): adding fruit
+  @  d300c8f961ce (draft): adding fruit
   |
-  o  dfd3a2d7691e (draft): adding condiment
+  o  723e5a43d6d9 (draft): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -629,18 +632,18 @@ We create two changesets.
   > Towel
   > Soap
   > EOF
-  $ hg ci -m 'bathroom stuff' -q # XXX remove the -q
+  $ hg ci -m 'bathroom stuff'
 
   $ sed -i'' -e 's/Spam/Spam Spam Spam/g' shopping
   $ hg ci -m 'SPAM SPAM'
   $ hg log -G
-  @  fac207dec9f5 (draft): SPAM SPAM
+  @  1c877d31b53f (draft): SPAM SPAM
   |
-  o  10b8aeaa8cc8 (draft): bathroom stuff
+  o  d1928babc208 (draft): bathroom stuff
   |
-  o  41aff6a42b75 (draft): adding fruit
+  o  d300c8f961ce (draft): adding fruit
   |
-  o  dfd3a2d7691e (draft): adding condiment
+  o  723e5a43d6d9 (draft): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -649,27 +652,27 @@ We create two changesets.
 
 .. note:: We can't amend changeset 7e82d3f3c2cb or 9ca060c80d74 as they are immutable.
 
- I now want to push to remote all my changes except the bathroom one, which I'm
- not totally happy with yet. To be able to push "SPAM SPAM" I need a version of
- "SPAM SPAM" which is not a child of "bathroom stuff"
+I now want to push to remote all my changes except the bathroom one, which I'm
+not totally happy with yet. To be able to push "SPAM SPAM" I need a version of
+"SPAM SPAM" which is not a child of "bathroom stuff".
 
-You can use the 'grab' alias for that.
+You can use the 'grab' command for that.
 
-.. note: grab is an alias for `hg rebase --dest . --rev <target>; hg up <there>`
+.. note:: `grab` is an alias for `hg rebase --dest . --rev <target>; hg up <result>`
 
-  $ hg up 'p1(10b8aeaa8cc8)' # going on "bathroom stuff" parent
+  $ hg up 'p1(d1928babc208)' # going on "bathroom stuff" parent
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg pick fac207dec9f5 # moving "SPAM SPAM" to the working directory parent
-  picking 9:fac207dec9f5 "SPAM SPAM"
+  $ hg pick 1c877d31b53f # moving "SPAM SPAM" to the working directory parent
+  picking 9:1c877d31b53f "SPAM SPAM"
   merging shopping
   $ hg log -G
-  @  57e9caedbcb8 (draft): SPAM SPAM
+  @  501b33037995 (draft): SPAM SPAM
   |
-  | o  10b8aeaa8cc8 (draft): bathroom stuff
+  | o  d1928babc208 (draft): bathroom stuff
   |/
-  o  41aff6a42b75 (draft): adding fruit
+  o  d300c8f961ce (draft): adding fruit
   |
-  o  dfd3a2d7691e (draft): adding condiment
+  o  723e5a43d6d9 (draft): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -758,7 +761,7 @@ You can use the 'grab' alias for that.
       }
 #endif
 
-We have a new SPAM SPAM version without the bathroom stuff
+We have a new version of "SPAM SPAM" without the bathroom stuff
 
   $ grep Spam shopping  # enough spam
   Spam Spam Spam Spam Spam Spam Spam Spam Spam
@@ -769,8 +772,8 @@ We have a new SPAM SPAM version without
   # User test
   # Date 0 0
   #      Thu Jan 01 00:00:00 1970 +0000
-  # Node ID 57e9caedbcb8575a01c128db9d1bcbd624ef2115
-  # Parent  41aff6a42b7578ec7ec3cb2041633f1ca43cca96
+  # Node ID 501b330379955b6bf194dc99504a477b1f2d3f89
+  # Parent  d300c8f961ceefede93601dbe478c701e2ff5995
   SPAM SPAM
   
   diff --git a/shopping b/shopping
@@ -783,10 +786,10 @@ We have a new SPAM SPAM version without
    Albatross
    Rat (rather a lot)
 
-To make sure I do not push unready changeset by mistake I set the "bathroom
-stuff" changeset in the secret phase.
+To make sure I do not push unfinished changeset by mistake I move the "bathroom
+stuff" changeset to the secret phase.
 
-  $ hg phase --force --secret 10b8aeaa8cc8
+  $ hg phase --force --secret d1928babc208
 
 we can now push our change:
 
@@ -799,20 +802,20 @@ we can now push our change:
   added 3 changesets with 3 changes to 1 files
   5 new obsolescence markers
 
-for simplicity sake we get the bathroom change in line again
+for simplicity's sake we get the bathroom change in line again
 
-  $ hg pick 10b8aeaa8cc8
-  picking 8:10b8aeaa8cc8 "bathroom stuff"
+  $ hg pick d1928babc208
+  picking 8:d1928babc208 "bathroom stuff"
   merging shopping
   $ hg phase --draft .
   $ hg log -G
-  @  4710c0968793 (draft): bathroom stuff
+  @  39b19dc3d1e4 (draft): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -905,26 +908,27 @@ Splitting change
 ------------------
 
 This part is not written yet, but you can use either the `histedit` extension
-of the `uncommit` command to splitting a change.
+or the `uncommit` command to split a change.
 
+#if hg69
   $ hg help uncommit
   hg uncommit [OPTION]... [FILE]...
   
   move changes from parent revision to working directory
   
-      Changes to selected files in the checked out revision appear again as
-      uncommitted changed in the working directory. A new revision without the
-      selected changes is created, becomes the checked out revision, and
-      obsoletes the previous one.
-  
-      The --include option specifies patterns to uncommit. The --exclude option
-      specifies patterns to keep in the commit.
-  
-      The --rev argument let you change the commit file to a content of another
-      revision. It still does not change the content of your file in the working
-      directory.
+  Changes to selected files in the checked out revision appear again as
+  uncommitted changed in the working directory. A new revision without the
+  selected changes is created, becomes the checked out revision, and obsoletes
+  the previous one.
+  
+  The --include option specifies patterns to uncommit. The --exclude option
+  specifies patterns to keep in the commit.
+  
+  The --rev argument let you change the commit file to a content of another
+  revision. It still does not change the content of your file in the working
+  directory.
   
-      Return 0 if changed files are uncommitted.
+  Return 0 if changed files are uncommitted.
   
   options ([+] can be repeated):
   
@@ -942,6 +946,7 @@ of the `uncommit` command to splitting a
    -U --current-user        record the current user as committer
   
   (some details hidden, use --verbose to show complete help)
+#endif
 
 
 The edit command of histedit can be used to split changeset:
@@ -952,6 +957,7 @@ Collapsing change
 
 The tutorial part is not written yet but can use `hg fold`:
 
+#if hg69
   $ hg help fold
   hg fold [OPTION]... [-r] REV...
   
@@ -959,12 +965,12 @@ The tutorial part is not written yet but
   
   fold multiple revisions into a single one
   
-      With --from, folds all the revisions linearly between the given revisions
-      and the parent of the working directory.
+  With --from, folds all the revisions linearly between the given revisions and
+  the parent of the working directory.
   
-      With --exact, folds only the specified revisions while ignoring the parent
-      of the working directory. In this case, the given revisions must form a
-      linear unbroken chain.
+  With --exact, folds only the specified revisions while ignoring the parent of
+  the working directory. In this case, the given revisions must form a linear
+  unbroken chain.
   
   options ([+] can be repeated):
   
@@ -980,6 +986,7 @@ The tutorial part is not written yet but
    -U --current-user record the current user as committer
   
   (some details hidden, use --verbose to show complete help)
+#endif
 
 
 -----------------------
@@ -998,8 +1005,8 @@ behavior where exchanged changeset are a
   $ hg -R ../local/ showconfig phases
   [1]
 
-The localrepo does not have any specific configuration for `phases.publish`. It
-is ``true`` by default.
+The local repo does not have any specific configuration for `phases.publish`.
+It is ``true`` by default.
 
   $ hg pull local
   pulling from $TESTTMP/local (glob)
@@ -1009,16 +1016,16 @@ is ``true`` by default.
   adding file changes
   added 1 changesets with 1 changes to 1 files
   1 new obsolescence markers
-  new changesets 4710c0968793
+  new changesets 39b19dc3d1e4
   (run 'hg update' to get a working copy)
   $ hg log -G
-  o  4710c0968793 (public): bathroom stuff
+  o  39b19dc3d1e4 (public): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   @  9ca060c80d74 (public): SPAM
   |
@@ -1027,16 +1034,16 @@ is ``true`` by default.
 
 We do not want to publish the "bathroom changeset". Let's rollback the last transaction.
 
-.. Warning: Rollback is actually a dangerous kind of internal command that is deprecated and should not be exposed to user. Please forget you read about it until someone fix this tutorial.
+.. warning:: `rollback` is actually a dangerous kind of internal command that is deprecated and should not be exposed to user. Please forget you read about it until someone fix this tutorial.
 
   $ hg rollback
   repository tip rolled back to revision 4 (undo pull)
   $ hg log -G
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   @  9ca060c80d74 (public): SPAM
   |
@@ -1065,16 +1072,16 @@ I can now exchange mutable changeset bet
   adding file changes
   added 1 changesets with 1 changes to 1 files
   1 new obsolescence markers
-  new changesets 4710c0968793 (1 drafts)
+  new changesets 39b19dc3d1e4 (1 drafts)
   (run 'hg update' to get a working copy)
   $ hg log -G
-  o  4710c0968793 (draft): bathroom stuff
+  o  39b19dc3d1e4 (draft): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   @  9ca060c80d74 (public): SPAM
   |
@@ -1086,7 +1093,7 @@ Rebasing unstable change after pull
 
 Remotely someone add a new changeset on top of the mutable "bathroom" on.
 
-  $ hg up 4710c0968793 -q
+  $ hg up 39b19dc3d1e4 -q
   $ cat >> shopping << EOF
   > Giraffe
   > Rhino
@@ -1098,17 +1105,17 @@ Remotely someone add a new changeset on
 But at the same time, locally, this same "bathroom changeset" was updated.
 
   $ cd ../local
-  $ hg up 4710c0968793 -q
+  $ hg up 39b19dc3d1e4 -q
   $ sed -i'' -e 's/... More bathroom stuff to come/Bath Robe/' shopping
   $ hg commit --amend
   $ hg log -G
-  @  682004e81e71 (draft): bathroom stuff
+  @  5486682f4225 (draft): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -1207,24 +1214,24 @@ When we pull from remote again we get an
   adding file changes
   added 1 changesets with 1 changes to 1 files
   1 new orphan changesets
-  new changesets e4e4fa805d92 (1 drafts)
+  new changesets 0609f95eccab (1 drafts)
   (run 'hg update' to get a working copy)
 
 The new changeset "animal" is based on an old changeset of "bathroom". You can
 see both version showing up in the log.
 
   $ hg log -G
-  *  e4e4fa805d92 (draft): animals
+  *  0609f95eccab (draft): animals
   |
-  | @  682004e81e71 (draft): bathroom stuff
+  | @  5486682f4225 (draft): bathroom stuff
   | |
-  x |  4710c0968793 (draft): bathroom stuff
+  x |  39b19dc3d1e4 (draft): bathroom stuff
   |/
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -1342,10 +1349,10 @@ see both version showing up in the log.
       }
 #endif
 
-The older version 75954b8cd933 never ceased to exist in the local repo. It was
+The older version 39b19dc3d1e4 never ceased to exist in the local repo. It was
 just hidden and excluded from pull and push.
 
-.. note:: In hgview there is a nice dotted relation highlighting a44c85f957d3 as a new version of 75954b8cd933. this is not yet ported to ``hg log -G``.
+.. note:: In hgview there is a nice dotted relation highlighting 5486682f4225 as a new version of 39b19dc3d1e4. This is not yet ported to ``hg log -G``.
 
 There is now an **unstable** changeset in this history. Mercurial will refuse to
 share it with the outside:
@@ -1353,20 +1360,20 @@ share it with the outside:
   $ hg push other
   pushing to $TESTTMP/other (glob)
   searching for changes
-  abort: push includes orphan changeset: e4e4fa805d92!
+  abort: push includes orphan changeset: 0609f95eccab!
   (use 'hg evolve' to get a stable history or --force to ignore warnings)
   [255]
  
 
-To resolve this unstable state, you need to rebase bf1b0d202029 onto
-a44c85f957d3. The `hg evolve` command will do this for you.
+To resolve this unstable state, you need to rebase 0609f95eccab onto
+5486682f4225. The `hg evolve` command will do this for you.
 
 It has a --dry-run option to only suggest the next move.
 
   $ hg evolve --dry-run
   move:[13] animals
   atop:[12] bathroom stuff
-  hg rebase -r e4e4fa805d92 -d 682004e81e71
+  hg rebase -r 0609f95eccab -d 5486682f4225
 
 Let's do it
 
@@ -1378,15 +1385,15 @@ Let's do it
 The old version of bathroom is hidden again.
 
   $ hg log -G
-  o  2a2b36e14660 (draft): animals
+  o  3266db1117c9 (draft): animals
   |
-  @  682004e81e71 (draft): bathroom stuff
+  @  5486682f4225 (draft): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -1516,13 +1523,13 @@ changeset.
 Now let's see where we are, and update to the successor.
 
   $ hg parents
-  e4e4fa805d92 (draft): animals
-  working directory parent is obsolete! (e4e4fa805d92)
-  (use 'hg evolve' to update to its successor: 2a2b36e14660)
+  0609f95eccab (draft): animals
+  working directory parent is obsolete! (0609f95eccab)
+  (use 'hg evolve' to update to its successor: 3266db1117c9)
   $ hg evolve
   update:[8] animals
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  working directory is now at 2a2b36e14660
+  working directory is now at 3266db1117c9
 
 Relocating unstable change after prune
 ----------------------------------------------
@@ -1542,20 +1549,20 @@ I'm pulling its work locally.
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  new changesets fc41faf45288 (1 drafts)
+  new changesets fff8c3d068b6 (1 drafts)
   (run 'hg update' to get a working copy)
   $ hg log -G
-  o  fc41faf45288 (draft): SPAM SPAM SPAM
+  o  fff8c3d068b6 (draft): SPAM SPAM SPAM
   |
-  @  2a2b36e14660 (draft): animals
+  @  3266db1117c9 (draft): animals
   |
-  o  682004e81e71 (draft): bathroom stuff
+  o  5486682f4225 (draft): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -1670,9 +1677,9 @@ I'm pulling its work locally.
 
 In the mean time I noticed you can't buy animals in a super market and I prune the animal changeset:
 
-  $ hg prune 2a2b36e14660
+  $ hg prune 3266db1117c9
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  working directory is now at 682004e81e71
+  working directory is now at 5486682f4225
   1 changesets pruned
   1 new orphan changesets
 
@@ -1681,17 +1688,17 @@ The animals changeset is still displayed
 is neither dead or obsolete. My repository is in an unstable state again.
 
   $ hg log -G
-  *  fc41faf45288 (draft): SPAM SPAM SPAM
+  *  fff8c3d068b6 (draft): SPAM SPAM SPAM
   |
-  x  2a2b36e14660 (draft): animals
+  x  3266db1117c9 (draft): animals
   |
-  @  682004e81e71 (draft): bathroom stuff
+  @  5486682f4225 (draft): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
@@ -1805,7 +1812,7 @@ is neither dead or obsolete. My reposito
 #endif
 
   $ hg log -r "orphan()"
-  fc41faf45288 (draft): SPAM SPAM SPAM
+  fff8c3d068b6 (draft): SPAM SPAM SPAM
 
 #if docgraph-ext
   $ hg docgraph -r "orphan()" --sphinx-directive --rankdir LR #rest-ignore
@@ -1836,18 +1843,18 @@ changeset.
   move:[15] SPAM SPAM SPAM
   atop:[12] bathroom stuff
   merging shopping
-  working directory is now at e6cfcb672150
+  working directory is now at c33e56ec23a8
 
   $ hg log -G
-  @  e6cfcb672150 (draft): SPAM SPAM SPAM
+  @  c33e56ec23a8 (draft): SPAM SPAM SPAM
   |
-  o  682004e81e71 (draft): bathroom stuff
+  o  5486682f4225 (draft): bathroom stuff
   |
-  o  57e9caedbcb8 (public): SPAM SPAM
+  o  501b33037995 (public): SPAM SPAM
   |
-  o  41aff6a42b75 (public): adding fruit
+  o  d300c8f961ce (public): adding fruit
   |
-  o  dfd3a2d7691e (public): adding condiment
+  o  723e5a43d6d9 (public): adding condiment
   |
   o  9ca060c80d74 (public): SPAM
   |
diff -pruN 11.1.3-1/tests/test-version-install.t 11.1.9-1/tests/test-version-install.t
--- 11.1.3-1/tests/test-version-install.t	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/test-version-install.t	2025-07-25 16:21:02.000000000 +0000
@@ -18,7 +18,15 @@ Test outputting version number
     evolve  external  * (glob)
 
 Test install
-TODO: fix warning
-  $ "$PYTHON" "$TESTDIR/../setup.py" install --root "$TESTTMP/installtest" > /dev/null
-  */distutils/dist.py:*: UserWarning: Unknown distribution option: 'python_requires' (glob)
-    warnings.warn(msg)
+(pip on python2 doesn't have --root-user-action flag, so we ignore the warning manually)
+
+  $ "$PYTHON" -m pip install "$TESTDIR/.." --root="$TESTTMP/installtest" --quiet
+  WARNING: Running pip as the 'root' user * (glob) (?)
+
+Test that evolve can be loaded from the above path
+
+  $ echo "evolve=$(find $TESTTMP -path '*/hgext3rd/evolve')" >> $HGRCPATH
+  $ hg debugconfig extensions.evolve
+  */installtest/*/python*/hgext3rd/evolve (glob)
+  $ hg help evolve | head -1
+  hg evolve [OPTIONS]...
diff -pruN 11.1.3-1/tests/testlib/pythonpath.sh 11.1.9-1/tests/testlib/pythonpath.sh
--- 11.1.3-1/tests/testlib/pythonpath.sh	2024-04-12 19:06:18.000000000 +0000
+++ 11.1.9-1/tests/testlib/pythonpath.sh	2025-07-25 16:21:02.000000000 +0000
@@ -11,3 +11,12 @@ if [ -n "$PYTHONPATH" ]; then
 else
     export PYTHONPATH=$SRCDIR
 fi
+
+for SP in "$HGTMP"/install/lib/python*/site-packages/; do
+    # find site-packages directory for each Python version (there's most likely
+    # only one, but let's be safe)
+    if [ -d "$SP" ]; then
+        # adding path to our extensions to the current virtualenv
+        echo "$SRCDIR" > "$SP/evolve.pth"
+    fi
+done
