changeset 3184:37aebaa73248 stable

branching: merge with an old and strange head
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Tue, 14 Nov 2017 23:04:04 +0100
parents bc09dd507c41 (diff) 884a3b8aadd6 (current diff)
children 0c64d0242ac2
files
diffstat 135 files changed, 12500 insertions(+), 5590 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Tue Jul 25 02:29:28 2017 +0200
+++ b/.hgtags	Tue Nov 14 23:04:04 2017 +0100
@@ -55,3 +55,8 @@
 e358c0263e4629746a7c925429c951f67d4b02b1 6.3.1
 e60248f26f923f4460682252f7863ff86f7b86b0 6.4.0
 734c0bc066cdc0121a20a9cb44c8cc30c653be94 6.5.0
+cc3e09e033a3c632c9ac35badbf8b5d53f584049 6.6.0
+3a4f75c6619c7ef7d78ee0912efd6cb01d55b521 6.7.0
+430ad68292d76b9387d1eeadf289951f51fd88d3 6.7.1
+ec0bbf26ce7fadd42c637e01d3750dac96ac0b1b 6.8.0
+c56c028f3802202241551e5953bea74ab3a6c434 7.0.0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CHANGELOG	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,652 @@
+Changelog
+=========
+
+7.0.1 - in progress
+-------------------
+
+  * obsdiscovery: allow the config option to disable discovery server side
+    (it was previously only honored on the client side)
+
+  * server: avoid exposing 'abort' to evolution enabled client talking
+            to server with the extension bu obsolescence marker exchange
+            disabled.
+
+7.0.0 -- 2017-10-23
+-------------------
+
+  * drop compatibility with Mercurial 3.8, 3.9 and 4.0,
+  * drop support for old and deprecated method to exchange obsmarkers,
+  * forbid usage of the old pushbey based protocol to exchange obsmarkers,
+  * evolve: rename '--contentdivergent' flag to '--content-divergent',
+  * evolve: rename '--phasedivergent' flag to '--phase-divergent'.
+
+topic (0.5.0)
+
+  * add an experimental flag to enforce one head per name policy,
+    (off by default, see 'hg help -e topic' for details)
+  * add an experimental flag to have changesets without topic published on push,
+    (off by default, see 'hg help -e topic' for details)
+  * add a '--publish' flag to `hg push` (4.4+ only).
+
+6.8.0 -- 2017-10-23
+-------------------
+
+  * compatibility with Mercurial 4.4
+    (use upstream implementation for obsfate and effect-flags starting hg 4.4+)
+  * pager: pager support to `obslog` and `evolve --list`
+
+topic(0.4.0)
+
+  * topic: fix handling of bookmarks and phases while changing topics.
+           (mercurial 4.2 and above only)
+  * topic: fix 'topic-mode' behavior when amending
+  * pager: pager support to `topics` and `stack`
+
+6.7.1 -- 2017-10-10
+-------------------
+
+  * obsfate: fix case were current user would disapear from the user list
+
+topic (0.3.1)
+
+  * topic: introduce a documented 'experimental.topic-mode' config
+  * topic: add support for 'random' topic mode (see documentation for details)
+  * stack: fix evolution preview for simple split.
+  * fix a performance regression affecting all transactions.
+    (the more non public changeset (hidden included), the slower)
+
+6.7.0 -- 2017-09-27
+-------------------
+
+  * compatibility with change in future 4.4 at this release date,
+  * documentation: improvement to content, wording and graphs,
+  * obslog: improved templatability,
+  * obslog/log: improve verb used to describe and evolution,
+  * pstatus/pdiff: update to full command. They now appears in the help,
+  * uncommit: add a --interactive option (4.3+ only).
+
+topic (0.3.0)
+
+  * push: add a --topic option to mirror --bookmark and --branch,
+  * stack: improve display of interleaved topic,
+  * stack: improve display of merge commit,
+  * topic: add a new 'debugconvertbookmark' commands (4.3+ only),
+    It helps migrating from bookmark feature branch to topic feature branch,
+  * topic: --age flag also shows the user who last touched the topic,
+  * topic: be more informative about topic activation and deactivation,
+  * topic: gain a --current flag,
+  * topic: small clarification and cleanup on various output.
+
+6.6.0 -- 2017-07-25
+-------------------
+
+  - amend: add a --extract flag to move change back to the working copy,
+    (same as uncommit, but accessible through the amend commit)
+  - split: now properly refuse to split public changeset,
+  - commands: unify and improve the pre-rewrite validation and error message,
+  - uncommit: add support for --current-date and --current-user option,
+  - fold: add support for --current-date and --current-user option,
+  - metaedit: add support for --current-date and --current-user option,
+  - split: add support for --current-date and --current-user option,
+  - compat: use various new API instead of the one deprecated in 4.3,
+    (when available)
+  - documentation: various minor documentation update.
+
+topic (0.2.0):
+
+  - topic: add --age option to sort topic by the most recently touched,
+  - topic: add a 't0' to access the root of a topic while keeping it active,
+  - topic: allow 'hg prev' to me move to 't0',
+  - topic: add a config option to enforce topic on new commit,
+    (experimental.enforce-topic)
+  - topic: make command names valid as expected, even if ui.strict=true.
+
+6.5.0 -- 2017-07-02
+-------------------
+
+features:
+
+ - obslog: gain a --patch flag to display changes introduced by the evolution
+  (Currently limited to in simple case only)
+ - log: display obsolescence fate by default, (future 4.3 only)
+ - doc: various minor improvement.
+
+bugfixes:
+
+ - evolve: fix branch preservation for merge,
+ - obsfate: improve support for advanced template reformating,
+ - split: preserve author of the splitted changeset.
+ - grab: properly fix hg executable on windows.
+
+topic (0.1.0):
+
+ - stack: also show the unstable status for the current changeset, (issue5553)
+ - stack: properly abort when and unknown topic is requested,
+ - stack: add basic and raw support for named branches,
+ - topic: changing topic on revs no longer adds extra instability, (issue5441)
+ - topic: topics: rename '--change' flag to '--rev' flag,
+ - topic: multiple large performance improvements,
+ - topic: various small output improvement,
+ - topic: improved topic preservation for various commands.
+
+
+6.4.0 -- 2017-06-16
+-------------------
+
+ - template: signifiant improvement to the '{obsfate}' template (now 4.2+ only)
+ - template: fix 'successors' and 'precursors' template to expose hex-node
+ - effect flag: the experiment is now active by default,
+   (see 'hg help -e evolve' to opt out)
+ - effect flag: fix a small bug related to hidden changeset,
+ - obscache: reduce impact on large repository
+ - obshashrange: install a '.max-revs' option see extension help for details
+
+6.3.1 -- 2017-06-01
+-------------------
+
+ - also backport the "revelant-markers" fix when using "evolve.serveronly"
+
+6.3.0 -- 2017-05-31
+-------------------
+
+ - olog: add an 'obslog' alias
+ - olog: add an '--all' option to show the whole obsolescence history tree.
+ - evolution: add an experiment to track the effect of rewrites.
+   (See hg help - evolve for details)
+ - exchange: fix the "relevant-markers" algorithm to include inline prune.
+   This will impact discovery of obsmarkers between server and client if one
+   still uses the old algorithm. Please upgrade both clients and servers as
+   soon as possible.
+   (See changeset 176d1a0ce385 in core Mercurial for details)
+ - obsdiscovery: add a config flag to disable all obsmarkers discovery
+   (See hg help - evolve for details)
+ - template: add a 'precursors' template that display the closests precursors of changesets
+ - template: add a 'successors' template that display the closests successors of changesets
+ - template: add a 'obsfate' template that display how a changeset has evolved
+ - new discovery experiment: add options to restrict memory consumption on
+   large repository (see "hg help -e evolve" for details).
+ - evolve: fix --rev handling in --list mode
+
+6.2.1 -- 2017-05-23
+-------------------
+
+ - prune: fix a crash related to color handling,
+ - next: fix a crash related to color handling,
+ - discovery: document the 'obshashrange' experiment,
+ - cache: reduce the warming load in case of reset,
+ - cache: add a 'experimental.obshashcache.warm-cache' option to allow
+   disabling post transaction cache warming.
+
+6.2.0 -- 2017-05-18
+-------------------
+
+ - olog: a new command to inspect the obs-history of a changeset (hg-4.0 + only),
+ - topic: have thg display topic name if possible,
+ - blackbox: log more information about discovery and cache computation,
+ - obscache: more efficient update in the (rare) case of a transaction adding
+   markers without changesets,
+ - obscache: fix more cache invalidation propagation,
+ - obscache: also enable the new cache (from 6.1.0) for 'evolve.server-only',
+ - obshashrange-cache: update incrementally in the (common) case of a
+   transaction not affecting existing range,
+ - obshashrange-cache: keep the cache warm after each transaction,
+ - topic: now requires Mercurial 4.0 or above,
+ - stack: now display if current revision is in bad state (issue5533),
+ - stack: fix json output to be valid json.
+
+6.1.0 -- 2017-05-03
+-------------------
+
+ - improve message about obsolete working copy parent,
+ - improve message issued  when accessing hidden nodes (4.2 only),
+ - introduce a new caches to reduce the impact of evolution on read-only commands,
+ - add a 'experimental.auto-publish' config. See `hg help -e evolve` for details.
+ - fix the propagation of some some cache invalidation,
+
+6.0.1 -- 2017-04-20
+-------------------
+
+ - template: adapt to change in 4.2,
+ - fix 'debugrecordpruneparents' (outdated API usage)
+ - checkheads: give priority to updated 4.2 code,
+ - serveronly: fix repository initialization.
+
+6.0.0 -- 2017-03-31
+-------------------
+
+- push: improved detection of obsoleted remote branch (issue4354),
+- drop compatibility for Mercurial < 3.8,
+- removed old (unpackaged) pushexperiment extension,
+- move all extensions in the official 'hgext3rd' namespace package,
+- add the "topic" experimental extensions. See the README.topic file for details
+- officially ship 'evolve.serveronly' extensions. That extensions contains
+  only the part related to exchange and is intended to be used by server.
+
+  Using the extension will enable evolution, use 'experimental.evolution=!'
+  to disable obsmarkers echange.  The old '__temporary__.advertiseobsolete'
+  option is no longer supported.
+
+- a new prototype of obsmarker discovery is available. The prototype is still
+  at early stage and not recommended for production.
+  Examples of current limitations:
+
+  - write access to the repo is highly recommanded for all operation,
+  - large memory footprint,
+  - initial caching is slow,
+  - unusable on large repo (because of various issue pointed earlier),
+  - likely to constains various bugs.
+
+  It can be tested by setting `experimental.obshashrange=1` on both client and
+  server. It is recommanded to get in touch with the evolve maintainer if you
+  decide to test it.
+
+- the 'debugrecordpruneparents' have been moved into the 'evolve.legacy'
+  separate extension. enable that extentions if you need to convert/update
+  markers in an old repository.
+
+5.6.1 -- 2017-02-28
+-------------------
+
+- fix a crash that sometime happened when evolving merges.
+
+5.6.0 -- 2017-02-01
+-------------------
+
+- compatibility with Mercurial 4.1.
+- improvement of prune error message.
+- fold: require --from flag for folding revisions to working copy
+- fix crash when trying to fold an empty revision set (issue5453)
+- uncommit: preserve copy information of remaining files (issue5403)
+
+5.5.0 -- 2016-10-30
+-------------------
+
+- The {obsolete} template now yield "obsolete" or "".
+- compatibility with Mercurial 4.0
+- Fix erroneous manifest computation when solving 'bumped' changeset.
+- split: avoid crash on empty commit (issue5191),
+- next: improve locking to avoid issue with working copy parent (issue5244)
+- prev: improve locking to avoid issue with working copy parent (issue5244)
+- evolve: fix abort suggestion to include '.' in 'hg update -C .'
+
+5.4.1 -- 2016-08-01
+-------------------
+
+ - compat with Mercurial 3.9
+
+5.4.0 -- 2016-05-06
+-------------------
+
+- Some collaboration with the topic experimental extensions,
+  - hg evolve --all with consider all troubles in your current topic,
+  - preserve 'topic' during evolve,
+  - 'next' and 'prev' restrict themself to the current topic by default,
+- remove the dangerous 'kill' alias for 'prune' (because 'hg kill -1' without
+  the leading 'hg' will give you an hardtime)
+- during 'hg evolve' skip unsupported merge instead of aborting
+- various documentation fix and update
+- hg summary now suggest 'hg evolve --continue when appropriate`
+- compatibility with Mercurial 3.8 'hgext' namespace package.
+- small improvement to the `hg split` instruction
+- add a 'metaedit' command to rewrite changeset meta data.
+
+5.3.0 -- 2016-02-11
+-------------------
+
+- split: add a new command to split changesets,
+- tests: drop our copy of 'run-tests.py' use core one instead,
+- bookmark: do all bookmark movement within a transaction.
+- evolve: compatibility with Mercurial 3.7
+- evolve: support merge with a single obsolete parent (hg-3.7+ only)
+- evolve: prevent added file to be marked as unknown if evolve fails (issue4966)
+- evolve: stop relying on graftstate file for save evolve state
+          (for `hg evolve --continue`)
+- evolve: fix divergence resolution when it result in an empty commit
+          (issue4950) (hg-3.5+ only)
+- no longer lock the repository for `hg parents` (issue4895)
+- updated help for the `evolve` command
+
+5.2.1 -- 2015-11-02
+-------------------
+
+- add compatibility with Mercurial 3.6
+- prune: fixed possible issue with lock and bookmark
+- next/prev: fixed possible issue with lock and bookmark
+- add some progress data during changesets discovery
+- take advantage of dirstate/transaction collaboration
+
+5.2.0 -- 2015-06-25
+-------------------
+
+- evolve: gain a --rev option to control what revisions to evolve (issue4391)
+- evolve: revision are processed in the order they stack on destination
+- evolve: properly skip unstable revision with non-evolved unstable parent
+- evolve: gain --unstable --divergent --bumped flag to select the trouble
+- evolve: issue more useful error message and hint when evolve has nothing to
+          do as invocated.
+- evolve: bare `hg evolve` commands now abort when multiple changesets could be
+          a target.
+- evolve: `hg evolve --all` only evolve changeset that will end up as
+          descendant of the current working copy. The old behavior of `--all`
+          in now in `--all --any`.
+- evolve: add a 'experimental.evolutioncommands' for fine grained commands
+          enabling
+- next/prev: requires `--merge` to move with uncommitted changes
+- next: significantly reword error messages
+- next: add a --evolve flag to evolve aspiring children when on a head
+
+5.1.5 -- 2015-06-23
+-------------------
+
+- minor documentation cleanup
+- support -i option for `hg amend` if commit supports it (3.4)
+- fix the `debugrecordpruneparents` utility
+- fix some possible crash during command abort (release nonexistent transaction)
+- fix simple4server bug tracker URL
+- compatibility with bookmark API change in future Mercurial 3.5
+- prune no longer move the active bookmark for no reason (issue4559)
+- evolve: stop reporting divergence base as missing when we actually have it
+- significant performance improvement for all revsets.
+- provide a hint of how to update to the successor of an obsolete working copy
+  parent.
+
+5.1.4 -- 2015-04-23
+-------------------
+
+- significant documentation update
+- fix issue4616: pulling with bundle2 would crash if common marker when
+  discovered on non-served changesets.
+- fix the debugobsrelsethashtree command
+
+5.1.3 -- 2015-04-20
+-------------------
+
+- discovery: fix misbehaving discovery across python version
+- pull: properly install the bundle2 par generator
+  (avoid sending all markers for each pull)
+- commit: avoid potential deadlock (acquires wlock before lock)
+- graft: avoid potential deadlock (acquires wlock before lock)
+
+5.1.2 -- 2015-04-01
+-------------------
+
+- evolve: prevent a crash in httpclient_pushobsmarkers() when pushing
+
+5.1.1 -- 2015-03-05
+-------------------
+
+- debugobsconvert: fix invalid markers during conversion
+- discovery: cache some of the obs hash computation to improve performance (issue4518)
+- revset: fix some crash with (issue4515)
+
+5.1 -- 2015-01-30
+-------------------
+
+- evolve: explicitly disable bookmark on evolve (issue4432)
+- evolve: don't abort Mercurial on version mismatch
+- compatibility with mercurial 3.3
+
+5.0.2 -- 2014-12-14
+-------------------
+
+- evolve: remove dependency to the rebase extension
+
+5.0.1 -- 2014-11-25
+-------------------
+
+- amend: fix --logfile argument
+- evolve: preserve branch change when evolving
+- evolve: fix potential crash while solving `bumped` changesets.
+- uncommit: abort when rev specifies the current changeset
+- evolve: various message improvement
+- evolve: fix selection of changeset to evolve from the middle of a stack (issue4434)
+- evolve: make next/prev only move bookmarks optionally
+- evolve: tell user which "base of divergent changeset" is not found
+
+5.0.0 -- 2014-10-22
+-------------------
+
+- drop compat with Mercurial pre 3.2
+- uncommit: add a --rev argument
+- evolve: add a `working directory now at xxxxxxxxxx` message
+- evolve: automatically translate obsolete hashes when evolving
+- properly skip marker creating if patch apply cleanly
+- prune: work around a massive slowdown from lazy revset
+- grab: "fix" the grab alias on window
+
+- fix an issue where prune performance were quadratic with the number of
+  changesets pruned.
+- pull: use discovery to pull less obsmarkers through bundle2
+
+
+4.1.0 -- 2014-08-08
+-------------------
+
+- amend: add -D/--current-date option
+- amend: add -U/--current-user option
+- evolve: add a --tool option
+- evolve: add a --confirm option
+- mark "commit -o", "graft -o" and "graft -O" as deprecated since they are
+  unlikely to eventually make it into core.
+- push obsmarkers and phases in the same transaction than changesets
+  (when using hg >= 3.1 and bundle2-exp is enabled)
+- hide message about the obsolescence marker exchange behind a
+  `experimental.verbose-obsolescence-exchange` variable (default to False).
+
+4.0.1 -- 2014-08-08
+-------------------
+
+- createmarkers() accept an iterable (for compat with other extension)
+
+4.0.0 -- 2014-06-03
+-------------------
+
+- require Mercurial version 3.0.1 or above
+- some compatibility fixes with future 3.1.0
+- deprecated `gup` and `gdown` in favor of prev and next
+- record parent of pruned parent at prune time
+- added a `debugobsstorestat` command to gather data on obsmarker content.
+- added a `debugrecordpruneparents` command to upgrade existing prune marker
+  with parent information. Please run it once per repo after upgrading.
+- improvement to obsolescence marker exchange:
+  - added progress when pushing obsmarkers
+  - added multiple output during obsolescence markers exchange
+  - only push markers relevant to pushed subset
+  - add a new experimental way to exchange marker (when server support):
+
+    - added progress when pulling obsmarkers
+    - only pull markers relevant to pulled subset
+    - avoid exchanging common markers in some case
+    - use bundle2 as transport when available.
+
+ - add a hook related to the new commands
+
+3.3.2 -- 2014-05-14
+-------------------
+
+- fix a bug where evolve were creating changeset with 2 parents on windows
+  (fix issues #16, #35 and #42)
+- adds a --obsolete flag to import (requires Mercurial 3.0)
+- prune: update to successor rather than parent when pruning '.' with -s
+- fold: add missing --message and --logfile option
+- fold: add squash as an alias
+
+3.3.1 -- 2014-04-23
+-------------------
+
+- various language fix
+- active bookmark now move when using prev/next (#37)
+- fix some preservation of rename information on evolve (#33)
+- abort when evolve tries to move a node on top of itself (will helps on the #35 front)
+- fold: enable --date and --user options
+
+3.3.0 -- 2014-03-04
+-------------------
+
+- raise Mercurial's minimal requirement to 2.7
+- drop `latercomer` and `conflicting` compatibility. Those old alias are
+  deprecated for a long time now.
+- add verbose hint about how to handle corner case by hand.
+  This should help people until evolve is able to to it itself.
+- removed the qsync extension. The only user I knew about (logilab) is not
+  using it anymore. It not compatible with coming Mercurial version 2.9.
+- add progress indicator for long evolve command
+- report troubles creation from `hg import`
+
+3.2.0 -- 2013-11-15
+-------------------
+
+- conform to the Mercurial custom of lowercase messages
+- added a small extension to experiment with obsolescence marker push
+- amend: drop the deprecated note option
+- amend: use core mechanism for amend (fix multiple bugs)
+- parents command: add "working directory parent is obsolete" message
+- evolve command: allow updating to the successor if the parent is
+  obsolete
+- gdown and gup commands: add next and previous alias, respectively
+- make grab aliases compatible with Mercurial 2.8
+- Tested with 2.6, 2.7 and 2.8
+
+3.1.0 -- 2013-02-11
+-------------------
+
+- amend: drop deprecated --change option for amend
+- alias: add a grab alias to be used instead of graft -O
+- touch: add a --duplicate option to *not* obsolete the old version
+- touch: fix touching multiple revision at the same time
+- evolve: add a --all option
+- prune: various minor improvements
+- prune: add option to prune a specific bookmark
+- prune: add -u and -d option to control metadata
+
+3.0.0 -- 2013-02-02
+-------------------
+
+- compatibility with 2.5
+
+2.2.0 --
+-------------------
+
+- make evolve smarter at picking next troubled to solved without --any
+
+2.1.0 -- 2012-12-03
+-------------------
+
+- qsync fixes
+- have qfold ask for commit message
+
+2.0.0 -- 2012-10-26
+-------------------
+
+- compat with mercurial 2.4
+
+1.1.0 -- 2012-10-26
+-------------------
+
+- fix troubles creation reporting from rebase
+- rename latecomer to bumped
+- renamed conflicting to divergent
+- smarter divergent handling
+
+1.0.2 -- 2012-09-19
+-------------------
+
+- fix hg fold bug
+- fix hg pull --rebase
+- fix detection of conflict with external tools
+- adapt to core movement (caches and --amend)
+
+1.0.1 -- 2012-08-31
+-------------------
+
+- documentation improvement
+- fix a performance bug with hgweb
+
+1.0 -- 2012-08-29
+-------------------
+
+- Align with Mercurial version 2.3 (drop 2.2 support).
+- stabilize handle killed parent
+- stabilize handle late comer
+- stabilize handle conflicting
+- stabilize get a --continue switch
+- merge and update ignore extinct changeset in most case.
+- new "troubled()" revset
+- summary now reports troubles changesets
+- new touch command
+- new fold command
+- new basic olog alias
+
+- rebase refuse to work on public changeset again
+- rebase explicitly state that there is nothing to rebase because everything is
+  extinct() when that happen.
+- amend now cleanly abort when --change switch is misused
+
+
+0.7 -- 2012-08-06
+-------------------
+
+- hook: work around insanely huge value in obsolete pushkey call
+- pushkey: properly handle abort during obsolete markers push
+- amend: wrap the whole process in a single transaction.
+- evolve: tweak and add EOL to kill warning
+- obsolete: fix doc, rebase no longer aborts with --keep
+- obsolete/evolve: fix grammar in prerequisite messages
+- evolve: avoid duplication in graft wrapper
+- evolve: graft --continue is optional, test
+
+0.6 -- 2012-07-31
+-------------------
+
+- obsolete: change warning output to match mercurial core on
+- qsync: ignore nonexistent nodes
+- make compat server both compatible with "dump" and "dump%i" version
+
+0.5 -- 2012-07-16
+-------------------
+
+- obsolete: Detect conflicting changeset!
+- obsolete: adapt to core: marker are written in transaction now
+- evolve: add the solve alias to obsolete
+- doc: big update of terms and summary of the concept
+- evolve: switch the official name for "kill" to prune
+
+
+0.4.1 -- 2012-07-10
+-------------------
+
+- [convert] properly exclude null successors from conversion
+- Ignore buggy marker in newerversion
+
+
+0.4.0 -- 2012-07-06
+-------------------
+
+- obsolete: public changeset are no longer latecomer.
+- obsolete: move to official binary format
+- adapt for new mercurial
+- obsolete: we are not compatible with 2.1 any more
+
+0.3.0 -- 2012-06-27
+-------------------
+
+- obsolete:  Add "latecomer" error detection (stabilize does not handle resolution yet)
+- evolve:    Introduce a new `uncommit` command to remove change from a changeset
+- rebase:    allow the use of --keep again
+- commit:    --amend option create obsolete marker (but still strip)
+- obsolete:  fewer marker are created when collapsing revision.
+- revset:    add, successors(), allsuccessors(), precursors(), allprecursors(),
+             latecomer() and hidden()
+- evolve:    add `prune` alias to `kill`.
+- stabilize: clearly state that stabilize does not handle conflict
+- template:  add an {obsolete} keyword
+
+0.2.0 -- 2012-06-20
+-------------------
+
+- stabilize: improve choice of the next changeset to stabilize
+- stabilize: improve resolution of several corner case
+- rebase:    handle removing empty changesets
+- rebase:    handle --collapse
+- evolve:   add `obsolete` alias to `kill`
+- evolve:   add `evolve` alias to `stabilize`
--- a/MANIFEST.in	Tue Jul 25 02:29:28 2017 +0200
+++ b/MANIFEST.in	Tue Nov 14 23:04:04 2017 +0100
@@ -18,9 +18,10 @@
 include hgext3rd/__init__.py
 include hgext3rd/evolve/*.py
 include hgext3rd/topic/*.py
+include hgext3rd/topic/README
 include MANIFEST.in
 include README
-include README-topic
+include CHANGELOG
 include setup.py
 include tests/*.py
 include tests/*.sh
--- a/README	Tue Jul 25 02:29:28 2017 +0200
+++ b/README	Tue Nov 14 23:04:04 2017 +0100
@@ -117,574 +117,3 @@
 In addition, we have compatibility branches to check tests on older version of
 Mercurial. They are the "mercurial-x.y" branches. They are used to apply
 expected test change only, no code change should happen there.
-
-Changelog
-=========
-
-6.6.0 - in progress
--------------------
-
-  - amend: add a --extract flag to move change back to the working copy
-    (same as uncommit, but accessible through the amend commit)
-  - split: now properly refuse to split public changeset
-  - commands: unify and improve the pre-rewrite validation and error message
-  - uncommit: add support for --current-date and --current-user option
-  - fold: add support for --current-date and --current-user option
-  - metaedit: add support for --current-date and --current-user option
-  - split add support for --current-date and --current-user option
-
-  - topic: add --age option to sort topic by the most recently touched,
-  - topic: add a 't0' to access the root of a topic while keeping it active,
-  - topic: allow 'hg prev' to me move to 't0',
-  - topic: add a config option to enforce topic on new commit
-    (experimental.enforce-topic)
-
-6.5.0 -- 2017-07-02
--------------------
-
-features:
-
- - obslog: gain a --patch flag to display changes introduced by the evolution
-  (Currently limited to in simple case only)
- - log: display obsolescence fate by default, (future 4.3 only)
- - doc: various minor improvement.
-
-bugfixes:
-
- - evolve: fix branch preservation for merge,
- - obsfate: improve support for advanced template reformating,
- - split: preserve author of the splitted changeset.
- - grab: properly fix hg executable on windows.
-
-topic (0.1.0):
-
- - stack: also show the unstable status for the current changeset, (issue5553)
- - stack: properly abort when and unknown topic is requested,
- - stack: add basic and raw support for named branches,
- - topic: changing topic on revs no longer adds extra instability, (issue5441)
- - topic: topics: rename '--change' flag to '--rev' flag,
- - topic: multiple large performance improvements,
- - topic: various small output improvement,
- - topic: improved topic preservation for various commands.
-
-
-6.4.0 -- 2017-06-16
--------------------
-
- - template: signifiant improvement to the '{obsfate}' template (now 4.2+ only)
- - template: fix 'successors' and 'precursors' template to expose hex-node
- - effect flag: the experiment is now active by default,
-   (see 'hg help -e evolve' to opt out)
- - effect flag: fix a small bug related to hidden changeset,
- - obscache: reduce impact on large repository
- - obshashrange: install a '.max-revs' option see extension help for details
-
-6.3.1 -- 2017-06-01
--------------------
-
- - also backport the "revelant-markers" fix when using "evolve.serveronly"
-
-6.3.0 -- 2017-05-31
--------------------
-
- - olog: add an 'obslog' alias
- - olog: add an '--all' option to show the whole obsolescence history tree.
- - evolution: add an experiment to track the effect of rewrites.
-   (See hg help - evolve for details)
- - exchange: fix the "relevant-markers" algorithm to include inline prune.
-   This will impact discovery of obsmarkers between server and client if one
-   still uses the old algorithm. Please upgrade both clients and servers as
-   soon as possible.
-   (See changeset 176d1a0ce385 in core Mercurial for details)
- - obsdiscovery: add a config flag to disable all obsmarkers discovery
-   (See hg help - evolve for details)
- - template: add a 'precursors' template that display the closests precursors of changesets
- - template: add a 'successors' template that display the closests successors of changesets
- - template: add a 'obsfate' template that display how a changeset has evolved
- - new discovery experiment: add options to restrict memory consumption on
-   large repository (see "hg help -e evolve" for details).
- - evolve: fix --rev handling in --list mode
-
-6.2.1 -- 2017-05-23
--------------------
-
- - prune: fix a crash related to color handling,
- - next: fix a crash related to color handling,
- - discovery: document the 'obshashrange' experiment,
- - cache: reduce the warming load in case of reset,
- - cache: add a 'experimental.obshashcache.warm-cache' option to allow
-   disabling post transaction cache warming.
-
-6.2.0 -- 2017-05-18
--------------------
-
- - olog: a new command to inspect the obs-history of a changeset (hg-4.0 + only),
- - topic: have thg display topic name if possible,
- - blackbox: log more information about discovery and cache computation,
- - obscache: more efficient update in the (rare) case of a transaction adding
-   markers without changesets,
- - obscache: fix more cache invalidation propagation,
- - obscache: also enable the new cache (from 6.1.0) for 'evolve.server-only',
- - obshashrange-cache: update incrementally in the (common) case of a
-   transaction not affecting existing range,
- - obshashrange-cache: keep the cache warm after each transaction,
- - topic: now requires Mercurial 4.0 or above,
- - stack: now display if current revision is in bad state (issue5533),
- - stack: fix json output to be valid json.
-
-6.1.0 -- 2017-05-03
--------------------
-
- - improve message about obsolete working copy parent,
- - improve message issued  when accessing hidden nodes (4.2 only),
- - introduce a new caches to reduce the impact of evolution on read-only commands,
- - add a 'experimental.auto-publish' config. See `hg help -e evolve` for details.
- - fix the propagation of some some cache invalidation,
-
-6.0.1 -- 2017-04-20
--------------------
-
- - template: adapt to change in 4.2,
- - fix 'debugrecordpruneparents' (outdated API usage)
- - checkheads: give priority to updated 4.2 code,
- - serveronly: fix repository initialization.
-
-6.0.0 -- 2017-03-31
--------------------
-
-- push: improved detection of obsoleted remote branch (issue4354),
-- drop compatibility for Mercurial < 3.8,
-- removed old (unpackaged) pushexperiment extension,
-- move all extensions in the official 'hgext3rd' namespace package,
-- add the "topic" experimental extensions. See the README.topic file for details
-- officially ship 'evolve.serveronly' extensions. That extensions contains
-  only the part related to exchange and is intended to be used by server.
-
-  Using the extension will enable evolution, use 'experimental.evolution=!'
-  to disable obsmarkers echange.  The old '__temporary__.advertiseobsolete'
-  option is no longer supported.
-
-- a new prototype of obsmarker discovery is available. The prototype is still
-  at early stage and not recommended for production.
-  Examples of current limitations:
-
-  - write access to the repo is highly recommanded for all operation,
-  - large memory footprint,
-  - initial caching is slow,
-  - unusable on large repo (because of various issue pointed earlier),
-  - likely to constains various bugs.
-
-  It can be tested by setting `experimental.obshashrange=1` on both client and
-  server. It is recommanded to get in touch with the evolve maintainer if you
-  decide to test it.
-
-- the 'debugrecordpruneparents' have been moved into the 'evolve.legacy'
-  separate extension. enable that extentions if you need to convert/update
-  markers in an old repository.
-
-5.6.1 -- 2017-02-28
--------------------
-
-- fix a crash that sometime happened when evolving merges.
-
-5.6.0 -- 2017-02-01
--------------------
-
-- compatibility with Mercurial 4.1.
-- improvement of prune error message.
-- fold: require --from flag for folding revisions to working copy
-- fix crash when trying to fold an empty revision set (issue5453)
-- uncommit: preserve copy information of remaining files (issue5403)
-
-5.5.0 -- 2016-10-30
--------------------
-
-- The {obsolete} template now yield "obsolete" or "".
-- compatibility with Mercurial 4.0
-- Fix erroneous manifest computation when solving 'bumped' changeset.
-- split: avoid crash on empty commit (issue5191),
-- next: improve locking to avoid issue with working copy parent (issue5244)
-- prev: improve locking to avoid issue with working copy parent (issue5244)
-- evolve: fix abort suggestion to include '.' in 'hg update -C .'
-
-5.4.1 -- 2016-08-01
--------------------
-
- - compat with Mercurial 3.9
-
-5.4.0 -- 2016-05-06
--------------------
-
-- Some collaboration with the topic experimental extensions,
-  - hg evolve --all with consider all troubles in your current topic,
-  - preserve 'topic' during evolve,
-  - 'next' and 'prev' restrict themself to the current topic by default,
-- remove the dangerous 'kill' alias for 'prune' (because 'hg kill -1' without
-  the leading 'hg' will give you an hardtime)
-- during 'hg evolve' skip unsupported merge instead of aborting
-- various documentation fix and update
-- hg summary now suggest 'hg evolve --continue when appropriate`
-- compatibility with Mercurial 3.8 'hgext' namespace package.
-- small improvement to the `hg split` instruction
-- add a 'metaedit' command to rewrite changeset meta data.
-
-5.3.0 -- 2016-02-11
--------------------
-
-- split: add a new command to split changesets,
-- tests: drop our copy of 'run-tests.py' use core one instead,
-- bookmark: do all bookmark movement within a transaction.
-- evolve: compatibility with Mercurial 3.7
-- evolve: support merge with a single obsolete parent (hg-3.7+ only)
-- evolve: prevent added file to be marked as unknown if evolve fails (issue4966)
-- evolve: stop relying on graftstate file for save evolve state
-          (for `hg evolve --continue`)
-- evolve: fix divergence resolution when it result in an empty commit
-          (issue4950) (hg-3.5+ only)
-- no longer lock the repository for `hg parents` (issue4895)
-- updated help for the `evolve` command
-
-5.2.1 -- 2015-11-02
--------------------
-
-- add compatibility with Mercurial 3.6
-- prune: fixed possible issue with lock and bookmark
-- next/prev: fixed possible issue with lock and bookmark
-- add some progress data during changesets discovery
-- take advantage of dirstate/transaction collaboration
-
-5.2.0 -- 2015-06-25
--------------------
-
-- evolve: gain a --rev option to control what revisions to evolve (issue4391)
-- evolve: revision are processed in the order they stack on destination
-- evolve: properly skip unstable revision with non-evolved unstable parent
-- evolve: gain --unstable --divergent --bumped flag to select the trouble
-- evolve: issue more useful error message and hint when evolve has nothing to
-          do as invocated.
-- evolve: bare `hg evolve` commands now abort when multiple changesets could be
-          a target.
-- evolve: `hg evolve --all` only evolve changeset that will end up as
-          descendant of the current working copy. The old behavior of `--all`
-          in now in `--all --any`.
-- evolve: add a 'experimental.evolutioncommands' for fine grained commands
-          enabling
-- next/prev: requires `--merge` to move with uncommitted changes
-- next: significantly reword error messages
-- next: add a --evolve flag to evolve aspiring children when on a head
-
-5.1.5 -- 2015-06-23
--------------------
-
-- minor documentation cleanup
-- support -i option for `hg amend` if commit supports it (3.4)
-- fix the `debugrecordpruneparents` utility
-- fix some possible crash during command abort (release nonexistent transaction)
-- fix simple4server bug tracker URL
-- compatibility with bookmark API change in future Mercurial 3.5
-- prune no longer move the active bookmark for no reason (issue4559)
-- evolve: stop reporting divergence base as missing when we actually have it
-- significant performance improvement for all revsets.
-- provide a hint of how to update to the successor of an obsolete working copy
-  parent.
-
-5.1.4 -- 2015-04-23
--------------------
-
-- significant documentation update
-- fix issue4616: pulling with bundle2 would crash if common marker when
-  discovered on non-served changesets.
-- fix the debugobsrelsethashtree command
-
-5.1.3 -- 2015-04-20
--------------------
-
-- discovery: fix misbehaving discovery across python version
-- pull: properly install the bundle2 par generator
-  (avoid sending all markers for each pull)
-- commit: avoid potential deadlock (acquires wlock before lock)
-- graft: avoid potential deadlock (acquires wlock before lock)
-
-5.1.2 -- 2015-04-01
--------------------
-
-- evolve: prevent a crash in httpclient_pushobsmarkers() when pushing
-
-5.1.1 -- 2015-03-05
--------------------
-
-- debugobsconvert: fix invalid markers during conversion
-- discovery: cache some of the obs hash computation to improve performance (issue4518)
-- revset: fix some crash with (issue4515)
-
-5.1 -- 2015-01-30
--------------------
-
-- evolve: explicitly disable bookmark on evolve (issue4432)
-- evolve: don't abort Mercurial on version mismatch
-- compatibility with mercurial 3.3
-
-5.0.2 -- 2014-12-14
--------------------
-
-- evolve: remove dependency to the rebase extension
-
-5.0.1 -- 2014-11-25
--------------------
-
-- amend: fix --logfile argument
-- evolve: preserve branch change when evolving
-- evolve: fix potential crash while solving `bumped` changesets.
-- uncommit: abort when rev specifies the current changeset
-- evolve: various message improvement
-- evolve: fix selection of changeset to evolve from the middle of a stack (issue4434)
-- evolve: make next/prev only move bookmarks optionally
-- evolve: tell user which "base of divergent changeset" is not found
-
-5.0.0 -- 2014-10-22
--------------------
-
-- drop compat with Mercurial pre 3.2
-- uncommit: add a --rev argument
-- evolve: add a `working directory now at xxxxxxxxxx` message
-- evolve: automatically translate obsolete hashes when evolving
-- properly skip marker creating if patch apply cleanly
-- prune: work around a massive slowdown from lazy revset
-- grab: "fix" the grab alias on window
-
-- fix an issue where prune performance were quadratic with the number of
-  changesets pruned.
-- pull: use discovery to pull less obsmarkers through bundle2
-
-
-4.1.0 -- 2014-08-08
--------------------
-
-- amend: add -D/--current-date option
-- amend: add -U/--current-user option
-- evolve: add a --tool option
-- evolve: add a --confirm option
-- mark "commit -o", "graft -o" and "graft -O" as deprecated since they are
-  unlikely to eventually make it into core.
-- push obsmarkers and phases in the same transaction than changesets
-  (when using hg >= 3.1 and bundle2-exp is enabled)
-- hide message about the obsolescence marker exchange behind a
-  `experimental.verbose-obsolescence-exchange` variable (default to False).
-
-4.0.1 -- 2014-08-08
--------------------
-
-- createmarkers() accept an iterable (for compat with other extension)
-
-4.0.0 -- 2014-06-03
--------------------
-
-- require Mercurial version 3.0.1 or above
-- some compatibility fixes with future 3.1.0
-- deprecated `gup` and `gdown` in favor of prev and next
-- record parent of pruned parent at prune time
-- added a `debugobsstorestat` command to gather data on obsmarker content.
-- added a `debugrecordpruneparents` command to upgrade existing prune marker
-  with parent information. Please run it once per repo after upgrading.
-- improvement to obsolescence marker exchange:
-  - added progress when pushing obsmarkers
-  - added multiple output during obsolescence markers exchange
-  - only push markers relevant to pushed subset
-  - add a new experimental way to exchange marker (when server support):
-
-    - added progress when pulling obsmarkers
-    - only pull markers relevant to pulled subset
-    - avoid exchanging common markers in some case
-    - use bundle2 as transport when available.
-
- - add a hook related to the new commands
-
-3.3.2 -- 2014-05-14
--------------------
-
-- fix a bug where evolve were creating changeset with 2 parents on windows
-  (fix issues #16, #35 and #42)
-- adds a --obsolete flag to import (requires Mercurial 3.0)
-- prune: update to successor rather than parent when pruning '.' with -s
-- fold: add missing --message and --logfile option
-- fold: add squash as an alias
-
-3.3.1 -- 2014-04-23
--------------------
-
-- various language fix
-- active bookmark now move when using prev/next (#37)
-- fix some preservation of rename information on evolve (#33)
-- abort when evolve tries to move a node on top of itself (will helps on the #35 front)
-- fold: enable --date and --user options
-
-3.3.0 -- 2014-03-04
--------------------
-
-- raise Mercurial's minimal requirement to 2.7
-- drop `latercomer` and `conflicting` compatibility. Those old alias are
-  deprecated for a long time now.
-- add verbose hint about how to handle corner case by hand.
-  This should help people until evolve is able to to it itself.
-- removed the qsync extension. The only user I knew about (logilab) is not
-  using it anymore. It not compatible with coming Mercurial version 2.9.
-- add progress indicator for long evolve command
-- report troubles creation from `hg import`
-
-3.2.0 -- 2013-11-15
--------------------
-
-- conform to the Mercurial custom of lowercase messages
-- added a small extension to experiment with obsolescence marker push
-- amend: drop the deprecated note option
-- amend: use core mechanism for amend (fix multiple bugs)
-- parents command: add "working directory parent is obsolete" message
-- evolve command: allow updating to the successor if the parent is
-  obsolete
-- gdown and gup commands: add next and previous alias, respectively
-- make grab aliases compatible with Mercurial 2.8
-- Tested with 2.6, 2.7 and 2.8
-
-3.1.0 -- 2013-02-11
--------------------
-
-- amend: drop deprecated --change option for amend
-- alias: add a grab alias to be used instead of graft -O
-- touch: add a --duplicate option to *not* obsolete the old version
-- touch: fix touching multiple revision at the same time
-- evolve: add a --all option
-- prune: various minor improvements
-- prune: add option to prune a specific bookmark
-- prune: add -u and -d option to control metadata
-
-3.0.0 -- 2013-02-02
--------------------
-
-- compatibility with 2.5
-
-2.2.0 --
--------------------
-
-- make evolve smarter at picking next troubled to solved without --any
-
-2.1.0 -- 2012-12-03
--------------------
-
-- qsync fixes
-- have qfold ask for commit message
-
-2.0.0 -- 2012-10-26
--------------------
-
-- compat with mercurial 2.4
-
-1.1.0 -- 2012-10-26
--------------------
-
-- fix troubles creation reporting from rebase
-- rename latecomer to bumped
-- renamed conflicting to divergent
-- smarter divergent handling
-
-1.0.2 -- 2012-09-19
--------------------
-
-- fix hg fold bug
-- fix hg pull --rebase
-- fix detection of conflict with external tools
-- adapt to core movement (caches and --amend)
-
-1.0.1 -- 2012-08-31
--------------------
-
-- documentation improvement
-- fix a performance bug with hgweb
-
-1.0 -- 2012-08-29
--------------------
-
-- Align with Mercurial version 2.3 (drop 2.2 support).
-- stabilize handle killed parent
-- stabilize handle late comer
-- stabilize handle conflicting
-- stabilize get a --continue switch
-- merge and update ignore extinct changeset in most case.
-- new "troubled()" revset
-- summary now reports troubles changesets
-- new touch command
-- new fold command
-- new basic olog alias
-
-- rebase refuse to work on public changeset again
-- rebase explicitly state that there is nothing to rebase because everything is
-  extinct() when that happen.
-- amend now cleanly abort when --change switch is misused
-
-
-0.7 -- 2012-08-06
--------------------
-
-- hook: work around insanely huge value in obsolete pushkey call
-- pushkey: properly handle abort during obsolete markers push
-- amend: wrap the whole process in a single transaction.
-- evolve: tweak and add EOL to kill warning
-- obsolete: fix doc, rebase no longer aborts with --keep
-- obsolete/evolve: fix grammar in prerequisite messages
-- evolve: avoid duplication in graft wrapper
-- evolve: graft --continue is optional, test
-
-0.6 -- 2012-07-31
--------------------
-
-- obsolete: change warning output to match mercurial core on
-- qsync: ignore nonexistent nodes
-- make compat server both compatible with "dump" and "dump%i" version
-
-0.5 -- 2012-07-16
--------------------
-
-- obsolete: Detect conflicting changeset!
-- obsolete: adapt to core: marker are written in transaction now
-- evolve: add the solve alias to obsolete
-- doc: big update of terms and summary of the concept
-- evolve: switch the official name for "kill" to prune
-
-
-0.4.1 -- 2012-07-10
--------------------
-
-- [convert] properly exclude null successors from conversion
-- Ignore buggy marker in newerversion
-
-
-0.4.0 -- 2012-07-06
--------------------
-
-- obsolete: public changeset are no longer latecomer.
-- obsolete: move to official binary format
-- adapt for new mercurial
-- obsolete: we are not compatible with 2.1 any more
-
-0.3.0 -- 2012-06-27
--------------------
-
-- obsolete:  Add "latecomer" error detection (stabilize does not handle resolution yet)
-- evolve:    Introduce a new `uncommit` command to remove change from a changeset
-- rebase:    allow the use of --keep again
-- commit:    --amend option create obsolete marker (but still strip)
-- obsolete:  fewer marker are created when collapsing revision.
-- revset:    add, successors(), allsuccessors(), precursors(), allprecursors(),
-             latecomer() and hidden()
-- evolve:    add `prune` alias to `kill`.
-- stabilize: clearly state that stabilize does not handle conflict
-- template:  add an {obsolete} keyword
-
-0.2.0 -- 2012-06-20
--------------------
-
-- stabilize: improve choice of the next changeset to stabilize
-- stabilize: improve resolution of several corner case
-- rebase:    handle removing empty changesets
-- rebase:    handle --collapse
-- evolve:   add `obsolete` alias to `kill`
-- evolve:   add `evolve` alias to `stabilize`
--- a/README-topic	Tue Jul 25 02:29:28 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-Topic Extension
-================
-
-This packages also provides the ``topic`` experiment in an independent
-extension. It implements a new experimental concept to provide lightweight
-feature branches for the mutable parts of the history. The experiments is still
-at an early stage and have significant usability and performance issues when
-enabled.
-
-How to Install
-==============
-
-The ``topic`` extension is included into the ``evolve` package, so the same instruction apply.
-
-Using Pip
----------
-
-You can install the latest version using pip::
-
-    $ pip install --user hg-evolve
-
-Then just enable it in you hgrc::
-
-    $ hg config --edit # adds the two line below:
-    [extensions]
-    topic =
-
-From Source
------------
-
-To install a local version from source::
-
-    $ hg clone https://www.mercurial-scm.org/repo/evolve/
-    $ cd evolve
-    $ make install-home
-
-Enable
-------
-
-The topic extensions is included in the evolve package. See the install instruction for evolve.
-
-Then enable it in you configuration::
-
-    $ hg config --edit # adds the two line below:
-    [extensions]
-    topic =
-
-Documentation
--------------
-
-* See 'hg help -e topic' for a generic help.
-* See 'hg help topics' and 'hg help stack' for help on specific commands.
-* See the 'tests/test-topic-tutorial.t' file for a quick tutorial.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/merge-test-compat.sh	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,15 @@
+#!/bin/bash
+set -euox pipefail
+
+unset GREP_OPTIONS
+NOTOPIC="--config experimental.topic-mode=ignore"
+
+compatbranches=`hg branches --quiet | grep 'mercurial-' | grep -v ':' | sort -n --reverse`
+prev='stable'
+for branch in $compatbranches; do
+    hg up $branch
+    hg merge $prev
+    hg commit -m "test-compat: merge $prev into $branch"
+    prev=$branch
+done
+
--- a/debian/changelog	Tue Jul 25 02:29:28 2017 +0200
+++ b/debian/changelog	Tue Nov 14 23:04:04 2017 +0100
@@ -1,8 +1,38 @@
-mercurial-evolve (6.5.0-1) UNRELEASED; urgency=medium
+mercurial-evolve (7.0.0-1) unstable; urgency=medium
+
+  * new upstream release
+
+ -- Pierre-Yves David <pierre-yves.david@ens-lyon.org>  Thu, 02 Nov 2017 00:30:29 +0100
+
+mercurial-evolve (6.8.0-1) unstable; urgency=medium
 
   * new upstream release
 
- -- Pierre-Yves David <marmoute@nodosa.octopoid.net>  Sun, 02 Jul 2017 19:35:17 +0200
+ -- Pierre-Yves David <pierre-yves.david@ens-lyon.org>  Mon, 23 Oct 2017 15:41:03 +0200
+
+mercurial-evolve (6.7.1-1) unstable; urgency=medium
+ 
+   * new upstream release
+ 
+ -- Pierre-Yves David <pierre-yves.david@ens-lyon.org>  Tue, 10 Oct 2017 16:03:23 +0200
+
+mercurial-evolve (6.7.0-1) unstable; urgency=medium
+
+  * new upstream release
+
+ -- Pierre-Yves David <pierre-yves.david@ens-lyon.org>  Wed, 27 Sep 2017 16:17:40 +0200
+
+mercurial-evolve (6.6.0-1) unstable; urgency=medium
+
+  * new upstream release
+
+ -- Pierre-Yves David <marmoute@nodosa.octopoid.net>  Tue, 25 Jul 2017 16:57:25 +0200
+
+mercurial-evolve (6.5.0-1) unstable; urgency=medium
+
+  * new upstream release
+
+ -- Pierre-Yves David <pierre-yves.david@ens-lyon.org>  Sun, 02 Jul 2017 19:35:17 +0200
 
 mercurial-evolve (6.4.0-1) unstable; urgency=medium
 
--- a/debian/control	Tue Jul 25 02:29:28 2017 +0200
+++ b/debian/control	Tue Nov 14 23:04:04 2017 +0100
@@ -7,7 +7,7 @@
  Pierre-Yves David <pierre-yves.david@logilab.fr>,
 Standards-Version: 3.9.3
 Build-Depends:
- mercurial (>= 3.4~),
+ mercurial (>= 4.1),
  python,
  debhelper (>= 8),
  python-sphinx (>= 1.0.8),
@@ -22,19 +22,12 @@
 Depends:
  ${python:Depends},
  ${misc:Depends},
- mercurial (>= 3.3~),
+ mercurial (>= 4.1),
 Description: evolve extension for Mercurial
  This package provides the experimental "evolve" extension for the Mercurial
  DVCS.
  .
  This extension provides several commands to mutate history and deal with issues
  it may raise.
- .
- It also:
-  - enables the "Changeset Obsolescence" feature of mercurial,
-  - alters core command and extension that rewrite history to use this feature,
-  - improves some aspects of the early implementation in Mercurial 2.3.
- .
- **These extensions are experimental and are not meant for production.**
 
 
--- a/docs/README	Tue Jul 25 02:29:28 2017 +0200
+++ b/docs/README	Tue Nov 14 23:04:04 2017 +0100
@@ -1,3 +1,22 @@
-doc generated with sphinx. tutorial exported using sphinxedhg
+Doc is generated with sphinx.
+
+You can generate the doc with:
+
+```
+make
+```
+
+# Tutorials
 
-http://hg.piranha.org.ua/sphinxedhg/
+For updating the tutorials, you need to have the docgraph extension installed
+(https://pypi.python.org/pypi/hg-docgraph).
+
+Then run the test-topic-tutorial.t and test-tutorial.t to update the output if
+needed.
+
+You'll need the dot binary (likely installed by the graphviz package in your
+package manager) in order to have graphviz graphs rendered in the html output.
+
+Simply run make in the docs directory should takes care of the conversion of
+the tutorial .t files into .rst files. Then sphinx should do the rest of the
+jobs by rendering graphviz graphs.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/commands.rst	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,70 @@
+-------------------------
+Evolve Commands Reference
+-------------------------
+
+.. highlight:: none
+
+amend
+-----
+
+.. hghelp:: amend
+
+evolve
+------
+
+.. hghelp:: evolve
+
+fold
+----
+
+.. hghelp:: fold
+
+metaedit
+--------
+
+.. hghelp:: metaedit
+
+next
+----
+
+.. hghelp:: next
+
+obslog
+------
+
+.. hghelp:: obslog
+
+pdiff
+-----
+
+.. hghelp:: pdiff
+
+previous
+--------
+
+.. hghelp:: previous
+
+prune
+-----
+
+.. hghelp:: prune
+
+pstatus
+-------
+
+.. hghelp:: pstatus
+
+split
+-----
+
+.. hghelp:: split
+
+touch
+-----
+
+.. hghelp:: touch
+
+uncommit
+--------
+
+.. hghelp:: uncommit
--- a/docs/conf.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/docs/conf.py	Tue Nov 14 23:04:04 2017 +0100
@@ -1,6 +1,16 @@
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = []
+from mercurial import demandimport
+demandimport.disable()
+from docutils import nodes
+from docutils.parsers.rst import Directive
+from mercurial import ui
+from mercurial import extensions as hgext
+from mercurial import commands
+import os
+
+extensions = ["sphinx.ext.graphviz"]
+
 # autoclass_content = 'both'
 # Add any paths that contain templates here, relative to this directory.
 # templates_path = []
@@ -122,3 +132,28 @@
 
 # Output file base name for HTML help builder.
 # htmlhelp_basename = ''
+
+graphviz_output_format = "svg"
+
+class hghelpdirective(Directive):
+    has_content = True
+
+    def run(self):
+        u = ui.ui()
+        if not hasattr(u, 'disablepager'):
+            return []
+        u.disablepager()
+        u.setconfig(
+            'extensions', 'evolve',
+            os.path.join(
+                os.path.abspath(os.path.dirname(__file__)),
+                os.pardir, 'hgext3rd', 'evolve'))
+        hgext.loadall(u)
+        u.pushbuffer()
+        commands.help_(u, self.content[0])
+        return [
+            nodes.literal_block(text=u.popbuffer())]
+
+
+def setup(app):
+    app.add_directive('hghelp', hghelpdirective)
--- a/docs/index.rst	Tue Jul 25 02:29:28 2017 +0200
+++ b/docs/index.rst	Tue Nov 14 23:04:04 2017 +0100
@@ -4,66 +4,98 @@
 Changeset Evolution with Mercurial
 ==================================
 
+`evolve`_ is a Mercurial extension for faster and safer mutable history. It
+implements the `changeset evolution`_ concept for `Mercurial`_.
+
+* It offers a safe and simple way to refine changesets locally and propagate
+  those changes to other repositories.
+
+* It can automatically detect and handle the complex issues that can arise from
+  exchanging draft changesets.
+
+* It even makes it possible for multiple developers to safely rewrite the same
+  parts of history in a distributed way.
+
+* It fully respects the Phases concept so users will only be able to rewrite
+  parts of the history that are safe to change. Phases have been part of
+  Mercurial since early 2012.
+
+.. _`evolve`: https://www.mercurial-scm.org/wiki/EvolveExtension
+.. _`Mercurial`: https://www.mercurial-scm.org/
+
+Installation and setup
+----------------------
+
+We recommend you subscribe to the `evolve-testers`_ mailing list to stay up
+to date with the latest news and announcement.
+
+.. _`evolve-testers`: https://www.mercurial-scm.org/mailman/listinfo/evolve-testers
+
+Using pip::
+
+    pip install --user hg-evolve
+
+Then add in your `hgrc` config::
+
+   [extensions]
+   evolve=
+
+You can easily edit the `hgrc` of a repository using `hg config --local`.
+Alternatively, you can edit your user configuration with `hg config --edit`.
+
+Table of Contents
+-----------------
+
 .. toctree::
    :maxdepth: 2
 
+   index
    user-guide
    sharing
    concepts
    from-mq
+   commands
+   known-doc-issues
 
-`evolve`_ is an experimental Mercurial extension for safe mutable history.
+.. _`changeset evolution`:
 
-.. _`evolve`: https://www.mercurial-scm.org/wiki/EvolveExtension
+What is Changeset Evolution?
+----------------------------
 
 With core Mercurial, changesets are permanent and immutable. You can
 commit new changesets to modify your source code, but you cannot
-modify or remove old changesets—they are carved in stone for all
-eternity.
-
-For years, Mercurial has included various extensions that allow
-history modification: ``rebase``, ``mq``, ``histedit``, and so forth.
-These are useful and popular extensions, and in fact history
-modification is one of the big reasons DVCSes (distributed version
-control systems) like Mercurial took off.
-
-But there's a catch: until now, Mercurial's various mechanisms for
-modifying history have been *unsafe*, in that changesets were
-destroyed (“stripped”) rather than simply made invisible.
+modify or remove old changesets.
 
-``evolve`` makes things better in a couple of ways:
+For years, Mercurial has included various commands that allow
+history modification: ``rebase``, ``histedit``, ``commit --amend`` and so forth.
+However, there's a catch: until now, Mercurial's various mechanisms for
+modifying history have been *unsafe*, in that changesets were
+destroyed (“stripped”) rather than simply hidden and still easy to recover.
 
-  * It changes the behaviour of most existing history modification
-    extensions (``rebase``, ``histedit``, etc.) so they use a safer
-    mechanism (*changeset obsolescence*, covered below) rather than
-    the older, less safe *strip* operation.
+``evolve`` makes things better by changing the behaviour of most existing
+history modification commands so they use a safer mechanism (*changeset
+obsolescence*, covered below) rather than the older, less safe *strip*
+operation.
 
-  * It provides a new way of modifying history that is roughly
-    equivalent to ``mq`` (but much nicer and safer).
-
-It helps to understand that ``evolve`` builds on infrastructure
-already in core Mercurial:
+``evolve`` is built on infrastructure in core Mercurial:
 
   * *Phases* (starting in Mercurial 2.1) allow you to distinguish
-    mutable and immutable changesets. We'll cover phases early in the
-    user guide, since understanding phases is essential to
-    understanding ``evolve``.
+    mutable and immutable changesets.
 
   * *Changeset obsolescence* (starting in Mercurial 2.3) is how
     Mercurial knows how history has been modified, specifically when
     one changeset replaces another. In the obsolescence model, a
     changeset is neither removed nor modified, but is instead marked
     *obsolete* and typically replaced by a *successor*. Obsolete
-    changesets usually become *hidden* as well. Obsolescence is an
-    invisible feature until you start using ``evolve``, so we'll cover
-    it in the user guide too.
+    changesets usually become *hidden* as well. Obsolescence is a
+    disabled feature in Mercurial until you start using ``evolve``.
 
 Some of the things you can do with ``evolve`` are:
 
   * Fix a mistake immediately: “Oops! I just committed a changeset
     with a syntax error—I'll fix that and amend the changeset so no
-    one sees my mistake.” (While this is possible using existing
-    features of core Mercurial, ``evolve`` makes it safer.)
+    one sees my mistake.” (While this is possible using default
+    features of core Mercurial, changeset evolution makes it safer.)
 
   * Fix a mistake a little bit later: “Oops! I broke the tests three
     commits back, but only noticed it now—I'll just update back to the
@@ -86,53 +118,49 @@
     for code review. The solution is to share mutable history with
     your reviewer, amending each changeset until it passes review.
 
-``evolve`` is experimental!
+  * Explore and audit the rewrite history of a changeset. Since Mercurial is
+    tracking the edits you make to a changeset, you can look at the history of
+    these edits. This is similar to Mercurial tracking the history of file
+    edits, but at the changeset level.
+
+Why the `evolve` extension?
 ---------------------------
 
-The long-term plan for ``evolve`` is to add it to core Mercurial.
-However, it is not yet stable enough for that. In particular:
-
-  * The UI is unstable: ``evolve``'s command names and command options
-    are not completely nailed down yet. They are subject to occasional
-    backwards-incompatible changes. If you write scripts that use
-    evolve commands, a future release could break your scripts.
+Mercurial core already has some support for `changeset evolution`_ so why have a
+dedicated extension?
 
-  * There are still some corner cases that aren't handled yet. If you
-    think you have found such a case, please check if it's already
-    described in the Mercurial bug tracker (https://bz.mercurial-scm.org/).
-    Bugs in ``evolve`` are files under component "evolution": use
-    `this query`_ to view open bugs in ``evolve``.
+The long-term plan for ``evolve`` is to add it to core Mercurial. However,
+having the extension helps us experiment with various user experience
+approaches and technical prototypes. Having a dedicated extension helps current
+users deploy the latest changes quickly and provides developers with low latency
+feedback.
 
-.. _`this query`: https://bz.mercurial-scm.org/buglist.cgi?component=evolution&bug_status=UNCONFIRMED&bug_status=CONFIRMED&bug_status=NEED_EXAMPLE
+Whenever we are happy with a experimental direction in the extension, the
+relevant code can go upstream into Core Mercurial.
 
-Installation and setup
-----------------------
-
-To use ``evolve``, you must:
+Development status
+------------------
 
-  #. Clone the ``evolve`` repository::
-
-       cd ~/src
-       hg clone https://www.mercurial-scm.org/repo/evolve
-
-  #. Configure the extension, either locally ::
-
-       hg config --local
-
-     or for all your repositories ::
+While well underway, the full implementation of the `changeset evolution`_
+concept is still a work in progress. Core Mercurial already supports many of the
+associated features, but for now they are still disabled by default. The current
+implementation has been usable for multiple years already, and some parts of it
+are used in production by multiple projects and companies (including the
+Mercurial project itself, Facebook, Google, etc…).
 
-       hg config --edit
-
-     Then add ::
-
-       evolve=~/src/evolve-main/hgext3rd/evolve/
+However, there are still some areas were the current implementation has gaps.
+This means some use cases or performance issues are not handled as well as they
+currently are without evolution. Mercurial has been around for a long time and
+is strongly committed to backward compatibility. Therefore turning evolution on
+by default today could regress the experience of some of our current users. The
+features will only be enabled by default at the point where users who do not use
+or care about the new features added by evolution won't be negatively impacted
+by the new default.
 
-     in the ``[extensions]`` section (adding the section if necessary). Use
-     the directory that you actually cloned to, of course.
+.. # .. _`this query`: https://bz.mercurial-scm.org/buglist.cgi?component=evolution&bug_status=UNCONFIRMED&bug_status=CONFIRMED&bug_status=NEED_EXAMPLE
 
-
-Next steps:
------------
+Resources
+---------
 
   * For a practical guide to using ``evolve`` in a single repository,
     see the `user guide`_.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/known-doc-issues.rst	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,45 @@
+.. Copyright © 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
+
+==============================================
+Known limitations of the current documentation
+==============================================
+
+Features not covered by tutorials
+=================================
+
+Some of the *newer* features of evolution might not be reflected in the
+documentation yet. You can directly check the inline documentation of the
+extension itself for fresher details using `hg help -e evolve`.
+
+Known undocumented features are:
+
+ * `hg prev`,
+ * `hg next`,
+ * `hg next --evolve`,
+ * `hg evolve --rev`,
+ * `hg evolve --list`,
+ * `hg obslog`,
+ * `hg split`,
+ * `hg metaedit`,
+ * `hg touch`,
+ * `hg amend --extract`,
+ * `hg pdiff`,
+ * `hg pstatus`,
+ * `hg amend -i`,
+ * various topic related elements (in particular `hg stack`),
+
+Unreferenced Documents
+======================
+
+There are documents with content not linked in the flow of the main
+documentation. Some might be outdated and some are too fresh to be integrated in
+the main flow yet.
+
+.. toctree::
+   :maxdepth: 1
+
+   evolve-faq
+   evolve-good-practice
+   obs-terms
+   tutorials/topic-tutorial
+   tutorials/tutorial
--- a/docs/makefile	Tue Jul 25 02:29:28 2017 +0200
+++ b/docs/makefile	Tue Nov 14 23:04:04 2017 +0100
@@ -1,8 +1,11 @@
 
-all: tutorials/tutorial.rst static/logo-evolve.ico
+all: tutorials/tutorial.rst tutorials/topic-tutorial.rst static/logo-evolve.ico
 	sphinx-build . ../html/
 
-tutorials/tutorial.rst: tutorials/tutorial.t
+tutorials/tutorial.rst: tutorials/tutorial.t test2rst.py
+	python test2rst.py tutorials/
+
+tutorials/topic-tutorial.rst: tutorials/topic-tutorial.t test2rst.py
 	python test2rst.py tutorials/
 
 static/logo-evolve.ico: static/logo-evolve.svg
--- a/docs/obs-terms.rst	Tue Jul 25 02:29:28 2017 +0200
+++ b/docs/obs-terms.rst	Tue Nov 14 23:04:04 2017 +0100
@@ -145,7 +145,7 @@
 |                     |                          | conflict)                   |
 |                     |                          |                             |
 |                     |                          | (possible alternative names:|
-|                     |                          | clashing, rival, concurent, |
+|                     |                          | clashing, rival, concurrent,|
 |                     |                          | conflicting)                |
 |                     |                          |                             |
 |                     +--------------------------+-----------------------------+
@@ -231,7 +231,7 @@
 This is an important name as hg pull/push will suggest it the same way it
 suggest merging when you add heads.
 
-alternative names:
+Alternative names:
 
 - solve (too generic ?)
 - stabilize
--- a/docs/sharing.rst	Tue Jul 25 02:29:28 2017 +0200
+++ b/docs/sharing.rst	Tue Nov 14 23:04:04 2017 +0100
@@ -45,8 +45,8 @@
 your test server before anything is carved in stone.
 
 A less common scenario is multiple developers sharing mutable history,
-typically for code review. We'll cover this scenario later. But first,
-single-user sharing.
+typically for code review. We'll cover this scenario later. First, we
+will cover single-user sharing.
 
 Sharing with a single developer
 -------------------------------
@@ -55,10 +55,10 @@
 ==========================================
 
 The key to shared mutable history is to keep your changesets in
-*draft* phase as you pass them around. Recall that by default, ``hg
-push`` promotes changesets from *draft* to *public*, and public
+*draft* phase as you pass them around. Recall that by default,
+``hg push`` promotes changesets from *draft* to *public*, and public
 changesets are immutable. You can change this behaviour by
-reconfiguring the *target* repository so that it is non-publishing.
+reconfiguring the *remote* repository so that it is non-publishing.
 (Short version: set ``phases.publish`` to ``false``. Long version
 follows.)
 
@@ -90,7 +90,7 @@
 
 The key to shared mutable history is to make the target repository, in
 this case ``test-repo``, non-publishing. And, of course, we have to
-enable ``evolve`` in both ``test-repo`` and ``dev-repo``.
+enable the ``evolve`` extension in both ``test-repo`` and ``dev-repo``.
 
 First, edit the configuration for ``test-repo``::
 
@@ -102,7 +102,7 @@
   publish = false
 
   [extensions]
-  evolve = /path/to/evolve-main/hgext3rd/evolve/
+  evolve =
 
 Then edit the configuration for ``dev-repo``::
 
@@ -111,7 +111,7 @@
 and add ::
 
   [extensions]
-  evolve = /path/to/evolve-main/hgext3rd/evolve/
+  evolve =
 
 Keep in mind that in real life, these repositories would probably be
 on separate computers, so you'd have to login to each one to configure
@@ -203,7 +203,7 @@
 As seen in figure 3, this transfers the new changeset *and* the
 obsolescence marker for revision 1. However, it does *not* transfer
 the temporary amend commit, because it is hidden. Push and pull
-transfer obsolesence markers between repositories, but they do not
+transfer obsolescence markers between repositories, but they do not
 transfer hidden changesets.
 
   [figure SG03: dev-repo grows new rev 2:60ff, marks 1:f649 obsolete]
@@ -251,7 +251,7 @@
 .. _`concept guide`: concepts.html
 
 So the picture in ``public`` is much simpler than in either
-``dev-repo`` or ``test-repo``. Neither our missteps nor our amendments
+``dev-repo`` or ``test-repo``. Neither of our missteps nor our amendments
 are publicly visible, just the final, beautifully polished changeset:
 
   [figure SG05: public repo with rev 0:0dc9, 1:de61, both public]
@@ -331,7 +331,7 @@
 and add ::
 
   [extensions]
-  evolve = /path/to/evolve-main/hgext3rd/evolve/
+  evolve =
 
 Then edit Bob's repository configuration::
 
@@ -508,13 +508,13 @@
 but every competent chef keeps several around. Ever try to chop onions
 with a spoon?)
 
-In the user guide, we saw examples of *unstable* changesets, which are
+In the user guide, we saw examples of *unstbale* changesets, which are
 the most common type of troubled changeset. (Recall that a
-non-obsolete changeset with obsolete ancestors is unstable.)
+non-obsolete changeset with obsolete ancestors is an orphan.)
 
-Two other types of trouble can happen: *divergent* and *bumped*
-changesets. Both are more likely with shared mutable history,
-especially mutable history shared by multiple developers.
+Two other types of troubles can happen: *divergent* and
+*bumped* changesets. Both are more likely with shared mutable
+history, especially mutable history shared by multiple developers.
 
 Setting up
 ==========
@@ -545,7 +545,7 @@
 
   [extensions]
   rebase =
-  evolve = /path/to/evolve-main/hgext3rd/evolve/
+  evolve =
 
   [phases]
   publish = false
@@ -560,8 +560,8 @@
 ===============================
 
 When an obsolete changeset has two successors, those successors are
-*divergent*. One way to get into such a situation is by failing to
-communicate with your teammates. Let's see how that might happen.
+*divergent*. One way to get into such a situation is by failing
+to communicate with your teammates. Let's see how that might happen.
 
 First, we'll have Bob commit a bug fix that could still be improved::
 
@@ -621,22 +621,18 @@
 ``internal:local``. He's avoiding a `bug`_ in ``evolve`` that occurs
 when evolving divergent changesets using ``internal:local``.)
 
+# XXX this link does not work
 .. _`bug`: https://bitbucket.org/marmoute/mutable-history/issue/48/
 
 ** STOP HERE: WORK IN PROGRESS **
 
-Bumped changesets: only one gets on the plane
-=============================================
+Phase-divergence: when a rewritten changeset is made public
+===========================================================
 
-If two people show up at the airport with tickets for the same seat on
-the same plane, only one of them gets on the plane. The would-be
-traveller left behind in the airport terminal is said to have been
-*bumped*.
-
-Similarly, if Alice and Bob are collaborating on some mutable
+If Alice and Bob are collaborating on some mutable
 changesets, it's possible to get into a situation where an otherwise
 worthwhile changeset cannot be pushed to the public repository; it is
-bumped by an alternative changeset that happened to get there first.
+*phase-divergent* with another changeset that was made public first.
 Let's demonstrate one way this could happen.
 
 It starts with Alice committing a bug fix. Right now, we don't yet
@@ -676,21 +672,21 @@
 
 This introduces a contradiction: in Bob's repository, changeset 2:e011
 (his copy of Alice's fix) is obsolete, since Bob amended it. But in
-Alice's repository (and ``public``), that changeset is public: it is
-immutable, carved in stone for all eternity. No changeset can be both
-obsolete and public, so Bob is in for a surprise the next time he
-pulls from ``public``::
+Alice's repository (and the ``public`` repository), that changeset is
+public: it is immutable, carved in stone for all eternity. No changeset
+can be both obsolete and public, so Bob is in for a surprise the next
+time he pulls from ``public``::
 
   $ cd ../bob
   $ hg pull -q -u
-  1 new bumped changesets
+  1 new phase-divergent changesets
 
 Figure 7 shows what just happened to Bob's repository: changeset
 2:e011 is now public, so it can't be obsolete. When that changeset was
 obsolete, it made perfect sense for it to have a successor, namely
 Bob's amendment of Alice's fix (changeset 4:fe88). But it's illogical
-for a public changeset to have a successor, so 4:fe88 is in trouble:
-it has been *bumped*.
+for a public changeset to have a successor, so 4:fe88 is troubled:
+it has become *bumped*.
 
   [figure SG07: 2:e011 now public not obsolete, 4:fe88 now bumped]
 
@@ -699,7 +695,7 @@
 
   $ hg evolve --all
 
-Figure 8 illustrate's Bob's repository after evolving away the bumped
+Figure 8 illustrates Bob's repository after evolving away the bumped
 changeset. Ignoring the obsolete changesets, Bob now has a nice,
 clean, simple history. His amendment of Alice's bug fix lives on, as
 changeset 5:227d—albeit with a software-generated commit message. (Bob
@@ -718,8 +714,8 @@
 inattentive or careless user can do harm to himself or others.
 Mercurial with ``evolve`` goes to great lengths to limit the harm you
 can do by trying to handle all possible types of “troubled”
-changesets. But having a first-aid kit nearby does not excuse you from
-being careful with sharp knives.
+changesets. Nevertheless, having a first-aid kit nearby does not mean
+you should stop being careful with sharp knives.
 
 Mutable history shared across multiple repositories by a single
 developer is a natural extension of this model. Once you are used to
--- a/docs/test2rst.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/docs/test2rst.py	Tue Nov 14 23:04:04 2017 +0100
@@ -1,15 +1,10 @@
 #!/usr/bin/env python
 
+import re
 import os
 import os.path as op
-import re
 import sys
 
-# line starts with two chars one of which is not a space (and both are not
-# newlines obviously) and ends with one or more newlines followed by two spaces
-# on a next line (indented text)
-CODEBLOCK = re.compile(r'()\n(([^ \n][^\n]|[^\n][^ \n])[^\n]*)\n+  ')
-
 INDEX = '''
 Mercurial tests
 ===============
@@ -18,12 +13,58 @@
    :maxdepth: 1
 '''
 
+ignored_patterns = [
+    re.compile('^#if'),
+    re.compile('^#else'),
+    re.compile('^#endif'),
+    re.compile('#rest-ignore$'),
+]
+
 
 def rstify(orig, name):
-    header = '%s\n%s\n\n' % (name, '=' * len(name))
-    content = header + orig
-    content = CODEBLOCK.sub(r'\n\1\n\n::\n\n  ', content)
-    return content
+    newlines = []
+
+    code_block_mode = False
+    sphinx_directive_mode = False
+
+    for line in orig.splitlines():
+
+        # Emtpy lines doesn't change output
+        if not line:
+            newlines.append(line)
+            code_block_mode = False
+            sphinx_directive_mode = False
+            continue
+
+        ignored = False
+        for pattern in ignored_patterns:
+            if pattern.search(line):
+                ignored = True
+                break
+        if ignored:
+            continue
+
+        # Sphinx directives mode
+        if line.startswith('  .. '):
+
+            # Insert a empty line to makes sphinx happy
+            newlines.append("")
+
+            # And unindent the directive
+            line = line[2:]
+            sphinx_directive_mode = True
+
+        # Code mode
+        codeline = line.startswith('  ')
+        if codeline and not sphinx_directive_mode:
+            if code_block_mode is False:
+                newlines.extend(['::', ''])
+
+            code_block_mode = True
+
+        newlines.append(line)
+
+    return "\n".join(newlines)
 
 
 def main(base):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/tutorials/topic-tutorial.t	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,1 @@
+../../tests/test-topic-tutorial.t
\ No newline at end of file
--- a/docs/user-guide.rst	Tue Jul 25 02:29:28 2017 +0200
+++ b/docs/user-guide.rst	Tue Nov 14 23:04:04 2017 +0100
@@ -26,17 +26,17 @@
 (``rebase``, ``histedit``, etc.), and also by the ``evolve``
 extension. Specifically, ``evolve`` adds a number of commands that can
 be used to modify history: ``amend``, ``uncommit``, ``prune``,
-``fold``, and ``evolve``. Generally speaking, changesets remain in
-*draft* phase until they are pushed to another repository, at which
-point they enter *public* phase. ::
+``fold``, and ``evolve``. ::
 
   $ hg commit -m 'implement feature X'
   $ hg phase -r .
   1: draft
 
-(Strictly speaking, changesets only become public when they are pushed
-to a *publishing* repository. But all repositories are publishing by
-default; you have to explicitly configure repositories to be
+Generally speaking, changesets remain in *draft* phase until they are
+pushed to another repository, at which point they enter the *public*
+phase. (Strictly speaking, changesets only become public when they are
+pushed to a *publishing* repository. But all repositories are publishing
+by default; you have to explicitly configure repositories to be
 *non-publishing*. Non-publishing repositories are an advanced topic
 which we'll see when we get to `sharing mutable history`_.)
 
@@ -60,7 +60,8 @@
 to create a new, amended changeset. The drawback of doing this with
 vanilla Mercurial is that your original, flawed, changeset is removed
 from the repository. This is *unsafe* history editing. It's probably
-not too serious if all you did was fix a syntax error, but still.
+not too serious if all you did was fix a syntax error, but for deeper
+changes there can be more serious consequences to unsafe history editing.
 
 .. figure:: figures/figure-ug01.svg
 
@@ -70,8 +71,9 @@
 (Incidentally, Mercurial's traditional history modification mechanism
 isn't *really* unsafe: any changeset(s) removed from the repository
 are kept in a backup directory, so you can manually restore them later
-if you change your mind. But it's awkward and inconvenient compared to
-the features provided by ``evolve`` and changeset obsolescence.)
+if you change your mind. However, this mechanism is very awkward and
+inconvenient compared to the features provided by ``evolve`` and
+changeset obsolescence.)
 
 Life with ``evolve`` (basic usage)
 ----------------------------------
@@ -99,7 +101,7 @@
 pass ``-m`` or ``-l``.)
 
 Under the hood, though, things are quite different. Mercurial has
-simply marked the old changeset *obsolete*, replacing it with a new
+simply marked the old changeset as *obsolete*, replacing it with a new
 one. We'll explore what this means in detail later, after working
 through a few more examples.
 
@@ -192,7 +194,7 @@
 
 and fold them::
 
-  $ hg fold -m 'fix bug 64' -r 7::
+  $ hg fold -m 'fix bug 64' -r 7:: --exact
   3 changesets folded
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
@@ -214,7 +216,7 @@
 When you have the ``evolve`` extension enabled, all history
 modification uses the same underlying mechanism: the original
 changesets are marked *obsolete* and replaced by zero or more
-*successors*. The obsolete changesets are the *precursors* of their
+*successors*. The obsolete changesets are the *predecessors* of their
 successors. This applies equally to built-in commands (``commit
 --amend``), commands added by ``evolve`` (``amend``, ``prune``,
 ``uncommit``, ``fold``), and commands provided by other extensions
@@ -232,7 +234,7 @@
 Consider Example 2, amending a changeset with ``evolve``. We saw above
 that you can do this using the exact same command-line syntax as core
 Mercurial, namely ``hg commit --amend``. But the implementation is
-quite different, and Figure 2 shows how.
+quite different, as Figure 2 shows.
 
 .. figure:: figures/figure-ug02.svg
 
@@ -243,8 +245,8 @@
    versions of Mercurial will not create them.)
 
 In this case, the obsolete changesets are also *hidden*. That is the
-usual end state for obsolete changesets. But many scenarios result in
-obsolete changesets that are still visible, which indicates your
+usual end state for obsolete changesets. However, many scenarios result
+in obsolete changesets that are still visible, which indicates your
 history modification work is not yet done. We'll see examples of that
 later, when we cover advanced usage.
 
@@ -287,7 +289,7 @@
 ``prune`` (example 4 above) is the simplest history modification
 command provided by ``evolve``. All it does is mark the specified
 changeset(s) obsolete, with no successor/precursor relationships
-involved. (If the working directory parent was one of the obsolete
+involved. (If the working directory parent was one of the obsoleted
 changesets, ``prune`` updates back to a suitable ancestor.)
 
 .. figure:: figures/figure-ug03.svg
@@ -299,11 +301,8 @@
 
 In one sense, ``uncommit`` is a simplified version of ``amend``. Like
 ``amend``, it obsoletes one changeset and leaves it with a single
-successor. Unlike ``amend``, there is no ugly "temporary amend commit"
-cluttering up the repository.
-
-In another sense, ``uncommit`` is the inverse of ``amend``: ``amend``
-takes any uncommitted changes in the working dir and “adds”
+successor. In another sense, ``uncommit`` is the inverse of ``amend``:
+``amend`` takes any uncommitted changes in the working dir and “adds”
 them to the working directory's parent changeset. (In reality, of
 course, it creates a successor changeset, marking the original
 obsolete.) In contrast, ``uncommit`` takes some changes in the working
@@ -341,8 +340,9 @@
 changesets.
 
 Note that all hidden changesets are obsolete: hidden is a subset of
-obsolete.
+obsolete. This is explained in more depth in the `concepts`_ section.
 
+.. _`concepts`: concepts.html
 
 Life with ``evolve`` (advanced usage)
 -------------------------------------
@@ -353,12 +353,12 @@
 which is an unavoidable consequence of obsolescence. What really sets
 ``evolve`` apart from other history modification mechanisms is the
 fact that it recognizes troubles like unstable changesets and provides
-a consistent way for you to get out of trouble.
+a consistent way for you to get back to a stable repository.
 
-(Incidentally, there are two other types of trouble that changesets
-can get into with ``evolve``: they may be *divergent* or *bumped*.
-Both of those states are more likely to occur when `sharing mutable
-history`_, so we won't see them in this user guide.)
+(Incidentally, there are two other types of troubles that changesets
+can get into with ``evolve``: they may be *divergent* or
+*bumped*. Both of those states are more likely to occur when
+`sharing mutable history`_, so we won't cover them in this user guide.)
 
 .. _`sharing mutable history`: sharing.html
 
@@ -366,8 +366,8 @@
 Example 7: Amend an older changeset
 ===================================
 
-Sometimes you don't notice your mistakes until after you have
-committed new changesets on top of them. ::
+Sometimes you don't notice a mistake until after you have committed
+new changesets on top of the changeset with the mistake. ::
 
   $ hg commit -m 'fix bug 17'         # rev 11 (mistake here)
   $ hg commit -m 'cleanup'            # rev 12
@@ -402,10 +402,10 @@
    descendants are *unstable*. The temporary amend commit, revision
    14, is hidden because it has no non-obsolete descendants.
 
-All non-obsolete descendants of an obsolete changeset are unstable. An
-interesting consequence of this is that revision 11 is still visible,
-even though it is obsolete. Obsolete changesets with non-obsolete
-descendants are not hidden.
+All non-obsolete descendants of an obsolete changeset are considered
+unstable. An interesting consequence of this is that revision 11 is
+still visible, even though it is obsolete. Obsolete changesets with
+non-obsolete descendants are not hidden.
 
 The fix is to *evolve* history::
 
@@ -415,9 +415,8 @@
 because there might be conflicts. If your amended changeset modifies a
 file that one of its descendants also modified, Mercurial has to fire
 up your merge tool to resolve the conflict. More importantly, you have
-to switch contexts from "writing code" to "resolving conflicts". That
-can be an expensive context switch, so Mercurial lets you decide when
-to do it.
+to switch from "writing code" to "resolving conflicts". That can be an
+expensive context switch, so Mercurial lets you decide when to do it.
 
 The end state, after ``evolve`` finishes, is that the original
 revisions (11-13) are obsolete and hidden. Their successor revisions
@@ -491,7 +490,7 @@
   M file2.c
 
 Now your repository has unstable changesets, so you need to evolve it.
-But ``hg evolve`` requires a clean working directory to resolve merge
+However, ``hg evolve`` requires a clean working directory to resolve merge
 conflicts, so you need to decide what to do with ``file2.c``.
 
 In this case, the change to ``file2.c`` was a temporary debugging
@@ -525,12 +524,12 @@
   $ hg commit -u dan -d '12 0' -m 'new feature'   # rev 27 (fine)
 
 As before, we update back to the flawed changeset (this time,
-revision 26) and ``uncommit``, leaving uncommitted changes to
+revision 26) and use ``uncommit``, leaving uncommitted changes to
 ``file2.c`` in the working dir::
 
   $ hg update -q 26
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg uncommit -q file2.c                        # obsoletes rev 26, creates rev 28
+  $ hg uncommit -q file2.c  # obsoletes rev 26, creates rev 28
   1 new unstable changesets
   $ hg status
   M file2.c
@@ -541,8 +540,8 @@
 
 Figure 11 shows the story so far: ``uncommit`` obsoleted revision 26
 and created revision 28, the successor of 26. Then we committed
-revision 29, a child of 28. We still have to deal with the unstable
-revision 27.
+revision 29, a child of 28. We still have to deal with the revision 27,
+which is an unstable changeset.
 
 .. figure:: figures/figure-ug11.svg
 
@@ -594,7 +593,7 @@
 The current implementation of ``hg touch`` is not ideal, and is likely to
 change in the future. Consider the history in Figure 12, where revision 27
 is obsolete and the child of 26, also obsolete. If we ``hg touch 27``, that
-creates a new revision which is a non-obsolete child of 26—i.e., it is
+creates a new revision which is a non-obsolete child of 26—i.e., it is an
 unstable. It's also *divergent*, another type of trouble that we'll learn
 about in the `next section`_.
 
--- a/hgext3rd/evolve/__init__.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/__init__.py	Tue Nov 14 23:04:04 2017 +0100
@@ -32,9 +32,9 @@
 backported to older version of Mercurial by this extension. Some older
 experimental protocol are also supported for a longer time in the extensions to
 help people transitioning. (The extensions is currently compatible down to
-Mercurial version 3.8).
+Mercurial version 4.1).
 
-New Config:
+New Config::
 
     [experimental]
     # Set to control the behavior when pushing draft changesets to a publishing
@@ -103,7 +103,7 @@
 
 For very large repositories. it is currently recommended to disable obsmarkers
 discovery (Make sure you follow release announcement to know when you can turn
-it back on).
+it back on)::
 
     [experimental]
     evolution.obsdiscovery = no
@@ -137,7 +137,7 @@
   # evolution.effect-flags = false
 
 You can display the effect flags with the command obslog, so if you have a
-changeset and you update only the message, you will see:
+changeset and you update only the message, you will see::
 
     $ hg commit -m "WIP
     $ hg commit -m "A better commit message!"
@@ -271,7 +271,7 @@
     registrar.templatekeyword # new in hg-3.8
 except ImportError:
     from . import metadata
-    raise ImportError('evolve needs version %s or above' %
+    raise ImportError('evolve needs Mercurial version %s or above' %
                       min(metadata.testedwith.split()))
 
 import mercurial
@@ -374,6 +374,16 @@
 extsetup = eh.final_extsetup
 reposetup = eh.final_reposetup
 cmdtable = eh.cmdtable
+configtable = eh.configtable
+
+# Configuration
+eh.configitem('experimental', 'evolutioncommands')
+eh.configitem('experimental', 'evolution.allnewcommands')
+eh.configitem('experimental', 'prunestrip')
+
+# hack around because we need an actual default there
+if configtable:
+    configtable['experimental']['evolution.allnewcommands'].default = None
 
 # pre hg 4.0 compat
 
@@ -410,6 +420,8 @@
     if not evolveopts:
         evolveopts = ['all']
         ui.setconfig('experimental', 'evolution', evolveopts, 'evolve')
+    if obsolete.isenabled(repo, 'exchange'):
+        repo.ui.setconfig('server', 'bundle1', False)
 
 @eh.uisetup
 def _configurecmdoptions(ui):
@@ -418,7 +430,7 @@
     # This must be in the same function as the option configuration above to
     # guarantee it happens after the above configuration, but before the
     # extsetup functions.
-    evolvecommands = ui.configlist('experimental', 'evolutioncommands')
+    evolvecommands = ui.configlist('experimental', 'evolutioncommands', [])
     evolveopts = ui.configlist('experimental', 'evolution')
     if evolveopts and (commandopt not in evolveopts and
                        'all' not in evolveopts):
@@ -458,16 +470,45 @@
 ### Useful alias
 
 @eh.uisetup
+def setupparentcommand(ui):
+
+    _alias, statuscmd = cmdutil.findcmd('status', commands.table)
+    pstatusopts = [o for o in statuscmd[1] if o[1] != 'rev']
+
+    @eh.command('pstatus', pstatusopts)
+    def pstatus(ui, repo, *args, **kwargs):
+        """show status combining committed and uncommited changes
+
+        This show the combined status of the current working copy parent commit and
+        the uncommitted change in the working copy itself. The status displayed
+        match the content of the commit that a bare :hg:`amend` will creates.
+
+        See :hg:`help status` for details."""
+        kwargs['rev'] = ['.^']
+        return statuscmd[0](ui, repo, *args, **kwargs)
+
+    _alias, diffcmd = cmdutil.findcmd('diff', commands.table)
+    pdiffopts = [o for o in diffcmd[1] if o[1] != 'rev']
+
+    @eh.command('pdiff', pdiffopts)
+    def pdiff(ui, repo, *args, **kwargs):
+        """show diff combining committed and uncommited changes
+
+        This show the combined diff of the current working copy parent commit and
+        the uncommitted change in the working copy itself. The diff displayed
+        match the content of the commit that a bare :hg:`amend` will creates.
+
+        See :hg:`help diff` for details."""
+        kwargs['rev'] = ['.^']
+        return diffcmd[0](ui, repo, *args, **kwargs)
+
+@eh.uisetup
 def _installalias(ui):
-    if ui.config('alias', 'pstatus', None) is None:
-        ui.setconfig('alias', 'pstatus', 'status --rev .^', 'evolve')
-    if ui.config('alias', 'pdiff', None) is None:
-        ui.setconfig('alias', 'pdiff', 'diff --rev .^', 'evolve')
-    if ui.config('alias', 'odiff', None) is None:
+    if ui.config('alias', 'odiff') is None:
         ui.setconfig('alias', 'odiff',
                      "diff --hidden --rev 'limit(precursors(.),1)' --rev .",
                      'evolve')
-    if ui.config('alias', 'grab', None) is None:
+    if ui.config('alias', 'grab') is None:
         if os.name == 'nt':
             hgexe = ('"%s"' % util.hgexecutable())
             ui.setconfig('alias', 'grab', "! " + hgexe
@@ -482,16 +523,15 @@
 
 ### Troubled revset symbol
 
-@eh.revset('troubled')
+@eh.revset('troubled()')
 def revsettroubled(repo, subset, x):
-    """``troubled()``
-    Changesets with troubles.
+    """Changesets with troubles.
     """
     revset.getargs(x, 0, 0, 'troubled takes no arguments')
     troubled = set()
-    troubled.update(getrevs(repo, 'unstable'))
-    troubled.update(getrevs(repo, 'bumped'))
-    troubled.update(getrevs(repo, 'divergent'))
+    troubled.update(getrevs(repo, 'orphan'))
+    troubled.update(getrevs(repo, 'phasedivergent'))
+    troubled.update(getrevs(repo, 'contentdivergent'))
     troubled = revset.baseset(troubled)
     troubled.sort() # set is non-ordered, enforce order
     return subset & troubled
@@ -504,7 +544,7 @@
     """Precursor of a changeset"""
     cs = set()
     nm = repo.changelog.nodemap
-    markerbysubj = repo.obsstore.precursors
+    markerbysubj = repo.obsstore.predecessors
     node = repo.changelog.node
     for r in s:
         for p in markerbysubj.get(node(r), ()):
@@ -519,7 +559,7 @@
     node = repo.changelog.node
     toproceed = [node(r) for r in s]
     seen = set()
-    allsubjects = repo.obsstore.precursors
+    allsubjects = repo.obsstore.predecessors
     while toproceed:
         nc = toproceed.pop()
         for mark in allsubjects.get(nc, ()):
@@ -589,10 +629,9 @@
 
 
 ### XXX I'm not sure this revset is useful
-@eh.revset('suspended')
+@eh.revset('suspended()')
 def revsetsuspended(repo, subset, x):
-    """``suspended()``
-    Obsolete changesets with non-obsolete descendants.
+    """Obsolete changesets with non-obsolete descendants.
     """
     revset.getargs(x, 0, 0, 'suspended takes no arguments')
     suspended = revset.baseset(getrevs(repo, 'suspended'))
@@ -600,10 +639,9 @@
     return subset & suspended
 
 
-@eh.revset('precursors')
+@eh.revset('precursors(set)')
 def revsetprecursors(repo, subset, x):
-    """``precursors(set)``
-    Immediate precursors of changesets in set.
+    """Immediate precursors of changesets in set.
     """
     s = revset.getset(repo, revset.fullreposet(repo), x)
     s = revset.baseset(_precursors(repo, s))
@@ -611,10 +649,9 @@
     return subset & s
 
 
-@eh.revset('allprecursors')
+@eh.revset('allprecursors(set)')
 def revsetallprecursors(repo, subset, x):
-    """``allprecursors(set)``
-    Transitive precursors of changesets in set.
+    """Transitive precursors of changesets in set.
     """
     s = revset.getset(repo, revset.fullreposet(repo), x)
     s = revset.baseset(_allprecursors(repo, s))
@@ -622,20 +659,18 @@
     return subset & s
 
 
-@eh.revset('successors')
+@eh.revset('successors(set)')
 def revsetsuccessors(repo, subset, x):
-    """``successors(set)``
-    Immediate successors of changesets in set.
+    """Immediate successors of changesets in set.
     """
     s = revset.getset(repo, revset.fullreposet(repo), x)
     s = revset.baseset(_successors(repo, s))
     s.sort()
     return subset & s
 
-@eh.revset('allsuccessors')
+@eh.revset('allsuccessors(set)')
 def revsetallsuccessors(repo, subset, x):
-    """``allsuccessors(set)``
-    Transitive successors of changesets in set.
+    """Transitive successors of changesets in set.
     """
     s = revset.getset(repo, revset.fullreposet(repo), x)
     s = revset.baseset(_allsuccessors(repo, s))
@@ -670,7 +705,7 @@
     if reason == 'pruned':
         solvemsg = _("use 'hg evolve' to update to its parent successor")
     elif reason == 'diverged':
-        debugcommand = "hg evolve --list --divergent"
+        debugcommand = "hg evolve --list --content-divergent"
         basemsg = _("%s has diverged, use '%s' to resolve the issue")
         solvemsg = basemsg % (shortnode, debugcommand)
     elif reason == 'superseed':
@@ -759,23 +794,25 @@
     # part of the troubled stuff may be filtered (stash ?)
     # This needs a better implementation but will probably wait for core.
     filtered = repo.changelog.filteredrevs
-    priorunstables = len(set(getrevs(repo, 'unstable')) - filtered)
-    priorbumpeds = len(set(getrevs(repo, 'bumped')) - filtered)
-    priordivergents = len(set(getrevs(repo, 'divergent')) - filtered)
+    priorunstables = len(set(getrevs(repo, 'orphan')) - filtered)
+    priorbumpeds = len(set(getrevs(repo, 'phasedivergent')) - filtered)
+    priordivergents = len(set(getrevs(repo, 'contentdivergent')) - filtered)
     ret = orig(ui, repo, *args, **kwargs)
     filtered = repo.changelog.filteredrevs
     newunstables = \
-        len(set(getrevs(repo, 'unstable')) - filtered) - priorunstables
+        len(set(getrevs(repo, 'orphan')) - filtered) - priorunstables
     newbumpeds = \
-        len(set(getrevs(repo, 'bumped')) - filtered) - priorbumpeds
+        len(set(getrevs(repo, 'phasedivergent')) - filtered) - priorbumpeds
     newdivergents = \
-        len(set(getrevs(repo, 'divergent')) - filtered) - priordivergents
+        len(set(getrevs(repo, 'contentdivergent')) - filtered) - priordivergents
+
+    base_msg = _('%i new %s changesets\n')
     if newunstables > 0:
-        ui.warn(_('%i new unstable changesets\n') % newunstables)
+        ui.warn(base_msg % (newunstables, compat.TROUBLES['ORPHAN']))
     if newbumpeds > 0:
-        ui.warn(_('%i new bumped changesets\n') % newbumpeds)
+        ui.warn(base_msg % (newbumpeds, compat.TROUBLES['PHASEDIVERGENT']))
     if newdivergents > 0:
-        ui.warn(_('%i new divergent changesets\n') % newdivergents)
+        ui.warn(base_msg % (newdivergents, compat.TROUBLES['CONTENTDIVERGENT']))
     return ret
 
 @eh.wrapfunction(mercurial.exchange, 'push')
@@ -899,7 +936,7 @@
             repo.setparents(repo['.'].node(), nullid)
             repo.dirstate.write(tr)
             # fix up dirstate for copies and renames
-            copies.duplicatecopies(repo, dest.rev(), orig.p1().rev())
+            compat.duplicatecopies(repo, repo[None], dest.rev(), orig.p1().rev())
 
         class LocalMergeFailure(MergeFailure, exc.__class__):
             pass
@@ -977,7 +1014,7 @@
         ui = args[0]
         ui.warn(deprecationwarning)
         util.checksignature(fn)(*args, **kwargs)
-    newfn.__doc__ = deprecationwarning
+    newfn.__doc__ = deprecationwarning + ' (DEPRECATED)'
     cmdwrapper = eh.command(oldalias, opts, synopsis)
     cmdwrapper(newfn)
 
@@ -993,11 +1030,11 @@
         wlock = repo.wlock()
         lock = repo.lock()
         tr = repo.transaction("evolve")
-        if 'unstable' == category:
+        if 'orphan' == category:
             result = _solveunstable(ui, repo, ctx, dryrun, confirm, progresscb)
-        elif 'bumped' == category:
+        elif 'phasedivergent' == category:
             result = _solvebumped(ui, repo, ctx, dryrun, confirm, progresscb)
-        elif 'divergent' == category:
+        elif 'contentdivergent' == category:
             result = _solvedivergent(ui, repo, ctx, dryrun, confirm,
                                      progresscb)
         else:
@@ -1010,37 +1047,44 @@
 def _handlenotrouble(ui, repo, allopt, revopt, anyopt, targetcat):
     """Used by the evolve function to display an error message when
     no troubles can be resolved"""
-    troublecategories = ['bumped', 'divergent', 'unstable']
+    troublecategories = ['phasedivergent', 'contentdivergent', 'orphan']
     unselectedcategories = [c for c in troublecategories if c != targetcat]
     msg = None
     hint = None
 
     troubled = {
-        "unstable": repo.revs("unstable()"),
-        "divergent": repo.revs("divergent()"),
-        "bumped": repo.revs("bumped()"),
+        "orphan": repo.revs("orphan()"),
+        "contentdivergent": repo.revs("contentdivergent()"),
+        "phasedivergent": repo.revs("phasedivergent()"),
         "all": repo.revs("troubled()"),
     }
 
     hintmap = {
-        'bumped': _("do you want to use --bumped"),
-        'bumped+divergent': _("do you want to use --bumped or --divergent"),
-        'bumped+unstable': _("do you want to use --bumped or --unstable"),
-        'divergent': _("do you want to use --divergent"),
-        'divergent+unstable': _("do you want to use --divergent"
-                                " or --unstable"),
-        'unstable': _("do you want to use --unstable"),
-        'any+bumped': _("do you want to use --any (or --rev) and --bumped"),
-        'any+bumped+divergent': _("do you want to use --any (or --rev) and"
-                                  " --bumped or --divergent"),
-        'any+bumped+unstable': _("do you want to use --any (or --rev) and"
-                                 "--bumped or --unstable"),
-        'any+divergent': _("do you want to use --any (or --rev) and"
-                           " --divergent"),
-        'any+divergent+unstable': _("do you want to use --any (or --rev)"
-                                    " and --divergent or --unstable"),
-        'any+unstable': _("do you want to use --any (or --rev)"
-                          "and --unstable"),
+        'phasedivergent': _("do you want to use --phase-divergent"),
+        'phasedivergent+contentdivergent': _("do you want to use "
+                                             "--phase-divergent or"
+                                             " --content-divergent"),
+        'phasedivergent+orphan': _("do you want to use --phase-divergent"
+                                   " or --orphan"),
+        'contentdivergent': _("do you want to use --content-divergent"),
+        'contentdivergent+orphan': _("do you want to use --content-divergent"
+                                     " or --orphan"),
+        'orphan': _("do you want to use --orphan"),
+        'any+phasedivergent': _("do you want to use --any (or --rev) and"
+                                " --phase-divergent"),
+        'any+phasedivergent+contentdivergent': _("do you want to use --any"
+                                                 " (or --rev) and"
+                                                 " --phase-divergent or"
+                                                 " --content-divergent"),
+        'any+phasedivergent+orphan': _("do you want to use --any (or --rev)"
+                                       " and --phase-divergent or --orphan"),
+        'any+contentdivergent': _("do you want to use --any (or --rev) and"
+                                  " --content-divergent"),
+        'any+contentdivergent+orphan': _("do you want to use --any (or --rev)"
+                                         " and --content-divergent or "
+                                         "--orphan"),
+        'any+orphan': _("do you want to use --any (or --rev)"
+                        "and --orphan"),
     }
 
     if revopt:
@@ -1067,7 +1111,7 @@
 
     else:
         # evolve without any option = relative to the current wdir
-        if targetcat == 'unstable':
+        if targetcat == 'orphan':
             msg = _("nothing to evolve on current working copy parent")
         else:
             msg = _("current working copy parent is not %s") % targetcat
@@ -1080,10 +1124,10 @@
         if othertroubles:
             hint = hintmap['+'.join(othertroubles)]
         else:
-            l = len(troubled[targetcat])
-            if l:
+            length = len(troubled[targetcat])
+            if length:
                 hint = _("%d other %s in the repository, do you want --any "
-                         "or --rev") % (l, targetcat)
+                         "or --rev") % (length, targetcat)
             else:
                 othertroubles = []
                 for cat in unselectedcategories:
@@ -1183,6 +1227,11 @@
         discarded.update(othersrevs)
     return res
 
+instabilities_map = {
+    'contentdivergent': "content-divergent",
+    'phasedivergent': "phase-divergent"
+}
+
 def _selectrevs(repo, allopt, revopt, anyopt, targetcat):
     """select troubles in repo matching according to given options"""
     revs = set()
@@ -1194,23 +1243,23 @@
             topic = getattr(repo, 'currenttopic', '')
             if topic:
                 revs = repo.revs('topic(%s)', topic) & revs
-            elif targetcat == 'unstable':
+            elif targetcat == 'orphan':
                 revs = _aspiringdescendant(repo,
                                            repo.revs('(.::) - obsolete()::'))
                 revs = set(revs)
-        if targetcat == 'divergent':
+        if targetcat == 'contentdivergent':
             # Pick one divergent per group of divergents
             revs = _dedupedivergents(repo, revs)
     elif anyopt:
         revs = repo.revs('first(%s())' % (targetcat))
-    elif targetcat == 'unstable':
+    elif targetcat == 'orphan':
         revs = set(_aspiringchildren(repo, repo.revs('(.::) - obsolete()::')))
         if 1 < len(revs):
             msg = "multiple evolve candidates"
             hint = (_("select one of %s with --rev")
                     % ', '.join([str(repo[r]) for r in sorted(revs)]))
             raise error.Abort(msg, hint=hint)
-    elif targetcat in repo['.'].troubles():
+    elif instabilities_map.get(targetcat, targetcat) in repo['.'].instabilities():
         revs = set([repo['.'].rev()])
     return revs
 
@@ -1287,10 +1336,10 @@
 
 def listtroubles(ui, repo, troublecategories, **opts):
     """Print all the troubles for the repo (or given revset)"""
-    troublecategories = troublecategories or ['divergent', 'unstable', 'bumped']
-    showunstable = 'unstable' in troublecategories
-    showbumped = 'bumped' in troublecategories
-    showdivergent = 'divergent' in troublecategories
+    troublecategories = troublecategories or ['contentdivergent', 'orphan', 'phasedivergent']
+    showunstable = 'orphan' in troublecategories
+    showbumped = 'phasedivergent' in troublecategories
+    showdivergent = 'contentdivergent' in troublecategories
 
     revs = repo.revs('+'.join("%s()" % t for t in troublecategories))
     if opts.get('rev'):
@@ -1299,7 +1348,7 @@
     fm = ui.formatter('evolvelist', opts)
     for rev in revs:
         ctx = repo[rev]
-        unpars = _preparelistctxs(ctx.parents(), lambda p: p.unstable())
+        unpars = _preparelistctxs(ctx.parents(), lambda p: p.orphan())
         obspars = _preparelistctxs(ctx.parents(), lambda p: p.obsolete())
         imprecs = _preparelistctxs(repo.set("allprecursors(%n)", ctx.node()),
                                    lambda p: not p.mutable())
@@ -1317,7 +1366,7 @@
         fm.data(node=ctx.hex(), rev=ctx.rev(), desc=desc, phase=ctx.phasestr())
 
         for unpar in unpars if showunstable else []:
-            fm.plain('  unstable: %s (unstable parent)\n' % unpar[:hashlen])
+            fm.plain('  orphan: %s (orphan parent)\n' % unpar[:hashlen])
         for obspar in obspars if showunstable else []:
             fm.plain('  unstable: %s (obsolete parent)\n' % obspar[:hashlen])
         for imprec in imprecs if showbumped else []:
@@ -1369,8 +1418,11 @@
         'directory')),
      ('r', 'rev', [], _('solves troubles of these revisions')),
      ('', 'bumped', False, _('solves only bumped changesets')),
+     ('', 'phase-divergent', False, _('solves only phase-divergent changesets')),
      ('', 'divergent', False, _('solves only divergent changesets')),
-     ('', 'unstable', False, _('solves only unstable changesets (default)')),
+     ('', 'content-divergent', False, _('solves only content-divergent changesets')),
+     ('', 'unstable', False, _('solves only unstable changesets')),
+     ('', 'orphan', False, _('solves only orphan changesets (default)')),
      ('a', 'all', False, _('evolve all troubled changesets related to the '
                            'current  working directory and its descendants')),
      ('c', 'continue', False, _('continue an interrupted evolution')),
@@ -1457,13 +1509,39 @@
     dryrunopt = opts['dry_run']
     confirmopt = opts['confirm']
     revopt = opts['rev']
-    troublecategories = ['bumped', 'divergent', 'unstable']
-    specifiedcategories = [t for t in troublecategories if opts[t]]
+
+    # Backward compatibility
+    if opts['unstable']:
+        msg = ("'evolve --unstable' is deprecated, "
+               "use 'evolve --orphan'")
+        repo.ui.deprecwarn(msg, '4.4')
+
+        opts['orphan'] = opts['divergent']
+
+    if opts['divergent']:
+        msg = ("'evolve --divergent' is deprecated, "
+               "use 'evolve --content-divergent'")
+        repo.ui.deprecwarn(msg, '4.4')
+
+        opts['content_divergent'] = opts['divergent']
+
+    if opts['bumped']:
+        msg = ("'evolve --bumped' is deprecated, "
+               "use 'evolve --phase-divergent'")
+        repo.ui.deprecwarn(msg, '4.4')
+
+        opts['phase_divergent'] = opts['bumped']
+
+    troublecategories = ['phase_divergent', 'content_divergent', 'orphan']
+    specifiedcategories = [t.replace('_', '')
+                           for t in troublecategories
+                           if opts[t]]
     if listopt:
+        compat.startpager(ui, 'evolve')
         listtroubles(ui, repo, specifiedcategories, **opts)
         return
 
-    targetcat = 'unstable'
+    targetcat = 'orphan'
     if 1 < len(specifiedcategories):
         msg = _('cannot specify more than one trouble category to solve (yet)')
         raise error.Abort(msg)
@@ -1543,7 +1621,7 @@
     # For the progress bar to show
     count = len(revs)
     # Order the revisions
-    if targetcat == 'unstable':
+    if targetcat == 'orphan':
         revs = _orderrevs(repo, revs)
     for rev in revs:
         progresscb()
@@ -1580,7 +1658,7 @@
     one of its descendants. Empty list if none can be found."""
     target = set(revs)
     result = []
-    for r in repo.revs('unstable() - %ld', revs):
+    for r in repo.revs('orphan() - %ld', revs):
         dest = _possibledestination(repo, r)
         if target & dest:
             result.append(r)
@@ -1592,7 +1670,7 @@
     target = set(revs)
     result = set(target)
     paths = collections.defaultdict(set)
-    for r in repo.revs('unstable() - %ld', revs):
+    for r in repo.revs('orphan() - %ld', revs):
         for d in _possibledestination(repo, r):
             paths[d].add(r)
 
@@ -2018,11 +2096,14 @@
         target, bookmark = _findprevtarget(repo, displayer,
                                            opts.get('move_bookmark'), topic)
         if target is not None:
-            overrides = {}
-            if topic and _getcurrenttopic(repo) != _gettopic(target):
-                overrides[('_internal', 'keep-topic')] = 'yes'
-            with repo.ui.configoverride(overrides, source='topic-extension'):
+            backup = repo.ui.backupconfig('_internal', 'keep-topic')
+            try:
+                if topic and _getcurrenttopic(repo) != _gettopic(target):
+                    repo.ui.setconfig('_internal', 'keep-topic', 'yes',
+                                      source='topic-extension')
                 _prevupdate(repo, displayer, target, bookmark, dryrunopt)
+            finally:
+                repo.ui.restoreconfig(backup)
             return 0
         else:
             return 1
@@ -2063,7 +2144,7 @@
                 raise
 
         children = [ctx for ctx in wparents[0].children() if not ctx.obsolete()]
-        topic = getattr(repo, 'currenttopic', '')
+        topic = _getcurrenttopic(repo)
         filtered = []
         if topic and not opts.get("no_topic", False):
             filtered = [ctx for ctx in children if ctx.topic() != topic]
@@ -2128,7 +2209,7 @@
             else:
                 cmdutil.bailifchanged(repo)
                 result = _solveone(ui, repo, repo[aspchildren[0]], dryrunopt,
-                                   False, lambda: None, category='unstable')
+                                   False, lambda: None, category='orphan')
                 if not result:
                     ui.status(_('working directory now at %s\n')
                               % ui.label(str(repo['.']), 'evolve.node'))
@@ -2180,7 +2261,7 @@
                            "backup bundle")),
     ])
 def stripwrapper(orig, ui, repo, *revs, **kwargs):
-    if (not ui.configbool('experimental', 'prunestrip') or
+    if (not ui.configbool('experimental', 'prunestrip', False) or
         kwargs.get('bundle', False)):
         return orig(ui, repo, *revs, **kwargs)
 
--- a/hgext3rd/evolve/cmdrewrite.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/cmdrewrite.py	Tue Nov 14 23:04:04 2017 +0100
@@ -24,6 +24,7 @@
     lock as lockmod,
     node,
     obsolete,
+    patch,
     phases,
     scmutil,
     util,
@@ -44,6 +45,7 @@
 commitopts = commands.commitopts
 commitopts2 = commands.commitopts2
 mergetoolopts = commands.mergetoolopts
+stringio = util.stringio
 
 # option added by evolve
 
@@ -98,9 +100,6 @@
     """
     opts = opts.copy()
     if opts.get('extract'):
-        if opts.pop('interactive', False):
-            msg = _('not support for --interactive with --extract yet')
-            raise error.Abort(msg)
         return uncommit(ui, repo, *pats, **opts)
     else:
         if opts.pop('all', False):
@@ -187,7 +186,7 @@
     newid = repo.commitctx(new)
     return newid
 
-def _uncommitdirstate(repo, oldctx, match):
+def _uncommitdirstate(repo, oldctx, match, interactive):
     """Fix the dirstate after switching the working directory from
     oldctx to a copy of oldctx not containing changed files matched by
     match.
@@ -195,29 +194,82 @@
     ctx = repo['.']
     ds = repo.dirstate
     copies = dict(ds.copies())
-    m, a, r = repo.status(oldctx.p1(), oldctx, match=match)[:3]
-    for f in m:
-        if ds[f] == 'r':
-            # modified + removed -> removed
-            continue
-        ds.normallookup(f)
+    if interactive:
+        # In interactive cases, we will find the status between oldctx and ctx
+        # and considering only the files which are changed between oldctx and
+        # ctx, and the status of what changed between oldctx and ctx will help
+        # us in defining the exact behavior
+        m, a, r = repo.status(oldctx, ctx, match=match)[:3]
+        for f in m:
+            # These are files which are modified between oldctx and ctx which
+            # contains two cases: 1) Were modified in oldctx and some
+            # modifications are uncommitted
+            # 2) Were added in oldctx but some part is uncommitted (this cannot
+            # contain the case when added files are uncommitted completely as
+            # that will result in status as removed not modified.)
+            # Also any modifications to a removed file will result the status as
+            # added, so we have only two cases. So in either of the cases, the
+            # resulting status can be modified or clean.
+            if ds[f] == 'r':
+                # But the file is removed in the working directory, leaving that
+                # as removed
+                continue
+            ds.normallookup(f)
+
+        for f in a:
+            # These are the files which are added between oldctx and ctx(new
+            # one), which means the files which were removed in oldctx
+            # but uncommitted completely while making the ctx
+            # This file should be marked as removed if the working directory
+            # does not adds it back. If it's adds it back, we do a normallookup.
+            # The file can't be removed in working directory, because it was
+            # removed in oldctx
+            if ds[f] == 'a':
+                ds.normallookup(f)
+                continue
+            ds.remove(f)
 
-    for f in a:
-        if ds[f] == 'r':
-            # added + removed -> unknown
-            ds.drop(f)
-        elif ds[f] != 'a':
+        for f in r:
+            # These are files which are removed between oldctx and ctx, which
+            # means the files which were added in oldctx and were completely
+            # uncommitted in ctx. If a added file is partially uncommitted, that
+            # would have resulted in modified status, not removed.
+            # So a file added in a commit, and uncommitting that addition must
+            # result in file being stated as unknown.
+            if ds[f] == 'r':
+                # The working directory say it's removed, so lets make the file
+                # unknown
+                ds.drop(f)
+                continue
             ds.add(f)
+    else:
+        m, a, r = repo.status(oldctx.p1(), oldctx, match=match)[:3]
+        for f in m:
+            if ds[f] == 'r':
+                # modified + removed -> removed
+                continue
+            ds.normallookup(f)
 
-    for f in r:
-        if ds[f] == 'a':
-            # removed + added -> normal
-            ds.normallookup(f)
-        elif ds[f] != 'r':
-            ds.remove(f)
+        for f in a:
+            if ds[f] == 'r':
+                # added + removed -> unknown
+                ds.drop(f)
+            elif ds[f] != 'a':
+                ds.add(f)
+
+        for f in r:
+            if ds[f] == 'a':
+                # removed + added -> normal
+                ds.normallookup(f)
+            elif ds[f] != 'r':
+                ds.remove(f)
 
     # Merge old parent and old working dir copies
     oldcopies = {}
+    if interactive:
+        # Interactive had different meaning of the variables so restoring the
+        # original meaning to use them
+        m, a, r = repo.status(oldctx.p1(), oldctx, match=match)[:3]
     for f in (m + a):
         src = oldctx[f].renamed()
         if src:
@@ -234,6 +286,7 @@
 @eh.command(
     '^uncommit',
     [('a', 'all', None, _('uncommit all changes when no arguments given')),
+     ('i', 'interactive', False, _('interactive mode to uncommit (EXPERIMENTAL)')),
      ('r', 'rev', '', _('revert commit content to REV instead')),
      ] + commands.walkopts + commitopts + commitopts2 + commitopts3,
     _('[OPTION]... [NAME]'))
@@ -252,10 +305,16 @@
     revision. It still does not change the content of your file in the working
     directory.
 
+    .. container:: verbose
+
+       The --interactive option lets you select hunks interactively to uncommit.
+       You can uncommit parts of file using this option.
+
     Return 0 if changed files are uncommitted.
     """
 
     _resolveoptions(ui, opts) # process commitopts3
+    interactive = opts.get('interactive')
     wlock = lock = tr = None
     try:
         wlock = repo.wlock()
@@ -287,25 +346,30 @@
         # Recommit the filtered changeset
         tr = repo.transaction('uncommit')
         updatebookmarks = rewriteutil.bookmarksupdater(repo, old.node(), tr)
-        newid = None
-        includeorexclude = opts.get('include') or opts.get('exclude')
-        if (pats or includeorexclude or opts.get('all')):
+        if interactive:
+            opts['all'] = True
             match = scmutil.match(old, pats, opts)
-            if not (opts['message'] or opts['logfile']):
-                opts['message'] = old.description()
-            message = cmdutil.logmessage(ui, opts)
-            newid = _commitfiltered(repo, old, match, target=rev,
-                                    message=message, user=opts.get('user'),
-                                    date=opts.get('date'))
-        if newid is None:
-            raise error.Abort(_('nothing to uncommit'),
-                              hint=_("use --all to uncommit all files"))
-        # Move local changes on filtered changeset
+            newid = _interactiveuncommit(ui, repo, old, match)
+        else:
+            newid = None
+            includeorexclude = opts.get('include') or opts.get('exclude')
+            if (pats or includeorexclude or opts.get('all')):
+                match = scmutil.match(old, pats, opts)
+                if not (opts['message'] or opts['logfile']):
+                    opts['message'] = old.description()
+                message = cmdutil.logmessage(ui, opts)
+                newid = _commitfiltered(repo, old, match, target=rev,
+                                        message=message, user=opts.get('user'),
+                                        date=opts.get('date'))
+            if newid is None:
+                raise error.Abort(_('nothing to uncommit'),
+                                  hint=_("use --all to uncommit all files"))
+
         obsolete.createmarkers(repo, [(old, (repo[newid],))])
         phases.retractboundary(repo, tr, oldphase, [newid])
         with repo.dirstate.parentchange():
             repo.dirstate.setparents(newid, node.nullid)
-            _uncommitdirstate(repo, old, match)
+            _uncommitdirstate(repo, old, match, interactive)
         updatebookmarks(newid)
         if not repo[newid].files():
             ui.warn(_("new changeset is empty\n"))
@@ -314,6 +378,101 @@
     finally:
         lockmod.release(tr, lock, wlock)
 
+def _interactiveuncommit(ui, repo, old, match):
+    """ The function which contains all the logic for interactively uncommiting
+    a commit. This function makes a temporary commit with the chunks which user
+    selected to uncommit. After that the diff of the parent and that commit is
+    applied to the working directory and committed again which results in the
+    new commit which should be one after uncommitted.
+    """
+
+    # create a temporary commit with hunks user selected
+    tempnode = _createtempcommit(ui, repo, old, match)
+
+    diffopts = patch.difffeatureopts(repo.ui, whitespace=True)
+    diffopts.nodates = True
+    diffopts.git = True
+    fp = stringio()
+    for chunk, label in patch.diffui(repo, tempnode, old.node(), None,
+                                     opts=diffopts):
+            fp.write(chunk)
+
+    fp.seek(0)
+    newnode = _patchtocommit(ui, repo, old, fp)
+    # creating obs marker temp -> ()
+    obsolete.createmarkers(repo, [(repo[tempnode], ())])
+    return newnode
+
+def _createtempcommit(ui, repo, old, match):
+    """ Creates a temporary commit for `uncommit --interative` which contains
+    the hunks which were selected by the user to uncommit.
+    """
+
+    pold = old.p1()
+    # The logic to interactively selecting something copied from
+    # cmdutil.revert()
+    diffopts = patch.difffeatureopts(repo.ui, whitespace=True)
+    diffopts.nodates = True
+    diffopts.git = True
+    diff = patch.diff(repo, pold.node(), old.node(), match, opts=diffopts)
+    originalchunks = patch.parsepatch(diff)
+    # XXX: The interactive selection is buggy and does not let you
+    # uncommit a removed file partially.
+    # TODO: wrap the operations in mercurial/patch.py and mercurial/crecord.py
+    # to add uncommit as an operation taking care of BC.
+    chunks, opts = cmdutil.recordfilter(repo.ui, originalchunks,
+                                        operation='discard')
+    if not chunks:
+        raise error.Abort(_("nothing selected to uncommit"))
+    fp = stringio()
+    for c in chunks:
+            c.write(fp)
+
+    fp.seek(0)
+    oldnode = node.hex(old.node())[:12]
+    message = 'temporary commit for uncommiting %s' % oldnode
+    tempnode = _patchtocommit(ui, repo, old, fp, message, oldnode)
+    return tempnode
+
+def _patchtocommit(ui, repo, old, fp, message=None, extras=None):
+    """ A function which will apply the patch to the working directory and
+    make a commit whose parents are same as that of old argument. The message
+    argument tells us whether to use the message of the old commit or a
+    different message which is passed. Returns the node of new commit made.
+    """
+    pold = old.p1()
+    parents = (old.p1().node(), old.p2().node())
+    date = old.date()
+    branch = old.branch()
+    user = old.user()
+    extra = old.extra()
+    if extras:
+        extra['uncommit_source'] = extras
+    if not message:
+        message = old.description()
+    store = patch.filestore()
+    try:
+        files = set()
+        try:
+            patch.patchrepo(ui, repo, pold, store, fp, 1, '',
+                            files=files, eolmode=None)
+        except patch.PatchError as err:
+            raise error.Abort(str(err))
+
+        finally:
+            del fp
+
+        memctx = context.memctx(repo, parents, message, files=files,
+                                filectxfn=store,
+                                user=user,
+                                date=date,
+                                branch=branch,
+                                extra=extra)
+        newcm = memctx.commit()
+    finally:
+        store.close()
+    return newcm
+
 @eh.command(
     '^fold|squash',
     [('r', 'rev', [], _("revision to fold")),
@@ -350,7 +509,7 @@
 
          hg fold --from 3::6
 
-     - Fold revisions 3 and 4:
+     - Fold revisions 3 and 4::
 
         hg fold "3 + 4" --exact
 
--- a/hgext3rd/evolve/compat.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/compat.py	Tue Nov 14 23:04:04 2017 +0100
@@ -7,8 +7,11 @@
 """
 
 from mercurial import (
+    copies,
+    context,
     hg,
     obsolete,
+    revset,
     util,
 )
 
@@ -45,7 +48,7 @@
         pendingnodes = set(nodes)
         seenmarkers = set()
         seennodes = set(pendingnodes)
-        precursorsmarkers = self.precursors
+        precursorsmarkers = self.predecessors
         succsmarkers = self.successors
         children = self.children
         while pendingnodes:
@@ -71,10 +74,13 @@
     return func(*args, **kwargs)
 
 # allprecursors set move from mercurial.obsolete to mercurial.obsutil in 4.3
+# allprecursors  was renamed into allpredecessors in 4.4
 def allprecursors(*args, **kwargs):
-    func = getattr(obsutil, 'allprecursors', None)
+    func = getattr(obsutil, 'allpredecessors', None)
     if func is None:
-        func = obsolete.allprecursors
+        func = getattr(obsutil, 'allprecursors', None)
+        if func is None:
+            func = obsolete.allprecursors
     return func(*args, **kwargs)
 
 # compatibility layer for mercurial < 4.3
@@ -86,7 +92,98 @@
         return bookmarks.applychanges(repo, tr, changes)
     for name, node in changes:
         if node is None:
-            bookmarks._del(name)
+            del bookmarks[name]
         else:
-            bookmarks._set(name, node)
+            bookmarks[name] = node
     bookmarks.recordchange(tr)
+
+# Evolution renaming compat
+
+TROUBLES = {}
+
+if not util.safehasattr(context.basectx, 'orphan'):
+    TROUBLES['ORPHAN'] = 'unstable'
+    context.basectx.orphan = context.basectx.unstable
+else:
+    TROUBLES['ORPHAN'] = 'orphan'
+
+if not util.safehasattr(context.basectx, 'contentdivergent'):
+    TROUBLES['CONTENTDIVERGENT'] = 'divergent'
+    context.basectx.contentdivergent = context.basectx.divergent
+else:
+    TROUBLES['CONTENTDIVERGENT'] = 'content-divergent'
+
+if not util.safehasattr(context.basectx, 'phasedivergent'):
+    TROUBLES['PHASEDIVERGENT'] = 'bumped'
+    context.basectx.phasedivergent = context.basectx.bumped
+else:
+    TROUBLES['PHASEDIVERGENT'] = 'phase-divergent'
+
+if not util.safehasattr(context.basectx, 'isunstable'):
+    context.basectx.isunstable = context.basectx.troubled
+
+if not util.safehasattr(revset, 'orphan'):
+    @eh.revset('orphan')
+    def oprhanrevset(*args, **kwargs):
+        return revset.unstable(*args, **kwargs)
+
+if not util.safehasattr(revset, 'contentdivergent'):
+    @eh.revset('contentdivergent')
+    def contentdivergentrevset(*args, **kwargs):
+        return revset.divergent(*args, **kwargs)
+
+if not util.safehasattr(revset, 'phasedivergent'):
+    @eh.revset('phasedivergent')
+    def phasedivergentrevset(*args, **kwargs):
+        return revset.bumped(*args, **kwargs)
+
+if not util.safehasattr(context.basectx, 'instabilities'):
+    def instabilities(self):
+        """return the list of instabilities affecting this changeset.
+
+        Instabilities are returned as strings. possible values are:
+         - orphan,
+         - phase-divergent,
+         - content-divergent.
+         """
+        instabilities = []
+        if self.orphan():
+            instabilities.append('orphan')
+        if self.phasedivergent():
+            instabilities.append('phase-divergent')
+        if self.contentdivergent():
+            instabilities.append('content-divergent')
+        return instabilities
+
+    context.basectx.instabilities = instabilities
+
+# XXX: Better detection of property cache
+if 'predecessors' not in dir(obsolete.obsstore):
+    @property
+    def predecessors(self):
+        return self.precursors
+
+    obsolete.obsstore.predecessors = predecessors
+
+if not util.safehasattr(obsolete, '_computeorphanset'):
+    obsolete._computeorphanset = obsolete.cachefor('orphan')(obsolete._computeunstableset)
+
+if not util.safehasattr(obsolete, '_computecontentdivergentset'):
+    obsolete._computecontentdivergentset = obsolete.cachefor('contentdivergent')(obsolete._computedivergentset)
+
+if not util.safehasattr(obsolete, '_computephasedivergentset'):
+    obsolete._computephasedivergentset = obsolete.cachefor('phasedivergent')(obsolete._computebumpedset)
+
+def startpager(ui, cmd):
+    """function to start a pager in case ui.pager() exists"""
+    if util.safehasattr(ui, 'pager'):
+        ui.pager(cmd)
+
+def duplicatecopies(repo, wctx, rev, fromrev, skiprev=None):
+    # cannot use anything else until 4.3 support is dropped.
+    assert wctx.rev() is None
+    if copies.duplicatecopies.__code__.co_argcount < 5:
+        # pre 4.4 duplicatecopies compat
+        copies.duplicatecopies(repo, rev, fromrev, skiprev=skiprev)
+    else:
+        copies.duplicatecopies(repo, wctx, rev, fromrev, skiprev=skiprev)
--- a/hgext3rd/evolve/exthelper.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/exthelper.py	Tue Nov 14 23:04:04 2017 +0100
@@ -17,6 +17,13 @@
     from mercurial import cmdutil
     command = cmdutil.command
 
+configitem = None
+dynamicdefault = None
+if util.safehasattr(registrar, 'configitem'):
+    configitem = registrar.configitem
+    from mercurial import configitems
+    dynamicdefault = configitems.dynamicdefault
+
 class exthelper(object):
     """Helper for modular extension setup
 
@@ -39,6 +46,22 @@
         self.cmdtable = {}
         self.command = command(self.cmdtable)
 
+        self.configtable = {}
+        self._configitem = None
+        if configitem is not None:
+            self._configitem = configitem(self.configtable)
+
+    def configitem(self, section, config):
+        """For Mercurial 4.4 and above, register a config item
+
+        For now constraint to 'dynamicdefault' until we only support version with the feature.
+        Older version would otherwise not use the declare default.
+
+        For older version no-op fallback for old Mercurial versions
+        """
+        if self._configitem is not None:
+            self._configitem(section, config, default=dynamicdefault)
+
     def merge(self, other):
         self._uicallables.extend(other._uicallables)
         self._extcallables.extend(other._extcallables)
@@ -50,6 +73,11 @@
         self._functionwrappers.extend(other._functionwrappers)
         self._duckpunchers.extend(other._duckpunchers)
         self.cmdtable.update(other.cmdtable)
+        for section, items in other.configtable.iteritems():
+            if section in self.configtable:
+                self.configtable[section].update(items)
+            else:
+                self.configtable[section] = items
 
     def final_uisetup(self, ui):
         """Method to be used as the extension uisetup
@@ -93,10 +121,17 @@
         - Register revset functions
         """
         knownexts = {}
+
+        revsetpredicate = registrar.revsetpredicate()
         for name, symbol in self._revsetsymbols:
-            revset.symbols[name] = symbol
+            revsetpredicate(name)(symbol)
+        revset.loadpredicate(ui, 'evolve', revsetpredicate)
+
+        templatekeyword = registrar.templatekeyword()
         for name, kw in self._templatekws:
-            templatekw.keywords[name] = kw
+            templatekeyword(name)(kw)
+        templatekw.loadkeyword(ui, 'evolve', templatekeyword)
+
         for ext, command, wrapper, opts in self._extcommandwrappers:
             if ext not in knownexts:
                 try:
--- a/hgext3rd/evolve/hack/directaccess.py	Tue Jul 25 02:29:28 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,199 +0,0 @@
-""" This extension provides direct access
-It is the ability to refer and access hidden sha in commands provided that you
-know their value.
-For example hg log -r xxx where xxx is a commit has should work whether xxx is
-hidden or not as we assume that the user knows what he is doing when referring
-to xxx.
-"""
-from mercurial import extensions
-from mercurial import repoview
-from mercurial import branchmap
-from mercurial import registrar
-from mercurial import revset
-from mercurial import error
-from mercurial import commands
-from mercurial import hg
-from mercurial import util
-from mercurial.i18n import _
-
-cmdtable = {}
-
-if util.safehasattr(registrar, 'command'):
-    command = registrar.command(cmdtable)
-else: # compat with hg < 4.3
-    from mercurial import cmdutil
-    command = cmdutil.command(cmdtable)
-
-# By default, all the commands have directaccess with warnings
-# List of commands that have no directaccess and directaccess with no warning
-directaccesslevel = [
-    # Format:
-    # ('nowarning', 'evolve', 'prune'),
-    # means: no directaccess warning, for the command in evolve named prune
-    #
-    # ('error', None, 'serve'),
-    # means: no directaccess for the command in core named serve
-    #
-    # The list is ordered alphabetically by command names, starting with all
-    # the commands in core then all the commands in the extensions
-    #
-    # The general guideline is:
-    # - remove directaccess warnings for read only commands
-    # - no direct access for commands with consequences outside of the repo
-    # - leave directaccess warnings for all the other commands
-    #
-    ('nowarning', None, 'annotate'),
-    ('nowarning', None, 'archive'),
-    ('nowarning', None, 'bisect'),
-    ('nowarning', None, 'bookmarks'),
-    ('nowarning', None, 'bundle'),
-    ('nowarning', None, 'cat'),
-    ('nowarning', None, 'diff'),
-    ('nowarning', None, 'export'),
-    ('nowarning', None, 'identify'),
-    ('nowarning', None, 'incoming'),
-    ('nowarning', None, 'log'),
-    ('nowarning', None, 'manifest'),
-    ('error', None, 'outgoing'), # confusing if push errors and not outgoing
-    ('error', None, 'push'), # destructive
-    ('nowarning', None, 'revert'),
-    ('error', None, 'serve'),
-    ('nowarning', None, 'tags'),
-    ('nowarning', None, 'unbundle'),
-    ('nowarning', None, 'update'),
-]
-
-def reposetup(ui, repo):
-    repo._explicitaccess = set()
-
-def _computehidden(repo):
-    hidden = repoview.filterrevs(repo, 'visible')
-    cl = repo.changelog
-    dynamic = hidden & repo._explicitaccess
-    if dynamic:
-        blocked = cl.ancestors(dynamic, inclusive=True)
-        hidden = frozenset(r for r in hidden if r not in blocked)
-    return hidden
-
-def setupdirectaccess():
-    """ Add two new filtername that behave like visible to provide direct access
-    and direct access with warning. Wraps the commands to setup direct access
-    """
-    repoview.filtertable.update({'visible-directaccess-nowarn': _computehidden})
-    repoview.filtertable.update({'visible-directaccess-warn': _computehidden})
-    branchmap.subsettable['visible-directaccess-nowarn'] = 'visible'
-    branchmap.subsettable['visible-directaccess-warn'] = 'visible'
-
-    for warn, ext, cmd in directaccesslevel:
-        try:
-            cmdtable = extensions.find(ext).cmdtable if ext else commands.table
-            wrapper = wrapwitherror if warn == 'error' else wrapwithoutwarning
-            extensions.wrapcommand(cmdtable, cmd, wrapper)
-        except (error.UnknownCommand, KeyError):
-            pass
-
-def wrapwitherror(orig, ui, repo, *args, **kwargs):
-    if repo and repo.filtername == 'visible-directaccess-warn':
-        repo = repo.filtered('visible')
-    return orig(ui, repo, *args, **kwargs)
-
-def wrapwithoutwarning(orig, ui, repo, *args, **kwargs):
-    if repo and repo.filtername == 'visible-directaccess-warn':
-        repo = repo.filtered("visible-directaccess-nowarn")
-    return orig(ui, repo, *args, **kwargs)
-
-def uisetup(ui):
-    """ Change ordering of extensions to ensure that directaccess extsetup comes
-    after the one of the extensions in the loadsafter list """
-    loadsafter = ui.configlist('directaccess', 'loadsafter')
-    order = list(extensions._order)
-    directaccesidx = order.index('directaccess')
-
-    # The min idx for directaccess to load after all the extensions in loadafter
-    minidxdirectaccess = directaccesidx
-
-    for ext in loadsafter:
-        try:
-            minidxdirectaccess = max(minidxdirectaccess, order.index(ext))
-        except ValueError:
-            pass # extension not loaded
-
-    if minidxdirectaccess > directaccesidx:
-        order.insert(minidxdirectaccess + 1, 'directaccess')
-        order.remove('directaccess')
-        extensions._order = order
-
-def _repository(orig, *args, **kwargs):
-    """Make visible-directaccess-warn the default filter for new repos"""
-    repo = orig(*args, **kwargs)
-    return repo.filtered("visible-directaccess-warn")
-
-def extsetup(ui):
-    extensions.wrapfunction(revset, 'posttreebuilthook', _posttreebuilthook)
-    extensions.wrapfunction(hg, 'repository', _repository)
-    setupdirectaccess()
-
-hashre = util.re.compile('[0-9a-fA-F]{1,40}')
-
-_listtuple = ('symbol', '_list')
-
-def _ishashsymbol(symbol, maxrev):
-    # Returns true if symbol looks like a hash
-    try:
-        n = int(symbol)
-        if n <= maxrev:
-            # It's a rev number
-            return False
-    except ValueError:
-        pass
-    return hashre.match(symbol)
-
-def gethashsymbols(tree, maxrev):
-    # Returns the list of symbols of the tree that look like hashes
-    # for example for the revset 3::abe3ff it will return ('abe3ff')
-    if not tree:
-        return []
-
-    results = []
-    if len(tree) == 2 and tree[0] == "symbol":
-        results.append(tree[1])
-    elif tree[0] == "func" and tree[1] == _listtuple:
-        # the optimiser will group sequence of hash request
-        results += tree[2][1].split('\0')
-    elif len(tree) >= 3:
-        for subtree in tree[1:]:
-            results += gethashsymbols(subtree, maxrev)
-        # return directly, we don't need to filter symbols again
-        return results
-    return [s for s in results if _ishashsymbol(s, maxrev)]
-
-def _posttreebuilthook(orig, tree, repo):
-    # This is use to enabled direct hash access
-    # We extract the symbols that look like hashes and add them to the
-    # explicitaccess set
-    orig(tree, repo)
-    filternm = ""
-    if repo is not None:
-        filternm = repo.filtername
-    if filternm is not None and filternm.startswith('visible-directaccess'):
-        prelength = len(repo._explicitaccess)
-        accessbefore = set(repo._explicitaccess)
-        cl = repo.unfiltered().changelog
-        repo.symbols = gethashsymbols(tree, len(cl))
-        for node in repo.symbols:
-            try:
-                node = cl._partialmatch(node)
-            except error.LookupError:
-                node = None
-            if node is not None:
-                rev = cl.rev(node)
-                if rev not in repo.changelog:
-                    repo._explicitaccess.add(rev)
-        if prelength != len(repo._explicitaccess):
-            if repo.filtername != 'visible-directaccess-nowarn':
-                unhiddencommits = repo._explicitaccess - accessbefore
-                repo.ui.warn(_("Warning: accessing hidden changesets %s "
-                               "for write operation\n") %
-                             (",".join([str(repo.unfiltered()[l])
-                              for l in unhiddencommits])))
-            repo.invalidatevolatilesets()
--- a/hgext3rd/evolve/hack/drophack.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/hack/drophack.py	Tue Nov 14 23:04:04 2017 +0100
@@ -50,7 +50,7 @@
     seennodes = set(nodes)
     seenmarkers = set()
     pendingnodes = set(nodes)
-    precursorsmarkers = obsstore.precursors
+    precursorsmarkers = obsstore.predecessors
     while pendingnodes:
         current = pendingnodes.pop()
         new = set()
--- a/hgext3rd/evolve/hack/inhibit.py	Tue Jul 25 02:29:28 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,316 +0,0 @@
-"""reduce the changesets evolution feature scope for early and noob friendly ui
-
-the full scale changeset evolution have some massive bleeding edge and it is
-very easy for people not very intimate with the concept to end up in intricate
-situation. in order to get some of the benefit sooner, this extension is
-disabling some of the less polished aspect of evolution. it should gradually
-get thinner and thinner as changeset evolution will get more polished. this
-extension is only recommended for large scale organisations. individual user
-should probably stick on using evolution in its current state, understand its
-concept and provide feedback
-
-This extension provides the ability to "inhibit" obsolescence markers. obsolete
-revision can be cheaply brought back to life that way.
-However as the inhibitor are not fitting in an append only model, this is
-incompatible with sharing mutable history.
-"""
-from mercurial import bookmarks
-from mercurial import commands
-from mercurial import error
-from mercurial import extensions
-from mercurial import localrepo
-from mercurial import lock as lockmod
-from mercurial import obsolete
-from mercurial import registrar
-from mercurial import scmutil
-from mercurial import util
-from mercurial.i18n import _
-
-cmdtable = {}
-
-if util.safehasattr(registrar, 'command'):
-    command = registrar.command(cmdtable)
-else: # compat with hg < 4.3
-    from mercurial import cmdutil
-    command = cmdutil.command(cmdtable)
-
-def _inhibitenabled(repo):
-    return util.safehasattr(repo, '_obsinhibit')
-
-def reposetup(ui, repo):
-
-    class obsinhibitedrepo(repo.__class__):
-
-        @localrepo.storecache('obsinhibit')
-        def _obsinhibit(self):
-            # XXX we should make sure it is invalidated by transaction failure
-            obsinhibit = set()
-            raw = self.svfs.tryread('obsinhibit')
-            for i in xrange(0, len(raw), 20):
-                obsinhibit.add(raw[i:i + 20])
-            return obsinhibit
-
-        def commit(self, *args, **kwargs):
-            newnode = super(obsinhibitedrepo, self).commit(*args, **kwargs)
-            if newnode is not None:
-                _inhibitmarkers(repo, [newnode])
-            return newnode
-
-    repo.__class__ = obsinhibitedrepo
-
-def _update(orig, ui, repo, *args, **kwargs):
-    """
-    When moving to a commit we want to inhibit any obsolete commit affecting
-    the changeset we are updating to. In other words we don't want any visible
-    commit to be obsolete.
-    """
-    wlock = None
-    try:
-        # Evolve is running a hook on lock release to display a warning message
-        # if the workind dir's parent is obsolete.
-        # We take the lock here to make sure that we inhibit the parent before
-        # that hook get a chance to run.
-        wlock = repo.wlock()
-        res = orig(ui, repo, *args, **kwargs)
-        newhead = repo['.'].node()
-        _inhibitmarkers(repo, [newhead])
-        return res
-    finally:
-        lockmod.release(wlock)
-
-def _bookmarkchanged(orig, bkmstoreinst, *args, **kwargs):
-    """ Add inhibition markers to every obsolete bookmarks """
-    repo = bkmstoreinst._repo
-    bkmstorenodes = [repo[v].node() for v in bkmstoreinst.values()]
-    _inhibitmarkers(repo, bkmstorenodes)
-    return orig(bkmstoreinst, *args, **kwargs)
-
-def _bookmark(orig, ui, repo, *bookmarks, **opts):
-    """ Add a -D option to the bookmark command, map it to prune -B """
-    haspruneopt = opts.get('prune', False)
-    if not haspruneopt:
-        return orig(ui, repo, *bookmarks, **opts)
-    elif opts.get('rename'):
-        raise error.Abort('Cannot use both -m and -D')
-    elif len(bookmarks) == 0:
-        hint = _('make sure to put a space between -D and your bookmark name')
-        raise error.Abort(_('Error, please check your command'), hint=hint)
-
-    # Call prune -B
-    evolve = extensions.find('evolve')
-    optsdict = {
-        'new': [],
-        'succ': [],
-        'rev': [],
-        'bookmark': bookmarks,
-        'keep': None,
-        'biject': False,
-    }
-    evolve.cmdrewrite.cmdprune(ui, repo, **optsdict)
-
-# obsolescence inhibitor
-########################
-
-def _schedulewrite(tr, obsinhibit):
-    """Make sure on disk content will be updated on transaction commit"""
-    def writer(fp):
-        """Serialize the inhibited list to disk.
-        """
-        raw = ''.join(obsinhibit)
-        fp.write(raw)
-    tr.addfilegenerator('obsinhibit', ('obsinhibit',), writer)
-    tr.hookargs['obs_inbihited'] = '1'
-
-def _filterpublic(repo, nodes):
-    """filter out inhibitor on public changeset
-
-    Public changesets are already immune to obsolescence"""
-    getrev = repo.changelog.nodemap.get
-    getphase = repo._phasecache.phase
-    return (n for n in nodes
-            if getrev(n) is not None and getphase(repo, getrev(n)))
-
-def _inhibitmarkers(repo, nodes):
-    """add marker inhibitor for all obsolete revision under <nodes>
-
-    Content of <nodes> and all mutable ancestors are considered. Marker for
-    obsolete revision only are created.
-    """
-    if not _inhibitenabled(repo):
-        return
-
-    # we add (non public()) as a lower boundary to
-    # - use the C code in 3.6 (no ancestors in C as this is written)
-    # - restrict the search space. Otherwise, the ancestors can spend a lot of
-    #   time iterating if you have a check very low in the repo. We do not need
-    #   to iterate over tens of thousand of public revisions with higher
-    #   revision number
-    #
-    # In addition, the revset logic could be made significantly smarter here.
-    newinhibit = repo.revs('(not public())::%ln and obsolete()', nodes)
-    if newinhibit:
-        node = repo.changelog.node
-        lock = tr = None
-        try:
-            lock = repo.lock()
-            tr = repo.transaction('obsinhibit')
-            repo._obsinhibit.update(node(r) for r in newinhibit)
-            _schedulewrite(tr, _filterpublic(repo, repo._obsinhibit))
-            repo.invalidatevolatilesets()
-            tr.close()
-        finally:
-            lockmod.release(tr, lock)
-
-def _deinhibitmarkers(repo, nodes):
-    """lift obsolescence inhibition on a set of nodes
-
-    This will be triggered when inhibited nodes received new obsolescence
-    markers. Otherwise the new obsolescence markers would also be inhibited.
-    """
-    if not _inhibitenabled(repo):
-        return
-
-    deinhibited = repo._obsinhibit & set(nodes)
-    if deinhibited:
-        tr = repo.transaction('obsinhibit')
-        try:
-            repo._obsinhibit -= deinhibited
-            _schedulewrite(tr, _filterpublic(repo, repo._obsinhibit))
-            repo.invalidatevolatilesets()
-            tr.close()
-        finally:
-            tr.release()
-
-def _createmarkers(orig, repo, relations, *args, **kwargs):
-    """wrap markers create to make sure we de-inhibit target nodes"""
-    # wrapping transactio to unify the one in each function
-    lock = tr = None
-    try:
-        lock = repo.lock()
-        tr = repo.transaction('add-obsolescence-marker')
-        orig(repo, relations, *args, **kwargs)
-        precs = (r[0].node() for r in relations)
-        _deinhibitmarkers(repo, precs)
-        tr.close()
-    finally:
-        lockmod.release(tr, lock)
-
-def _filterobsoleterevswrap(orig, repo, rebasesetrevs, *args, **kwargs):
-    repo._notinhibited = rebasesetrevs
-    try:
-        repo.invalidatevolatilesets()
-        r = orig(repo, rebasesetrevs, *args, **kwargs)
-    finally:
-        del repo._notinhibited
-        repo.invalidatevolatilesets()
-    return r
-
-def transactioncallback(orig, repo, desc, *args, **kwargs):
-    """ Wrap localrepo.transaction to inhibit new obsolete changes """
-    def inhibitposttransaction(transaction):
-        # At the end of the transaction we catch all the new visible and
-        # obsolete commit to inhibit them
-        visibleobsolete = repo.revs('obsolete() - hidden()')
-        ignoreset = set(getattr(repo, '_rebaseset', []))
-        ignoreset |= set(getattr(repo, '_obsoletenotrebased', []))
-        visibleobsolete = list(r for r in visibleobsolete if r not in ignoreset)
-        if visibleobsolete:
-            _inhibitmarkers(repo, [repo[r].node() for r in visibleobsolete])
-    transaction = orig(repo, desc, *args, **kwargs)
-    if desc != 'strip' and _inhibitenabled(repo):
-        transaction.addpostclose('inhibitposttransaction',
-                                 inhibitposttransaction)
-    return transaction
-
-
-# We wrap these two functions to address the following scenario:
-# - Assuming that we have markers between commits in the rebase set and
-#   destination and that these markers are inhibited
-# - At the end of the rebase the nodes are still visible because rebase operate
-#   without inhibition and skip these nodes
-# We keep track in repo._obsoletenotrebased of the obsolete commits skipped by
-# the rebase and lift the inhibition in the end of the rebase.
-
-def _computeobsoletenotrebased(orig, repo, *args, **kwargs):
-    r = orig(repo, *args, **kwargs)
-    repo._obsoletenotrebased = r.keys()
-    return r
-
-def _clearrebased(orig, ui, repo, *args, **kwargs):
-    r = orig(ui, repo, *args, **kwargs)
-    tonode = repo.changelog.node
-    if util.safehasattr(repo, '_obsoletenotrebased'):
-        _deinhibitmarkers(repo, [tonode(k) for k in repo._obsoletenotrebased])
-    return r
-
-
-def extsetup(ui):
-    # lets wrap the computation of the obsolete set
-    # We apply inhibition there
-    obsfunc = obsolete.cachefuncs['obsolete']
-
-    def _computeobsoleteset(repo):
-        """remove any inhibited nodes from the obsolete set
-
-        This will trickle down to other part of mercurial (hidden, log, etc)"""
-        obs = obsfunc(repo)
-        if _inhibitenabled(repo):
-            getrev = repo.changelog.nodemap.get
-            blacklist = getattr(repo, '_notinhibited', set())
-            for n in repo._obsinhibit:
-                if getrev(n) not in blacklist:
-                    obs.discard(getrev(n))
-        return obs
-    try:
-        extensions.find('directaccess')
-    except KeyError:
-        errormsg = _('cannot use inhibit without the direct access extension\n')
-        hint = _("(please enable it or inhibit won\'t work)\n")
-        ui.warn(errormsg)
-        ui.warn(hint)
-        return
-
-    # Wrapping this to inhibit obsolete revs resulting from a transaction
-    extensions.wrapfunction(localrepo.localrepository,
-                            'transaction', transactioncallback)
-
-    obsolete.cachefuncs['obsolete'] = _computeobsoleteset
-    # wrap create marker to make it able to lift the inhibition
-    extensions.wrapfunction(obsolete, 'createmarkers', _createmarkers)
-    # drop divergence computation since it is incompatible with "light revive"
-    obsolete.cachefuncs['divergent'] = lambda repo: set()
-    # drop bumped computation since it is incompatible with "light revive"
-    obsolete.cachefuncs['bumped'] = lambda repo: set()
-    # wrap update to make sure that no obsolete commit is visible after an
-    # update
-    extensions.wrapcommand(commands.table, 'update', _update)
-    try:
-        rebase = extensions.find('rebase')
-        if rebase:
-            if util.safehasattr(rebase, '_filterobsoleterevs'):
-                extensions.wrapfunction(rebase,
-                                        '_filterobsoleterevs',
-                                        _filterobsoleterevswrap)
-            extensions.wrapfunction(rebase, 'clearrebased', _clearrebased)
-            if util.safehasattr(rebase, '_computeobsoletenotrebased'):
-                extensions.wrapfunction(rebase,
-                                        '_computeobsoletenotrebased',
-                                        _computeobsoletenotrebased)
-
-    except KeyError:
-        pass
-    # There are two ways to save bookmark changes during a transation, we
-    # wrap both to add inhibition markers.
-    extensions.wrapfunction(bookmarks.bmstore, 'recordchange', _bookmarkchanged)
-    if getattr(bookmarks.bmstore, 'write', None) is not None:# mercurial < 3.9
-        extensions.wrapfunction(bookmarks.bmstore, 'write', _bookmarkchanged)
-    # Add bookmark -D option
-    entry = extensions.wrapcommand(commands.table, 'bookmark', _bookmark)
-    entry[1].append(('D', 'prune', None,
-                    _('delete the bookmark and prune the commits underneath')))
-
-@command('debugobsinhibit', [], '')
-def cmddebugobsinhibit(ui, repo, *revs):
-    """inhibit obsolescence markers effect on a set of revs"""
-    nodes = (repo[r].node() for r in scmutil.revrange(repo, revs))
-    _inhibitmarkers(repo, nodes)
--- a/hgext3rd/evolve/legacy.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/legacy.py	Tue Nov 14 23:04:04 2017 +0100
@@ -86,7 +86,7 @@
     """import markers from an .hg/obsolete-relations file"""
     cnt = 0
     err = 0
-    l = repo.lock()
+    lock = repo.lock()
     some = False
     try:
         unlink = []
@@ -129,16 +129,16 @@
                     del oldmark['reason']  # unused until then
                     oldobject = str(oldmark.pop('object'))
                     oldsubjects = [str(s) for s in oldmark.pop('subjects', [])]
-                    LOOKUP_ERRORS = (error.RepoLookupError, error.LookupError)
+                    lookup_errors = (error.RepoLookupError, error.LookupError)
                     if len(oldobject) != 40:
                         try:
                             oldobject = repo[oldobject].node()
-                        except LOOKUP_ERRORS:
+                        except lookup_errors:
                             pass
                     if any(len(s) != 40 for s in oldsubjects):
                         try:
                             oldsubjects = [repo[s].node() for s in oldsubjects]
-                        except LOOKUP_ERRORS:
+                        except lookup_errors:
                             pass
 
                     oldmark['date'] = '%i %i' % tuple(oldmark['date'])
@@ -163,7 +163,7 @@
             tr.release()
     finally:
         del repo._importoldobsolete
-        l.release()
+        lock.release()
     if not some:
         ui.warn(_('nothing to do\n'))
     ui.status('%i obsolete marker converted\n' % cnt)
--- a/hgext3rd/evolve/metadata.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/metadata.py	Tue Nov 14 23:04:04 2017 +0100
@@ -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__ = '6.6.0.dev'
-testedwith = '3.8.4 3.9.2 4.0.2 4.1.3 4.2.1'
-minimumhgversion = '3.8'
+__version__ = '7.0.1.dev'
+testedwith = '4.1.3 4.2.3 4.3.2 4.4'
+minimumhgversion = '4.1'
 buglink = 'https://bz.mercurial-scm.org/'
--- a/hgext3rd/evolve/obscache.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/obscache.py	Tue Nov 14 23:04:04 2017 +0100
@@ -22,7 +22,6 @@
     pycompat,
     node,
     util,
-    vfs as vfsmod,
 )
 
 from mercurial.i18n import _
@@ -43,16 +42,14 @@
 else:
     timer = time.time
 
-
+# hg < 4.2 compat
 try:
-    obsstorefilecache = localrepo.localrepository.obsstore
-except AttributeError:
-    # XXX hg-3.8 compat
-    #
-    # mercurial 3.8 has issue with accessing file cache property from their
-    # cache. This is fix by 36fbd72c2f39fef8ad52d7c559906c2bc388760c in core
-    # and shipped in 3.9
-    obsstorefilecache = localrepo.localrepository.__dict__['obsstore']
+    from mercurial import vfs as vfsmod
+    vfsmod.vfs
+except ImportError:
+    from mercurial import scmutil as vfsmod
+
+obsstorefilecache = localrepo.localrepository.obsstore
 
 # obsstore is a filecache so we have do to some spacial dancing
 @eh.wrapfunction(obsstorefilecache, 'func')
@@ -106,21 +103,29 @@
 
     return obsstore
 
-# XXX copied as is from Mercurial 4.2 and added the "offset" parameters
-@util.nogc
-def _readmarkers(data, offset=None):
-    """Read and enumerate markers from raw data"""
-    off = 0
-    diskversion = struct.unpack('>B', data[off:off + 1])[0]
-    if offset is None:
-        off += 1
-    else:
-        assert 1 <= offset
-        off = offset
-    if diskversion not in obsolete.formats:
-        raise error.Abort(_('parsing obsolete marker: unknown version %r')
-                          % diskversion)
-    return diskversion, obsolete.formats[diskversion][0](data, off)
+if obsolete._fm0readmarkers.__code__.co_argcount > 1:
+    # hg-4.3+ has the "offset" parameter, and _fm?readmarkers also have an
+    # extra "stop" parameter
+    # Note that _readmarkers is wrapped by @util.nogc, so its co_argcount is
+    # misleadingly 0. So we check _fm0readmarkers instead, which increased its
+    # argument count in the same changeset (5d3ba439).
+    _readmarkers = obsolete._readmarkers
+else:
+    # XXX copied as is from Mercurial 4.2 and added the "offset" parameters
+    @util.nogc
+    def _readmarkers(data, offset=None):
+        """Read and enumerate markers from raw data"""
+        off = 0
+        diskversion = struct.unpack('>B', data[off:off + 1])[0]
+        if offset is None:
+            off += 1
+        else:
+            assert 1 <= offset
+            off = offset
+        if diskversion not in obsolete.formats:
+            raise error.Abort(_('parsing obsolete marker: unknown version %r')
+                              % diskversion)
+        return diskversion, obsolete.formats[diskversion][0](data, off)
 
 def markersfrom(obsstore, byteoffset, firstmarker):
     if not firstmarker:
--- a/hgext3rd/evolve/obsdiscovery.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/obsdiscovery.py	Tue Nov 14 23:04:04 2017 +0100
@@ -72,6 +72,13 @@
 eh.merge(stablerange.eh)
 obsexcmsg = utility.obsexcmsg
 
+# Config
+eh.configitem('experimental', 'evolution.obsdiscovery')
+eh.configitem('experimental', 'obshashrange')
+eh.configitem('experimental', 'obshashrange.warm-cache')
+eh.configitem('experimental', 'obshashrange.max-revs')
+eh.configitem('experimental', 'obshashrange.lru-size')
+
 ##################################
 ###  Code performing discovery ###
 ##################################
@@ -550,15 +557,7 @@
     obsstore.rangeobshashcache.clear()
     return orig(obsstore, *args, **kwargs)
 
-try:
-    obsstorefilecache = localrepo.localrepository.obsstore
-except AttributeError:
-    # XXX hg-3.8 compat
-    #
-    # mercurial 3.8 has issue with accessing file cache property from their
-    # cache. This is fix by 36fbd72c2f39fef8ad52d7c559906c2bc388760c in core
-    # and shipped in 3.9
-    obsstorefilecache = localrepo.localrepository.__dict__['obsstore']
+obsstorefilecache = localrepo.localrepository.obsstore
 
 
 # obsstore is a filecache so we have do to some spacial dancing
@@ -821,7 +820,8 @@
 def _obshash_capabilities(orig, repo, proto):
     """wrapper to advertise new capability"""
     caps = orig(repo, proto)
-    if obsolete.isenabled(repo, obsolete.exchangeopt):
+    if (obsolete.isenabled(repo, obsolete.exchangeopt)
+        and repo.ui.configbool('experimental', 'evolution.obsdiscovery', True)):
         caps = caps.split()
         caps.append('_evoext_obshash_0')
         caps.append('_evoext_obshash_1')
--- a/hgext3rd/evolve/obsexchange.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/obsexchange.py	Tue Nov 14 23:04:04 2017 +0100
@@ -14,24 +14,20 @@
     import io
     StringIO = io.StringIO
 
-import errno
-import socket
-
 from mercurial import (
     bundle2,
     error,
     exchange,
     extensions,
-    httppeer,
-    localrepo,
     lock as lockmod,
     node,
     obsolete,
+    pushkey,
     util,
     wireproto,
 )
-from mercurial.hgweb import hgweb_mod
-from mercurial.i18n import _
+
+from mercurial.hgweb import common as hgwebcommon
 
 from . import (
     exthelper,
@@ -44,6 +40,7 @@
 obsexcmsg = utility.obsexcmsg
 obsexcprg = utility.obsexcprg
 
+eh.configitem('experimental', 'verbose-obsolescence-exchange')
 
 _bestformat = max(obsolete.formats.keys())
 
@@ -181,17 +178,6 @@
     obsdata.seek(0)
     return obsdata
 
-# The wireproto.streamres API changed, handling chunking and compression
-# directly. Handle either case.
-if util.safehasattr(wireproto.abstractserverproto, 'groupchunks'):
-    # We need to handle chunking and compression directly
-    def streamres(d, proto):
-        return wireproto.streamres(proto.groupchunks(d))
-else:
-    # Leave chunking and compression to streamres
-    def streamres(d, proto):
-        return wireproto.streamres(reader=d, v1compressible=True)
-
 def srv_pullobsmarkers(repo, proto, others):
     """serves a binary stream of markers.
 
@@ -208,245 +194,30 @@
     finaldata.write('%20i' % len(obsdata))
     finaldata.write(obsdata)
     finaldata.seek(0)
-    return streamres(finaldata, proto)
-
-###############################################
-### Support for old legacy exchange methods ###
-###############################################
-
-class pushobsmarkerStringIO(StringIO):
-    """hacky string io for progress"""
-
-    @util.propertycache
-    def length(self):
-        return len(self.getvalue())
+    return wireproto.streamres(reader=finaldata, v1compressible=True)
 
-    def read(self, size=None):
-        obsexcprg(self.ui, self.tell(), unit=_("bytes"), total=self.length)
-        return StringIO.read(self, size)
-
-    def __iter__(self):
-        d = self.read(4096)
-        while d:
-            yield d
-            d = self.read(4096)
-
-# compat-code: _pushobsolete
-#
-# the _pushobsolete function is a core function used to exchange
-# obsmarker with repository that does not support bundle2
+abortmsg = "won't exchange obsmarkers through pushkey"
+hint = "upgrade your client or server to use the bundle2 protocol"
 
-@eh.wrapfunction(exchange, '_pushobsolete')
-def _pushobsolete(orig, pushop):
-    """utility function to push obsolete markers to a remote"""
-    if not obsolete.isenabled(pushop.repo, obsolete.exchangeopt):
-        return
-    if 'obsmarkers' in pushop.stepsdone:
-        return
-    pushop.stepsdone.add('obsmarkers')
-    if pushop.cgresult == 0:
-        return
-    pushop.ui.debug('try to push obsolete markers to remote\n')
-    repo = pushop.repo
-    remote = pushop.remote
-    if (repo.obsstore and 'obsolete' in remote.listkeys('namespaces')):
-        markers = pushop.outobsmarkers
-        if not markers:
-            obsexcmsg(repo.ui, "no marker to push\n")
-        elif remote.capable('_evoext_pushobsmarkers_0'):
-            msg = ('the remote repository use years old versions of Mercurial'
-                   ' and evolve\npushing obsmarker using legacy method\n')
-            repo.ui.warn(msg)
-            repo.ui.warn('(please upgrade your server)\n')
-            obsdata = pushobsmarkerStringIO()
-            for chunk in obsolete.encodemarkers(markers, True):
-                obsdata.write(chunk)
-            obsdata.seek(0)
-            obsdata.ui = repo.ui
-            obsexcmsg(repo.ui, "pushing %i obsolescence markers (%i bytes)\n"
-                               % (len(markers), len(obsdata.getvalue())),
-                      True)
-            remote.evoext_pushobsmarkers_0(obsdata)
-            obsexcprg(repo.ui, None)
-
-        else:
-            # XXX core could be able do the same things but without the debug
-            # and progress output.
-            msg = ('the remote repository usea years old version of Mercurial'
-                   ' and not evolve extension\n')
-            repo.ui.warn(msg)
-            msg = 'pushing obsmarker using and extremely slow legacy method\n'
-            repo.ui.warn(msg)
-            repo.ui.warn('(please upgrade your server and enable evolve.serveronly on it)\n')
-            rslts = []
-            remotedata = obsolete._pushkeyescape(markers).items()
-            totalbytes = sum(len(d) for k, d in remotedata)
-            sentbytes = 0
-            obsexcmsg(repo.ui, "pushing %i obsolescence markers in %i "
-                               "pushkey payload (%i bytes)\n"
-                               % (len(markers), len(remotedata), totalbytes),
-                      True)
-            for key, data in remotedata:
-                obsexcprg(repo.ui, sentbytes, item=key, unit=_("bytes"),
-                          total=totalbytes)
-                rslts.append(remote.pushkey('obsolete', key, '', data))
-                sentbytes += len(data)
-                obsexcprg(repo.ui, sentbytes, item=key, unit=_("bytes"),
-                          total=totalbytes)
-            obsexcprg(repo.ui, None)
-            if [r for r in rslts if not r]:
-                msg = _('failed to push some obsolete markers!\n')
-                repo.ui.warn(msg)
-        obsexcmsg(repo.ui, "DONE\n")
-
-# Supporting legacy way to push obsmarker so that old client can still push
-# them somewhat efficiently
-
-@eh.addattr(wireproto.wirepeer, 'evoext_pushobsmarkers_0')
-def client_pushobsmarkers(self, obsfile):
-    """wireprotocol peer method"""
-    self.requirecap('_evoext_pushobsmarkers_0',
-                    _('push obsolete markers faster'))
-    ret, output = self._callpush('evoext_pushobsmarkers_0', obsfile)
-    for l in output.splitlines(True):
-        self.ui.status(_('remote: '), l)
-    return ret
-
-@eh.addattr(httppeer.httppeer, 'evoext_pushobsmarkers_0')
-def httpclient_pushobsmarkers(self, obsfile):
-    """httpprotocol peer method
-    (Cannot simply use _callpush as http is doing some special handling)"""
-    self.requirecap('_evoext_pushobsmarkers_0',
-                    _('push obsolete markers faster'))
-    try:
-        r = self._call('evoext_pushobsmarkers_0', data=obsfile)
-        vals = r.split('\n', 1)
-        if len(vals) < 2:
-            raise error.ResponseError(_("unexpected response:"), r)
+class HTTPCompatibleAbort(hgwebcommon.ErrorResponse, error.Abort):
+    def __init__(self, message, code, hint=None):
+        # initialisation of each class is a bit messy.
+        # We explicitly do the dispatch
+        hgwebcommon.ErrorResponse.__init__(self, 410, message)
+        error.Abort.__init__(self, message, hint=hint)
 
-        for l in vals[1].splitlines(True):
-            if l.strip():
-                self.ui.status(_('remote: '), l)
-        return vals[0]
-    except socket.error as err:
-        if err.args[0] in (errno.ECONNRESET, errno.EPIPE):
-            raise error.Abort(_('push failed: %s') % err.args[1])
-        raise error.Abort(err.args[1])
-
-@eh.wrapfunction(localrepo.localrepository, '_restrictcapabilities')
-def local_pushobsmarker_capabilities(orig, repo, caps):
-    caps = orig(repo, caps)
-    caps.add('_evoext_pushobsmarkers_0')
-    return caps
-
-@eh.addattr(localrepo.localpeer, 'evoext_pushobsmarkers_0')
-def local_pushobsmarkers(peer, obsfile):
-    data = obsfile.read()
-    _pushobsmarkers(peer._repo, data)
-
-# compat-code: _pullobsolete
-#
-# the _pullobsolete function is a core function used to exchange
-# obsmarker with repository that does not support bundle2
-
-@eh.wrapfunction(exchange, '_pullobsolete')
-def _pullobsolete(orig, pullop):
-    if not obsolete.isenabled(pullop.repo, obsolete.exchangeopt):
-        return None
-    if 'obsmarkers' in pullop.stepsdone:
-        return None
-    wirepull = pullop.remote.capable('_evoext_pullobsmarkers_0')
-    if 'obsolete' not in pullop.remote.listkeys('namespaces'):
-        return None # remote opted out of obsolescence marker exchange
-    if not wirepull:
-        return orig(pullop)
-    tr = None
-    ui = pullop.repo.ui
-    boundaries = obsdiscovery.buildpullobsmarkersboundaries(pullop, bundle2=False)
-    if 'missing' in boundaries and not boundaries['missing']:
-        obsexcmsg(ui, "nothing to pull\n")
-        return None
-    elif not set(boundaries['heads']) - set(boundaries['common']):
-        obsexcmsg(ui, "nothing to pull\n")
-        return None
-
-    obsexcmsg(ui, "pull obsolescence markers\n", True)
-    new = 0
-
-    msg = ('the remote repository use years old versions of Mercurial and evolve\n'
-           'pulling obsmarker using legacy method\n')
-    ui.warn(msg)
-    ui.warn('(please upgrade your server)\n')
+def forbidpushkey(repo=None, key=None, old=None, new=None):
+    """prevent exchange through pushkey"""
+    err = HTTPCompatibleAbort(abortmsg, 410, hint=hint)
+    raise err
 
-    obsdata = pullop.remote.evoext_pullobsmarkers_0(**boundaries)
-    obsdata = obsdata.read()
-    if len(obsdata) > 5:
-        msg = "merging obsolescence markers (%i bytes)\n" % len(obsdata)
-        obsexcmsg(ui, msg)
-        tr = pullop.gettransaction()
-        old = len(pullop.repo.obsstore._all)
-        pullop.repo.obsstore.mergemarkers(tr, obsdata)
-        new = len(pullop.repo.obsstore._all) - old
-        obsexcmsg(ui, "%i obsolescence markers added\n" % new, True)
-    else:
-        obsexcmsg(ui, "no unknown remote markers\n")
-    obsexcmsg(ui, "DONE\n")
-    if new:
-        pullop.repo.invalidatevolatilesets()
-    return tr
+def forbidlistkey(repo=None, key=None, old=None, new=None):
+    """prevent exchange through pushkey"""
+    if obsolete.isenabled(repo, obsolete.exchangeopt):
+        err = HTTPCompatibleAbort(abortmsg, 410, hint=hint)
+        raise err
+    return {}
 
-@eh.addattr(wireproto.wirepeer, 'evoext_pullobsmarkers_0')
-def client_pullobsmarkers(self, heads=None, common=None):
-    self.requirecap('_evoext_pullobsmarkers_0', _('look up remote obsmarkers'))
-    opts = {}
-    if heads is not None:
-        opts['heads'] = wireproto.encodelist(heads)
-    if common is not None:
-        opts['common'] = wireproto.encodelist(common)
-    f = self._callcompressable("evoext_pullobsmarkers_0", **opts)
-    length = int(f.read(20))
-    chunk = 4096
-    current = 0
-    data = StringIO()
-    ui = self.ui
-    obsexcprg(ui, current, unit=_("bytes"), total=length)
-    while current < length:
-        readsize = min(length - current, chunk)
-        data.write(f.read(readsize))
-        current += readsize
-        obsexcprg(ui, current, unit=_("bytes"), total=length)
-    obsexcprg(ui, None)
-    data.seek(0)
-    return data
-
-@eh.addattr(localrepo.localpeer, 'evoext_pullobsmarkers_0')
-def local_pullobsmarkers(self, heads=None, common=None):
-    return _getobsmarkersstream(self._repo, heads=heads,
-                                common=common)
-
-def _legacypush_capabilities(orig, repo, proto):
-    """wrapper to advertise new capability"""
-    caps = orig(repo, proto)
-    if obsolete.isenabled(repo, obsolete.exchangeopt):
-        caps = caps.split()
-        caps.append('_evoext_pushobsmarkers_0')
-        caps.append('_evoext_pullobsmarkers_0')
-        caps.sort()
-        caps = ' '.join(caps)
-    return caps
-
-@eh.extsetup
-def extsetup(ui):
-    # legacy standalone method
-    hgweb_mod.perms['evoext_pushobsmarkers_0'] = 'push'
-    hgweb_mod.perms['evoext_pullobsmarkers_0'] = 'pull'
-    wireproto.commands['evoext_pushobsmarkers_0'] = (srv_pushobsmarkers, '')
-    wireproto.commands['evoext_pullobsmarkers_0'] = (srv_pullobsmarkers, '*')
-
-    extensions.wrapfunction(wireproto, 'capabilities', _legacypush_capabilities)
-    # wrap command content
-    oldcap, args = wireproto.commands['capabilities']
-
-    def newcap(repo, proto):
-        return _legacypush_capabilities(oldcap, repo, proto)
-    wireproto.commands['capabilities'] = (newcap, args)
+@eh.uisetup
+def setuppushkeyforbidding(ui):
+    pushkey._namespaces['obsolete'] = (forbidpushkey, forbidlistkey)
--- a/hgext3rd/evolve/obshistory.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/obshistory.py	Tue Nov 14 23:04:04 2017 +0100
@@ -19,8 +19,15 @@
     obsolete,
     node as nodemod,
     scmutil,
+    util,
 )
 
+try:
+    from mercurial import obsutil
+    obsutil.marker
+except ImportError:
+    obsutil = None
+
 from mercurial.i18n import _
 
 from . import (
@@ -30,6 +37,18 @@
 
 eh = exthelper.exthelper()
 
+# Config
+efd = {'default': True} # pass a default value unless the config is registered
+
+@eh.extsetup
+def enableeffectflags(ui):
+    item = (getattr(ui, '_knownconfig', {})
+            .get('experimental', {})
+            .get('evolution.effect-flags'))
+    if item is not None:
+        item.default = True
+        efd.clear()
+
 @eh.command(
     'obslog|olog',
     [('G', 'graph', True, _("show the revision DAG")),
@@ -66,6 +85,7 @@
 
     Returns 0 on success.
     """
+    compat.startpager(ui, 'obslog')
     revs = list(revs) + opts['rev']
     if not revs:
         revs = ['.']
@@ -74,11 +94,8 @@
     if opts['graph']:
         return _debugobshistorygraph(ui, repo, revs, opts)
 
-    fm = ui.formatter('debugobshistory', opts)
     revs.reverse()
-    _debugobshistoryrevs(fm, repo, revs, opts)
-
-    fm.end()
+    _debugobshistoryrevs(ui, repo, revs, opts)
 
 class obsmarker_printer(cmdutil.changeset_printer):
     """show (available) information about a node
@@ -92,20 +109,23 @@
 
             changenode = ctx.node()
 
-            fm = self.ui.formatter('debugobshistory', props)
+            _props = self.diffopts.copy()
+            _props.update(props)
+            fm = self.ui.formatter('debugobshistory', _props)
             _debugobshistorydisplaynode(fm, self.repo, changenode)
 
             # Succs markers
             succs = self.repo.obsstore.successors.get(changenode, ())
             succs = sorted(succs)
 
-            markerfm = fm.nested("debugobshistory.markers")
+            markerfm = fm.nested("markers")
             for successor in succs:
                 _debugobshistorydisplaymarker(markerfm, successor,
                                               ctx.node(), self.repo, self.diffopts)
             markerfm.end()
 
             markerfm.plain('\n')
+            fm.end()
             self.hunk[ctx.node()] = self.ui.popbuffer()
         else:
             ### graph output is buffered only
@@ -132,7 +152,7 @@
     succ = successors[0]
 
     if succ not in repo:
-        return False, "succ is unknown locally"
+        return False, "successor is unknown locally"
 
     # Check that both node and succ have the same parents
     nodep1, nodep2 = repo[node].p1(), repo[node].p2()
@@ -301,7 +321,7 @@
     - The dictionnary of each node successors, values are a set
     - The dictionnary of each node precursors, values are a list
     """
-    precursors = repo.obsstore.precursors
+    precursors = repo.obsstore.predecessors
     successors = repo.obsstore.successors
     nodec = repo.changelog.node
 
@@ -355,10 +375,11 @@
     walker = _obshistorywalker(repo.unfiltered(), revs, opts.get('all', False))
     cmdutil.displaygraph(ui, repo, walker, displayer, edges)
 
-def _debugobshistoryrevs(fm, repo, revs, opts):
+def _debugobshistoryrevs(ui, repo, revs, opts):
     """ Display the obsolescence history for revset
     """
-    precursors = repo.obsstore.precursors
+    fm = ui.formatter('debugobshistory', opts)
+    precursors = repo.obsstore.predecessors
     successors = repo.obsstore.successors
     nodec = repo.changelog.node
     unfi = repo.unfiltered()
@@ -373,9 +394,9 @@
 
         succs = successors.get(ctxnode, ())
 
-        markerfm = fm.nested("debugobshistory.markers")
+        markerfm = fm.nested("markers")
         for successor in sorted(succs):
-            _debugobshistorydisplaymarker(markerfm, successor, ctxnode, repo, opts)
+            _debugobshistorydisplaymarker(markerfm, successor, ctxnode, unfi, opts)
         markerfm.end()
 
         precs = precursors.get(ctxnode, ())
@@ -384,6 +405,7 @@
             if p[0] not in seen:
                 seen.add(p[0])
                 nodes.append(p[0])
+    fm.end()
 
 def _debugobshistorydisplaynode(fm, repo, node):
     if node in repo:
@@ -395,22 +417,22 @@
     shortdescription = ctx.description().splitlines()[0]
 
     fm.startitem()
-    fm.write('debugobshistory.node', '%s', str(ctx),
+    fm.write('node', '%s', str(ctx),
              label="evolve.node")
     fm.plain(' ')
 
-    fm.write('debugobshistory.rev', '(%d)', int(ctx),
+    fm.write('rev', '(%d)', int(ctx),
              label="evolve.rev")
     fm.plain(' ')
 
-    fm.write('debugobshistory.shortdescription', '%s', shortdescription,
+    fm.write('shortdescription', '%s', shortdescription,
              label="evolve.short_description")
     fm.plain('\n')
 
 def _debugobshistorydisplaymissingctx(fm, nodewithoutctx):
     hexnode = nodemod.short(nodewithoutctx)
     fm.startitem()
-    fm.write('debugobshistory.node', '%s', hexnode,
+    fm.write('node', '%s', hexnode,
              label="evolve.node evolve.missing_change_ctx")
     fm.plain('\n')
 
@@ -428,7 +450,7 @@
     else:
         verb = 'rewritten'
 
-    fm.write('debugobshistory.verb', '%s', verb,
+    fm.write('verb', '%s', verb,
              label="evolve.verb")
 
     effectflag = metadata.get('ef1')
@@ -457,26 +479,26 @@
             effect.append('content')
 
         if effect:
-            fmteffect = fm.formatlist(effect, 'debugobshistory.effect', sep=', ')
-            fm.write('debugobshistory.effect', '(%s)', fmteffect)
-
-    fm.plain(' by ')
-
-    fm.write('debugobshistory.marker_user', '%s', metadata['user'],
-             label="evolve.user")
-    fm.plain(' ')
-
-    fm.write('debugobshistory.marker_date', '(%s)', fm.formatdate(date),
-             label="evolve.date")
+            fmteffect = fm.formatlist(effect, 'effect', sep=', ')
+            fm.write('effect', '(%s)', fmteffect)
 
     if len(succnodes) > 0:
         fm.plain(' as ')
 
         shortsnodes = (nodemod.short(succnode) for succnode in sorted(succnodes))
-        nodes = fm.formatlist(shortsnodes, 'debugobshistory.succnodes', sep=', ')
-        fm.write('debugobshistory.succnodes', '%s', nodes,
+        nodes = fm.formatlist(shortsnodes, 'succnodes', sep=', ')
+        fm.write('succnodes', '%s', nodes,
                  label="evolve.node")
 
+    fm.plain(' by ')
+
+    fm.write('user', '%s', metadata['user'],
+             label="evolve.user")
+    fm.plain(' ')
+
+    fm.write('date', '(%s)', fm.formatdate(date),
+             label="evolve.date")
+
     # Patch display
     if opts.get('patch'):
         _patchavailable = patchavailable(node, repo, marker)
@@ -496,7 +518,7 @@
                 fm.plain("\n")
                 fm.plain(contentpatch)
         else:
-            patch = "    (No patch available yet, %s)" % _patchavailable[1]
+            patch = "    (No patch available, %s)" % _patchavailable[1]
             fm.plain("\n")
             # TODO: should be in json too
             fm.plain(patch)
@@ -614,46 +636,48 @@
             return False
     return True
 
-@eh.wrapfunction(obsolete, 'createmarkers')
-def createmarkerswithbits(orig, repo, relations, flag=0, date=None,
-                          metadata=None, **kwargs):
-    """compute 'effect-flag' and augment the created markers
+# Wrap pre Mercurial 4.4 createmarkers that didn't included effect-flag
+if not util.safehasattr(obsutil, 'geteffectflag'):
+    @eh.wrapfunction(obsolete, 'createmarkers')
+    def createmarkerswithbits(orig, repo, relations, flag=0, date=None,
+                              metadata=None, **kwargs):
+        """compute 'effect-flag' and augment the created markers
 
-    Wrap obsolete.createmarker in order to compute the effect of each
-    relationship and store them as flag in the metadata.
+        Wrap obsolete.createmarker in order to compute the effect of each
+        relationship and store them as flag in the metadata.
 
-    While we experiment, we store flag in a metadata field. This field is
-    "versionned" to easilly allow moving to other meaning for flags.
+        While we experiment, we store flag in a metadata field. This field is
+        "versionned" to easilly allow moving to other meaning for flags.
 
-    The comparison of description or other infos just before creating the obs
-    marker might induce overhead in some cases. However it is a good place to
-    start since it automatically makes all markers creation recording more
-    meaningful data. In the future, we can introduce way for commands to
-    provide precomputed effect to avoid the overhead.
-    """
-    if not repo.ui.configbool('experimental', 'evolution.effect-flags', True):
-        return orig(repo, relations, flag, date, metadata, **kwargs)
-    if metadata is None:
-        metadata = {}
-    tr = repo.transaction('add-obsolescence-marker')
-    try:
-        for r in relations:
-            # Compute the effect flag for each obsmarker
-            effect = geteffectflag(r)
+        The comparison of description or other infos just before creating the obs
+        marker might induce overhead in some cases. However it is a good place to
+        start since it automatically makes all markers creation recording more
+        meaningful data. In the future, we can introduce way for commands to
+        provide precomputed effect to avoid the overhead.
+        """
+        if not repo.ui.configbool('experimental', 'evolution.effect-flags', **efd):
+            return orig(repo, relations, flag, date, metadata, **kwargs)
+        if metadata is None:
+            metadata = {}
+        tr = repo.transaction('add-obsolescence-marker')
+        try:
+            for r in relations:
+                # Compute the effect flag for each obsmarker
+                effect = geteffectflag(r)
 
-            # Copy the metadata in order to add them, we copy because the
-            # effect flag might be different per relation
-            m = metadata.copy()
-            # we store the effect even if "0". This disctinct markers created
-            # without the feature with markers recording a no-op.
-            m['ef1'] = "%d" % effect
+                # Copy the metadata in order to add them, we copy because the
+                # effect flag might be different per relation
+                m = metadata.copy()
+                # we store the effect even if "0". This disctinct markers created
+                # without the feature with markers recording a no-op.
+                m['ef1'] = "%d" % effect
 
-            # And call obsolete.createmarkers for creating the obsmarker for real
-            orig(repo, [r], flag, date, m, **kwargs)
+                # And call obsolete.createmarkers for creating the obsmarker for real
+                orig(repo, [r], flag, date, m, **kwargs)
 
-        tr.close()
-    finally:
-        tr.release()
+            tr.close()
+        finally:
+            tr.release()
 
 def _getobsfate(successorssets):
     """ Compute a changeset obsolescence fate based on his successorssets.
@@ -726,17 +750,71 @@
 
     return {'users': sorted(users)}
 
+VERBMAPPING = {
+    DESCCHANGED: "reworded",
+    METACHANGED: "meta-changed",
+    USERCHANGED: "reauthored",
+    DATECHANGED: "date-changed",
+    BRANCHCHANGED: "branch-changed",
+    PARENTCHANGED: "rebased",
+    DIFFCHANGED: "amended"
+}
+
 def _successorsetverb(successorset, markers):
     """ Return the verb summarizing the successorset
     """
+    verb = None
     if not successorset:
         verb = 'pruned'
     elif len(successorset) == 1:
-        verb = 'rewritten'
+        # Check for effect flag
+
+        metadata = [dict(marker[3]) for marker in markers]
+        ef1 = [data.get('ef1') for data in metadata]
+
+        if all(ef1):
+            combined = 0
+            for ef in ef1:
+                combined |= int(ef)
+
+            # Combined will be in VERBMAPPING only of one bit is set
+            if combined in VERBMAPPING:
+                verb = VERBMAPPING[combined]
+
+        if verb is None:
+            verb = 'rewritten'
     else:
         verb = 'split'
     return {'verb': verb}
 
+# Hijack callers of successorsetverb
+if util.safehasattr(obsutil, 'obsfateprinter'):
+
+    @eh.wrapfunction(obsutil, 'obsfateprinter')
+    def obsfateprinter(orig, successors, markers, ui):
+
+        def closure(successors):
+            return _successorsetverb(successors, markers)['verb']
+
+        if not util.safehasattr(obsutil, 'successorsetverb'):
+            return orig(successors, markers, ui)
+
+        # Save the old value
+        old = obsutil.successorsetverb
+
+        try:
+            # Replace by own
+            obsutil.successorsetverb = closure
+
+            # Call the orig
+            result = orig(successors, markers, ui)
+
+            # And return result
+            return result
+        finally:
+            # Replace the old one
+            obsutil.successorsetverb = old
+
 FORMATSSETSFUNCTIONS = [
     _successorsetdates,
     _successorsetusers,
--- a/hgext3rd/evolve/rewriteutil.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/rewriteutil.py	Tue Nov 14 23:04:04 2017 +0100
@@ -24,7 +24,6 @@
     phases,
     repair,
     revset,
-    util,
 )
 
 from mercurial.i18n import _
@@ -47,10 +46,7 @@
         shorts = [node.short(tonode(r)) for r in revs]
         summary = ', '.join(shorts)
     else:
-        if util.safehasattr(revs, 'first'):
-            first = revs.first()
-        else:
-            first = revs[0]
+        first = revs.first()
         summary = _('%s and %d others')
         summary %= (node.short(tonode(first)), numrevs - 1)
     return summary
--- a/hgext3rd/evolve/safeguard.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/safeguard.py	Tue Nov 14 23:04:04 2017 +0100
@@ -16,6 +16,8 @@
 
 eh = exthelper.exthelper()
 
+eh.configitem('experimental', 'auto-publish')
+
 @eh.reposetup
 def setuppublishprevention(ui, repo):
 
--- a/hgext3rd/evolve/serveronly.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/serveronly.py	Tue Nov 14 23:04:04 2017 +0100
@@ -13,6 +13,8 @@
 import sys
 import os
 
+from mercurial import obsolete
+
 try:
     from . import (
         compat,
@@ -47,6 +49,7 @@
 extsetup = eh.final_extsetup
 reposetup = eh.final_reposetup
 cmdtable = eh.cmdtable
+configtable = eh.configtable
 
 @eh.reposetup
 def default2evolution(ui, repo):
@@ -54,3 +57,5 @@
     if not evolveopts:
         evolveopts = 'all'
         ui.setconfig('experimental', 'evolution', evolveopts)
+    if obsolete.isenabled(repo, 'exchange'):
+        repo.ui.setconfig('server', 'bundle1', False)
--- a/hgext3rd/evolve/stablerange.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/stablerange.py	Tue Nov 14 23:04:04 2017 +0100
@@ -395,13 +395,7 @@
             # data about the merge. But I'm not sure this function will be even
             # call for the general case.
 
-            # Lrudict.get in hg-3.9 returns the lrunode instead of the
-            # value, use __getitem__ instead and catch the exception directly
-            try:
-                allrevs = self._stablesortcache[headrev]
-            except KeyError:
-                allrevs = None
-
+            allrevs = self._stablesortcache.get(headrev)
             if allrevs is None:
                 allrevs = self._getrevsfrommerge(repo, headrev)
                 if allrevs is None:
@@ -450,11 +444,8 @@
             self._stablesortprepared[merge] = (sortedrevs, len(sortedrevs))
 
     def _getrevsfrommerge(self, repo, merge):
-        # Lrudict.get in hg-3.9 returns the lrunode instead of the
-        # value, use __getitem__ instead and catch the exception directly
-        try:
-            prepared = self._stablesortprepared[merge]
-        except KeyError:
+        prepared = self._stablesortprepared.get(merge)
+        if prepared is None:
             return None
 
         mergedepth = self.depthrev(repo, merge)
--- a/hgext3rd/evolve/templatekw.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/evolve/templatekw.py	Tue Nov 14 23:04:04 2017 +0100
@@ -28,7 +28,7 @@
 
 @eh.templatekw('obsolete')
 def obsoletekw(repo, ctx, templ, **args):
-    """:obsolete: String. Whether the changeset is ``obsolete``.
+    """String. Whether the changeset is ``obsolete``.
     """
     if ctx.obsolete():
         return 'obsolete'
@@ -36,80 +36,89 @@
 
 @eh.templatekw('troubles')
 def showtroubles(**args):
-    """:troubles: List of strings. Evolution troubles affecting the changeset
+    """List of strings. Evolution troubles affecting the changeset
     (zero or more of "unstable", "divergent" or "bumped")."""
     ctx = args['ctx']
     try:
         # specify plural= explicitly to trigger TypeError on hg < 4.2
-        return templatekw.showlist('trouble', ctx.troubles(), args,
+        return templatekw.showlist('trouble', ctx.instabilities(), args,
                                    plural='troubles')
     except TypeError:
-        return templatekw.showlist('trouble', ctx.troubles(), plural='troubles',
+        return templatekw.showlist('trouble', ctx.instabilities(), plural='troubles',
                                    **args)
 
-def closestprecursors(repo, nodeid):
-    """ Yield the list of next precursors pointing on visible changectx nodes
-    """
-
-    precursors = repo.obsstore.precursors
-    stack = [nodeid]
+if util.safehasattr(templatekw, 'showpredecessors'):
+    eh.templatekw("precursors")(templatekw.showpredecessors)
+else:
+    # for version <= hg4.3
+    def closestprecursors(repo, nodeid):
+        """ Yield the list of next precursors pointing on visible changectx nodes
+        """
 
-    while stack:
-        current = stack.pop()
-        currentpreccs = precursors.get(current, ())
+        precursors = repo.obsstore.predecessors
+        stack = [nodeid]
 
-        for prec in currentpreccs:
-            precnodeid = prec[0]
+        while stack:
+            current = stack.pop()
+            currentpreccs = precursors.get(current, ())
+
+            for prec in currentpreccs:
+                precnodeid = prec[0]
 
-            if precnodeid in repo:
-                yield precnodeid
-            else:
-                stack.append(precnodeid)
+                if precnodeid in repo:
+                    yield precnodeid
+                else:
+                    stack.append(precnodeid)
 
-@eh.templatekw("precursors")
-def shownextvisibleprecursors(repo, ctx, **args):
-    """Returns a string containing the list of the closest precursors
-    """
-    precursors = sorted(closestprecursors(repo, ctx.node()))
-    precursors = [node.hex(p) for p in precursors]
+    @eh.templatekw("precursors")
+    def shownextvisibleprecursors(repo, ctx, **args):
+        """Returns a string containing the list of the closest precursors
+        """
+        precursors = sorted(closestprecursors(repo, ctx.node()))
+        precursors = [node.hex(p) for p in precursors]
 
-    # <= hg-4.1 requires an explicite gen.
-    # we can use None once the support is dropped
-    #
-    # They also requires an iterator instead of an iterable.
-    gen = iter(" ".join(p[:12] for p in precursors))
-    return templatekw._hybrid(gen.__iter__(), precursors, lambda x: {'precursor': x},
-                              lambda d: d['precursor'][:12])
+        # <= hg-4.1 requires an explicite gen.
+        # we can use None once the support is dropped
+        #
+        # They also requires an iterator instead of an iterable.
+        gen = iter(" ".join(p[:12] for p in precursors))
+        return templatekw._hybrid(gen.__iter__(), precursors, lambda x: {'precursor': x},
+                                  lambda d: d['precursor'][:12])
 
 def closestsuccessors(repo, nodeid):
     """ returns the closest visible successors sets instead.
     """
     return directsuccessorssets(repo, nodeid)
 
-@eh.templatekw("successors")
-def shownextvisiblesuccessors(repo, ctx, templ, **args):
-    """Returns a string of sets of successors for a changectx
+if util.safehasattr(templatekw, 'showsuccessorssets'):
+    eh.templatekw("successors")(templatekw.showsuccessorssets)
+else:
+    # for version <= hg4.3
 
-    Format used is: [ctx1, ctx2], [ctx3] if ctx has been splitted into ctx1 and
-    ctx2 while also diverged into ctx3"""
-    if not ctx.obsolete():
-        return ''
+    @eh.templatekw("successors")
+    def shownextvisiblesuccessors(repo, ctx, templ, **args):
+        """Returns a string of sets of successors for a changectx
 
-    ssets, _ = closestsuccessors(repo, ctx.node())
-    ssets = [[node.hex(n) for n in ss] for ss in ssets]
+        Format used is: [ctx1, ctx2], [ctx3] if ctx has been splitted into ctx1 and
+        ctx2 while also diverged into ctx3"""
+        if not ctx.obsolete():
+            return ''
 
-    data = []
-    gen = []
-    for ss in ssets:
-        subgen = '[%s]' % ', '.join(n[:12] for n in ss)
-        gen.append(subgen)
-        h = templatekw._hybrid(iter(subgen), ss, lambda x: {'successor': x},
-                               lambda d: "%s" % d["successor"])
-        data.append(h)
+        ssets, _ = closestsuccessors(repo, ctx.node())
+        ssets = [[node.hex(n) for n in ss] for ss in ssets]
 
-    gen = ', '.join(gen)
-    return templatekw._hybrid(iter(gen), data, lambda x: {'successorset': x},
-                              lambda d: d["successorset"])
+        data = []
+        gen = []
+        for ss in ssets:
+            subgen = '[%s]' % ', '.join(n[:12] for n in ss)
+            gen.append(subgen)
+            h = templatekw._hybrid(iter(subgen), ss, lambda x: {'successor': x},
+                                   lambda d: "%s" % d["successor"])
+            data.append(h)
+
+        gen = ', '.join(gen)
+        return templatekw._hybrid(iter(gen), data, lambda x: {'successorset': x},
+                                  lambda d: d["successorset"])
 
 def _getusername(ui):
     """the default username in the config or None"""
@@ -138,8 +147,8 @@
     # Assemble them
     return {
         'obsfate_quiet': verbtempl + succtempl,
-        'obsfate': verbtempl + optionalusertempl + succtempl,
-        'obsfate_verbose': verbtempl + usertempl + succtempl + datetempl,
+        'obsfate': verbtempl + succtempl + optionalusertempl,
+        'obsfate_verbose': verbtempl + succtempl + usertempl + datetempl,
     }
 
 def obsfatedata(repo, ctx):
@@ -191,17 +200,6 @@
     # Verb
     line.append(obsfateline['verb'])
 
-    # Users
-    if (verbose or normal) and 'users' in obsfateline:
-        users = obsfateline['users']
-
-        if normal:
-            username = _getusername(ui)
-            users = [user for user in users if user != username]
-
-        if users:
-            line.append(" by %s" % ",".join(users))
-
     # Successors
     successors = obsfateline["successors"]
 
@@ -209,6 +207,20 @@
         fmtsuccessors = map(lambda s: s[:12], successors)
         line.append(" as %s" % ", ".join(fmtsuccessors))
 
+    # Users
+    if (verbose or normal) and 'users' in obsfateline:
+        users = obsfateline['users']
+
+        if not verbose:
+            # If current user is the only user, do not show anything if not in
+            # verbose mode
+            username = _getusername(ui)
+            if len(users) == 1 and users[0] == username:
+                users = None
+
+        if users:
+            line.append(" by %s" % ", ".join(users))
+
     # Date
     if verbose:
         min_date = obsfateline['min_date']
@@ -234,13 +246,13 @@
 
     return "\n".join(lines)
 
-@eh.templatekw("obsfate")
-def showobsfate(repo, ctx, **args):
+@eh.templatekw("obsfatedata")
+def showobsfatedata(repo, ctx, **args):
     # Get the needed obsfate data
     values = obsfatedata(repo, ctx)
 
     if values is None:
-        return ''
+        return templatekw.showlist("obsfatedata", [], args)
 
     # Format each successorset successors list
     for raw in values:
@@ -291,8 +303,16 @@
 
     return templatekw._hybrid(gen, values, lambda x: {name: x}, fmt)
 
-# Check if we can hook directly on the changeset_printer
-if util.safehasattr(cmdutil.changeset_printer, '_exthook'):
+# rely on core mercurial starting from 4.4 for the obsfate template
+if not util.safehasattr(templatekw, 'showobsfate'):
+
+    @eh.templatekw("obsfate")
+    def showobsfate(*args, **kwargs):
+        return showobsfatedata(*args, **kwargs)
+
+if util.safehasattr(cmdutil.changeset_printer, '_showobsfate'):
+    pass # already included by default
+elif util.safehasattr(cmdutil.changeset_printer, '_exthook'):
     @eh.wrapfunction(cmdutil.changeset_printer, '_exthook')
     def exthook(original, self, ctx):
         # Call potential other extensions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext3rd/topic/README	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,53 @@
+Topic Extension
+================
+
+This packages also provides the ``topic`` experiment in an independent
+extension. It implements a new experimental concept to provide lightweight
+feature branches for the mutable parts of the history. The experiments is still
+at an early stage and have significant usability and performance issues when
+enabled.
+
+How to Install
+==============
+
+The ``topic`` extension is included into the ``evolve` package, so the same instruction apply.
+
+Using Pip
+---------
+
+You can install the latest version using pip::
+
+    $ pip install --user hg-evolve
+
+Then just enable it in you hgrc::
+
+    $ hg config --edit # adds the two line below:
+    [extensions]
+    topic =
+
+From Source
+-----------
+
+To install a local version from source::
+
+    $ hg clone https://www.mercurial-scm.org/repo/evolve/
+    $ cd evolve
+    $ make install-home
+
+Enable
+------
+
+The topic extensions is included in the evolve package. See the install instruction for evolve.
+
+Then enable it in you configuration::
+
+    $ hg config --edit # adds the two line below:
+    [extensions]
+    topic =
+
+Documentation
+-------------
+
+* See 'hg help -e topic' for a generic help.
+* See 'hg help topics' and 'hg help stack' for help on specific commands.
+* See the 'tests/test-topic-tutorial.t' file for a quick tutorial.
--- a/hgext3rd/topic/__init__.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/topic/__init__.py	Tue Nov 14 23:04:04 2017 +0100
@@ -48,15 +48,68 @@
 
 Be aware that this extension is still an experiment, commands and other features
 are likely to be change/adjusted/dropped over time as we refine the concept.
+
+topic-mode
+==========
+
+The topic extension can be configured to ensure the user do not forget to add
+a topic when committing a new topic::
+
+    [experimental]
+    # behavior when commit is made without an active topic
+    topic-mode = ignore # do nothing special (default)
+    topic-mode = warning # print a warning
+    topic-mode = enforce # abort the commit (except for merge)
+    topic-mode = enforce-all # abort the commit (even for merge)
+    topic-mode = random # use a randomized generated topic (except for merge)
+    topic-mode = random-all # use a randomized generated topic (even for merge)
+
+Single head enforcing
+=====================
+
+The extensions come with an option to enforce that there is only one heads for
+each name in the repository at any time.
+
+    [experimental]
+    enforce-single-head = yes
+
+Publishing behavior
+===================
+
+Topic vanish when changeset move to the public phases. Moving to the public
+phase usually happens on push, but it is possible ot update that behavior. The
+server needs to have specific config for this.
+
+    # everything pushed become public (the default)
+    [phase]
+    publish = yes
+
+    # nothing push turned public
+    [phase]
+    publish = no
+
+    # topic branches are not published, changeset without topic are
+    [phase]
+    publish = no
+    [experimental]
+    topic.publish-bare-branch = yes
+
+In addition, the topic extension adds a ``--publish`` flag on :hg:`push`. When
+used, the pushed revisions are published if the push succeeds. It also applies
+to common revisions selected by the push.
 """
 
 from __future__ import absolute_import
 
+import functools
 import re
 import time
+import weakref
 
 from mercurial.i18n import _
 from mercurial import (
+    bookmarks,
+    changelog,
     cmdutil,
     commands,
     context,
@@ -64,26 +117,29 @@
     extensions,
     hg,
     localrepo,
-    lock,
+    lock as lockmod,
     merge,
     namespaces,
     node,
     obsolete,
-    obsutil,
     patch,
     phases,
     registrar,
+    scmutil,
     templatefilters,
     util,
 )
 
 from . import (
+    compat,
     constants,
+    flow,
     revset as topicrevset,
     destination,
     stack,
     topicmap,
     discovery,
+    randomname
 )
 
 if util.safehasattr(registrar, 'command'):
@@ -118,11 +174,50 @@
               'topic.active': 'green',
              }
 
-version = '0.2.0.dev'
-testedwith = '4.0.2 4.1.3 4.2.1'
-minimumhgversion = '4.0'
+__version__ = '0.5.1.dev'
+
+testedwith = '4.1.3 4.2.3 4.3.3 4.4'
+minimumhgversion = '4.1'
 buglink = 'https://bz.mercurial-scm.org/'
 
+if util.safehasattr(registrar, 'configitem'):
+    configtable = {}
+    configitem = registrar.configitem(configtable)
+
+    configitem('experimental', 'enforce-topic',
+               default=False,
+    )
+    configitem('experimental', 'enforce-single-head',
+               default=False,
+    )
+    configitem('experimental', 'topic-mode',
+               default=None,
+    )
+    configitem('experimental', 'topic.publish-bare-branch',
+               default=False,
+    )
+    configitem('_internal', 'keep-topic',
+               default=False,
+    )
+
+    def extsetup(ui):
+        # register config that strickly belong to other code (thg, core, etc)
+        #
+        # To ensure all config items we used are registerd, we register them if
+        # nobody else did so far.
+        from mercurial import configitems
+        extraitem = functools.partial(configitems._register, ui._knownconfig)
+        if ('experimental' not in ui._knownconfig
+                or not ui._knownconfig['experimental'].get('thg.displaynames')):
+            extraitem('experimental', 'thg.displaynames',
+                      default=None,
+            )
+        if ('devel' not in ui._knownconfig
+                or not ui._knownconfig['devel'].get('random')):
+            extraitem('devel', 'randomseed',
+                      default=None,
+            )
+
 def _contexttopic(self, force=False):
     if not (force or self.mutable()):
         return ''
@@ -134,7 +229,7 @@
         # XXX we might want to include t0 here,
         # however t0 is related to  'currenttopic' which has no place here.
         return None
-    revlist = stack.getstack(self._repo, topic=topic)
+    revlist = stack.stack(self._repo, topic=topic)
     try:
         return revlist.index(self.rev())
     except IndexError:
@@ -153,12 +248,12 @@
         tname = topic = repo.currenttopic
         if not tname:
             raise error.Abort(_('cannot resolve "%s": no active topic') % name)
-        revs = list(stack.getstack(repo, topic=topic))
+        revs = list(stack.stack(repo, topic=topic))
     elif branchrev.match(name):
         ttype = 'branch'
         idx = int(name[1:])
         tname = branch = repo[None].branch()
-        revs = list(stack.getstack(repo, branch=branch))
+        revs = list(stack.stack(repo, branch=branch))
 
     if revs is not None:
         try:
@@ -185,17 +280,27 @@
 
 def uisetup(ui):
     destination.modsetup(ui)
-    topicrevset.modsetup(ui)
     discovery.modsetup(ui)
     topicmap.modsetup(ui)
     setupimportexport(ui)
 
     extensions.afterloaded('rebase', _fixrebase)
 
+    flow.installpushflag(ui)
+
     entry = extensions.wrapcommand(commands.table, 'commit', commitwrap)
     entry[1].append(('t', 'topic', '',
                      _("use specified topic"), _('TOPIC')))
 
+    entry = extensions.wrapcommand(commands.table, 'push', pushoutgoingwrap)
+    entry[1].append(('t', 'topic', '',
+                     _("topic to push"), _('TOPIC')))
+
+    entry = extensions.wrapcommand(commands.table, 'outgoing',
+                                   pushoutgoingwrap)
+    entry[1].append(('t', 'topic', '',
+                     _("topic to push"), _('TOPIC')))
+
     extensions.wrapfunction(cmdutil, 'buildcommittext', committextwrap)
     extensions.wrapfunction(merge, 'update', mergeupdatewrap)
     # We need to check whether t0 or b0 is passed to override the default update
@@ -220,7 +325,7 @@
 
     repo = repo.unfiltered()
 
-    if repo.ui.config('experimental', 'thg.displaynames', None) is None:
+    if repo.ui.config('experimental', 'thg.displaynames') is None:
         repo.ui.setconfig('experimental', 'thg.displaynames', 'topics',
                           source='topic-extension')
 
@@ -300,43 +405,165 @@
                 peer.__class__ = topicpeer
             return peer
 
+        def transaction(self, desc, *a, **k):
+            ctr = self.currenttransaction()
+            tr = super(topicrepo, self).transaction(desc, *a, **k)
+            if desc in ('strip', 'repair') or ctr is not None:
+                return tr
+
+            reporef = weakref.ref(self)
+            if repo.ui.configbool('experimental', 'enforce-single-head'):
+                origvalidator = tr.validator
+
+                def validator(tr2):
+                    repo = reporef()
+                    flow.enforcesinglehead(repo, tr2)
+                    origvalidator(tr2)
+                tr.validator = validator
+
+            if (repo.ui.configbool('experimental', 'topic.publish-bare-branch')
+                    and (desc.startswith('push')
+                         or desc.startswith('serve'))
+                    ):
+                origclose = tr.close
+                trref = weakref.ref(tr)
+
+                def close():
+                    repo = reporef()
+                    tr2 = trref()
+                    flow.publishbarebranch(repo, tr2)
+                    origclose()
+                tr.close = close
+
+            # real transaction start
+            ct = self.currenttopic
+            if not ct:
+                return tr
+            ctwasempty = stack.stack(self, topic=ct).changesetcount == 0
+
+            reporef = weakref.ref(self)
+
+            def currenttopicempty(tr):
+                # check active topic emptyness
+                repo = reporef()
+                csetcount = stack.stack(repo, topic=ct).changesetcount
+                empty = csetcount == 0
+                if empty and not ctwasempty:
+                    ui.status('active topic %r is now empty\n' % ct)
+                if ctwasempty and not empty:
+                    if csetcount == 1:
+                        msg = _('active topic %r grew its first changeset\n')
+                        ui.status(msg % ct)
+                    else:
+                        msg = _('active topic %r grew its %s first changesets\n')
+                        ui.status(msg % (ct, csetcount))
+
+            tr.addpostclose('signalcurrenttopicempty', currenttopicempty)
+            return tr
+
     repo.__class__ = topicrepo
     repo._topics = None
     if util.safehasattr(repo, 'names'):
         repo.names.addnamespace(namespaces.namespace(
             'topics', 'topic', namemap=_namemap, nodemap=_nodemap,
             listnames=lambda repo: repo.topics))
+    # Wrap workingctx extra to return the topic name
+    extensions.wrapfunction(context.workingctx, '__init__', wrapinit)
+    # Wrap changelog.add to drop empty topic
+    extensions.wrapfunction(changelog.changelog, 'add', wrapadd)
 
-@command('topics [TOPIC]', [
+def wrapinit(orig, self, repo, *args, **kwargs):
+    orig(self, repo, *args, **kwargs)
+    if repo.currenttopic:
+        self._extra[constants.extrakey] = repo.currenttopic
+    else:
+        # Empty key will be dropped from extra by another hack at the changegroup level
+        self._extra[constants.extrakey] = ''
+
+def wrapadd(orig, cl, manifest, files, desc, transaction, p1, p2, user,
+            date=None, extra=None):
+    if constants.extrakey in extra and not extra[constants.extrakey]:
+        extra = extra.copy()
+        del extra[constants.extrakey]
+    return orig(cl, manifest, files, desc, transaction, p1, p2, user,
+                date=date, extra=extra)
+
+# revset predicates are automatically registered at loading via this symbol
+revsetpredicate = topicrevset.revsetpredicate
+
+@command('topics', [
         ('', 'clear', False, 'clear active topic if any'),
-        ('r', 'rev', '', 'revset of existing revisions', _('REV')),
+        ('r', 'rev', [], 'revset of existing revisions', _('REV')),
         ('l', 'list', False, 'show the stack of changeset in the topic'),
-        ('', 'age', False, 'show when you last touched the topics')
-    ] + commands.formatteropts)
-def topics(ui, repo, topic='', clear=False, rev=None, list=False, **opts):
+        ('', 'age', False, 'show when you last touched the topics'),
+        ('', 'current', None, 'display the current topic only'),
+    ] + commands.formatteropts,
+    _('hg topics [TOPIC]'))
+def topics(ui, repo, topic=None, **opts):
     """View current topic, set current topic, change topic for a set of revisions, or see all topics.
 
-    Clear topic on existing topiced revisions:
-        `hg topic --rev <related revset> --clear`
+    Clear topic on existing topiced revisions::
+
+      hg topics --rev <related revset> --clear
+
+    Change topic on some revisions::
 
-    Change topic on some revisions:
-        `hg topic <newtopicname> --rev <related revset>`
+      hg topics <newtopicname> --rev <related revset>
 
-    Clear current topic:
-        `hg topic --clear`
+    Clear current topic::
+
+      hg topics --clear
 
-    Set current topic:
-        `hg topic <topicname>`
+    Set current topic::
+
+      hg topics <topicname>
+
+    List of topics::
 
-    List of topics:
-        `hg topics`
+      hg topics
 
-    List of topics with their last touched time sorted according to it:
-        `hg topic --age`
+    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
 
     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 --verbose version of this command display various information on the state of each topic."""
+
+    clear = opts.get('clear')
+    list = opts.get('list')
+    rev = opts.get('rev')
+    current = opts.get('current')
+    age = opts.get('age')
+
+    if current and topic:
+        raise error.Abort(_("cannot use --current when setting a topic"))
+    if current and clear:
+        raise error.Abort(_("cannot use --current and --clear"))
+    if clear and topic:
+        raise error.Abort(_("cannot use --clear when setting a topic"))
+    if age and topic:
+        raise error.Abort(_("cannot use --age while setting a topic"))
+
+    touchedrevs = set()
+    if rev:
+        touchedrevs = scmutil.revrange(repo, rev)
+
+    if topic:
+        topic = topic.strip()
+        if not topic:
+            raise error.Abort(_("topic name cannot consist entirely of whitespaces"))
+        # Have some restrictions on the topic name just like bookmark name
+        scmutil.checknewlabel(repo, topic, 'topic')
+
+    compat.startpager(ui, 'topics')
+
     if list:
         if clear or rev:
             raise error.Abort(_("cannot use --clear or --rev with --list"))
@@ -346,26 +573,62 @@
             raise error.Abort(_('no active topic to list'))
         return stack.showstack(ui, repo, topic=topic, opts=opts)
 
-    if rev:
+    if touchedrevs:
         if not obsolete.isenabled(repo, obsolete.createmarkersopt):
             raise error.Abort(_('must have obsolete enabled to change topics'))
         if clear:
             topic = None
+        elif opts.get('current'):
+            topic = repo.currenttopic
         elif not topic:
             raise error.Abort('changing topic requires a topic name or --clear')
-        if any(not c.mutable() for c in repo.set('%r and public()', rev)):
+        if repo.revs('%ld and public()', touchedrevs):
             raise error.Abort("can't change topic of a public change")
-        return _changetopics(ui, repo, rev, topic)
+        wl = lock = txn = None
+        try:
+            wl = repo.wlock()
+            lock = repo.lock()
+            txn = repo.transaction('rewrite-topics')
+            rewrote = _changetopics(ui, repo, touchedrevs, topic)
+            txn.close()
+            ui.status('changed topic on %d changes\n' % rewrote)
+        finally:
+            lockmod.release(txn, lock, wl)
+            repo.invalidate()
+        return
 
+    ct = repo.currenttopic
     if clear:
+        empty = stack.stack(repo, topic=ct).changesetcount == 0
+        if empty:
+            if ct:
+                ui.status(_('clearing empty topic "%s"\n') % ct)
         return _changecurrenttopic(repo, None)
 
     if topic:
+        if not ct:
+            ui.status(_('marked working directory as topic: %s\n') % topic)
         return _changecurrenttopic(repo, topic)
 
-    _listtopics(ui, repo, opts)
+    # `hg topic --current`
+    ret = 0
+    if current and not ct:
+        ui.write_err(_('no active topic\n'))
+        ret = 1
+    elif current:
+        fm = ui.formatter('topic', opts)
+        namemask = '%s\n'
+        label = 'topic.active'
+        fm.startitem()
+        fm.write('topic', namemask, ct, label=label)
+        fm.end()
+    else:
+        _listtopics(ui, repo, opts)
+    return ret
 
-@command('stack [TOPIC]', [] + commands.formatteropts)
+@command('stack', [
+    ] + commands.formatteropts,
+    _('hg stack [TOPIC]'))
 def cmdstack(ui, repo, topic='', **opts):
     """list all changesets in a topic and other information
 
@@ -380,8 +643,131 @@
         topic = repo.currenttopic
     if topic is None:
         branch = repo[None].branch()
+    compat.startpager(ui, 'stack')
     return stack.showstack(ui, repo, branch=branch, topic=topic, opts=opts)
 
+@command('debugcb|debugconvertbookmark', [
+        ('b', 'bookmark', '', _('bookmark to convert to topic')),
+        ('', 'all', None, _('convert all bookmarks to topics')),
+    ],
+    _('[-b BOOKMARK] [--all]'))
+def debugconvertbookmark(ui, repo, **opts):
+    """Converts a bookmark to a topic with the same name.
+    """
+
+    bookmark = opts.get('bookmark')
+    convertall = opts.get('all')
+
+    if convertall and bookmark:
+        raise error.Abort(_("cannot use '--all' and '-b' together"))
+    if not (convertall or bookmark):
+        raise error.Abort(_("you must specify either '--all' or '-b'"))
+
+    bmstore = repo._bookmarks
+
+    nodetobook = {}
+    for book, revnode in bmstore.iteritems():
+        if nodetobook.get(revnode):
+            nodetobook[revnode].append(book)
+        else:
+            nodetobook[revnode] = [book]
+
+    # a list of nodes which we have skipped so that we don't print the skip
+    # warning repeatedly
+    skipped = []
+
+    actions = {}
+
+    lock = wlock = tr = None
+    try:
+        wlock = repo.wlock()
+        lock = repo.lock()
+        if bookmark:
+            try:
+                node = bmstore[bookmark]
+            except KeyError:
+                raise error.Abort(_("no such bookmark exists: '%s'") % bookmark)
+
+            revnum = repo[node].rev()
+            if len(nodetobook[node]) > 1:
+                ui.status(_("skipping revision '%d' as it has multiple bookmarks "
+                          "on it\n") % revnum)
+                return
+            targetrevs = _findconvertbmarktopic(repo, bookmark)
+            if targetrevs:
+                actions[(bookmark, revnum)] = targetrevs
+
+        elif convertall:
+            for bmark, revnode in sorted(bmstore.iteritems()):
+                revnum = repo[revnode].rev()
+                if revnum in skipped:
+                    continue
+                if len(nodetobook[revnode]) > 1:
+                    ui.status(_("skipping '%d' as it has multiple bookmarks on"
+                              " it\n") % revnum)
+                    skipped.append(revnum)
+                    continue
+                if bmark == '@':
+                    continue
+                targetrevs = _findconvertbmarktopic(repo, bmark)
+                if targetrevs:
+                    actions[(bmark, revnum)] = targetrevs
+
+        if actions:
+            try:
+                tr = repo.transaction('debugconvertbookmark')
+                for ((bmark, revnum), targetrevs) in sorted(actions.iteritems()):
+                    _applyconvertbmarktopic(ui, repo, targetrevs, revnum, bmark, tr)
+                tr.close()
+            finally:
+                tr.release()
+    finally:
+        lockmod.release(lock, wlock)
+
+# inspired from mercurial.repair.stripbmrevset
+CONVERTBOOKREVSET = """
+not public() and (
+    ancestors(bookmark(%s))
+    and not ancestors(
+        (
+            (head() and not bookmark(%s))
+            or (bookmark() - bookmark(%s))
+        ) - (
+            descendants(bookmark(%s))
+            - bookmark(%s)
+        )
+    )
+)
+"""
+
+def _findconvertbmarktopic(repo, bmark):
+    """find revisions unambigiously defined by a bookmark
+
+    find all changesets under the bookmark and under that bookmark only.
+    """
+    return repo.revs(CONVERTBOOKREVSET, bmark, bmark, bmark, bmark, bmark)
+
+def _applyconvertbmarktopic(ui, repo, revs, old, bmark, tr):
+    """apply bookmark convertion to topic
+
+    Sets a topic as same as bname to all the changesets under the bookmark
+    and delete the bookmark, if topic is set to any changeset
+
+    old is the revision on which bookmark bmark is and tr is transaction object.
+    """
+
+    rewrote = _changetopics(ui, repo, revs, bmark)
+    # We didn't changed topic to any changesets because the revset
+    # returned an empty set of revisions, so let's skip deleting the
+    # bookmark corresponding to which we didn't put a topic on any
+    # changeset
+    if rewrote == 0:
+        return
+    ui.status(_('changed topic to "%s" on %d revisions\n') % (bmark,
+              rewrote))
+    ui.debug('removing bookmark "%s" from "%d"' % (bmark, old))
+    bookmarks.delete(repo, tr, [bmark])
+
 def _changecurrenttopic(repo, newtopic):
     """changes the current topic."""
 
@@ -393,73 +779,84 @@
         if repo.vfs.exists('topic'):
             repo.vfs.unlink('topic')
 
-def _changetopics(ui, repo, revset, newtopic):
+def _changetopics(ui, repo, revs, newtopic):
+    """ Changes topic to newtopic of all the revisions in the revset and return
+    the count of revisions whose topic has been changed.
+    """
     rewrote = 0
-    wl = l = txn = None
-    try:
-        wl = repo.wlock()
-        l = repo.lock()
-        txn = repo.transaction('rewrite-topics')
-        p1 = None
-        p2 = None
-        successors = {}
-        for c in repo.set('%r', revset):
-            def filectxfn(repo, ctx, path):
-                try:
-                    return c[path]
-                except error.ManifestLookupError:
-                    return None
-            fixedextra = dict(c.extra())
-            ui.debug('old node id is %s\n' % node.hex(c.node()))
-            ui.debug('origextra: %r\n' % fixedextra)
-            oldtopic = fixedextra.get(constants.extrakey, None)
-            if oldtopic == newtopic:
-                continue
-            if newtopic is None:
-                del fixedextra[constants.extrakey]
-            else:
-                fixedextra[constants.extrakey] = newtopic
-            fixedextra[constants.changekey] = c.hex()
-            if 'amend_source' in fixedextra:
-                # TODO: right now the commitctx wrapper in
-                # topicrepo overwrites the topic in extra if
-                # amend_source is set to support 'hg commit
-                # --amend'. Support for amend should be adjusted
-                # to not be so invasive.
-                del fixedextra['amend_source']
-            ui.debug('changing topic of %s from %s to %s\n' % (
-                c, oldtopic, newtopic))
-            ui.debug('fixedextra: %r\n' % fixedextra)
-            # While changing topic of set of linear commits, make sure that
-            # we base our commits on new parent rather than old parent which
-            # was obsoleted while changing the topic
-            p1 = c.p1().node()
-            p2 = c.p2().node()
-            if p1 in successors:
-                p1 = successors[p1]
-            if p2 in successors:
-                p2 = successors[p2]
-            mc = context.memctx(
-                repo, (p1, p2), c.description(),
-                c.files(), filectxfn,
-                user=c.user(), date=c.date(), extra=fixedextra)
+    p1 = None
+    p2 = None
+    successors = {}
+    for r in revs:
+        c = repo[r]
+
+        def filectxfn(repo, ctx, path):
+            try:
+                return c[path]
+            except error.ManifestLookupError:
+                return None
+        fixedextra = dict(c.extra())
+        ui.debug('old node id is %s\n' % node.hex(c.node()))
+        ui.debug('origextra: %r\n' % fixedextra)
+        oldtopic = fixedextra.get(constants.extrakey, None)
+        if oldtopic == newtopic:
+            continue
+        if newtopic is None:
+            del fixedextra[constants.extrakey]
+        else:
+            fixedextra[constants.extrakey] = newtopic
+        fixedextra[constants.changekey] = c.hex()
+        if 'amend_source' in fixedextra:
+            # TODO: right now the commitctx wrapper in
+            # topicrepo overwrites the topic in extra if
+            # amend_source is set to support 'hg commit
+            # --amend'. Support for amend should be adjusted
+            # to not be so invasive.
+            del fixedextra['amend_source']
+        ui.debug('changing topic of %s from %s to %s\n' % (
+            c, oldtopic, newtopic))
+        ui.debug('fixedextra: %r\n' % fixedextra)
+        # While changing topic of set of linear commits, make sure that
+        # we base our commits on new parent rather than old parent which
+        # was obsoleted while changing the topic
+        p1 = c.p1().node()
+        p2 = c.p2().node()
+        if p1 in successors:
+            p1 = successors[p1][0]
+        if p2 in successors:
+            p2 = successors[p2][0]
+        mc = context.memctx(repo,
+                            (p1, p2),
+                            c.description(),
+                            c.files(),
+                            filectxfn,
+                            user=c.user(),
+                            date=c.date(),
+                            extra=fixedextra)
+
+        # phase handling
+        commitphase = c.phase()
+        overrides = {('phases', 'new-commit'): commitphase}
+        with repo.ui.configoverride(overrides, 'changetopic'):
             newnode = repo.commitctx(mc)
-            successors[c.node()] = newnode
-            ui.debug('new node id is %s\n' % node.hex(newnode))
-            obsolete.createmarkers(repo, [(c, (repo[newnode],))])
-            rewrote += 1
-        # move the working copy too
-        wctx = repo[None]
-        # in-progress merge is a bit too complex for now.
-        if len(wctx.parents()) == 1:
-            newid = successors.get(wctx.p1().node())
-            if newid is not None:
-                hg.update(repo, newid, quietempty=True)
-        txn.close()
-    finally:
-        lock.release(txn, l, wl)
-        repo.invalidate()
-    ui.status('changed topic on %d changes\n' % rewrote)
+
+        successors[c.node()] = (newnode,)
+        ui.debug('new node id is %s\n' % node.hex(newnode))
+        rewrote += 1
+
+    # create obsmarkers and move bookmarks
+    # XXX we should be creating marker as we go instead of only at the end,
+    # this makes the operations more modulars
+    compat.cleanupnodes(repo, successors, 'changetopics')
+
+    # move the working copy too
+    wctx = repo[None]
+    # in-progress merge is a bit too complex for now.
+    if len(wctx.parents()) == 1:
+        newid = successors.get(wctx.p1().node())
+        if newid is not None:
+            hg.update(repo, newid[0], quietempty=True)
+    return rewrote
 
 def _listtopics(ui, repo, opts):
     fm = ui.formatter('topics', opts)
@@ -470,7 +867,7 @@
         return _showlasttouched(repo, fm, opts)
     activetopic = repo.currenttopic
     namemask = '%s'
-    if repo.topics and ui.verbose:
+    if repo.topics:
         maxwidth = max(len(t) for t in repo.topics)
         namemask = '%%-%is' % maxwidth
     for topic in sorted(repo.topics):
@@ -486,38 +883,46 @@
             fm.plain(' %s ' % marker, label=label)
         fm.write('topic', namemask, topic, label=label)
         fm.data(active=active)
+
+        data = stack.stack(repo, topic=topic)
+        fm.plain(' (')
+        if ui.verbose:
+            fm.write('branches+', 'on branch: %s',
+                     '+'.join(data.branches), # XXX use list directly after 4.0 is released
+                     label='topic.list.branches')
+
+            fm.plain(', ')
+        fm.write('changesetcount', '%d changesets', data.changesetcount,
+                 label='topic.list.changesetcount')
+
+        if data.troubledcount:
+            fm.plain(', ')
+            fm.write('troubledcount', '%d troubled',
+                     data.troubledcount,
+                     label='topic.list.troubledcount')
+
+        headcount = len(data.heads)
+        if 1 < headcount:
+            fm.plain(', ')
+            fm.write('headcount', '%d heads',
+                     headcount,
+                     label='topic.list.headcount.multiple')
+
         if ui.verbose:
             # XXX we should include the data even when not verbose
-            data = stack.stackdata(repo, topic=topic)
-            fm.plain(' (')
-            fm.write('branches+', 'on branch: %s',
-                     '+'.join(data['branches']), # XXX use list directly after 4.0 is released
-                     label='topic.list.branches')
-            fm.plain(', ')
-            fm.write('changesetcount', '%d changesets', data['changesetcount'],
-                     label='topic.list.changesetcount')
-            if data['troubledcount']:
-                fm.plain(', ')
-                fm.write('troubledcount', '%d troubled',
-                         data['troubledcount'],
-                         label='topic.list.troubledcount')
-            if 1 < data['headcount']:
-                fm.plain(', ')
-                fm.write('headcount', '%d heads',
-                         data['headcount'],
-                         label='topic.list.headcount.multiple')
-            if 0 < data['behindcount']:
+
+            behindcount = data.behindcount
+            if 0 < behindcount:
                 fm.plain(', ')
                 fm.write('behindcount', '%d behind',
-                         data['behindcount'],
+                         behindcount,
                          label='topic.list.behindcount')
-            elif -1 == data['behindcount']:
+            elif -1 == behindcount:
                 fm.plain(', ')
                 fm.write('behinderror', '%s',
-                         _('ambiguous destination'),
+                         _('ambiguous destination: %s') % data.behinderror,
                          label='topic.list.behinderror')
-            fm.plain(')')
-        fm.plain('\n')
+        fm.plain(')\n')
     fm.end()
 
 def _showlasttouched(repo, fm, opts):
@@ -530,8 +935,8 @@
         namemask = '%%-%is' % maxwidth
     activetopic = repo.currenttopic
     for timevalue in times:
-        curtopics = timedict[timevalue][1]
-        for topic in curtopics:
+        curtopics = sorted(timedict[timevalue][1])
+        for topic, user in curtopics:
             fm.startitem()
             marker = ' '
             label = 'topic'
@@ -544,10 +949,12 @@
             fm.data(active=active)
             fm.plain(' (')
             if timevalue == -1:
-                timestr = 'not yet touched'
+                timestr = 'empty and active'
             else:
                 timestr = templatefilters.age(timedict[timevalue][0])
             fm.write('lasttouched', '%s', timestr, label='topic.list.time')
+            if user:
+                fm.write('usertouched', ' by %s', user, label='topic.list.user')
             fm.plain(')')
             fm.plain('\n')
     fm.end()
@@ -560,6 +967,8 @@
     topicstime = {}
     curtime = time.time()
     for t in topics:
+        secspassed = -1
+        user = None
         maxtime = (0, 0)
         trevs = repo.revs("topic(%s)", t)
         # Need to check for the time of all changesets in the topic, whether
@@ -567,26 +976,38 @@
         # XXX: can we just rely on the max rev number for this
         for revs in trevs:
             rt = repo[revs].date()
-            if rt[0] > maxtime[0]:
+            if rt[0] >= maxtime[0]:
                 # Can store the rev to gather more info
                 # latesthead = revs
                 maxtime = rt
+                user = repo[revs].user()
             # looking on the markers also to get more information and accurate
             # last touch time.
-            obsmarkers = obsutil.getmarkers(repo, [repo[revs].node()])
+            obsmarkers = compat.getmarkers(repo, [repo[revs].node()])
             for marker in obsmarkers:
                 rt = marker.date()
                 if rt[0] > maxtime[0]:
+                    user = marker.metadata().get('user', user)
                     maxtime = rt
-        # is the topic still yet untouched
-        if not trevs:
-            secspassed = -1
-        else:
+
+        # Making the username more better
+        username = None
+        if user:
+            # user is of form "abc <abc@xyz.com>"
+            username = user.split('<')[0]
+            if not username:
+                # user is of form "<abc@xyz.com>"
+                username = user[1:-1]
+            username = username.strip()
+
+        topicuser = (t, username)
+
+        if trevs:
             secspassed = (curtime - maxtime[0])
         try:
-            topicstime[secspassed][1].append(t)
+            topicstime[secspassed][1].append(topicuser)
         except KeyError:
-            topicstime[secspassed] = (maxtime, [t])
+            topicstime[secspassed] = (maxtime, [topicuser])
 
     return topicstime
 
@@ -597,18 +1018,68 @@
     # i18n: column positioning for "hg summary"
     ui.write(_("topic:  %s\n") % ui.label(t, 'topic.active'))
 
+_validmode = [
+    'ignore',
+    'warning',
+    'enforce',
+    'enforce-all',
+    'random',
+    'random-all',
+]
+
+def _configtopicmode(ui):
+    """ Parse the config to get the topicmode
+    """
+    topicmode = ui.config('experimental', 'topic-mode')
+
+    # Fallback to read enforce-topic
+    if topicmode is None:
+        enforcetopic = ui.configbool('experimental', 'enforce-topic')
+        if enforcetopic:
+            topicmode = "enforce"
+    if topicmode not in _validmode:
+        topicmode = _validmode[0]
+
+    return topicmode
+
 def commitwrap(orig, ui, repo, *args, **opts):
     with repo.wlock():
-        enforcetopic = ui.configbool('experimental', 'enforce-topic')
+        topicmode = _configtopicmode(ui)
+        ismergecommit = len(repo[None].parents()) == 2
+
+        notopic = not repo.currenttopic
+        mayabort = (topicmode == "enforce" and not ismergecommit)
+        maywarn = (topicmode == "warning"
+                   or (topicmode == "enforce" and ismergecommit))
+
+        mayrandom = False
+        if topicmode == "random":
+            mayrandom = not ismergecommit
+        elif topicmode == "random-all":
+            mayrandom = True
+
+        if topicmode == 'enforce-all':
+            ismergecommit = False
+            mayabort = True
+            maywarn = False
+
+        hint = _("see 'hg help -e topic.topic-mode' for details")
         if opts.get('topic'):
             t = opts['topic']
             with repo.vfs.open('topic', 'w') as f:
                 f.write(t)
-        elif not repo.currenttopic and enforcetopic:
+        elif opts.get('amend'):
+            pass
+        elif notopic and mayabort:
             msg = _("no active topic")
-            hint = _("set a current topic or use '--config " +
-                     "experimental.enforce-topic=no' to commit without a topic")
             raise error.Abort(msg, hint=hint)
+        elif notopic and maywarn:
+            ui.warn(_("warning: new draft commit without topic\n"))
+            if not ui.quiet:
+                ui.warn(("(%s)\n") % hint)
+        elif notopic and mayrandom:
+            with repo.vfs.open('topic', 'w') as f:
+                f.write(randomname.randomtopicname(ui))
         return orig(ui, repo, *args, **opts)
 
 def committextwrap(orig, repo, ctx, subs, extramsg):
@@ -619,6 +1090,12 @@
                           "\nHG: topic '%s'\nHG: branch" % t)
     return ret
 
+def pushoutgoingwrap(orig, ui, repo, *args, **opts):
+    if opts.get('topic'):
+        topicrevs = repo.revs('topic(%s) - obsolete()', opts['topic'])
+        opts.setdefault('rev', []).extend(topicrevs)
+    return orig(ui, repo, *args, **opts)
+
 def mergeupdatewrap(orig, repo, node, branchmerge, force, *args, **kwargs):
     matcher = kwargs.get('matcher')
     partial = not (matcher is None or matcher.always())
@@ -632,12 +1109,13 @@
         # if rebase is running and update the currenttopic to topic of new
         # rebased commit. We have explicitly stored in config if rebase is
         # running.
+        ot = repo.currenttopic
+        empty = stack.stack(repo, topic=ot).changesetcount == 0
         if repo.ui.hasconfig('experimental', 'topicrebase'):
             isrebase = True
         if repo.ui.configbool('_internal', 'keep-topic'):
             ist0 = True
         if ((not partial and not branchmerge) or isrebase) and not ist0:
-            ot = repo.currenttopic
             t = ''
             pctx = repo[node]
             if pctx.phase() > phases.public:
@@ -646,22 +1124,25 @@
                 f.write(t)
             if t and t != ot:
                 repo.ui.status(_("switching to topic %s\n") % t)
+            if ot and not t and empty:
+                repo.ui.status(_('clearing empty topic "%s"\n') % ot)
         elif ist0:
-            repo.ui.status(_("preserving the current topic '%s'\n") %
-                           repo.currenttopic)
+            repo.ui.status(_("preserving the current topic '%s'\n") % ot)
         return ret
     finally:
         wlock.release()
 
-def checkt0(orig, ui, repo, node=None, rev=None, clean=False, date=None,
-            check=False, merge=None, tool=None):
+def checkt0(orig, ui, repo, node=None, rev=None, *args, **kwargs):
 
     thezeros = set(['t0', 'b0'])
-    overrides = {}
-    if node in thezeros or rev in thezeros:
-        overrides[('_internal', 'keep-topic')] = 'yes'
-    with repo.ui.configoverride(overrides, source='topic-extension'):
-        return orig(ui, repo, node, rev, clean, date, check, merge, tool)
+    backup = repo.ui.backupconfig('_internal', 'keep-topic')
+    try:
+        if node in thezeros or rev in thezeros:
+            repo.ui.setconfig('_internal', 'keep-topic', 'yes',
+                              source='topic-extension')
+        return orig(ui, repo, node, rev, *args, **kwargs)
+    finally:
+        repo.ui.restoreconfig(backup)
 
 def _fixrebase(loaded):
     if not loaded:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext3rd/topic/compat.py	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,47 @@
+# Copyright 2017 FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+"""
+Compatibility module
+"""
+from __future__ import absolute_import
+
+from mercurial import (
+    obsolete,
+    scmutil,
+    util,
+)
+
+getmarkers = None
+successorssets = None
+try:
+    from mercurial import obsutil
+    getmarkers = getattr(obsutil, 'getmarkers', None)
+    successorssets = getattr(obsutil, 'successorssets', None)
+except ImportError:
+    pass
+
+if getmarkers is None:
+    getmarkers = obsolete.getmarkers
+if successorssets is None:
+    successorssets = obsolete.successorssets
+
+def startpager(ui, cmd):
+    """function to start a pager in case ui.pager() exists"""
+    try:
+        ui.pager(cmd)
+    except AttributeError:
+        pass
+
+def cleanupnodes(repo, replacements, operation, moves=None):
+    # create obsmarkers and move bookmarks
+    # XXX we should be creating marker as we go instead of only at the end,
+    # this makes the operations more modulars
+    if util.safehasattr(scmutil, 'cleanupnodes'):
+        scmutil.cleanupnodes(repo, replacements, 'changetopics',
+                             moves=moves)
+    else:
+        relations = [(repo[o], tuple(repo[n] for n in new))
+                     for (o, new) in replacements.iteritems()]
+        obsolete.createmarkers(repo, relations)
--- a/hgext3rd/topic/destination.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/topic/destination.py	Tue Nov 14 23:04:04 2017 +0100
@@ -6,7 +6,6 @@
     destutil,
     error,
     extensions,
-    util,
 )
 from . import topicmap
 from .evolvebits import builddependencies
@@ -54,12 +53,7 @@
             msg = _("topic '%s' has %d heads "
                     "- please merge with an explicit rev") % (top, len(heads))
             raise error.ManyMergeDestAbort(msg)
-    if len(getattr(orig, 'func_defaults', ())) == 3: # version hg-3.7
-        return orig(repo, action, sourceset, onheadcheck)
-    if 3 < len(getattr(orig, 'func_defaults', ())): # version hg-3.8 and above
-        return orig(repo, action, sourceset, onheadcheck, destspace=destspace)
-    else:
-        return orig(repo)
+    return orig(repo, action, sourceset, onheadcheck, destspace=destspace)
 
 def _destupdatetopic(repo, clean, check=None):
     """decide on an update destination from current topic"""
@@ -100,19 +94,8 @@
 
 def modsetup(ui):
     """run a uisetup time to install all destinations wrapping"""
-    if util.safehasattr(destutil, '_destmergebranch'):
-        extensions.wrapfunction(destutil, '_destmergebranch', _destmergebranch)
-    try:
-        rebase = extensions.find('rebase')
-    except KeyError:
-        rebase = None
-    if (util.safehasattr(rebase, '_destrebase')
-            # logic not shared with merge yet < hg-3.8
-            and not util.safehasattr(rebase, '_definesets')):
-        extensions.wrapfunction(rebase, '_destrebase', _destmergebranch)
-    if util.safehasattr(destutil, 'destupdatesteps'):
-        bridx = destutil.destupdatesteps.index('branch')
-        destutil.destupdatesteps.insert(bridx, 'topic')
-        destutil.destupdatestepmap['topic'] = _destupdatetopic
-    if util.safehasattr(destutil, 'desthistedit'):
-        extensions.wrapfunction(destutil, 'desthistedit', desthistedit)
+    extensions.wrapfunction(destutil, '_destmergebranch', _destmergebranch)
+    bridx = destutil.destupdatesteps.index('branch')
+    destutil.destupdatesteps.insert(bridx, 'topic')
+    destutil.destupdatestepmap['topic'] = _destupdatetopic
+    extensions.wrapfunction(destutil, 'desthistedit', desthistedit)
--- a/hgext3rd/topic/discovery.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/topic/discovery.py	Tue Nov 14 23:04:04 2017 +0100
@@ -1,5 +1,6 @@
 from __future__ import absolute_import
 
+import collections
 import weakref
 
 from mercurial.i18n import _
@@ -31,17 +32,50 @@
 
     publishing = ('phases' not in remote.listkeys('namespaces')
                   or bool(remote.listkeys('phases').get('publishing', False)))
-    if publishing or not remote.capable('topics'):
+    if ((publishing or not remote.capable('topics'))
+            and (pushoparg and not pushop.publish)):
         return orig(*args)
 
+    publishedset = ()
+    remotebranchmap = None
+    origremotebranchmap = remote.branchmap
+    if pushoparg: # < hg-4.4 do not have a --publish flag anyway
+        publishednode = [c.node() for c in pushop.outdatedphases]
+        publishedset = repo.revs('ancestors(%ln + %ln)',
+                                 publishednode,
+                                 pushop.remotephases.publicheads)
+
+        rev = repo.unfiltered().changelog.nodemap.get
+
+        def remotebranchmap():
+            # drop topic information from changeset about to be published
+            result = collections.defaultdict(list)
+            for branch, heads in origremotebranchmap().iteritems():
+                if ':' not in branch:
+                    result[branch].extend(heads)
+                else:
+                    namedbranch = branch.split(':', 1)[0]
+                    for h in heads:
+                        r = rev(h)
+                        if r is not None and r in publishedset:
+                            result[namedbranch].append(h)
+                        else:
+                            result[branch].append(h)
+            for heads in result.itervalues():
+                heads.sort()
+            return result
+
     class repocls(repo.__class__):
         # awful hack to see branch as "branch:topic"
         def __getitem__(self, key):
             ctx = super(repocls, self).__getitem__(key)
             oldbranch = ctx.branch
+            rev = ctx.rev()
 
             def branch():
                 branch = oldbranch()
+                if rev in publishedset:
+                    return branch
                 topic = ctx.topic()
                 if topic:
                     branch = "%s:%s" % (branch, topic)
@@ -56,6 +90,8 @@
 
             def branchinfo(rev):
                 branch, close = changelog.branchinfo(rev)
+                if rev in publishedset:
+                    return branch, close
                 topic = repo[rev].topic()
                 if topic:
                     branch = "%s:%s" % (branch, topic)
@@ -67,6 +103,7 @@
     oldrepocls = repo.__class__
     try:
         repo.__class__ = repocls
+        remote.branchmap = remotebranchmap
         unxx = repo.filtered('unfiltered-topic')
         repo.unfiltered = lambda: unxx
         if pushoparg:
@@ -83,6 +120,7 @@
         if 'unfiltered' in vars(repo):
             del repo.unfiltered
         repo.__class__ = oldrepocls
+        remote.branchmap = origremotebranchmap
 
 def wireprotobranchmap(orig, repo, proto):
     oldrepo = repo.__class__
--- a/hgext3rd/topic/evolvebits.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/topic/evolvebits.py	Tue Nov 14 23:04:04 2017 +0100
@@ -1,15 +1,6 @@
 import collections
-from mercurial import obsolete
 
-successorssets = None
-try:
-    from mercurial import obsutil
-    successorssets = getattr(obsutil, 'successorssets', None)
-except ImportError:
-    pass
-
-if successorssets is None:
-    successorssets = obsolete.successorssets
+from . import compat
 
 # Copied from evolve 081605c2e9b6
 
@@ -82,16 +73,24 @@
         return p.rev()
     obs = repo[p]
     ui = repo.ui
-    newer = successorssets(repo, obs.node())
+    newer = compat.successorssets(repo, obs.node())
     # search of a parent which is not killed
     while not newer:
         ui.debug("stabilize target %s is plain dead,"
                  " trying to stabilize on its parent\n" %
                  obs)
         obs = obs.parents()[0]
-        newer = successorssets(repo, obs.node())
-    if len(newer) > 1 or len(newer[0]) > 1:
+        newer = compat.successorssets(repo, obs.node())
+    if 1 < len(newer):
+        # divergence case
+        # we should pick as arbitrary one
         raise MultipleSuccessorsError(newer)
+    elif 1 < len(newer[0]):
+        splitheads = list(repo.revs('heads(%ln::%ln)', newer[0], newer[0]))
+        if 1 < len(splitheads):
+            # split case, See if we can make sense of it.
+            raise MultipleSuccessorsError(newer)
+        return splitheads[0]
 
     return repo[newer[0][0]].rev()
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext3rd/topic/flow.py	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,69 @@
+from __future__ import absolute_import
+
+from mercurial import (
+    commands,
+    error,
+    exchange,
+    extensions,
+    node,
+    phases,
+    util,
+)
+
+from mercurial.i18n import _
+
+def enforcesinglehead(repo, tr):
+    for name, heads in repo.filtered('visible').branchmap().iteritems():
+        if len(heads) > 1:
+            hexs = [node.short(n) for n in heads]
+            raise error.Abort(_('%d heads on "%s"') % (len(heads), name),
+                              hint=(', '.join(hexs)))
+
+def publishbarebranch(repo, tr):
+    """Publish changeset without topic"""
+    if 'node' not in tr.hookargs: # no new node
+        return
+    startnode = node.bin(tr.hookargs['node'])
+    topublish = repo.revs('not public() and (%n:) - hidden() - topic()', startnode)
+    if topublish:
+        cl = repo.changelog
+        nodes = [cl.node(r) for r in topublish]
+        repo._phasecache.advanceboundary(repo, tr, phases.public, nodes)
+
+def wrappush(orig, repo, remote, *args, **kwargs):
+    """interpret the --publish flag and pass it to the push operation"""
+    newargs = kwargs.copy()
+    if kwargs.pop('publish', False):
+        opargs = kwargs.get('opargs')
+        if opargs is None:
+            opargs = {}
+        newargs['opargs'] = opargs.copy()
+        newargs['opargs']['publish'] = True
+    return orig(repo, remote, *args, **newargs)
+
+def extendpushoperation(orig, *args, **kwargs):
+    publish = kwargs.pop('publish', False)
+    op = orig(*args, **kwargs)
+    op.publish = publish
+    return op
+
+def wrapphasediscovery(orig, pushop):
+    orig(pushop)
+    if pushop.publish:
+        if not util.safehasattr(pushop, 'remotephases'):
+            msg = _('--publish flag only supported from Mercurial 4.4 and higher')
+            raise error.Abort(msg)
+        if not pushop.remotephases.publishing:
+            unfi = pushop.repo.unfiltered()
+            droots = pushop.remotephases.draftroots
+            revset = '%ln and (not public() or %ln::)'
+            future = list(unfi.set(revset, pushop.futureheads, droots))
+            pushop.outdatedphases = future
+
+def installpushflag(ui):
+    entry = extensions.wrapcommand(commands.table, 'push', wrappush)
+    entry[1].append(('', 'publish', False,
+                    _('push the changeset as public')))
+    extensions.wrapfunction(exchange, 'pushoperation', extendpushoperation)
+    extensions.wrapfunction(exchange, '_pushdiscoveryphase', wrapphasediscovery)
+    exchange.pushdiscoverymapping['phase'] = exchange._pushdiscoveryphase
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext3rd/topic/randomname.py	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,1011 @@
+# randomname.py - topic extension
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+"""random topic generator utils
+"""
+
+import random
+
+animals = [
+    'aardvark',
+    'albatross',
+    'alligator',
+    'alpaca',
+    'ant',
+    'anteater',
+    'antelope',
+    'ape',
+    'armadillo',
+    'baboon',
+    'badger',
+    'barracuda',
+    'bat',
+    'bear',
+    'beaver',
+    'bee',
+    'beetle',
+    'bison',
+    'boar',
+    'buffalo',
+    'bushbaby',
+    'bustard',
+    'butterfly',
+    'camel',
+    'capuchin',
+    'carabao',
+    'caribou',
+    'cat',
+    'caterpillar',
+    'cattle',
+    'chameleon',
+    'chamois',
+    'cheetah',
+    'chicken',
+    'chimpanzee',
+    'chinchilla',
+    'chipmunk',
+    'chough',
+    'cicada',
+    'clam',
+    'cobra',
+    'cockroach',
+    'cod',
+    'cormorant',
+    'coyote',
+    'crab',
+    'crane',
+    'cricket',
+    'crocodile',
+    'crow',
+    'curlew',
+    'deer',
+    'dinosaur',
+    'dog',
+    'dogfish',
+    'dolphin',
+    'donkey',
+    'dotterel',
+    'dove',
+    'dragon',
+    'dragonfly',
+    'duck',
+    'dugong',
+    'dunlin',
+    'eagle',
+    'echidna',
+    'eel',
+    'eland',
+    'elephant',
+    'elk',
+    'emu',
+    'falcon',
+    'ferret',
+    'finch',
+    'fish',
+    'flamingo',
+    'fly',
+    'fox',
+    'frog',
+    'gaur',
+    'gazelle',
+    'gecko',
+    'gerbil',
+    'giraffe',
+    'gnat',
+    'gnu',
+    'goat',
+    'goldfish',
+    'goose',
+    'gorilla',
+    'goshawk',
+    'grasshopper',
+    'grouse',
+    'guanaco',
+    'guinea',
+    'gull',
+    'hamster',
+    'hare',
+    'hawk',
+    'hedgehog',
+    'heron',
+    'herring',
+    'hippopotamus',
+    'hornet',
+    'horse',
+    'horsecrab',
+    'hound',
+    'hummingbird',
+    'hyena',
+    'hyrax',
+    'ibex',
+    'ibis',
+    'iguana',
+    'impala',
+    'insect',
+    'jackal',
+    'jaguar',
+    'jay',
+    'jellyfish',
+    'kangaroo',
+    'koala',
+    'kouprey',
+    'kudu',
+    'lapwing',
+    'lark',
+    'lemming',
+    'lemur',
+    'leopard',
+    'lion',
+    'lizard',
+    'llama',
+    'lobster',
+    'locust',
+    'loris',
+    'louse',
+    'lynx',
+    'lyrebird',
+    'magpie',
+    'mallard',
+    'mammoth',
+    'manatee',
+    'marten',
+    'meerkat',
+    'mink',
+    'minnow',
+    'mole',
+    'mongoose',
+    'monkey',
+    'moose',
+    'mosquito',
+    'mouse',
+    'mule',
+    'muskrat',
+    'narwhal',
+    'newt',
+    'nightingale',
+    'numbat',
+    'octopus',
+    'okapi',
+    'opossum',
+    'oryx',
+    'ostrich',
+    'otter',
+    'owl',
+    'ox',
+    'oyster',
+    'panda',
+    'panther',
+    'parrot',
+    'partridge',
+    'peacock',
+    'peafowl',
+    'pelican',
+    'penguin',
+    'pheasant',
+    'pig',
+    'pigeon',
+    'platypus',
+    'pony',
+    'porcupine',
+    'porpoise',
+    'prairie',
+    'puffin',
+    'pug',
+    'quagga',
+    'quail',
+    'quelea',
+    'rabbit',
+    'raccoon',
+    'ram',
+    'rat',
+    'raven',
+    'reindeer',
+    'rhea',
+    'rhinoceros',
+    'rook',
+    'ruff',
+    'salamander',
+    'salmon',
+    'sambar',
+    'sandpiper',
+    'sardine',
+    'scorpion',
+    'seahorse',
+    'seal',
+    'serval',
+    'shark',
+    'sheep',
+    'shrew',
+    'shrimp',
+    'skink',
+    'skunk',
+    'snail',
+    'snake',
+    'spider',
+    'squid',
+    'squirrel',
+    'starling',
+    'stinkbug',
+    'stork',
+    'swan',
+    'tapir',
+    'tarsier',
+    'termite',
+    'tern',
+    'tiger',
+    'toad',
+    'trout',
+    'turkey',
+    'turtle',
+    'unicorn',
+    'viper',
+    'vulture',
+    'wallaby',
+    'walrus',
+    'wasp',
+    'weasel',
+    'whale',
+    'wolf',
+    'wolverine',
+    'wombat',
+    'woodchuck',
+    'woodcock',
+    'woodpecker',
+    'worm',
+    'wren',
+    'yak',
+    'zebra',
+    'zorilla'
+]
+
+adjectives = [
+    'abiding',
+    'abject',
+    'ablaze',
+    'able',
+    'aboard',
+    'abounding',
+    'absorbed',
+    'absorbing',
+    'abstracted',
+    'abundant',
+    'acceptable',
+    'accessible',
+    'accurate',
+    'acoustic',
+    'adamant',
+    'adaptable',
+    'adhesive',
+    'adjoining',
+    'adorable',
+    'adventurous',
+    'affable',
+    'affectionate',
+    'agreeable',
+    'alert',
+    'alive',
+    'alluring',
+    'amazing',
+    'ambiguous',
+    'ambitious',
+    'amiable',
+    'amicable',
+    'amused',
+    'amusing',
+    'ancient',
+    'animated',
+    'apricot',
+    'aquatic',
+    'arctic',
+    'arenaceous',
+    'aromatic',
+    'aspiring',
+    'assiduous',
+    'assorted',
+    'astonishing',
+    'attractive',
+    'auspicious',
+    'automatic',
+    'available',
+    'average',
+    'awake',
+    'aware',
+    'awesome',
+    'axiomatic',
+    'bashful',
+    'bawdy',
+    'beautiful',
+    'beefy',
+    'befitting',
+    'beneficial',
+    'benevolent',
+    'bent',
+    'best',
+    'better',
+    'bewildered',
+    'bewitching',
+    'big',
+    'billowy',
+    'bizarre',
+    'black',
+    'blithe',
+    'blue',
+    'blushing',
+    'bouncy',
+    'boundless',
+    'brainy',
+    'brash',
+    'brave',
+    'brawny',
+    'brazen',
+    'breezy',
+    'brief',
+    'bright',
+    'brilliant',
+    'broad',
+    'brown',
+    'bucolic',
+    'bulky',
+    'bumpy',
+    'burgundy',
+    'burly',
+    'bustling',
+    'busy',
+    'calm',
+    'capable',
+    'capricious',
+    'captivating',
+    'carefree',
+    'careful',
+    'caring',
+    'carrot',
+    'ceaseless',
+    'cerise',
+    'certain',
+    'challenging',
+    'changeable',
+    'charming',
+    'cheerful',
+    'chief',
+    'chilly',
+    'chipper',
+    'classy',
+    'clean',
+    'clear',
+    'clever',
+    'cloudy',
+    'coherent',
+    'colorful',
+    'colossal',
+    'comfortable',
+    'common',
+    'communicative',
+    'compassionate',
+    'complete',
+    'complex',
+    'compulsive',
+    'confused',
+    'conscientious',
+    'conscious',
+    'conservative',
+    'considerate',
+    'convivial',
+    'cooing',
+    'cool',
+    'cooperative',
+    'coordinated',
+    'courageous',
+    'courteous',
+    'crazy',
+    'creative',
+    'crispy',
+    'crooked',
+    'crowded',
+    'cuddly',
+    'cultured',
+    'cunning',
+    'curious',
+    'curly',
+    'curved',
+    'curvy',
+    'cut',
+    'cute',
+    'daily',
+    'damp',
+    'dapper',
+    'dashing',
+    'dazzling',
+    'dear',
+    'debonair',
+    'decisive',
+    'decorous',
+    'deep',
+    'defiant',
+    'delicate',
+    'delicious',
+    'delighted',
+    'delightful',
+    'delirious',
+    'descriptive',
+    'detached',
+    'detailed',
+    'determined',
+    'different',
+    'diligent',
+    'diminutive',
+    'diplomatic',
+    'discreet',
+    'distinct',
+    'distinctive',
+    'dramatic',
+    'dry',
+    'dynamic',
+    'dynamite',
+    'eager',
+    'early',
+    'earthy',
+    'easy',
+    'easygoing',
+    'eatable',
+    'economic',
+    'ecstatic',
+    'educated',
+    'efficacious',
+    'efficient',
+    'effortless',
+    'eight',
+    'elastic',
+    'elated',
+    'electric',
+    'elegant',
+    'elfin',
+    'elite',
+    'eminent',
+    'emotional',
+    'enchanted',
+    'enchanting',
+    'encouraging',
+    'endless',
+    'energetic',
+    'enormous',
+    'entertaining',
+    'enthusiastic',
+    'envious',
+    'epicurean',
+    'equable',
+    'equal',
+    'eternal',
+    'ethereal',
+    'evanescent',
+    'even',
+    'excellent',
+    'excited',
+    'exciting',
+    'exclusive',
+    'exotic',
+    'expensive',
+    'exquisite',
+    'extroverted',
+    'exuberant',
+    'exultant',
+    'fabulous',
+    'fair',
+    'faithful',
+    'familiar',
+    'famous',
+    'fancy',
+    'fantastic',
+    'far',
+    'fascinated',
+    'fast',
+    'fearless',
+    'female',
+    'fertile',
+    'festive',
+    'few',
+    'fine',
+    'first',
+    'five',
+    'fixed',
+    'flamboyant',
+    'flashy',
+    'flat',
+    'flawless',
+    'flirtatious',
+    'florid',
+    'flowery',
+    'fluffy',
+    'fluttering',
+    'foamy',
+    'foolish',
+    'foregoing',
+    'fortunate',
+    'four',
+    'frank',
+    'free',
+    'frequent',
+    'fresh',
+    'friendly',
+    'full',
+    'functional',
+    'funny',
+    'furry',
+    'future',
+    'futuristic',
+    'fuzzy',
+    'gabby',
+    'gainful',
+    'garrulous',
+    'general',
+    'generous',
+    'gentle',
+    'giant',
+    'giddy',
+    'gifted',
+    'gigantic',
+    'gilded',
+    'glamorous',
+    'gleaming',
+    'glorious',
+    'glossy',
+    'glowing',
+    'godly',
+    'good',
+    'goofy',
+    'gorgeous',
+    'graceful',
+    'grandiose',
+    'grateful',
+    'gratis',
+    'gray',
+    'great',
+    'green',
+    'gregarious',
+    'grey',
+    'groovy',
+    'guiltless',
+    'gusty',
+    'guttural',
+    'habitual',
+    'half',
+    'hallowed',
+    'halting',
+    'handsome',
+    'happy',
+    'hard',
+    'hardworking',
+    'harmonious',
+    'heady',
+    'healthy',
+    'heavenly',
+    'helpful',
+    'hilarious',
+    'historical',
+    'holistic',
+    'hollow',
+    'honest',
+    'honorable',
+    'hopeful',
+    'hospitable',
+    'hot',
+    'huge',
+    'humorous',
+    'hungry',
+    'hushed',
+    'hypnotic',
+    'illustrious',
+    'imaginary',
+    'imaginative',
+    'immense',
+    'imminent',
+    'impartial',
+    'important',
+    'imported',
+    'impossible',
+    'incandescent',
+    'inconclusive',
+    'incredible',
+    'independent',
+    'industrious',
+    'inexpensive',
+    'innate',
+    'innocent',
+    'inquisitive',
+    'instinctive',
+    'intellectual',
+    'intelligent',
+    'intense',
+    'interesting',
+    'internal',
+    'intuitive',
+    'inventive',
+    'invincible',
+    'jazzy',
+    'jolly',
+    'joyful',
+    'joyous',
+    'judicious',
+    'juicy',
+    'jumpy',
+    'keen',
+    'kind',
+    'kindhearted',
+    'kindly',
+    'knotty',
+    'knowing',
+    'knowledgeable',
+    'known',
+    'laconic',
+    'large',
+    'lavish',
+    'lean',
+    'learned',
+    'left',
+    'legal',
+    'level',
+    'light',
+    'likeable',
+    'literate',
+    'little',
+    'lively',
+    'living',
+    'long',
+    'longing',
+    'loud',
+    'lovely',
+    'loving',
+    'loyal',
+    'lucky',
+    'luminous',
+    'lush',
+    'luxuriant',
+    'luxurious',
+    'lyrical',
+    'magenta',
+    'magical',
+    'magnificent',
+    'majestic',
+    'male',
+    'mammoth',
+    'many',
+    'marvelous',
+    'massive',
+    'material',
+    'mature',
+    'meandering',
+    'meaty',
+    'medical',
+    'mellow',
+    'melodic',
+    'melted',
+    'merciful',
+    'mighty',
+    'miniature',
+    'miniscule',
+    'minor',
+    'minute',
+    'misty',
+    'modern',
+    'modest',
+    'momentous',
+    'motionless',
+    'mountainous',
+    'mute',
+    'mysterious',
+    'narrow',
+    'natural',
+    'near',
+    'neat',
+    'nebulous',
+    'necessary',
+    'neighborly',
+    'new',
+    'next',
+    'nice',
+    'nifty',
+    'nimble',
+    'nine',
+    'nippy',
+    'noiseless',
+    'noisy',
+    'nonchalant',
+    'normal',
+    'numberless',
+    'numerous',
+    'nutritious',
+    'obedient',
+    'observant',
+    'obtainable',
+    'oceanic',
+    'omniscient',
+    'one',
+    'open',
+    'opposite',
+    'optimal',
+    'optimistic',
+    'opulent',
+    'orange',
+    'ordinary',
+    'organic',
+    'outgoing',
+    'outrageous',
+    'outstanding',
+    'oval',
+    'overjoyed',
+    'overt',
+    'palatial',
+    'panoramic',
+    'parallel',
+    'passionate',
+    'past',
+    'pastoral',
+    'patient',
+    'peaceful',
+    'perfect',
+    'periodic',
+    'permissible',
+    'perpetual',
+    'persistent',
+    'petite',
+    'philosophical',
+    'physical',
+    'picturesque',
+    'pink',
+    'pioneering',
+    'piquant',
+    'plausible',
+    'pleasant',
+    'plucky',
+    'poised',
+    'polite',
+    'possible',
+    'powerful',
+    'practical',
+    'precious',
+    'premium',
+    'present',
+    'pretty',
+    'previous',
+    'private',
+    'probable',
+    'productive',
+    'profound',
+    'profuse',
+    'protective',
+    'proud',
+    'psychedelic',
+    'public',
+    'pumped',
+    'purple',
+    'purring',
+    'puzzled',
+    'puzzling',
+    'quaint',
+    'quick',
+    'quicker',
+    'quickest',
+    'quiet',
+    'quirky',
+    'quixotic',
+    'quizzical',
+    'rainy',
+    'rapid',
+    'rare',
+    'rational',
+    'ready',
+    'real',
+    'rebel',
+    'receptive',
+    'red',
+    'reflective',
+    'regular',
+    'relaxed',
+    'reliable',
+    'relieved',
+    'remarkable',
+    'reminiscent',
+    'reserved',
+    'resolute',
+    'resonant',
+    'resourceful',
+    'responsible',
+    'rich',
+    'ridiculous',
+    'right',
+    'rightful',
+    'ripe',
+    'ritzy',
+    'roasted',
+    'robust',
+    'romantic',
+    'roomy',
+    'round',
+    'royal',
+    'ruddy',
+    'rural',
+    'rustic',
+    'sable',
+    'safe',
+    'salty',
+    'same',
+    'satisfying',
+    'savory',
+    'scientific',
+    'scintillating',
+    'scrumptious',
+    'second',
+    'secret',
+    'secretive',
+    'seemly',
+    'selective',
+    'sensible',
+    'separate',
+    'shaggy',
+    'shaky',
+    'shining',
+    'shiny',
+    'short',
+    'shy',
+    'silent',
+    'silky',
+    'silly',
+    'simple',
+    'simplistic',
+    'sincere',
+    'six',
+    'sizzling',
+    'skillful',
+    'sleepy',
+    'slick',
+    'slim',
+    'smart',
+    'smiling',
+    'smooth',
+    'soaring',
+    'sociable',
+    'soft',
+    'solid',
+    'sophisticated',
+    'sparkling',
+    'special',
+    'spectacular',
+    'speedy',
+    'spicy',
+    'spiffy',
+    'spiritual',
+    'splendid',
+    'spooky',
+    'spotless',
+    'spotted',
+    'square',
+    'standing',
+    'statuesque',
+    'steadfast',
+    'steady',
+    'steep',
+    'stimulating',
+    'straight',
+    'straightforward',
+    'striking',
+    'striped',
+    'strong',
+    'stunning',
+    'stupendous',
+    'sturdy',
+    'subsequent',
+    'substantial',
+    'subtle',
+    'successful',
+    'succinct',
+    'sudden',
+    'super',
+    'superb',
+    'supreme',
+    'swanky',
+    'sweet',
+    'swift',
+    'sympathetic',
+    'synonymous',
+    'talented',
+    'tall',
+    'tame',
+    'tan',
+    'tangible',
+    'tangy',
+    'tasteful',
+    'tasty',
+    'telling',
+    'temporary',
+    'tempting',
+    'ten',
+    'tender',
+    'terrific',
+    'tested',
+    'thankful',
+    'therapeutic',
+    'thin',
+    'thinkable',
+    'third',
+    'thoughtful',
+    'three',
+    'thrifty',
+    'tidy',
+    'tiny',
+    'toothsome',
+    'towering',
+    'tranquil',
+    'tremendous',
+    'tricky',
+    'true',
+    'truthful',
+    'two',
+    'typical',
+    'ubiquitous',
+    'ultra',
+    'unassuming',
+    'unbiased',
+    'uncovered',
+    'understanding',
+    'understood',
+    'unequaled',
+    'unique',
+    'unusual',
+    'unwritten',
+    'upbeat',
+    'useful',
+    'utopian',
+    'utter',
+    'uttermost',
+    'valuable',
+    'various',
+    'vast',
+    'verdant',
+    'vermilion',
+    'versatile',
+    'versed',
+    'victorious',
+    'vigorous',
+    'violet',
+    'vivacious',
+    'voiceless',
+    'voluptuous',
+    'wacky',
+    'waiting',
+    'wakeful',
+    'wandering',
+    'warm',
+    'warmhearted',
+    'wealthy',
+    'whimsical',
+    'whispering',
+    'white',
+    'whole',
+    'wholesale',
+    'whopping',
+    'wide',
+    'wiggly',
+    'wild',
+    'willing',
+    'windy',
+    'winsome',
+    'wiry',
+    'wise',
+    'wistful',
+    'witty',
+    'womanly',
+    'wonderful',
+    'workable',
+    'young',
+    'youthful',
+    'yummy',
+    'zany',
+    'zealous',
+    'zesty',
+    'zippy'
+]
+
+def randomtopicname(ui):
+    if ui.configint("devel", "randomseed"):
+        random.seed(ui.configint("devel", "randomseed"))
+    return random.choice(adjectives) + "-" + random.choice(animals)
--- a/hgext3rd/topic/revset.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/topic/revset.py	Tue Nov 14 23:04:04 2017 +0100
@@ -1,6 +1,7 @@
 from __future__ import absolute_import
 
 from mercurial import (
+    registrar,
     revset,
     util,
 )
@@ -16,10 +17,11 @@
 except AttributeError:
     mkmatcher = util.stringmatcher
 
+revsetpredicate = registrar.revsetpredicate()
 
+@revsetpredicate('topic([topic])')
 def topicset(repo, subset, x):
-    """`topic([topic])`
-    Specified topic or all changes with any topic specified.
+    """Specified topic or all changes with any topic specified.
 
     If `topic` starts with `re:` the remainder of the name is treated
     as a regular expression.
@@ -48,10 +50,9 @@
         return matcher(topic)
     return (subset & mutable).filter(matchtopic)
 
+@revsetpredicate('ngtip([branch])')
 def ngtipset(repo, subset, x):
-    """`ngtip([branch])`
-
-    The untopiced tip.
+    """The untopiced tip.
 
     Name is horrible so that people change it.
     """
@@ -62,26 +63,19 @@
         branch = repo['.'].branch()
     return subset & revset.baseset(destination.ngtip(repo, branch))
 
+@revsetpredicate('stack()')
 def stackset(repo, subset, x):
-    """`stack()`
-    All relevant changes in the current topic,
+    """All relevant changes in the current topic,
 
     This is roughly equivalent to 'topic(.) - obsolete' with a sorting moving
     unstable changeset after there future parent (as if evolve where already
     run)."""
     err = 'stack() takes no argument, it works on current topic'
     revset.getargs(x, 0, 0, err)
-    topic = repo.currenttopic
     topic = None
     branch = None
-    if not topic and repo.currenttopic:
+    if repo.currenttopic:
         topic = repo.currenttopic
-    if not topic:
+    else:
         branch = repo[None].branch()
-    return revset.baseset(stack.getstack(repo, branch=branch, topic=topic)[1:]) & subset
-
-
-def modsetup(ui):
-    revset.symbols.update({'topic': topicset})
-    revset.symbols.update({'ngtip': ngtipset})
-    revset.symbols.update({'stack': stackset})
+    return revset.baseset(stack.stack(repo, branch=branch, topic=topic)[1:]) & subset
--- a/hgext3rd/topic/stack.py	Tue Jul 25 02:29:28 2017 +0200
+++ b/hgext3rd/topic/stack.py	Tue Nov 14 23:04:04 2017 +0100
@@ -5,30 +5,203 @@
 from mercurial.i18n import _
 from mercurial import (
     destutil,
+    context,
     error,
     node,
+    phases,
+    obsolete,
+    util,
 )
-from .evolvebits import builddependencies, _orderrevs, _singlesuccessor
+from .evolvebits import builddependencies, _singlesuccessor
 
 short = node.short
 
-def getstack(repo, branch=None, topic=None):
-    # XXX need sorting
-    if topic is not None and branch is not None:
-        raise error.ProgrammingError('both branch and topic specified (not defined yet)')
-    elif topic is not None:
-        trevs = repo.revs("topic(%s) - obsolete()", topic)
-    elif branch is not None:
-        trevs = repo.revs("branch(%s) - public() - obsolete() - topic()", branch)
-    else:
-        raise error.ProgrammingError('neither branch and topic specified (not defined yet)')
-    revs = _orderrevs(repo, trevs)
-    if revs:
-        pt1 = repo[revs[0]].p1()
+# TODO: compat
+
+if not util.safehasattr(context.basectx, 'orphan'):
+    context.basectx.orphan = context.basectx.unstable
+
+if not util.safehasattr(context.basectx, 'isunstable'):
+    context.basectx.isunstable = context.basectx.troubled
+
+def _stackcandidates(repo):
+    """build the smaller set of revs that might be part of a stack.
+
+    The intend is to build something more efficient than what revsets do in
+    this area.
+    """
+    phasecache = repo._phasecache
+    if not phasecache._phasesets:
+        return repo.revs('(not public()) - obsolete()')
+    if any(s is None for s in phasecache._phasesets):
+        return repo.revs('(not public()) - obsolete()')
+
+    result = set()
+    for s in phasecache._phasesets[phases.draft:]:
+        result |= s
+
+    result -= obsolete.getrevs(repo, 'obsolete')
+    return result
+
+class stack(object):
+    """object represent a stack and common logic associated to it."""
+
+    def __init__(self, repo, branch=None, topic=None):
+        self._repo = repo
+        self.branch = branch
+        self.topic = topic
+        self.behinderror = None
+
+        subset = _stackcandidates(repo)
+
+        if topic is not None and branch is not None:
+            raise error.ProgrammingError('both branch and topic specified (not defined yet)')
+        elif topic is not None:
+            trevs = repo.revs("%ld and topic(%s)", subset, topic)
+        elif branch is not None:
+            trevs = repo.revs("%ld and branch(%s) - topic()", subset, branch)
+        else:
+            raise error.ProgrammingError('neither branch and topic specified (not defined yet)')
+        self._revs = trevs
+
+    def __iter__(self):
+        return iter(self.revs)
+
+    def __getitem__(self, index):
+        return self.revs[index]
+
+    def index(self, item):
+        return self.revs.index(item)
+
+    @util.propertycache
+    def _dependencies(self):
+        deps, rdeps = builddependencies(self._repo, self._revs)
+
+        repo = self._repo
+        srcpfunc = repo.changelog.parentrevs
+
+        ### post process to skip over possible gaps in the stack
+        #
+        # For example in the following situation, we need to detect that "t3"
+        # indirectly depends on t2.
+        #
+        #  o t3
+        #  |
+        #  o other
+        #  |
+        #  o t2
+        #  |
+        #  o t1
+
+        pmap = {}
+
+        def pfuncrev(repo, rev):
+            """a special "parent func" that also consider successors"""
+            parents = pmap.get(rev)
+            if parents is None:
+                parents = [repo[_singlesuccessor(repo, repo[p])].rev()
+                           for p in srcpfunc(rev) if 0 <= p]
+                pmap[rev] = parents
+            return parents
+
+        revs = self._revs
+        stackrevs = set(self._revs)
+        for root in [r for r in revs if not deps[r]]:
+            seen = set()
+            stack = [root]
+            while stack:
+                current = stack.pop()
+                for p in pfuncrev(repo, current):
+                    if p in seen:
+                        continue
+                    seen.add(p)
+                    if p in stackrevs:
+                        rdeps[p].add(root)
+                        deps[root].add(p)
+                    elif phases.public < repo[p].phase():
+                        # traverse only if we did not found a proper candidate
+                        stack.append(p)
+
+        return deps, rdeps
+
+    @util.propertycache
+    def revs(self):
+        # some duplication/change from _orderrevs because we use a post
+        # processed dependency graph.
+
+        # Step 1: compute relation of revision with each other
+        dependencies, rdependencies = self._dependencies
+        dependencies = dependencies.copy()
+        rdependencies = rdependencies.copy()
+        # Step 2: Build the ordering
+        # Remove the revisions with no dependency(A) and add them to the ordering.
+        # Removing these revisions leads to new revisions with no dependency (the
+        # one depending on A) that we can remove from the dependency graph and add
+        # to the ordering. We progress in a similar fashion until the ordering is
+        # built
+        solvablerevs = [r for r in sorted(dependencies.keys())
+                        if not dependencies[r]]
+        revs = []
+        while solvablerevs:
+            rev = solvablerevs.pop()
+            for dependent in rdependencies[rev]:
+                dependencies[dependent].remove(rev)
+                if not dependencies[dependent]:
+                    solvablerevs.append(dependent)
+            del dependencies[rev]
+            revs.append(rev)
+
+        revs.extend(sorted(dependencies))
+        # step 3: add t0
+        if revs:
+            pt1 = self._repo[revs[0]].p1()
+        else:
+            pt1 = self._repo['.']
+
         if pt1.obsolete():
-            pt1 = repo[_singlesuccessor(repo, pt1)]
+            pt1 = self._repo[_singlesuccessor(self._repo, pt1)]
         revs.insert(0, pt1.rev())
-    return revs
+        return revs
+
+    @util.propertycache
+    def changesetcount(self):
+        return len(self._revs)
+
+    @util.propertycache
+    def troubledcount(self):
+        return len([r for r in self._revs if self._repo[r].isunstable()])
+
+    @util.propertycache
+    def heads(self):
+        revs = self.revs[1:]
+        deps, rdeps = self._dependencies
+        return [r for r in revs if not rdeps[r]]
+
+    @util.propertycache
+    def behindcount(self):
+        revs = self.revs[1:]
+        deps, rdeps = self._dependencies
+        if revs:
+            minroot = [min(r for r in revs if not deps[r])]
+            try:
+                dest = destutil.destmerge(self._repo, action='rebase',
+                                          sourceset=minroot,
+                                          onheadcheck=False)
+                return len(self._repo.revs("only(%d, %ld)", dest, minroot))
+            except error.NoMergeDestAbort:
+                return 0
+            except error.ManyMergeDestAbort as exc:
+                # XXX we should make it easier for upstream to provide the information
+                self.behinderror = str(exc).split('-', 1)[0].rstrip()
+                return -1
+        return 0
+
+    @util.propertycache
+    def branches(self):
+        branches = sorted(set(self._repo[r].branch() for r in self._revs))
+        if not branches:
+            branches = set([self._repo[None].branch()])
+        return branches
 
 def labelsgen(prefix, labelssuffix):
     """ Takes a label prefix and a list of suffixes. Returns a string of the prefix
@@ -63,6 +236,9 @@
         label = 'topic.active'
 
     data = stackdata(repo, branch=branch, topic=topic)
+    empty = False
+    if data['changesetcount'] == 0:
+        empty = True
     if topic is not None:
         fm.plain(_('### topic: %s')
                  % ui.label(topic, label),
@@ -74,7 +250,7 @@
                      label='topic.stack.summary.headcount.multiple')
             fm.plain(')')
         fm.plain('\n')
-    fm.plain(_('### branch: %s')
+    fm.plain(_('### target: %s (branch)')
              % '+'.join(data['branches']), # XXX handle multi branches
              label='topic.stack.summary.branches')
     if topic is None:
@@ -86,13 +262,17 @@
     else:
         if data['behindcount'] == -1:
             fm.plain(', ')
-            fm.plain('ambigious rebase destination', label='topic.stack.summary.behinderror')
+            fm.plain('ambigious rebase destination - %s' % data['behinderror'],
+                     label='topic.stack.summary.behinderror')
         elif data['behindcount']:
             fm.plain(', ')
             fm.plain('%d behind' % data['behindcount'], label='topic.stack.summary.behindcount')
     fm.plain('\n')
 
-    for idx, r in enumerate(getstack(repo, branch=branch, topic=topic), 0):
+    if empty:
+        fm.plain(_("(stack is empty)\n"))
+
+    for idx, r in enumerate(stack(repo, branch=branch, topic=topic), 0):
         ctx = repo[r]
         # special case for t0, b0 as it's hard to plugin into rest of the logic
         if idx == 0:
@@ -103,9 +283,13 @@
             prev = ctx.rev()
             continue
         p1 = ctx.p1()
+        p2 = ctx.p2()
         if p1.obsolete():
             p1 = repo[_singlesuccessor(repo, p1)]
-        if p1.rev() != prev and p1.node() != node.nullid:
+        if p2.node() != node.nullid:
+            entries.append((idxmap.get(p1.rev()), False, p1))
+            entries.append((idxmap.get(p2.rev()), False, p2))
+        elif p1.rev() != prev and p1.node() != node.nullid:
             entries.append((idxmap.get(p1.rev()), False, p1))
         entries.append((idx, True, ctx))
         idxmap[ctx.rev()] = idx
@@ -114,28 +298,30 @@
     # super crude initial version
     for idx, isentry, ctx in entries[::-1]:
 
+        symbol = None
         states = []
         iscurrentrevision = repo.revs('%d and parents()', ctx.rev())
 
+        if iscurrentrevision:
+            states.append('current')
+            symbol = '@'
+
+        if ctx.orphan():
+            symbol = '$'
+            states.append('unstable')
+
         if not isentry:
             symbol = '^'
             # "base" is kind of a "ghost" entry
-            # skip other label for them (no current, no unstable)
-            states = ['base']
-        elif ctx.unstable():
-            # current revision can be unstable also, so in that case show both
-            # the states and the symbol '@' (issue5553)
-            if iscurrentrevision:
-                states.append('current')
-                symbol = '@'
-            symbol = '$'
-            states.append('unstable')
-        elif iscurrentrevision:
-            states.append('current')
-            symbol = '@'
-        else:
+            states.append('base')
+
+        # none of the above if statments get executed
+        if not symbol:
             symbol = ':'
             states.append('clean')
+
+        states.sort()
+
         fm.startitem()
         fm.data(isentry=isentry)
 
@@ -169,24 +355,11 @@
     :behindcount: number of changeset on rebase destination
     """
     data = {}
-    revs = getstack(repo, branch, topic)[1:]
-    data['changesetcount'] = len(revs)
-    data['troubledcount'] = len([r for r in revs if repo[r].troubled()])
-    deps, rdeps = builddependencies(repo, revs)
-    data['headcount'] = len([r for r in revs if not rdeps[r]])
-    data['behindcount'] = 0
-    if revs:
-        minroot = [min(r for r in revs if not deps[r])]
-        try:
-            dest = destutil.destmerge(repo, action='rebase',
-                                      sourceset=minroot,
-                                      onheadcheck=False)
-            data['behindcount'] = len(repo.revs("only(%d, %ld)", dest,
-                                                minroot))
-        except error.NoMergeDestAbort:
-            data['behindcount'] = 0
-        except error.ManyMergeDestAbort:
-            data['behindcount'] = -1
-    data['branches'] = sorted(set(repo[r].branch() for r in revs))
-
+    current = stack(repo, branch, topic)
+    data['changesetcount'] = current.changesetcount
+    data['troubledcount'] = current.troubledcount
+    data['headcount'] = len(current.heads)
+    data['behindcount'] = current.behindcount
+    data['behinderror'] = current.behinderror
+    data['branches'] = current.branches
     return data
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/hghaveaddon.py	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,14 @@
+import hghave
+
+@hghave.check("docgraph-ext", "Extension to generate graph from repository")
+def docgraph():
+    try:
+        import hgext.docgraph
+        hgext.docgraph.cmdtable # trigger import
+    except ImportError:
+        try:
+            import hgext3rd.docgraph
+            hgext3rd.docgraph.cmdtable # trigger import
+        except ImportError:
+            return False
+    return True
--- a/tests/test-amend.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-amend.t	Tue Nov 14 23:04:04 2017 +0100
@@ -21,13 +21,12 @@
   $ hg amend -d '0 0'
   $ hg debugobsolete
   07f4944404050f47db2e5c5071e0e84e7a27bba9 6a022cbb61d5ba0f03f98ff2d36319dfea1034ae 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  b2e32ffb533cbe1d5759638c0cd4e8abc43b2738 0 {07f4944404050f47db2e5c5071e0e84e7a27bba9} (*) {'ef1': '*', 'user': 'test'} (glob)
   $ hg branch
   foo
   $ hg branches
-  foo                            2:6a022cbb61d5
+  foo                            1:6a022cbb61d5
   $ glog
-  @  2@foo(draft) adda
+  @  1@foo(draft) adda
   
 Test no-op
 
@@ -35,7 +34,7 @@
   nothing changed
   [1]
   $ glog
-  @  2@foo(draft) adda
+  @  1@foo(draft) adda
   
 
 Test forcing the message to the same value, no intermediate revision.
@@ -44,7 +43,7 @@
   nothing changed
   [1]
   $ glog
-  @  2@foo(draft) adda
+  @  1@foo(draft) adda
   
 
 Test collapsing into an existing revision, no intermediate revision.
@@ -66,20 +65,19 @@
   $ hg ci -m reseta
   $ hg debugobsolete
   07f4944404050f47db2e5c5071e0e84e7a27bba9 6a022cbb61d5ba0f03f98ff2d36319dfea1034ae 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  b2e32ffb533cbe1d5759638c0cd4e8abc43b2738 0 {07f4944404050f47db2e5c5071e0e84e7a27bba9} (*) {'ef1': '*', 'user': 'test'} (glob)
   $ hg phase 2
   2: draft
   $ glog
-  @  4@foo(draft) reseta
+  @  3@foo(draft) reseta
   |
-  o  3@foo(draft) changea
+  o  2@foo(draft) changea
   |
-  o  2@foo(draft) adda
+  o  1@foo(draft) adda
   
 Specify precise commit date with -d
   $ hg amend -d '2001-02-03 04:05:06 +0700'
   $ hg parents --template '{rev}  {date|date}\n'
-  5  Sat Feb 03 04:05:06 2001 +0700
+  4  Sat Feb 03 04:05:06 2001 +0700
 
 Specify "now" as commit date with -D
   $ before=`date +%s`
@@ -88,13 +86,13 @@
   $ after=`date +%s`
   $ (echo $before ; echo $commit; echo $after) | sort -k1 -n -s
   \d+ (re)
-  \d+ 0 rev6 (re)
+  \d+ 0 rev5 (re)
   \d+ (re)
 
 Specify current user as committer with -U
   $ HGUSER=newbie hg amend -U
   $ hg parents --template '{rev}  {author}\n'
-  7  newbie
+  6  newbie
 
 Check that --logfile works
   $ echo "logfile message" > logfile.txt
@@ -109,7 +107,7 @@
   (use 'hg config --edit' to set your username)
   [255]
   $ hg sum
-  parent: 8:* tip (glob)
+  parent: 7:* tip (glob)
    logfile message
   branch: foo
   commit: 1 unknown (clean)
--- a/tests/test-discovery-obshashrange.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-discovery-obshashrange.t	Tue Nov 14 23:04:04 2017 +0100
@@ -31,6 +31,7 @@
   $ cd server
   $ hg debugbuilddag '.+7'
   $ hg blackbox
+  * @0000000000000000000000000000000000000000 (*)> init server exited 0 after *.?? seconds (glob)
   * @0000000000000000000000000000000000000000 (*)> serve --stdio (glob)
   * @0000000000000000000000000000000000000000 (*)> -R server serve --stdio exited 0 after *.?? seconds (glob)
   * @0000000000000000000000000000000000000000 (*)> debugbuilddag .+7 (glob)
@@ -136,6 +137,7 @@
   adding file changes
   added 5 changesets with 0 changes to 0 files
   3 new obsolescence markers
+  new changesets 1ea73414a91b:bebd167eb94d
   (run 'hg update' to get a working copy)
   $ hg -R ../server blackbox
   * @0000000000000000000000000000000000000000 (*)> debugobshashrange --subranges --rev tip (glob)
@@ -151,6 +153,7 @@
   cccccccccccccccccccccccccccccccccccccccc bebd167eb94d257ace0e814aeb98e6972ed2970d 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
   $ rm ../server/.hg/blackbox.log
   $ hg blackbox
+  * @0000000000000000000000000000000000000000 (*)> clone 'ssh://user@dummy/server' client exited 0 after *.?? seconds (glob)
   * @0000000000000000000000000000000000000000 (*)> pull --rev 4 (glob)
   * @0000000000000000000000000000000000000000 (*)> updated stablerange cache in *.???? seconds (glob)
   * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (5r, 3o) (glob)
@@ -177,11 +180,11 @@
   $ hg debugobsolete ffffffffffffffffffffffffffffffffffffffff `getid '.'`
   $ hg push -f --debug
   pushing to ssh://user@dummy/server
-  running python "*/dummyssh" user@dummy 'hg -R server serve --stdio' (glob)
+  running python "*/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob)
   sending hello command
   sending between command
-  remote: 516
-  remote: capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_obshashrange_v0 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch branchmap bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Aobsmarkers%3DV0%2CV1%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps changegroupsubset getbundle known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
+  remote: 483
+  remote: capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_obshashrange_v0 batch * (glob)
   remote: 1
   preparing listkeys for "phases"
   sending listkeys command
@@ -215,9 +218,9 @@
   45f8b879de922f6a6e620ba04205730335b6fc7e
   sending unbundle command
   bundle2-output-bundle: "HG20", 4 parts total
-  bundle2-output-part: "replycaps" 172 bytes payload
+  bundle2-output-part: "replycaps" 185 bytes payload
   bundle2-output-part: "changegroup" (params: 1 mandatory) streamed payload
-  bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
+  bundle2-output-part: "phase-heads" 24 bytes payload
   bundle2-output-part: "obsmarkers" streamed payload
   remote: adding changesets
   remote: adding manifests
@@ -226,9 +229,8 @@
   remote: 1 new obsolescence markers
   bundle2-input-bundle: no-transaction
   bundle2-input-part: "reply:changegroup" (advisory) (params: 0 advisory) supported
-  bundle2-input-part: "reply:pushkey" (params: 0 advisory) supported
   bundle2-input-part: "reply:obsmarkers" (params: 0 advisory) supported
-  bundle2-input-bundle: 2 parts total
+  bundle2-input-bundle: 1 parts total
   preparing listkeys for "phases"
   sending listkeys command
   received listkey for "phases": 58 bytes
@@ -369,6 +371,7 @@
   adding file changes
   added 2 changesets with 0 changes to 0 files (+1 heads)
   3 new obsolescence markers
+  new changesets c8d03c1b5e94:f69452c5b1af
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
   $ hg -R ../server blackbox
@@ -546,6 +549,7 @@
   adding file changes
   added 1 changesets with 0 changes to 0 files
   1 new obsolescence markers
+  new changesets 4de32a90b66c
   (run 'hg update' to get a working copy)
   $ hg rollback
   repository tip rolled back to revision 7 (undo pull)
@@ -596,6 +600,7 @@
   adding file changes
   added 1 changesets with 0 changes to 0 files
   1 new obsolescence markers
+  new changesets 4de32a90b66c
   (run 'hg update' to get a working copy)
   $ hg blackbox
   * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' (glob)
@@ -687,6 +692,7 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
   2 new obsolescence markers
+  new changesets 45f8b879de92
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg log -G
   o  8 45f8b879de92 foo tip
--- a/tests/test-divergent.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-divergent.t	Tue Nov 14 23:04:04 2017 +0100
@@ -45,15 +45,15 @@
   1 changesets pruned
   $ hg prune -s "desc(bdivergent2)" "desc(_b)" --hidden
   1 changesets pruned
-  2 new divergent changesets
+  2 new content-divergent changesets
   $ hg log -G
-  @  3:e708fd28d5cf@default(draft) add bdivergent2 [divergent]
+  @  3:e708fd28d5cf@default(draft) add bdivergent2 [content-divergent]
   |
-  | o  2:c2f698071cba@default(draft) add bdivergent1 [divergent]
+  | o  2:c2f698071cba@default(draft) add bdivergent1 [content-divergent]
   |/
   o  0:135f39f4bd78@default(draft) add _a []
   
-  $ hg evolve --all --any --divergent
+  $ hg evolve --all --any --content-divergent
   merge:[2] add bdivergent1
   with: [3] add bdivergent2
   base: [1] add _b
@@ -62,7 +62,7 @@
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   working directory is now at c26f1d3baed2
   $ hg log -G
-  @  5:c26f1d3baed2@default(draft) add bdivergent1 []
+  @  4:c26f1d3baed2@default(draft) add bdivergent1 []
   |
   o  0:135f39f4bd78@default(draft) add _a []
   
@@ -88,24 +88,25 @@
   1 changesets pruned
   $ hg prune -s "desc(cdivergent2)" "desc(_c)" --hidden
   1 changesets pruned
-  2 new divergent changesets
+  2 new content-divergent changesets
   $ hg log -G
-  @  8:0a768ef678d9@default(draft) cdivergent2 [divergent]
+  @  7:0a768ef678d9@default(draft) cdivergent2 [content-divergent]
   |
-  | o  7:26c7705fee96@default(draft) add cdivergent1 [divergent]
+  | o  6:26c7705fee96@default(draft) add cdivergent1 [content-divergent]
   |/
-  | o  5:c26f1d3baed2@default(draft) add bdivergent1 []
+  | o  4:c26f1d3baed2@default(draft) add bdivergent1 []
   |/
   o  0:135f39f4bd78@default(draft) add _a []
   
-  $ hg evolve --all --any --divergent
-  merge:[7] add cdivergent1
-  with: [8] cdivergent2
-  base: [6] add _c
+  $ hg evolve --all --any --content-divergent
+  merge:[6] add cdivergent1
+  with: [7] cdivergent2
+  base: [5] add _c
   updating to "local" conflict
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  working directory is now at 6602ff5a79dc
+  nothing changed
+  working directory is now at 26c7705fee96
 
 Test None docstring issue of evolve divergent, which caused hg crush
 
@@ -124,11 +125,11 @@
   1 changesets pruned
   $ hg prune -s "desc(bdivergent2)" "desc(_b)" --hidden
   1 changesets pruned
-  2 new divergent changesets
+  2 new content-divergent changesets
   $ hg log -G
-  @  3:e708fd28d5cf@default(draft) add bdivergent2 [divergent]
+  @  3:e708fd28d5cf@default(draft) add bdivergent2 [content-divergent]
   |
-  | o  2:c2f698071cba@default(draft) add bdivergent1 [divergent]
+  | o  2:c2f698071cba@default(draft) add bdivergent1 [content-divergent]
   |/
   o  0:135f39f4bd78@default(draft) add _a []
   
@@ -145,9 +146,9 @@
   > EOF
   $ hg evolve --all
   nothing to evolve on current working copy parent
-  (do you want to use --divergent)
+  (do you want to use --content-divergent)
   [2]
-  $ hg evolve --divergent
+  $ hg evolve --content-divergent
   merge:[3] add bdivergent2
   with: [2] add bdivergent1
   base: [1] add _b
--- a/tests/test-drop.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-drop.t	Tue Nov 14 23:04:04 2017 +0100
@@ -178,7 +178,7 @@
   $ hg commit --amend
   $ summary
   ============ graph ==============
-  @  changeset:   4:a2c06c884bfe
+  @  changeset:   3:a2c06c884bfe
   |  tag:         tip
   |  parent:      1:19509a42b0d0
   |  user:        test
@@ -196,23 +196,17 @@
      summary:     add base
   
   ============ hidden =============
-  @  changeset:   4:a2c06c884bfe
+  @  changeset:   3:a2c06c884bfe
   |  tag:         tip
   |  parent:      1:19509a42b0d0
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     add child
   |
-  | x  changeset:   3:87ea30a976fd
-  | |  user:        test
-  | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  obsolete:    pruned
-  | |  summary:     temporary amend commit for 34b6c051bf1f
-  | |
   | x  changeset:   2:34b6c051bf1f
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as a2c06c884bfe
+  |    obsolete:    amended using amend as 3:a2c06c884bfe
   |    summary:     add child
   |
   o  changeset:   1:19509a42b0d0
@@ -227,7 +221,6 @@
   
   ============ obsmark ============
   34b6c051bf1f78db6aef400776de5cb964470207 a2c06c884bfe53d3840026248bd8a7eafa152df8 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  87ea30a976fdf235bf096f04899cb02a903873e2 0 {34b6c051bf1f78db6aef400776de5cb964470207} (*) {'ef1': '*', 'user': 'test'} (glob)
   $ hg drop .
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   working directory now at 19509a42b0d0
--- a/tests/test-evolve-bumped.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-evolve-bumped.t	Tue Nov 14 23:04:04 2017 +0100
@@ -49,6 +49,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets 4d1169d82e47
   (run 'hg update' to get a working copy)
   $ hg log -r 'draft()'
   1:4d1169d82e47@default(draft) modify a
@@ -67,9 +68,9 @@
   pulling from ../public
   searching for changes
   no changes found
-  1 new bumped changesets
+  1 new phase-divergent changesets
 
-  $ hg evolve -a -A --bumped
+  $ hg evolve -a -A --phase-divergent
   recreate:[2] tweak a
   atop:[1] modify a
   computing new diff
@@ -105,7 +106,7 @@
   $ hg commit -m "merge"
   $ hg commit --amend -m "New message"
   $ hg phase --public 551127da2a8a --hidden
-  1 new bumped changesets
+  1 new phase-divergent changesets
   $ hg log -G
   @    7:b28e84916d8c@default(draft) New message
   |\
@@ -121,5 +122,5 @@
   |
   o  0:d3873e73d99e@default(public) init
   
-  $ hg evolve --all --bumped
+  $ hg evolve --all --phase-divergent
   skipping b28e84916d8c : we do not handle merge yet
--- a/tests/test-evolve-cycles.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-evolve-cycles.t	Tue Nov 14 23:04:04 2017 +0100
@@ -50,7 +50,7 @@
 Create a cycle
   $ hg prune -s "desc(B)" "desc(A)"
   1 changesets pruned
-  2 new unstable changesets
+  2 new orphan changesets
   $ hg prune -s "desc(C)" "desc(B)"
   1 changesets pruned
   $ hg prune -s "desc(A)" "desc(C)"
@@ -62,19 +62,19 @@
   |  tag:         tip
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  obsolete:    rewritten as 2a34000d3544
+  |  obsolete:    rewritten as 1:2a34000d3544
   |  summary:     C
   |
   x  changeset:   2:c473644ee0e9
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  obsolete:    rewritten as a8df460dbbfe
+  |  obsolete:    rewritten as 3:a8df460dbbfe
   |  summary:     B
   |
   @  changeset:   1:2a34000d3544
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  obsolete:    rewritten as c473644ee0e9
+  |  obsolete:    rewritten as 2:c473644ee0e9
   |  summary:     A
   |
   o  changeset:   0:ea207398892e
@@ -89,48 +89,48 @@
 
   $ hg obslog "desc(A)" --hidden
   @  2a34000d3544 (1) A
-  |    rewritten(description, parent, content) by test (*) as c473644ee0e9 (glob)
+  |    rewritten(description, parent, content) as c473644ee0e9 by test (*) (glob)
   |
   x  a8df460dbbfe (3) C
-  |    rewritten(description, parent, content) by test (*) as 2a34000d3544 (glob)
+  |    rewritten(description, parent, content) as 2a34000d3544 by test (*) (glob)
   |
   x  c473644ee0e9 (2) B
-  |    rewritten(description, parent, content) by test (*) as a8df460dbbfe (glob)
+  |    rewritten(description, parent, content) as a8df460dbbfe by test (*) (glob)
   |
 
   $ hg obslog "desc(B)" --hidden
   @  2a34000d3544 (1) A
-  |    rewritten(description, parent, content) by test (*) as c473644ee0e9 (glob)
+  |    rewritten(description, parent, content) as c473644ee0e9 by test (*) (glob)
   |
   x  a8df460dbbfe (3) C
-  |    rewritten(description, parent, content) by test (*) as 2a34000d3544 (glob)
+  |    rewritten(description, parent, content) as 2a34000d3544 by test (*) (glob)
   |
   x  c473644ee0e9 (2) B
-  |    rewritten(description, parent, content) by test (*) as a8df460dbbfe (glob)
+  |    rewritten(description, parent, content) as a8df460dbbfe by test (*) (glob)
   |
 
   $ hg obslog "desc(C)" --hidden
   @  2a34000d3544 (1) A
-  |    rewritten(description, parent, content) by test (*) as c473644ee0e9 (glob)
+  |    rewritten(description, parent, content) as c473644ee0e9 by test (*) (glob)
   |
   x  a8df460dbbfe (3) C
-  |    rewritten(description, parent, content) by test (*) as 2a34000d3544 (glob)
+  |    rewritten(description, parent, content) as 2a34000d3544 by test (*) (glob)
   |
   x  c473644ee0e9 (2) B
-  |    rewritten(description, parent, content) by test (*) as a8df460dbbfe (glob)
+  |    rewritten(description, parent, content) as a8df460dbbfe by test (*) (glob)
   |
 
 Check that all option don't crash on a cycle either
 
   $ hg obslog "desc(C)" --hidden --all
   @  2a34000d3544 (1) A
-  |    rewritten(description, parent, content) by test (*) as c473644ee0e9 (glob)
+  |    rewritten(description, parent, content) as c473644ee0e9 by test (*) (glob)
   |
   x  a8df460dbbfe (3) C
-  |    rewritten(description, parent, content) by test (*) as 2a34000d3544 (glob)
+  |    rewritten(description, parent, content) as 2a34000d3544 by test (*) (glob)
   |
   x  c473644ee0e9 (2) B
-  |    rewritten(description, parent, content) by test (*) as a8df460dbbfe (glob)
+  |    rewritten(description, parent, content) as a8df460dbbfe by test (*) (glob)
   |
 
 Test with multiple cyles
@@ -188,7 +188,7 @@
 Create a first cycle
   $ hg prune -s "desc(B)" "desc(A)"
   1 changesets pruned
-  5 new unstable changesets
+  5 new orphan changesets
   $ hg prune -s "desc(C)" "desc(B)"
   1 changesets pruned
   $ hg prune --split -s "desc(A)" -s "desc(D)" "desc(C)"
@@ -207,37 +207,37 @@
   |  tag:         tip
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  obsolete:    rewritten as 868d2e0eb19c
+  |  obsolete:    rewritten as 4:868d2e0eb19c
   |  summary:     F
   |
   x  changeset:   5:0da815c333f6
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  obsolete:    rewritten as d9f908fde1a1
+  |  obsolete:    rewritten as 6:d9f908fde1a1
   |  summary:     E
   |
   @  changeset:   4:868d2e0eb19c
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  obsolete:    rewritten as 0da815c333f6
+  |  obsolete:    rewritten as 5:0da815c333f6
   |  summary:     D
   |
   x  changeset:   3:a8df460dbbfe
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  obsolete:    split as 2a34000d3544, 868d2e0eb19c
+  |  obsolete:    split as 1:2a34000d3544, 4:868d2e0eb19c
   |  summary:     C
   |
   x  changeset:   2:c473644ee0e9
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  obsolete:    rewritten as a8df460dbbfe
+  |  obsolete:    rewritten as 3:a8df460dbbfe
   |  summary:     B
   |
   x  changeset:   1:2a34000d3544
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  obsolete:    rewritten as c473644ee0e9
+  |  obsolete:    rewritten as 2:c473644ee0e9
   |  summary:     A
   |
   o  changeset:   0:ea207398892e
@@ -252,185 +252,185 @@
 
   $ hg obslog "desc(D)" --hidden
   x  0da815c333f6 (5) E
-  |    rewritten(description, parent, content) by test (*) as d9f908fde1a1 (glob)
+  |    rewritten(description, parent, content) as d9f908fde1a1 by test (*) (glob)
   |
   @    868d2e0eb19c (4) D
-  |\     rewritten(description, parent, content) by test (*) as 0da815c333f6 (glob)
+  |\     rewritten(description, parent, content) as 0da815c333f6 by test (*) (glob)
   | |
   | x  d9f908fde1a1 (6) F
-  | |    rewritten(description, parent, content) by test (*) as 868d2e0eb19c (glob)
+  | |    rewritten(description, parent, content) as 868d2e0eb19c by test (*) (glob)
   | |
   +---x  2a34000d3544 (1) A
-  | |      rewritten(description, parent, content) by test (*) as c473644ee0e9 (glob)
+  | |      rewritten(description, parent, content) as c473644ee0e9 by test (*) (glob)
   | |
   x |  a8df460dbbfe (3) C
-  | |    rewritten(description, parent, content) by test (*) as 2a34000d3544, 868d2e0eb19c (glob)
+  | |    rewritten(description, parent, content) as 2a34000d3544, 868d2e0eb19c by test (*) (glob)
   | |
   x |  c473644ee0e9 (2) B
-  | |    rewritten(description, parent, content) by test (*) as a8df460dbbfe (glob)
+  | |    rewritten(description, parent, content) as a8df460dbbfe by test (*) (glob)
   | |
 Check that all option don't crash either on a cycle
   $ hg obslog --all --hidden "desc(F)"
   x  0da815c333f6 (5) E
-  |    rewritten(description, parent, content) by test (*) as d9f908fde1a1 (glob)
+  |    rewritten(description, parent, content) as d9f908fde1a1 by test (*) (glob)
   |
   @    868d2e0eb19c (4) D
-  |\     rewritten(description, parent, content) by test (*) as 0da815c333f6 (glob)
+  |\     rewritten(description, parent, content) as 0da815c333f6 by test (*) (glob)
   | |
   | x  d9f908fde1a1 (6) F
-  | |    rewritten(description, parent, content) by test (*) as 868d2e0eb19c (glob)
+  | |    rewritten(description, parent, content) as 868d2e0eb19c by test (*) (glob)
   | |
   +---x  2a34000d3544 (1) A
-  | |      rewritten(description, parent, content) by test (*) as c473644ee0e9 (glob)
+  | |      rewritten(description, parent, content) as c473644ee0e9 by test (*) (glob)
   | |
   x |  a8df460dbbfe (3) C
-  | |    rewritten(description, parent, content) by test (*) as 2a34000d3544, 868d2e0eb19c (glob)
+  | |    rewritten(description, parent, content) as 2a34000d3544, 868d2e0eb19c by test (*) (glob)
   | |
   x |  c473644ee0e9 (2) B
-  | |    rewritten(description, parent, content) by test (*) as a8df460dbbfe (glob)
+  | |    rewritten(description, parent, content) as a8df460dbbfe by test (*) (glob)
   | |
 Check the json output is valid in this case
 
   $ hg obslog "desc(D)" --hidden --no-graph -Tjson | python -m json.tool
   [
       {
-          "debugobshistory.markers": [
+          "markers": [
               {
-                  "debugobshistory.effect": [
+                  "date": [
+                      *, (glob)
+                      0
+                  ],
+                  "effect": [
                       "description",
                       "parent",
                       "content"
                   ],
-                  "debugobshistory.marker_date": [
+                  "succnodes": [
+                      "0da815c333f6"
+                  ],
+                  "user": "test",
+                  "verb": "rewritten"
+              }
+          ],
+          "node": "868d2e0eb19c",
+          "rev": 4,
+          "shortdescription": "D"
+      },
+      {
+          "markers": [
+              {
+                  "date": [
                       *, (glob)
                       0
                   ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
-                      "0da815c333f6"
-                  ],
-                  "debugobshistory.verb": "rewritten"
-              }
-          ],
-          "debugobshistory.node": "868d2e0eb19c",
-          "debugobshistory.rev": 4,
-          "debugobshistory.shortdescription": "D"
-      },
-      {
-          "debugobshistory.markers": [
-              {
-                  "debugobshistory.effect": [
+                  "effect": [
                       "description",
                       "parent",
                       "content"
                   ],
-                  "debugobshistory.marker_date": [
+                  "succnodes": [
+                      "868d2e0eb19c"
+                  ],
+                  "user": "test",
+                  "verb": "rewritten"
+              }
+          ],
+          "node": "d9f908fde1a1",
+          "rev": 6,
+          "shortdescription": "F"
+      },
+      {
+          "markers": [
+              {
+                  "date": [
                       *, (glob)
                       0
                   ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
-                      "868d2e0eb19c"
-                  ],
-                  "debugobshistory.verb": "rewritten"
-              }
-          ],
-          "debugobshistory.node": "d9f908fde1a1",
-          "debugobshistory.rev": 6,
-          "debugobshistory.shortdescription": "F"
-      },
-      {
-          "debugobshistory.markers": [
-              {
-                  "debugobshistory.effect": [
+                  "effect": [
                       "description",
                       "parent",
                       "content"
                   ],
-                  "debugobshistory.marker_date": [
+                  "succnodes": [
+                      "d9f908fde1a1"
+                  ],
+                  "user": "test",
+                  "verb": "rewritten"
+              }
+          ],
+          "node": "0da815c333f6",
+          "rev": 5,
+          "shortdescription": "E"
+      },
+      {
+          "markers": [
+              {
+                  "date": [
                       *, (glob)
                       0
                   ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
-                      "d9f908fde1a1"
-                  ],
-                  "debugobshistory.verb": "rewritten"
-              }
-          ],
-          "debugobshistory.node": "0da815c333f6",
-          "debugobshistory.rev": 5,
-          "debugobshistory.shortdescription": "E"
-      },
-      {
-          "debugobshistory.markers": [
-              {
-                  "debugobshistory.effect": [
+                  "effect": [
                       "description",
                       "parent",
                       "content"
                   ],
-                  "debugobshistory.marker_date": [
-                      *, (glob)
-                      0
-                  ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "succnodes": [
                       "2a34000d3544",
                       "868d2e0eb19c"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               }
           ],
-          "debugobshistory.node": "a8df460dbbfe",
-          "debugobshistory.rev": 3,
-          "debugobshistory.shortdescription": "C"
+          "node": "a8df460dbbfe",
+          "rev": 3,
+          "shortdescription": "C"
       },
       {
-          "debugobshistory.markers": [
+          "markers": [
               {
-                  "debugobshistory.effect": [
+                  "date": [
+                      *, (glob)
+                      0
+                  ],
+                  "effect": [
                       "description",
                       "parent",
                       "content"
                   ],
-                  "debugobshistory.marker_date": [
+                  "succnodes": [
+                      "a8df460dbbfe"
+                  ],
+                  "user": "test",
+                  "verb": "rewritten"
+              }
+          ],
+          "node": "c473644ee0e9",
+          "rev": 2,
+          "shortdescription": "B"
+      },
+      {
+          "markers": [
+              {
+                  "date": [
                       *, (glob)
                       0
                   ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
-                      "a8df460dbbfe"
-                  ],
-                  "debugobshistory.verb": "rewritten"
-              }
-          ],
-          "debugobshistory.node": "c473644ee0e9",
-          "debugobshistory.rev": 2,
-          "debugobshistory.shortdescription": "B"
-      },
-      {
-          "debugobshistory.markers": [
-              {
-                  "debugobshistory.effect": [
+                  "effect": [
                       "description",
                       "parent",
                       "content"
                   ],
-                  "debugobshistory.marker_date": [
-                      *, (glob)
-                      0
-                  ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "succnodes": [
                       "c473644ee0e9"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               }
           ],
-          "debugobshistory.node": "2a34000d3544",
-          "debugobshistory.rev": 1,
-          "debugobshistory.shortdescription": "A"
+          "node": "2a34000d3544",
+          "rev": 1,
+          "shortdescription": "A"
       }
   ]
 
--- a/tests/test-evolve-effectflags.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-evolve-effectflags.t	Tue Nov 14 23:04:04 2017 +0100
@@ -29,12 +29,19 @@
 check result
 
   $ hg debugobsolete --rev .
-  471f378eab4c5e25f6c77f785b27c936efb22874 fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e 0 (*) {'ef1': '1', 'user': 'test'} (glob)
+  471f378eab4c5e25f6c77f785b27c936efb22874 fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '1', 'operation': 'amend', 'user': 'test'}
   $ hg obslog .
   @  fdf9bde5129a (2) A1
   |
   x  471f378eab4c (1) A0
-       rewritten(description) by test (*) as fdf9bde5129a (glob)
+       rewritten(description) as fdf9bde5129a by test (*) (glob)
+  
+  $ hg log --hidden -r "desc(A0)"
+  changeset:   1:471f378eab4c
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  obsolete:    reworded using amend as 2:fdf9bde5129a
+  summary:     A0
   
 
 amend touching the user only
@@ -46,12 +53,19 @@
 check result
 
   $ hg debugobsolete --rev .
-  ef4a313b1e0ade55718395d80e6b88c5ccd875eb 5485c92d34330dac9d7a63dc07e1e3373835b964 0 (*) {'ef1': '16', 'user': 'test'} (glob)
+  ef4a313b1e0ade55718395d80e6b88c5ccd875eb 5485c92d34330dac9d7a63dc07e1e3373835b964 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '16', 'operation': 'amend', 'user': 'test'}
   $ hg obslog .
   @  5485c92d3433 (4) B0
   |
   x  ef4a313b1e0a (3) B0
-       rewritten(user) by test (*) as 5485c92d3433 (glob)
+       rewritten(user) as 5485c92d3433 by test (*) (glob)
+  
+  $ hg log --hidden -r "ef4a313b1e0a"
+  changeset:   3:ef4a313b1e0a
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  obsolete:    reauthored using amend as 4:5485c92d3433
+  summary:     B0
   
 
 amend touching the date only
@@ -63,12 +77,19 @@
 check result
 
   $ hg debugobsolete --rev .
-  2ef0680ff45038ac28c9f1ff3644341f54487280 4dd84345082e9e5291c2e6b3f335bbf8bf389378 0 (*) {'ef1': '32', 'user': 'test'} (glob)
+  2ef0680ff45038ac28c9f1ff3644341f54487280 4dd84345082e9e5291c2e6b3f335bbf8bf389378 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '32', 'operation': 'amend', 'user': 'test'}
   $ hg obslog .
   @  4dd84345082e (6) B1
   |
   x  2ef0680ff450 (5) B1
-       rewritten(date) by test (*) as 4dd84345082e (glob)
+       rewritten(date) as 4dd84345082e by test (*) (glob)
+  
+  $ hg log --hidden -r "2ef0680ff450"
+  changeset:   5:2ef0680ff450
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  obsolete:    date-changed using amend as 6:4dd84345082e
+  summary:     B1
   
 
 amend touching the branch only
@@ -83,13 +104,19 @@
 check result
 
   $ hg debugobsolete --rev .
-  4d1430a201c1ffbd8465dec75edd4a691a2d97ec 0 {bd3db8264ceebf1966319f5df3be7aac6acd1a8e} (*) {'ef1': '0', 'user': 'test'} (glob)
-  bd3db8264ceebf1966319f5df3be7aac6acd1a8e 14a01456e0574f0e0a0b15b2345486a6364a8d79 0 (*) {'ef1': '64', 'user': 'test'} (glob)
+  bd3db8264ceebf1966319f5df3be7aac6acd1a8e 14a01456e0574f0e0a0b15b2345486a6364a8d79 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '64', 'operation': 'amend', 'user': 'test'}
   $ hg obslog .
-  @  14a01456e057 (9) B2
+  @  14a01456e057 (8) B2
   |
   x  bd3db8264cee (7) B2
-       rewritten(branch) by test (*) as 14a01456e057 (glob)
+       rewritten(branch) as 14a01456e057 by test (*) (glob)
+  
+  $ hg log --hidden -r "bd3db8264cee"
+  changeset:   7:bd3db8264cee
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  obsolete:    branch-changed using amend as 8:14a01456e057
+  summary:     B2
   
 
   $ hg up default
@@ -101,17 +128,24 @@
   $ mkcommit C0
   $ mkcommit D0
   $ hg rebase -r . -d 'desc(B0)'
-  rebasing 11:c85eff83a034 "D0" (tip)
+  rebasing 10:c85eff83a034 "D0" (tip)
 
 check result
 
   $ hg debugobsolete --rev .
-  c85eff83a0340efd9da52b806a94c350222f3371 da86aa2f19a30d6686b15cae15c7b6c908ec9699 0 (*) {'ef1': '4', 'user': 'test'} (glob)
+  c85eff83a0340efd9da52b806a94c350222f3371 da86aa2f19a30d6686b15cae15c7b6c908ec9699 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '4', 'operation': 'rebase', 'user': 'test'}
   $ hg obslog .
-  @  da86aa2f19a3 (12) D0
+  @  da86aa2f19a3 (11) D0
   |
-  x  c85eff83a034 (11) D0
-       rewritten(parent) by test (*) as da86aa2f19a3 (glob)
+  x  c85eff83a034 (10) D0
+       rewritten(parent) as da86aa2f19a3 by test (*) (glob)
+  
+  $ hg log --hidden -r "c85eff83a034"
+  changeset:   10:c85eff83a034
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  obsolete:    rebased using rebase as 11:da86aa2f19a3
+  summary:     D0
   
 
 amend touching the diff
@@ -124,13 +158,19 @@
 check result
 
   $ hg debugobsolete --rev .
-  d6f4d8b8d3c8cde990f13915bced7f92ce1cc54f 0 {ebfe0333e0d96f68a917afd97c0a0af87f1c3b5f} (*) {'ef1': '0', 'user': 'test'} (glob)
-  ebfe0333e0d96f68a917afd97c0a0af87f1c3b5f 75781fdbdbf58a987516b00c980bccda1e9ae588 0 (*) {'ef1': '8', 'user': 'test'} (glob)
+  ebfe0333e0d96f68a917afd97c0a0af87f1c3b5f 75781fdbdbf58a987516b00c980bccda1e9ae588 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'}
   $ hg obslog .
-  @  75781fdbdbf5 (15) E0
+  @  75781fdbdbf5 (13) E0
   |
-  x  ebfe0333e0d9 (13) E0
-       rewritten(content) by test (*) as 75781fdbdbf5 (glob)
+  x  ebfe0333e0d9 (12) E0
+       rewritten(content) as 75781fdbdbf5 by test (*) (glob)
+  
+  $ hg log --hidden -r "ebfe0333e0d9"
+  changeset:   12:ebfe0333e0d9
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  obsolete:    amended using amend as 13:75781fdbdbf5
+  summary:     E0
   
 
 amend with multiple effect (desc and meta)
@@ -144,14 +184,21 @@
 check result
 
   $ hg debugobsolete --rev .
-  3b12912003b4e7aa6df6cded86255006c3c29d27 0 {fad47e5bd78e6aa4db1b5a0a1751bc12563655ff} (*) {'ef1': '0', 'user': 'test'} (glob)
-  fad47e5bd78e6aa4db1b5a0a1751bc12563655ff a94e0fd5f1c81d969381a76eb0d37ce499a44fae 0 (*) {'ef1': '113', 'user': 'test'} (glob)
+  fad47e5bd78e6aa4db1b5a0a1751bc12563655ff a94e0fd5f1c81d969381a76eb0d37ce499a44fae 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '113', 'operation': 'amend', 'user': 'test'}
   $ hg obslog .
-  @  a94e0fd5f1c8 (18) F1
+  @  a94e0fd5f1c8 (15) F1
   |
-  x  fad47e5bd78e (16) F0
-       rewritten(description, user, date, branch) by test (*) as a94e0fd5f1c8 (glob)
+  x  fad47e5bd78e (14) F0
+       rewritten(description, user, date, branch) as a94e0fd5f1c8 by test (*) (glob)
   
+  $ hg log --hidden -r "fad47e5bd78e"
+  changeset:   14:fad47e5bd78e
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  obsolete:    rewritten using amend as 15:a94e0fd5f1c8
+  summary:     F0
+  
+
 rebase not touching the diff
 ----------------------------
 
@@ -191,13 +238,21 @@
   $ hg commit -m "H2"
   created new head
   $ hg rebase -s "desc(H1)" -d "desc(H2)" -t :merge3
-  rebasing 20:b57fed8d8322 "H1"
+  rebasing 17:b57fed8d8322 "H1"
   merging H0
   $ hg obslog tip
-  o  e509e2eb3df5 (22) H1
+  o  e509e2eb3df5 (19) H1
   |
-  x  b57fed8d8322 (20) H1
-       rewritten(parent) by test (*) as e509e2eb3df5 (glob)
+  x  b57fed8d8322 (17) H1
+       rewritten(parent) as e509e2eb3df5 by test (*) (glob)
+  
+  $ hg log --hidden -r "b57fed8d8322"
+  changeset:   17:b57fed8d8322
+  branch:      my-other-branch
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  obsolete:    rebased using rebase as 19:e509e2eb3df5
+  summary:     H1
   
 amend closing the branch should be detected as meta change
 ----------------------------------------------------------
@@ -211,8 +266,16 @@
 check result
 
   $ hg obslog .
-  @  12c6238b5e37 (26) I0
+  @  12c6238b5e37 (22) I0
   |
-  x  2f599e54c1c6 (24) I0
-       rewritten(meta) by test (*) as 12c6238b5e37 (glob)
+  x  2f599e54c1c6 (21) I0
+       rewritten(meta) as 12c6238b5e37 by test (*) (glob)
   
+  $ hg log --hidden -r "2f599e54c1c6"
+  changeset:   21:2f599e54c1c6
+  branch:      closedbranch
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  obsolete:    meta-changed using amend as 22:12c6238b5e37
+  summary:     I0
+  
--- a/tests/test-evolve-list.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-evolve-list.t	Tue Nov 14 23:04:04 2017 +0100
@@ -17,13 +17,13 @@
   $ hg up 0
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ echo a >> a && hg ci --amend -m a
-  2 new unstable changesets
+  2 new orphan changesets
   $ hg evolve --list
   d2ae7f538514: b
     unstable: cb9a9f314b8b (obsolete parent)
   
   177f92b77385: c
-    unstable: d2ae7f538514 (unstable parent)
+    orphan: d2ae7f538514 (orphan parent)
   
   $ cd ..
 
@@ -34,7 +34,7 @@
   adding a
   $ echo b > b && hg ci --amend -m ab
   $ hg phase --public --rev 0 --hidden
-  1 new bumped changesets
+  1 new phase-divergent changesets
   $ hg evolve --list
   88cc282e27fc: ab
     bumped: cb9a9f314b8b (immutable precursor)
@@ -64,7 +64,7 @@
   rebasing 1:d2ae7f538514 "b"
   $ hg rebase -s 1 -d 3 --hidden --config experimental.allowdivergence=True
   rebasing 1:d2ae7f538514 "b"
-  2 new divergent changesets
+  2 new content-divergent changesets
   $ hg evolve --list
   c882616e9d84: b
     divergent: a922b3733e98 (draft) (precursor d2ae7f538514)
--- a/tests/test-evolve-obshistory-complex.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-evolve-obshistory-complex.t	Tue Nov 14 23:04:04 2017 +0100
@@ -68,7 +68,7 @@
 
   $ hg fold --exact -r 1 -r 2 --date "0 0" -m "fold0"
   2 changesets folded
-  4 new unstable changesets
+  4 new orphan changesets
   $ hg fold --exact -r 3 -r 4 --date "0 0" -m "fold1"
   2 changesets folded
   $ hg fold --exact -r 5 -r 6 --date "0 0" -m "fold2"
@@ -80,14 +80,14 @@
   |  parent:      4:868d2e0eb19c
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  trouble:     unstable
+  |  instability: orphan
   |  summary:     fold2
   |
   | o  changeset:   8:d15d0ffc75f6
   | |  parent:      2:c473644ee0e9
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  trouble:     unstable
+  | |  instability: orphan
   | |  summary:     fold1
   | |
   | | o  changeset:   7:b868bc49b0a4
@@ -99,25 +99,25 @@
   x | |  changeset:   4:868d2e0eb19c
   | | |  user:        test
   | | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | | |  obsolete:    rewritten as d15d0ffc75f6
+  | | |  obsolete:    rewritten as 8:d15d0ffc75f6
   | | |  summary:     D
   | | |
   x | |  changeset:   3:a8df460dbbfe
   |/ /   user:        test
   | |    date:        Thu Jan 01 00:00:00 1970 +0000
-  | |    obsolete:    rewritten as d15d0ffc75f6
+  | |    obsolete:    rewritten as 8:d15d0ffc75f6
   | |    summary:     C
   | |
   x |  changeset:   2:c473644ee0e9
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  obsolete:    rewritten as b868bc49b0a4
+  | |  obsolete:    rewritten as 7:b868bc49b0a4
   | |  summary:     B
   | |
   x |  changeset:   1:2a34000d3544
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as b868bc49b0a4
+  |    obsolete:    rewritten as 7:b868bc49b0a4
   |    summary:     A
   |
   o  changeset:   0:ea207398892e
@@ -236,27 +236,27 @@
   |  tag:         tip
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  trouble:     unstable
+  |  instability: orphan
   |  summary:     fold2
   |
   o  changeset:   14:ec31316faa9d
   |  parent:      4:868d2e0eb19c
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  trouble:     unstable
+  |  instability: orphan
   |  summary:     fold2
   |
   | o  changeset:   13:d0f33db50670
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  trouble:     unstable
+  | |  instability: orphan
   | |  summary:     fold1
   | |
   | o  changeset:   12:7b3290f6e0a0
   | |  parent:      2:c473644ee0e9
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  trouble:     unstable
+  | |  instability: orphan
   | |  summary:     fold1
   | |
   | | o  changeset:   11:e036916b63ea
@@ -273,25 +273,25 @@
   x | |  changeset:   4:868d2e0eb19c
   | | |  user:        test
   | | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | | |  obsolete:    split as 7b3290f6e0a0, d0f33db50670
+  | | |  obsolete:    split as 12:7b3290f6e0a0, 13:d0f33db50670
   | | |  summary:     D
   | | |
   x | |  changeset:   3:a8df460dbbfe
   |/ /   user:        test
   | |    date:        Thu Jan 01 00:00:00 1970 +0000
-  | |    obsolete:    split as 7b3290f6e0a0, d0f33db50670
+  | |    obsolete:    split as 12:7b3290f6e0a0, 13:d0f33db50670
   | |    summary:     C
   | |
   x |  changeset:   2:c473644ee0e9
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  obsolete:    split as 19e14c8397fc, e036916b63ea
+  | |  obsolete:    split as 10:19e14c8397fc, 11:e036916b63ea
   | |  summary:     B
   | |
   x |  changeset:   1:2a34000d3544
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    split as 19e14c8397fc, e036916b63ea
+  |    obsolete:    split as 10:19e14c8397fc, 11:e036916b63ea
   |    summary:     A
   |
   o  changeset:   0:ea207398892e
@@ -312,21 +312,21 @@
   |  tag:         tip
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  trouble:     unstable
+  |  instability: orphan
   |  summary:     fold2
   |
   o  changeset:   14:ec31316faa9d
   |  parent:      4:868d2e0eb19c
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  trouble:     unstable
+  |  instability: orphan
   |  summary:     fold2
   |
   | o  changeset:   12:7b3290f6e0a0
   | |  parent:      2:c473644ee0e9
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  trouble:     unstable
+  | |  instability: orphan
   | |  summary:     fold1
   | |
   | | o  changeset:   10:19e14c8397fc
@@ -338,25 +338,25 @@
   x | |  changeset:   4:868d2e0eb19c
   | | |  user:        test
   | | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | | |  obsolete:    split as 7b3290f6e0a0, ec31316faa9d
+  | | |  obsolete:    split as 12:7b3290f6e0a0, 14:ec31316faa9d
   | | |  summary:     D
   | | |
   x | |  changeset:   3:a8df460dbbfe
   |/ /   user:        test
   | |    date:        Thu Jan 01 00:00:00 1970 +0000
-  | |    obsolete:    split as 7b3290f6e0a0, ec31316faa9d
+  | |    obsolete:    split as 12:7b3290f6e0a0, 14:ec31316faa9d
   | |    summary:     C
   | |
   x |  changeset:   2:c473644ee0e9
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  obsolete:    split as 19e14c8397fc, 7b3290f6e0a0
+  | |  obsolete:    split as 10:19e14c8397fc, 12:7b3290f6e0a0
   | |  summary:     B
   | |
   x |  changeset:   1:2a34000d3544
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    split as 19e14c8397fc, 7b3290f6e0a0
+  |    obsolete:    split as 10:19e14c8397fc, 12:7b3290f6e0a0
   |    summary:     A
   |
   o  changeset:   0:ea207398892e
@@ -374,25 +374,25 @@
   o    7b3290f6e0a0 (12) fold1
   |\
   x |    d15d0ffc75f6 (8) fold1
-  |\ \     rewritten(parent, content) by test (*) as 7b3290f6e0a0, d0f33db50670 (glob)
+  |\ \     rewritten(parent, content) as 7b3290f6e0a0, d0f33db50670 by test (*) (glob)
   | | |
   | | x  e036916b63ea (11) fold0
-  | | |    rewritten(description, parent, content) by test (*) as 7b3290f6e0a0 (glob)
+  | | |    rewritten(description, parent, content) as 7b3290f6e0a0 by test (*) (glob)
   | | |
   x | |  868d2e0eb19c (4) D
-   / /     rewritten(description, parent, content) by test (*) as d15d0ffc75f6 (glob)
+   / /     rewritten(description, parent, content) as d15d0ffc75f6 by test (*) (glob)
   | |
   x |  a8df460dbbfe (3) C
-   /     rewritten(description, content) by test (*) as d15d0ffc75f6 (glob)
+   /     rewritten(description, content) as d15d0ffc75f6 by test (*) (glob)
   |
   x    b868bc49b0a4 (7) fold0
-  |\     rewritten(parent, content) by test (*) as 19e14c8397fc, e036916b63ea (glob)
+  |\     rewritten(parent, content) as 19e14c8397fc, e036916b63ea by test (*) (glob)
   | |
   x |  2a34000d3544 (1) A
-   /     rewritten(description, content) by test (*) as b868bc49b0a4 (glob)
+   /     rewritten(description, content) as b868bc49b0a4 by test (*) (glob)
   |
   x  c473644ee0e9 (2) B
-       rewritten(description, parent, content) by test (*) as b868bc49b0a4 (glob)
+       rewritten(description, parent, content) as b868bc49b0a4 by test (*) (glob)
   
 While with all option, we should see 15 changesets
 
@@ -406,35 +406,35 @@
   | | | | o  ec31316faa9d (14) fold2
   | | | |/|
   | | | x |    100cc25b765f (9) fold2
-  | | | |\ \     rewritten(parent, content) by test (*) as d4a000f63ee9, ec31316faa9d (glob)
+  | | | |\ \     rewritten(parent, content) as d4a000f63ee9, ec31316faa9d by test (*) (glob)
   | | | | | |
   | +-------x  d0f33db50670 (13) fold1
-  | | | | |      rewritten(description, parent, content) by test (*) as ec31316faa9d (glob)
+  | | | | |      rewritten(description, parent, content) as ec31316faa9d by test (*) (glob)
   | | | | |
   +---x | |  e036916b63ea (11) fold0
-  | |  / /     rewritten(description, parent, content) by test (*) as 7b3290f6e0a0 (glob)
+  | |  / /     rewritten(description, parent, content) as 7b3290f6e0a0 by test (*) (glob)
   | | | |
   | | x |  0da815c333f6 (5) E
-  | |  /     rewritten(description, content) by test (*) as 100cc25b765f (glob)
+  | |  /     rewritten(description, content) as 100cc25b765f by test (*) (glob)
   | | |
   x | |    b868bc49b0a4 (7) fold0
-  |\ \ \     rewritten(parent, content) by test (*) as 19e14c8397fc, e036916b63ea (glob)
+  |\ \ \     rewritten(parent, content) as 19e14c8397fc, e036916b63ea by test (*) (glob)
   | | | |
   | | x |    d15d0ffc75f6 (8) fold1
-  | | |\ \     rewritten(parent, content) by test (*) as 7b3290f6e0a0, d0f33db50670 (glob)
+  | | |\ \     rewritten(parent, content) as 7b3290f6e0a0, d0f33db50670 by test (*) (glob)
   | | | | |
   | | | | x  d9f908fde1a1 (6) F
-  | | | |      rewritten(description, parent, content) by test (*) as 100cc25b765f (glob)
+  | | | |      rewritten(description, parent, content) as 100cc25b765f by test (*) (glob)
   | | | |
   x | | |  2a34000d3544 (1) A
-   / / /     rewritten(description, content) by test (*) as b868bc49b0a4 (glob)
+   / / /     rewritten(description, content) as b868bc49b0a4 by test (*) (glob)
   | | |
   | x |  868d2e0eb19c (4) D
-  |  /     rewritten(description, parent, content) by test (*) as d15d0ffc75f6 (glob)
+  |  /     rewritten(description, parent, content) as d15d0ffc75f6 by test (*) (glob)
   | |
   | x  a8df460dbbfe (3) C
-  |      rewritten(description, content) by test (*) as d15d0ffc75f6 (glob)
+  |      rewritten(description, content) as d15d0ffc75f6 by test (*) (glob)
   |
   x  c473644ee0e9 (2) B
-       rewritten(description, parent, content) by test (*) as b868bc49b0a4 (glob)
+       rewritten(description, parent, content) as b868bc49b0a4 by test (*) (glob)
   
--- a/tests/test-evolve-obshistory.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-evolve-obshistory.t	Tue Nov 14 23:04:04 2017 +0100
@@ -31,23 +31,17 @@
   > 
   > Better commit message"
   $ hg log --hidden -G
-  @  changeset:   3:4ae3a4151de9
+  @  changeset:   2:4ae3a4151de9
   |  tag:         tip
   |  parent:      0:ea207398892e
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     A1
   |
-  | x  changeset:   2:f137d23bb3e1
-  | |  user:        test
-  | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  obsolete:    pruned
-  | |  summary:     temporary amend commit for 471f378eab4c
-  | |
   | x  changeset:   1:471f378eab4c
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as 4ae3a4151de9
+  |    obsolete:    rewritten using amend as 2:4ae3a4151de9
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -58,10 +52,10 @@
 Actual test
 -----------
   $ hg obslog --patch 4ae3a4151de9
-  @  4ae3a4151de9 (3) A1
+  @  4ae3a4151de9 (2) A1
   |
   x  471f378eab4c (1) A0
-       rewritten(description, content) by test (Thu Jan 01 00:00:00 1970 +0000) as 4ae3a4151de9
+       rewritten(description, content) as 4ae3a4151de9 by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/4ae3a4151de9-changeset-description
          @@ -1,1 +1,3 @@
@@ -78,40 +72,66 @@
          +42
   
   
+
+  $ hg obslog --no-graph --patch 4ae3a4151de9
+  4ae3a4151de9 (2) A1
+  471f378eab4c (1) A0
+    rewritten(description, content) as 4ae3a4151de9 by test (Thu Jan 01 00:00:00 1970 +0000)
+      --- a/471f378eab4c-changeset-description	
+      +++ b/4ae3a4151de9-changeset-description	
+      @@ -1,1 +1,3 @@
+      -A0
+      +A1
+      +
+      +Better commit message
+  
+      diff -r 471f378eab4c -r 4ae3a4151de9 A0
+      --- a/A0	Thu Jan 01 00:00:00 1970 +0000
+      +++ b/A0	Thu Jan 01 00:00:00 1970 +0000
+      @@ -1,1 +1,2 @@
+       A0
+      +42
+  
+
+  $ hg obslog 4ae3a4151de9 --graph -T'{label("log.summary", shortdescription)} {if(markers, join(markers % "at {date|hgdate} by {user|person} ", " also "))}'
+  @  A1
+  |
+  x  A0 at 0 0 by test
+  
   $ hg obslog 4ae3a4151de9 --no-graph -Tjson | python -m json.tool
   [
       {
-          "debugobshistory.markers": [],
-          "debugobshistory.node": "4ae3a4151de9",
-          "debugobshistory.rev": 3,
-          "debugobshistory.shortdescription": "A1"
+          "markers": [],
+          "node": "4ae3a4151de9",
+          "rev": 2,
+          "shortdescription": "A1"
       },
       {
-          "debugobshistory.markers": [
+          "markers": [
               {
-                  "debugobshistory.effect": [
+                  "date": [
+                      *, (glob)
+                      0 (glob)
+                  ],
+                  "effect": [
                       "description",
                       "content"
                   ],
-                  "debugobshistory.marker_date": [
-                      *, (glob)
-                      0 (glob)
-                  ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "succnodes": [
                       "4ae3a4151de9"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               }
           ],
-          "debugobshistory.node": "471f378eab4c",
-          "debugobshistory.rev": 1,
-          "debugobshistory.shortdescription": "A0"
+          "node": "471f378eab4c",
+          "rev": 1,
+          "shortdescription": "A0"
       }
   ]
   $ hg obslog --hidden --patch 471f378eab4c
   x  471f378eab4c (1) A0
-       rewritten(description, content) by test (*) as 4ae3a4151de9 (glob)
+       rewritten(description, content) as 4ae3a4151de9 by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/4ae3a4151de9-changeset-description
          @@ -1,1 +1,3 @@
@@ -131,26 +151,26 @@
   $ hg obslog --hidden 471f378eab4c --no-graph -Tjson | python -m json.tool
   [
       {
-          "debugobshistory.markers": [
+          "markers": [
               {
-                  "debugobshistory.effect": [
-                      *, (glob)
-                      "content"
-                  ],
-                  "debugobshistory.marker_date": [
+                  "date": [
                       *, (glob)
                       0 (glob)
                   ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "effect": [
+                      *, (glob)
+                      "content"
+                  ],
+                  "succnodes": [
                       "4ae3a4151de9"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               }
           ],
-          "debugobshistory.node": "471f378eab4c",
-          "debugobshistory.rev": 1,
-          "debugobshistory.shortdescription": "A0"
+          "node": "471f378eab4c",
+          "rev": 1,
+          "shortdescription": "A0"
       }
   ]
   $ hg update 471f378eab4c
@@ -219,24 +239,24 @@
   $ hg obslog 'desc(B0)' --hidden --patch
   x  0dec01379d3b (2) B0
        pruned by test (*) (glob)
-         (No patch available yet, no successors)
+         (No patch available, no successors)
   
   $ hg obslog 'desc(B0)' --hidden --no-graph -Tjson | python -m json.tool
   [
       {
-          "debugobshistory.markers": [
+          "markers": [
               {
-                  "debugobshistory.marker_date": [
+                  "date": [
                       *, (glob)
                       0 (glob)
                   ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.verb": "pruned"
+                  "user": "test",
+                  "verb": "pruned"
               }
           ],
-          "debugobshistory.node": "0dec01379d3b",
-          "debugobshistory.rev": 2,
-          "debugobshistory.shortdescription": "B0"
+          "node": "0dec01379d3b",
+          "rev": 2,
+          "shortdescription": "B0"
       }
   ]
   $ hg obslog 'desc(A0)' --patch
@@ -245,10 +265,10 @@
   $ hg obslog 'desc(A0)' --no-graph -Tjson | python -m json.tool
   [
       {
-          "debugobshistory.markers": [],
-          "debugobshistory.node": "471f378eab4c",
-          "debugobshistory.rev": 1,
-          "debugobshistory.shortdescription": "A0"
+          "markers": [],
+          "node": "471f378eab4c",
+          "rev": 1,
+          "shortdescription": "A0"
       }
   ]
   $ hg up 1
@@ -339,7 +359,7 @@
   | x  changeset:   1:471597cad322
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    split as 337fec4d2edc, f257fde29c7a
+  |    obsolete:    split as 2:337fec4d2edc, 3:f257fde29c7a
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -353,33 +373,33 @@
 Check that debugobshistory on splitted commit show both targets
   $ hg obslog 471597cad322 --hidden --patch
   x  471597cad322 (1) A0
-       rewritten(parent, content) by test (*) as 337fec4d2edc, f257fde29c7a (glob)
-         (No patch available yet, too many successors (2))
+       rewritten(parent, content) as 337fec4d2edc, f257fde29c7a by test (*) (glob)
+         (No patch available, too many successors (2))
   
   $ hg obslog 471597cad322 --hidden --no-graph -Tjson | python -m json.tool
   [
       {
-          "debugobshistory.markers": [
+          "markers": [
               {
-                  "debugobshistory.effect": [
-                      "parent",
-                      "content"
-                  ],
-                  "debugobshistory.marker_date": [
+                  "date": [
                       *, (glob)
                       0 (glob)
                   ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "effect": [
+                      "parent",
+                      "content"
+                  ],
+                  "succnodes": [
                       "337fec4d2edc",
                       "f257fde29c7a"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               }
           ],
-          "debugobshistory.node": "471597cad322",
-          "debugobshistory.rev": 1,
-          "debugobshistory.shortdescription": "A0"
+          "node": "471597cad322",
+          "rev": 1,
+          "shortdescription": "A0"
       }
   ]
 Check that debugobshistory on the first successor after split show
@@ -388,8 +408,8 @@
   o  337fec4d2edc (2) A0
   |
   x  471597cad322 (1) A0
-       rewritten(parent, content) by test (*) as 337fec4d2edc, f257fde29c7a (glob)
-         (No patch available yet, too many successors (2))
+       rewritten(parent, content) as 337fec4d2edc, f257fde29c7a by test (*) (glob)
+         (No patch available, too many successors (2))
   
 With the all option, it should show the three changesets
   $ hg obslog --all 337fec4d2edc --patch
@@ -398,8 +418,8 @@
   | @  f257fde29c7a (3) A0
   |/
   x  471597cad322 (1) A0
-       rewritten(parent, content) by test (*) as 337fec4d2edc, f257fde29c7a (glob)
-         (No patch available yet, too many successors (2))
+       rewritten(parent, content) as 337fec4d2edc, f257fde29c7a by test (*) (glob)
+         (No patch available, too many successors (2))
   
 Check that debugobshistory on the second successor after split show
 the revision plus the splitted one
@@ -407,8 +427,8 @@
   @  f257fde29c7a (3) A0
   |
   x  471597cad322 (1) A0
-       rewritten(parent, content) by test (*) as 337fec4d2edc, f257fde29c7a (glob)
-         (No patch available yet, too many successors (2))
+       rewritten(parent, content) as 337fec4d2edc, f257fde29c7a by test (*) (glob)
+         (No patch available, too many successors (2))
   
 With the all option, it should show the three changesets
   $ hg obslog f257fde29c7a --all --patch
@@ -417,8 +437,8 @@
   | @  f257fde29c7a (3) A0
   |/
   x  471597cad322 (1) A0
-       rewritten(parent, content) by test (*) as 337fec4d2edc, f257fde29c7a (glob)
-         (No patch available yet, too many successors (2))
+       rewritten(parent, content) as 337fec4d2edc, f257fde29c7a by test (*) (glob)
+         (No patch available, too many successors (2))
   
 Obslog with all option all should also works on the splitted commit
   $ hg obslog -a 471597cad322 --hidden --patch
@@ -427,8 +447,8 @@
   | @  f257fde29c7a (3) A0
   |/
   x  471597cad322 (1) A0
-       rewritten(parent, content) by test (*) as 337fec4d2edc, f257fde29c7a (glob)
-         (No patch available yet, too many successors (2))
+       rewritten(parent, content) as 337fec4d2edc, f257fde29c7a by test (*) (glob)
+         (No patch available, too many successors (2))
   
 Check that debugobshistory on both successors after split show
 a coherent graph
@@ -438,8 +458,8 @@
   | @  f257fde29c7a (3) A0
   |/
   x  471597cad322 (1) A0
-       rewritten(parent, content) by test (*) as 337fec4d2edc, f257fde29c7a (glob)
-         (No patch available yet, too many successors (2))
+       rewritten(parent, content) as 337fec4d2edc, f257fde29c7a by test (*) (glob)
+         (No patch available, too many successors (2))
   
   $ hg update 471597cad322
   abort: hidden revision '471597cad322'!
@@ -593,7 +613,7 @@
   | x  changeset:   1:de7290d8b885
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    split as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a
+  |    obsolete:    split as 2:337fec4d2edc, 3:f257fde29c7a, 4:1ae8bc733a14, 5:c7f044602e9b
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -606,8 +626,8 @@
 
   $ hg obslog de7290d8b885 --hidden --patch
   x  de7290d8b885 (1) A0
-       rewritten(parent, content) by test (*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob)
-         (No patch available yet, too many successors (4))
+       rewritten(parent, content) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a by test (*) (glob)
+         (No patch available, too many successors (4))
   
   $ hg obslog de7290d8b885 --hidden --all --patch
   o  1ae8bc733a14 (4) A0
@@ -619,76 +639,76 @@
   | o  f257fde29c7a (3) A0
   |/
   x  de7290d8b885 (1) A0
-       rewritten(parent, content) by test (*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob)
-         (No patch available yet, too many successors (4))
+       rewritten(parent, content) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a by test (*) (glob)
+         (No patch available, too many successors (4))
   
   $ hg obslog de7290d8b885 --hidden --no-graph -Tjson | python -m json.tool
   [
       {
-          "debugobshistory.markers": [
+          "markers": [
               {
-                  "debugobshistory.effect": [
+                  "date": [
+                      *, (glob)
+                      0 (glob)
+                  ],
+                  "effect": [
                       "parent",
                       "content"
                   ],
-                  "debugobshistory.marker_date": [
-                      *, (glob)
-                      0 (glob)
-                  ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "succnodes": [
                       "1ae8bc733a14",
                       "337fec4d2edc",
                       "c7f044602e9b",
                       "f257fde29c7a"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               }
           ],
-          "debugobshistory.node": "de7290d8b885",
-          "debugobshistory.rev": 1,
-          "debugobshistory.shortdescription": "A0"
+          "node": "de7290d8b885",
+          "rev": 1,
+          "shortdescription": "A0"
       }
   ]
   $ hg obslog c7f044602e9b --patch
   @  c7f044602e9b (5) A0
   |
   x  de7290d8b885 (1) A0
-       rewritten(parent, content) by test (*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob)
-         (No patch available yet, too many successors (4))
+       rewritten(parent, content) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a by test (*) (glob)
+         (No patch available, too many successors (4))
   
   $ hg obslog c7f044602e9b --no-graph -Tjson | python -m json.tool
   [
       {
-          "debugobshistory.markers": [],
-          "debugobshistory.node": "c7f044602e9b",
-          "debugobshistory.rev": 5,
-          "debugobshistory.shortdescription": "A0"
+          "markers": [],
+          "node": "c7f044602e9b",
+          "rev": 5,
+          "shortdescription": "A0"
       },
       {
-          "debugobshistory.markers": [
+          "markers": [
               {
-                  "debugobshistory.effect": [
+                  "date": [
+                      *, (glob)
+                      0 (glob)
+                  ],
+                  "effect": [
                       "parent",
                       "content"
                   ],
-                  "debugobshistory.marker_date": [
-                      *, (glob)
-                      0 (glob)
-                  ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "succnodes": [
                       "1ae8bc733a14",
                       "337fec4d2edc",
                       "c7f044602e9b",
                       "f257fde29c7a"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               }
           ],
-          "debugobshistory.node": "de7290d8b885",
-          "debugobshistory.rev": 1,
-          "debugobshistory.shortdescription": "A0"
+          "node": "de7290d8b885",
+          "rev": 1,
+          "shortdescription": "A0"
       }
   ]
 Check that debugobshistory on all heads show a coherent graph
@@ -702,8 +722,8 @@
   | o  f257fde29c7a (3) A0
   |/
   x  de7290d8b885 (1) A0
-       rewritten(parent, content) by test (*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob)
-         (No patch available yet, too many successors (4))
+       rewritten(parent, content) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a by test (*) (glob)
+         (No patch available, too many successors (4))
   
   $ hg obslog 5 --all --patch
   o  1ae8bc733a14 (4) A0
@@ -715,8 +735,8 @@
   | o  f257fde29c7a (3) A0
   |/
   x  de7290d8b885 (1) A0
-       rewritten(parent, content) by test (*) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a (glob)
-         (No patch available yet, too many successors (4))
+       rewritten(parent, content) as 1ae8bc733a14, 337fec4d2edc, c7f044602e9b, f257fde29c7a by test (*) (glob)
+         (No patch available, too many successors (4))
   
   $ hg update de7290d8b885
   abort: hidden revision 'de7290d8b885'!
@@ -769,13 +789,13 @@
   | x  changeset:   2:0dec01379d3b
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  obsolete:    rewritten as eb5a0daa2192
+  | |  obsolete:    rewritten as 3:eb5a0daa2192
   | |  summary:     B0
   | |
   | x  changeset:   1:471f378eab4c
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as eb5a0daa2192
+  |    obsolete:    rewritten as 3:eb5a0daa2192
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -790,7 +810,7 @@
 the revision with the target
   $ hg obslog --hidden 471f378eab4c --patch
   x  471f378eab4c (1) A0
-       rewritten(description, content) by test (*) as eb5a0daa2192 (glob)
+       rewritten(description, content) as eb5a0daa2192 by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/eb5a0daa2192-changeset-description
          @@ -1,1 +1,1 @@
@@ -809,11 +829,11 @@
   @    eb5a0daa2192 (3) C0
   |\
   x |  0dec01379d3b (2) B0
-   /     rewritten(description, parent, content) by test (*) as eb5a0daa2192 (glob)
-  |        (No patch available yet, changesets rebased)
+   /     rewritten(description, parent, content) as eb5a0daa2192 by test (*) (glob)
+  |        (No patch available, changesets rebased)
   |
   x  471f378eab4c (1) A0
-       rewritten(description, content) by test (*) as eb5a0daa2192 (glob)
+       rewritten(description, content) as eb5a0daa2192 by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/eb5a0daa2192-changeset-description
          @@ -1,1 +1,1 @@
@@ -831,19 +851,19 @@
 the revision with the target
   $ hg obslog --hidden 0dec01379d3b --patch
   x  0dec01379d3b (2) B0
-       rewritten(description, parent, content) by test (*) as eb5a0daa2192 (glob)
-         (No patch available yet, changesets rebased)
+       rewritten(description, parent, content) as eb5a0daa2192 by test (*) (glob)
+         (No patch available, changesets rebased)
   
 Check that with all option, all changesets are shown
   $ hg obslog --hidden --all 0dec01379d3b --patch
   @    eb5a0daa2192 (3) C0
   |\
   x |  0dec01379d3b (2) B0
-   /     rewritten(description, parent, content) by test (*) as eb5a0daa2192 (glob)
-  |        (No patch available yet, changesets rebased)
+   /     rewritten(description, parent, content) as eb5a0daa2192 by test (*) (glob)
+  |        (No patch available, changesets rebased)
   |
   x  471f378eab4c (1) A0
-       rewritten(description, content) by test (*) as eb5a0daa2192 (glob)
+       rewritten(description, content) as eb5a0daa2192 by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/eb5a0daa2192-changeset-description
          @@ -1,1 +1,1 @@
@@ -863,11 +883,11 @@
   @    eb5a0daa2192 (3) C0
   |\
   x |  0dec01379d3b (2) B0
-   /     rewritten(description, parent, content) by test (*) as eb5a0daa2192 (glob)
-  |        (No patch available yet, changesets rebased)
+   /     rewritten(description, parent, content) as eb5a0daa2192 by test (*) (glob)
+  |        (No patch available, changesets rebased)
   |
   x  471f378eab4c (1) A0
-       rewritten(description, content) by test (*) as eb5a0daa2192 (glob)
+       rewritten(description, content) as eb5a0daa2192 by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/eb5a0daa2192-changeset-description
          @@ -1,1 +1,1 @@
@@ -884,55 +904,55 @@
   $ hg obslog eb5a0daa2192 --no-graph -Tjson | python -m json.tool
   [
       {
-          "debugobshistory.markers": [],
-          "debugobshistory.node": "eb5a0daa2192",
-          "debugobshistory.rev": 3,
-          "debugobshistory.shortdescription": "C0"
+          "markers": [],
+          "node": "eb5a0daa2192",
+          "rev": 3,
+          "shortdescription": "C0"
       },
       {
-          "debugobshistory.markers": [
+          "markers": [
               {
-                  "debugobshistory.effect": [
-                      "description",
-                      "content"
-                  ],
-                  "debugobshistory.marker_date": [
+                  "date": [
                       *, (glob)
                       0 (glob)
                   ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "effect": [
+                      "description",
+                      "content"
+                  ],
+                  "succnodes": [
                       "eb5a0daa2192"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               }
           ],
-          "debugobshistory.node": "471f378eab4c",
-          "debugobshistory.rev": 1,
-          "debugobshistory.shortdescription": "A0"
+          "node": "471f378eab4c",
+          "rev": 1,
+          "shortdescription": "A0"
       },
       {
-          "debugobshistory.markers": [
+          "markers": [
               {
-                  "debugobshistory.effect": [
+                  "date": [
+                      *, (glob)
+                      0 (glob)
+                  ],
+                  "effect": [
                       "description",
                       "parent",
                       "content"
                   ],
-                  "debugobshistory.marker_date": [
-                      *, (glob)
-                      0 (glob)
-                  ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "succnodes": [
                       "eb5a0daa2192"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               }
           ],
-          "debugobshistory.node": "0dec01379d3b",
-          "debugobshistory.rev": 2,
-          "debugobshistory.shortdescription": "B0"
+          "node": "0dec01379d3b",
+          "rev": 2,
+          "shortdescription": "B0"
       }
   ]
   $ hg update 471f378eab4c
@@ -976,7 +996,7 @@
   | x  changeset:   1:471f378eab4c
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as fdf9bde5129a
+  |    obsolete:    reworded using amend as 2:fdf9bde5129a
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -989,28 +1009,28 @@
   working directory parent is obsolete! (471f378eab4c)
   (use 'hg evolve' to update to its successor: fdf9bde5129a)
   $ hg amend -m "A2"
-  2 new divergent changesets
+  2 new content-divergent changesets
   $ hg log --hidden -G
   @  changeset:   3:65b757b745b9
   |  tag:         tip
   |  parent:      0:ea207398892e
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  trouble:     divergent
+  |  instability: content-divergent
   |  summary:     A2
   |
   | o  changeset:   2:fdf9bde5129a
   |/   parent:      0:ea207398892e
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    trouble:     divergent
+  |    instability: content-divergent
   |    summary:     A1
   |
   | x  changeset:   1:471f378eab4c
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as fdf9bde5129a
-  |    obsolete:    rewritten as 65b757b745b9
+  |    obsolete:    reworded using amend as 2:fdf9bde5129a
+  |    obsolete:    reworded using amend as 3:65b757b745b9
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -1024,14 +1044,14 @@
 Check that debugobshistory on the divergent revision show both destinations
   $ hg obslog --hidden 471f378eab4c --patch
   x  471f378eab4c (1) A0
-       rewritten(description) by test (*) as 65b757b745b9 (glob)
+       rewritten(description) as 65b757b745b9 by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/65b757b745b9-changeset-description
          @@ -1,1 +1,1 @@
          -A0
          +A2
   
-       rewritten(description) by test (*) as fdf9bde5129a (glob)
+       rewritten(description) as fdf9bde5129a by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/fdf9bde5129a-changeset-description
          @@ -1,1 +1,1 @@
@@ -1047,14 +1067,14 @@
   | o  fdf9bde5129a (2) A1
   |/
   x  471f378eab4c (1) A0
-       rewritten(description) by test (*) as 65b757b745b9 (glob)
+       rewritten(description) as 65b757b745b9 by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/65b757b745b9-changeset-description
          @@ -1,1 +1,1 @@
          -A0
          +A2
   
-       rewritten(description) by test (*) as fdf9bde5129a (glob)
+       rewritten(description) as fdf9bde5129a by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/fdf9bde5129a-changeset-description
          @@ -1,1 +1,1 @@
@@ -1065,39 +1085,39 @@
   $ hg obslog --hidden 471f378eab4c --no-graph -Tjson | python -m json.tool
   [
       {
-          "debugobshistory.markers": [
+          "markers": [
               {
-                  "debugobshistory.effect": [
-                      "description"
-                  ],
-                  "debugobshistory.marker_date": [
+                  "date": [
                       *, (glob)
                       0 (glob)
                   ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "effect": [
+                      "description"
+                  ],
+                  "succnodes": [
                       "65b757b745b9"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               },
               {
-                  "debugobshistory.effect": [
-                      "description"
-                  ],
-                  "debugobshistory.marker_date": [
+                  "date": [
                       *, (glob)
                       0 (glob)
                   ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "effect": [
+                      "description"
+                  ],
+                  "succnodes": [
                       "fdf9bde5129a"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               }
           ],
-          "debugobshistory.node": "471f378eab4c",
-          "debugobshistory.rev": 1,
-          "debugobshistory.shortdescription": "A0"
+          "node": "471f378eab4c",
+          "rev": 1,
+          "shortdescription": "A0"
       }
   ]
 Check that debugobshistory on the first diverged revision show the revision
@@ -1106,14 +1126,14 @@
   o  fdf9bde5129a (2) A1
   |
   x  471f378eab4c (1) A0
-       rewritten(description) by test (*) as 65b757b745b9 (glob)
+       rewritten(description) as 65b757b745b9 by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/65b757b745b9-changeset-description
          @@ -1,1 +1,1 @@
          -A0
          +A2
   
-       rewritten(description) by test (*) as fdf9bde5129a (glob)
+       rewritten(description) as fdf9bde5129a by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/fdf9bde5129a-changeset-description
          @@ -1,1 +1,1 @@
@@ -1129,14 +1149,14 @@
   | o  fdf9bde5129a (2) A1
   |/
   x  471f378eab4c (1) A0
-       rewritten(description) by test (*) as 65b757b745b9 (glob)
+       rewritten(description) as 65b757b745b9 by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/65b757b745b9-changeset-description
          @@ -1,1 +1,1 @@
          -A0
          +A2
   
-       rewritten(description) by test (*) as fdf9bde5129a (glob)
+       rewritten(description) as fdf9bde5129a by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/fdf9bde5129a-changeset-description
          @@ -1,1 +1,1 @@
@@ -1150,14 +1170,14 @@
   @  65b757b745b9 (3) A2
   |
   x  471f378eab4c (1) A0
-       rewritten(description) by test (*) as 65b757b745b9 (glob)
+       rewritten(description) as 65b757b745b9 by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/65b757b745b9-changeset-description
          @@ -1,1 +1,1 @@
          -A0
          +A2
   
-       rewritten(description) by test (*) as fdf9bde5129a (glob)
+       rewritten(description) as fdf9bde5129a by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/fdf9bde5129a-changeset-description
          @@ -1,1 +1,1 @@
@@ -1172,14 +1192,14 @@
   | o  fdf9bde5129a (2) A1
   |/
   x  471f378eab4c (1) A0
-       rewritten(description) by test (*) as 65b757b745b9 (glob)
+       rewritten(description) as 65b757b745b9 by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/65b757b745b9-changeset-description
          @@ -1,1 +1,1 @@
          -A0
          +A2
   
-       rewritten(description) by test (*) as fdf9bde5129a (glob)
+       rewritten(description) as fdf9bde5129a by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/fdf9bde5129a-changeset-description
          @@ -1,1 +1,1 @@
@@ -1195,14 +1215,14 @@
   | o  fdf9bde5129a (2) A1
   |/
   x  471f378eab4c (1) A0
-       rewritten(description) by test (*) as 65b757b745b9 (glob)
+       rewritten(description) as 65b757b745b9 by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/65b757b745b9-changeset-description
          @@ -1,1 +1,1 @@
          -A0
          +A2
   
-       rewritten(description) by test (*) as fdf9bde5129a (glob)
+       rewritten(description) as fdf9bde5129a by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/fdf9bde5129a-changeset-description
          @@ -1,1 +1,1 @@
@@ -1213,51 +1233,51 @@
   $ hg obslog '65b757b745b9+fdf9bde5129a' --no-graph -Tjson | python -m json.tool
   [
       {
-          "debugobshistory.markers": [],
-          "debugobshistory.node": "65b757b745b9",
-          "debugobshistory.rev": 3,
-          "debugobshistory.shortdescription": "A2"
+          "markers": [],
+          "node": "65b757b745b9",
+          "rev": 3,
+          "shortdescription": "A2"
       },
       {
-          "debugobshistory.markers": [
+          "markers": [
               {
-                  "debugobshistory.effect": [
-                      "description"
-                  ],
-                  "debugobshistory.marker_date": [
+                  "date": [
                       *, (glob)
                       0 (glob)
                   ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "effect": [
+                      "description"
+                  ],
+                  "succnodes": [
                       "65b757b745b9"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               },
               {
-                  "debugobshistory.effect": [
-                      "description"
-                  ],
-                  "debugobshistory.marker_date": [
+                  "date": [
                       *, (glob)
                       0 (glob)
                   ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "effect": [
+                      "description"
+                  ],
+                  "succnodes": [
                       "fdf9bde5129a"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               }
           ],
-          "debugobshistory.node": "471f378eab4c",
-          "debugobshistory.rev": 1,
-          "debugobshistory.shortdescription": "A0"
+          "node": "471f378eab4c",
+          "rev": 1,
+          "shortdescription": "A0"
       },
       {
-          "debugobshistory.markers": [],
-          "debugobshistory.node": "fdf9bde5129a",
-          "debugobshistory.rev": 2,
-          "debugobshistory.shortdescription": "A1"
+          "markers": [],
+          "node": "fdf9bde5129a",
+          "rev": 2,
+          "shortdescription": "A1"
       }
   ]
   $ hg update 471f378eab4c
@@ -1267,7 +1287,7 @@
   $ hg update --hidden 'desc(A0)'
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   working directory parent is obsolete! (471f378eab4c)
-  (471f378eab4c has diverged, use 'hg evolve --list --divergent' to resolve the issue)
+  (471f378eab4c has diverged, use 'hg evolve --list --content-divergent' to resolve the issue)
 
 Test output with amended + folded commit
 ========================================
@@ -1292,7 +1312,7 @@
   | x  changeset:   2:0dec01379d3b
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as b7ea6d14e664
+  |    obsolete:    reworded using amend as 3:b7ea6d14e664
   |    summary:     B0
   |
   o  changeset:   1:471f378eab4c
@@ -1320,19 +1340,19 @@
   | |  parent:      1:471f378eab4c
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  obsolete:    rewritten as eb5a0daa2192
+  | |  obsolete:    rewritten as 4:eb5a0daa2192
   | |  summary:     B1
   | |
   | | x  changeset:   2:0dec01379d3b
   | |/   user:        test
   | |    date:        Thu Jan 01 00:00:00 1970 +0000
-  | |    obsolete:    rewritten as b7ea6d14e664
+  | |    obsolete:    reworded using amend as 3:b7ea6d14e664
   | |    summary:     B0
   | |
   | x  changeset:   1:471f378eab4c
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as eb5a0daa2192
+  |    obsolete:    rewritten as 4:eb5a0daa2192
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -1348,7 +1368,7 @@
   @    eb5a0daa2192 (4) C0
   |\
   x |  471f378eab4c (1) A0
-   /     rewritten(description, content) by test (*) as eb5a0daa2192 (glob)
+   /     rewritten(description, content) as eb5a0daa2192 by test (*) (glob)
   |        --- a/471f378eab4c-changeset-description
   |        +++ b/eb5a0daa2192-changeset-description
   |        @@ -1,1 +1,1 @@
@@ -1363,11 +1383,11 @@
   |
   |
   x  b7ea6d14e664 (3) B1
-  |    rewritten(description, parent, content) by test (*) as eb5a0daa2192 (glob)
-  |      (No patch available yet, changesets rebased)
+  |    rewritten(description, parent, content) as eb5a0daa2192 by test (*) (glob)
+  |      (No patch available, changesets rebased)
   |
   x  0dec01379d3b (2) B0
-       rewritten(description) by test (*) as b7ea6d14e664 (glob)
+       rewritten(description) as b7ea6d14e664 by test (*) (glob)
          --- a/0dec01379d3b-changeset-description
          +++ b/b7ea6d14e664-changeset-description
          @@ -1,1 +1,1 @@
@@ -1380,7 +1400,7 @@
   @    eb5a0daa2192 (4) C0
   |\
   x |  471f378eab4c (1) A0
-   /     rewritten(description, content) by test (*) as eb5a0daa2192 (glob)
+   /     rewritten(description, content) as eb5a0daa2192 by test (*) (glob)
   |        --- a/471f378eab4c-changeset-description
   |        +++ b/eb5a0daa2192-changeset-description
   |        @@ -1,1 +1,1 @@
@@ -1395,11 +1415,11 @@
   |
   |
   x  b7ea6d14e664 (3) B1
-  |    rewritten(description, parent, content) by test (*) as eb5a0daa2192 (glob)
-  |      (No patch available yet, changesets rebased)
+  |    rewritten(description, parent, content) as eb5a0daa2192 by test (*) (glob)
+  |      (No patch available, changesets rebased)
   |
   x  0dec01379d3b (2) B0
-       rewritten(description) by test (*) as b7ea6d14e664 (glob)
+       rewritten(description) as b7ea6d14e664 by test (*) (glob)
          --- a/0dec01379d3b-changeset-description
          +++ b/b7ea6d14e664-changeset-description
          @@ -1,1 +1,1 @@
@@ -1410,76 +1430,76 @@
   $ hg obslog eb5a0daa2192 --no-graph -Tjson | python -m json.tool
   [
       {
-          "debugobshistory.markers": [],
-          "debugobshistory.node": "eb5a0daa2192",
-          "debugobshistory.rev": 4,
-          "debugobshistory.shortdescription": "C0"
+          "markers": [],
+          "node": "eb5a0daa2192",
+          "rev": 4,
+          "shortdescription": "C0"
       },
       {
-          "debugobshistory.markers": [
+          "markers": [
               {
-                  "debugobshistory.effect": [
+                  "date": [
+                      *, (glob)
+                      0 (glob)
+                  ],
+                  "effect": [
                       *, (glob)
                       *, (glob)
                       "content"
                   ],
-                  "debugobshistory.marker_date": [
-                      *, (glob)
-                      0 (glob)
-                  ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "succnodes": [
                       "eb5a0daa2192"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               }
           ],
-          "debugobshistory.node": "b7ea6d14e664",
-          "debugobshistory.rev": 3,
-          "debugobshistory.shortdescription": "B1"
+          "node": "b7ea6d14e664",
+          "rev": 3,
+          "shortdescription": "B1"
       },
       {
-          "debugobshistory.markers": [
+          "markers": [
               {
-                  "debugobshistory.effect": [
-                      "description"
-                  ],
-                  "debugobshistory.marker_date": [
+                  "date": [
                       *, (glob)
                       0 (glob)
                   ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "effect": [
+                      "description"
+                  ],
+                  "succnodes": [
                       "b7ea6d14e664"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               }
           ],
-          "debugobshistory.node": "0dec01379d3b",
-          "debugobshistory.rev": 2,
-          "debugobshistory.shortdescription": "B0"
+          "node": "0dec01379d3b",
+          "rev": 2,
+          "shortdescription": "B0"
       },
       {
-          "debugobshistory.markers": [
+          "markers": [
               {
-                  "debugobshistory.effect": [
+                  "date": [
+                      *, (glob)
+                      0 (glob)
+                  ],
+                  "effect": [
                       "description",
                       "content"
                   ],
-                  "debugobshistory.marker_date": [
-                      *, (glob)
-                      0 (glob)
-                  ],
-                  "debugobshistory.marker_user": "test",
-                  "debugobshistory.succnodes": [
+                  "succnodes": [
                       "eb5a0daa2192"
                   ],
-                  "debugobshistory.verb": "rewritten"
+                  "user": "test",
+                  "verb": "rewritten"
               }
           ],
-          "debugobshistory.node": "471f378eab4c",
-          "debugobshistory.rev": 1,
-          "debugobshistory.shortdescription": "A0"
+          "node": "471f378eab4c",
+          "rev": 1,
+          "shortdescription": "A0"
       }
   ]
   $ hg update 471f378eab4c
@@ -1556,13 +1576,13 @@
   |/   parent:      0:ea207398892e
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as 7a230b46bf61
+  |    obsolete:    reworded using amend as 3:7a230b46bf61
   |    summary:     A1
   |
   | x  changeset:   1:471f378eab4c
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as fdf9bde5129a
+  |    obsolete:    reworded using amend as 2:fdf9bde5129a
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -1577,7 +1597,7 @@
   @  7a230b46bf61 (3) A2
   |
   x  fdf9bde5129a (2) A1
-  |    rewritten(description) by test (*) as 7a230b46bf61 (glob)
+  |    rewritten(description) as 7a230b46bf61 by test (*) (glob)
   |      --- a/fdf9bde5129a-changeset-description
   |      +++ b/7a230b46bf61-changeset-description
   |      @@ -1,1 +1,1 @@
@@ -1586,7 +1606,7 @@
   |
   |
   x  471f378eab4c (1) A0
-       rewritten(description) by test (*) as fdf9bde5129a (glob)
+       rewritten(description) as fdf9bde5129a by test (*) (glob)
          --- a/471f378eab4c-changeset-description
          +++ b/fdf9bde5129a-changeset-description
          @@ -1,1 +1,1 @@
@@ -1604,6 +1624,7 @@
   added 1 changesets with 0 changes to 1 files (+1 heads)
   2 new obsolescence markers
   obsoleted 1 changesets
+  new changesets 7a230b46bf61
   (run 'hg heads' to see heads, 'hg merge' to merge)
   working directory parent is obsolete! (471f378eab4c)
   (use 'hg evolve' to update to its successor: 7a230b46bf61)
@@ -1613,21 +1634,21 @@
   o  7a230b46bf61 (2) A2
   |
   x  fdf9bde5129a
-  |    rewritten(description) by test (*) as 7a230b46bf61 (glob)
-  |      (No patch available yet, context is not local)
+  |    rewritten(description) as 7a230b46bf61 by test (*) (glob)
+  |      (No patch available, context is not local)
   |
   @  471f378eab4c (1) A0
-       rewritten(description) by test (*) as fdf9bde5129a (glob)
-         (No patch available yet, succ is unknown locally)
+       rewritten(description) as fdf9bde5129a by test (*) (glob)
+         (No patch available, successor is unknown locally)
   
   $ hg obslog 7a230b46bf61 --color=debug --patch
   o  [evolve.node|7a230b46bf61] [evolve.rev|(2)] [evolve.short_description|A2]
   |
   x  [evolve.node evolve.missing_change_ctx|fdf9bde5129a]
-  |    [evolve.verb|rewritten](description) by [evolve.user|test] [evolve.date|(*)] as [evolve.node|7a230b46bf61] (glob)
-  |      (No patch available yet, context is not local)
+  |    [evolve.verb|rewritten](description) as [evolve.node|7a230b46bf61] by [evolve.user|test] [evolve.date|(*)] (glob)
+  |      (No patch available, context is not local)
   |
   @  [evolve.node|471f378eab4c] [evolve.rev|(1)] [evolve.short_description|A0]
-       [evolve.verb|rewritten](description) by [evolve.user|test] [evolve.date|(*)] as [evolve.node|fdf9bde5129a] (glob)
-         (No patch available yet, succ is unknown locally)
+       [evolve.verb|rewritten](description) as [evolve.node|fdf9bde5129a] by [evolve.user|test] [evolve.date|(*)] (glob)
+         (No patch available, successor is unknown locally)
   
--- a/tests/test-evolve-order.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-evolve-order.t	Tue Nov 14 23:04:04 2017 +0100
@@ -44,9 +44,9 @@
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ echo "aaa" > _a
   $ hg amend
-  2 new unstable changesets
+  2 new orphan changesets
   $ hg log -G
-  @  5:12d519679175@default(draft) add _a
+  @  4:12d519679175@default(draft) add _a
   |
   | o  3:4d156641b718@default(draft) add _c
   | |
@@ -60,9 +60,9 @@
 evolve --rev reorders the rev to solve instability, trivial case 2 revs wrong order
   $ hg evolve --rev 'desc(_c) + desc(_b)'
   move:[2] add _b
-  atop:[5] add _a
+  atop:[4] add _a
   move:[3] add _c
-  atop:[6] add _b
+  atop:[5] add _b
   working directory is now at 52b8f9b04f83
 
 evolve --rev reorders the rev to solve instability. Harder case, obsolescence
@@ -73,10 +73,10 @@
   $ hg up "desc(_a)"
   0 files updated, 0 files merged, 3 files removed, 0 files unresolved
   $ hg amend -m "aprime"
-  3 new unstable changesets
+  3 new orphan changesets
   $ hg evolve --rev "desc(_b)"
-  move:[6] add _b
-  atop:[9] aprime
+  move:[5] add _b
+  atop:[8] aprime
   working directory is now at 476c9c052aae
   $ hg up "desc(_b) - obsolete()"
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -84,40 +84,40 @@
   $ hg up "desc(aprime)"
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg amend -m "asecond"
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg log -G
-  @  12:9a584314f3f3@default(draft) asecond
+  @  11:9a584314f3f3@default(draft) asecond
   |
-  | o  11:a59c79776f7c@default(draft) bprime
+  | o  10:a59c79776f7c@default(draft) bprime
   | |
-  | x  9:81a687b96d4d@default(draft) aprime
+  | x  8:81a687b96d4d@default(draft) aprime
   |/
-  | o  8:464731bc0ed0@default(draft) add _d
+  | o  7:464731bc0ed0@default(draft) add _d
   | |
-  | o  7:52b8f9b04f83@default(draft) add _c
+  | o  6:52b8f9b04f83@default(draft) add _c
   | |
-  | x  6:59476c3836ef@default(draft) add _b
+  | x  5:59476c3836ef@default(draft) add _b
   | |
-  | x  5:12d519679175@default(draft) add _a
+  | x  4:12d519679175@default(draft) add _a
   |/
   o  0:f92638be10c7@default(public) add p
   
-  $ hg evolve --rev "unstable()"
-  move:[11] bprime
-  atop:[12] asecond
-  move:[7] add _c
-  atop:[13] bprime
-  move:[8] add _d
-  atop:[14] add _c
+  $ hg evolve --rev "orphan()"
+  move:[10] bprime
+  atop:[11] asecond
+  move:[6] add _c
+  atop:[12] bprime
+  move:[7] add _d
+  atop:[13] add _c
   working directory is now at 739f18ac1d03
   $ hg log -G
-  @  15:739f18ac1d03@default(draft) add _d
+  @  14:739f18ac1d03@default(draft) add _d
   |
-  o  14:e5960578d158@default(draft) add _c
+  o  13:e5960578d158@default(draft) add _c
   |
-  o  13:4ad33fa88946@default(draft) bprime
+  o  12:4ad33fa88946@default(draft) bprime
   |
-  o  12:9a584314f3f3@default(draft) asecond
+  o  11:9a584314f3f3@default(draft) asecond
   |
   o  0:f92638be10c7@default(public) add p
   
@@ -131,28 +131,28 @@
   $ mkstack "desc(_d)" c1second >/dev/null
   $ hg prune "desc(c1_)" -s "desc(c1prime)"
   1 changesets pruned
-  3 new unstable changesets
+  3 new orphan changesets
   $ hg prune "desc(c2_)" -s "desc(c2prime)"
   1 changesets pruned
   $ hg prune "desc(c1prime)" -s "desc(c1second)"
   1 changesets pruned
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg log -G -r "desc(_d)::"
-  @  22:dcf786e878fd@default(draft) add c1second
+  @  21:dcf786e878fd@default(draft) add c1second
   |
-  | o  21:507d52d715f6@default(draft) add c2prime
+  | o  20:507d52d715f6@default(draft) add c2prime
   | |
-  | x  20:c995cb124ddc@default(draft) add c1prime
+  | x  19:c995cb124ddc@default(draft) add c1prime
   |/
-  | o  19:d096a2437fd0@default(draft) add c4_
+  | o  18:d096a2437fd0@default(draft) add c4_
   | |
-  | o  18:cde95c6cba7a@default(draft) add c3_
+  | o  17:cde95c6cba7a@default(draft) add c3_
   | |
-  | x  17:e0d9f7a099fe@default(draft) add c2_
+  | x  16:e0d9f7a099fe@default(draft) add c2_
   | |
-  | x  16:43b7c338b1f8@default(draft) add c1_
+  | x  15:43b7c338b1f8@default(draft) add c1_
   |/
-  o  15:739f18ac1d03@default(draft) add _d
+  o  14:739f18ac1d03@default(draft) add _d
   |
   ~
 
@@ -161,40 +161,40 @@
   $ mkstack "desc(_d)" b1prime b3prime >/dev/null
   $ hg prune "desc(b1_)" -s "desc(b1prime)"
   1 changesets pruned
-  3 new unstable changesets
+  3 new orphan changesets
   $ hg prune "desc(b3_)" -s "desc(b3prime)"
   1 changesets pruned
   $ hg prune "desc(b2_)"
   1 changesets pruned
 
   $ hg log -G -r "desc(_d)::"
-  @  28:b253ff5b65d1@default(draft) add b3prime
+  @  27:b253ff5b65d1@default(draft) add b3prime
   |
-  o  27:4acf61f11dfb@default(draft) add b1prime
+  o  26:4acf61f11dfb@default(draft) add b1prime
   |
-  | o  26:594e1fbbd61f@default(draft) add b4_
+  | o  25:594e1fbbd61f@default(draft) add b4_
   | |
-  | x  25:be27500cfc76@default(draft) add b3_
+  | x  24:be27500cfc76@default(draft) add b3_
   | |
-  | x  24:b54f77dc5831@default(draft) add b2_
+  | x  23:b54f77dc5831@default(draft) add b2_
   | |
-  | x  23:0e1eba27e9aa@default(draft) add b1_
+  | x  22:0e1eba27e9aa@default(draft) add b1_
   |/
-  | o  22:dcf786e878fd@default(draft) add c1second
+  | o  21:dcf786e878fd@default(draft) add c1second
   |/
-  | o  21:507d52d715f6@default(draft) add c2prime
+  | o  20:507d52d715f6@default(draft) add c2prime
   | |
-  | x  20:c995cb124ddc@default(draft) add c1prime
+  | x  19:c995cb124ddc@default(draft) add c1prime
   |/
-  | o  19:d096a2437fd0@default(draft) add c4_
+  | o  18:d096a2437fd0@default(draft) add c4_
   | |
-  | o  18:cde95c6cba7a@default(draft) add c3_
+  | o  17:cde95c6cba7a@default(draft) add c3_
   | |
-  | x  17:e0d9f7a099fe@default(draft) add c2_
+  | x  16:e0d9f7a099fe@default(draft) add c2_
   | |
-  | x  16:43b7c338b1f8@default(draft) add c1_
+  | x  15:43b7c338b1f8@default(draft) add c1_
   |/
-  o  15:739f18ac1d03@default(draft) add _d
+  o  14:739f18ac1d03@default(draft) add _d
   |
   ~
 
@@ -203,35 +203,35 @@
   (desc(_d)::) - desc(c3_)
   $ hg evolve --rev "(desc(_d)::) - desc(c3_)"
   cannot solve instability of d096a2437fd0, skipping
-  move:[21] add c2prime
-  atop:[22] add c1second
-  move:[26] add b4_
-  atop:[28] add b3prime
+  move:[20] add c2prime
+  atop:[21] add c1second
+  move:[25] add b4_
+  atop:[27] add b3prime
   working directory is now at ea93190a9cd1
 
 Cleanup
   $ hg evolve --rev "(desc(_d)::)"
-  move:[18] add c3_
-  atop:[29] add c2prime
-  move:[19] add c4_
-  atop:[31] add c3_
+  move:[17] add c3_
+  atop:[28] add c2prime
+  move:[18] add c4_
+  atop:[30] add c3_
   working directory is now at 35e7b797ace5
   $ hg log -G -r "desc(_d)::"
-  @  32:35e7b797ace5@default(draft) add c4_
+  @  31:35e7b797ace5@default(draft) add c4_
   |
-  o  31:0b9488394e89@default(draft) add c3_
+  o  30:0b9488394e89@default(draft) add c3_
   |
-  | o  30:ea93190a9cd1@default(draft) add b4_
+  | o  29:ea93190a9cd1@default(draft) add b4_
   | |
-  o |  29:881b9c092e53@default(draft) add c2prime
+  o |  28:881b9c092e53@default(draft) add c2prime
   | |
-  | o  28:b253ff5b65d1@default(draft) add b3prime
+  | o  27:b253ff5b65d1@default(draft) add b3prime
   | |
-  | o  27:4acf61f11dfb@default(draft) add b1prime
+  | o  26:4acf61f11dfb@default(draft) add b1prime
   | |
-  o |  22:dcf786e878fd@default(draft) add c1second
+  o |  21:dcf786e878fd@default(draft) add c1second
   |/
-  o  15:739f18ac1d03@default(draft) add _d
+  o  14:739f18ac1d03@default(draft) add _d
   |
   ~
 
@@ -244,22 +244,22 @@
   created new head
   $ hg prev
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  [29] add c2prime
+  [28] add c2prime
   $ mkcommit c3part2
   created new head
   $ hg prune -s 'desc(c3part1)' 'desc(c3_)'
   1 changesets pruned
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg prune -s 'desc(c3part2)' 'desc(c3_)'
   1 changesets pruned
-  2 new divergent changesets
+  2 new content-divergent changesets
   $ hg up 'desc(b3prime)'
   2 files updated, 0 files merged, 3 files removed, 0 files unresolved
   $ hg amend -m 'b3second'
-  1 new unstable changesets
-  $ hg evolve --rev 'unstable()'
-  move:[30] add b4_
-  atop:[35] b3second
+  1 new orphan changesets
+  $ hg evolve --rev "orphan()"
+  move:[29] add b4_
+  atop:[34] b3second
   skipping 0b9488394e89: divergent rewriting. can't choose destination
   working directory is now at 31809a198477
 
--- a/tests/test-evolve-serveronly-bundle2.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-evolve-serveronly-bundle2.t	Tue Nov 14 23:04:04 2017 +0100
@@ -72,6 +72,7 @@
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 2 files
+  new changesets 8685c6d34325:4957bfdac07e
   (run 'hg update' to get a working copy)
   $ cat ../errors.log
   $ hg push -R ../other
@@ -85,9 +86,9 @@
 ===================
 
   $ curl -s http://localhost:$HGPORT/?cmd=hello
-  capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob)
+  capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (glob)
   $ curl -s http://localhost:$HGPORT/?cmd=capabilities
-  _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob)
+  _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (no-eol) (glob)
 
   $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort
   bookmarks	
@@ -107,7 +108,7 @@
   remote: adding manifests
   remote: adding file changes
   remote: added 1 changesets with 1 changes to 1 files (+1 heads)
-  remote: 2 new obsolescence markers
+  remote: 1 new obsolescence markers
   remote: obsoleted 1 changesets
   $ cat ../errors.log
   $ hg push
@@ -127,8 +128,9 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to [12] files \(\+1 heads\) (re)
-  2 new obsolescence markers
+  1 new obsolescence markers
   obsoleted 1 changesets
+  new changesets 9d1c114e7797
   (run 'hg heads' to see heads)
   $ cat ../errors.log
   $ hg -R ../other pull
@@ -149,9 +151,9 @@
   obsolete	
   phases	
   $ curl -s http://localhost:$HGPORT/?cmd=hello
-  capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob)
+  capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (glob)
   $ curl -s http://localhost:$HGPORT/?cmd=capabilities
-  _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob)
+  _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (no-eol) (glob)
 
   $ echo '[experimental]' >> server/.hg/hgrc
   $ echo 'evolution=!' >> server/.hg/hgrc
@@ -176,9 +178,9 @@
   phases	
 
   $ curl -s http://localhost:$HGPORT/?cmd=hello
-  capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob)
+  capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (glob)
   $ curl -s http://localhost:$HGPORT/?cmd=capabilities
-  _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob)
+  _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 batch * (no-eol) (glob)
 
 Test obshashrange discover
 ===========================================
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-evolve-serveronly-legacy.t	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,63 @@
+
+  $ . ${TESTDIR}/testlib/pythonpath.sh
+
+  $ cat >> $HGRCPATH <<EOF
+  > [defaults]
+  > amend=-d "0 0"
+  > [web]
+  > push_ssl = false
+  > allow_push = *
+  > [phases]
+  > publish = False
+  > [experimental]
+  > bundle2-exp=False # < Mercurial-4.0
+  > [devel]
+  > legacy.exchange=bundle1
+  > [extensions]
+  > EOF
+
+  $ mkcommit() {
+  >    echo "$1" > "$1"
+  >    hg add "$1"
+  >    hg ci -m "add $1"
+  > }
+
+
+  $ hg init server
+
+Try the multiple ways to setup the extension
+
+  $ hg -R server log --config 'extensions.evolve.serveronly='
+  $ hg -R server log --config "extensions.evolve.serveronly=${SRCDIR}/hgext3rd/evolve/serveronly.py"
+  $ PYTHONPATH=$HGTEST_ORIG_PYTHONPATH hg -R server log --config "extensions.evolve.serveronly=${SRCDIR}/hgext3rd/evolve/serveronly.py"
+
+setup repo
+
+  $ echo "[extensions]" >> ./server/.hg/hgrc
+  $ echo "evolve.serveronly=" >> ./server/.hg/hgrc
+  $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log --traceback
+  $ cat hg.pid >> $DAEMON_PIDS
+
+  $ hg clone http://localhost:$HGPORT/ client
+  no changes found
+  updating to branch default
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cat ./errors.log
+  $ echo "[extensions]" >> ./client/.hg/hgrc
+  $ echo "evolve=" >> ./client/.hg/hgrc
+  $ cp -r client other
+
+Smoke testing
+===============
+
+  $ cd client
+  $ mkcommit 0
+  $ mkcommit a
+  $ hg push
+  pushing to http://localhost:$HGPORT/
+  searching for changes
+  abort: remote error:
+  incompatible Mercurial client; bundle2 required
+  (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
+  [255]
+  $ cat ../errors.log
--- a/tests/test-evolve-serveronly.t	Tue Jul 25 02:29:28 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-
-  $ . ${TESTDIR}/testlib/pythonpath.sh
-
-  $ cat >> $HGRCPATH <<EOF
-  > [defaults]
-  > amend=-d "0 0"
-  > [web]
-  > push_ssl = false
-  > allow_push = *
-  > [phases]
-  > publish = False
-  > [experimental]
-  > bundle2-exp=False # < Mercurial-4.0
-  > [devel]
-  > legacy.exchange=bundle1
-  > [extensions]
-  > EOF
-
-  $ mkcommit() {
-  >    echo "$1" > "$1"
-  >    hg add "$1"
-  >    hg ci -m "add $1"
-  > }
-
-
-  $ hg init server
-
-Try the multiple ways to setup the extension
-
-  $ hg -R server log --config 'extensions.evolve.serveronly='
-  $ hg -R server log --config "extensions.evolve.serveronly=${SRCDIR}/hgext3rd/evolve/serveronly.py"
-  $ PYTHONPATH=$HGTEST_ORIG_PYTHONPATH hg -R server log --config "extensions.evolve.serveronly=${SRCDIR}/hgext3rd/evolve/serveronly.py"
-
-setup repo
-
-  $ echo "[extensions]" >> ./server/.hg/hgrc
-  $ echo "evolve.serveronly=" >> ./server/.hg/hgrc
-  $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log --traceback
-  $ cat hg.pid >> $DAEMON_PIDS
-
-  $ hg clone http://localhost:$HGPORT/ client
-  no changes found
-  updating to branch default
-  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ cat ./errors.log
-  $ echo "[extensions]" >> ./client/.hg/hgrc
-  $ echo "evolve=" >> ./client/.hg/hgrc
-  $ cp -r client other
-
-Smoke testing
-===============
-
-  $ cd client
-  $ mkcommit 0
-  $ mkcommit a
-  $ hg push
-  pushing to http://localhost:$HGPORT/
-  searching for changes
-  remote: adding changesets
-  remote: adding manifests
-  remote: adding file changes
-  remote: added 2 changesets with 2 changes to 2 files
-  $ hg pull
-  pulling from http://localhost:$HGPORT/
-  searching for changes
-  no changes found
-  $ cat ../errors.log
-  $ hg pull -R ../other
-  pulling from http://localhost:$HGPORT/
-  requesting all changes
-  adding changesets
-  adding manifests
-  adding file changes
-  added 2 changesets with 2 changes to 2 files
-  pull obsolescence markers
-  the remote repository use years old versions of Mercurial and evolve
-  pulling obsmarker using legacy method
-  (please upgrade your server)
-  (run 'hg update' to get a working copy)
-  $ cat ../errors.log
-  $ hg push -R ../other
-  pushing to http://localhost:$HGPORT/
-  searching for changes
-  no changes found
-  [1]
-  $ cat ../errors.log
-
-Capacity testing
-===================
-
-  $ curl -s http://localhost:$HGPORT/?cmd=hello
-  capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob)
-  $ curl -s http://localhost:$HGPORT/?cmd=capabilities
-  _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob)
-
-  $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort
-  bookmarks	
-  namespaces	
-  obsolete	
-  phases	
-
-Push
-=============
-
-  $ echo 'A' > a
-  $ hg amend
-  $ hg push
-  pushing to http://localhost:$HGPORT/
-  searching for changes
-  remote: adding changesets
-  remote: adding manifests
-  remote: adding file changes
-  remote: added 1 changesets with 1 changes to 1 files (+1 heads)
-  the remote repository use years old versions of Mercurial and evolve
-  pushing obsmarker using legacy method
-  (please upgrade your server)
-  pushing 2 obsolescence markers (* bytes) (glob)
-  remote: 2 obsolescence markers added
-  remote: obsoleted 1 changesets
-  $ cat ../errors.log
-  $ hg push
-  pushing to http://localhost:$HGPORT/
-  searching for changes
-  no changes found
-  [1]
-  $ cat ../errors.log
-
-Pull
-=============
-
-  $ hg -R ../other pull
-  pulling from http://localhost:$HGPORT/
-  searching for changes
-  adding changesets
-  adding manifests
-  adding file changes
-  added 1 changesets with 1 changes to [12] files \(\+1 heads\) (re)
-  pull obsolescence markers
-  the remote repository use years old versions of Mercurial and evolve
-  pulling obsmarker using legacy method
-  (please upgrade your server)
-  2 obsolescence markers added
-  obsoleted 1 changesets
-  (run 'hg heads' to see heads)
-  $ cat ../errors.log
-  $ hg -R ../other pull
-  pulling from http://localhost:$HGPORT/
-  searching for changes
-  no changes found
-  $ cat ../errors.log
-
-  $ cd ..
-
-Test disabling obsolete advertisement
-===========================================
-(used by bitbucket to select which repo use evolve)
-
-  $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort
-  bookmarks	
-  namespaces	
-  obsolete	
-  phases	
-  $ curl -s http://localhost:$HGPORT/?cmd=hello
-  capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob)
-  $ curl -s http://localhost:$HGPORT/?cmd=capabilities
-  _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob)
-
-  $ echo '[experimental]' >> server/.hg/hgrc
-  $ echo 'evolution=!' >> server/.hg/hgrc
-  $ $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
-  $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
-  $ cat hg.pid >> $DAEMON_PIDS
-
-  $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort
-  bookmarks	
-  namespaces	
-  phases	
-  $ curl -s http://localhost:$HGPORT/?cmd=hello | grep _evoext_pushobsmarkers_0
-  [1]
-  $ curl -s http://localhost:$HGPORT/?cmd=capabilities | grep _evoext_pushobsmarkers_0
-  [1]
-
-  $ echo 'evolution=' >> server/.hg/hgrc
-  $ $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
-  $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
-  $ cat hg.pid >> $DAEMON_PIDS
-
-  $ curl -s "http://localhost:$HGPORT/?cmd=listkeys&namespace=namespaces" | sort
-  bookmarks	
-  namespaces	
-  obsolete	
-  phases	
-  $ curl -s http://localhost:$HGPORT/?cmd=hello
-  capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (glob)
-  $ curl -s http://localhost:$HGPORT/?cmd=capabilities
-  _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_pullobsmarkers_0 _evoext_pushobsmarkers_0 batch * (no-eol) (glob)
--- a/tests/test-evolve-split.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-evolve-split.t	Tue Nov 14 23:04:04 2017 +0100
@@ -44,7 +44,7 @@
   $ hg commit -m "_pp"
   $ hg prune --succ "desc(_oo) + desc(_pp)" -r "desc('oo+pp')" --split
   1 changesets pruned
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg log -G
   @  4:d0dcf24cddd3@default(draft) _pp
   |
--- a/tests/test-evolve-templates.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-evolve-templates.t	Tue Nov 14 23:04:04 2017 +0100
@@ -19,7 +19,7 @@
   >     {if(successors, "\n  semi-colon: {join(successors, "; ")}")}\
   >     {if(obsfate, "\n  Fate: {join(obsfate, "\n  Fate: ")}\n")}\n'
   > fatelog = log -G -T '{node|short}\n{if(obsfate, "  Obsfate: {join(obsfate, "; ")}\n\n")}'
-  > fatelogjson = log -G -T '{node|short} {obsfate|json}\n'
+  > fatelogjson = log -G -T '{node|short} {obsfatedata|json}\n'
   > EOF
 
 Test templates on amended commit
@@ -33,33 +33,27 @@
   $ mkcommit ROOT
   $ mkcommit A0
   $ echo 42 >> A0
-  $ HGUSER=test1 hg amend -m "A1" --config devel.default-date="1234567890 0"
+  $ HGUSER=test hg amend -m "A1" --config devel.default-date="1234567890 0"
   $ HGUSER=test2 hg amend -m "A2" --config devel.default-date="987654321 0"
   $ hg log --hidden -G
-  @  changeset:   4:d004c8f274b9
+  @  changeset:   3:d004c8f274b9
   |  tag:         tip
   |  parent:      0:ea207398892e
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     A2
   |
-  | x  changeset:   3:a468dc9b3633
+  | x  changeset:   2:a468dc9b3633
   |/   parent:      0:ea207398892e
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten by test2 as d004c8f274b9
+  |    obsolete:    reworded using amend as 3:d004c8f274b9 by test2
   |    summary:     A1
   |
-  | x  changeset:   2:f137d23bb3e1
-  | |  user:        test
-  | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  obsolete:    pruned by test1
-  | |  summary:     temporary amend commit for 471f378eab4c
-  | |
   | x  changeset:   1:471f378eab4c
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten by test1 as a468dc9b3633
+  |    obsolete:    rewritten using amend as 2:a468dc9b3633
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -76,30 +70,51 @@
 
 Precursors template should show current revision as it is the working copy
   $ hg olog tip
-  o  d004c8f274b9 (4) A2
+  o  d004c8f274b9 (3) A2
   |
-  x  a468dc9b3633 (3) A1
-  |    rewritten(description) by test2 (Thu Apr 19 04:25:21 2001 +0000) as d004c8f274b9
+  x  a468dc9b3633 (2) A1
+  |    rewritten(description) as d004c8f274b9 by test2 (Thu Apr 19 04:25:21 2001 +0000)
   |
   @  471f378eab4c (1) A0
-       rewritten(description, content) by test1 (Fri Feb 13 23:31:30 2009 +0000) as a468dc9b3633
+       rewritten(description, content) as a468dc9b3633 by test (Fri Feb 13 23:31:30 2009 +0000)
   
   $ hg tlog
   o  d004c8f274b9
-  |    Precursors: 471f378eab4c
-  |    semi-colon: 471f378eab4c
+  |    Precursors: 1:471f378eab4c
+  |    semi-colon: 1:471f378eab4c
   | @  471f378eab4c
-  |/     Successors: [d004c8f274b9]
-  |      semi-colon: [d004c8f274b9]
-  |      Fate: rewritten by test1, test2 as d004c8f274b9
+  |/     Successors: 3:d004c8f274b9
+  |      semi-colon: 3:d004c8f274b9
+  |      Fate: rewritten using amend as 3:d004c8f274b9 by test, test2
   |
   o  ea207398892e
   
+
+  $ hg log -G
+  o  changeset:   3:d004c8f274b9
+  |  tag:         tip
+  |  parent:      0:ea207398892e
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     A2
+  |
+  | @  changeset:   1:471f378eab4c
+  |/   user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    obsolete:    rewritten using amend as 3:d004c8f274b9 by test, test2
+  |    summary:     A0
+  |
+  o  changeset:   0:ea207398892e
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     ROOT
+  
+
   $ hg fatelog -q
   o  d004c8f274b9
   |
   | @  471f378eab4c
-  |/     Obsfate: rewritten as d004c8f274b9
+  |/     Obsfate: rewritten using amend as 3:d004c8f274b9
   |
   o  ea207398892e
   
@@ -108,7 +123,7 @@
   o  d004c8f274b9
   |
   | @  471f378eab4c
-  |/     Obsfate: rewritten by test1, test2 as d004c8f274b9
+  |/     Obsfate: rewritten using amend as 3:d004c8f274b9 by test, test2
   |
   o  ea207398892e
   
@@ -116,7 +131,7 @@
   o  d004c8f274b9
   |
   | @  471f378eab4c
-  |/     Obsfate: rewritten by test1, test2 as d004c8f274b9 (between 2001-04-19 04:25 +0000 and 2009-02-13 23:31 +0000)
+  |/     Obsfate: rewritten using amend as 3:d004c8f274b9 by test, test2 (between 2001-04-19 04:25 +0000 and 2009-02-13 23:31 +0000)
   |
   o  ea207398892e
   
@@ -147,12 +162,12 @@
 Precursors template should show current revision as it is the working copy
   $ hg tlog
   o  d004c8f274b9
-  |    Precursors: a468dc9b3633
-  |    semi-colon: a468dc9b3633
+  |    Precursors: 2:a468dc9b3633
+  |    semi-colon: 2:a468dc9b3633
   | @  a468dc9b3633
-  |/     Successors: [d004c8f274b9]
-  |      semi-colon: [d004c8f274b9]
-  |      Fate: rewritten by test2 as d004c8f274b9
+  |/     Successors: 3:d004c8f274b9
+  |      semi-colon: 3:d004c8f274b9
+  |      Fate: reworded using amend as 3:d004c8f274b9 by test2
   |
   o  ea207398892e
   
@@ -160,22 +175,19 @@
 --hidden  
   $ hg tlog --hidden
   o  d004c8f274b9
-  |    Precursors: a468dc9b3633
-  |    semi-colon: a468dc9b3633
+  |    Precursors: 2:a468dc9b3633
+  |    semi-colon: 2:a468dc9b3633
   | @  a468dc9b3633
-  |/     Precursors: 471f378eab4c
-  |      semi-colon: 471f378eab4c
-  |      Successors: [d004c8f274b9]
-  |      semi-colon: [d004c8f274b9]
-  |      Fate: rewritten by test2 as d004c8f274b9
+  |/     Precursors: 1:471f378eab4c
+  |      semi-colon: 1:471f378eab4c
+  |      Successors: 3:d004c8f274b9
+  |      semi-colon: 3:d004c8f274b9
+  |      Fate: reworded using amend as 3:d004c8f274b9 by test2
   |
-  | x  f137d23bb3e1
-  | |    Fate: pruned by test1
-  | |
   | x  471f378eab4c
-  |/     Successors: [a468dc9b3633]
-  |      semi-colon: [a468dc9b3633]
-  |      Fate: rewritten by test1 as a468dc9b3633
+  |/     Successors: 2:a468dc9b3633
+  |      semi-colon: 2:a468dc9b3633
+  |      Fate: rewritten using amend as 2:a468dc9b3633
   |
   o  ea207398892e
   
@@ -183,7 +195,7 @@
   o  d004c8f274b9
   |
   | @  a468dc9b3633
-  |/     Obsfate: rewritten by test2 as d004c8f274b9 (at 2001-04-19 04:25 +0000)
+  |/     Obsfate: reworded using amend as 3:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000)
   |
   o  ea207398892e
   
@@ -196,22 +208,19 @@
   
   $ hg tlog --hidden
   @  d004c8f274b9
-  |    Precursors: a468dc9b3633
-  |    semi-colon: a468dc9b3633
+  |    Precursors: 2:a468dc9b3633
+  |    semi-colon: 2:a468dc9b3633
   | x  a468dc9b3633
-  |/     Precursors: 471f378eab4c
-  |      semi-colon: 471f378eab4c
-  |      Successors: [d004c8f274b9]
-  |      semi-colon: [d004c8f274b9]
-  |      Fate: rewritten by test2 as d004c8f274b9
+  |/     Precursors: 1:471f378eab4c
+  |      semi-colon: 1:471f378eab4c
+  |      Successors: 3:d004c8f274b9
+  |      semi-colon: 3:d004c8f274b9
+  |      Fate: reworded using amend as 3:d004c8f274b9 by test2
   |
-  | x  f137d23bb3e1
-  | |    Fate: pruned by test1
-  | |
   | x  471f378eab4c
-  |/     Successors: [a468dc9b3633]
-  |      semi-colon: [a468dc9b3633]
-  |      Fate: rewritten by test1 as a468dc9b3633
+  |/     Successors: 2:a468dc9b3633
+  |      semi-colon: 2:a468dc9b3633
+  |      Fate: rewritten using amend as 2:a468dc9b3633
   |
   o  ea207398892e
   
@@ -225,27 +234,22 @@
   @  d004c8f274b9
   |
   | x  a468dc9b3633
-  |/     Obsfate: rewritten by test2 as d004c8f274b9 (at 2001-04-19 04:25 +0000)
+  |/     Obsfate: reworded using amend as 3:d004c8f274b9 by test2 (at 2001-04-19 04:25 +0000)
   |
-  | x  f137d23bb3e1
-  | |    Obsfate: pruned by test1 (at 2009-02-13 23:31 +0000)
-  | |
   | x  471f378eab4c
-  |/     Obsfate: rewritten by test1 as a468dc9b3633 (at 2009-02-13 23:31 +0000)
+  |/     Obsfate: rewritten using amend as 2:a468dc9b3633 by test (at 2009-02-13 23:31 +0000)
   |
   o  ea207398892e
   
 
   $ hg fatelogjson --hidden
-  @  d004c8f274b9 ""
+  @  d004c8f274b9 []
   |
-  | x  a468dc9b3633 [{"markers": [["a468dc9b36338b14fdb7825f55ce3df4e71517ad", ["d004c8f274b9ec480a47a93c10dac5eee63adb78"], 0, [["ef1", "1"], ["user", "test2"]], [987654321.0, 0], null]], "max_date": [987654321.0, 0], "min_date": [987654321.0, 0], "successors": ["d004c8f274b9ec480a47a93c10dac5eee63adb78"], "users": ["test2"], "verb": "rewritten"}]
+  | x  a468dc9b3633 [{"markers": [["a468dc9b36338b14fdb7825f55ce3df4e71517ad", ["d004c8f274b9ec480a47a93c10dac5eee63adb78"], 0, [["ef1", "1"], ["operation", "amend"], ["user", "test2"]], [987654321.0, 0], null]], "max_date": [987654321.0, 0], "min_date": [987654321.0, 0], "successors": ["d004c8f274b9ec480a47a93c10dac5eee63adb78"], "users": ["test2"], "verb": "reworded"}]
   |/
-  | x  f137d23bb3e1 [{"markers": [["f137d23bb3e11dc1daeb6264fac9cb2433782e15", [], 0, [["ef1", "0"], ["user", "test1"]], [1234567890.0, 0], ["471f378eab4c5e25f6c77f785b27c936efb22874"]]], "max_date": [1234567890.0, 0], "min_date": [1234567890.0, 0], "successors": [], "users": ["test1"], "verb": "pruned"}]
-  | |
-  | x  471f378eab4c [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"], 0, [["ef1", "9"], ["user", "test1"]], [1234567890.0, 0], null]], "max_date": [1234567890.0, 0], "min_date": [1234567890.0, 0], "successors": ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"], "users": ["test1"], "verb": "rewritten"}]
+  | x  471f378eab4c [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"], 0, [["ef1", "9"], ["operation", "amend"], ["user", "test"]], [1234567890.0, 0], null]], "max_date": [1234567890.0, 0], "min_date": [1234567890.0, 0], "successors": ["a468dc9b36338b14fdb7825f55ce3df4e71517ad"], "users": ["test"], "verb": "rewritten"}]
   |/
-  o  ea207398892e ""
+  o  ea207398892e []
   
 
 Test templates with splitted commit
@@ -322,7 +326,7 @@
   | x  changeset:   1:471597cad322
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    split as 337fec4d2edc, f257fde29c7a
+  |    obsolete:    split as 2:337fec4d2edc, 3:f257fde29c7a
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -342,15 +346,15 @@
 Precursors template should show current revision as it is the working copy
   $ hg tlog
   o  f257fde29c7a
-  |    Precursors: 471597cad322
-  |    semi-colon: 471597cad322
+  |    Precursors: 1:471597cad322
+  |    semi-colon: 1:471597cad322
   o  337fec4d2edc
-  |    Precursors: 471597cad322
-  |    semi-colon: 471597cad322
+  |    Precursors: 1:471597cad322
+  |    semi-colon: 1:471597cad322
   | @  471597cad322
-  |/     Successors: [337fec4d2edc, f257fde29c7a]
-  |      semi-colon: [337fec4d2edc, f257fde29c7a]
-  |      Fate: split as 337fec4d2edc, f257fde29c7a
+  |/     Successors: 2:337fec4d2edc 3:f257fde29c7a
+  |      semi-colon: 2:337fec4d2edc 3:f257fde29c7a
+  |      Fate: split as 2:337fec4d2edc, 3:f257fde29c7a
   |
   o  ea207398892e
   
@@ -360,7 +364,7 @@
   o  337fec4d2edc
   |
   | @  471597cad322
-  |/     Obsfate: split as 337fec4d2edc, f257fde29c7a
+  |/     Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a
   |
   o  ea207398892e
   
@@ -381,15 +385,15 @@
 --hidden
   $ hg tlog --hidden
   @  f257fde29c7a
-  |    Precursors: 471597cad322
-  |    semi-colon: 471597cad322
+  |    Precursors: 1:471597cad322
+  |    semi-colon: 1:471597cad322
   o  337fec4d2edc
-  |    Precursors: 471597cad322
-  |    semi-colon: 471597cad322
+  |    Precursors: 1:471597cad322
+  |    semi-colon: 1:471597cad322
   | x  471597cad322
-  |/     Successors: [337fec4d2edc, f257fde29c7a]
-  |      semi-colon: [337fec4d2edc, f257fde29c7a]
-  |      Fate: split as 337fec4d2edc, f257fde29c7a
+  |/     Successors: 2:337fec4d2edc 3:f257fde29c7a
+  |      semi-colon: 2:337fec4d2edc 3:f257fde29c7a
+  |      Fate: split as 2:337fec4d2edc, 3:f257fde29c7a
   |
   o  ea207398892e
   
@@ -399,19 +403,19 @@
   o  337fec4d2edc
   |
   | x  471597cad322
-  |/     Obsfate: split as 337fec4d2edc, f257fde29c7a
+  |/     Obsfate: split as 2:337fec4d2edc, 3:f257fde29c7a
   |
   o  ea207398892e
   
 
   $ hg fatelogjson --hidden
-  @  f257fde29c7a ""
+  @  f257fde29c7a []
   |
-  o  337fec4d2edc ""
+  o  337fec4d2edc []
   |
   | x  471597cad322 [{"markers": [["471597cad322d1f659bb169751be9133dad92ef3", ["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"], 0, [["ef1", "12"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["337fec4d2edcf0e7a467e35f818234bc620068b5", "f257fde29c7a847c9b607f6e958656d0df0fb15c"], "users": ["test"], "verb": "split"}]
   |/
-  o  ea207398892e ""
+  o  ea207398892e []
   
 
 Test templates with folded commit
@@ -456,13 +460,13 @@
   | x  changeset:   2:0dec01379d3b
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  obsolete:    rewritten as eb5a0daa2192
+  | |  obsolete:    rewritten as 3:eb5a0daa2192
   | |  summary:     B0
   | |
   | x  changeset:   1:471f378eab4c
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as eb5a0daa2192
+  |    obsolete:    rewritten as 3:eb5a0daa2192
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -481,12 +485,12 @@
 Precursors template should show current revision as it is the working copy
   $ hg tlog
   o  eb5a0daa2192
-  |    Precursors: 471f378eab4c
-  |    semi-colon: 471f378eab4c
+  |    Precursors: 1:471f378eab4c
+  |    semi-colon: 1:471f378eab4c
   | @  471f378eab4c
-  |/     Successors: [eb5a0daa2192]
-  |      semi-colon: [eb5a0daa2192]
-  |      Fate: rewritten as eb5a0daa2192
+  |/     Successors: 3:eb5a0daa2192
+  |      semi-colon: 3:eb5a0daa2192
+  |      Fate: rewritten as 3:eb5a0daa2192
   |
   o  ea207398892e
   
@@ -494,7 +498,7 @@
   o  eb5a0daa2192
   |
   | @  471f378eab4c
-  |/     Obsfate: rewritten as eb5a0daa2192
+  |/     Obsfate: rewritten as 3:eb5a0daa2192
   |
   o  ea207398892e
   
@@ -507,17 +511,17 @@
 displayed
   $ hg tlog
   o  eb5a0daa2192
-  |    Precursors: 0dec01379d3b 471f378eab4c
-  |    semi-colon: 0dec01379d3b; 471f378eab4c
+  |    Precursors: 2:0dec01379d3b 1:471f378eab4c
+  |    semi-colon: 2:0dec01379d3b; 1:471f378eab4c
   | @  0dec01379d3b
-  | |    Successors: [eb5a0daa2192]
-  | |    semi-colon: [eb5a0daa2192]
-  | |    Fate: rewritten as eb5a0daa2192
+  | |    Successors: 3:eb5a0daa2192
+  | |    semi-colon: 3:eb5a0daa2192
+  | |    Fate: rewritten as 3:eb5a0daa2192
   | |
   | x  471f378eab4c
-  |/     Successors: [eb5a0daa2192]
-  |      semi-colon: [eb5a0daa2192]
-  |      Fate: rewritten as eb5a0daa2192
+  |/     Successors: 3:eb5a0daa2192
+  |      semi-colon: 3:eb5a0daa2192
+  |      Fate: rewritten as 3:eb5a0daa2192
   |
   o  ea207398892e
   
@@ -525,10 +529,10 @@
   o  eb5a0daa2192
   |
   | @  0dec01379d3b
-  | |    Obsfate: rewritten as eb5a0daa2192
+  | |    Obsfate: rewritten as 3:eb5a0daa2192
   | |
   | x  471f378eab4c
-  |/     Obsfate: rewritten as eb5a0daa2192
+  |/     Obsfate: rewritten as 3:eb5a0daa2192
   |
   o  ea207398892e
   
@@ -547,17 +551,17 @@
 --hidden
   $ hg tlog --hidden
   @  eb5a0daa2192
-  |    Precursors: 0dec01379d3b 471f378eab4c
-  |    semi-colon: 0dec01379d3b; 471f378eab4c
+  |    Precursors: 2:0dec01379d3b 1:471f378eab4c
+  |    semi-colon: 2:0dec01379d3b; 1:471f378eab4c
   | x  0dec01379d3b
-  | |    Successors: [eb5a0daa2192]
-  | |    semi-colon: [eb5a0daa2192]
-  | |    Fate: rewritten as eb5a0daa2192
+  | |    Successors: 3:eb5a0daa2192
+  | |    semi-colon: 3:eb5a0daa2192
+  | |    Fate: rewritten as 3:eb5a0daa2192
   | |
   | x  471f378eab4c
-  |/     Successors: [eb5a0daa2192]
-  |      semi-colon: [eb5a0daa2192]
-  |      Fate: rewritten as eb5a0daa2192
+  |/     Successors: 3:eb5a0daa2192
+  |      semi-colon: 3:eb5a0daa2192
+  |      Fate: rewritten as 3:eb5a0daa2192
   |
   o  ea207398892e
   
@@ -565,22 +569,22 @@
   @  eb5a0daa2192
   |
   | x  0dec01379d3b
-  | |    Obsfate: rewritten as eb5a0daa2192
+  | |    Obsfate: rewritten as 3:eb5a0daa2192
   | |
   | x  471f378eab4c
-  |/     Obsfate: rewritten as eb5a0daa2192
+  |/     Obsfate: rewritten as 3:eb5a0daa2192
   |
   o  ea207398892e
   
 
   $ hg fatelogjson --hidden
-  @  eb5a0daa2192 ""
+  @  eb5a0daa2192 []
   |
   | x  0dec01379d3b [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["ef1", "13"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], "users": ["test"], "verb": "rewritten"}]
   | |
   | x  471f378eab4c [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["ef1", "9"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], "users": ["test"], "verb": "rewritten"}]
   |/
-  o  ea207398892e ""
+  o  ea207398892e []
   
 
 Test templates with divergence
@@ -605,7 +609,7 @@
   | x  changeset:   1:471f378eab4c
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as fdf9bde5129a
+  |    obsolete:    reworded using amend as 2:fdf9bde5129a
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -618,28 +622,28 @@
   working directory parent is obsolete! (471f378eab4c)
   (use 'hg evolve' to update to its successor: fdf9bde5129a)
   $ hg amend -m "A2"
-  2 new divergent changesets
+  2 new content-divergent changesets
   $ hg log --hidden -G
   @  changeset:   3:65b757b745b9
   |  tag:         tip
   |  parent:      0:ea207398892e
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  trouble:     divergent
+  |  instability: content-divergent
   |  summary:     A2
   |
   | o  changeset:   2:fdf9bde5129a
   |/   parent:      0:ea207398892e
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    trouble:     divergent
+  |    instability: content-divergent
   |    summary:     A1
   |
   | x  changeset:   1:471f378eab4c
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as fdf9bde5129a
-  |    obsolete:    rewritten as 65b757b745b9
+  |    obsolete:    reworded using amend as 2:fdf9bde5129a
+  |    obsolete:    reworded using amend as 3:65b757b745b9
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -655,21 +659,21 @@
   $ hg up 'desc(A0)' --hidden
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   working directory parent is obsolete! (471f378eab4c)
-  (471f378eab4c has diverged, use 'hg evolve --list --divergent' to resolve the issue)
+  (471f378eab4c has diverged, use 'hg evolve --list --content-divergent' to resolve the issue)
 
 Precursors template should show current revision as it is the working copy
   $ hg tlog
   o  019fadeab383
-  |    Precursors: 471f378eab4c
-  |    semi-colon: 471f378eab4c
+  |    Precursors: 1:471f378eab4c
+  |    semi-colon: 1:471f378eab4c
   | o  fdf9bde5129a
-  |/     Precursors: 471f378eab4c
-  |      semi-colon: 471f378eab4c
+  |/     Precursors: 1:471f378eab4c
+  |      semi-colon: 1:471f378eab4c
   | @  471f378eab4c
-  |/     Successors: [fdf9bde5129a], [019fadeab383]
-  |      semi-colon: [fdf9bde5129a]; [019fadeab383]
-  |      Fate: rewritten as fdf9bde5129a
-  |      Fate: rewritten as 019fadeab383
+  |/     Successors: 2:fdf9bde5129a; 4:019fadeab383
+  |      semi-colon: 2:fdf9bde5129a; 4:019fadeab383
+  |      Fate: reworded using amend as 2:fdf9bde5129a
+  |      Fate: reworded using amend as 4:019fadeab383
   |
   o  ea207398892e
   
@@ -679,7 +683,7 @@
   | o  fdf9bde5129a
   |/
   | @  471f378eab4c
-  |/     Obsfate: rewritten as fdf9bde5129a; rewritten as 019fadeab383
+  |/     Obsfate: reworded using amend as 2:fdf9bde5129a; reworded using amend as 4:019fadeab383
   |
   o  ea207398892e
   
@@ -706,23 +710,23 @@
 Precursors template should a precursor as we force its display with --hidden
   $ hg tlog --hidden
   o  019fadeab383
-  |    Precursors: 65b757b745b9
-  |    semi-colon: 65b757b745b9
+  |    Precursors: 3:65b757b745b9
+  |    semi-colon: 3:65b757b745b9
   | x  65b757b745b9
-  |/     Precursors: 471f378eab4c
-  |      semi-colon: 471f378eab4c
-  |      Successors: [019fadeab383]
-  |      semi-colon: [019fadeab383]
-  |      Fate: rewritten as 019fadeab383
+  |/     Precursors: 1:471f378eab4c
+  |      semi-colon: 1:471f378eab4c
+  |      Successors: 4:019fadeab383
+  |      semi-colon: 4:019fadeab383
+  |      Fate: reworded using amend as 4:019fadeab383
   |
   | @  fdf9bde5129a
-  |/     Precursors: 471f378eab4c
-  |      semi-colon: 471f378eab4c
+  |/     Precursors: 1:471f378eab4c
+  |      semi-colon: 1:471f378eab4c
   | x  471f378eab4c
-  |/     Successors: [fdf9bde5129a], [65b757b745b9]
-  |      semi-colon: [fdf9bde5129a]; [65b757b745b9]
-  |      Fate: rewritten as fdf9bde5129a
-  |      Fate: rewritten as 65b757b745b9
+  |/     Successors: 2:fdf9bde5129a; 3:65b757b745b9
+  |      semi-colon: 2:fdf9bde5129a; 3:65b757b745b9
+  |      Fate: reworded using amend as 2:fdf9bde5129a
+  |      Fate: reworded using amend as 3:65b757b745b9
   |
   o  ea207398892e
   
@@ -730,26 +734,26 @@
   o  019fadeab383
   |
   | x  65b757b745b9
-  |/     Obsfate: rewritten as 019fadeab383
+  |/     Obsfate: reworded using amend as 4:019fadeab383
   |
   | @  fdf9bde5129a
   |/
   | x  471f378eab4c
-  |/     Obsfate: rewritten as fdf9bde5129a; rewritten as 65b757b745b9
+  |/     Obsfate: reworded using amend as 2:fdf9bde5129a; reworded using amend as 3:65b757b745b9
   |
   o  ea207398892e
   
 
   $ hg fatelogjson --hidden
-  o  019fadeab383 ""
+  o  019fadeab383 []
   |
-  | x  65b757b745b9 [{"markers": [["65b757b745b935093c87a2bccd877521cccffcbd", ["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"], 0, [["ef1", "1"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"], "users": ["test"], "verb": "rewritten"}]
+  | x  65b757b745b9 [{"markers": [["65b757b745b935093c87a2bccd877521cccffcbd", ["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"], 0, [["ef1", "1"], ["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["019fadeab383f6699fa83ad7bdb4d82ed2c0e5ab"], "users": ["test"], "verb": "reworded"}]
   |/
-  | @  fdf9bde5129a ""
+  | @  fdf9bde5129a []
   |/
-  | x  471f378eab4c [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], 0, [["ef1", "1"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], "users": ["test"], "verb": "rewritten"}, {"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["65b757b745b935093c87a2bccd877521cccffcbd"], 0, [["ef1", "1"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["65b757b745b935093c87a2bccd877521cccffcbd"], "users": ["test"], "verb": "rewritten"}]
+  | x  471f378eab4c [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], 0, [["ef1", "1"], ["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], "users": ["test"], "verb": "reworded"}, {"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["65b757b745b935093c87a2bccd877521cccffcbd"], 0, [["ef1", "1"], ["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["65b757b745b935093c87a2bccd877521cccffcbd"], "users": ["test"], "verb": "reworded"}]
   |/
-  o  ea207398892e ""
+  o  ea207398892e []
   
 
 Test templates with amended + folded commit
@@ -775,7 +779,7 @@
   | x  changeset:   2:0dec01379d3b
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as b7ea6d14e664
+  |    obsolete:    reworded using amend as 3:b7ea6d14e664
   |    summary:     B0
   |
   o  changeset:   1:471f378eab4c
@@ -803,19 +807,19 @@
   | |  parent:      1:471f378eab4c
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  obsolete:    rewritten as eb5a0daa2192
+  | |  obsolete:    rewritten as 4:eb5a0daa2192
   | |  summary:     B1
   | |
   | | x  changeset:   2:0dec01379d3b
   | |/   user:        test
   | |    date:        Thu Jan 01 00:00:00 1970 +0000
-  | |    obsolete:    rewritten as b7ea6d14e664
+  | |    obsolete:    reworded using amend as 3:b7ea6d14e664
   | |    summary:     B0
   | |
   | x  changeset:   1:471f378eab4c
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as eb5a0daa2192
+  |    obsolete:    rewritten as 4:eb5a0daa2192
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -832,12 +836,12 @@
   (use 'hg evolve' to update to its successor: eb5a0daa2192)
   $ hg tlog
   o  eb5a0daa2192
-  |    Precursors: 471f378eab4c
-  |    semi-colon: 471f378eab4c
+  |    Precursors: 1:471f378eab4c
+  |    semi-colon: 1:471f378eab4c
   | @  471f378eab4c
-  |/     Successors: [eb5a0daa2192]
-  |      semi-colon: [eb5a0daa2192]
-  |      Fate: rewritten as eb5a0daa2192
+  |/     Successors: 4:eb5a0daa2192
+  |      semi-colon: 4:eb5a0daa2192
+  |      Fate: rewritten as 4:eb5a0daa2192
   |
   o  ea207398892e
   
@@ -845,7 +849,7 @@
   o  eb5a0daa2192
   |
   | @  471f378eab4c
-  |/     Obsfate: rewritten as eb5a0daa2192
+  |/     Obsfate: rewritten as 4:eb5a0daa2192
   |
   o  ea207398892e
   
@@ -855,17 +859,17 @@
   (use 'hg evolve' to update to its successor: eb5a0daa2192)
   $ hg tlog
   o  eb5a0daa2192
-  |    Precursors: 0dec01379d3b 471f378eab4c
-  |    semi-colon: 0dec01379d3b; 471f378eab4c
+  |    Precursors: 2:0dec01379d3b 1:471f378eab4c
+  |    semi-colon: 2:0dec01379d3b; 1:471f378eab4c
   | @  0dec01379d3b
-  | |    Successors: [eb5a0daa2192]
-  | |    semi-colon: [eb5a0daa2192]
-  | |    Fate: rewritten as eb5a0daa2192
+  | |    Successors: 4:eb5a0daa2192
+  | |    semi-colon: 4:eb5a0daa2192
+  | |    Fate: rewritten using amend as 4:eb5a0daa2192
   | |
   | x  471f378eab4c
-  |/     Successors: [eb5a0daa2192]
-  |      semi-colon: [eb5a0daa2192]
-  |      Fate: rewritten as eb5a0daa2192
+  |/     Successors: 4:eb5a0daa2192
+  |      semi-colon: 4:eb5a0daa2192
+  |      Fate: rewritten as 4:eb5a0daa2192
   |
   o  ea207398892e
   
@@ -873,10 +877,10 @@
   o  eb5a0daa2192
   |
   | @  0dec01379d3b
-  | |    Obsfate: rewritten as eb5a0daa2192
+  | |    Obsfate: rewritten using amend as 4:eb5a0daa2192
   | |
   | x  471f378eab4c
-  |/     Obsfate: rewritten as eb5a0daa2192
+  |/     Obsfate: rewritten as 4:eb5a0daa2192
   |
   o  ea207398892e
   
@@ -887,17 +891,17 @@
   (use 'hg evolve' to update to its successor: eb5a0daa2192)
   $ hg tlog
   o  eb5a0daa2192
-  |    Precursors: 471f378eab4c b7ea6d14e664
-  |    semi-colon: 471f378eab4c; b7ea6d14e664
+  |    Precursors: 1:471f378eab4c 3:b7ea6d14e664
+  |    semi-colon: 1:471f378eab4c; 3:b7ea6d14e664
   | @  b7ea6d14e664
-  | |    Successors: [eb5a0daa2192]
-  | |    semi-colon: [eb5a0daa2192]
-  | |    Fate: rewritten as eb5a0daa2192
+  | |    Successors: 4:eb5a0daa2192
+  | |    semi-colon: 4:eb5a0daa2192
+  | |    Fate: rewritten as 4:eb5a0daa2192
   | |
   | x  471f378eab4c
-  |/     Successors: [eb5a0daa2192]
-  |      semi-colon: [eb5a0daa2192]
-  |      Fate: rewritten as eb5a0daa2192
+  |/     Successors: 4:eb5a0daa2192
+  |      semi-colon: 4:eb5a0daa2192
+  |      Fate: rewritten as 4:eb5a0daa2192
   |
   o  ea207398892e
   
@@ -905,10 +909,10 @@
   o  eb5a0daa2192
   |
   | @  b7ea6d14e664
-  | |    Obsfate: rewritten as eb5a0daa2192
+  | |    Obsfate: rewritten as 4:eb5a0daa2192
   | |
   | x  471f378eab4c
-  |/     Obsfate: rewritten as eb5a0daa2192
+  |/     Obsfate: rewritten as 4:eb5a0daa2192
   |
   o  ea207398892e
   
@@ -922,24 +926,24 @@
   
   $ hg tlog --hidden
   @  eb5a0daa2192
-  |    Precursors: 471f378eab4c b7ea6d14e664
-  |    semi-colon: 471f378eab4c; b7ea6d14e664
+  |    Precursors: 1:471f378eab4c 3:b7ea6d14e664
+  |    semi-colon: 1:471f378eab4c; 3:b7ea6d14e664
   | x  b7ea6d14e664
-  | |    Precursors: 0dec01379d3b
-  | |    semi-colon: 0dec01379d3b
-  | |    Successors: [eb5a0daa2192]
-  | |    semi-colon: [eb5a0daa2192]
-  | |    Fate: rewritten as eb5a0daa2192
+  | |    Precursors: 2:0dec01379d3b
+  | |    semi-colon: 2:0dec01379d3b
+  | |    Successors: 4:eb5a0daa2192
+  | |    semi-colon: 4:eb5a0daa2192
+  | |    Fate: rewritten as 4:eb5a0daa2192
   | |
   | | x  0dec01379d3b
-  | |/     Successors: [b7ea6d14e664]
-  | |      semi-colon: [b7ea6d14e664]
-  | |      Fate: rewritten as b7ea6d14e664
+  | |/     Successors: 3:b7ea6d14e664
+  | |      semi-colon: 3:b7ea6d14e664
+  | |      Fate: reworded using amend as 3:b7ea6d14e664
   | |
   | x  471f378eab4c
-  |/     Successors: [eb5a0daa2192]
-  |      semi-colon: [eb5a0daa2192]
-  |      Fate: rewritten as eb5a0daa2192
+  |/     Successors: 4:eb5a0daa2192
+  |      semi-colon: 4:eb5a0daa2192
+  |      Fate: rewritten as 4:eb5a0daa2192
   |
   o  ea207398892e
   
@@ -947,26 +951,26 @@
   @  eb5a0daa2192
   |
   | x  b7ea6d14e664
-  | |    Obsfate: rewritten as eb5a0daa2192
+  | |    Obsfate: rewritten as 4:eb5a0daa2192
   | |
   | | x  0dec01379d3b
-  | |/     Obsfate: rewritten as b7ea6d14e664
+  | |/     Obsfate: reworded using amend as 3:b7ea6d14e664
   | |
   | x  471f378eab4c
-  |/     Obsfate: rewritten as eb5a0daa2192
+  |/     Obsfate: rewritten as 4:eb5a0daa2192
   |
   o  ea207398892e
   
   $ hg fatelogjson --hidden
-  @  eb5a0daa2192 ""
+  @  eb5a0daa2192 []
   |
   | x  b7ea6d14e664 [{"markers": [["b7ea6d14e664bdc8922221f7992631b50da3fb07", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["ef1", "13"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], "users": ["test"], "verb": "rewritten"}]
   | |
-  | | x  0dec01379d3b [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["b7ea6d14e664bdc8922221f7992631b50da3fb07"], 0, [["ef1", "1"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["b7ea6d14e664bdc8922221f7992631b50da3fb07"], "users": ["test"], "verb": "rewritten"}]
+  | | x  0dec01379d3b [{"markers": [["0dec01379d3be6318c470ead31b1fe7ae7cb53d5", ["b7ea6d14e664bdc8922221f7992631b50da3fb07"], 0, [["ef1", "1"], ["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["b7ea6d14e664bdc8922221f7992631b50da3fb07"], "users": ["test"], "verb": "reworded"}]
   | |/
   | x  471f378eab4c [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], 0, [["ef1", "9"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["eb5a0daa21923bbf8caeb2c42085b9e463861fd0"], "users": ["test"], "verb": "rewritten"}]
   |/
-  o  ea207398892e ""
+  o  ea207398892e []
   
 
 Test template with pushed and pulled obs markers
@@ -1010,13 +1014,13 @@
   |/   parent:      0:ea207398892e
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as 7a230b46bf61
+  |    obsolete:    reworded using amend as 3:7a230b46bf61
   |    summary:     A1
   |
   | x  changeset:   1:471f378eab4c
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as fdf9bde5129a
+  |    obsolete:    reworded using amend as 2:fdf9bde5129a
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -1034,6 +1038,7 @@
   added 1 changesets with 0 changes to 1 files (+1 heads)
   2 new obsolescence markers
   obsoleted 1 changesets
+  new changesets 7a230b46bf61
   (run 'hg heads' to see heads, 'hg merge' to merge)
   working directory parent is obsolete! (471f378eab4c)
   (use 'hg evolve' to update to its successor: 7a230b46bf61)
@@ -1048,7 +1053,7 @@
   | @  changeset:   1:471f378eab4c
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as 7a230b46bf61
+  |    obsolete:    reworded using amend as 2:7a230b46bf61
   |    summary:     A0
   |
   o  changeset:   0:ea207398892e
@@ -1061,12 +1066,12 @@
 
   $ hg tlog
   o  7a230b46bf61
-  |    Precursors: 471f378eab4c
-  |    semi-colon: 471f378eab4c
+  |    Precursors: 1:471f378eab4c
+  |    semi-colon: 1:471f378eab4c
   | @  471f378eab4c
-  |/     Successors: [7a230b46bf61]
-  |      semi-colon: [7a230b46bf61]
-  |      Fate: rewritten as 7a230b46bf61
+  |/     Successors: 2:7a230b46bf61
+  |      semi-colon: 2:7a230b46bf61
+  |      Fate: reworded using amend as 2:7a230b46bf61
   |
   o  ea207398892e
   
@@ -1074,7 +1079,7 @@
   o  7a230b46bf61
   |
   | @  471f378eab4c
-  |/     Obsfate: rewritten by test as 7a230b46bf61 (at 1970-01-01 00:00 +0000)
+  |/     Obsfate: reworded using amend as 2:7a230b46bf61 by test (at 1970-01-01 00:00 +0000)
   |
   o  ea207398892e
   
@@ -1092,12 +1097,12 @@
   
   $ hg tlog --hidden
   @  7a230b46bf61
-  |    Precursors: 471f378eab4c
-  |    semi-colon: 471f378eab4c
+  |    Precursors: 1:471f378eab4c
+  |    semi-colon: 1:471f378eab4c
   | x  471f378eab4c
-  |/     Successors: [7a230b46bf61]
-  |      semi-colon: [7a230b46bf61]
-  |      Fate: rewritten as 7a230b46bf61
+  |/     Successors: 2:7a230b46bf61
+  |      semi-colon: 2:7a230b46bf61
+  |      Fate: reworded using amend as 2:7a230b46bf61
   |
   o  ea207398892e
   
@@ -1105,17 +1110,17 @@
   @  7a230b46bf61
   |
   | x  471f378eab4c
-  |/     Obsfate: rewritten by test as 7a230b46bf61 (at 1970-01-01 00:00 +0000)
+  |/     Obsfate: reworded using amend as 2:7a230b46bf61 by test (at 1970-01-01 00:00 +0000)
   |
   o  ea207398892e
   
 
   $ hg fatelogjson --hidden
-  @  7a230b46bf61 ""
+  @  7a230b46bf61 []
   |
-  | x  471f378eab4c [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], 0, [["ef1", "1"], ["user", "test"]], [0.0, 0], null], ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e", ["7a230b46bf61e50b30308c6cfd7bd1269ef54702"], 0, [["ef1", "1"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["7a230b46bf61e50b30308c6cfd7bd1269ef54702"], "users": ["test"], "verb": "rewritten"}]
+  | x  471f378eab4c [{"markers": [["471f378eab4c5e25f6c77f785b27c936efb22874", ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e"], 0, [["ef1", "1"], ["operation", "amend"], ["user", "test"]], [0.0, 0], null], ["fdf9bde5129a28d4548fadd3f62b265cdd3b7a2e", ["7a230b46bf61e50b30308c6cfd7bd1269ef54702"], 0, [["ef1", "1"], ["operation", "amend"], ["user", "test"]], [0.0, 0], null]], "max_date": [0.0, 0], "min_date": [0.0, 0], "successors": ["7a230b46bf61e50b30308c6cfd7bd1269ef54702"], "users": ["test"], "verb": "reworded"}]
   |/
-  o  ea207398892e ""
+  o  ea207398892e []
   
 
 Test templates with pruned commits
--- a/tests/test-evolve-topic.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-evolve-topic.t	Tue Nov 14 23:04:04 2017 +0100
@@ -31,12 +31,15 @@
   $ mkcommit aaa
   $ mkcommit bbb
   $ hg topic foo
+  marked working directory as topic: foo
   $ mkcommit ccc
+  active topic 'foo' grew its first changeset
   $ mkcommit ddd
   $ mkcommit eee
   $ mkcommit fff
   $ hg topic bar
   $ mkcommit ggg
+  active topic 'bar' grew its first changeset
   $ mkcommit hhh
   $ mkcommit iii
   $ mkcommit jjj
@@ -74,6 +77,7 @@
   $ hg topic -l 
   ### topic: foo (?)
   ### branch: default (?)
+  ### target: default (branch)
   t4@ add fff (current)
   t3: add eee
   t2: add ddd
@@ -83,16 +87,16 @@
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ echo ddd >> ddd
   $ hg amend
-  6 new unstable changesets
+  6 new orphan changesets
   $ hg up 'desc(fff)'
   3 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ echo fff >> fff
   $ hg amend
 
   $ hg log -G
-  @  13 - {foo} e104f49bab28 add fff (draft)
+  @  11 - {foo} e104f49bab28 add fff (draft)
   |
-  | o  11 - {foo} d9cacd156ffc add ddd (draft)
+  | o  10 - {foo} d9cacd156ffc add ddd (draft)
   | |
   | | o  9 - {bar} 1d964213b023 add jjj (draft)
   | | |
@@ -119,16 +123,16 @@
 
   $ hg evolve --all
   move:[4] add eee
-  atop:[11] add ddd
-  move:[13] add fff
-  atop:[14] add eee
+  atop:[10] add ddd
+  move:[11] add fff
+  atop:[12] add eee
   working directory is now at 070c5573d8f9
   $ hg log -G
-  @  15 - {foo} 070c5573d8f9 add fff (draft)
+  @  13 - {foo} 070c5573d8f9 add fff (draft)
   |
-  o  14 - {foo} 42b49017ff90 add eee (draft)
+  o  12 - {foo} 42b49017ff90 add eee (draft)
   |
-  o  11 - {foo} d9cacd156ffc add ddd (draft)
+  o  10 - {foo} d9cacd156ffc add ddd (draft)
   |
   | o  9 - {bar} 1d964213b023 add jjj (draft)
   | |
@@ -156,28 +160,28 @@
 
   $ hg evolve --rev 'topic(bar)'
   move:[6] add ggg
-  atop:[15] add fff
+  atop:[13] add fff
   move:[7] add hhh
-  atop:[16] add ggg
+  atop:[14] add ggg
   move:[8] add iii
-  atop:[17] add hhh
+  atop:[15] add hhh
   move:[9] add jjj
-  atop:[18] add iii
+  atop:[16] add iii
   working directory is now at 9bf430c106b7
   $ hg log -G
-  @  19 - {bar} 9bf430c106b7 add jjj (draft)
+  @  17 - {bar} 9bf430c106b7 add jjj (draft)
   |
-  o  18 - {bar} d2dc89c57700 add iii (draft)
+  o  16 - {bar} d2dc89c57700 add iii (draft)
   |
-  o  17 - {bar} 20bc4d02aa62 add hhh (draft)
+  o  15 - {bar} 20bc4d02aa62 add hhh (draft)
   |
-  o  16 - {bar} 16d6f664b17c add ggg (draft)
+  o  14 - {bar} 16d6f664b17c add ggg (draft)
   |
-  o  15 - {foo} 070c5573d8f9 add fff (draft)
+  o  13 - {foo} 070c5573d8f9 add fff (draft)
   |
-  o  14 - {foo} 42b49017ff90 add eee (draft)
+  o  12 - {foo} 42b49017ff90 add eee (draft)
   |
-  o  11 - {foo} d9cacd156ffc add ddd (draft)
+  o  10 - {foo} d9cacd156ffc add ddd (draft)
   |
   o  2 - {foo} cced9bac76e3 add ccc (draft)
   |
@@ -196,10 +200,10 @@
   0 files updated, 0 files merged, 4 files removed, 0 files unresolved
   $ hg prev
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  [14] add eee
+  [12] add eee
   $ hg next
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  [15] add fff
+  [13] add fff
   $ hg next
   no children on topic "foo"
   do you want --no-topic
@@ -207,11 +211,11 @@
   $ hg next --no-topic
   switching to topic bar
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  [16] add ggg
+  [14] add ggg
   $ hg prev
   preserving the current topic 'bar'
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  [15] add fff
+  [13] add fff
   $ hg prev
   no parent in topic "bar"
   (do you want --no-topic)
@@ -219,4 +223,4 @@
   $ hg prev --no-topic
   switching to topic foo
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  [14] add eee
+  [12] add eee
--- a/tests/test-evolve.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-evolve.t	Tue Nov 14 23:04:04 2017 +0100
@@ -327,7 +327,7 @@
 changeset plus the updating changeset are hidden from view by default::
 
   $ hg log
-  4	feature-B: another feature (child of 568a468b60fc) - test
+  3	feature-B: another feature (child of 568a468b60fc) - test
   1	feature-A: a nifty feature - test
   0	: base - test
 
@@ -344,22 +344,18 @@
 (amend of on ancestors)
 
   $ hg amend
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg log
-  6	feature-A: a nifty feature - test
-  4	feature-B: another feature (child of 568a468b60fc) - test
+  4	feature-A: a nifty feature - test
+  3	feature-B: another feature (child of 568a468b60fc) - test
   1	: a nifty feature - test
   0	: base - test
   $ hg up -q 0
   $ glog --hidden
-  o  6:ba0ec09b1bab@default(draft) a nifty feature
+  o  4:ba0ec09b1bab@default(draft) a nifty feature
   |
-  | x  5:c296b79833d1@default(draft) temporary amend commit for 568a468b60fc
+  | o  3:6992c59c6b06@default(draft) another feature (child of 568a468b60fc)
   | |
-  | | o  4:6992c59c6b06@default(draft) another feature (child of 568a468b60fc)
-  | |/
-  | | x  3:c97947cdc7a2@default(draft) temporary amend commit for 73296a82292a
-  | | |
   | | x  2:73296a82292a@default(draft) another feature (child of 568a468b60fc)
   | |/
   | x  1:568a468b60fc@default(draft) a nifty feature
@@ -367,101 +363,99 @@
   @  0:e55e0562ee93@default(public) base
   
   $ hg debugobsolete
-  73296a82292a76fb8a7061969d2489ec0d84cd5e 6992c59c6b06a1b4a92e24ff884829ae026d018b 0 (*) {'ef1': '8', 'user': 'test'} (glob)
-  c97947cdc7a2a11cf78419f5c2c3dd3944ec79e8 0 {73296a82292a76fb8a7061969d2489ec0d84cd5e} (*) {'ef1': '0', 'user': 'test'} (glob)
-  568a468b60fc99a42d5d4ddbe181caff1eef308d ba0ec09b1babf3489b567853807f452edd46704f 0 (*) {'ef1': '8', 'user': 'test'} (glob)
-  c296b79833d1d497f33144786174bf35e04e44a3 0 {568a468b60fc99a42d5d4ddbe181caff1eef308d} (*) {'ef1': '0', 'user': 'test'} (glob)
+  73296a82292a76fb8a7061969d2489ec0d84cd5e 6992c59c6b06a1b4a92e24ff884829ae026d018b 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'}
+  568a468b60fc99a42d5d4ddbe181caff1eef308d ba0ec09b1babf3489b567853807f452edd46704f 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'}
   $ hg evolve
-  move:[4] another feature (child of 568a468b60fc)
-  atop:[6] a nifty feature
+  move:[3] another feature (child of 568a468b60fc)
+  atop:[4] a nifty feature
   merging main-file-1
   working directory is now at 99833d22b0c6
   $ hg log
-  7	feature-B: another feature (child of ba0ec09b1bab) - test
-  6	feature-A: a nifty feature - test
+  5	feature-B: another feature (child of ba0ec09b1bab) - test
+  4	feature-A: a nifty feature - test
   0	: base - test
 
 Test commit -o options
 
-  $ hg up 6
+  $ hg up -r "desc('a nifty feature')"
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ hg revert -r 7 --all
+  $ hg revert -r "desc('another feature')" --all
   adding file-from-B
   reverting main-file-1
   $ sed -i'' -e s/Zwei/deux/ main-file-1
-  $ hg commit -m 'another feature that rox' -o 7
+  $ hg commit -m 'another feature that rox' -o 5
   created new head
   $ hg log
-  8	feature-B: another feature that rox - test
-  6	feature-A: a nifty feature - test
+  6	feature-B: another feature that rox - test
+  4	feature-A: a nifty feature - test
   0	: base - test
 
 phase change turning obsolete changeset public issue a bumped warning
 
-  $ hg phase --hidden --public 7
-  1 new bumped changesets
+  $ hg phase --hidden --public 99833d22b0c6
+  1 new phase-divergent changesets
 
 all solving bumped troubled
 
-  $ hg log -G
-  @  8	feature-B: another feature that rox - test
+  $ glog
+  @  6:47d52a103155@default(draft) another feature that rox
   |
-  | o  7	: another feature (child of ba0ec09b1bab) - test
+  | o  5:99833d22b0c6@default(public) another feature (child of ba0ec09b1bab)
   |/
-  o  6	feature-A: a nifty feature - test
+  o  4:ba0ec09b1bab@default(public) a nifty feature
   |
-  o  0	: base - test
+  o  0:e55e0562ee93@default(public) base
   
-  $ hg evolve --any --traceback --bumped
-  recreate:[8] another feature that rox
-  atop:[7] another feature (child of ba0ec09b1bab)
+  $ hg evolve --any --traceback --phase-divergent
+  recreate:[6] another feature that rox
+  atop:[5] another feature (child of ba0ec09b1bab)
   computing new diff
   committed as 6707c5e1c49d
   working directory is now at 6707c5e1c49d
-  $ hg log -G
-  @  9	feature-B: bumped update to 99833d22b0c6: - test
+  $ glog
+  @  7:6707c5e1c49d@default(draft) bumped update to 99833d22b0c6:
   |
-  o  7	: another feature (child of ba0ec09b1bab) - test
+  o  5:99833d22b0c6@default(public) another feature (child of ba0ec09b1bab)
   |
-  o  6	feature-A: a nifty feature - test
+  o  4:ba0ec09b1bab@default(public) a nifty feature
   |
-  o  0	: base - test
+  o  0:e55e0562ee93@default(public) base
   
-  $ hg diff --hidden -r 9 -r 8
-  $ hg diff -r 9^ -r 9
+  $ hg diff --hidden -r 6707c5e1c49d -r 47d52a103155
+  $ hg diff -r 6707c5e1c49d^ -r 6707c5e1c49d
   diff --git a/main-file-1 b/main-file-1
   --- a/main-file-1
   +++ b/main-file-1
   @@ -3,1 +3,1 @@
   -Zwei
   +deux
-  $ hg log -r 'bumped()' # no more bumped
+  $ hg log -r 'phasedivergent()' # no more bumped
 
 test evolve --all
   $ sed -i'' -e s/deux/to/ main-file-1
   $ hg commit -m 'dansk 2!'
   $ sed -i'' -e s/Three/tre/ main-file-1
   $ hg commit -m 'dansk 3!'
-  $ hg update 9
+  $ hg update 6707c5e1c49d
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ sed -i'' -e s/Un/Én/ main-file-1
   $ hg commit --amend -m 'dansk!'
-  2 new unstable changesets
+  2 new orphan changesets
 
 (ninja test for the {trouble} template:
 
   $ hg log -G --template '{rev} {troubles}\n'
-  @  13
+  @  10
   |
-  | o  11 unstable
+  | o  9 orphan
   | |
-  | o  10 unstable
+  | o  8 orphan
   | |
-  | x  9
+  | x  7
   |/
-  o  7
+  o  5
   |
-  o  6
+  o  4
   |
   o  0
   
@@ -470,23 +464,23 @@
 (/ninja)
 
   $ hg evolve --all --traceback
-  move:[10] dansk 2!
-  atop:[13] dansk!
+  move:[8] dansk 2!
+  atop:[10] dansk!
   merging main-file-1
-  move:[11] dansk 3!
-  atop:[14] dansk 2!
+  move:[9] dansk 3!
+  atop:[11] dansk 2!
   merging main-file-1
   working directory is now at 68557e4f0048
   $ hg log -G
-  @  15	: dansk 3! - test
+  @  12	: dansk 3! - test
   |
-  o  14	: dansk 2! - test
+  o  11	: dansk 2! - test
   |
-  o  13	feature-B: dansk! - test
+  o  10	feature-B: dansk! - test
   |
-  o  7	: another feature (child of ba0ec09b1bab) - test
+  o  5	: another feature (child of ba0ec09b1bab) - test
   |
-  o  6	feature-A: a nifty feature - test
+  o  4	feature-A: a nifty feature - test
   |
   o  0	: base - test
   
@@ -514,6 +508,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets 702e4d0a6d86
   $ cd alpha
 
   $ cat << EOF > A
@@ -546,13 +541,13 @@
   checking manifests
   crosschecking files in changesets and manifests
   checking files
-  3 files, 4 changesets, 4 total revisions
+  3 files, 3 changesets, 3 total revisions
   $ hg --config extensions.hgext.mq= strip 'extinct()'
   abort: empty revision set
   [255]
 (do some garbare collection)
   $ hg --config extensions.hgext.mq= strip --hidden 'extinct()'  --config devel.strip-obsmarkers=no
-  saved backup bundle to $TESTTMP/alpha/.hg/strip-backup/e87767087a57-d7bd82e9-backup.hg (glob)
+  saved backup bundle to $TESTTMP/alpha/.hg/strip-backup/e87767087a57-a365b072-backup.hg (glob)
   $ hg verify
   checking changesets
   checking manifests
@@ -571,7 +566,8 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  2 new obsolescence markers
+  1 new obsolescence markers
+  new changesets c6dda801837c
   (run 'hg update' to get a working copy)
   $ hg up
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -770,12 +766,12 @@
   @    d26d339c513f (12) add 4
   |\
   x |    af636757ce3b (11) add 3
-  |\ \     rewritten(description, user, parent, content) by test (*) as d26d339c513f (glob)
+  |\ \     rewritten(description, user, parent, content) as d26d339c513f by test (*) (glob)
   | | |
   | \ \
   | |\ \
   | | | x  ce341209337f (4) add 4
-  | | |      rewritten(description, user, content) by test (*) as d26d339c513f (glob)
+  | | |      rewritten(description, user, content) as d26d339c513f by test (*) (glob)
   | | |
 
 Test obsstore stat
@@ -831,7 +827,7 @@
   $ hg ci -m c
   $ hg prune .^
   1 changesets pruned
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg stab --any
   move:[15] c
   atop:[13] a
@@ -848,13 +844,13 @@
   2 changesets folded
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ glog
-  @  16:98cb758db56d@default(draft) Folding with custom commit message
+  @  13:98cb758db56d@default(draft) Folding with custom commit message
   |
-  o  13:0a2f9b959bb4@default(draft) dansk!
+  o  10:0a2f9b959bb4@default(draft) dansk!
   |
-  o  7:99833d22b0c6@default(public) another feature (child of ba0ec09b1bab)
+  o  5:99833d22b0c6@default(public) another feature (child of ba0ec09b1bab)
   |
-  o  6:ba0ec09b1bab@default(public) a nifty feature
+  o  4:ba0ec09b1bab@default(public) a nifty feature
   |
   o  0:e55e0562ee93@default(public) base
   
@@ -867,10 +863,10 @@
   2 changesets folded
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg qlog
-  17 - a00182c58888 A longer
+  14 - a00182c58888 A longer
                     commit message (draft)
-  7 - 99833d22b0c6 another feature (child of ba0ec09b1bab) (public)
-  6 - ba0ec09b1bab a nifty feature (public)
+  5 - 99833d22b0c6 another feature (child of ba0ec09b1bab) (public)
+  4 - ba0ec09b1bab a nifty feature (public)
   0 - e55e0562ee93 base (public)
 
   $ cd ..
@@ -908,17 +904,17 @@
   marked working directory as branch mybranch
   (branches are permanent and global, did you want a bookmark?)
   $ hg amend
-  1 new unstable changesets
+  1 new orphan changesets
 
   $ hg evolve
   move:[3] a3
-  atop:[5] a2
+  atop:[4] a2
   working directory is now at 7c5649f73d11
 
   $ hg log -G --template '{rev} [{branch}] {desc|firstline}\n'
-  @  6 [mybranch] a3
+  @  5 [mybranch] a3
   |
-  o  5 [mybranch] a2
+  o  4 [mybranch] a2
   |
   o  1 [default] a1
   |
@@ -930,103 +926,116 @@
   $ hg up 'desc(a1)'
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg amend -m 'a1_'
-  2 new unstable changesets
+  2 new orphan changesets
   $ hg evolve
-  move:[5] a2
-  atop:[7] a1_
+  move:[4] a2
+  atop:[6] a1_
   working directory is now at eb07e22a0e63
   $ hg evolve
-  move:[6] a3
-  atop:[8] a2
+  move:[5] a3
+  atop:[7] a2
   working directory is now at 777c26ca5e78
   $ hg log -G --template '{rev} [{branch}] {desc|firstline}\n'
-  @  9 [mybranch] a3
+  @  8 [mybranch] a3
   |
-  o  8 [mybranch] a2
+  o  7 [mybranch] a2
   |
-  o  7 [default] a1_
+  o  6 [default] a1_
   |
   o  0 [default] a0
   
 
 Evolve from the middle of a stack pick the right changesets.
 
-  $ hg up 7
+  $ hg up -r "desc('a1_')"
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg ci --amend -m 'a1__'
-  2 new unstable changesets
+  2 new orphan changesets
 
-  $ hg up 8
+  $ hg up -r "desc('a2')"
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg log -G --template '{rev} [{branch}] {desc|firstline}\n'
-  o  10 [default] a1__
+  o  9 [default] a1__
   |
-  | o  9 [mybranch] a3
+  | o  8 [mybranch] a3
   | |
-  | @  8 [mybranch] a2
+  | @  7 [mybranch] a2
   | |
-  | x  7 [default] a1_
+  | x  6 [default] a1_
   |/
   o  0 [default] a0
   
   $ hg evolve
   nothing to evolve on current working copy parent
-  (2 other unstable in the repository, do you want --any or --rev)
+  (2 other orphan in the repository, do you want --any or --rev)
   [2]
 
 
 Evolve disables active bookmarks.
 
-  $ hg up 10
+  $ hg up -r "desc('a1__')"
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg bookmark testbookmark
   $ ls .hg/bookmarks*
   .hg/bookmarks
   .hg/bookmarks.* (glob)
   $ hg evolve
-  move:[8] a2
-  atop:[10] a1__
+  move:[7] a2
+  atop:[9] a1__
   (leaving bookmark testbookmark)
   working directory is now at d952e93add6f
   $ ls .hg/bookmarks*
   .hg/bookmarks
+  $ glog
+  @  10:d952e93add6f@mybranch(draft) a2
+  |
+  o  9:9f8b83c2e7f3@default(draft) a1__
+  |
+  | o  8:777c26ca5e78@mybranch(draft) a3
+  | |
+  | x  7:eb07e22a0e63@mybranch(draft) a2
+  | |
+  | x  6:faafc6cea0ba@default(draft) a1_
+  |/
+  o  0:07c1c36d9ef0@default(draft) a0
+  
 
 Possibility to select what trouble to solve first, asking for bumped before
 divergent
-  $ hg up 10
+  $ hg up -r "desc('a1__')"
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg revert -r 11 --all
+  $ hg revert -r d952e93add6f --all
   reverting a
   $ hg log -G --template '{rev} [{branch}] {desc|firstline}\n'
-  o  11 [mybranch] a2
+  o  10 [mybranch] a2
   |
-  @  10 [default] a1__
+  @  9 [default] a1__
   |
-  | o  9 [mybranch] a3
+  | o  8 [mybranch] a3
   | |
-  | x  8 [mybranch] a2
+  | x  7 [mybranch] a2
   | |
-  | x  7 [default] a1_
+  | x  6 [default] a1_
   |/
   o  0 [default] a0
   
   $ echo "hello world" > newfile
   $ hg add newfile
-  $ hg commit -m "add new file bumped" -o 11
-  $ hg phase --public --hidden 11
-  1 new bumped changesets
+  $ hg commit -m "add new file bumped" -o 10
+  $ hg phase --public --hidden d952e93add6f
+  1 new phase-divergent changesets
   $ hg log -G
-  @  12	: add new file bumped - test
+  @  11	: add new file bumped - test
   |
-  | o  11	: a2 - test
+  | o  10	: a2 - test
   |/
-  o  10	testbookmark: a1__ - test
+  o  9	testbookmark: a1__ - test
   |
-  | o  9	: a3 - test
+  | o  8	: a3 - test
   | |
-  | x  8	: a2 - test
+  | x  7	: a2 - test
   | |
-  | x  7	: a1_ - test
+  | x  6	: a1_ - test
   |/
   o  0	: a0 - test
   
@@ -1035,105 +1044,117 @@
 normally the unstable changeset would be solve first
 
   $ hg log -G
-  @  12	: add new file bumped - test
+  @  11	: add new file bumped - test
   |
-  | o  11	: a2 - test
+  | o  10	: a2 - test
   |/
-  o  10	testbookmark: a1__ - test
+  o  9	testbookmark: a1__ - test
   |
-  | o  9	: a3 - test
+  | o  8	: a3 - test
   | |
-  | x  8	: a2 - test
+  | x  7	: a2 - test
   | |
-  | x  7	: a1_ - test
+  | x  6	: a1_ - test
   |/
   o  0	: a0 - test
   
-  $ hg evolve -r 12 --bumped
-  recreate:[12] add new file bumped
-  atop:[11] a2
+  $ hg evolve -r "desc('add new file bumped')" --phase-divergent
+  recreate:[11] add new file bumped
+  atop:[10] a2
   computing new diff
   committed as f15d32934071
   working directory is now at f15d32934071
   $ hg evolve --any
-  move:[9] a3
-  atop:[13] bumped update to d952e93add6f:
+  move:[8] a3
+  atop:[12] bumped update to d952e93add6f:
   working directory is now at cce26b684bfe
+  $ glog
+  @  13:cce26b684bfe@default(draft) a3
+  |
+  o  12:f15d32934071@default(draft) bumped update to d952e93add6f:
+  |
+  o  10:d952e93add6f@mybranch(public) a2
+  |
+  o  9:9f8b83c2e7f3@default(public) a1__
+  |
+  o  0:07c1c36d9ef0@default(public) a0
+  
+
 Check that we can resolve troubles in a revset with more than one commit
-  $ hg up 14 -C
+  $ hg up cce26b684bfe -C
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ mkcommit gg
-  $ hg up 14 
+  $ hg up cce26b684bfe
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ mkcommit gh
   created new head
-  $ hg up 14 
+  $ hg up cce26b684bfe
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ printf "newline\nnewline\n" >> a
   $ hg log -G
-  o  16	: add gh - test
+  o  15	: add gh - test
   |
-  | o  15	: add gg - test
+  | o  14	: add gg - test
   |/
-  @  14	: a3 - test
+  @  13	: a3 - test
   |
-  o  13	: bumped update to d952e93add6f: - test
+  o  12	: bumped update to d952e93add6f: - test
   |
-  o  11	: a2 - test
+  o  10	: a2 - test
   |
-  o  10	testbookmark: a1__ - test
+  o  9	testbookmark: a1__ - test
   |
   o  0	: a0 - test
   
   $ hg amend
-  2 new unstable changesets
-  $ hg log -G
-  @  18	: a3 - test
+  2 new orphan changesets
+  $ glog
+  @  16:edc3c9de504e@default(draft) a3
   |
-  | o  16	: add gh - test
+  | o  15:beb41503aa3e@default(draft) add gh
   | |
-  | | o  15	: add gg - test
+  | | o  14:27247fcb2df6@default(draft) add gg
   | |/
-  | x  14	: a3 - test
+  | x  13:cce26b684bfe@default(draft) a3
   |/
-  o  13	: bumped update to d952e93add6f: - test
+  o  12:f15d32934071@default(draft) bumped update to d952e93add6f:
   |
-  o  11	: a2 - test
+  o  10:d952e93add6f@mybranch(public) a2
   |
-  o  10	testbookmark: a1__ - test
+  o  9:9f8b83c2e7f3@default(public) a1__
   |
-  o  0	: a0 - test
+  o  0:07c1c36d9ef0@default(public) a0
   
 
 Evolving an empty revset should do nothing
-  $ hg evolve --rev "16 and 15"
+  $ hg evolve --rev "beb41503aa3e and 27247fcb2df6"
   set of specified revisions is empty
   [1]
 
-  $ hg evolve --rev "14::" --bumped
-  no bumped changesets in specified revisions
-  (do you want to use --unstable)
+  $ hg evolve --rev "cce26b684bfe::" --phase-divergent
+  no phasedivergent changesets in specified revisions
+  (do you want to use --orphan)
   [2]
-  $ hg evolve --rev "14::" --unstable
-  move:[15] add gg
-  atop:[18] a3
-  move:[16] add gh
-  atop:[18] a3
+  $ hg evolve --rev "cce26b684bfe::" --orphan
+  move:[14] add gg
+  atop:[16] a3
+  move:[15] add gh
+  atop:[16] a3
   working directory is now at e02107f98737
-  $ hg log -G
-  @  20	: add gh - test
+  $ glog
+  @  18:e02107f98737@default(draft) add gh
   |
-  | o  19	: add gg - test
+  | o  17:24e63b319adf@default(draft) add gg
   |/
-  o  18	: a3 - test
+  o  16:edc3c9de504e@default(draft) a3
   |
-  o  13	: bumped update to d952e93add6f: - test
+  o  12:f15d32934071@default(draft) bumped update to d952e93add6f:
   |
-  o  11	: a2 - test
+  o  10:d952e93add6f@mybranch(public) a2
   |
-  o  10	testbookmark: a1__ - test
+  o  9:9f8b83c2e7f3@default(public) a1__
   |
-  o  0	: a0 - test
+  o  0:07c1c36d9ef0@default(public) a0
   
 Enabling commands selectively, no command enabled, next and fold and unknown
   $ cat >> $HGRCPATH <<EOF
@@ -1237,7 +1258,7 @@
   > EOF
 
 Check hg evolve --rev on singled out commit
-  $ hg up 19 -C
+  $ hg up 24e63b319adf -C
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ mkcommit j1
   $ mkcommit j2
@@ -1247,28 +1268,28 @@
   $ echo "hello" > j4
   $ hg add j4
   $ hg amend
-  2 new unstable changesets
-  $ glog -r "18::"
-  @  25:8dc373be86d9@default(draft) add j1
+  2 new orphan changesets
+  $ glog -r "edc3c9de504e::"
+  @  22:8dc373be86d9@default(draft) add j1
   |
-  | o  23:d7eadcf6eccd@default(draft) add j3
+  | o  21:d7eadcf6eccd@default(draft) add j3
   | |
-  | o  22:2223ea564144@default(draft) add j2
+  | o  20:2223ea564144@default(draft) add j2
   | |
-  | x  21:48490698b269@default(draft) add j1
+  | x  19:48490698b269@default(draft) add j1
   |/
-  | o  20:e02107f98737@default(draft) add gh
+  | o  18:e02107f98737@default(draft) add gh
   | |
-  o |  19:24e63b319adf@default(draft) add gg
+  o |  17:24e63b319adf@default(draft) add gg
   |/
-  o  18:edc3c9de504e@default(draft) a3
+  o  16:edc3c9de504e@default(draft) a3
   |
   ~
 
-  $ hg evolve --rev 23 --any
+  $ hg evolve --rev d7eadcf6eccd --any
   abort: cannot specify both "--rev" and "--any"
   [255]
-  $ hg evolve --rev 23
+  $ hg evolve --rev d7eadcf6eccd
   cannot solve instability of d7eadcf6eccd, skipping
 
 Check that uncommit respects the allowunstable option
@@ -1288,74 +1309,74 @@
   $ hg uncommit --all
   new changeset is empty
   (use 'hg prune .' to remove it)
-  $ glog -r "18::"
-  @  26:044804d0c10d@default(draft) add j1
+  $ glog -r "edc3c9de504e::"
+  @  23:044804d0c10d@default(draft) add j1
   |
-  | o  23:d7eadcf6eccd@default(draft) add j3
+  | o  21:d7eadcf6eccd@default(draft) add j3
   | |
-  | o  22:2223ea564144@default(draft) add j2
+  | o  20:2223ea564144@default(draft) add j2
   | |
-  | x  21:48490698b269@default(draft) add j1
+  | x  19:48490698b269@default(draft) add j1
   |/
-  | o  20:e02107f98737@default(draft) add gh
+  | o  18:e02107f98737@default(draft) add gh
   | |
-  o |  19:24e63b319adf@default(draft) add gg
+  o |  17:24e63b319adf@default(draft) add gg
   |/
-  o  18:edc3c9de504e@default(draft) a3
+  o  16:edc3c9de504e@default(draft) a3
   |
   ~
 
 Check that prune respects the allowunstable option
   $ hg up -C .
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg up 20
+  $ hg up e02107f98737
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg evolve --all
   nothing to evolve on current working copy parent
-  (2 other unstable in the repository, do you want --any or --rev)
+  (2 other orphan in the repository, do you want --any or --rev)
   [2]
   $ hg evolve --all --any
-  move:[22] add j2
-  atop:[26] add j1
-  move:[23] add j3
-  atop:[27] add j2
+  move:[20] add j2
+  atop:[23] add j1
+  move:[21] add j3
+  atop:[24] add j2
   working directory is now at c9a20e2d74aa
-  $ glog -r "18::"
-  @  28:c9a20e2d74aa@default(draft) add j3
+  $ glog -r "edc3c9de504e::"
+  @  25:c9a20e2d74aa@default(draft) add j3
   |
-  o  27:b0e3066231e2@default(draft) add j2
+  o  24:b0e3066231e2@default(draft) add j2
   |
-  o  26:044804d0c10d@default(draft) add j1
+  o  23:044804d0c10d@default(draft) add j1
   |
-  | o  20:e02107f98737@default(draft) add gh
+  | o  18:e02107f98737@default(draft) add gh
   | |
-  o |  19:24e63b319adf@default(draft) add gg
+  o |  17:24e63b319adf@default(draft) add gg
   |/
-  o  18:edc3c9de504e@default(draft) a3
+  o  16:edc3c9de504e@default(draft) a3
   |
   ~
-  $ hg up 19
+  $ hg up 24e63b319adf
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ mkcommit c5_
   created new head
-  $ hg prune '26 + 27'
+  $ hg prune '044804d0c10d + b0e3066231e2'
   abort: touch will orphan 1 descendants
   (see 'hg help evolution.instability')
   [255]
-  $ hg prune '19::28'
+  $ hg prune '24e63b319adf::c9a20e2d74aa'
   abort: touch will orphan 1 descendants
   (see 'hg help evolution.instability')
   [255]
-  $ hg prune '26::'
+  $ hg prune '044804d0c10d::'
   3 changesets pruned
-  $ glog -r "18::"
-  @  29:2251801b6c91@default(draft) add c5_
+  $ glog -r "edc3c9de504e::"
+  @  26:2251801b6c91@default(draft) add c5_
   |
-  | o  20:e02107f98737@default(draft) add gh
+  | o  18:e02107f98737@default(draft) add gh
   | |
-  o |  19:24e63b319adf@default(draft) add gg
+  o |  17:24e63b319adf@default(draft) add gg
   |/
-  o  18:edc3c9de504e@default(draft) a3
+  o  16:edc3c9de504e@default(draft) a3
   |
   ~
 
@@ -1367,20 +1388,20 @@
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ mkcommit unstableifparentisfolded
   created new head
-  $ glog -r "18::"
-  @  30:68330ac625b8@default(draft) add unstableifparentisfolded
+  $ glog -r "edc3c9de504e::"
+  @  27:68330ac625b8@default(draft) add unstableifparentisfolded
   |
-  | o  29:2251801b6c91@default(draft) add c5_
+  | o  26:2251801b6c91@default(draft) add c5_
   | |
-  +---o  20:e02107f98737@default(draft) add gh
+  +---o  18:e02107f98737@default(draft) add gh
   | |
-  | o  19:24e63b319adf@default(draft) add gg
+  | o  17:24e63b319adf@default(draft) add gg
   |/
-  o  18:edc3c9de504e@default(draft) a3
+  o  16:edc3c9de504e@default(draft) a3
   |
   ~
 
-  $ hg fold --exact "19::"
+  $ hg fold --exact "24e63b319adf::"
   2 changesets folded
 
 Check that evolve shows error while handling split commits
@@ -1391,14 +1412,14 @@
   > evolution=all
   > EOF
 
-  $ glog -r "18::"
-  o  31:580886d07058@default(draft) add gg
+  $ glog -r "edc3c9de504e::"
+  o  28:580886d07058@default(draft) add gg
   |
-  | @  30:68330ac625b8@default(draft) add unstableifparentisfolded
+  | @  27:68330ac625b8@default(draft) add unstableifparentisfolded
   |/
-  | o  20:e02107f98737@default(draft) add gh
+  | o  18:e02107f98737@default(draft) add gh
   |/
-  o  18:edc3c9de504e@default(draft) a3
+  o  16:edc3c9de504e@default(draft) a3
   |
   ~
 
@@ -1408,7 +1429,7 @@
   $ hg add oo pp
   $ hg commit -m "oo+pp"
   $ mkcommit uu
-  $ hg up 30
+  $ hg up 68330ac625b8
   0 files updated, 0 files merged, 3 files removed, 0 files unresolved
   $ printf "oo" > oo;
   $ hg add oo
@@ -1419,28 +1440,28 @@
   $ hg commit -m "_pp"
   $ hg prune --succ "desc(_oo) + desc(_pp)" -r "desc('oo+pp')" --split
   1 changesets pruned
-  1 new unstable changesets
-  $ glog -r "18::"
-  @  35:7a555adf2b4a@default(draft) _pp
+  1 new orphan changesets
+  $ glog -r "edc3c9de504e::"
+  @  32:7a555adf2b4a@default(draft) _pp
   |
-  o  34:2be4d2d5bf34@default(draft) _oo
+  o  31:2be4d2d5bf34@default(draft) _oo
   |
-  | o  33:53f0c003e03e@default(draft) add uu
+  | o  30:53f0c003e03e@default(draft) add uu
   | |
-  | x  32:1bf2152f4f82@default(draft) oo+pp
+  | x  29:1bf2152f4f82@default(draft) oo+pp
   |/
-  | o  31:580886d07058@default(draft) add gg
+  | o  28:580886d07058@default(draft) add gg
   | |
-  o |  30:68330ac625b8@default(draft) add unstableifparentisfolded
+  o |  27:68330ac625b8@default(draft) add unstableifparentisfolded
   |/
-  | o  20:e02107f98737@default(draft) add gh
+  | o  18:e02107f98737@default(draft) add gh
   |/
-  o  18:edc3c9de504e@default(draft) a3
+  o  16:edc3c9de504e@default(draft) a3
   |
   ~
-  $ hg evolve --rev "18::"
-  move:[33] add uu
-  atop:[35] _pp
+  $ hg evolve --rev "edc3c9de504e::"
+  move:[30] add uu
+  atop:[32] _pp
   working directory is now at 43c3f5ef149f
 
 
@@ -1450,7 +1471,7 @@
   $ echo "will be amended" > newfile
   $ hg commit -m "will be amended"
   $ hg parents
-  37	: will be amended - test
+  34	: will be amended - test
 
   $ echo "will be evolved safely" >> a
   $ hg commit -m "will be evolved safely"
@@ -1460,16 +1481,39 @@
   $ hg add newlyadded
   $ hg commit -m "will cause conflict at evolve"
 
-  $ hg update -q 37
+  $ glog -r "edc3c9de504e::"
+  @  36:02e943732647@default(draft) will cause conflict at evolve
+  |
+  o  35:f8e30e9317aa@default(draft) will be evolved safely
+  |
+  o  34:36030b147271@default(draft) will be amended
+  |
+  o  33:43c3f5ef149f@default(draft) add uu
+  |
+  o  32:7a555adf2b4a@default(draft) _pp
+  |
+  o  31:2be4d2d5bf34@default(draft) _oo
+  |
+  | o  28:580886d07058@default(draft) add gg
+  | |
+  o |  27:68330ac625b8@default(draft) add unstableifparentisfolded
+  |/
+  | o  18:e02107f98737@default(draft) add gh
+  |/
+  o  16:edc3c9de504e@default(draft) a3
+  |
+  ~
+
+  $ hg update -q 36030b147271
   $ echo "amended" > newfile
   $ hg amend -m "amended"
-  2 new unstable changesets
+  2 new orphan changesets
 
-  $ hg evolve --rev "37::"
-  move:[38] will be evolved safely
-  atop:[41] amended
-  move:[39] will cause conflict at evolve
-  atop:[42] will be evolved safely
+  $ hg evolve --rev "36030b147271::"
+  move:[35] will be evolved safely
+  atop:[37] amended
+  move:[36] will cause conflict at evolve
+  atop:[38] will be evolved safely
   merging newfile
   warning: conflicts while merging newfile! (edit, then use 'hg resolve --mark')
   evolve failed!
@@ -1477,20 +1521,18 @@
   abort: unresolved merge conflicts (see hg help resolve)
   [255]
 
-  $ glog -r "36::" --hidden
-  @  42:c904da5245b0@default(draft) will be evolved safely
+  $ glog -r "43c3f5ef149f::" --hidden
+  @  38:c904da5245b0@default(draft) will be evolved safely
   |
-  o  41:34ae045ec400@default(draft) amended
+  o  37:34ae045ec400@default(draft) amended
   |
-  | x  40:e88bee38ffc2@default(draft) temporary amend commit for 36030b147271
+  | o  36:02e943732647@default(draft) will cause conflict at evolve
   | |
-  | | o  39:02e943732647@default(draft) will cause conflict at evolve
-  | | |
-  | | x  38:f8e30e9317aa@default(draft) will be evolved safely
-  | |/
-  | x  37:36030b147271@default(draft) will be amended
+  | x  35:f8e30e9317aa@default(draft) will be evolved safely
+  | |
+  | x  34:36030b147271@default(draft) will be amended
   |/
-  o  36:43c3f5ef149f@default(draft) add uu
+  o  33:43c3f5ef149f@default(draft) add uu
   |
   ~
 
--- a/tests/test-exchange-obsmarkers-case-A1.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-exchange-obsmarkers-case-A1.t	Tue Nov 14 23:04:04 2017 +0100
@@ -113,6 +113,7 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files
   1 new obsolescence markers
+  new changesets f5bc6836db60
   (run 'hg update' to get a working copy)
   ## post pull state
   # obstore: main
@@ -154,6 +155,7 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files
   1 new obsolescence markers
+  new changesets f5bc6836db60
   (run 'hg update' to get a working copy)
   ## post pull state
   # obstore: main
@@ -267,6 +269,7 @@
   adding file changes
   added 2 changesets with 2 changes to 2 files
   1 new obsolescence markers
+  new changesets f5bc6836db60:f6fbb35d8ac9
   (run 'hg update' to get a working copy)
   ## post pull state
   # obstore: main
@@ -308,6 +311,7 @@
   adding file changes
   added 2 changesets with 2 changes to 2 files
   1 new obsolescence markers
+  new changesets f5bc6836db60:f6fbb35d8ac9
   (run 'hg update' to get a working copy)
   ## post pull state
   # obstore: main
--- a/tests/test-exchange-obsmarkers-case-A2.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-exchange-obsmarkers-case-A2.t	Tue Nov 14 23:04:04 2017 +0100
@@ -124,6 +124,7 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files
   1 new obsolescence markers
+  new changesets f5bc6836db60
   (run 'hg update' to get a working copy)
   ## post pull state
   # obstore: main
--- a/tests/test-exchange-obsmarkers-case-A3.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-exchange-obsmarkers-case-A3.t	Tue Nov 14 23:04:04 2017 +0100
@@ -145,6 +145,7 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files
   1 new obsolescence markers
+  new changesets e5ea8f9c7314
   (run 'hg update' to get a working copy)
   ## post pull state
   # obstore: main
@@ -263,8 +264,9 @@
   added 1 changesets with 1 changes to 1 files (+1 heads)
   1 new obsolescence markers
   obsoleted 1 changesets
+  new changesets e5ea8f9c7314
   (run 'hg heads' to see heads, 'hg merge' to merge)
-  1 new unstable changesets
+  1 new orphan changesets
   ## post pull state
   # obstore: main
   28b51eb45704506b5c603decd6bf7ac5e0f6a52f e5ea8f9c73143125d36658e90ef70c6d2027a5b7 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
--- a/tests/test-exchange-obsmarkers-case-A4.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-exchange-obsmarkers-case-A4.t	Tue Nov 14 23:04:04 2017 +0100
@@ -133,6 +133,7 @@
   adding file changes
   added 2 changesets with 2 changes to 2 files
   1 new obsolescence markers
+  new changesets 28b51eb45704:06055a7959d4
   (run 'hg update' to get a working copy)
   ## post pull state
   # obstore: main
--- a/tests/test-exchange-obsmarkers-case-A5.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-exchange-obsmarkers-case-A5.t	Tue Nov 14 23:04:04 2017 +0100
@@ -141,6 +141,7 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files
   1 new obsolescence markers
+  new changesets f6298a8ac3a4
   (run 'hg update' to get a working copy)
   ## post pull state
   # obstore: main
--- a/tests/test-exchange-obsmarkers-case-B3.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-exchange-obsmarkers-case-B3.t	Tue Nov 14 23:04:04 2017 +0100
@@ -120,6 +120,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets f5bc6836db60
   (run 'hg update' to get a working copy)
   ## post pull state
   # obstore: main
--- a/tests/test-exchange-obsmarkers-case-B5.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-exchange-obsmarkers-case-B5.t	Tue Nov 14 23:04:04 2017 +0100
@@ -157,6 +157,7 @@
   adding file changes
   added 3 changesets with 3 changes to 3 files
   1 new obsolescence markers
+  new changesets 28b51eb45704:1d0f3cd25300
   (run 'hg update' to get a working copy)
   ## post pull state
   # obstore: main
--- a/tests/test-exchange-obsmarkers-case-C1.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-exchange-obsmarkers-case-C1.t	Tue Nov 14 23:04:04 2017 +0100
@@ -58,7 +58,7 @@
   $ mkcommit A
   $ mkcommit B
   $ hg prune -qd '0 0' '.~1'
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg prune -qd '0 0' .
   $ hg log -G --hidden
   x  f6fbb35d8ac9 (draft): B
--- a/tests/test-exchange-obsmarkers-case-C2.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-exchange-obsmarkers-case-C2.t	Tue Nov 14 23:04:04 2017 +0100
@@ -131,6 +131,7 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files
   2 new obsolescence markers
+  new changesets e5ea8f9c7314
   (run 'hg update' to get a working copy)
   ## post pull state
   # obstore: main
@@ -178,6 +179,7 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files
   2 new obsolescence markers
+  new changesets e5ea8f9c7314
   (run 'hg update' to get a working copy)
   ## post pull state
   # obstore: main
--- a/tests/test-exchange-obsmarkers-case-D1.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-exchange-obsmarkers-case-D1.t	Tue Nov 14 23:04:04 2017 +0100
@@ -127,6 +127,7 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files
   2 new obsolescence markers
+  new changesets e5ea8f9c7314
   (run 'hg update' to get a working copy)
   ## post pull state
   # obstore: main
@@ -174,6 +175,7 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files
   2 new obsolescence markers
+  new changesets e5ea8f9c7314
   (run 'hg update' to get a working copy)
   ## post pull state
   # obstore: main
--- a/tests/test-exchange-obsmarkers-case-D4.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-exchange-obsmarkers-case-D4.t	Tue Nov 14 23:04:04 2017 +0100
@@ -140,6 +140,7 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files
   2 new obsolescence markers
+  new changesets e5ea8f9c7314
   (run 'hg update' to get a working copy)
   ## post pull state
   # obstore: main
--- a/tests/test-inhibit.t	Tue Jul 25 02:29:28 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,932 +0,0 @@
-  $ cat >> $HGRCPATH <<EOF
-  > [ui]
-  > logtemplate = {rev}:{node|short} {desc}\n
-  > [experimental]
-  > prunestrip=True
-  > evolution=createmarkers
-  > [extensions]
-  > rebase=
-  > strip=
-  > EOF
-  $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
-  $ echo "directaccess=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/hack/directaccess.py" >> $HGRCPATH
-  $ echo "inhibit=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/hack/inhibit.py" >> $HGRCPATH
-  $ mkcommit() {
-  >    echo "$1" > "$1"
-  >    hg add "$1"
-  >    hg ci -m "add $1"
-  > }
-
-  $ hg init inhibit
-  $ cd inhibit
-  $ mkcommit cA
-  $ mkcommit cB
-  $ mkcommit cC
-  $ mkcommit cD
-  $ hg up 'desc(cA)'
-  0 files updated, 0 files merged, 3 files removed, 0 files unresolved
-  $ mkcommit cE
-  created new head
-  $ mkcommit cG
-  $ mkcommit cH
-  $ mkcommit cJ
-  $ hg log -G
-  @  7:18214586bf78 add cJ
-  |
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  | o  3:2db36d8066ff add cD
-  | |
-  | o  2:7df62a38b9bf add cC
-  | |
-  | o  1:02bcbc3f6e56 add cB
-  |/
-  o  0:54ccbc537fc2 add cA
-  
-
-plain prune
-
-  $ hg strip 1::
-  3 changesets pruned
-  $ hg log -G
-  @  7:18214586bf78 add cJ
-  |
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
-  $ hg debugobsinhibit --hidden 1::
-  $ hg log -G
-  @  7:18214586bf78 add cJ
-  |
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  | o  3:2db36d8066ff add cD
-  | |
-  | o  2:7df62a38b9bf add cC
-  | |
-  | o  1:02bcbc3f6e56 add cB
-  |/
-  o  0:54ccbc537fc2 add cA
-  
-  $ hg strip --hidden 1::
-  3 changesets pruned
-  $ hg log -G
-  @  7:18214586bf78 add cJ
-  |
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
-
-after amend
-
-  $ echo babar > cJ
-  $ hg commit --amend
-  $ hg log -G
-  @  9:55c73a90e4b4 add cJ
-  |
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
-  $ hg debugobsinhibit --hidden 18214586bf78
-  $ hg log -G
-  @  9:55c73a90e4b4 add cJ
-  |
-  | o  7:18214586bf78 add cJ
-  |/
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
-
-and no divergence
-
-  $ hg summary
-  parent: 9:55c73a90e4b4 tip
-   add cJ
-  branch: default
-  commit: (clean)
-  update: 1 new changesets, 2 branch heads (merge)
-  phases: 6 draft
-
-check public revision got cleared
-(when adding the second inhibitor, the first one is removed because it is public)
-
-  $ wc -m .hg/store/obsinhibit | sed -e 's/^[ \t]*//'
-  20 .hg/store/obsinhibit
-  $ hg strip 7
-  1 changesets pruned
-  $ hg debugobsinhibit --hidden 18214586bf78
-  $ wc -m .hg/store/obsinhibit | sed -e 's/^[ \t]*//'
-  20 .hg/store/obsinhibit
-  $ hg log -G
-  @  9:55c73a90e4b4 add cJ
-  |
-  | o  7:18214586bf78 add cJ
-  |/
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
-  $ hg phase --public 7
-  $ hg strip 9
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  working directory now at cf5c4f4554ce
-  1 changesets pruned
-  $ hg log -G
-  o  7:18214586bf78 add cJ
-  |
-  @  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
-  $ hg debugobsinhibit --hidden 55c73a90e4b4
-  $ wc -m .hg/store/obsinhibit | sed -e 's/^[ \t]*//'
-  20 .hg/store/obsinhibit
-  $ hg log -G
-  o  9:55c73a90e4b4 add cJ
-  |
-  | o  7:18214586bf78 add cJ
-  |/
-  @  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
-Update should inhibit all related unstable commits
-
-  $ hg update 2 --hidden
-  2 files updated, 0 files merged, 3 files removed, 0 files unresolved
-  $ hg log -G
-  o  9:55c73a90e4b4 add cJ
-  |
-  | o  7:18214586bf78 add cJ
-  |/
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  | @  2:7df62a38b9bf add cC
-  | |
-  | o  1:02bcbc3f6e56 add cB
-  |/
-  o  0:54ccbc537fc2 add cA
-  
-
-  $ hg update 9
-  4 files updated, 0 files merged, 2 files removed, 0 files unresolved
-  $ hg log -G
-  @  9:55c73a90e4b4 add cJ
-  |
-  | o  7:18214586bf78 add cJ
-  |/
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  | o  2:7df62a38b9bf add cC
-  | |
-  | o  1:02bcbc3f6e56 add cB
-  |/
-  o  0:54ccbc537fc2 add cA
-  
-  $ hg strip --hidden 1::
-  3 changesets pruned
-  $ hg log -G
-  @  9:55c73a90e4b4 add cJ
-  |
-  | o  7:18214586bf78 add cJ
-  |/
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
-
-Bookmark should inhibit all related unstable commits
-  $ hg bookmark -r 2 book1  --hidden
-  $ hg log -G
-  @  9:55c73a90e4b4 add cJ
-  |
-  | o  7:18214586bf78 add cJ
-  |/
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  | o  2:7df62a38b9bf add cC
-  | |
-  | o  1:02bcbc3f6e56 add cB
-  |/
-  o  0:54ccbc537fc2 add cA
-  
-
-Removing a bookmark with bookmark -D should prune the changes underneath
-that are not reachable from another bookmark or head
-
-  $ hg bookmark -r 1 book2
-  $ hg bookmark -D book1  --config experimental.evolution=createmarkers #--config to make sure prune is not registered as a command.
-  bookmark 'book1' deleted
-  1 changesets pruned
-  $ hg log -G
-  @  9:55c73a90e4b4 add cJ
-  |
-  | o  7:18214586bf78 add cJ
-  |/
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  | o  1:02bcbc3f6e56 add cB
-  |/
-  o  0:54ccbc537fc2 add cA
-  
-  $ hg bookmark -D book2
-  bookmark 'book2' deleted
-  1 changesets pruned
-  $ hg log -G
-  @  9:55c73a90e4b4 add cJ
-  |
-  | o  7:18214586bf78 add cJ
-  |/
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
-Test edge cases of bookmark -D
-  $ hg book -D book2 -m hello
-  abort: Cannot use both -m and -D
-  [255]
-
-  $ hg book -Draster-fix
-  abort: Error, please check your command
-  (make sure to put a space between -D and your bookmark name)
-  [255]
-
-Test that direct access make changesets visible
-
-  $ hg export 2db36d8066ff 02bcbc3f6e56
-  # HG changeset patch
-  # User test
-  # Date 0 0
-  #      Thu Jan 01 00:00:00 1970 +0000
-  # Node ID 2db36d8066ff50e8be3d3e6c2da1ebc0a8381d82
-  # Parent  7df62a38b9bf9daf968de235043ba88a8ef43393
-  add cD
-  
-  diff -r 7df62a38b9bf -r 2db36d8066ff cD
-  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-  +++ b/cD	Thu Jan 01 00:00:00 1970 +0000
-  @@ -0,0 +1,1 @@
-  +cD
-  # HG changeset patch
-  # User test
-  # Date 0 0
-  #      Thu Jan 01 00:00:00 1970 +0000
-  # Node ID 02bcbc3f6e56fb2928efec2c6e24472720bf5511
-  # Parent  54ccbc537fc2d6845a5d61337c1cfb80d1d2815e
-  add cB
-  
-  diff -r 54ccbc537fc2 -r 02bcbc3f6e56 cB
-  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-  +++ b/cB	Thu Jan 01 00:00:00 1970 +0000
-  @@ -0,0 +1,1 @@
-  +cB
-
-But only with hash
-
-  $ hg export 2db36d8066ff::
-  # HG changeset patch
-  # User test
-  # Date 0 0
-  #      Thu Jan 01 00:00:00 1970 +0000
-  # Node ID 2db36d8066ff50e8be3d3e6c2da1ebc0a8381d82
-  # Parent  7df62a38b9bf9daf968de235043ba88a8ef43393
-  add cD
-  
-  diff -r 7df62a38b9bf -r 2db36d8066ff cD
-  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-  +++ b/cD	Thu Jan 01 00:00:00 1970 +0000
-  @@ -0,0 +1,1 @@
-  +cD
-
-  $ hg export 1 3
-  abort: hidden revision '1'!
-  (use --hidden to access hidden revisions; pruned)
-  [255]
-
-
-Test directaccess in a larger revset
-
-  $ hg log -r '. + .^ + 2db36d8066ff' -T '{node|short}\n'
-  55c73a90e4b4
-  cf5c4f4554ce
-  2db36d8066ff
-
-Test directaccess only takes hashes
-
-  $ HOOKPATH=$TESTTMP/printexplicitaccess.py
-  $ cat >> $HOOKPATH <<EOF
-  > def hook(ui, repo, **kwds):
-  >     for i in sorted(repo._explicitaccess):
-  >         ui.write('directaccess: %s\n' % i)
-  > EOF
-
-  $ hg log -r 1 -r 2 -r 2db36d8066f -T '{rev}\n' --config hooks.post-log=python:$HOOKPATH:hook
-  1
-  2
-  3
-  directaccess: 3
-
-With severals hidden sha, rebase of one hidden stack onto another one:
-  $ hg update -C 0
-  0 files updated, 0 files merged, 4 files removed, 0 files unresolved
-  $ mkcommit cK
-  created new head
-  $ mkcommit cL
-  $ hg update -C 9
-  4 files updated, 0 files merged, 2 files removed, 0 files unresolved
-  $ hg log -G
-  o  11:53a94305e133 add cL
-  |
-  o  10:ad78ff7d621f add cK
-  |
-  | @  9:55c73a90e4b4 add cJ
-  | |
-  | | o  7:18214586bf78 add cJ
-  | |/
-  | o  6:cf5c4f4554ce add cH
-  | |
-  | o  5:5419eb264a33 add cG
-  | |
-  | o  4:98065434e5c6 add cE
-  |/
-  o  0:54ccbc537fc2 add cA
-  
-  $ hg strip --hidden 10:
-  2 changesets pruned
-  $ hg log -G
-  @  9:55c73a90e4b4 add cJ
-  |
-  | o  7:18214586bf78 add cJ
-  |/
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
-  $ hg rebase -s 10 -d 3 
-  abort: hidden revision '3'!
-  (use --hidden to access hidden revisions; pruned)
-  [255]
-  $ hg rebase -r ad78ff7d621f -r 53a94305e133 -d  2db36d8066ff --config experimental.rebaseskipobsolete=0
-  Warning: accessing hidden changesets 2db36d8066ff for write operation
-  Warning: accessing hidden changesets ad78ff7d621f,53a94305e133 for write operation
-  rebasing 10:ad78ff7d621f "add cK"
-  rebasing 11:53a94305e133 "add cL"
-  $ hg log -G
-  o  13:2f7b7704d714 add cL
-  |
-  o  12:fe1634cbe235 add cK
-  |
-  | @  9:55c73a90e4b4 add cJ
-  | |
-  | | o  7:18214586bf78 add cJ
-  | |/
-  | o  6:cf5c4f4554ce add cH
-  | |
-  | o  5:5419eb264a33 add cG
-  | |
-  | o  4:98065434e5c6 add cE
-  | |
-  o |  3:2db36d8066ff add cD
-  | |
-  o |  2:7df62a38b9bf add cC
-  | |
-  o |  1:02bcbc3f6e56 add cB
-  |/
-  o  0:54ccbc537fc2 add cA
-  
-
-Check that amending in the middle of a stack does not show obsolete revs
-Since we are doing operation in the middle of the stack we cannot just
-have createmarkers as we are creating instability
-
-  $ cat >> $HGRCPATH <<EOF
-  > [experimental]
-  > evolution=all
-  > EOF
-
-  $ hg strip --hidden 1::
-  5 changesets pruned
-  $ hg log -G
-  @  9:55c73a90e4b4 add cJ
-  |
-  | o  7:18214586bf78 add cJ
-  |/
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
-  $ hg up 7
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ mkcommit cL
-  $ mkcommit cM
-  $ mkcommit cN
-  $ hg log -G
-  @  16:a438c045eb37 add cN
-  |
-  o  15:2d66e189f5b5 add cM
-  |
-  o  14:d66ccb8c5871 add cL
-  |
-  | o  9:55c73a90e4b4 add cJ
-  | |
-  o |  7:18214586bf78 add cJ
-  |/
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
-  $ hg up 15
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ echo "mmm" >> cM
-  $ hg amend
-  $ hg log -G
-  @  18:210589181b14 add cM
-  |
-  | o  16:a438c045eb37 add cN
-  | |
-  | o  15:2d66e189f5b5 add cM
-  |/
-  o  14:d66ccb8c5871 add cL
-  |
-  | o  9:55c73a90e4b4 add cJ
-  | |
-  o |  7:18214586bf78 add cJ
-  |/
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
-Check that rebasing a commit twice makes the commit visible again
-
-  $ hg rebase -d 18 -r 16 --keep
-  rebasing 16:a438c045eb37 "add cN"
-  $ hg log -r 14:: -G
-  o  19:104eed5354c7 add cN
-  |
-  @  18:210589181b14 add cM
-  |
-  | o  16:a438c045eb37 add cN
-  | |
-  | o  15:2d66e189f5b5 add cM
-  |/
-  o  14:d66ccb8c5871 add cL
-  |
-  ~
-  $ hg strip -r 210589181b14
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  working directory now at d66ccb8c5871
-  2 changesets pruned
-
-Using a hash prefix solely made of digits should work
-  $ hg update 210589181
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg rebase -d 18 -r 16 --keep
-  rebasing 16:a438c045eb37 "add cN"
-  $ hg log -r 14:: -G
-  o  19:104eed5354c7 add cN
-  |
-  @  18:210589181b14 add cM
-  |
-  | o  16:a438c045eb37 add cN
-  | |
-  | o  15:2d66e189f5b5 add cM
-  |/
-  o  14:d66ccb8c5871 add cL
-  |
-  ~
-
-Test prunestrip
-
-  $ hg book foo -r 104eed5354c7
-  $ hg strip -r 210589181b14
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  working directory now at d66ccb8c5871
-  2 changesets pruned
-  $ hg log -r 14:: -G -T '{rev}:{node|short} {desc|firstline} {bookmarks}\n'
-  o  16:a438c045eb37 add cN
-  |
-  o  15:2d66e189f5b5 add cM
-  |
-  @  14:d66ccb8c5871 add cL foo
-  |
-  ~
-
-Check that --hidden used with inhibit does not hide every obsolete commit
-We show the log before and after a log -G --hidden, they should be the same
-  $ hg log -G
-  o  16:a438c045eb37 add cN
-  |
-  o  15:2d66e189f5b5 add cM
-  |
-  @  14:d66ccb8c5871 add cL
-  |
-  | o  9:55c73a90e4b4 add cJ
-  | |
-  o |  7:18214586bf78 add cJ
-  |/
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
-  $ hg log -G --hidden
-  x  19:104eed5354c7 add cN
-  |
-  x  18:210589181b14 add cM
-  |
-  | x  17:b3c3274523f9 temporary amend commit for 2d66e189f5b5
-  | |
-  | | o  16:a438c045eb37 add cN
-  | |/
-  | o  15:2d66e189f5b5 add cM
-  |/
-  @  14:d66ccb8c5871 add cL
-  |
-  | x  13:2f7b7704d714 add cL
-  | |
-  | x  12:fe1634cbe235 add cK
-  | |
-  | | x  11:53a94305e133 add cL
-  | | |
-  | | x  10:ad78ff7d621f add cK
-  | | |
-  | | | o  9:55c73a90e4b4 add cJ
-  | | | |
-  +-------x  8:e84f73d9ad36 temporary amend commit for 18214586bf78
-  | | | |
-  o-----+  7:18214586bf78 add cJ
-   / / /
-  | | o  6:cf5c4f4554ce add cH
-  | | |
-  | | o  5:5419eb264a33 add cG
-  | | |
-  | | o  4:98065434e5c6 add cE
-  | |/
-  x |  3:2db36d8066ff add cD
-  | |
-  x |  2:7df62a38b9bf add cC
-  | |
-  x |  1:02bcbc3f6e56 add cB
-  |/
-  o  0:54ccbc537fc2 add cA
-  
-
-  $ hg log -G
-  o  16:a438c045eb37 add cN
-  |
-  o  15:2d66e189f5b5 add cM
-  |
-  @  14:d66ccb8c5871 add cL
-  |
-  | o  9:55c73a90e4b4 add cJ
-  | |
-  o |  7:18214586bf78 add cJ
-  |/
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
- 
-check that pruning and inhibited node does not confuse anything
-
-  $ hg up --hidden 210589181b14
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg strip --bundle 210589181b14
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  saved backup bundle to $TESTTMP/inhibit/.hg/strip-backup/210589181b14-e09c7b88-backup.hg (glob)
-  $ hg unbundle .hg/strip-backup/210589181b14-e09c7b88-backup.hg # restore state
-  adding changesets
-  adding manifests
-  adding file changes
-  added 2 changesets with 1 changes to 2 files (+1 heads)
-  3 new obsolescence markers
-  obsoleted 1 changesets
-  (run 'hg heads .' to see heads, 'hg merge' to merge)
-
- Only allow direct access and check that evolve works like before
-(also disable evolve commands to avoid hint about using evolve)
-  $ cat >> $HGRCPATH <<EOF
-  > [extensions]
-  > inhibit=!
-  > [experimental]
-  > evolution=createmarkers
-  > EOF
-
-  $ hg up 15
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  working directory parent is obsolete! (2d66e189f5b5)
-  $ cat >> $HGRCPATH <<EOF
-  > [experimental]
-  > evolution=all
-  > EOF
-  $ echo "CM" > cM
-  $ hg amend
-  $ hg log -G
-  @  21:721c3c279519 add cM
-  |
-  | o  16:a438c045eb37 add cN
-  | |
-  | x  15:2d66e189f5b5 add cM
-  |/
-  o  14:d66ccb8c5871 add cL
-  |
-  o  7:18214586bf78 add cJ
-  |
-  o  6:cf5c4f4554ce add cH
-  |
-  o  5:5419eb264a33 add cG
-  |
-  o  4:98065434e5c6 add cE
-  |
-  o  0:54ccbc537fc2 add cA
-  
-  $ cat >> $HGRCPATH <<EOF
-  > [extensions]
-  > EOF
-  $ echo "inhibit=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/hack/inhibit.py" >> $HGRCPATH
-
-Empty commit
-  $ hg amend
-  nothing changed
-  [1]
-
-Check that the behavior of rebase with obsolescence markers is maintained
-despite inhibit
-
-  $ hg up a438c045eb37
-  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg rebase -r 15:: -d 21 --config experimental.rebaseskipobsolete=True
-  note: not rebasing 15:2d66e189f5b5 "add cM", already in destination as 21:721c3c279519 "add cM"
-  rebasing 16:a438c045eb37 "add cN"
-  $ hg up -q 2d66e189f5b5 # To inhibit it as the rest of test depends on it
-  $ hg up -q 21
-
-Directaccess should load after some extensions precised in the conf
-With no extension specified:
-
-  $ cat >$TESTTMP/test_extension.py  << EOF
-  > from mercurial import extensions
-  > def uisetup(ui):
-  >   print extensions._order
-  > EOF
-  $ cat >> $HGRCPATH << EOF
-  > [extensions]
-  > testextension=$TESTTMP/test_extension.py
-  > EOF
-  $ hg id
-  ['rebase', 'strip', 'evolve', 'directaccess', 'inhibit', 'testextension']
-  721c3c279519
-
-With test_extension specified:
-  $ cat >> $HGRCPATH << EOF
-  > [directaccess]
-  > loadsafter=testextension
-  > EOF
-  $ hg id
-  ['rebase', 'strip', 'evolve', 'inhibit', 'testextension', 'directaccess']
-  721c3c279519
-
-Inhibit should not work without directaccess
-  $ cat >> $HGRCPATH <<EOF
-  > [extensions]
-  > directaccess=!
-  > testextension=!
-  > EOF
-  $ hg up .
-  cannot use inhibit without the direct access extension
-  (please enable it or inhibit won't work)
-  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ echo "directaccess=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/hack/directaccess.py" >> $HGRCPATH
-  $ cd ..
-
-hg push should not allow directaccess unless forced with --hidden
-We copy the inhibhit repo to inhibit2 and make some changes to push to inhibit
-
-  $ cp -r inhibit inhibit2
-  $ pwd=$(pwd)
-  $ cd inhibit
-  $ mkcommit pk
-  created new head
-  $ hg id
-  003a4735afde tip
-  $ echo "OO" > pk
-  $ hg amend
-  $ hg id
-  71eb4f100663 tip
-
-Hidden commits cannot be pushed without --hidden
-  $ hg push -r 003a4735afde $pwd/inhibit2
-  pushing to $TESTTMP/inhibit2
-  abort: hidden revision '003a4735afde'!
-  (use --hidden to access hidden revisions; successor: 71eb4f100663)
-  [255]
-
-Visible commits can still be pushed
-  $ hg push -fr 71eb4f100663 $pwd/inhibit2
-  pushing to $TESTTMP/inhibit2
-  searching for changes
-  adding changesets
-  adding manifests
-  adding file changes
-  added 1 changesets with 1 changes to 1 files (+1 heads)
-  2 new obsolescence markers
-
-Create a stack (obsolete with successor in dest) -> (not obsolete) and rebase
-it. We expect to not see the stack at the end of the rebase.
-  $ hg log -G  -r "25::"
-  @  25:71eb4f100663 add pk
-  |
-  ~
-  $ hg up -C 22
-  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ mkcommit Dk
-  $ hg prune 22 -s 25
-  1 changesets pruned
-  $ hg rebase -s 22 -d 25 --config experimental.rebaseskipobsolete=True
-  note: not rebasing 22:46cb6daad392 "add cN", already in destination as 25:71eb4f100663 "add pk"
-  rebasing 26:7ad60e760c7b "add Dk" (tip)
-  $ hg log -G  -r "25::"
-  @  27:1192fa9fbc68 add Dk
-  |
-  o  25:71eb4f100663 add pk
-  |
-  ~
-
-Create a stack (obsolete with succ in dest) -> (not obsolete) -> (not obsolete).
-Rebase the first two revs of the stack onto dest, we expect to see one new
-revision on the destination and everything visible.
-  $ hg up 25
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ mkcommit Dl
-  created new head
-  $ mkcommit Dp
-  $ mkcommit Do
-  $ hg log -G -r "25::"
-  @  30:b517facce1ef add Do
-  |
-  o  29:c5a47ab27c2e add Dp
-  |
-  o  28:8c1c2edbaf1b add Dl
-  |
-  | o  27:1192fa9fbc68 add Dk
-  |/
-  o  25:71eb4f100663 add pk
-  |
-  ~
-  $ hg prune 28 -s 27
-  1 changesets pruned
-  $ hg up 25
-  0 files updated, 0 files merged, 3 files removed, 0 files unresolved
-  $ hg rebase -r "28 + 29" --keep -d 27 --config experimental.rebaseskipobsolete=True
-  note: not rebasing 28:8c1c2edbaf1b "add Dl", already in destination as 27:1192fa9fbc68 "add Dk"
-  rebasing 29:c5a47ab27c2e "add Dp"
-  $ hg log -G  -r "25::"
-  o  31:7d8affb1f604 add Dp
-  |
-  | o  30:b517facce1ef add Do
-  | |
-  | o  29:c5a47ab27c2e add Dp
-  | |
-  | o  28:8c1c2edbaf1b add Dl
-  | |
-  o |  27:1192fa9fbc68 add Dk
-  |/
-  @  25:71eb4f100663 add pk
-  |
-  ~
-
-Rebase the same stack in full on the destination, we expect it to disappear
-and only see the top revision added to destination. We don\'t expect 29 to be
-skipped as we used --keep before.
-  $ hg rebase -s 28 -d 27 --config experimental.rebaseskipobsolete=True
-  note: not rebasing 28:8c1c2edbaf1b "add Dl", already in destination as 27:1192fa9fbc68 "add Dk"
-  rebasing 29:c5a47ab27c2e "add Dp"
-  rebasing 30:b517facce1ef "add Do"
-  $ hg log -G  -r "25::"
-  o  32:1d43fff9e26f add Do
-  |
-  o  31:7d8affb1f604 add Dp
-  |
-  o  27:1192fa9fbc68 add Dk
-  |
-  @  25:71eb4f100663 add pk
-  |
-  ~
-
-Pulling from a inhibit repo to a non-inhibit repo should work
-
-  $ cd ..
-  $ hg clone -q inhibit not-inhibit
-  $ cat >> not-inhibit/.hg/hgrc <<EOF
-  > [extensions]
-  > inhibit=!
-  > directaccess=!
-  > evolve=!
-  > EOF
-  $ cd not-inhibit
-  $ hg book -d foo
-  $ hg pull
-  pulling from $TESTTMP/inhibit (glob)
-  searching for changes
-  no changes found
-  adding remote bookmark foo
-
-Test that bookmark -D can take multiple branch names
-  $ cd ../inhibit
-  $ hg bookmark book2 book1 book3
-  $ touch foo && hg add foo && hg ci -m "add foo"
-  created new head
-  $ hg up book1
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  (activating bookmark book1)
-  $ hg bookmark -D book2 book3
-  bookmark 'book2' deleted
-  bookmark 'book3' deleted
-  1 changesets pruned
--- a/tests/test-metaedit.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-metaedit.t	Tue Nov 14 23:04:04 2017 +0100
@@ -80,11 +80,11 @@
 ----
 
   $ hg log -G
-  @  8	: F - test
+  @  7	: F - test
   |
-  o  7	: E - test
+  o  6	: E - test
   |
-  | o  6	: D2 - test
+  | o  5	: D2 - test
   |/
   o  3	: C - test
   |
@@ -124,13 +124,10 @@
   $ hg metaedit --user foobar
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg log --template '{rev}: {author}\n' -r 'desc(F):' --hidden
-  5: test
-  6: test
   7: test
-  8: test
-  9: foobar
+  8: foobar
   $ hg log --template '{rev}: {author}\n' -r .
-  9: foobar
+  8: foobar
 
 TODO: support this
   $ hg metaedit '.^::.'
@@ -139,11 +136,11 @@
 
   $ HGEDITOR=cat hg metaedit '.^::.' --fold
   HG: This is a fold of 2 changesets.
-  HG: Commit message of changeset 7.
+  HG: Commit message of changeset 6.
   
   E
   
-  HG: Commit message of changeset 9.
+  HG: Commit message of changeset 8.
   
   F
   
@@ -160,7 +157,7 @@
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
   $ glog -r .
-  @  10:a08d35fd7d9d@default(draft) E
+  @  9:a08d35fd7d9d@default(draft) E
   |
   ~
 
@@ -182,7 +179,7 @@
   nothing changed
 
   $ glog -r '.^::.'
-  @  10:a08d35fd7d9d@default(draft) E
+  @  9:a08d35fd7d9d@default(draft) E
   |
   o  3:3260958f1169@default(draft) C
   |
@@ -196,20 +193,20 @@
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg log -r '.^::.' --template '{rev}: {desc|firstline}\n'
   3: C
-  11: E
+  10: E
 
   $ hg up .^
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ hg metaedit --user foobar2 tip
   $ hg log --template '{rev}: {author}\n' -r "user(foobar):" --hidden
-  9: foobar
+  8: foobar
+  9: test
   10: test
-  11: test
-  12: foobar2
+  11: foobar2
   $ hg diff -r "10" -r "11" --hidden
 
 'fold' one commit
   $ HGUSER=foobar3 hg metaedit "desc(D2)" --fold -U --config
   1 changesets folded
   $ hg log -r "tip" --template '{rev}: {author}\n'
-  13: foobar3
+  12: foobar3
--- a/tests/test-obsconvert.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-obsconvert.t	Tue Nov 14 23:04:04 2017 +0100
@@ -16,49 +16,33 @@
 Test conversion between obsolete marker formats
   $ hg debugobsolete
   e63c23eaa88ae77967edcf4ea194d31167c478b0 b81ac6b9d2a55f9a7a6b90a006b1aab0568d6d34 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  a5b276878fa564da042b4b9efef3713ceea20350 0 {e63c23eaa88ae77967edcf4ea194d31167c478b0} (*) {'ef1': '*', 'user': 'test'} (glob)
   b81ac6b9d2a55f9a7a6b90a006b1aab0568d6d34 384fc811182687231962e486f23ea8c5bab7a2d3 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  2291082406feb57d0f83b9b0a6777b6074f3fde6 0 {b81ac6b9d2a55f9a7a6b90a006b1aab0568d6d34} (*) {'ef1': '*', 'user': 'test'} (glob)
   384fc811182687231962e486f23ea8c5bab7a2d3 949d379b3c3bf051906bc3528c049cb536e2ec86 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  1616bdbe82d3fd1fb7c4e068aee277835672ffdc 0 {384fc811182687231962e486f23ea8c5bab7a2d3} (*) {'ef1': '*', 'user': 'test'} (glob)
   949d379b3c3bf051906bc3528c049cb536e2ec86 f2e4c45b2a4a58ccf7ef6825b8fa5685873cd2f7 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  8668d55aac650158bb510be6d47d21e3db9e5c75 0 {949d379b3c3bf051906bc3528c049cb536e2ec86} (*) {'ef1': '*', 'user': 'test'} (glob)
   $ hg debugobsconvert --new-format 0
   Old store is version 1, will rewrite in version 0
   Done!
   $ hg debugobsolete
   e63c23eaa88ae77967edcf4ea194d31167c478b0 b81ac6b9d2a55f9a7a6b90a006b1aab0568d6d34 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  a5b276878fa564da042b4b9efef3713ceea20350 0 {e63c23eaa88ae77967edcf4ea194d31167c478b0} (*) {'ef1': '*', 'user': 'test'} (glob)
   b81ac6b9d2a55f9a7a6b90a006b1aab0568d6d34 384fc811182687231962e486f23ea8c5bab7a2d3 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  2291082406feb57d0f83b9b0a6777b6074f3fde6 0 {b81ac6b9d2a55f9a7a6b90a006b1aab0568d6d34} (*) {'ef1': '*', 'user': 'test'} (glob)
   384fc811182687231962e486f23ea8c5bab7a2d3 949d379b3c3bf051906bc3528c049cb536e2ec86 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  1616bdbe82d3fd1fb7c4e068aee277835672ffdc 0 {384fc811182687231962e486f23ea8c5bab7a2d3} (*) {'ef1': '*', 'user': 'test'} (glob)
   949d379b3c3bf051906bc3528c049cb536e2ec86 f2e4c45b2a4a58ccf7ef6825b8fa5685873cd2f7 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  8668d55aac650158bb510be6d47d21e3db9e5c75 0 {949d379b3c3bf051906bc3528c049cb536e2ec86} (*) {'ef1': '*', 'user': 'test'} (glob)
   $ hg debugobsconvert --new-format 0
   abort: New format is the same as the old format, not upgrading!
   [255]
   $ hg debugobsolete
   e63c23eaa88ae77967edcf4ea194d31167c478b0 b81ac6b9d2a55f9a7a6b90a006b1aab0568d6d34 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  a5b276878fa564da042b4b9efef3713ceea20350 0 {e63c23eaa88ae77967edcf4ea194d31167c478b0} (*) {'ef1': '*', 'user': 'test'} (glob)
   b81ac6b9d2a55f9a7a6b90a006b1aab0568d6d34 384fc811182687231962e486f23ea8c5bab7a2d3 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  2291082406feb57d0f83b9b0a6777b6074f3fde6 0 {b81ac6b9d2a55f9a7a6b90a006b1aab0568d6d34} (*) {'ef1': '*', 'user': 'test'} (glob)
   384fc811182687231962e486f23ea8c5bab7a2d3 949d379b3c3bf051906bc3528c049cb536e2ec86 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  1616bdbe82d3fd1fb7c4e068aee277835672ffdc 0 {384fc811182687231962e486f23ea8c5bab7a2d3} (*) {'ef1': '*', 'user': 'test'} (glob)
   949d379b3c3bf051906bc3528c049cb536e2ec86 f2e4c45b2a4a58ccf7ef6825b8fa5685873cd2f7 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  8668d55aac650158bb510be6d47d21e3db9e5c75 0 {949d379b3c3bf051906bc3528c049cb536e2ec86} (*) {'ef1': '*', 'user': 'test'} (glob)
   $ hg debugobsconvert --new-format 1
   Old store is version 0, will rewrite in version 1
   Done!
   $ hg debugobsolete
   e63c23eaa88ae77967edcf4ea194d31167c478b0 b81ac6b9d2a55f9a7a6b90a006b1aab0568d6d34 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  a5b276878fa564da042b4b9efef3713ceea20350 0 {e63c23eaa88ae77967edcf4ea194d31167c478b0} (*) {'ef1': '*', 'user': 'test'} (glob)
   b81ac6b9d2a55f9a7a6b90a006b1aab0568d6d34 384fc811182687231962e486f23ea8c5bab7a2d3 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  2291082406feb57d0f83b9b0a6777b6074f3fde6 0 {b81ac6b9d2a55f9a7a6b90a006b1aab0568d6d34} (*) {'ef1': '*', 'user': 'test'} (glob)
   384fc811182687231962e486f23ea8c5bab7a2d3 949d379b3c3bf051906bc3528c049cb536e2ec86 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  1616bdbe82d3fd1fb7c4e068aee277835672ffdc 0 {384fc811182687231962e486f23ea8c5bab7a2d3} (*) {'ef1': '*', 'user': 'test'} (glob)
   949d379b3c3bf051906bc3528c049cb536e2ec86 f2e4c45b2a4a58ccf7ef6825b8fa5685873cd2f7 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  8668d55aac650158bb510be6d47d21e3db9e5c75 0 {949d379b3c3bf051906bc3528c049cb536e2ec86} (*) {'ef1': '*', 'user': 'test'} (glob)
 
 Test that the default is some reasonably modern format (first downgrade)
   $ hg debugobsconvert --new-format 0
@@ -69,10 +53,6 @@
   Done!
   $ hg debugobsolete
   e63c23eaa88ae77967edcf4ea194d31167c478b0 b81ac6b9d2a55f9a7a6b90a006b1aab0568d6d34 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  a5b276878fa564da042b4b9efef3713ceea20350 0 {e63c23eaa88ae77967edcf4ea194d31167c478b0} (*) {'ef1': '*', 'user': 'test'} (glob)
   b81ac6b9d2a55f9a7a6b90a006b1aab0568d6d34 384fc811182687231962e486f23ea8c5bab7a2d3 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  2291082406feb57d0f83b9b0a6777b6074f3fde6 0 {b81ac6b9d2a55f9a7a6b90a006b1aab0568d6d34} (*) {'ef1': '*', 'user': 'test'} (glob)
   384fc811182687231962e486f23ea8c5bab7a2d3 949d379b3c3bf051906bc3528c049cb536e2ec86 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  1616bdbe82d3fd1fb7c4e068aee277835672ffdc 0 {384fc811182687231962e486f23ea8c5bab7a2d3} (*) {'ef1': '*', 'user': 'test'} (glob)
   949d379b3c3bf051906bc3528c049cb536e2ec86 f2e4c45b2a4a58ccf7ef6825b8fa5685873cd2f7 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  8668d55aac650158bb510be6d47d21e3db9e5c75 0 {949d379b3c3bf051906bc3528c049cb536e2ec86} (*) {'ef1': '*', 'user': 'test'} (glob)
--- a/tests/test-obsolete-push.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-obsolete-push.t	Tue Nov 14 23:04:04 2017 +0100
@@ -26,7 +26,7 @@
   $ hg phase --secret --force .
   $ hg prune 0 1
   2 changesets pruned
-  1 new unstable changesets
+  1 new orphan changesets
   $ glog --hidden
   @  2:244232c2222a@default(secret) C
   |
@@ -56,6 +56,7 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files
   2 new obsolescence markers
+  new changesets 1994f17a630e
   updating to branch default
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cd strict-publish-client
--- a/tests/test-obsolete.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-obsolete.t	Tue Nov 14 23:04:04 2017 +0100
@@ -128,13 +128,13 @@
   parent:      1:7c3bad9141dc
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
-  obsolete:    rewritten as 725c380fe99b
+  obsolete:    rewritten as 4:725c380fe99b
   summary:     add obsol_c
   
   working directory parent is obsolete! (0d3f46688ccc)
   (use 'hg evolve' to update to its successor: 725c380fe99b)
   $ mkcommit d # 5 (on 3)
-  1 new unstable changesets
+  1 new orphan changesets
   $ qlog -r 'obsolete()'
   3
   - 0d3f46688ccc
@@ -145,7 +145,7 @@
   $ qlog -r 'suspended()'
   3
   - 0d3f46688ccc
-  $ qlog -r 'unstable()'
+  $ qlog -r "orphan()"
   5
   - a7a6f2b5d8a5
 
@@ -175,7 +175,7 @@
   $ hg push ../other-new
   pushing to ../other-new
   searching for changes
-  abort: push includes unstable changeset: a7a6f2b5d8a5!
+  abort: push includes orphan changeset: a7a6f2b5d8a5!
   (use 'hg evolve' to get a stable history or --force to ignore warnings)
   [255]
   $ hg push -f ../other-new
@@ -210,7 +210,7 @@
   working directory parent is obsolete! (0d3f46688ccc)
   $ mkcommit obsol_d # 6
   created new head
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg debugobsolete `getid 5` `getid 6`
   obsoleted 1 changesets
   $ qlog
@@ -230,7 +230,7 @@
   $ hg push ../other-new
   pushing to ../other-new
   searching for changes
-  abort: push includes unstable changeset: 95de7fc6918d!
+  abort: push includes orphan changeset: 95de7fc6918d!
   (use 'hg evolve' to get a stable history or --force to ignore warnings)
   [255]
   $ hg push ../other-new -f # use f because there is unstability
@@ -269,7 +269,7 @@
   working directory parent is obsolete! (0d3f46688ccc)
   $ mkcommit "obsol_d'" # 7
   created new head
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg debugobsolete `getid 6` `getid 7`
   obsoleted 1 changesets
   $ hg pull -R ../other-new .
@@ -281,6 +281,7 @@
   added 1 changesets with 1 changes to [12] files \(\+1 heads\) (re)
   1 new obsolescence markers
   obsoleted 1 changesets
+  new changesets 909a0fb57e5d
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ qlog -R ../other-new
   6
@@ -359,7 +360,7 @@
   working directory parent is obsolete! (0d3f46688ccc)
   $ mkcommit "obsol_d''"
   created new head
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg debugobsolete `getid 7` `getid 8`
   obsoleted 1 changesets
   $ cd ../other-new
@@ -373,6 +374,7 @@
   added 1 changesets with 1 changes to [12] files \(\+1 heads\) (re)
   1 new obsolescence markers
   obsoleted 1 changesets
+  new changesets 159dfc9fa5d3
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
   $ hg up -q 7 # to check rollback update behavior
@@ -397,7 +399,7 @@
   commit: 1 deleted, 2 unknown (clean)
   update: 2 new changesets, 2 branch heads (merge)
   phases: 4 draft
-  unstable: 1 changesets
+  orphan: 1 changesets
   $ qlog
   6
   - 909a0fb57e5d
@@ -520,8 +522,8 @@
 #excluded 'whole rebase set is extinct and ignored.' message not in core
   $ hg rebase -b '3' -d 4 --traceback --config experimental.rebaseskipobsolete=0
   rebasing 3:0d3f46688ccc "add obsol_c"
-  rebasing 8:159dfc9fa5d3 "add obsol_d''" (tip)
-  2 new divergent changesets
+  rebasing 8:159dfc9fa5d3 "add obsol_d''"
+  2 new content-divergent changesets
   $ hg --hidden log -q -r 'successors(3)'
   4:725c380fe99b
   10:2033b4e49474
@@ -572,7 +574,7 @@
 
   $ cd local
   $ hg phase --hidden --public 11
-  1 new bumped changesets
+  1 new phase-divergent changesets
   $ hg log -G --template='{rev} - ({phase}) {node|short} {desc}\n'
   @  12 - (draft) 6db5e282cb91 add obsol_d'''
   |
@@ -586,19 +588,19 @@
   |
   o  0 - (public) 1f0dee641bb7 add a
   
-  $ hg log -r 'bumped()'
+  $ hg log -r 'phasedivergent()'
   changeset:   12:6db5e282cb91
   tag:         tip
   parent:      10:2033b4e49474
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
-  trouble:     bumped
+  instability: phase-divergent
   summary:     add obsol_d'''
   
   $ hg push ../other-new/
   pushing to ../other-new/
   searching for changes
-  abort: push includes bumped changeset: 6db5e282cb91!
+  abort: push includes phase-divergent changeset: 6db5e282cb91!
   (use 'hg evolve' to get a stable history or --force to ignore warnings)
   [255]
 
@@ -611,7 +613,7 @@
   $ echo 42 >> f
   $ hg commit --amend --traceback --quiet
   $ hg log -G
-  @  changeset:   15:705ab2a6b72e
+  @  changeset:   14:705ab2a6b72e
   |  tag:         tip
   |  parent:      10:2033b4e49474
   |  user:        test
@@ -622,7 +624,7 @@
   |/   parent:      10:2033b4e49474
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    trouble:     bumped
+  |    instability: phase-divergent
   |    summary:     add obsol_d'''
   |
   | o  changeset:   11:9468a5f5d8b2
@@ -673,28 +675,28 @@
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ mkcommit "obsolet_conflicting_d"
   $ hg summary
-  parent: 1[46]:50f11e5e3a63 tip (re)
+  parent: 15:50f11e5e3a63 tip
    add obsolet_conflicting_d
   branch: default
   commit: (clean)
   update: (2|9|11) new changesets, (3|9|10) branch heads \(merge\) (re)
   phases: 3 draft
-  bumped: 1 changesets
+  phase-divergent: 1 changesets
   $ hg debugobsolete `getid a7a6f2b5d8a5` `getid 50f11e5e3a63`
-  $ hg log -r 'divergent()'
+  $ hg log -r 'contentdivergent()'
   changeset:   12:6db5e282cb91
   parent:      10:2033b4e49474
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
-  trouble:     bumped, divergent
+  instability: phase-divergent, content-divergent
   summary:     add obsol_d'''
   
-  changeset:   16:50f11e5e3a63
+  changeset:   15:50f11e5e3a63
   tag:         tip
   parent:      11:9468a5f5d8b2
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
-  trouble:     divergent
+  instability: content-divergent
   summary:     add obsolet_conflicting_d
   
 
@@ -707,11 +709,11 @@
   [2]
   $ hg olog
   @  0d3f46688ccc (3) add obsol_c
-  |    rewritten(parent) by test (*) as 2033b4e49474 (glob)
-  |    rewritten by test (*) as 725c380fe99b (glob)
+  |    rewritten(parent) as 2033b4e49474 by test (*) (glob)
+  |    rewritten as 725c380fe99b by test (*) (glob)
   |
   x  4538525df7e2 (2) add c
-       rewritten by test (*) as 0d3f46688ccc (glob)
+       rewritten as 0d3f46688ccc by test (*) (glob)
   
 
 Check import reports new unstable changeset:
@@ -719,55 +721,49 @@
   $ hg up --hidden 2
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   working directory parent is obsolete! (4538525df7e2)
-  (4538525df7e2 has diverged, use 'hg evolve --list --divergent' to resolve the issue)
+  (4538525df7e2 has diverged, use 'hg evolve --list --content-divergent' to resolve the issue)
   $ hg export 9468a5f5d8b2 | hg import -
   applying patch from stdin
-  1 new unstable changesets
+  1 new orphan changesets
 
 
 Relevant marker computation
 ==============================
 
   $ hg log -G --hidden
-  @  changeset:   17:a5f7a21fe7bc
+  @  changeset:   16:a5f7a21fe7bc
   |  tag:         tip
   |  parent:      2:4538525df7e2
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  trouble:     unstable
+  |  instability: orphan
   |  summary:     add obsol_d''
   |
-  | o  changeset:   16:50f11e5e3a63
+  | o  changeset:   15:50f11e5e3a63
   | |  parent:      11:9468a5f5d8b2
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  trouble:     divergent
+  | |  instability: content-divergent
   | |  summary:     add obsolet_conflicting_d
   | |
-  | | o  changeset:   15:705ab2a6b72e
+  | | o  changeset:   14:705ab2a6b72e
   | | |  parent:      10:2033b4e49474
   | | |  user:        test
   | | |  date:        Thu Jan 01 00:00:00 1970 +0000
   | | |  summary:     add f
   | | |
-  | | | x  changeset:   14:33d458d86621
-  | | | |  user:        test
-  | | | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | | | |  obsolete:    pruned
-  | | | |  summary:     temporary amend commit for 0b1b6dd009c0
-  | | | |
   | | | x  changeset:   13:0b1b6dd009c0
   | | |/   parent:      10:2033b4e49474
   | | |    user:        test
   | | |    date:        Thu Jan 01 00:00:00 1970 +0000
-  | | |    obsolete:    rewritten as 705ab2a6b72e
+  | | |    obsolete:    amended using amend as 14:705ab2a6b72e
   | | |    summary:     add f
   | | |
   | | | o  changeset:   12:6db5e282cb91
   | | |/   parent:      10:2033b4e49474
   | | |    user:        test
   | | |    date:        Thu Jan 01 00:00:00 1970 +0000
-  | | |    trouble:     bumped, divergent
+  | | |    instability: phase-divergent, content-divergent
   | | |    summary:     add obsol_d'''
   | | |
   | o |  changeset:   11:9468a5f5d8b2
@@ -792,29 +788,29 @@
   | | |  parent:      3:0d3f46688ccc
   | | |  user:        test
   | | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | | |  obsolete:    rewritten as 9468a5f5d8b2
+  | | |  obsolete:    rebased using rebase as 11:9468a5f5d8b2
   | | |  summary:     add obsol_d''
   | | |
   | | | x  changeset:   7:909a0fb57e5d
   | | |/   parent:      3:0d3f46688ccc
   | | |    user:        test
   | | |    date:        Thu Jan 01 00:00:00 1970 +0000
-  | | |    obsolete:    rewritten as 159dfc9fa5d3
+  | | |    obsolete:    rewritten as 8:159dfc9fa5d3
   | | |    summary:     add obsol_d'
   | | |
   | | | x  changeset:   6:95de7fc6918d
   | | |/   parent:      3:0d3f46688ccc
   | | |    user:        test
   | | |    date:        Thu Jan 01 00:00:00 1970 +0000
-  | | |    obsolete:    rewritten as 909a0fb57e5d
+  | | |    obsolete:    rewritten as 7:909a0fb57e5d
   | | |    summary:     add obsol_d
   | | |
   | | | x  changeset:   5:a7a6f2b5d8a5
   | | |/   parent:      3:0d3f46688ccc
   | | |    user:        test
   | | |    date:        Thu Jan 01 00:00:00 1970 +0000
-  | | |    obsolete:    rewritten as 95de7fc6918d
-  | | |    obsolete:    rewritten as 50f11e5e3a63
+  | | |    obsolete:    rewritten as 6:95de7fc6918d
+  | | |    obsolete:    rewritten as 15:50f11e5e3a63
   | | |    summary:     add d
   | | |
   | o |  changeset:   4:725c380fe99b
@@ -827,14 +823,14 @@
   | |/   parent:      1:7c3bad9141dc
   | |    user:        test
   | |    date:        Thu Jan 01 00:00:00 1970 +0000
-  | |    obsolete:    rewritten as 725c380fe99b
-  | |    obsolete:    rewritten as 2033b4e49474
+  | |    obsolete:    rewritten as 4:725c380fe99b
+  | |    obsolete:    rebased using rebase as 10:2033b4e49474
   | |    summary:     add obsol_c
   | |
   x |  changeset:   2:4538525df7e2
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as 0d3f46688ccc
+  |    obsolete:    rewritten as 3:0d3f46688ccc
   |    summary:     add c
   |
   o  changeset:   1:7c3bad9141dc
@@ -856,8 +852,7 @@
 simple rewrite with a prune attached to it
 
   $ hg debugobsolete --rev 15
-  0b1b6dd009c037985363e2290a0b579819f659db 705ab2a6b72e2cd86edb799ebe15f2695f86143e 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  33d458d86621f3186c40bfccd77652f4a122743e 0 {0b1b6dd009c037985363e2290a0b579819f659db} (*) {'ef1': '*', 'user': 'test'} (glob)
+  a7a6f2b5d8a54b81bc7aa2fba2934ad6d700a79e 50f11e5e3a63806e678c734e525502f522d37e38 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
 
 Transitive rewrite
 
--- a/tests/test-prev-next.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-prev-next.t	Tue Nov 14 23:04:04 2017 +0100
@@ -169,7 +169,7 @@
 some aspiring children
 
   $ hg amend -m 'added b (2)'
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg next
   no children
   (1 unstable changesets to be evolved here, do you want --evolve?)
@@ -209,7 +209,7 @@
 next with ambiguity in aspiring children
 
   $ hg am -m 'added b (3)'
-  2 new unstable changesets
+  2 new orphan changesets
   $ hg next
   no children
   (2 unstable changesets to be evolved here, do you want --evolve?)
@@ -251,7 +251,7 @@
   $ sleep 1
   $ hg next --evolve
   waiting for lock on working directory of $TESTTMP/repo held by process '*' on host '*' (glob)
-  1 new unstable changesets
+  1 new orphan changesets
   got lock after [4-6] seconds (re)
   move:[2] two
   atop:[3] one
--- a/tests/test-prune.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-prune.t	Tue Nov 14 23:04:04 2017 +0100
@@ -63,7 +63,7 @@
 
   $ hg prune 1
   1 changesets pruned
-  2 new unstable changesets
+  2 new orphan changesets
   $ hg book -i BABAR
   $ hg debugobsolete
   9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'ef1': '*', 'user': 'blah'} (glob)
--- a/tests/test-push-checkheads-partial-C1.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-partial-C1.t	Tue Nov 14 23:04:04 2017 +0100
@@ -51,6 +51,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets d73caddc5533
   (run 'hg update' to get a working copy)
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-partial-C2.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-partial-C2.t	Tue Nov 14 23:04:04 2017 +0100
@@ -53,6 +53,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets d73caddc5533
   (run 'hg update' to get a working copy)
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-partial-C3.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-partial-C3.t	Tue Nov 14 23:04:04 2017 +0100
@@ -53,6 +53,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets d73caddc5533
   (run 'hg update' to get a working copy)
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-partial-C4.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-partial-C4.t	Tue Nov 14 23:04:04 2017 +0100
@@ -53,6 +53,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets d73caddc5533
   (run 'hg update' to get a working copy)
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-pruned-B2.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-pruned-B2.t	Tue Nov 14 23:04:04 2017 +0100
@@ -53,6 +53,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets d73caddc5533
   (run 'hg update' to get a working copy)
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-pruned-B3.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-pruned-B3.t	Tue Nov 14 23:04:04 2017 +0100
@@ -53,6 +53,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets d73caddc5533
   (run 'hg update' to get a working copy)
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-pruned-B4.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-pruned-B4.t	Tue Nov 14 23:04:04 2017 +0100
@@ -54,6 +54,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets d73caddc5533
   (run 'hg update' to get a working copy)
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-pruned-B5.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-pruned-B5.t	Tue Nov 14 23:04:04 2017 +0100
@@ -57,6 +57,7 @@
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 2 files
+  new changesets d73caddc5533:821fb21d0dd2
   (run 'hg update' to get a working copy)
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-pruned-B8.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-pruned-B8.t	Tue Nov 14 23:04:04 2017 +0100
@@ -55,6 +55,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets d73caddc5533
   (run 'hg update' to get a working copy)
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-superceed-A2.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-superceed-A2.t	Tue Nov 14 23:04:04 2017 +0100
@@ -52,6 +52,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets d73caddc5533
   (run 'hg update' to get a working copy)
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-superceed-A3.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-superceed-A3.t	Tue Nov 14 23:04:04 2017 +0100
@@ -55,6 +55,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets d73caddc5533
   (run 'hg update' to get a working copy)
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-superceed-A6.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-superceed-A6.t	Tue Nov 14 23:04:04 2017 +0100
@@ -59,6 +59,7 @@
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 2 files (+1 heads)
+  new changesets d73caddc5533:0f88766e02d6
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-superceed-A7.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-superceed-A7.t	Tue Nov 14 23:04:04 2017 +0100
@@ -59,6 +59,7 @@
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 2 files (+1 heads)
+  new changesets d73caddc5533:0f88766e02d6
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg up 'desc(C0)'
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-unpushed-D2.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-unpushed-D2.t	Tue Nov 14 23:04:04 2017 +0100
@@ -57,6 +57,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets d73caddc5533
   (run 'hg update' to get a working copy)
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-unpushed-D3.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-unpushed-D3.t	Tue Nov 14 23:04:04 2017 +0100
@@ -56,6 +56,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets d73caddc5533
   (run 'hg update' to get a working copy)
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-unpushed-D4.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-unpushed-D4.t	Tue Nov 14 23:04:04 2017 +0100
@@ -73,6 +73,7 @@
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 2 files (+1 heads)
+  new changesets d73caddc5533:0f88766e02d6
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-push-checkheads-unpushed-D5.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-push-checkheads-unpushed-D5.t	Tue Nov 14 23:04:04 2017 +0100
@@ -62,6 +62,7 @@
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 2 files (+1 heads)
+  new changesets d73caddc5533:0f88766e02d6
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg up 'desc(C0)'
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-sharing.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-sharing.t	Tue Nov 14 23:04:04 2017 +0100
@@ -46,6 +46,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets 0dc9c9f6ab91
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
 Let's commit a preliminary change and push it to ``test-repo`` for
@@ -69,10 +70,8 @@
 
 Figure SG02
   $ hg shortlog --hidden -G
-  @  3:60ffde5765c5  draft  fix bug 37
+  @  2:60ffde5765c5  draft  fix bug 37
   |
-  | x  2:2a039763c0f4  draft  temporary amend commit for f6490818a721
-  | |
   | x  1:f6490818a721  draft  prelim change
   |/
   o  0:0dc9c9f6ab91  public  create new project
@@ -87,8 +86,9 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  2 new obsolescence markers
+  1 new obsolescence markers
   obsoleted 1 changesets
+  new changesets 60ffde5765c5
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   updated to "60ffde5765c5: fix bug 37"
   1 other heads for branch "default"
@@ -108,10 +108,8 @@
 
 Figure SG04 (dev-repo)
   $ hg shortlog --hidden -G
-  @  4:de6151c48e1c  draft  fix bug 37
+  @  3:de6151c48e1c  draft  fix bug 37
   |
-  | x  3:ad19d3570adb  draft  temporary amend commit for 60ffde5765c5
-  | |
   | x  2:60ffde5765c5  draft  fix bug 37
   |/
   | x  1:f6490818a721  draft  prelim change
@@ -125,12 +123,10 @@
   updated to "de6151c48e1c: fix bug 37"
   1 other heads for branch "default"
   $ hg shortlog --hidden -G
-  @  4:de6151c48e1c  draft  fix bug 37
+  @  3:de6151c48e1c  draft  fix bug 37
   |
-  | x  3:60ffde5765c5  draft  fix bug 37
+  | x  2:60ffde5765c5  draft  fix bug 37
   |/
-  | x  2:2a039763c0f4  draft  temporary amend commit for f6490818a721
-  | |
   | x  1:f6490818a721  draft  prelim change
   |/
   o  0:0dc9c9f6ab91  public  create new project
@@ -143,7 +139,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  4 new obsolescence markers
+  2 new obsolescence markers
 
 Now that the fix is public, we cannot amend it any more.
   $ hg amend -m 'fix bug 37'
@@ -159,7 +155,7 @@
   
 Oops, still have draft changesets in dev-repo: push the phase change there.
   $ hg -R ../dev-repo shortlog -r 'draft()'
-  4:de6151c48e1c  draft  fix bug 37
+  3:de6151c48e1c  draft  fix bug 37
   $ hg push ../dev-repo
   pushing to ../dev-repo
   searching for changes
@@ -212,7 +208,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  2 new obsolescence markers
+  1 new obsolescence markers
   obsoleted 1 changesets
   updating bookmark bug15
   $ hg -R ../review bookmarks
@@ -257,7 +253,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  2 new obsolescence markers
+  1 new obsolescence markers
   obsoleted 1 changesets
   updating bookmark featureX
 
@@ -272,7 +268,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  4 new obsolescence markers
+  2 new obsolescence markers
   $ hg -R ../public bookmarks
   no bookmarks set
   $ hg push ../review
@@ -283,7 +279,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  2 new obsolescence markers
+  1 new obsolescence markers
   obsoleted 1 changesets
   updating bookmark featureX
   $ hg -R ../review bookmarks
@@ -333,17 +329,15 @@
 her change, so now she can publish it.
   $ cd ../alice
   $ hg --hidden shortlog -G -r 1::
-  @  4:cbdfbd5a5db2  draft  fix bug 15 (v2)
+  @  3:cbdfbd5a5db2  draft  fix bug 15 (v2)
   |
-  | x  3:55dd95168a35  draft  temporary amend commit for f91e97234c2b
-  | |
   | x  2:f91e97234c2b  draft  fix bug 15 (v1)
   |/
   o  1:de6151c48e1c  public  fix bug 37
   |
   ~
   $ hg outgoing -q ../public
-  4:cbdfbd5a5db2
+  3:cbdfbd5a5db2
   $ hg push ../public
   pushing to ../public
   searching for changes
@@ -358,22 +352,21 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  4 new obsolescence markers
+  2 new obsolescence markers
+  new changesets 540ba8f317e6
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg log -G -q -r 'head()'
-  o  5:540ba8f317e6
+  o  4:540ba8f317e6
   |
   ~
-  @  4:cbdfbd5a5db2
+  @  3:cbdfbd5a5db2
   |
   ~
   $ hg --hidden shortlog -G -r 1::
-  o  5:540ba8f317e6  public  implement feature X (v3)
+  o  4:540ba8f317e6  public  implement feature X (v3)
   |
-  | @  4:cbdfbd5a5db2  draft  fix bug 15 (v2)
+  | @  3:cbdfbd5a5db2  draft  fix bug 15 (v2)
   |/
-  | x  3:55dd95168a35  draft  temporary amend commit for f91e97234c2b
-  | |
   | x  2:f91e97234c2b  draft  fix bug 15 (v1)
   |/
   o  1:de6151c48e1c  public  fix bug 37
@@ -383,7 +376,7 @@
 Alice rebases her draft changeset on top of Bob's public changeset and
 publishes the result.
   $ hg rebase -d 5
-  rebasing 4:cbdfbd5a5db2 "fix bug 15 (v2)" (bug15)
+  rebasing 3:cbdfbd5a5db2 "fix bug 15 (v2)" (bug15)
   $ hg push ../public
   pushing to ../public
   searching for changes
@@ -391,7 +384,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  3 new obsolescence markers
+  2 new obsolescence markers
   $ hg push ../review
   pushing to ../review
   searching for changes
@@ -464,6 +457,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets 2fe6c4bd32d0
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ echo 'better fix (alice)' >> file1
   $ hg amend -u alice -m 'fix bug 24 (v2 by alice)'
@@ -474,10 +468,8 @@
   $ echo 'better fix (bob)' >> file1
   $ hg amend -u bob -m 'fix bug 24 (v2 by bob)'
   $ hg --hidden shortlog -G -r 3::
-  @  6:a360947f6faf  draft  fix bug 24 (v2 by bob)
+  @  5:a360947f6faf  draft  fix bug 24 (v2 by bob)
   |
-  | x  5:3466c7f5a149  draft  temporary amend commit for 2fe6c4bd32d0
-  | |
   | x  4:2fe6c4bd32d0  draft  fix bug 24 (v1)
   |/
   o  3:a06ec1bf97bd  public  fix bug 15 (v2)
@@ -492,56 +484,51 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  2 new obsolescence markers
+  1 new obsolescence markers
+  new changesets e3f99ce9d9cd
   (run 'hg heads' to see heads, 'hg merge' to merge)
-  2 new divergent changesets
+  2 new content-divergent changesets
 
 Figure SG09: multiple heads! divergence! oh my!
   $ hg --hidden shortlog -G -r 3::
-  o  7:e3f99ce9d9cd  draft  fix bug 24 (v2 by alice)
+  o  6:e3f99ce9d9cd  draft  fix bug 24 (v2 by alice)
   |
-  | @  6:a360947f6faf  draft  fix bug 24 (v2 by bob)
+  | @  5:a360947f6faf  draft  fix bug 24 (v2 by bob)
   |/
-  | x  5:3466c7f5a149  draft  temporary amend commit for 2fe6c4bd32d0
-  | |
   | x  4:2fe6c4bd32d0  draft  fix bug 24 (v1)
   |/
   o  3:a06ec1bf97bd  public  fix bug 15 (v2)
   |
   ~
   $ hg --hidden shortlog -r 'successors(2fe6)'
-  6:a360947f6faf  draft  fix bug 24 (v2 by bob)
-  7:e3f99ce9d9cd  draft  fix bug 24 (v2 by alice)
+  5:a360947f6faf  draft  fix bug 24 (v2 by bob)
+  6:e3f99ce9d9cd  draft  fix bug 24 (v2 by alice)
 
 Use evolve to fix the divergence.
-  $ HGMERGE=internal:other hg evolve --divergent
-  merge:[6] fix bug 24 (v2 by bob)
-  with: [7] fix bug 24 (v2 by alice)
+  $ HGMERGE=internal:other hg evolve --content-divergent
+  merge:[5] fix bug 24 (v2 by bob)
+  with: [6] fix bug 24 (v2 by alice)
   base: [4] fix bug 24 (v1)
   0 files updated, 1 files merged, 0 files removed, 0 files unresolved
   working directory is now at 5ad6037c046c
-  $ hg log -q -r 'divergent()'
+  $ hg log -q -r 'contentdivergent()'
 
 Figure SG10: Bob's repository after fixing divergence.
   $ hg --hidden shortlog -G -r 3::
-  @  9:5ad6037c046c  draft  fix bug 24 (v2 by bob)
+  @  7:5ad6037c046c  draft  fix bug 24 (v2 by bob)
   |
-  | x  8:bcfc9a755ac3  draft  temporary amend commit for a360947f6faf
-  | |
-  +---x  7:e3f99ce9d9cd  draft  fix bug 24 (v2 by alice)
-  | |
-  | x  6:a360947f6faf  draft  fix bug 24 (v2 by bob)
+  | x  6:e3f99ce9d9cd  draft  fix bug 24 (v2 by alice)
   |/
-  | x  5:3466c7f5a149  draft  temporary amend commit for 2fe6c4bd32d0
-  | |
+  | x  5:a360947f6faf  draft  fix bug 24 (v2 by bob)
+  |/
   | x  4:2fe6c4bd32d0  draft  fix bug 24 (v1)
   |/
   o  3:a06ec1bf97bd  public  fix bug 15 (v2)
   |
   ~
-  $ hg --hidden shortlog -r 'precursors(9)'
-  6:a360947f6faf  draft  fix bug 24 (v2 by bob)
-  7:e3f99ce9d9cd  draft  fix bug 24 (v2 by alice)
+  $ hg --hidden shortlog -r 'precursors(5ad6037c046c)'
+  5:a360947f6faf  draft  fix bug 24 (v2 by bob)
+  6:e3f99ce9d9cd  draft  fix bug 24 (v2 by alice)
   $ cat file1
   Do stuff.
   pretty good fix
--- a/tests/test-split.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-split.t	Tue Nov 14 23:04:04 2017 +0100
@@ -39,8 +39,7 @@
   $ echo "change to a" >> _a
   $ hg amend
   $ hg debugobsolete
-  1334a80b33c3f9873edab728fbbcf500eab61d2e d2fe56e71366c2c5376c89960c281395062c0619 0 (*) {'ef1': '8', 'user': 'test'} (glob)
-  06be89dfe2ae447383f30a2984933352757b6fb4 0 {1334a80b33c3f9873edab728fbbcf500eab61d2e} (*) {'ef1': '0', 'user': 'test'} (glob)
+  1334a80b33c3f9873edab728fbbcf500eab61d2e d2fe56e71366c2c5376c89960c281395062c0619 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'}
 
 To create commits with the number of split
   $ echo 0 > num
@@ -92,17 +91,16 @@
   no more change to split
 
   $ hg debugobsolete
-  1334a80b33c3f9873edab728fbbcf500eab61d2e d2fe56e71366c2c5376c89960c281395062c0619 0 (*) {'ef1': '8', 'user': 'test'} (glob)
-  06be89dfe2ae447383f30a2984933352757b6fb4 0 {1334a80b33c3f9873edab728fbbcf500eab61d2e} (*) {'ef1': '0', 'user': 'test'} (glob)
+  1334a80b33c3f9873edab728fbbcf500eab61d2e d2fe56e71366c2c5376c89960c281395062c0619 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'}
   d2fe56e71366c2c5376c89960c281395062c0619 2d8abdb827cdf71ca477ef6985d7ceb257c53c1b 033b3f5ae73db67c10de938fb6f26b949aaef172 0 (*) {'ef1': '13', 'user': 'test'} (glob)
   $ hg log -G
-  @  changeset:   7:033b3f5ae73d
+  @  changeset:   6:033b3f5ae73d
   |  tag:         tip
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     split2
   |
-  o  changeset:   6:2d8abdb827cd
+  o  changeset:   5:2d8abdb827cd
   |  parent:      2:52149352b372
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
@@ -148,15 +146,15 @@
 Split a revision specified with -r
   $ echo "change to b" >> _b
   $ hg amend -m "_cprim"
-  2 new unstable changesets
+  2 new orphan changesets
   $ hg evolve --all
-  move:[6] split1
-  atop:[9] _cprim
-  move:[7] split2
-  atop:[10] split1
+  move:[5] split1
+  atop:[7] _cprim
+  move:[6] split2
+  atop:[8] split1
   working directory is now at * (glob)
   $ hg log -r "desc(_cprim)" -v -p
-  changeset:   9:b434287e665c
+  changeset:   7:b434287e665c
   parent:      1:37445b16603b
   user:        other-test-user
   date:        Thu Jan 01 00:00:00 1970 +0000
@@ -210,38 +208,36 @@
 remaining changes
 
   $ hg debugobsolete
-  1334a80b33c3f9873edab728fbbcf500eab61d2e d2fe56e71366c2c5376c89960c281395062c0619 0 (*) {'ef1': '8', 'user': 'test'} (glob)
-  06be89dfe2ae447383f30a2984933352757b6fb4 0 {1334a80b33c3f9873edab728fbbcf500eab61d2e} (*) {'ef1': '0', 'user': 'test'} (glob)
+  1334a80b33c3f9873edab728fbbcf500eab61d2e d2fe56e71366c2c5376c89960c281395062c0619 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'}
   d2fe56e71366c2c5376c89960c281395062c0619 2d8abdb827cdf71ca477ef6985d7ceb257c53c1b 033b3f5ae73db67c10de938fb6f26b949aaef172 0 (*) {'ef1': '13', 'user': 'test'} (glob)
-  52149352b372d39b19127d5bd2d488b1b63f9f85 b434287e665ce757ee5463a965cb3d119ca9e893 0 (*) {'ef1': '9', 'user': 'test'} (glob)
-  7a4fc25a48a5797bb069563854455aecf738d8f2 0 {52149352b372d39b19127d5bd2d488b1b63f9f85} (*) {'ef1': '0', 'user': 'test'} (glob)
+  52149352b372d39b19127d5bd2d488b1b63f9f85 b434287e665ce757ee5463a965cb3d119ca9e893 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '9', 'operation': 'amend', 'user': 'test'}
   2d8abdb827cdf71ca477ef6985d7ceb257c53c1b e2b4afde39803bd42bb1374b230fca1b1e8cc868 0 (*) {'ef1': '4', 'user': 'test'} (glob)
   033b3f5ae73db67c10de938fb6f26b949aaef172 bb5e4f6020c74e7961a51fda635ea9df9b04dda8 0 (*) {'ef1': '4', 'user': 'test'} (glob)
   b434287e665ce757ee5463a965cb3d119ca9e893 ead2066d1dbf14833fe1069df1b735e4e9468c40 1188c4216eba37f18a1de6558564601d00ff2143 0 (*) {'ef1': '13', 'user': 'test'} (glob)
   $ hg evolve --all
-  move:[10] split1
-  atop:[13] split4
-  move:[11] split2
-  atop:[14] split1
+  move:[8] split1
+  atop:[11] split4
+  move:[9] split2
+  atop:[12] split1
   working directory is now at d74c6715e706
   $ hg log -G
-  @  changeset:   15:d74c6715e706
+  @  changeset:   13:d74c6715e706
   |  tag:         tip
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     split2
   |
-  o  changeset:   14:3f134f739075
+  o  changeset:   12:3f134f739075
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     split1
   |
-  o  changeset:   13:1188c4216eba
+  o  changeset:   11:1188c4216eba
   |  user:        other-test-user
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     split4
   |
-  o  changeset:   12:ead2066d1dbf
+  o  changeset:   10:ead2066d1dbf
   |  parent:      1:37445b16603b
   |  user:        other-test-user
   |  date:        Thu Jan 01 00:00:00 1970 +0000
@@ -265,19 +261,19 @@
   $ echo "changetofilea" > _a
   $ hg amend
   $ hg book
-     bookA                     17:7a6b35779b85
-   * bookB                     17:7a6b35779b85
-  $ hg log -G -r "14::"
-  @  changeset:   17:7a6b35779b85
+     bookA                     14:7a6b35779b85
+   * bookB                     14:7a6b35779b85
+  $ hg log -G -r "3f134f739075::"
+  @  changeset:   14:7a6b35779b85
   |  bookmark:    bookA
   |  bookmark:    bookB
   |  tag:         tip
-  |  parent:      14:3f134f739075
+  |  parent:      12:3f134f739075
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     split2
   |
-  o  changeset:   14:3f134f739075
+  o  changeset:   12:3f134f739075
   |  user:        test
   ~  date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     split1
@@ -308,8 +304,8 @@
   
   created new head
   Done splitting? [yN] y
-  $ hg log -G -r "14::"
-  @  changeset:   19:452a26648478
+  $ hg log -G -r "3f134f739075::"
+  @  changeset:   16:452a26648478
   |  bookmark:    bookA
   |  bookmark:    bookB
   |  tag:         tip
@@ -317,20 +313,20 @@
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     split6
   |
-  o  changeset:   18:1315679b77dc
-  |  parent:      14:3f134f739075
+  o  changeset:   15:1315679b77dc
+  |  parent:      12:3f134f739075
   |  user:        victor
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     split5
   |
-  o  changeset:   14:3f134f739075
+  o  changeset:   12:3f134f739075
   |  user:        test
   ~  date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     split1
   
   $ hg book
-     bookA                     19:452a26648478
-   * bookB                     19:452a26648478
+     bookA                     16:452a26648478
+   * bookB                     16:452a26648478
  
 Lastest revision is selected if multiple are given to -r
   $ hg split -r "desc(_a)::"
@@ -409,12 +405,14 @@
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "topic=$(echo $(dirname $TESTDIR))/hgext3rd/topic/" >> $HGRCPATH
   $ hg topic mytopic
+  marked working directory as topic: mytopic
   $ echo babar > babar
   $ echo celeste > celeste
   $ hg add babar celeste
   $ hg commit -m "Works on mytopic" babar celeste --user victor
+  active topic 'mytopic' grew its first changeset
   $ hg log -r . 
-  changeset:   21:26f72cfaf036
+  changeset:   18:26f72cfaf036
   branch:      new-branch
   tag:         tip
   topic:       mytopic
@@ -423,7 +421,7 @@
   summary:     Works on mytopic
   
   $ hg summary
-  parent: 21:26f72cfaf036 tip
+  parent: 18:26f72cfaf036 tip
    Works on mytopic
   branch: new-branch
   commit: 2 unknown (clean)
@@ -470,15 +468,15 @@
 Check that the topic is still here
 
   $ hg log -r "tip~1::"
-  changeset:   22:addcf498f19e
+  changeset:   19:addcf498f19e
   branch:      new-branch
   topic:       mytopic
-  parent:      20:fdb403258632
+  parent:      17:fdb403258632
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
   summary:     split7
   
-  changeset:   23:2532b288af61
+  changeset:   20:2532b288af61
   branch:      new-branch
   tag:         tip
   topic:       mytopic
@@ -487,4 +485,4 @@
   summary:     split8
   
   $ hg topic
-   * mytopic
+   * mytopic (2 changesets)
--- a/tests/test-stabilize-conflict.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-stabilize-conflict.t	Tue Nov 14 23:04:04 2017 +0100
@@ -65,7 +65,7 @@
   $ safesed 's/huit/eight/' babar
   $ hg diff
   diff -r 9d5daf8bd956 babar
-  --- a/babar	Thu Jan 01 00:00:00 1970 +0000
+  --- a/babar	* (glob)
   +++ b/babar	* (glob)
   @@ -5,6 +5,6 @@
    cinq
@@ -76,21 +76,21 @@
    neuf
    dix
   $ hg amend
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg evolve
   move:[2] babar count up to fifteen
-  atop:[4] babar count up to ten
+  atop:[3] babar count up to ten
   merging babar
   working directory is now at 71c18f70c34f
   $ hg resolve -l
   $ hg log -G
-  @  changeset:   5:71c18f70c34f
+  @  changeset:   4:71c18f70c34f
   |  tag:         tip
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     babar count up to fifteen
   |
-  o  changeset:   4:5977072d13c5
+  o  changeset:   3:5977072d13c5
   |  parent:      0:29ec1554cfaf
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
@@ -109,12 +109,12 @@
   $ hg gdown
   gdown have been deprecated in favor of previous
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  [4] babar count up to ten
+  [3] babar count up to ten
   $ safesed 's/dix/ten/' babar
   $ hg diff
   diff -r 5977072d13c5 babar
   --- a/babar	Thu Jan 01 00:00:00 1970 +0000
-  +++ b/babar	* (glob)
+  +++ b/babar	Thu Jan 01 00:00:00 1970 +0000
   @@ -7,4 +7,4 @@
    sept
    eight
@@ -122,10 +122,10 @@
   -dix
   +ten
   $ hg amend
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg evolve
-  move:[5] babar count up to fifteen
-  atop:[7] babar count up to ten
+  move:[4] babar count up to fifteen
+  atop:[5] babar count up to ten
   merging babar
   warning: conflicts while merging babar! (edit, then use 'hg resolve --mark')
   evolve failed!
@@ -135,24 +135,24 @@
   $ hg resolve -l
   U babar
   $ hg log -G
-  @  changeset:   7:e04690b09bc6
+  @  changeset:   5:e04690b09bc6
   |  tag:         tip
   |  parent:      0:29ec1554cfaf
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     babar count up to ten
   |
-  | o  changeset:   5:71c18f70c34f
+  | o  changeset:   4:71c18f70c34f
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  trouble:     unstable
+  | |  instability: orphan
   | |  summary:     babar count up to fifteen
   | |
-  | x  changeset:   4:5977072d13c5
+  | x  changeset:   3:5977072d13c5
   |/   parent:      0:29ec1554cfaf
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as e04690b09bc6
+  |    obsolete:    amended using amend as 5:e04690b09bc6
   |    summary:     babar count up to ten
   |
   o  changeset:   0:29ec1554cfaf
@@ -162,22 +162,22 @@
   
 (fix the conflict and continue)
 
-  $ hg revert -r 5 --all
+  $ hg revert -r 71c18f70c34f --all
   reverting babar
   $ safesed 's/dix/ten/' babar
   $ hg resolve --all -m
   (no more unresolved files)
   $ hg evolve --continue
-  grafting 5:71c18f70c34f "babar count up to fifteen"
+  grafting 4:71c18f70c34f "babar count up to fifteen"
   $ hg resolve -l
   $ hg log -G
-  @  changeset:   8:1836b91c6c1d
+  @  changeset:   6:1836b91c6c1d
   |  tag:         tip
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     babar count up to fifteen
   |
-  o  changeset:   7:e04690b09bc6
+  o  changeset:   5:e04690b09bc6
   |  parent:      0:29ec1554cfaf
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
@@ -196,12 +196,12 @@
   $ hg gdown
   gdown have been deprecated in favor of previous
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  [7] babar count up to ten
+  [5] babar count up to ten
   $ safesed 's/ten/zehn/' babar
   $ hg diff
   diff -r e04690b09bc6 babar
   --- a/babar	Thu Jan 01 00:00:00 1970 +0000
-  +++ b/babar	* (glob)
+  +++ b/babar	Thu Jan 01 00:00:00 1970 +0000
   @@ -7,4 +7,4 @@
    sept
    eight
@@ -209,13 +209,13 @@
   -ten
   +zehn
   $ hg amend
-  1 new unstable changesets
+  1 new orphan changesets
   $ safesed 's/interactive=.*/interactive=true/' $HGRCPATH
   $ hg evolve --tool touch <<EOF
   > n
   > EOF
-  move:[8] babar count up to fifteen
-  atop:[10] babar count up to ten
+  move:[6] babar count up to fifteen
+  atop:[7] babar count up to ten
   merging babar
    output file babar appears unchanged
   was merge successful (yn)? n
@@ -227,24 +227,24 @@
   $ hg resolve -l
   U babar
   $ hg log -G
-  @  changeset:   10:b20d08eea373
+  @  changeset:   7:b20d08eea373
   |  tag:         tip
   |  parent:      0:29ec1554cfaf
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     babar count up to ten
   |
-  | o  changeset:   8:1836b91c6c1d
+  | o  changeset:   6:1836b91c6c1d
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  trouble:     unstable
+  | |  instability: orphan
   | |  summary:     babar count up to fifteen
   | |
-  | x  changeset:   7:e04690b09bc6
+  | x  changeset:   5:e04690b09bc6
   |/   parent:      0:29ec1554cfaf
   |    user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as b20d08eea373
+  |    obsolete:    amended using amend as 7:b20d08eea373
   |    summary:     babar count up to ten
   |
   o  changeset:   0:29ec1554cfaf
--- a/tests/test-stabilize-order.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-stabilize-order.t	Tue Nov 14 23:04:04 2017 +0100
@@ -38,18 +38,18 @@
   [2] addb
   $ echo b >> b
   $ hg amend
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg gdown
   gdown have been deprecated in favor of previous
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   [1] adda
   $ echo a >> a
   $ hg amend
-  1 new unstable changesets
+  1 new orphan changesets
   $ glog
-  @  7:005fe5914f78@default(draft) adda
+  @  5:005fe5914f78@default(draft) adda
   |
-  | o  5:22619daeed78@default(draft) addb
+  | o  4:22619daeed78@default(draft) addb
   | |
   | | o  3:7a7552255fb5@default(draft) addc
   | | |
@@ -63,8 +63,8 @@
 Test stabilizing a predecessor child
 
   $ hg evolve -v
-  move:[5] addb
-  atop:[7] adda
+  move:[4] addb
+  atop:[5] adda
   hg rebase -r 22619daeed78 -d 005fe5914f78
   resolving manifests
   getting b
@@ -74,9 +74,9 @@
   committing changelog
   working directory is now at 81b8bbcd5892
   $ glog
-  @  8:81b8bbcd5892@default(draft) addb
+  @  6:81b8bbcd5892@default(draft) addb
   |
-  o  7:005fe5914f78@default(draft) adda
+  o  5:005fe5914f78@default(draft) adda
   |
   | o  3:7a7552255fb5@default(draft) addc
   | |
@@ -89,12 +89,12 @@
 
 Test stabilizing a descendant predecessor's child
 
-  $ hg up 7
+  $ hg up -r 005fe5914f78
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg debugobsolete > successors.old
   $ hg evolve -v
   move:[3] addc
-  atop:[8] addb
+  atop:[6] addb
   hg rebase -r 7a7552255fb5 -d 81b8bbcd5892
   resolving manifests
   getting b
@@ -109,21 +109,21 @@
   $ diff -u successors.old successors.new
   --- successors.old* (glob)
   +++ successors.new* (glob)
-  @@ -3,3 +3,4 @@
-   93418d2c0979643ad446f621195e78720edb05b4 005fe5914f78e8bc64c7eba28117b0b1fa210d0d 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-   7a7d76dc97c57751de9e80f61ed2a639bd03cd24 0 {93418d2c0979643ad446f621195e78720edb05b4} (*) {'ef1': '*', 'user': 'test'} (glob)
-   22619daeed78036f80fbd326b6852519c4f0c25e 81b8bbcd5892841efed41433d7a5e9df922396cb 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  +7a7552255fb5f8bd745e46fba6f0ca633a4dd716 0f691739f91762462bf8ba21f35fdf71fe64310e 0 (*) {'ef1': '*', 'user': 'test'} (glob)
+  @@ -1,3 +1,4 @@
+   ef23d6ef94d68dea65d20587dfecc8b33d165617 22619daeed78036f80fbd326b6852519c4f0c25e 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'}
+   93418d2c0979643ad446f621195e78720edb05b4 005fe5914f78e8bc64c7eba28117b0b1fa210d0d 0 (Thu Jan 01 00:00:00 1970 +0000) {'ef1': '8', 'operation': 'amend', 'user': 'test'}
+   22619daeed78036f80fbd326b6852519c4f0c25e 81b8bbcd5892841efed41433d7a5e9df922396cb 0 (*) {'ef1': '4', 'user': 'test'} (glob)
+  +7a7552255fb5f8bd745e46fba6f0ca633a4dd716 0f691739f91762462bf8ba21f35fdf71fe64310e 0 (*) {'ef1': '4', 'user': 'test'} (glob)
   [1]
 
 
 
   $ glog
-  @  9:0f691739f917@default(draft) addc
+  @  7:0f691739f917@default(draft) addc
   |
-  o  8:81b8bbcd5892@default(draft) addb
+  o  6:81b8bbcd5892@default(draft) addb
   |
-  o  7:005fe5914f78@default(draft) adda
+  o  5:005fe5914f78@default(draft) adda
   |
   o  0:c471ef929e6a@default(draft) addroot
   
@@ -133,31 +133,31 @@
 
 Test behavior with --any
 
-  $ hg up 8
+  $ hg up 81b8bbcd5892
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ echo b >> b
   $ hg amend
-  1 new unstable changesets
+  1 new orphan changesets
   $ glog
-  @  11:7a68bc4596ea@default(draft) addb
+  @  8:7a68bc4596ea@default(draft) addb
   |
-  | o  9:0f691739f917@default(draft) addc
+  | o  7:0f691739f917@default(draft) addc
   | |
-  | x  8:81b8bbcd5892@default(draft) addb
+  | x  6:81b8bbcd5892@default(draft) addb
   |/
-  o  7:005fe5914f78@default(draft) adda
+  o  5:005fe5914f78@default(draft) adda
   |
   o  0:c471ef929e6a@default(draft) addroot
   
-  $ hg up 9
+  $ hg up 0f691739f917
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg evolve -v
   nothing to evolve on current working copy parent
-  (1 other unstable in the repository, do you want --any or --rev)
+  (1 other orphan in the repository, do you want --any or --rev)
   [2]
   $ hg evolve --any -v
-  move:[9] addc
-  atop:[11] addb
+  move:[7] addc
+  atop:[8] addb
   hg rebase -r 0f691739f917 -d 7a68bc4596ea
   resolving manifests
   removing c
@@ -170,16 +170,16 @@
   committing changelog
   working directory is now at 2256dae6521f
   $ glog
-  @  12:2256dae6521f@default(draft) addc
+  @  9:2256dae6521f@default(draft) addc
   |
-  o  11:7a68bc4596ea@default(draft) addb
+  o  8:7a68bc4596ea@default(draft) addb
   |
-  o  7:005fe5914f78@default(draft) adda
+  o  5:005fe5914f78@default(draft) adda
   |
   o  0:c471ef929e6a@default(draft) addroot
   
   $ hg evolve --any -v
-  no unstable changesets to evolve
+  no orphan changesets to evolve
   [1]
 
 Ambiguous evolution
@@ -195,41 +195,41 @@
   $ hg up .^
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg commit --amend -m "newmessage"
-  2 new unstable changesets
+  2 new orphan changesets
   $ hg log -G
-  @  changeset:   15:f83a0bce03e4
+  @  changeset:   12:f83a0bce03e4
   |  tag:         tip
-  |  parent:      11:7a68bc4596ea
+  |  parent:      8:7a68bc4596ea
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     newmessage
   |
-  | o  changeset:   14:fa68011f392e
-  | |  parent:      12:2256dae6521f
+  | o  changeset:   11:fa68011f392e
+  | |  parent:      9:2256dae6521f
   | |  user:        test
   | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  trouble:     unstable
+  | |  instability: orphan
   | |  summary:     secondambiguous
   | |
-  | | o  changeset:   13:bdc003b6eec2
+  | | o  changeset:   10:bdc003b6eec2
   | |/   user:        test
   | |    date:        Thu Jan 01 00:00:00 1970 +0000
-  | |    trouble:     unstable
+  | |    instability: orphan
   | |    summary:     firstambiguous
   | |
-  | x  changeset:   12:2256dae6521f
+  | x  changeset:   9:2256dae6521f
   |/   user:        test
   |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    obsolete:    rewritten as f83a0bce03e4
+  |    obsolete:    reworded using amend as 12:f83a0bce03e4
   |    summary:     addc
   |
-  o  changeset:   11:7a68bc4596ea
-  |  parent:      7:005fe5914f78
+  o  changeset:   8:7a68bc4596ea
+  |  parent:      5:005fe5914f78
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     addb
   |
-  o  changeset:   7:005fe5914f78
+  o  changeset:   5:005fe5914f78
   |  parent:      0:c471ef929e6a
   |  user:        test
   |  date:        Thu Jan 01 00:00:00 1970 +0000
--- a/tests/test-stabilize-result.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-stabilize-result.t	Tue Nov 14 23:04:04 2017 +0100
@@ -27,33 +27,30 @@
   (leaving bookmark changea)
   $ echo a >> a
   $ hg amend -m changea
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg evolve -v --confirm
   move:[2] changea
-  atop:[4] changea
+  atop:[3] changea
   perform evolve? [Ny] n
   abort: evolve aborted by user
   [255]
   $ echo y | hg evolve -v --confirm --config ui.interactive=True
   move:[2] changea
-  atop:[4] changea
+  atop:[3] changea
   perform evolve? [Ny] y
   hg rebase -r cce2c55b8965 -d fb9d051ec0a4
   resolving manifests
   $ glog --hidden
-  @  4:fb9d051ec0a4@default(draft) bk:[changea] changea
+  @  3:fb9d051ec0a4@default(draft) bk:[changea] changea
   |
-  | x  3:c5727dbded3c@default(draft) bk:[] temporary amend commit for 102a90ea7b4a
+  | x  2:cce2c55b8965@default(draft) bk:[] changea
   | |
-  | | x  2:cce2c55b8965@default(draft) bk:[] changea
-  | |/
   | x  1:102a90ea7b4a@default(draft) bk:[] addb
   |/
   o  0:07f494440405@default(draft) bk:[] adda
   
   $ hg debugobsolete
   102a90ea7b4a3361e4082ed620918c261189a36a fb9d051ec0a450a4aa2ffc8c324979832ef88065 0 (*) {'ef1': '*', 'user': 'test'} (glob)
-  c5727dbded3c3a6877cf60d6bb552a76812cb844 0 {102a90ea7b4a3361e4082ed620918c261189a36a} (*) {'ef1': '*', 'user': 'test'} (glob)
   cce2c55b896511e0b6e04173c9450ba822ebc740 0 {102a90ea7b4a3361e4082ed620918c261189a36a} (*) {'ef1': '*', 'user': 'test'} (glob)
 
 Test evolve with conflict
@@ -73,20 +70,20 @@
   $ hg gdown
   gdown have been deprecated in favor of previous
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  [4] changea
+  [3] changea
   $ echo 'a' > a
   $ hg amend
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg evolve
-  move:[5] newer a
-  atop:[7] changea
+  move:[4] newer a
+  atop:[5] changea
   merging a
   warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
   evolve failed!
   fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort
   abort: unresolved merge conflicts (see hg help resolve)
   [255]
-  $ hg revert -r 'unstable()' a
+  $ hg revert -r "orphan()" a
   $ hg diff
   diff -r 66719795a494 a
   --- a/a	* (glob)
@@ -96,13 +93,13 @@
   +a
   +newer a
   $ hg evolve --continue
-  grafting 5:3655f0f50885 "newer a"
+  grafting 4:3655f0f50885 "newer a"
   abort: unresolved merge conflicts (see 'hg help resolve')
   [255]
   $ hg resolve -m a
   (no more unresolved files)
   $ hg evolve --continue
-  grafting 5:3655f0f50885 "newer a"
+  grafting 4:3655f0f50885 "newer a"
 
 Stabilize latecomer with different parent
 =========================================
@@ -110,9 +107,9 @@
 (the same-parent case is handled in test-evolve.t)
 
   $ glog
-  @  8:1cf0aacfd363@default(draft) bk:[] newer a
+  @  6:1cf0aacfd363@default(draft) bk:[] newer a
   |
-  o  7:66719795a494@default(draft) bk:[changea] changea
+  o  5:66719795a494@default(draft) bk:[changea] changea
   |
   o  0:07f494440405@default(draft) bk:[] adda
   
@@ -121,7 +118,7 @@
   $ hg gdown
   gdown have been deprecated in favor of previous
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  [7] changea
+  [5] changea
   $ echo 'c' > c
   $ hg add c
   $ hg commit -m 'add c'
@@ -129,8 +126,8 @@
 
 Get a successors of 8 on it
 
-  $ hg grab 8
-  rebasing 8:1cf0aacfd363 "newer a"
+  $ hg grab 1cf0aacfd363
+  rebasing 6:1cf0aacfd363 "newer a"
   ? files updated, 0 files merged, 0 files removed, 0 files unresolved (glob)
 
 Add real change to the successors
@@ -140,51 +137,51 @@
 
 Make precursors public
 
-  $ hg phase --hidden --public 8
-  1 new bumped changesets
+  $ hg phase --hidden --public 1cf0aacfd363
+  1 new phase-divergent changesets
   $ glog
-  @  12:(73b15c7566e9|d5c7ef82d003)@default\(draft\) bk:\[\] newer a (re)
+  @  9:(73b15c7566e9|d5c7ef82d003)@default\(draft\) bk:\[\] newer a (re)
   |
-  o  9:7bc2f5967f5e@default(draft) bk:[] add c
+  o  7:7bc2f5967f5e@default(draft) bk:[] add c
   |
-  | o  8:1cf0aacfd363@default(public) bk:[] newer a
+  | o  6:1cf0aacfd363@default(public) bk:[] newer a
   |/
-  o  7:66719795a494@default(public) bk:[changea] changea
+  o  5:66719795a494@default(public) bk:[changea] changea
   |
   o  0:07f494440405@default(public) bk:[] adda
   
 
 Stabilize!
 
-  $ hg evolve --any --dry-run --bumped
-  recreate:[12] newer a
-  atop:[8] newer a
-  hg rebase --rev (73b15c7566e9|d5c7ef82d003) --dest 66719795a494; (re)
+  $ hg evolve --any --dry-run --phase-divergent
+  recreate:[9] newer a
+  atop:[6] newer a
+  hg rebase --rev d5c7ef82d003 --dest 66719795a494;
   hg update 1cf0aacfd363;
-  hg revert --all --rev (73b15c7566e9|d5c7ef82d003); (re)
+  hg revert --all --rev d5c7ef82d003;
   hg commit --msg "bumped update to %s" (no-eol)
-  $ hg evolve --any --confirm --bumped
-  recreate:[12] newer a
-  atop:[8] newer a
+  $ hg evolve --any --confirm --phase-divergent
+  recreate:[9] newer a
+  atop:[6] newer a
   perform evolve? [Ny] n
   abort: evolve aborted by user
   [255]
-  $ echo y | hg evolve --any --confirm --config ui.interactive=True --bumped
-  recreate:[12] newer a
-  atop:[8] newer a
+  $ echo y | hg evolve --any --confirm --config ui.interactive=True --phase-divergent
+  recreate:[9] newer a
+  atop:[6] newer a
   perform evolve? [Ny] y
   rebasing to destination parent: 66719795a494
   computing new diff
   committed as c2c1151aa854
   working directory is now at c2c1151aa854
   $ glog
-  @  14:c2c1151aa854@default(draft) bk:[] bumped update to 1cf0aacfd363:
+  @  11:c2c1151aa854@default(draft) bk:[] bumped update to 1cf0aacfd363:
   |
-  | o  9:7bc2f5967f5e@default(draft) bk:[] add c
+  | o  7:7bc2f5967f5e@default(draft) bk:[] add c
   | |
-  o |  8:1cf0aacfd363@default(public) bk:[] newer a
+  o |  6:1cf0aacfd363@default(public) bk:[] newer a
   |/
-  o  7:66719795a494@default(public) bk:[changea] changea
+  o  5:66719795a494@default(public) bk:[changea] changea
   |
   o  0:07f494440405@default(public) bk:[] adda
   
@@ -193,7 +190,7 @@
 ===============================================
 
   $ rm a.orig
-  $ hg up 9
+  $ hg up 7bc2f5967f5e
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cat << EOF >> a
   > flore
@@ -205,21 +202,21 @@
   > EOF
   $ hg ci -m 'More addition'
   $ glog
-  @  15:3932c176bbaa@default(draft) bk:[] More addition
+  @  12:3932c176bbaa@default(draft) bk:[] More addition
   |
-  | o  14:(a7cabd7bd9c2|671b9d7eeaec)@default\(draft\) bk:\[\] bumped update to 1cf0aacfd363: (re)
+  | o  11:c2c1151aa854@default(draft) bk:[] bumped update to 1cf0aacfd363:
   | |
-  o |  9:7bc2f5967f5e@default(draft) bk:[] add c
+  o |  7:7bc2f5967f5e@default(draft) bk:[] add c
   | |
-  | o  8:1cf0aacfd363@default(public) bk:[] newer a
+  | o  6:1cf0aacfd363@default(public) bk:[] newer a
   |/
-  o  7:66719795a494@default(public) bk:[changea] changea
+  o  5:66719795a494@default(public) bk:[changea] changea
   |
   o  0:07f494440405@default(public) bk:[] adda
   
   $ echo 'babar' >> a
   $ hg amend
-  $ hg up --hidden 15
+  $ hg up --hidden 3932c176bbaa
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   working directory parent is obsolete! (3932c176bbaa)
   (use 'hg evolve' to update to its successor: d2f173e25686)
@@ -228,36 +225,36 @@
   $ cat a.old >> a
   $ rm a.old
   $ hg amend
-  2 new divergent changesets
+  2 new content-divergent changesets
   $ glog
-  @  19:eacc9c8240fe@default(draft) bk:[] More addition
+  @  14:eacc9c8240fe@default(draft) bk:[] More addition
   |
-  | o  17:d2f173e25686@default(draft) bk:[] More addition
+  | o  13:d2f173e25686@default(draft) bk:[] More addition
   |/
-  | o  14:(a7cabd7bd9c2|671b9d7eeaec)@default\(draft\) bk:\[\] bumped update to 1cf0aacfd363: (re)
+  | o  11:c2c1151aa854@default(draft) bk:[] bumped update to 1cf0aacfd363:
   | |
-  o |  9:7bc2f5967f5e@default(draft) bk:[] add c
+  o |  7:7bc2f5967f5e@default(draft) bk:[] add c
   | |
-  | o  8:1cf0aacfd363@default(public) bk:[] newer a
+  | o  6:1cf0aacfd363@default(public) bk:[] newer a
   |/
-  o  7:66719795a494@default(public) bk:[changea] changea
+  o  5:66719795a494@default(public) bk:[changea] changea
   |
   o  0:07f494440405@default(public) bk:[] adda
   
 
 Stabilize it
 
-  $ hg evolve -qn --confirm --divergent
-  merge:[19] More addition
-  with: [17] More addition
-  base: [15] More addition
+  $ hg evolve -qn --confirm --content-divergent
+  merge:[14] More addition
+  with: [13] More addition
+  base: [12] More addition
   perform evolve? [Ny] n
   abort: evolve aborted by user
   [255]
-  $ echo y | hg evolve -qn --confirm --config ui.interactive=True --divergent
-  merge:[19] More addition
-  with: [17] More addition
-  base: [15] More addition
+  $ echo y | hg evolve -qn --confirm --config ui.interactive=True --content-divergent
+  merge:[14] More addition
+  with: [13] More addition
+  base: [12] More addition
   perform evolve? [Ny] y
   hg update -c eacc9c8240fe &&
   hg merge d2f173e25686 &&
@@ -265,10 +262,10 @@
   hg up -C 3932c176bbaa &&
   hg revert --all --rev tip &&
   hg commit -m "`hg log -r eacc9c8240fe --template={desc}`";
-  $ hg evolve -v --divergent
-  merge:[19] More addition
-  with: [17] More addition
-  base: [15] More addition
+  $ hg evolve -v --content-divergent
+  merge:[14] More addition
+  with: [13] More addition
+  base: [12] More addition
   merging divergent changeset
   resolving manifests
   merging a
@@ -278,29 +275,24 @@
   a
   committing manifest
   committing changelog
-  copying changeset 283ccd10e2b8 to 7bc2f5967f5e
-  committing files:
-  a
-  committing manifest
-  committing changelog
-  committed changeset 21:f344982e63c4
+  committed changeset 15:f344982e63c4
   working directory is now at f344982e63c4
   $ hg st
   $ glog
-  @  21:f344982e63c4@default(draft) bk:[] More addition
+  @  15:f344982e63c4@default(draft) bk:[] More addition
   |
-  | o  14:(a7cabd7bd9c2|671b9d7eeaec)@default\(draft\) bk:\[\] bumped update to 1cf0aacfd363: (re)
+  | o  11:c2c1151aa854@default(draft) bk:[] bumped update to 1cf0aacfd363:
   | |
-  o |  9:7bc2f5967f5e@default(draft) bk:[] add c
+  o |  7:7bc2f5967f5e@default(draft) bk:[] add c
   | |
-  | o  8:1cf0aacfd363@default(public) bk:[] newer a
+  | o  6:1cf0aacfd363@default(public) bk:[] newer a
   |/
-  o  7:66719795a494@default(public) bk:[changea] changea
+  o  5:66719795a494@default(public) bk:[changea] changea
   |
   o  0:07f494440405@default(public) bk:[] adda
   
   $ hg summary
-  parent: 21:f344982e63c4 tip
+  parent: 15:f344982e63c4 tip
    More addition
   branch: default
   commit: (clean)
@@ -332,29 +324,29 @@
 Check conflict during divergence resolution
 -------------------------------------------------
 
-  $ hg up --hidden 15
+  $ hg up --hidden 3932c176bbaa
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   working directory parent is obsolete! (3932c176bbaa)
   (use 'hg evolve' to update to its successor: f344982e63c4)
   $ echo 'gotta break' >> a
   $ hg amend
-  2 new divergent changesets
+  2 new content-divergent changesets
 # reamend so that the case is not the first precursor.
   $ hg amend -m "More addition (2)"
-  $ hg phase 'divergent()'
-  21: draft
-  24: draft
-  $ hg evolve -qn --divergent
+  $ hg phase 'contentdivergent()'
+  15: draft
+  17: draft
+  $ hg evolve -qn --content-divergent
   hg update -c 0b336205a5d0 &&
   hg merge f344982e63c4 &&
   hg commit -m "auto merge resolving conflict between 0b336205a5d0 and f344982e63c4"&&
   hg up -C 3932c176bbaa &&
   hg revert --all --rev tip &&
   hg commit -m "`hg log -r 0b336205a5d0 --template={desc}`";
-  $ hg evolve --divergent
-  merge:[24] More addition (2)
-  with: [21] More addition
-  base: [15] More addition
+  $ hg evolve --content-divergent
+  merge:[17] More addition (2)
+  with: [15] More addition
+  base: [12] More addition
   merging a
   warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
   0 files updated, 0 files merged, 0 files removed, 1 files unresolved
--- a/tests/test-stablesort-criss-cross.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-stablesort-criss-cross.t	Tue Nov 14 23:04:04 2017 +0100
@@ -608,6 +608,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 0 changes to 0 files
+  new changesets 1ea73414a91b
   updating to branch default
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cd crisscross_random
--- a/tests/test-stablesort.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-stablesort.t	Tue Nov 14 23:04:04 2017 +0100
@@ -145,6 +145,7 @@
   adding manifests
   adding file changes
   added 4 changesets with 0 changes to 0 files
+  new changesets 1ea73414a91b:f0f3ef9a6cd5
   updating to branch default
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg -R repo_B pull --rev 13
@@ -154,6 +155,7 @@
   adding manifests
   adding file changes
   added 4 changesets with 0 changes to 0 files (+1 heads)
+  new changesets 66f7d451a68b:b4594d867745
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg -R repo_B pull --rev 14
   pulling from $TESTTMP/repo_A (glob)
@@ -162,6 +164,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 0 changes to 0 files (+1 heads)
+  new changesets 43227190fef8
   (run 'hg heads .' to see heads, 'hg merge' to merge)
   $ hg -R repo_B pull
   pulling from $TESTTMP/repo_A (glob)
@@ -170,6 +173,7 @@
   adding manifests
   adding file changes
   added 7 changesets with 0 changes to 0 files (+3 heads)
+  new changesets 2702dd0c91e7:1d8d22637c2d
   (run 'hg heads .' to see heads, 'hg merge' to merge)
   $ hg -R repo_B log -G
   o    15 1d8d22637c2d r15 tip
@@ -211,6 +215,7 @@
   adding manifests
   adding file changes
   added 7 changesets with 0 changes to 0 files
+  new changesets 1ea73414a91b:ff43616e5d0f
   updating to branch default
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg -R repo_C pull --rev 12
@@ -220,6 +225,7 @@
   adding manifests
   adding file changes
   added 2 changesets with 0 changes to 0 files (+1 heads)
+  new changesets bab5d5bf48bd:e46a4836065c
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg -R repo_C pull --rev 15
   pulling from $TESTTMP/repo_A (glob)
@@ -228,6 +234,7 @@
   adding manifests
   adding file changes
   added 4 changesets with 0 changes to 0 files (+1 heads)
+  new changesets 4c748ffd1a46:1d8d22637c2d
   (run 'hg heads .' to see heads, 'hg merge' to merge)
   $ hg -R repo_C pull
   pulling from $TESTTMP/repo_A (glob)
@@ -236,6 +243,7 @@
   adding manifests
   adding file changes
   added 3 changesets with 0 changes to 0 files (+3 heads)
+  new changesets 2702dd0c91e7:b4594d867745
   (run 'hg heads .' to see heads, 'hg merge' to merge)
   $ hg -R repo_C log -G
   o  15 b4594d867745 r13 tip
@@ -277,6 +285,7 @@
   adding manifests
   adding file changes
   added 2 changesets with 0 changes to 0 files
+  new changesets 1ea73414a91b:fa942426a6fd
   updating to branch default
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg -R repo_D pull --rev 10
@@ -286,6 +295,7 @@
   adding manifests
   adding file changes
   added 5 changesets with 0 changes to 0 files
+  new changesets 66f7d451a68b:ff43616e5d0f
   (run 'hg update' to get a working copy)
   $ hg -R repo_D pull --rev 15
   pulling from $TESTTMP/repo_A (glob)
@@ -294,6 +304,7 @@
   adding manifests
   adding file changes
   added 4 changesets with 0 changes to 0 files (+1 heads)
+  new changesets 4c748ffd1a46:1d8d22637c2d
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg -R repo_D pull
   pulling from $TESTTMP/repo_A (glob)
@@ -302,6 +313,7 @@
   adding manifests
   adding file changes
   added 5 changesets with 0 changes to 0 files (+4 heads)
+  new changesets 2702dd0c91e7:b4594d867745
   (run 'hg heads .' to see heads, 'hg merge' to merge)
   $ hg -R repo_D log -G
   o  15 b4594d867745 r13 tip
@@ -411,6 +423,7 @@
   adding manifests
   adding file changes
   added 5 changesets with 0 changes to 0 files
+  new changesets 1ea73414a91b:43227190fef8
   updating to branch default
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg -R repo_E pull --rev e7d9710d9fc6
@@ -420,6 +433,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 0 changes to 0 files (+1 heads)
+  new changesets e7d9710d9fc6
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
   $ hg clone repo_A repo_F --rev "1d8d22637c2d"
@@ -427,6 +441,7 @@
   adding manifests
   adding file changes
   added 8 changesets with 0 changes to 0 files
+  new changesets 1ea73414a91b:1d8d22637c2d
   updating to branch default
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg -R repo_F pull --rev d62d843c9a01
@@ -436,6 +451,7 @@
   adding manifests
   adding file changes
   added 2 changesets with 0 changes to 0 files (+1 heads)
+  new changesets e7d9710d9fc6:d62d843c9a01
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
   $ hg clone repo_A repo_G --rev "e7d9710d9fc6"
@@ -443,6 +459,7 @@
   adding manifests
   adding file changes
   added 5 changesets with 0 changes to 0 files
+  new changesets 1ea73414a91b:e7d9710d9fc6
   updating to branch default
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg -R repo_G pull --rev 43227190fef8
@@ -452,6 +469,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 0 changes to 0 files (+1 heads)
+  new changesets 43227190fef8
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg -R repo_G pull --rev 2702dd0c91e7
   pulling from $TESTTMP/repo_A (glob)
@@ -460,6 +478,7 @@
   adding manifests
   adding file changes
   added 3 changesets with 0 changes to 0 files (+1 heads)
+  new changesets 4c748ffd1a46:2702dd0c91e7
   (run 'hg heads .' to see heads, 'hg merge' to merge)
 
   $ for x in E F G; do
@@ -588,6 +607,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 0 changes to 0 files
+  new changesets 1ea73414a91b
   updating to branch default
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cd recursion_random
--- a/tests/test-stack-branch.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-stack-branch.t	Tue Nov 14 23:04:04 2017 +0100
@@ -55,7 +55,7 @@
   $ hg up other
   0 files updated, 0 files merged, 4 files removed, 0 files unresolved
   $ hg stack
-  ### branch: other
+  ### target: other (branch)
   b2@ c_b (current)
   b1: c_a
   $ hg phase --public 'branch("other")'
@@ -70,14 +70,14 @@
   $ hg branch
   foo
   $ hg stack
-  ### branch: foo
+  ### target: foo (branch)
   b4@ c_f (current)
   b3: c_e
   b2: c_d
   b1: c_c
   b0^ c_b (base)
   $ hg stack -v
-  ### branch: foo
+  ### target: foo (branch)
   b4(913c298d8b0a)@ c_f (current)
   b3(4f2a69f6d380): c_e
   b2(f61adbacd17a): c_d
@@ -110,7 +110,7 @@
   $ echo bbb > ddd
   $ hg commit --amend
   $ hg log -G
-  @  7 foo {} draft c_d
+  @  6 foo {} draft c_d
   |
   | o  5 foo {} draft c_f
   | |
@@ -125,7 +125,7 @@
   o  0 other {} public c_a
   
   $ hg stack
-  ### branch: foo
+  ### target: foo (branch)
   b4$ c_f (unstable)
   b3$ c_e (unstable)
   b2@ c_d (current)
@@ -134,7 +134,7 @@
   $ hg up b3
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg stack
-  ### branch: foo
+  ### target: foo (branch)
   b4$ c_f (unstable)
   b3$ c_e (current unstable)
   b2: c_d
@@ -147,7 +147,7 @@
 
   $ hg log -r 'stack()'
   2 foo {} draft c_c
-  7 foo {} draft c_d
+  6 foo {} draft c_d
   4 foo {} draft c_e
   5 foo {} draft c_f
 
@@ -160,11 +160,11 @@
   rebasing 4:4f2a69f6d380 "c_e"
   rebasing 5:913c298d8b0a "c_f"
   $ hg log -G
-  o  9 foo {} draft c_f
+  o  8 foo {} draft c_f
   |
-  o  8 foo {} draft c_e
+  o  7 foo {} draft c_e
   |
-  @  7 foo {} draft c_d
+  @  6 foo {} draft c_d
   |
   o  2 foo {} draft c_c
   |
@@ -185,15 +185,15 @@
   $ hg add hhh
   $ hg commit -m c_h
   $ hg log -G
-  @  11 foo {} draft c_h
+  @  10 foo {} draft c_h
   |
-  o  10 foo {} draft c_g
+  o  9 foo {} draft c_g
   |
-  | o  9 foo {} draft c_f
+  | o  8 foo {} draft c_f
   | |
-  | o  8 foo {} draft c_e
+  | o  7 foo {} draft c_e
   |/
-  o  7 foo {} draft c_d
+  o  6 foo {} draft c_d
   |
   o  2 foo {} draft c_c
   |
@@ -205,12 +205,12 @@
 Test output
 
   $ hg stack
-  ### branch: foo (2 heads)
-  b6: c_f
-  b5: c_e
+  ### target: foo (branch) (2 heads)
+  b6@ c_h (current)
+  b5: c_g
   b2^ c_d (base)
-  b4@ c_h (current)
-  b3: c_g
+  b4: c_f
+  b3: c_e
   b2: c_d
   b1: c_c
   b0^ c_b (base)
@@ -225,20 +225,20 @@
   $ echo ccc > ddd
   $ hg commit --amend -m 'c_D' 
   $ hg rebase -d . -s 'desc(c_g)'
-  rebasing 10:2ebb6e48ab8a "c_g"
-  rebasing 11:634f38e27a1d "c_h"
+  rebasing 9:2ebb6e48ab8a "c_g"
+  rebasing 10:634f38e27a1d "c_h"
   $ hg log -G
-  o  15 foo {} draft c_h
+  o  13 foo {} draft c_h
   |
-  o  14 foo {} draft c_g
+  o  12 foo {} draft c_g
   |
-  @  13 foo {} draft c_D
+  @  11 foo {} draft c_D
   |
-  | o  9 foo {} draft c_f
+  | o  8 foo {} draft c_f
   | |
-  | o  8 foo {} draft c_e
+  | o  7 foo {} draft c_e
   | |
-  | x  7 foo {} draft c_d
+  | x  6 foo {} draft c_d
   |/
   o  2 foo {} draft c_c
   |
@@ -248,12 +248,12 @@
   
 
   $ hg stack
-  ### branch: foo (2 heads)
-  b6$ c_f (unstable)
-  b5$ c_e (unstable)
-  b2^ c_D (base)
-  b4: c_h
-  b3: c_g
+  ### target: foo (branch) (2 heads)
+  b6: c_h
+  b5: c_g
+  b2^ c_D (base current)
+  b4$ c_f (unstable)
+  b3$ c_e (unstable)
   b2@ c_D (current)
   b1: c_c
   b0^ c_b (base)
@@ -261,24 +261,44 @@
 Check that stack doesn't show draft changesets on a branch
 ----------------------------------------------------------
 
+  $ hg log --graph
+  o  13 foo {} draft c_h
+  |
+  o  12 foo {} draft c_g
+  |
+  @  11 foo {} draft c_D
+  |
+  | o  8 foo {} draft c_f
+  | |
+  | o  7 foo {} draft c_e
+  | |
+  | x  6 foo {} draft c_d
+  |/
+  o  2 foo {} draft c_c
+  |
+  o  1 other {} public c_b
+  |
+  o  0 other {} public c_a
+  
+
   $ hg stack
-  ### branch: foo (2 heads)
-  b6$ c_f (unstable)
-  b5$ c_e (unstable)
-  b2^ c_D (base)
-  b4: c_h
-  b3: c_g
+  ### target: foo (branch) (2 heads)
+  b6: c_h
+  b5: c_g
+  b2^ c_D (base current)
+  b4$ c_f (unstable)
+  b3$ c_e (unstable)
   b2@ c_D (current)
   b1: c_c
   b0^ c_b (base)
   $ hg phase --public b1
   $ hg stack
-  ### branch: foo (2 heads)
-  b5$ c_f (unstable)
-  b4$ c_e (unstable)
-  b1^ c_D (base)
-  b3: c_h
-  b2: c_g
+  ### target: foo (branch) (2 heads)
+  b5: c_h
+  b4: c_g
+  b1^ c_D (base current)
+  b3$ c_f (unstable)
+  b2$ c_e (unstable)
   b1@ c_D (current)
   b0^ c_c (base)
 
@@ -288,8 +308,8 @@
   $ hg topic --rev b4::b5 sometopic
   changed topic on 2 changes
   $ hg stack
-  ### branch: foo
-  b3: c_h
-  b2: c_g
+  ### target: foo (branch)
+  b3$ c_f (unstable)
+  b2$ c_e (unstable)
   b1@ c_D (current)
   b0^ c_c (base)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-topic-change.t	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,405 @@
+Tests for changing and clearing topics
+======================================
+
+  $ . "$TESTDIR/testlib/topic_setup.sh"
+  $ cat <<EOF >> $HGRCPATH
+  > [experimental]
+  > # disable the new graph style until we drop 3.7 support
+  > graphstyle.missing = |
+  > evolution=createmarkers, allowunstable
+  > [phases]
+  > publish=false
+  > [alias]
+  > glog = log -G -T "{rev}:{node|short} \{{topics}}\n{desc}  ({bookmarks})\n\n"
+  > EOF
+
+About the glog output: {} contains the topic name and () will contain the bookmark
+
+Setting up a repo
+----------------
+
+  $ hg init topics
+  $ cd topics
+  $ for ch in a b c d e f g h; do touch $ch; echo "foo" >> $ch; hg ci -Aqm "Added "$ch; done
+
+  $ hg glog
+  @  7:ec2426147f0e {}
+  |  Added h  ()
+  |
+  o  6:87d6d6676308 {}
+  |  Added g  ()
+  |
+  o  5:825660c69f0c {}
+  |  Added f  ()
+  |
+  o  4:aa98ab95a928 {}
+  |  Added e  ()
+  |
+  o  3:62615734edd5 {}
+  |  Added d  ()
+  |
+  o  2:28ad74487de9 {}
+  |  Added c  ()
+  |
+  o  1:29becc82797a {}
+  |  Added b  ()
+  |
+  o  0:18d04c59bb5d {}
+     Added a  ()
+  
+
+Clearing topic from revision without topic
+
+  $ hg topic -r . --clear
+  changed topic on 0 changes
+
+Clearing current topic when no active topic is not error
+
+  $ hg topic
+  $ hg topic --clear
+
+Setting topics to all the revisions
+
+  $ hg topic -r 0:: foo
+  switching to topic foo
+  changed topic on 8 changes
+  $ hg glog
+  @  15:05095f607171 {foo}
+  |  Added h  ()
+  |
+  o  14:97505b53ab0d {foo}
+  |  Added g  ()
+  |
+  o  13:75a8360fe626 {foo}
+  |  Added f  ()
+  |
+  o  12:abcedffeae90 {foo}
+  |  Added e  ()
+  |
+  o  11:1315a3808ed0 {foo}
+  |  Added d  ()
+  |
+  o  10:1fa891977a22 {foo}
+  |  Added c  ()
+  |
+  o  9:a53ba98dd6b8 {foo}
+  |  Added b  ()
+  |
+  o  8:86a186070af2 {foo}
+     Added a  ()
+  
+
+Clearing the active topic using --clear
+
+  $ hg topic
+   * foo (8 changesets)
+  $ hg topic --clear
+  $ hg topic
+     foo (8 changesets)
+Changing topics on some revisions (also testing issue 5441)
+
+  $ hg topic -r 12:: bar
+  switching to topic bar
+  changed topic on 4 changes
+  $ hg glog
+  @  19:d7d36e193ea7 {bar}
+  |  Added h  ()
+  |
+  o  18:e7b418d79a05 {bar}
+  |  Added g  ()
+  |
+  o  17:82e0b14f4d9e {bar}
+  |  Added f  ()
+  |
+  o  16:edc4a6b9ea60 {bar}
+  |  Added e  ()
+  |
+  o  11:1315a3808ed0 {foo}
+  |  Added d  ()
+  |
+  o  10:1fa891977a22 {foo}
+  |  Added c  ()
+  |
+  o  9:a53ba98dd6b8 {foo}
+  |  Added b  ()
+  |
+  o  8:86a186070af2 {foo}
+     Added a  ()
+  
+
+Changing topics without passing topic name and clear
+
+  $ hg topic -r .
+  abort: changing topic requires a topic name or --clear
+  [255]
+
+Changing topic using --current flag
+
+  $ hg topic foobar
+  $ hg topic -r . --current
+  active topic 'foobar' grew its first changeset
+  changed topic on 1 changes
+  $ hg glog -r .
+  @  20:c2d6b7df5dcf {foobar}
+  |  Added h  ()
+  |
+
+Changing topic in between the stack
+
+  $ hg topic -r 9::10 --current
+  changed topic on 2 changes
+  $ hg glog
+  o  22:1b88140feefe {foobar}
+  |  Added c  ()
+  |
+  o  21:c39cabfcbbf7 {foobar}
+  |  Added b  ()
+  |
+  | @  20:c2d6b7df5dcf {foobar}
+  | |  Added h  ()
+  | |
+  | o  18:e7b418d79a05 {bar}
+  | |  Added g  ()
+  | |
+  | o  17:82e0b14f4d9e {bar}
+  | |  Added f  ()
+  | |
+  | o  16:edc4a6b9ea60 {bar}
+  | |  Added e  ()
+  | |
+  | o  11:1315a3808ed0 {foo}
+  | |  Added d  ()
+  | |
+  | x  10:1fa891977a22 {foo}
+  | |  Added c  ()
+  | |
+  | x  9:a53ba98dd6b8 {foo}
+  |/   Added b  ()
+  |
+  o  8:86a186070af2 {foo}
+     Added a  ()
+  
+  $ hg rebase -s 11 -d 22
+  rebasing 11:1315a3808ed0 "Added d" (foo)
+  switching to topic foo
+  rebasing 16:edc4a6b9ea60 "Added e" (bar)
+  switching to topic bar
+  rebasing 17:82e0b14f4d9e "Added f" (bar)
+  rebasing 18:e7b418d79a05 "Added g" (bar)
+  rebasing 20:c2d6b7df5dcf "Added h" (foobar)
+  switching to topic foobar
+
+  $ hg glog
+  @  27:a1a9465da59b {foobar}
+  |  Added h  ()
+  |
+  o  26:7c76c271395f {bar}
+  |  Added g  ()
+  |
+  o  25:7f26084dfaf1 {bar}
+  |  Added f  ()
+  |
+  o  24:b1f05e9ba0b5 {bar}
+  |  Added e  ()
+  |
+  o  23:f9869da2286e {foo}
+  |  Added d  ()
+  |
+  o  22:1b88140feefe {foobar}
+  |  Added c  ()
+  |
+  o  21:c39cabfcbbf7 {foobar}
+  |  Added b  ()
+  |
+  o  8:86a186070af2 {foo}
+     Added a  ()
+  
+Amending a topic
+----------------
+
+When the changeset has a topic and we have different active topic
+
+  $ hg topic wat
+  $ hg ci --amend
+  active topic 'wat' grew its first changeset
+  $ hg glog -r .
+  @  28:61470c956807 {wat}
+  |  Added h  ()
+  |
+
+Clear the current topic and amending
+
+  $ hg topic --clear
+  $ hg ci --amend
+  $ hg glog -r .
+  @  29:b584fa49f42e {}
+  |  Added h  ()
+  |
+
+When the changeset does not has a topic but we have an active topic
+
+  $ hg topic watwat
+  marked working directory as topic: watwat
+  $ hg ci --amend
+  active topic 'watwat' grew its first changeset
+  $ hg glog -r .
+  @  30:a24c31c35013 {watwat}
+  |  Added h  ()
+  |
+
+Testing changing topics on public changeset
+-------------------------------------------
+
+  $ hg phase -r 8 -p
+
+Clearing the topic
+
+  $ hg topic -r 8 --clear
+  abort: can't change topic of a public change
+  [255]
+
+Changing the topic
+
+  $ hg topic -r 8 foobarboo
+  abort: can't change topic of a public change
+  [255]
+
+Testing the bookmark movement
+-----------------------------
+
+  $ hg bookmark book
+  $ hg glog
+  @  30:a24c31c35013 {watwat}
+  |  Added h  (book)
+  |
+  o  26:7c76c271395f {bar}
+  |  Added g  ()
+  |
+  o  25:7f26084dfaf1 {bar}
+  |  Added f  ()
+  |
+  o  24:b1f05e9ba0b5 {bar}
+  |  Added e  ()
+  |
+  o  23:f9869da2286e {foo}
+  |  Added d  ()
+  |
+  o  22:1b88140feefe {foobar}
+  |  Added c  ()
+  |
+  o  21:c39cabfcbbf7 {foobar}
+  |  Added b  ()
+  |
+  o  8:86a186070af2 {}
+     Added a  ()
+  
+On clearing the topic
+
+  $ hg topic -r . --clear
+  clearing empty topic "watwat"
+  active topic 'watwat' is now empty
+  changed topic on 1 changes
+
+  $ hg glog
+  @  31:c48d6d71b2d9 {}
+  |  Added h  (book)
+  |
+  o  26:7c76c271395f {bar}
+  |  Added g  ()
+  |
+  o  25:7f26084dfaf1 {bar}
+  |  Added f  ()
+  |
+  o  24:b1f05e9ba0b5 {bar}
+  |  Added e  ()
+  |
+  o  23:f9869da2286e {foo}
+  |  Added d  ()
+  |
+  o  22:1b88140feefe {foobar}
+  |  Added c  ()
+  |
+  o  21:c39cabfcbbf7 {foobar}
+  |  Added b  ()
+  |
+  o  8:86a186070af2 {}
+     Added a  ()
+  
+
+On changing the topic
+
+  $ hg bookmark bookboo
+  $ hg topic -r . movebook
+  switching to topic movebook
+  changed topic on 1 changes
+  $ hg glog
+  @  32:1b83d11095b9 {movebook}
+  |  Added h  (book bookboo)
+  |
+  o  26:7c76c271395f {bar}
+  |  Added g  ()
+  |
+  o  25:7f26084dfaf1 {bar}
+  |  Added f  ()
+  |
+  o  24:b1f05e9ba0b5 {bar}
+  |  Added e  ()
+  |
+  o  23:f9869da2286e {foo}
+  |  Added d  ()
+  |
+  o  22:1b88140feefe {foobar}
+  |  Added c  ()
+  |
+  o  21:c39cabfcbbf7 {foobar}
+  |  Added b  ()
+  |
+  o  8:86a186070af2 {}
+     Added a  ()
+  
+Changing topic on secret changesets
+-----------------------------------
+
+  $ hg up 26
+  switching to topic bar
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  (leaving bookmark bookboo)
+
+  $ hg phase -r . -s -f
+  $ hg phase -r .
+  26: secret
+
+  $ hg topic -r . watwat
+  switching to topic watwat
+  changed topic on 1 changes
+
+  $ hg glog
+  @  33:894983f69e69 {watwat}
+  |  Added g  ()
+  |
+  | o  32:1b83d11095b9 {movebook}
+  | |  Added h  (book bookboo)
+  | |
+  | x  26:7c76c271395f {bar}
+  |/   Added g  ()
+  |
+  o  25:7f26084dfaf1 {bar}
+  |  Added f  ()
+  |
+  o  24:b1f05e9ba0b5 {bar}
+  |  Added e  ()
+  |
+  o  23:f9869da2286e {foo}
+  |  Added d  ()
+  |
+  o  22:1b88140feefe {foobar}
+  |  Added c  ()
+  |
+  o  21:c39cabfcbbf7 {foobar}
+  |  Added b  ()
+  |
+  o  8:86a186070af2 {}
+     Added a  ()
+  
+  $ hg phase -r .
+  33: secret
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-topic-debugcb.t	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,316 @@
+==================================================
+Test for `hg debugconvertbookmark` added by topics
+==================================================
+
+  $ . "$TESTDIR/testlib/topic_setup.sh"
+
+  $ cat << EOF >> $HGRCPATH
+  > drawdag=$RUNTESTDIR/drawdag.py
+  > [ui]
+  > logtemplate = [{rev}:{node|short}] {desc|firstline}\n\
+  > {if(bookmarks, "  bookmark: {join(bookmarks,"\n  bookmark:")}\n")}\
+  > {if(topics, "  topic: {topics}\n")}
+  > EOF
+
+Setting up the things
+---------------------
+
+  $ hg init repo
+  $ cd repo
+  $ echo "Hello" > root
+  $ hg commit -Aqm "root"
+  $ hg phase --public .
+  $ echo "Hello" > a
+  $ hg commit -Aqm "First commit"
+  $ echo "Hello" > b
+  $ hg commit -Aqm "Second commit"
+  $ hg bookmark "hellos"
+  $ hg up 0 -q
+  $ echo "Fix 1" > l
+  $ hg commit -Aqm "Fixing first"
+  $ echo "Fix 2" > m
+  $ hg commit -Aqm "Fixing second"
+  $ hg bookmark "secondfix"
+
+  $ hg log -G
+  @  [4:ec0e17135a94] Fixing second
+  |    bookmark: secondfix
+  o  [3:e05947b88d69] Fixing first
+  |
+  | o  [2:f53d1144f925] Second commit
+  | |    bookmark: hellos
+  | o  [1:df1fd5e18154] First commit
+  |/
+  o  [0:249055fcca50] root
+  
+
+Generic tests
+=============
+
+Help for the command
+--------------------
+
+  $ hg help debugconvertbookmark
+  hg debugcb [-b BOOKMARK] [--all]
+  
+  aliases: debugconvertbookmark
+  
+  Converts a bookmark to a topic with the same name.
+  
+  options:
+  
+   -b --bookmark VALUE bookmark to convert to topic
+      --all            convert all bookmarks to topics
+  
+  (some details hidden, use --verbose to show complete help)
+
+Running without any argument
+----------------------------
+
+  $ hg debugconvertbookmark
+  abort: you must specify either '--all' or '-b'
+  [255]
+
+Changing a particular bookmark to topic
+=======================================
+
+  $ hg debugconvertbookmark -b hellos
+  changed topic to "hellos" on 2 revisions
+  $ hg log -G
+  o  [6:98ae7930f6ed] Second commit
+  |    topic: hellos
+  o  [5:ff69f6ee4618] First commit
+  |    topic: hellos
+  | @  [4:ec0e17135a94] Fixing second
+  | |    bookmark: secondfix
+  | o  [3:e05947b88d69] Fixing first
+  |/
+  o  [0:249055fcca50] root
+  
+
+Changing all bookmarks to topic
+===============================
+
+Simple test
+-----------
+
+  $ hg debugconvertbookmark --all
+  switching to topic secondfix
+  changed topic to "secondfix" on 2 revisions
+  $ hg log -G
+  @  [8:5f0f9cc1979a] Fixing second
+  |    topic: secondfix
+  o  [7:f8ecbf3b10be] Fixing first
+  |    topic: secondfix
+  | o  [6:98ae7930f6ed] Second commit
+  | |    topic: hellos
+  | o  [5:ff69f6ee4618] First commit
+  |/     topic: hellos
+  o  [0:249055fcca50] root
+  
+
+Trying with multiple bookmarks on a single changeset
+----------------------------------------------------
+
+  $ echo "multiple bookmarks" >> m
+  $ hg commit -Aqm "Trying multiple bookmarks"
+  $ hg bookmark book1
+  $ hg bookmark book2
+  $ hg log -G
+  @  [9:4ad3e7d421d4] Trying multiple bookmarks
+  |    bookmark: book1
+  |    bookmark:book2
+  |    topic: secondfix
+  o  [8:5f0f9cc1979a] Fixing second
+  |    topic: secondfix
+  o  [7:f8ecbf3b10be] Fixing first
+  |    topic: secondfix
+  | o  [6:98ae7930f6ed] Second commit
+  | |    topic: hellos
+  | o  [5:ff69f6ee4618] First commit
+  |/     topic: hellos
+  o  [0:249055fcca50] root
+  
+  $ hg debugconvertbookmark --all
+  skipping '9' as it has multiple bookmarks on it
+  $ hg log -G
+  @  [9:4ad3e7d421d4] Trying multiple bookmarks
+  |    bookmark: book1
+  |    bookmark:book2
+  |    topic: secondfix
+  o  [8:5f0f9cc1979a] Fixing second
+  |    topic: secondfix
+  o  [7:f8ecbf3b10be] Fixing first
+  |    topic: secondfix
+  | o  [6:98ae7930f6ed] Second commit
+  | |    topic: hellos
+  | o  [5:ff69f6ee4618] First commit
+  |/     topic: hellos
+  o  [0:249055fcca50] root
+  
+
+Two bookmarks on two different topological branches
+---------------------------------------------------
+
+  $ cd ..
+  $ rm -rf repo
+  $ hg init setup1
+  $ cd setup1
+  $ echo "Hello" > root
+  $ hg commit -Aqm "root"
+  $ hg phase --public .
+  $ echo "Hello" > A
+  $ hg commit -Aqm "A"
+  $ echo "Hello" > B
+  $ hg commit -Aqm "B"
+  $ echo "Hello" > C
+  $ hg commit -Aqm "C"
+  $ echo "Hello" > D
+  $ hg commit -Aqm "D"
+  $ hg up 'desc(B)'
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ echo "Hello" > E
+  $ hg commit -Aqm "E"
+  $ echo "Hello" > F
+  $ hg commit -Aqm "F"
+  $ hg bookmark -r 'desc(D)' bar
+  $ hg bookmark -r 'desc(F)' foo
+
+  $ hg log -G
+  @  [6:32f4660df717] F
+  |    bookmark: foo
+  o  [5:d4608d9df75e] E
+  |
+  | o  [4:4963af405f62] D
+  | |    bookmark: bar
+  | o  [3:ac05e0d05d00] C
+  |/
+  o  [2:10f317d09e78] B
+  |
+  o  [1:e34122c9a2bf] A
+  |
+  o  [0:249055fcca50] root
+  
+  $ hg debugconvertbookmark --all
+  changed topic to "bar" on 2 revisions
+  switching to topic foo
+  changed topic to "foo" on 2 revisions
+  $ hg log -G
+  @  [10:f0b5f2a5f31a] F
+  |    topic: foo
+  o  [9:7affa1350ff0] E
+  |    topic: foo
+  | o  [8:a1bb64d88f0e] D
+  | |    topic: bar
+  | o  [7:71827f564e9e] C
+  |/     topic: bar
+  o  [2:10f317d09e78] B
+  |
+  o  [1:e34122c9a2bf] A
+  |
+  o  [0:249055fcca50] root
+  
+
+Two bookmarks on top of each other
+----------------------------------
+
+  $ cd ..
+  $ rm -rf setup1
+  $ hg init setup2
+  $ cd setup2
+  $ echo "Hello" > root
+  $ hg commit -Aqm "root"
+  $ hg phase --public .
+  $ echo "Hello" > A
+  $ hg commit -Aqm "A"
+  $ hg phase --public .
+  $ echo "Hello" > B
+  $ hg commit -Aqm "B"
+  $ echo "Hello" > C
+  $ hg commit -Aqm "C"
+  $ hg bookmark -r . bar
+  $ echo "Hello" > D
+  $ hg commit -Aqm "D"
+  $ echo "Hello" > E
+  $ hg commit -Aqm "E"
+  $ hg bookmark -r . foo
+
+  $ hg log -G
+  @  [5:c633aa1ad270] E
+  |    bookmark: foo
+  o  [4:4963af405f62] D
+  |
+  o  [3:ac05e0d05d00] C
+  |    bookmark: bar
+  o  [2:10f317d09e78] B
+  |
+  o  [1:e34122c9a2bf] A
+  |
+  o  [0:249055fcca50] root
+  
+
+XXX: this should  avoid create orphan changesets.
+
+  $ hg debugconvertbookmark --all
+  changed topic to "bar" on 2 revisions
+  switching to topic foo
+  changed topic to "foo" on 2 revisions
+
+  $ hg log -G
+  @  [9:b14d13efcfa7] E
+  |    topic: foo
+  o  [8:c89ca6e70978] D
+  |    topic: foo
+  | o  [7:a3ea0dfe6a10] C
+  | |    topic: bar
+  | o  [6:db1bc6aab480] B
+  | |    topic: bar
+  x |  [3:ac05e0d05d00] C
+  | |
+  x |  [2:10f317d09e78] B
+  |/
+  o  [1:e34122c9a2bf] A
+  |
+  o  [0:249055fcca50] root
+  
+
+Check that phase are properly take in account
+---------------------------------------------
+
+(we reuse above test, taking advantage of a small bug regarding stacked bookmarks. we can fuse the two tests once that bug is fixed)
+
+  $ cd ..
+  $ hg init setup-phases
+  $ cd setup-phases
+  $ echo "Hello" > root
+  $ hg commit -Aqm "root"
+  $ hg phase --public .
+  $ echo "Hello" > A
+  $ hg commit -Aqm "A"
+  $ echo "Hello" > B
+  $ hg commit -Aqm "B"
+  $ echo "Hello" > C
+  $ hg commit -Aqm "C"
+  $ hg bookmark -r . bar
+  $ hg log -G
+  @  [3:ac05e0d05d00] C
+  |    bookmark: bar
+  o  [2:10f317d09e78] B
+  |
+  o  [1:e34122c9a2bf] A
+  |
+  o  [0:249055fcca50] root
+  
+
+  $ hg debugconvertbookmark --all
+  switching to topic bar
+  changed topic to "bar" on 3 revisions
+  $ hg log -G
+  @  [6:863c43a7951c] C
+  |    topic: bar
+  o  [5:ac7f12ac947f] B
+  |    topic: bar
+  o  [4:fc82c8c14b4c] A
+  |    topic: bar
+  o  [0:249055fcca50] root
+  
--- a/tests/test-topic-dest.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-topic-dest.t	Tue Nov 14 23:04:04 2017 +0100
@@ -28,6 +28,7 @@
   $ echo babar >> jungle
   $ hg add jungle
   $ hg ci -t elephant -m babar
+  active topic 'elephant' grew its first changeset
 
   $ hg log -G
   @  4 (elephant) babar
@@ -53,6 +54,7 @@
   $ echo zephir >> jungle
   $ hg add jungle
   $ hg ci -t monkey -m zephir
+  active topic 'monkey' grew its first changeset
   $ hg log -G
   @  5 (monkey) zephir
   |
@@ -107,7 +109,7 @@
   switching to topic elephant
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg rebase
-  rebasing 4:cb7ae72f4a80 "babar"
+  rebasing 4:cb7ae72f4a80 "babar" (elephant)
   switching to topic elephant
   $ hg log -G
   @  7 (elephant) babar
@@ -128,7 +130,7 @@
   switching to topic monkey
   1 files updated, 0 files merged, 3 files removed, 0 files unresolved
   $ hg rebase
-  rebasing 5:d832ddc604ec "zephir"
+  rebasing 5:d832ddc604ec "zephir" (monkey)
   switching to topic monkey
   $ hg log -G
   @  8 (monkey) zephir
@@ -171,7 +173,7 @@
   o  0 () c_alpha
   
   $ hg rebase
-  rebasing 9:d79a104e2902 "Huc" (tip)
+  rebasing 9:d79a104e2902 "Huc" (tip monkey)
   $ hg log -G
   @  10 (monkey) Huc
   |
@@ -223,7 +225,7 @@
   switching to topic elephant
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg rebase -d 'desc(c_zeta)' # make sure tip is elsewhere
-  rebasing 7:8d0b77140b05 "babar"
+  rebasing 7:8d0b77140b05 "babar" (elephant)
   switching to topic elephant
   $ hg up monkey
   switching to topic monkey
@@ -232,12 +234,12 @@
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   $ hg topic
-     elephant
-   * monkey
+     elephant (1 changesets)
+   * monkey   (2 changesets)
   $ hg ci -m 'merge with default'
   $ hg topic
-     elephant
-   * monkey
+     elephant (1 changesets)
+   * monkey   (3 changesets)
   $ hg log -G
   @    13 (monkey) merge with default
   |\
@@ -272,6 +274,7 @@
   adding manifests
   adding file changes
   added 3 changesets with 3 changes to 3 files
+  new changesets 13ec05df14e1:6482f08916a5
   updating to branch default
   3 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cd other
@@ -285,6 +288,7 @@
   adding manifests
   adding file changes
   added 3 changesets with 3 changes to 3 files (+1 heads)
+  new changesets 6f5edd7450bb:c9c03b99196b
   rebasing 3:dbc48dd9e743 "c_other"
   $ hg log -G
   @  7 () c_other
@@ -450,6 +454,7 @@
   $ hg up 'p1(roots(topic(elephant)))'
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg topic elephant
+  marked working directory as topic: elephant
   $ hg up
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg log -G
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-topic-flow-publish-bare.t	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,292 @@
+=====================
+Test workflow options
+=====================
+
+  $ . "$TESTDIR/testlib/topic_setup.sh"
+  $ . "$TESTDIR/testlib/common.sh"
+
+Publishing of bare branch
+=========================
+
+  $ hg init bare-branch-server
+  $ cd bare-branch-server
+  $ cat <<EOF >> .hg/hgrc
+  > [phases]
+  > publish = no
+  > [experimental]
+  > topic.publish-bare-branch = yes
+  > EOF
+  $ mkcommit ROOT
+  $ mkcommit c_dA0
+  $ hg phase --public -r 'all()'
+  $ cd ..
+
+  $ hg clone bare-branch-server bare-client
+  updating to branch default
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+pushing a simple branch publish it
+----------------------------------
+
+  $ cd bare-client
+  $ mkcommit c_dB0
+  $ hg push
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  2:286d02a6e2a2 c_dB0 public default
+  |
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
+
+pushing two heads at the same time
+----------------------------------
+
+  $ hg update 'desc("c_dA0")'
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ mkcommit c_dC0
+  created new head
+  $ hg update 'desc("c_dA0")'
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ mkcommit c_dD0
+  created new head
+  $ hg push -f
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files (+2 heads)
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  4:9bf953aa81f6 c_dD0 public default
+  |
+  | o  3:9d5b8e1f08a4 c_dC0 public default
+  |/
+  | o  2:286d02a6e2a2 c_dB0 public default
+  |/
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
+
+pushing something not on default
+--------------------------------
+
+  $ hg update 'desc("ROOT")'
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ hg branch branchA
+  marked working directory as branch branchA
+  (branches are permanent and global, did you want a bookmark?)
+  $ mkcommit c_aE0
+  $ hg push --new-branch
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files (+1 heads)
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  5:0db08e758601 c_aE0 public branchA
+  |
+  | o  4:9bf953aa81f6 c_dD0 public default
+  | |
+  | | o  3:9d5b8e1f08a4 c_dC0 public default
+  | |/
+  | | o  2:286d02a6e2a2 c_dB0 public default
+  | |/
+  | o  1:134bc3852ad2 c_dA0 public default
+  |/
+  o  0:ea207398892e ROOT public default
+  
+
+pushing topic
+-------------
+
+  $ hg update 'desc("c_dD0")'
+  2 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg topic foo
+  marked working directory as topic: foo
+  $ mkcommit c_dF0
+  active topic 'foo' grew its first changeset
+  $ hg push
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  6:0867c4471796 c_dF0 draft default foo
+  |
+  o  4:9bf953aa81f6 c_dD0 public default
+  |
+  | o  3:9d5b8e1f08a4 c_dC0 public default
+  |/
+  | o  2:286d02a6e2a2 c_dB0 public default
+  |/
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  | o  5:0db08e758601 c_aE0 public branchA
+  |/
+  o  0:ea207398892e ROOT public default
+  
+
+pushing topic over a bare branch
+--------------------------------
+
+  $ hg update 'desc("c_dC0")'
+  1 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ mkcommit c_dG0
+  $ hg topic bar
+  marked working directory as topic: bar
+  $ mkcommit c_dH0
+  active topic 'bar' grew its first changeset
+  $ hg push
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  8:858be9a8daaf c_dH0 draft default bar
+  |
+  o  7:0e4041d324d0 c_dG0 public default
+  |
+  o  3:9d5b8e1f08a4 c_dC0 public default
+  |
+  | o  2:286d02a6e2a2 c_dB0 public default
+  |/
+  | o  6:0867c4471796 c_dF0 draft default foo
+  | |
+  | o  4:9bf953aa81f6 c_dD0 public default
+  |/
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  | o  5:0db08e758601 c_aE0 public branchA
+  |/
+  o  0:ea207398892e ROOT public default
+  
+
+Pushing topic in between bare branch
+------------------------------------
+
+  $ hg update 'desc("c_dB0")'
+  1 files updated, 0 files merged, 3 files removed, 0 files unresolved
+  $ mkcommit c_dI0
+  $ hg update 'desc("c_dH0")'
+  switching to topic bar
+  3 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ mkcommit c_dJ0
+  $ hg update 'desc("c_aE0")'
+  1 files updated, 0 files merged, 5 files removed, 0 files unresolved
+  $ mkcommit c_aK0
+  $ hg push
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 3 changesets with 3 changes to 3 files
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  11:b0a00ebdfd24 c_aK0 public branchA
+  |
+  o  5:0db08e758601 c_aE0 public branchA
+  |
+  | o  10:abb5c84eb9e9 c_dJ0 draft default bar
+  | |
+  | o  8:858be9a8daaf c_dH0 draft default bar
+  | |
+  | o  7:0e4041d324d0 c_dG0 public default
+  | |
+  | o  3:9d5b8e1f08a4 c_dC0 public default
+  | |
+  | | o  9:4b5570d89f0f c_dI0 public default
+  | | |
+  | | o  2:286d02a6e2a2 c_dB0 public default
+  | |/
+  | | o  6:0867c4471796 c_dF0 draft default foo
+  | | |
+  | | o  4:9bf953aa81f6 c_dD0 public default
+  | |/
+  | o  1:134bc3852ad2 c_dA0 public default
+  |/
+  o  0:ea207398892e ROOT public default
+  
+
+merging a topic in branch
+-------------------------
+
+  $ hg update default
+  3 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ hg merge foo
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ hg ci -m 'c_dL0'
+  $ hg push
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 0 changes to 0 files (-1 heads)
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @    12:a6f9f8c6c6cc c_dL0 public default
+  |\
+  | o  9:4b5570d89f0f c_dI0 public default
+  | |
+  o |  6:0867c4471796 c_dF0 public default
+  | |
+  o |  4:9bf953aa81f6 c_dD0 public default
+  | |
+  | | o  10:abb5c84eb9e9 c_dJ0 draft default bar
+  | | |
+  | | o  8:858be9a8daaf c_dH0 draft default bar
+  | | |
+  | | o  7:0e4041d324d0 c_dG0 public default
+  | | |
+  +---o  3:9d5b8e1f08a4 c_dC0 public default
+  | |
+  | o  2:286d02a6e2a2 c_dB0 public default
+  |/
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  | o  11:b0a00ebdfd24 c_aK0 public branchA
+  | |
+  | o  5:0db08e758601 c_aE0 public branchA
+  |/
+  o  0:ea207398892e ROOT public default
+  
+  $ hg log -R ../bare-branch-server --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  o    12:a6f9f8c6c6cc c_dL0 public default
+  |\
+  | o  9:4b5570d89f0f c_dI0 public default
+  | |
+  o |  6:0867c4471796 c_dF0 public default
+  | |
+  o |  4:9bf953aa81f6 c_dD0 public default
+  | |
+  | | o  10:abb5c84eb9e9 c_dJ0 draft default bar
+  | | |
+  | | o  8:858be9a8daaf c_dH0 draft default bar
+  | | |
+  | | o  7:0e4041d324d0 c_dG0 public default
+  | | |
+  +---o  3:9d5b8e1f08a4 c_dC0 public default
+  | |
+  | o  2:286d02a6e2a2 c_dB0 public default
+  |/
+  @  1:134bc3852ad2 c_dA0 public default
+  |
+  | o  11:b0a00ebdfd24 c_aK0 public branchA
+  | |
+  | o  5:0db08e758601 c_aE0 public branchA
+  |/
+  o  0:ea207398892e ROOT public default
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-topic-flow-publish-flag.t	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,426 @@
+=====================
+Test workflow options
+=====================
+
+  $ . "$TESTDIR/testlib/topic_setup.sh"
+  $ . "$TESTDIR/testlib/common.sh"
+
+testing hg push --publish flag
+==============================
+
+  $ hg init bare-branch-server
+  $ cd bare-branch-server
+  $ cat <<EOF >> .hg/hgrc
+  > [phases]
+  > publish = no
+  > EOF
+  $ mkcommit ROOT
+  $ mkcommit c_dA0
+  $ hg phase --public -r 'all()'
+  $ cd ..
+
+  $ hg clone bare-branch-server bare-client
+  updating to branch default
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd bare-client
+
+Pushing a 1 new changeset
+-------------------------
+
+  $ mkcommit c_dB0
+  $ hg push --publish
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  2:286d02a6e2a2 c_dB0 public default
+  |
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
+
+Pushing a 2 new changeset (same branch)
+---------------------------------------
+
+  $ mkcommit c_dC0
+  $ mkcommit c_dD0
+  $ hg push --publish
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  4:c63e7dd93a91 c_dD0 public default
+  |
+  o  3:7d56a56d2547 c_dC0 public default
+  |
+  o  2:286d02a6e2a2 c_dB0 public default
+  |
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
+
+Pushing a 2 new changeset two head
+----------------------------------
+
+  $ mkcommit c_dE0
+  $ hg update 'desc("c_dD0")'
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg branch other
+  marked working directory as branch other
+  (branches are permanent and global, did you want a bookmark?)
+  $ mkcommit c_oF0
+  $ hg push -f --publish
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files (+1 heads)
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  6:45b23c834b6a c_oF0 public other
+  |
+  | o  5:5576ae39eaee c_dE0 public default
+  |/
+  o  4:c63e7dd93a91 c_dD0 public default
+  |
+  o  3:7d56a56d2547 c_dC0 public default
+  |
+  o  2:286d02a6e2a2 c_dB0 public default
+  |
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
+
+Publishing 1 common changeset
+-----------------------------
+  $ mkcommit c_oG0
+  $ hg push
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  7:d293f74a1233 c_oG0 draft other
+  |
+  o  6:45b23c834b6a c_oF0 public other
+  |
+  | o  5:5576ae39eaee c_dE0 public default
+  |/
+  o  4:c63e7dd93a91 c_dD0 public default
+  |
+  o  3:7d56a56d2547 c_dC0 public default
+  |
+  o  2:286d02a6e2a2 c_dB0 public default
+  |
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
+  $ hg push --publish
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  no changes found
+  [1]
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  7:d293f74a1233 c_oG0 public other
+  |
+  o  6:45b23c834b6a c_oF0 public other
+  |
+  | o  5:5576ae39eaee c_dE0 public default
+  |/
+  o  4:c63e7dd93a91 c_dD0 public default
+  |
+  o  3:7d56a56d2547 c_dC0 public default
+  |
+  o  2:286d02a6e2a2 c_dB0 public default
+  |
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
+
+Selectively publishing 1 changeset
+----------------------------------
+
+  $ mkcommit c_oH0
+  $ hg update default
+  1 files updated, 0 files merged, 3 files removed, 0 files unresolved
+  $ mkcommit c_dI0
+  $ hg push -r default --publish
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  9:fbf2be276221 c_dI0 public default
+  |
+  o  5:5576ae39eaee c_dE0 public default
+  |
+  | o  8:8e85646c135f c_oH0 draft other
+  | |
+  | o  7:d293f74a1233 c_oG0 public other
+  | |
+  | o  6:45b23c834b6a c_oF0 public other
+  |/
+  o  4:c63e7dd93a91 c_dD0 public default
+  |
+  o  3:7d56a56d2547 c_dC0 public default
+  |
+  o  2:286d02a6e2a2 c_dB0 public default
+  |
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
+
+Selectively publishing 1 common changeset
+-----------------------------------------
+
+  $ mkcommit c_dJ0
+  $ hg push
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  10:ac4cf59f2aac c_dJ0 draft default
+  |
+  o  9:fbf2be276221 c_dI0 public default
+  |
+  o  5:5576ae39eaee c_dE0 public default
+  |
+  | o  8:8e85646c135f c_oH0 draft other
+  | |
+  | o  7:d293f74a1233 c_oG0 public other
+  | |
+  | o  6:45b23c834b6a c_oF0 public other
+  |/
+  o  4:c63e7dd93a91 c_dD0 public default
+  |
+  o  3:7d56a56d2547 c_dC0 public default
+  |
+  o  2:286d02a6e2a2 c_dB0 public default
+  |
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
+  $ hg push --rev default --publish
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  no changes found
+  [1]
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  10:ac4cf59f2aac c_dJ0 public default
+  |
+  o  9:fbf2be276221 c_dI0 public default
+  |
+  o  5:5576ae39eaee c_dE0 public default
+  |
+  | o  8:8e85646c135f c_oH0 draft other
+  | |
+  | o  7:d293f74a1233 c_oG0 public other
+  | |
+  | o  6:45b23c834b6a c_oF0 public other
+  |/
+  o  4:c63e7dd93a91 c_dD0 public default
+  |
+  o  3:7d56a56d2547 c_dC0 public default
+  |
+  o  2:286d02a6e2a2 c_dB0 public default
+  |
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
+
+Selectively publishing no changeset
+-----------------------------------
+
+  $ hg push --rev default --publish
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  no changes found
+  [1]
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  10:ac4cf59f2aac c_dJ0 public default
+  |
+  o  9:fbf2be276221 c_dI0 public default
+  |
+  o  5:5576ae39eaee c_dE0 public default
+  |
+  | o  8:8e85646c135f c_oH0 draft other
+  | |
+  | o  7:d293f74a1233 c_oG0 public other
+  | |
+  | o  6:45b23c834b6a c_oF0 public other
+  |/
+  o  4:c63e7dd93a91 c_dD0 public default
+  |
+  o  3:7d56a56d2547 c_dC0 public default
+  |
+  o  2:286d02a6e2a2 c_dB0 public default
+  |
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
+
+Testing --publish interaction with multiple head detection
+============================================================
+
+pushing a topic changeset, publishing it
+----------------------------------------
+
+  $ hg topic topic_A
+  marked working directory as topic: topic_A
+  $ mkcommit c_dK0
+  active topic 'topic_A' grew its first changeset
+  $ hg push -r 'desc("c_dK0")' --publish
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  active topic 'topic_A' is now empty
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  11:d06fc4f891e8 c_dK0 public default
+  |
+  o  10:ac4cf59f2aac c_dJ0 public default
+  |
+  o  9:fbf2be276221 c_dI0 public default
+  |
+  o  5:5576ae39eaee c_dE0 public default
+  |
+  | o  8:8e85646c135f c_oH0 draft other
+  | |
+  | o  7:d293f74a1233 c_oG0 public other
+  | |
+  | o  6:45b23c834b6a c_oF0 public other
+  |/
+  o  4:c63e7dd93a91 c_dD0 public default
+  |
+  o  3:7d56a56d2547 c_dC0 public default
+  |
+  o  2:286d02a6e2a2 c_dB0 public default
+  |
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
+
+pushing a new branch, alongside an existing topic
+-------------------------------------------------
+
+  $ hg topic topic_A
+  $ mkcommit c_dL0
+  active topic 'topic_A' grew its first changeset
+  $ hg push -r 'desc("c_dL0")'
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  $ hg update 'desc("c_dK")'
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ mkcommit c_dM0
+  $ hg push -r 'desc("c_dM0")' --publish
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files (+1 heads)
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  13:0d144c8b6c8f c_dM0 public default
+  |
+  | o  12:3c73f6cabf07 c_dL0 draft default topic_A
+  |/
+  o  11:d06fc4f891e8 c_dK0 public default
+  |
+  o  10:ac4cf59f2aac c_dJ0 public default
+  |
+  o  9:fbf2be276221 c_dI0 public default
+  |
+  o  5:5576ae39eaee c_dE0 public default
+  |
+  | o  8:8e85646c135f c_oH0 draft other
+  | |
+  | o  7:d293f74a1233 c_oG0 public other
+  | |
+  | o  6:45b23c834b6a c_oF0 public other
+  |/
+  o  4:c63e7dd93a91 c_dD0 public default
+  |
+  o  3:7d56a56d2547 c_dC0 public default
+  |
+  o  2:286d02a6e2a2 c_dB0 public default
+  |
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
+
+pushing a topic (publishing) alongside and existing branch head
+---------------------------------------------------------------
+
+  $ hg update 'desc("c_dK")'
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg topic topic_B
+  marked working directory as topic: topic_B
+  $ mkcommit c_dN0
+  active topic 'topic_B' grew its first changeset
+  $ hg push -r 'desc("c_dN0")' --publish
+  pushing to $TESTTMP/bare-branch-server
+  searching for changes
+  abort: push creates new remote head 4dcd0be9db96!
+  (merge or see 'hg help push' for details about pushing new heads)
+  [255]
+  $ hg log --rev 'sort(all(), "topo")' -GT '{rev}:{node|short} {desc} {phase} {branch} {topics}'
+  @  14:4dcd0be9db96 c_dN0 draft default topic_B
+  |
+  | o  13:0d144c8b6c8f c_dM0 public default
+  |/
+  | o  12:3c73f6cabf07 c_dL0 draft default topic_A
+  |/
+  o  11:d06fc4f891e8 c_dK0 public default
+  |
+  o  10:ac4cf59f2aac c_dJ0 public default
+  |
+  o  9:fbf2be276221 c_dI0 public default
+  |
+  o  5:5576ae39eaee c_dE0 public default
+  |
+  | o  8:8e85646c135f c_oH0 draft other
+  | |
+  | o  7:d293f74a1233 c_oG0 public other
+  | |
+  | o  6:45b23c834b6a c_oF0 public other
+  |/
+  o  4:c63e7dd93a91 c_dD0 public default
+  |
+  o  3:7d56a56d2547 c_dC0 public default
+  |
+  o  2:286d02a6e2a2 c_dB0 public default
+  |
+  o  1:134bc3852ad2 c_dA0 public default
+  |
+  o  0:ea207398892e ROOT public default
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-topic-flow-single-head.t	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,189 @@
+=====================
+Test workflow options
+=====================
+
+  $ . "$TESTDIR/testlib/topic_setup.sh"
+  $ . "$TESTDIR/testlib/common.sh"
+
+Test single head enforcing - Setup
+=============================================
+
+  $ hg init single-head-server
+  $ cd single-head-server
+  $ cat <<EOF >> .hg/hgrc
+  > [phases]
+  > publish = no
+  > [experimental]
+  > enforce-single-head = yes
+  > evolution = all
+  > EOF
+  $ mkcommit ROOT
+  $ mkcommit c_dA0
+  $ cd ..
+
+  $ hg clone single-head-server client
+  updating to branch default
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+Test single head enforcing - with branch only
+---------------------------------------------
+
+  $ cd client
+
+continuing the current defaultbranch
+
+  $ mkcommit c_dB0
+  $ hg push
+  pushing to $TESTTMP/single-head-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+
+creating a new branch
+
+  $ hg up 'desc("ROOT")'
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ hg branch branch_A
+  marked working directory as branch branch_A
+  (branches are permanent and global, did you want a bookmark?)
+  $ mkcommit c_aC0
+  $ hg push --new-branch
+  pushing to $TESTTMP/single-head-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files (+1 heads)
+
+Create a new head on the default branch
+
+  $ hg up 'desc("c_dA0")'
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ mkcommit c_dD0
+  created new head
+  $ hg push -f
+  pushing to $TESTTMP/single-head-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files (+1 heads)
+  transaction abort!
+  rollback completed
+  abort: 2 heads on "default"
+  (286d02a6e2a2, 9bf953aa81f6)
+  [255]
+
+remerge them
+
+  $ hg merge
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ mkcommit c_dE0
+  $ hg push
+  pushing to $TESTTMP/single-head-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files
+
+Test single head enforcing - with topic
+---------------------------------------
+
+pushing a new topic
+
+  $ hg topic foo
+  marked working directory as topic: foo
+  $ mkcommit c_dF0
+  active topic 'foo' grew its first changeset
+  $ hg push
+  pushing to $TESTTMP/single-head-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+
+pushing a new topo branch (with a topic)
+
+  $ hg up 'desc("c_dD0")'
+  0 files updated, 0 files merged, 3 files removed, 0 files unresolved
+  $ hg topic bar
+  marked working directory as topic: bar
+  $ mkcommit c_dG0
+  active topic 'bar' grew its first changeset
+  $ hg push
+  pushing to $TESTTMP/single-head-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files (+1 heads)
+
+detect multiple heads on the topic
+
+  $ mkcommit c_dH0
+  $ hg push
+  pushing to $TESTTMP/single-head-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  $ hg up 'desc("c_dG0")'
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ mkcommit c_dI0
+  $ hg push  -f
+  pushing to $TESTTMP/single-head-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files (+1 heads)
+  transaction abort!
+  rollback completed
+  abort: 2 heads on "default:bar"
+  (5194f5dcd542, 48a01453c1c5)
+  [255]
+
+merge works fine
+
+  $ hg merge
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ mkcommit c_dJ0
+  $ hg push
+  pushing to $TESTTMP/single-head-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files
+
+Test single head enforcing - by phase move
+------------------------------------------
+
+  $ hg -R ../single-head-server phase --public 'desc("c_dJ0")'
+  abort: 2 heads on "default"
+  (6ed1df20edb1, 678bca4de98c)
+  [255]
+
+Test single head enforcing - after rewrite
+------------------------------------------
+
+  $ hg up foo
+  switching to topic foo
+  3 files updated, 0 files merged, 4 files removed, 0 files unresolved
+  $ hg commit --amend -m c_dF1
+  $ hg push
+  pushing to $TESTTMP/single-head-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 0 changes to 1 files (+1 heads)
+  1 new obsolescence markers
+  obsoleted 1 changesets
--- a/tests/test-topic-fold.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-topic-fold.t	Tue Nov 14 23:04:04 2017 +0100
@@ -37,7 +37,9 @@
   $ cd testfold
   $ mkcommit ROOT
   $ hg topic myfeature
+  marked working directory as topic: myfeature
   $ mkcommit feature1
+  active topic 'myfeature' grew its first changeset
   $ mkcommit feature2
   $ logtopic
   @  2:d76a6166b18c835be9a487c5e21c7d260f0a1676
@@ -51,7 +53,7 @@
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg stack
   ### topic: myfeature
-  ### branch: default
+  ### target: default (branch)
   t1@ folded (current)
   t0^ add ROOT (base)
   $ logtopic
@@ -77,7 +79,9 @@
   $ mkcommit feature3
   created new head
   $ hg topic myotherfeature
+  marked working directory as topic: myotherfeature
   $ mkcommit feature4
+  active topic 'myotherfeature' grew its first changeset
   $ logtopic
   @  5:5ded4d6d578c37f339b0716de2e46e12ece7cbde
   |  topics: myotherfeature
@@ -88,7 +92,9 @@
   o  0:3e7df3b3b17c6deb4a1c70e790782fdf17af96a7
      topics:
   $ hg fold --exact -r "(tip~1)::" -m "folded 2"
+  active topic 'myotherfeature' is now empty
   2 changesets folded
+  clearing empty topic "myotherfeature"
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ logtopic
   @  6:03da8f7238e9a4d708d6b8af402c91c68f271477
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-topic-mode.t	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,330 @@
+  $ . "$TESTDIR/testlib/topic_setup.sh"
+
+Testing the config knob to forbid untopiced commit
+======================================================
+
+  $ hg init $TESTTMP/untopic-commit
+  $ cd $TESTTMP/untopic-commit
+  $ cat <<EOF >> .hg/hgrc
+  > [phases]
+  > publish=false
+  > EOF
+  $ cat <<EOF >> $HGRCPATH
+  > [experimental]
+  > topic-mode = enforce
+  > EOF
+  $ touch a b c d
+  $ hg add a
+  $ hg ci -m "Added a"
+  abort: no active topic
+  (see 'hg help -e topic.topic-mode' for details)
+  [255]
+
+(same test, checking we abort before the editor)
+
+  $ EDITOR=cat hg ci -m "Added a" --edit
+  abort: no active topic
+  (see 'hg help -e topic.topic-mode' for details)
+  [255]
+  $ hg ci -m "added a" --config experimental.topic-mode=ignore
+  $ hg log
+  changeset:   0:a154386e50d1
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     added a
+  
+
+Testing the config knob to warn about untopiced commit
+==========================================================
+
+  $ hg init $TESTTMP/untopic-warn-commit
+  $ cd $TESTTMP/untopic-warn-commit
+  $ cat <<EOF >> .hg/hgrc
+  > [phases]
+  > publish=false
+  > EOF
+  $ cat <<EOF >> $HGRCPATH
+  > [experimental]
+  > topic-mode = warning
+  > EOF
+  $ touch a b c d
+  $ hg add a
+
+(same test, checking we abort before the editor)
+
+  $ HGEDITOR=cat hg ci -m "Added a" --edit
+  warning: new draft commit without topic
+  (see 'hg help -e topic.topic-mode' for details)
+  Added a
+  
+  
+  HG: Enter commit message.  Lines beginning with 'HG:' are removed.
+  HG: Leave message empty to abort commit.
+  HG: --
+  HG: user: test
+  HG: branch 'default'
+  HG: added a
+
+  $ HGEDITOR=cat hg ci --amend -m "Added a" --edit
+  Added a
+  
+  
+  HG: Enter commit message.  Lines beginning with 'HG:' are removed.
+  HG: Leave message empty to abort commit.
+  HG: --
+  HG: user: test
+  HG: branch 'default'
+  HG: added a
+  $ hg ci --amend -m "added a'" --config experimental.topic-mode=ignore
+  $ hg log
+  changeset:   2:2e862d8b5eff
+  tag:         tip
+  parent:      -1:000000000000
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     added a'
+  
+
+Testing the config knob to warn about untopiced merge commit
+================================================================
+
+  $ hg init $TESTTMP/test-untopic-merge-commit
+  $ cd $TESTTMP/test-untopic-merge-commit
+  $ cat <<EOF >> .hg/hgrc
+  > [phases]
+  > publish=false
+  > EOF
+  $ cat <<EOF >> $HGRCPATH
+  > [experimental]
+  > topic-mode = enforce
+  > EOF
+  $ touch ROOT
+  $ hg commit -A -m "ROOT" --config experimental.topic-mode=ignore
+  adding ROOT
+  $ touch a
+  $ hg add a
+  $ hg topic mytopic
+  marked working directory as topic: mytopic
+  $ hg ci -m "Added a"
+  active topic 'mytopic' grew its first changeset
+
+  $ hg up -r "desc('ROOT')"
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ touch default
+  $ hg add default
+  $ hg commit -m "default" --config experimental.topic-mode=ignore
+
+  $ hg merge mytopic
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ hg commit -m "merge mytopic"
+  warning: new draft commit without topic
+  (see 'hg help -e topic.topic-mode' for details)
+
+  $ hg log -G
+  @    changeset:   3:676a445d1c09
+  |\   tag:         tip
+  | |  parent:      2:a4da109ee59f
+  | |  parent:      1:e5b6c632bd8e
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     merge mytopic
+  | |
+  | o  changeset:   2:a4da109ee59f
+  | |  parent:      0:ec1d2790416d
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     default
+  | |
+  o |  changeset:   1:e5b6c632bd8e
+  |/   topic:       mytopic
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Added a
+  |
+  o  changeset:   0:ec1d2790416d
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     ROOT
+  
+
+Testing the config knob to about on untopiced merge commit
+================================================================
+
+  $ hg init $TESTTMP/test-untopic-merge-commit-abort
+  $ cd $TESTTMP/test-untopic-merge-commit-abort
+  $ cat <<EOF >> .hg/hgrc
+  > [phases]
+  > publish=false
+  > EOF
+  $ cat <<EOF >> $HGRCPATH
+  > [experimental]
+  > topic-mode = enforce-all
+  > EOF
+  $ touch ROOT
+  $ hg commit -A -m "ROOT" --config experimental.topic-mode=ignore
+  adding ROOT
+  $ touch a
+  $ hg add a
+  $ hg topic mytopic
+  marked working directory as topic: mytopic
+  $ hg ci -m "Added a"
+  active topic 'mytopic' grew its first changeset
+
+  $ hg up -r "desc('ROOT')"
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ touch default
+  $ hg add default
+  $ hg commit -m "default" --config experimental.topic-mode=ignore
+
+  $ hg merge mytopic
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ hg commit -m "merge mytopic"
+  abort: no active topic
+  (see 'hg help -e topic.topic-mode' for details)
+  [255]
+
+  $ hg log -G
+  @  changeset:   2:a4da109ee59f
+  |  tag:         tip
+  |  parent:      0:ec1d2790416d
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     default
+  |
+  | @  changeset:   1:e5b6c632bd8e
+  |/   topic:       mytopic
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Added a
+  |
+  o  changeset:   0:ec1d2790416d
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     ROOT
+  
+Testing the config knob to use a random topic for untopic commit
+====================================================================
+
+  $ hg init $TESTTMP/test-untopic-random
+  $ cd $TESTTMP/test-untopic-random
+  $ cat <<EOF >> .hg/hgrc
+  > [phases]
+  > publish=false
+  > EOF
+  $ cat <<EOF >> $HGRCPATH
+  > [experimental]
+  > topic-mode = random
+  > EOF
+
+  $ touch ROOT
+  $ hg commit -A -m "ROOT" --config experimental.topic-mode=ignore
+  adding ROOT
+
+  $ touch A
+  $ hg add A
+  $ hg commit -m "Add A" --config devel.randomseed=42
+  active topic 'panoramic-antelope' grew its first changeset
+
+  $ hg up -r "desc(ROOT)"
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+
+  $ touch B
+  $ hg add B
+  $ hg commit -m "Add B" --config devel.randomseed=128
+  active topic 'various-dove' grew its first changeset
+
+Test a merge too
+
+  $ hg phase --public -r .
+  active topic 'various-dove' is now empty
+  $ hg up default
+  clearing empty topic "various-dove"
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg log -G
+  @  changeset:   2:2d2acb6efad5
+  |  tag:         tip
+  |  parent:      0:ec1d2790416d
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Add B
+  |
+  | o  changeset:   1:d4b548f35972
+  |/   topic:       panoramic-antelope
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Add A
+  |
+  o  changeset:   0:ec1d2790416d
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     ROOT
+  
+  $ hg merge panoramic-antelope
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ hg ci -m 'merge'
+Testing the config knob to use a random topic for untopic commit (even for merge)
+=================================================================================
+
+  $ hg init $TESTTMP/test-untopic-random-all
+  $ cd $TESTTMP/test-untopic-random-all
+  $ cat <<EOF >> .hg/hgrc
+  > [phases]
+  > publish=false
+  > EOF
+  $ cat <<EOF >> $HGRCPATH
+  > [experimental]
+  > topic-mode = random-all
+  > EOF
+
+  $ touch ROOT
+  $ hg commit -A -m "ROOT" --config experimental.topic-mode=ignore
+  adding ROOT
+
+  $ touch A
+  $ hg add A
+  $ hg commit -m "Add A" --config devel.randomseed=42
+  active topic 'panoramic-antelope' grew its first changeset
+
+  $ hg up -r "desc(ROOT)"
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+
+  $ touch B
+  $ hg add B
+  $ hg commit -m "Add B" --config devel.randomseed=128
+  active topic 'various-dove' grew its first changeset
+
+Test a merge too
+
+  $ hg phase --public -r .
+  active topic 'various-dove' is now empty
+  $ hg up default
+  clearing empty topic "various-dove"
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg log -G
+  @  changeset:   2:2d2acb6efad5
+  |  tag:         tip
+  |  parent:      0:ec1d2790416d
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Add B
+  |
+  | o  changeset:   1:d4b548f35972
+  |/   topic:       panoramic-antelope
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Add A
+  |
+  o  changeset:   0:ec1d2790416d
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     ROOT
+  
+  $ hg merge panoramic-antelope
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ hg ci -m 'merge'  --config devel.randomseed=1337
+  active topic 'omniscient-locust' grew its first changeset
--- a/tests/test-topic-push-concurrent-on.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-topic-push-concurrent-on.t	Tue Nov 14 23:04:04 2017 +0100
@@ -93,7 +93,7 @@
   $ hg outgoing -G
   comparing with $TESTTMP/main (glob)
   searching for changes
-  @  4 mountain  draft CC
+  @  3 mountain  draft CC
   
   $ hg push 
   pushing to $TESTTMP/main (glob)
@@ -108,7 +108,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  2 new obsolescence markers
+  1 new obsolescence markers
 
 Including on non-publishing
 
@@ -119,7 +119,7 @@
   adding manifests
   adding file changes
   added 3 changesets with 3 changes to 3 files (+1 heads)
-  2 new obsolescence markers
+  1 new obsolescence markers
 
 Testing topic behavior
 ======================
@@ -130,13 +130,15 @@
   $ hg up -r 'desc(CA)'
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg topic babar
+  marked working directory as topic: babar
   $ echo aaa > ddd
   $ hg add ddd
   $ hg commit -m 'CD'
+  active topic 'babar' grew its first changeset
   $ hg log -G # keep track of phase because I saw some strange bug during developement
-  @  5 default babar draft CD
+  @  4 default babar draft CD
   |
-  | o  4 mountain  public CC
+  | o  3 mountain  public CC
   |/
   | o  1 default  public CB
   |/
@@ -153,9 +155,9 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
   $ hg log -G
-  @  5 default babar draft CD
+  @  4 default babar draft CD
   |
-  | o  4 mountain  public CC
+  | o  3 mountain  public CC
   |/
   | o  1 default  public CB
   |/
@@ -171,9 +173,9 @@
   (merge or see 'hg help push' for details about pushing new heads)
   [255]
   $ hg log -G
-  @  5 default babar draft CD
+  @  4 default babar draft CD
   |
-  | o  4 mountain  public CC
+  | o  3 mountain  public CC
   |/
   | o  1 default  public CB
   |/
@@ -186,15 +188,17 @@
   $ hg up -r 'desc(CA)'
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg topic celeste
+  marked working directory as topic: celeste
   $ echo aaa > eee
   $ hg add eee
   $ hg commit -m 'CE'
+  active topic 'celeste' grew its first changeset
   $ hg log -G # keep track of phase because I saw some strange bug during developement
-  @  6 default celeste draft CE
+  @  5 default celeste draft CE
   |
-  | o  5 default babar draft CD
+  | o  4 default babar draft CD
   |/
-  | o  4 mountain  public CC
+  | o  3 mountain  public CC
   |/
   | o  1 default  public CB
   |/
@@ -214,11 +218,11 @@
   (merge or see 'hg help push' for details about pushing new heads)
   [255]
   $ hg log -G
-  @  6 default celeste draft CE
+  @  5 default celeste draft CE
   |
-  | o  5 default babar draft CD
+  | o  4 default babar draft CD
   |/
-  | o  4 mountain  public CC
+  | o  3 mountain  public CC
   |/
   | o  1 default  public CB
   |/
@@ -237,11 +241,11 @@
   remote: adding file changes
   remote: added 1 changesets with 1 changes to 1 files (+1 heads)
   $ hg log -G
-  @  6 default celeste draft CE
+  @  5 default celeste draft CE
   |
-  | o  5 default babar draft CD
+  | o  4 default babar draft CD
   |/
-  | o  4 mountain  public CC
+  | o  3 mountain  public CC
   |/
   | o  1 default  public CB
   |/
@@ -257,11 +261,11 @@
   (merge or see 'hg help push' for details about pushing new heads)
   [255]
   $ hg log -G
-  @  6 default celeste draft CE
+  @  5 default celeste draft CE
   |
-  | o  5 default babar draft CD
+  | o  4 default babar draft CD
   |/
-  | o  4 mountain  public CC
+  | o  3 mountain  public CC
   |/
   | o  1 default  public CB
   |/
@@ -274,17 +278,18 @@
   $ hg up 'desc(CB)'
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg topic babar
+  marked working directory as topic: babar
   $ echo aaa > fff
   $ hg add fff
   $ hg commit -m 'CF'
   $ hg log -G
-  @  7 default babar draft CF
+  @  6 default babar draft CF
   |
-  | o  6 default celeste draft CE
+  | o  5 default celeste draft CE
   | |
-  | | o  5 default babar draft CD
+  | | o  4 default babar draft CD
   | |/
-  | | o  4 mountain  public CC
+  | | o  3 mountain  public CC
   | |/
   o |  1 default  public CB
   |/
@@ -316,17 +321,17 @@
   (branch merge, don't forget to commit)
   $ hg commit -m 'CM'
   $ hg log -G
-  @    9 default babar draft CM
+  @    8 default babar draft CM
   |\
-  | o  8 default  draft CG
+  | o  7 default  draft CG
   | |
-  o |  7 default babar draft CF
+  o |  6 default babar draft CF
   | |
-  | | o  6 default celeste draft CE
+  | | o  5 default celeste draft CE
   | |/
-  | | o  5 default babar draft CD
+  | | o  4 default babar draft CD
   | |/
-  | | o  4 mountain  public CC
+  | | o  3 mountain  public CC
   | |/
   o |  1 default  public CB
   |/
@@ -379,13 +384,17 @@
   $ echo aaa > aaa
   $ hg add aaa
   $ hg topic topicA
+  marked working directory as topic: topicA
   $ hg commit -m 'CA'
+  active topic 'topicA' grew its first changeset
   $ hg up 'desc(CBASE)'
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ echo aaa > bbb
   $ hg add bbb
   $ hg topic topicB
+  marked working directory as topic: topicB
   $ hg commit -m 'CB'
+  active topic 'topicB' grew its first changeset
   $ cd ..
   $ hg push -R repoA repoB
   pushing to repoB
--- a/tests/test-topic-push.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-topic-push.t	Tue Nov 14 23:04:04 2017 +0100
@@ -89,7 +89,7 @@
   $ hg outgoing -G
   comparing with $TESTTMP/main (glob)
   searching for changes
-  @  4 mountain  draft CC
+  @  3 mountain  draft CC
   
   $ hg push 
   pushing to $TESTTMP/main (glob)
@@ -104,7 +104,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  2 new obsolescence markers
+  1 new obsolescence markers
 
 Including on non-publishing
 
@@ -115,7 +115,7 @@
   adding manifests
   adding file changes
   added 3 changesets with 3 changes to 3 files (+1 heads)
-  2 new obsolescence markers
+  1 new obsolescence markers
 
 Testing topic behavior
 ======================
@@ -126,13 +126,15 @@
   $ hg up -r 'desc(CA)'
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg topic babar
+  marked working directory as topic: babar
   $ echo aaa > ddd
   $ hg add ddd
   $ hg commit -m 'CD'
+  active topic 'babar' grew its first changeset
   $ hg log -G # keep track of phase because I saw some strange bug during developement
-  @  5 default babar draft CD
+  @  4 default babar draft CD
   |
-  | o  4 mountain  public CC
+  | o  3 mountain  public CC
   |/
   | o  1 default  public CB
   |/
@@ -149,14 +151,69 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
   $ hg log -G
-  @  5 default babar draft CD
+  @  4 default babar draft CD
   |
-  | o  4 mountain  public CC
+  | o  3 mountain  public CC
+  |/
+  | o  1 default  public CB
+  |/
+  o  0 default  public CA
+  
+push --topic
+
+  $ hg log -G -R $TESTTMP/draft
+  o  3 default babar draft CD
+  |
+  | o  2 mountain  public CC
   |/
   | o  1 default  public CB
   |/
   o  0 default  public CA
   
+  $ echo bbb >> aaa
+  $ hg commit -m "C'A"
+  $ hg up 1
+  2 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg topic --clear
+  $ echo bbb >> bbb
+  $ hg commit -m "C'B"
+  $ hg log -G
+  @  6 default  draft C'B
+  |
+  | o  5 default babar draft C'A
+  | |
+  | o  4 default babar draft CD
+  | |
+  | | o  3 mountain  public CC
+  | |/
+  o |  1 default  public CB
+  |/
+  o  0 default  public CA
+  
+  $ hg outgoing draft --topic babar
+  comparing with $TESTTMP/draft
+  searching for changes
+  5 default babar draft C'A
+  $ hg push draft --topic babar
+  pushing to $TESTTMP/draft
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  $ hg log -G -R $TESTTMP/draft
+  o  4 default babar draft C'A
+  |
+  o  3 default babar draft CD
+  |
+  | o  2 mountain  public CC
+  |/
+  | o  1 default  public CB
+  |/
+  o  0 default  public CA
+  
+  $ hg strip --config extensions.strip= --no-backup -r 7a9e34dbf547: --quiet
+  $ hg strip --config extensions.strip= -R $TESTTMP/draft --no-backup -r 7a9e34dbf547: --quiet
 
 Pushing a new topic to a publishing server should be seen as a new head
 
@@ -167,9 +224,9 @@
   (merge or see 'hg help push' for details about pushing new heads)
   [255]
   $ hg log -G
-  @  5 default babar draft CD
+  @  4 default babar draft CD
   |
-  | o  4 mountain  public CC
+  | o  3 mountain  public CC
   |/
   | o  1 default  public CB
   |/
@@ -182,15 +239,17 @@
   $ hg up -r 'desc(CA)'
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg topic celeste
+  marked working directory as topic: celeste
   $ echo aaa > eee
   $ hg add eee
   $ hg commit -m 'CE'
+  active topic 'celeste' grew its first changeset
   $ hg log -G # keep track of phase because I saw some strange bug during developement
-  @  6 default celeste draft CE
+  @  5 default celeste draft CE
   |
-  | o  5 default babar draft CD
+  | o  4 default babar draft CD
   |/
-  | o  4 mountain  public CC
+  | o  3 mountain  public CC
   |/
   | o  1 default  public CB
   |/
@@ -210,11 +269,11 @@
   (merge or see 'hg help push' for details about pushing new heads)
   [255]
   $ hg log -G
-  @  6 default celeste draft CE
+  @  5 default celeste draft CE
   |
-  | o  5 default babar draft CD
+  | o  4 default babar draft CD
   |/
-  | o  4 mountain  public CC
+  | o  3 mountain  public CC
   |/
   | o  1 default  public CB
   |/
@@ -233,11 +292,11 @@
   remote: adding file changes
   remote: added 1 changesets with 1 changes to 1 files (+1 heads)
   $ hg log -G
-  @  6 default celeste draft CE
+  @  5 default celeste draft CE
   |
-  | o  5 default babar draft CD
+  | o  4 default babar draft CD
   |/
-  | o  4 mountain  public CC
+  | o  3 mountain  public CC
   |/
   | o  1 default  public CB
   |/
@@ -253,11 +312,11 @@
   (merge or see 'hg help push' for details about pushing new heads)
   [255]
   $ hg log -G
-  @  6 default celeste draft CE
+  @  5 default celeste draft CE
   |
-  | o  5 default babar draft CD
+  | o  4 default babar draft CD
   |/
-  | o  4 mountain  public CC
+  | o  3 mountain  public CC
   |/
   | o  1 default  public CB
   |/
@@ -270,17 +329,18 @@
   $ hg up 'desc(CB)'
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg topic babar
+  marked working directory as topic: babar
   $ echo aaa > fff
   $ hg add fff
   $ hg commit -m 'CF'
   $ hg log -G
-  @  7 default babar draft CF
+  @  6 default babar draft CF
   |
-  | o  6 default celeste draft CE
+  | o  5 default celeste draft CE
   | |
-  | | o  5 default babar draft CD
+  | | o  4 default babar draft CD
   | |/
-  | | o  4 mountain  public CC
+  | | o  3 mountain  public CC
   | |/
   o |  1 default  public CB
   |/
@@ -312,17 +372,17 @@
   (branch merge, don't forget to commit)
   $ hg commit -m 'CM'
   $ hg log -G
-  @    9 default babar draft CM
+  @    8 default babar draft CM
   |\
-  | o  8 default  draft CG
+  | o  7 default  draft CG
   | |
-  o |  7 default babar draft CF
+  o |  6 default babar draft CF
   | |
-  | | o  6 default celeste draft CE
+  | | o  5 default celeste draft CE
   | |/
-  | | o  5 default babar draft CD
+  | | o  4 default babar draft CD
   | |/
-  | | o  4 mountain  public CC
+  | | o  3 mountain  public CC
   | |/
   o |  1 default  public CB
   |/
@@ -375,13 +435,17 @@
   $ echo aaa > aaa
   $ hg add aaa
   $ hg topic topicA
+  marked working directory as topic: topicA
   $ hg commit -m 'CA'
+  active topic 'topicA' grew its first changeset
   $ hg up 'desc(CBASE)'
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ echo aaa > bbb
   $ hg add bbb
   $ hg topic topicB
+  marked working directory as topic: topicB
   $ hg commit -m 'CB'
+  active topic 'topicB' grew its first changeset
   $ cd ..
   $ hg push -R repoA repoB
   pushing to repoB
--- a/tests/test-topic-rebase.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-topic-rebase.t	Tue Nov 14 23:04:04 2017 +0100
@@ -40,10 +40,12 @@
 
 Work on myfeature
   $ hg topic myfeature
+  marked working directory as topic: myfeature
   $ mkcommit feature1
+  active topic 'myfeature' grew its first changeset
   $ hg stack
   ### topic: myfeature
-  ### branch: default
+  ### target: default (branch)
   t1@ add feature1 (current)
   t0^ add ROOT (base)
   $ logtopic
@@ -69,11 +71,11 @@
   switching to topic myfeature
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg rebase
-  rebasing 1:39e7a938055e "add feature1"
+  rebasing 1:39e7a938055e "add feature1" (myfeature)
   switching to topic myfeature
   $ hg stack
   ### topic: myfeature
-  ### branch: default
+  ### target: default (branch)
   t1@ add feature1 (current)
   t0^ add default (base)
   $ logtopic
@@ -87,7 +89,7 @@
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg stack
   ### topic: myfeature
-  ### branch: default
+  ### target: default (branch)
   t1@ add feature1 (current)
   t0^ add default (base)
 
@@ -102,8 +104,10 @@
 
 Update the common file in a topic
   $ hg topic myotherfeature
+  marked working directory as topic: myotherfeature
   $ echo "B" >> file
   $ hg commit -m "myotherfeature1"
+  active topic 'myotherfeature' grew its first changeset
 
 Update the common file in default
   $ hg update --rev default
@@ -116,7 +120,7 @@
   switching to topic myotherfeature
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg rebase
-  rebasing 5:81f854012ec5 "myotherfeature1"
+  rebasing 5:81f854012ec5 "myotherfeature1" (myotherfeature)
   merging file
   warning: conflicts while merging file! (edit, then use 'hg resolve --mark')
   switching to topic myotherfeature
@@ -130,7 +134,7 @@
   (no more unresolved files)
   continue: hg rebase --continue
   $ hg rebase --continue
-  rebasing 5:81f854012ec5 "myotherfeature1"
+  rebasing 5:81f854012ec5 "myotherfeature1" (myotherfeature)
 
 Check the the commit has the right topic
 
@@ -149,13 +153,13 @@
      topics:
   $ hg stack
   ### topic: myotherfeature
-  ### branch: default
+  ### target: default (branch)
   t1@ myotherfeature1 (current)
   t0^ default3 (base)
   $ hg update --rev 7
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg stack
   ### topic: myotherfeature
-  ### branch: default
+  ### target: default (branch)
   t1@ myotherfeature1 (current)
   t0^ default3 (base)
--- a/tests/test-topic-shelve.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-topic-shelve.t	Tue Nov 14 23:04:04 2017 +0100
@@ -13,16 +13,18 @@
   $ touch a
   $ echo "Hello" >> a
   $ hg topic "testing-shelve"
+  marked working directory as topic: testing-shelve
   $ hg topic
-   * testing-shelve
+   * testing-shelve (0 changesets)
   $ hg ci -m "First commit" -A
   adding a
+  active topic 'testing-shelve' grew its first changeset
   $ hg topic
-   * testing-shelve
+   * testing-shelve (1 changesets)
   $ echo " World" >> a
   $ hg stack
   ### topic: testing-shelve
-  ### branch: default
+  ### target: default (branch)
   t1@ First commit (current)
 
 shelve test
@@ -32,10 +34,10 @@
   shelved as default
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg topic
-   * testing-shelve
+   * testing-shelve (1 changesets)
   $ hg stack
   ### topic: testing-shelve
-  ### branch: default
+  ### target: default (branch)
   t1@ First commit (current)
 
 unshelve test
@@ -43,8 +45,8 @@
   $ hg unshelve
   unshelving change 'default'
   $ hg topic
-   * testing-shelve
+   * testing-shelve (1 changesets)
   $ hg stack
   ### topic: testing-shelve
-  ### branch: default
+  ### target: default (branch)
   t1@ First commit (current)
--- a/tests/test-topic-stack-data.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-topic-stack-data.t	Tue Nov 14 23:04:04 2017 +0100
@@ -54,7 +54,9 @@
   $ hg up 'desc(base_c)'
   2 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ hg topic baz
+  marked working directory as topic: baz
   $ mkcommit baz_a
+  active topic 'baz' grew its first changeset
   $ mkcommit baz_b
 
 A simple topic with unstability
@@ -62,7 +64,9 @@
   $ hg up 'desc(base_d)'
   1 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ hg topic fuz
+  marked working directory as topic: fuz
   $ mkcommit fuz_a
+  active topic 'fuz' grew its first changeset
   $ mkcommit fuz_b
   $ mkcommit fuz_c
   $ hg up 'desc(fuz_a)'
@@ -74,7 +78,9 @@
   $ hg up 'desc(base_e)'
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg topic bar
+  marked working directory as topic: bar
   $ mkcommit bar_a
+  active topic 'bar' grew its first changeset
   $ mkcommit bar_b
   $ mkcommit bar_c
   $ hg up 'desc(bar_b)'
@@ -90,7 +96,9 @@
   $ hg up 'desc(lake_a)'
   1 files updated, 0 files merged, 7 files removed, 0 files unresolved
   $ hg topic foo
+  marked working directory as topic: foo
   $ mkcommit foo_a
+  active topic 'foo' grew its first changeset
   $ mkcommit foo_b
 
 Summary
@@ -103,7 +111,7 @@
   commit: (clean)
   update: 2 new changesets (update)
   phases: 22 draft
-  unstable: 3 changesets
+  orphan: 3 changesets
   topic:  foo
   $ hg log --graph -T '{desc} ({branch}) [{topic}]'
   @  add foo_b (lake) []
@@ -157,25 +165,25 @@
 basic output
 
   $ hg topic
-     bar
-     baz
-   * foo
-     fuz
+     bar (5 changesets, 1 troubled, 2 heads)
+     baz (2 changesets)
+   * foo (2 changesets)
+     fuz (3 changesets, 2 troubled)
 
 quiet version
 
   $ hg topic --quiet
-  bar
-  baz
-  foo
-  fuz
+  bar (5 changesets, 1 troubled, 2 heads)
+  baz (2 changesets)
+  foo (2 changesets)
+  fuz (3 changesets, 2 troubled)
 
 verbose
 
   $ hg topic --verbose
      bar (on branch: default, 5 changesets, 1 troubled, 2 heads)
      baz (on branch: default, 2 changesets, 2 behind)
-   * foo (on branch: lake, 2 changesets, ambiguous destination)
+   * foo (on branch: lake, 2 changesets, ambiguous destination: branch 'lake' has 2 heads)
      fuz (on branch: default, 3 changesets, 2 troubled, 1 behind)
 
 json
@@ -184,19 +192,26 @@
   [
    {
     "active": false,
-    "topic": "bar"
+    "changesetcount": 5,
+    "headcount": 2,
+    "topic": "bar",
+    "troubledcount": 1
    },
    {
     "active": false,
+    "changesetcount": 2,
     "topic": "baz"
    },
    {
     "active": true,
+    "changesetcount": 2,
     "topic": "foo"
    },
    {
     "active": false,
-    "topic": "fuz"
+    "changesetcount": 3,
+    "topic": "fuz",
+    "troubledcount": 2
    }
   ]
 
@@ -221,7 +236,7 @@
    },
    {
     "active": true,
-    "behinderror": "ambiguous destination",
+    "behinderror": "ambiguous destination: branch 'lake' has 2 heads",
     "branches+": "lake",
     "changesetcount": 2,
     "topic": "foo"
@@ -241,7 +256,7 @@
 
   $ hg stack bar
   ### topic: bar (2 heads)
-  ### branch: default
+  ### target: default (branch)
   t5: add bar_c
   t2^ add bar_b (base)
   t4$ add bar_e (unstable)
@@ -251,7 +266,7 @@
   t0^ add base_e (base)
   $ hg stack bar -v
   ### topic: bar (2 heads)
-  ### branch: default
+  ### target: default (branch)
   t5(9cbadf11b44d): add bar_c
   t2(e555c7e8c767)^ add bar_b (base)
   t4(a920412b5a05)$ add bar_e (unstable)
@@ -261,19 +276,19 @@
   t0(92f489a6251f)^ add base_e (base)
   $ hg stack baz
   ### topic: baz
-  ### branch: default, 2 behind
+  ### target: default (branch), 2 behind
   t2: add baz_b
   t1: add baz_a
   t0^ add base_c (base)
   $ hg stack foo
   ### topic: foo
-  ### branch: lake, ambigious rebase destination
+  ### target: lake (branch), ambigious rebase destination - branch 'lake' has 2 heads
   t2@ add foo_b (current)
   t1: add foo_a
   t0^ add lake_a (base)
   $ hg stack fuz
   ### topic: fuz
-  ### branch: default, 1 behind
+  ### target: default (branch), 1 behind
   t3$ add fuz_c (unstable)
   t2$ add fuz_b (unstable)
   t1: fuz1_a
--- a/tests/test-topic-stack.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-topic-stack.t	Tue Nov 14 23:04:04 2017 +0100
@@ -7,15 +7,17 @@
   > [ui]
   > logtemplate = {rev} {branch} \{{get(namespaces, "topics")}} {phase} {desc|firstline}\n
   > [experimental]
-  > evolution=createmarkers,exchange,allowunstable
+  > evolution=all
   > EOF
 
   $ hg init main
   $ cd main
   $ hg topic other
+  marked working directory as topic: other
   $ echo aaa > aaa
   $ hg add aaa
   $ hg commit -m c_a
+  active topic 'other' grew its first changeset
   $ echo aaa > bbb
   $ hg add bbb
   $ hg commit -m c_b
@@ -23,6 +25,7 @@
   $ echo aaa > ccc
   $ hg add ccc
   $ hg commit -m c_c
+  active topic 'foo' grew its first changeset
   $ echo aaa > ddd
   $ hg add ddd
   $ hg commit -m c_d
@@ -54,10 +57,23 @@
   0 files updated, 0 files merged, 4 files removed, 0 files unresolved
   $ hg topic --list
   ### topic: other
-  ### branch: default
+  ### target: default (branch)
   t2@ c_b (current)
   t1: c_a
   $ hg phase --public 'topic("other")'
+  active topic 'other' is now empty
+
+After changing the phase of all the changesets in "other" to public, the topic should still be active, but is empty. We should be better at informating the user about it and displaying good data in this case.
+
+  $ hg topic
+     foo   (4 changesets)
+   * other (0 changesets)
+  $ hg stack
+  ### topic: other
+  ### target: default (branch)
+  (stack is empty)
+  t0^ c_b (base current)
+
   $ hg up foo
   switching to topic foo
   4 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -68,10 +84,10 @@
 'hg stack' list all changeset in the topic
 
   $ hg topic
-   * foo
+   * foo (4 changesets)
   $ hg stack
   ### topic: foo
-  ### branch: default
+  ### target: default (branch)
   t4@ c_f (current)
   t3: c_e
   t2: c_d
@@ -79,7 +95,7 @@
   t0^ c_b (base)
   $ hg stack -v
   ### topic: foo
-  ### branch: default
+  ### target: default (branch)
   t4(6559e6d93aea)@ c_f (current)
   t3(0f9ac936c87d): c_e
   t2(e629654d7050): c_d
@@ -187,11 +203,36 @@
       }
   ]
 
+check that topics and stack are available even if ui.strict=true
+
+  $ hg topics
+   * foo (4 changesets)
+  $ hg stack
+  ### topic: foo
+  ### target: default (branch)
+  t4@ c_f (current)
+  t3: c_e
+  t2: c_d
+  t1: c_c
+  t0^ c_b (base)
+  $ hg topics --config ui.strict=true
+   * foo (4 changesets)
+  $ hg stack --config ui.strict=true
+  ### topic: foo
+  ### target: default (branch)
+  t4@ c_f (current)
+  t3: c_e
+  t2: c_d
+  t1: c_c
+  t0^ c_b (base)
+
 error case, nothing to list
 
   $ hg topic --clear
   $ hg stack
-  ### branch: 
+  ### target: default (branch)
+  (stack is empty)
+  b0^ c_f (base current)
 
 Test "t#" reference
 -------------------
@@ -201,6 +242,7 @@
   abort: cannot resolve "t2": no active topic
   [255]
   $ hg topic foo
+  marked working directory as topic: foo
   $ hg up t42
   abort: cannot resolve "t42": topic "foo" has only 4 changesets
   [255]
@@ -221,7 +263,7 @@
   $ echo bbb > ddd
   $ hg commit --amend
   $ hg log -G
-  @  7 default {foo} draft c_d
+  @  6 default {foo} draft c_d
   |
   | o  5 default {foo} draft c_f
   | |
@@ -237,7 +279,7 @@
   
   $ hg topic --list
   ### topic: foo
-  ### branch: default
+  ### target: default (branch)
   t4$ c_f (unstable)
   t3$ c_e (unstable)
   t2@ c_d (current)
@@ -247,7 +289,7 @@
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg topic --list
   ### topic: foo
-  ### branch: default
+  ### target: default (branch)
   t4$ c_f (unstable)
   t3$ c_e (current unstable)
   t2: c_d
@@ -255,7 +297,7 @@
   t0^ c_b (base)
   $ hg topic --list --color=debug
   [topic.stack.summary.topic|### topic: [topic.active|foo]]
-  [topic.stack.summary.branches|### branch: default]
+  [topic.stack.summary.branches|### target: default (branch)]
   [topic.stack.index topic.stack.index.unstable|t4][topic.stack.state topic.stack.state.unstable|$] [topic.stack.desc topic.stack.desc.unstable|c_f][topic.stack.state topic.stack.state.unstable| (unstable)]
   [topic.stack.index topic.stack.index.current topic.stack.index.unstable|t3][topic.stack.state topic.stack.state.current topic.stack.state.unstable|$] [topic.stack.desc topic.stack.desc.current topic.stack.desc.unstable|c_e][topic.stack.state topic.stack.state.current topic.stack.state.unstable| (current unstable)]
   [topic.stack.index topic.stack.index.clean|t2][topic.stack.state topic.stack.state.clean|:] [topic.stack.desc topic.stack.desc.clean|c_d]
@@ -268,7 +310,7 @@
 
   $ hg log -r 'stack()'
   2 default {foo} draft c_c
-  7 default {foo} draft c_d
+  6 default {foo} draft c_d
   4 default {foo} draft c_e
   5 default {foo} draft c_f
 
@@ -286,14 +328,14 @@
 Make things linear again
 
   $ hg rebase -s 'desc(c_e)' -d 'desc(c_d) - obsolete()'
-  rebasing 4:0f9ac936c87d "c_e"
-  rebasing 5:6559e6d93aea "c_f"
+  rebasing 4:0f9ac936c87d "c_e" (foo)
+  rebasing 5:6559e6d93aea "c_f" (foo)
   $ hg log -G
-  o  9 default {foo} draft c_f
+  o  8 default {foo} draft c_f
   |
-  o  8 default {foo} draft c_e
+  o  7 default {foo} draft c_e
   |
-  @  7 default {foo} draft c_d
+  @  6 default {foo} draft c_d
   |
   o  2 default {foo} draft c_c
   |
@@ -314,15 +356,15 @@
   $ hg add hhh
   $ hg commit -m c_h
   $ hg log -G
-  @  11 default {foo} draft c_h
+  @  10 default {foo} draft c_h
   |
-  o  10 default {foo} draft c_g
+  o  9 default {foo} draft c_g
   |
-  | o  9 default {foo} draft c_f
+  | o  8 default {foo} draft c_f
   | |
-  | o  8 default {foo} draft c_e
+  | o  7 default {foo} draft c_e
   |/
-  o  7 default {foo} draft c_d
+  o  6 default {foo} draft c_d
   |
   o  2 default {foo} draft c_c
   |
@@ -335,12 +377,12 @@
 
   $ hg top -l
   ### topic: foo (2 heads)
-  ### branch: default
-  t6: c_f
-  t5: c_e
+  ### target: default (branch)
+  t6@ c_h (current)
+  t5: c_g
   t2^ c_d (base)
-  t4@ c_h (current)
-  t3: c_g
+  t4: c_f
+  t3: c_e
   t2: c_d
   t1: c_c
   t0^ c_b (base)
@@ -355,20 +397,20 @@
   $ echo ccc > ddd
   $ hg commit --amend -m 'c_D' 
   $ hg rebase -d . -s 'desc(c_g)'
-  rebasing 10:81264ae8a36a "c_g"
-  rebasing 11:fde5f5941642 "c_h"
+  rebasing 9:81264ae8a36a "c_g" (foo)
+  rebasing 10:fde5f5941642 "c_h" (foo)
   $ hg log -G
-  o  15 default {foo} draft c_h
+  o  13 default {foo} draft c_h
   |
-  o  14 default {foo} draft c_g
+  o  12 default {foo} draft c_g
   |
-  @  13 default {foo} draft c_D
+  @  11 default {foo} draft c_D
   |
-  | o  9 default {foo} draft c_f
+  | o  8 default {foo} draft c_f
   | |
-  | o  8 default {foo} draft c_e
+  | o  7 default {foo} draft c_e
   | |
-  | x  7 default {foo} draft c_d
+  | x  6 default {foo} draft c_d
   |/
   o  2 default {foo} draft c_c
   |
@@ -379,12 +421,12 @@
 
   $ hg topic --list
   ### topic: foo (2 heads)
-  ### branch: default
-  t6$ c_f (unstable)
-  t5$ c_e (unstable)
-  t2^ c_D (base)
-  t4: c_h
-  t3: c_g
+  ### target: default (branch)
+  t6: c_h
+  t5: c_g
+  t2^ c_D (base current)
+  t4$ c_f (unstable)
+  t3$ c_e (unstable)
   t2@ c_D (current)
   t1: c_c
   t0^ c_b (base)
@@ -397,3 +439,477 @@
   abort: cannot resolve "thisdoesnotexist": no such topic found
   [255]
 
+Complex cases where commits with same topic are not consecutive but are linear
+==============================================================================
+
+  $ hg log --graph
+  o  13 default {foo} draft c_h
+  |
+  o  12 default {foo} draft c_g
+  |
+  @  11 default {foo} draft c_D
+  |
+  | o  8 default {foo} draft c_f
+  | |
+  | o  7 default {foo} draft c_e
+  | |
+  | x  6 default {foo} draft c_d
+  |/
+  o  2 default {foo} draft c_c
+  |
+  o  1 default {} public c_b
+  |
+  o  0 default {} public c_a
+  
+Converting into a linear chain
+  $ hg rebase -s 'desc("c_e") - obsolete()' -d 'desc("c_h") - obsolete()'
+  rebasing 7:215bc359096a "c_e" (foo)
+  rebasing 8:ec9267b3f33f "c_f" (foo)
+
+  $ hg log -G
+  o  15 default {foo} draft c_f
+  |
+  o  14 default {foo} draft c_e
+  |
+  o  13 default {foo} draft c_h
+  |
+  o  12 default {foo} draft c_g
+  |
+  @  11 default {foo} draft c_D
+  |
+  o  2 default {foo} draft c_c
+  |
+  o  1 default {} public c_b
+  |
+  o  0 default {} public c_a
+  
+Changing topics on some commits in between
+  $ hg topic foobar -r 'desc(c_e) + desc(c_D)'
+  switching to topic foobar
+  changed topic on 2 changes
+  $ hg log -G
+  @  17 default {foobar} draft c_D
+  |
+  | o  16 default {foobar} draft c_e
+  | |
+  | | o  15 default {foo} draft c_f
+  | | |
+  | | x  14 default {foo} draft c_e
+  | |/
+  | o  13 default {foo} draft c_h
+  | |
+  | o  12 default {foo} draft c_g
+  | |
+  | x  11 default {foo} draft c_D
+  |/
+  o  2 default {foo} draft c_c
+  |
+  o  1 default {} public c_b
+  |
+  o  0 default {} public c_a
+  
+  $ hg rebase -s 'desc("c_f") - obsolete()' -d 'desc("c_e") - obsolete()'
+  rebasing 15:77082e55de88 "c_f" (foo)
+  switching to topic foo
+  switching to topic foobar
+  $ hg rebase -s 'desc("c_g") - obsolete()' -d 'desc("c_D") - obsolete()'
+  rebasing 12:0c3e8aed985d "c_g" (foo)
+  switching to topic foo
+  rebasing 13:b9e4f3709bc5 "c_h" (foo)
+  rebasing 16:4bc813530301 "c_e" (foobar)
+  switching to topic foobar
+  rebasing 18:4406ea4be852 "c_f" (tip foo)
+  switching to topic foo
+  switching to topic foobar
+  $ hg up
+  3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg log --graph
+  o  22 default {foo} draft c_f
+  |
+  @  21 default {foobar} draft c_e
+  |
+  o  20 default {foo} draft c_h
+  |
+  o  19 default {foo} draft c_g
+  |
+  o  17 default {foobar} draft c_D
+  |
+  o  2 default {foo} draft c_c
+  |
+  o  1 default {} public c_b
+  |
+  o  0 default {} public c_a
+  
+XXX: The following should show single heads
+XXX: The behind count is weird, because the topic are interleaved.
+
+  $ hg stack
+  ### topic: foobar
+  ### target: default (branch), 3 behind
+  t2@ c_e (current)
+    ^ c_h
+  t1: c_D
+  t0^ c_c (base)
+
+  $ hg stack foo
+  ### topic: foo
+  ### target: default (branch), ambigious rebase destination - topic 'foo' has 3 heads
+  t4: c_f
+    ^ c_e
+  t3: c_h
+  t2: c_g
+    ^ c_D
+  t1: c_c
+  t0^ c_b (base)
+
+case involving a merge
+----------------------
+
+  $ cd ..
+  $ hg init stack-gap-merge
+  $ cd stack-gap-merge
+
+  $ echo aaa > aaa
+  $ hg commit -Am 'c_A'
+  adding aaa
+  $ hg topic red
+  marked working directory as topic: red
+  $ echo bbb > bbb
+  $ hg commit -Am 'c_B'
+  adding bbb
+  active topic 'red' grew its first changeset
+  $ echo ccc > ccc
+  $ hg commit -Am 'c_C'
+  adding ccc
+  $ hg topic blue
+  $ echo ddd > ddd
+  $ hg commit -Am 'c_D'
+  adding ddd
+  active topic 'blue' grew its first changeset
+  $ hg up 'desc("c_B")'
+  switching to topic red
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ echo eee > eee
+  $ hg commit -Am 'c_E'
+  adding eee
+  $ echo fff > fff
+  $ hg commit -Am 'c_F'
+  adding fff
+  $ hg topic blue
+  $ echo ggg > ggg
+  $ hg commit -Am 'c_G'
+  adding ggg
+  $ hg up 'desc("c_D")'
+  2 files updated, 0 files merged, 3 files removed, 0 files unresolved
+  $ hg topic red
+  $ hg merge 'desc("c_G")'
+  3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ hg commit -Am 'c_H'
+  $ hg topic blue
+  $ echo iii > iii
+  $ hg ci -Am 'c_I'
+  adding iii
+
+  $ hg log -G
+  @  8 default {blue} draft c_I
+  |
+  o    7 default {red} draft c_H
+  |\
+  | o  6 default {blue} draft c_G
+  | |
+  | o  5 default {red} draft c_F
+  | |
+  | o  4 default {red} draft c_E
+  | |
+  o |  3 default {blue} draft c_D
+  | |
+  o |  2 default {red} draft c_C
+  |/
+  o  1 default {red} draft c_B
+  |
+  o  0 default {} draft c_A
+  
+
+  $ hg stack red
+  ### topic: red
+  ### target: default (branch), 6 behind
+  t5: c_H
+    ^ c_G
+    ^ c_D
+  t4: c_C
+  t1^ c_B (base)
+  t3: c_F
+  t2: c_E
+  t1: c_B
+  t0^ c_A (base)
+  $ hg stack blue
+  ### topic: blue
+  ### target: default (branch), ambigious rebase destination - topic 'blue' has 3 heads
+  t3@ c_I (current)
+    ^ c_H
+  t2: c_D
+    ^ c_C
+  t1: c_G
+  t0^ c_F (base)
+
+Even with some obsolete and orphan changesets
+
+(the ordering of each branch of "blue" change because their hash change. we
+should stabilize this eventuelly)
+
+  $ hg up 'desc("c_B")'
+  switching to topic red
+  0 files updated, 0 files merged, 6 files removed, 0 files unresolved
+  $ hg commit --amend --user test2
+  $ hg up 'desc("c_C")'
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg commit --amend --user test2
+  $ hg up 'desc("c_D")'
+  switching to topic blue
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg commit --amend --user test2
+
+  $ hg log -G --rev 'sort(all(), "topo")'
+  @  11 default {blue} draft c_D
+  |
+  | o  8 default {blue} draft c_I
+  | |
+  | o    7 default {red} draft c_H
+  | |\
+  | | o  6 default {blue} draft c_G
+  | | |
+  | | o  5 default {red} draft c_F
+  | | |
+  | | o  4 default {red} draft c_E
+  | | |
+  | x |  3 default {blue} draft c_D
+  |/ /
+  x /  2 default {red} draft c_C
+  |/
+  | o  10 default {red} draft c_C
+  |/
+  x  1 default {red} draft c_B
+  |
+  | o  9 default {red} draft c_B
+  |/
+  o  0 default {} draft c_A
+  
+
+  $ hg stack red
+  ### topic: red
+  ### target: default (branch), ambigious rebase destination - topic 'red' has 3 heads
+  t5$ c_H (unstable)
+    ^ c_G
+    ^ c_D
+  t4$ c_C (unstable)
+  t1^ c_B (base)
+  t3$ c_F (unstable)
+  t2$ c_E (unstable)
+  t1: c_B
+  t0^ c_A (base)
+  $ hg stack blue
+  ### topic: blue
+  ### target: default (branch), ambigious rebase destination - topic 'blue' has 3 heads
+  t3$ c_I (unstable)
+    ^ c_H
+  t2$ c_G (unstable)
+    ^ c_F
+  t1$ c_D (current unstable)
+  t0^ c_C (base unstable)
+
+more obsolescence
+
+  $ hg up 'max(desc("c_H"))'
+  switching to topic red
+  3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg commit --amend --user test3
+  $ hg up 'max(desc("c_G"))'
+  switching to topic blue
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ hg commit --amend --user test3
+  $ hg up 'max(desc("c_B"))'
+  switching to topic red
+  0 files updated, 0 files merged, 3 files removed, 0 files unresolved
+  $ hg commit --amend --user test3
+  $ hg up 'max(desc("c_C"))'
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg commit --amend --user test3
+  $ hg up 'max(desc("c_D"))'
+  switching to topic blue
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg commit --amend --user test3
+
+  $ hg log -G --rev 'sort(all(), "topo")'
+  @  16 default {blue} draft c_D
+  |
+  | o  13 default {blue} draft c_G
+  | |
+  | | o    12 default {red} draft c_H
+  | | |\
+  | | | | o  8 default {blue} draft c_I
+  | | | | |
+  | | +---x  7 default {red} draft c_H
+  | | | |/
+  | +---x  6 default {blue} draft c_G
+  | | |
+  | o |  5 default {red} draft c_F
+  | | |
+  | o |  4 default {red} draft c_E
+  | | |
+  +---x  3 default {blue} draft c_D
+  | |
+  x |  2 default {red} draft c_C
+  |/
+  | o  15 default {red} draft c_C
+  |/
+  x  1 default {red} draft c_B
+  |
+  | o  14 default {red} draft c_B
+  |/
+  o  0 default {} draft c_A
+  
+
+  $ hg stack red
+  ### topic: red
+  ### target: default (branch), ambigious rebase destination - topic 'red' has 3 heads
+  t5$ c_H (unstable)
+    ^ c_G
+    ^ c_D
+  t4$ c_F (unstable)
+  t3$ c_E (unstable)
+  t1^ c_B (base)
+  t2$ c_C (unstable)
+  t1: c_B
+  t0^ c_A (base)
+  $ hg stack blue
+  ### topic: blue
+  ### target: default (branch), ambigious rebase destination - topic 'blue' has 3 heads
+  t3$ c_I (unstable)
+    ^ c_H
+  t2$ c_G (unstable)
+    ^ c_F
+  t1$ c_D (current unstable)
+  t0^ c_C (base unstable)
+
+Test stack behavior with a split
+--------------------------------
+
+get things linear again
+
+  $ hg rebase -r t1 -d default
+  rebasing 16:1d84ec948370 "c_D" (tip blue)
+  switching to topic blue
+  $ hg rebase -r t2 -d t1
+  rebasing 13:3ab2eedae500 "c_G" (blue)
+  $ hg rebase -r t3 -d t2
+  rebasing 8:3bfe800e0486 "c_I" (blue)
+  $ hg stack
+  ### topic: blue
+  ### target: default (branch)
+  t3: c_I
+  t2: c_G
+  t1@ c_D (current)
+  t0^ c_A (base)
+
+making a split
+(first get something to split)
+
+  $ hg up t2
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg status --change .
+  A ggg
+  $ echo zzz > Z
+  $ hg add Z
+  $ hg commit --amend
+  $ hg status --change .
+  A Z
+  A ggg
+  $ hg stack
+  ### topic: blue
+  ### target: default (branch)
+  t3$ c_I (unstable)
+  t2@ c_G (current)
+  t1: c_D
+  t0^ c_A (base)
+  $ hg --config extensions.evolve=  --config ui.interactive=yes split << EOF
+  > y
+  > y
+  > n
+  > y
+  > EOF
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  adding Z
+  adding ggg
+  diff --git a/Z b/Z
+  new file mode 100644
+  examine changes to 'Z'? [Ynesfdaq?] y
+  
+  @@ -0,0 +1,1 @@
+  +zzz
+  record change 1/2 to 'Z'? [Ynesfdaq?] y
+  
+  diff --git a/ggg b/ggg
+  new file mode 100644
+  examine changes to 'ggg'? [Ynesfdaq?] n
+  
+  Done splitting? [yN] y
+
+  $ hg --config extensions.evolve= obslog --all
+  o  dde94df880e9 (21) c_G
+  |
+  | @  e7ea874afbd5 (22) c_G
+  |/
+  x  b24bab30ac12 (20) c_G
+  |    rewritten(parent, content) as dde94df880e9, e7ea874afbd5 by test (Thu Jan 01 00:00:00 1970 +0000)
+  |
+  x  907f7d3c2333 (18) c_G
+  |    rewritten as b24bab30ac12 by test (Thu Jan 01 00:00:00 1970 +0000)
+  |
+  x  3ab2eedae500 (13) c_G
+  |    rewritten as 907f7d3c2333 by test (Thu Jan 01 00:00:00 1970 +0000)
+  |
+  x  c7d60a180d05 (6) c_G
+       rewritten as 3ab2eedae500 by test (Thu Jan 01 00:00:00 1970 +0000)
+  
+  $ hg export .
+  # HG changeset patch
+  # User test3
+  # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
+  # Node ID e7ea874afbd5c17aeee366d39a828dbcb01682ce
+  # Parent  dde94df880e97f4a1ee8c5408254b429b3d90204
+  # EXP-Topic blue
+  c_G
+  
+  diff -r dde94df880e9 -r e7ea874afbd5 ggg
+  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/ggg	Thu Jan 01 00:00:00 1970 +0000
+  @@ -0,0 +1,1 @@
+  +ggg
+  $ hg export .^
+  # HG changeset patch
+  # User test3
+  # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
+  # Node ID dde94df880e97f4a1ee8c5408254b429b3d90204
+  # Parent  f3328cd199dc389b850ca952f65a15a8e6dbc79b
+  # EXP-Topic blue
+  c_G
+  
+  diff -r f3328cd199dc -r dde94df880e9 Z
+  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/Z	Thu Jan 01 00:00:00 1970 +0000
+  @@ -0,0 +1,1 @@
+  +zzz
+
+Check that stack ouput still make sense
+
+  $ hg stack
+  ### topic: blue
+  ### target: default (branch)
+  t4$ c_I (unstable)
+  t3@ c_G (current)
+  t2: c_G
+  t1: c_D
+  t0^ c_A (base)
--- a/tests/test-topic-tutorial.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-topic-tutorial.t	Tue Nov 14 23:04:04 2017 +0100
@@ -2,18 +2,27 @@
 Topic Tutorial
 ==============
 
-.. This test file is also supposed to be able to compile as a rest file.
+This Mercurial configuration example is used for testing.
 
-
-.. Some Setup::
+.. Various setup
 
   $ . "$TESTDIR/testlib/topic_setup.sh"
+  $ cat >> $HGRCPATH << EOF
+  > [experimental]
+  > evolution=all
+  > [extensions]
+  > evolve=
+  > EOF
+
   $ hg init server
+
   $ cd server
+
   $ cat >> .hg/hgrc << EOF
   > [ui]
   > user= Shopping Master
   > EOF
+
   $ cat >> shopping << EOF
   > Spam
   > Whizzo butter
@@ -23,8 +32,10 @@
   > Blancmange
   > Salmon mousse
   > EOF
+
   $ hg commit -A -m "Shopping list"
   adding shopping
+
   $ cd ..
   $ hg clone server client
   updating to branch default
@@ -34,15 +45,71 @@
   > [ui]
   > user= Tutorial User
   > EOF
+#if docgraph-ext
+  $ . "$TESTDIR/testlib/docgraph_setup.sh" #rest-ignore
+#endif
 
 Topic branches are lightweight branches which disappear when changes are
-finalized (move to the public phase). They can help users to organise and share
+finalized (moved to the public phase). They can help users to organize and share
 their unfinished work.
 
+In this tutorial, we explain how to use topics for local development. In the first part,
+there is a central *publishing* server. Anything pushed to the central server will become public and immutable This means no unfinished work should escapes the local repository.
+
+
 Topic Basics
 ============
 
-Let's say we use Mercurial to manage our shopping list::
+Let's say we use Mercurial to manage our shopping list:
+
+  $ hg log --graph
+  @  changeset:   0:38da43f0a2ea
+     tag:         tip
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     Shopping list
+  
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      }
+#endif
+
+We are about to make some additions to this list and would like to do them
+within a topic. Creating a new topic is done using the ``topic`` command:
+
+  $ hg topics food
+  marked working directory as topic: food
+
+Much like a named branch, our topic is active but it does not contain any
+changeset yet:
+
+  $ hg topics
+   * food (0 changesets)
+
+  $ hg summary
+  parent: 0:38da43f0a2ea tip
+   Shopping list
+  branch: default
+  commit: (clean)
+  update: (current)
+  topic:  food
 
   $ hg log --graph
   @  changeset:   0:38da43f0a2ea
@@ -52,32 +119,29 @@
      summary:     Shopping list
   
 
-We are about to make some additions to this list and would like to do them
-within a topic. Creating a new topic is done using the ``topic`` command::
-
-  $ hg topic food
-
-Much like a named branch, our topic is active but it does not contain any
-changesets yet::
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      }
+#endif
 
-  $ hg topic
-   * food
-  $ hg summary
-  parent: 0:38da43f0a2ea tip
-   Shopping list
-  branch: default
-  commit: (clean)
-  update: (current)
-  topic:  food
-  $ hg log --graph
-  @  changeset:   0:38da43f0a2ea
-     tag:         tip
-     user:        test
-     date:        Thu Jan 01 00:00:00 1970 +0000
-     summary:     Shopping list
-  
-
-Our next commit will be part of the active topic::
+Our next commit will be part of the active topic:
 
   $ cat >> shopping << EOF
   > Egg
@@ -85,7 +149,10 @@
   > Vinegar
   > Oil
   > EOF
+
   $ hg commit -m "adding condiments"
+  active topic 'food' grew its first changeset
+
   $ hg log --graph --rev 'topic("food")'
   @  changeset:   1:13900241408b
   |  tag:         tip
@@ -95,14 +162,38 @@
      summary:     adding condiments
   
 
-And future commits will be part of that topic too::
+#if docgraph-ext
+  $ hg docgraph -r "topic("food")" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	1	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=1,
+      		pin=true,
+      		pos="1,1!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      }
+#endif
+
+And future commits will be part of that topic too:
 
   $ cat >> shopping << EOF
   > Bananas
   > Pear
   > Apple
   > EOF
+
   $ hg commit -m "adding fruits"
+
   $ hg log --graph --rev 'topic("food")'
   @  changeset:   2:287de11b401f
   |  tag:         tip
@@ -118,25 +209,60 @@
      summary:     adding condiments
   
 
+#if docgraph-ext
+  $ hg docgraph -r "topic("food")" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	1	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=1,
+      		pin=true,
+      		pos="1,1!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	2	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=2,
+      		pin=true,
+      		pos="1,2!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	1 -> 2	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
+
 We can get a compact view of the content of our topic using the ``stack``
-command::
+command:
 
   $ hg stack
   ### topic: food
-  ### branch: default
+  ### target: default (branch)
   t2@ adding fruits (current)
   t1: adding condiments
   t0^ Shopping list (base)
 
-The topic deactivates when we update away from it::
+The topic deactivates when we update away from it:
 
-  $ hg up default
+  $ hg update default
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg topic
-     food
+
+  $ hg topics
+     food (2 changesets)
 
 Note that ``default`` (name of the branch) now refers to the tipmost
-changeset of default without a topic::
+changeset of default without a topic:
 
   $ hg log --graph
   o  changeset:   2:287de11b401f
@@ -158,26 +284,74 @@
      summary:     Shopping list
   
 
-And updating back to the topic reactivates it::
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	1	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=1,
+      		pin=true,
+      		pos="1,1!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	0 -> 1	 [arrowhead=none,
+      		penwidth=2.0];
+      	2	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=2,
+      		pin=true,
+      		pos="1,2!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	1 -> 2	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
+And updating back to the topic reactivates it:
 
-  $ hg up food
+  $ hg update food
   switching to topic food
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg topic
-   * food
+
+  $ hg topics
+   * food (2 changesets)
 
 Updating to any changeset that is part of a topic activates the topic
-regardless of how the revision was specified::
+regardless of how the revision was specified:
 
-  $ hg up default
+  $ hg update default
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg up --rev 'desc("condiments")'
+
+  $ hg update --rev 'desc("condiments")'
   switching to topic food
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg topic
-   * food
 
-.. server side activity::
+  $ hg topics
+   * food (2 changesets)
+
+.. Server side activity:
 
   $ cd ../server/
   $ cat > shopping << EOF
@@ -191,11 +365,13 @@
   > Blancmange
   > Salmon mousse
   > EOF
+
   $ hg commit -A -m "Adding clothes"
+
   $ cd ../client
 
 The topic will also affect the rebase and the merge destinations. Let's pull
-the latest update from the main server::
+the latest update from the main server:
 
   $ hg pull
   pulling from $TESTTMP/server (glob)
@@ -204,7 +380,9 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
+  new changesets 6104862e8b84
   (run 'hg heads' to see heads)
+
   $ hg log -G
   o  changeset:   3:6104862e8b84
   |  tag:         tip
@@ -230,28 +408,88 @@
      date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     Shopping list
   
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	1	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=1,
+      		pin=true,
+      		pos="1,1!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	0 -> 1	 [arrowhead=none,
+      		penwidth=2.0];
+      	3	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=3,
+      		pin=true,
+      		pos="1,3!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 3	 [arrowhead=none,
+      		penwidth=2.0];
+      	2	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=2,
+      		pin=true,
+      		pos="1,2!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	1 -> 2	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
 
 The topic head will not be considered when merging from the new head of the
-branch::
+branch:
 
-  $ hg up default
+  $ hg update default
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
   $ hg merge
   abort: branch 'default' has one head - please merge with an explicit rev
   (run 'hg heads' to see all heads)
   [255]
 
-But the topic will see that branch head as a valid destination::
+But the topic will see that branch head as a valid destination:
 
-  $ hg up food
+  $ hg update food
   switching to topic food
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
   $ hg rebase
-  rebasing 1:13900241408b "adding condiments"
+  rebasing 1:13900241408b "adding condiments" (food)
   merging shopping
   switching to topic food
-  rebasing 2:287de11b401f "adding fruits"
+  rebasing 2:287de11b401f "adding fruits" (food)
   merging shopping
+
   $ hg log --graph
   @  changeset:   5:2d50db8b5b4c
   |  tag:         tip
@@ -277,11 +515,69 @@
      date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     Shopping list
   
-
-The topic information will disappear when we publish the changesets::
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	3	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=3,
+      		pin=true,
+      		pos="1,3!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 3	 [arrowhead=none,
+      		penwidth=2.0];
+      	4	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=4,
+      		pin=true,
+      		pos="1,4!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	3 -> 4	 [arrowhead=none,
+      		penwidth=2.0];
+      	5	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=5,
+      		pin=true,
+      		pos="1,5!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	4 -> 5	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
 
-  $ hg topic
-   * food
+The topic information will disappear when we publish the changesets:
+
+  $ hg topics
+   * food (2 changesets)
+
   $ hg push
   pushing to $TESTTMP/server (glob)
   searching for changes
@@ -290,8 +586,20 @@
   adding file changes
   added 2 changesets with 2 changes to 1 files
   2 new obsolescence markers
-  $ hg topic
-   * food
+  active topic 'food' is now empty
+
+  $ hg topics
+   * food (0 changesets)
+
+The topic still exists, and any new commit will be in the topic. But
+note that it is now devoid of any commit.
+
+  $ hg topics --list
+  ### topic: food
+  ### target: default (branch)
+  (stack is empty)
+  t0^ adding fruits (base current)
+
   $ hg log --graph
   @  changeset:   5:2d50db8b5b4c
   |  tag:         tip
@@ -315,88 +623,197 @@
      date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     Shopping list
   
-  $ hg up default
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	3	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=3,
+      		pin=true,
+      		pos="1,3!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 3	 [arrowhead=none,
+      		penwidth=2.0];
+      	4	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=4,
+      		pin=true,
+      		pos="1,4!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	3 -> 4	 [arrowhead=none,
+      		penwidth=2.0];
+      	5	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=5,
+      		pin=true,
+      		pos="1,5!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4 -> 5	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
+
+If we update to the *default* head, we will leave the topic behind,
+and since it is commit-less, it will vanish.
+
+  $ hg update default
+  clearing empty topic "food"
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
+From there, the topic has been completely forgotten.
+
+  $ hg topics
+
+
+Keep working within topics
+==========================
+
+Making sure all your new local commit are made within a topic will help your
+organise your work. It is possible to ensure this through the Mercurial
+configuration.
+
+For this tutorial, we'll add the config at the repository level:
+
+  $ cat << EOF >> .hg/hgrc
+  > [experimental]
+  > topic-mode = enforce
+  > EOF
+
+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.
+
+  $ echo sickle >> shopping
+  $ hg commit -m 'Adding sickle'
+  abort: no active topic
+  (see 'hg help -e topic.topic-mode' for details)
+  [255]
+
+Ok, let's clean this up and delve into multiple topics.
+
+  $ hg revert .
+  reverting shopping
+
+
 Working with Multiple Topics
 ============================
 
-In the above example, topics do not bring much benefit since you only have one
+In the above example, topics do not bring much benefits since you only have one
 line of development. Topics start to be more useful when you have to work on
 multiple features at the same time.
 
 We might go shopping in a hardware store in the same go, so let's add some
-tools to the shopping list within a new topic::
+tools to the shopping list within a new topic:
 
-  $ hg topic tools
+  $ hg topics tools
+  marked working directory as topic: tools
   $ echo hammer >> shopping
-  $ hg ci -m 'Adding hammer'
+  $ hg commit -m 'Adding hammer'
+  active topic 'tools' grew its first changeset
+
   $ echo saw >> shopping
-  $ hg ci -m 'Adding saw'
+  $ hg commit -m 'Adding saw'
+
   $ echo drill >> shopping
-  $ hg ci -m 'Adding drill'
+  $ hg commit -m 'Adding drill'
 
 But we are not sure 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::
+default branch and start a new topic:
 
-  $ hg up default
+  $ hg update default
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg topic drinks
+
+  $ hg topics drinks
+  marked working directory as topic: drinks
   $ echo 'apple juice' >> shopping
-  $ hg ci -m 'Adding apple juice'
+  $ hg commit -m 'Adding apple juice'
+  active topic 'drinks' grew its first changeset
+
   $ echo 'orange juice' >> shopping
-  $ hg ci -m 'Adding orange juice'
+  $ hg commit -m 'Adding orange juice'
 
-We now have two topics::
+We now have two topics:
 
-  $ hg topic
-   * drinks
-     tools
+  $ hg topics
+   * drinks (2 changesets)
+     tools  (3 changesets)
 
-The information displayed by ``hg stack`` adapts to the active topic::
+The information displayed by ``hg stack`` adapts to the active topic:
 
   $ hg stack
   ### topic: drinks
-  ### branch: default
+  ### target: default (branch)
   t2@ Adding orange juice (current)
   t1: Adding apple juice
   t0^ adding fruits (base)
-  $ hg up tools
+
+  $ hg update tools
   switching to topic tools
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
   $ hg stack
   ### topic: tools
-  ### branch: default
+  ### target: default (branch)
   t3@ Adding drill (current)
   t2: Adding saw
   t1: Adding hammer
   t0^ adding fruits (base)
 
 They are seen as independent branches by Mercurial. No rebase or merge
-between them will be attempted by default::
+between them will be attempted by default:
 
   $ hg rebase
   nothing to rebase
   [1]
 
-.. server activity::
+We simulate independant contributions to the repo with this
+activity:
 
   $ cd ../server
-  $ hg up
+  $ hg update
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ mv shopping foo
   $ echo 'Coat' > shopping
   $ cat foo >> shopping
-  $ hg ci -m 'add a coat'
+  $ hg commit -m 'add a coat'
   $ echo 'Coat' > shopping
   $ echo 'Shoes' >> shopping
   $ cat foo >> shopping
   $ rm foo
-  $ hg ci -m 'add a pair of shoes'
+  $ hg commit -m 'add a pair of shoes'
   $ cd ../client
 
-Let's see what other people did in the meantime::
+Let's discover what other people did contribute:
 
   $ hg pull
   pulling from $TESTTMP/server (glob)
@@ -405,31 +822,238 @@
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 1 files (+1 heads)
+  new changesets f2d6cacc6115:fbff9bc37a43
   (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::
+changeset on top of the latest:
+
+  $ hg log -G
+  o  changeset:   12:fbff9bc37a43
+  |  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
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     add a coat
+  |
+  | o  changeset:   10:70dfa201ed73
+  | |  topic:       drinks
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     Adding orange juice
+  | |
+  | o  changeset:   9:8dfa45bd5e0c
+  |/   topic:       drinks
+  |    parent:      5:2d50db8b5b4c
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Adding apple juice
+  |
+  | @  changeset:   8:34255b455dac
+  | |  topic:       tools
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     Adding drill
+  | |
+  | o  changeset:   7:cffff85af537
+  | |  topic:       tools
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     Adding saw
+  | |
+  | o  changeset:   6:183984ef46d1
+  |/   topic:       tools
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Adding hammer
+  |
+  o  changeset:   5:2d50db8b5b4c
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     adding fruits
+  |
+  o  changeset:   4:4011b46eeb33
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     adding condiments
+  |
+  o  changeset:   3:6104862e8b84
+  |  parent:      0:38da43f0a2ea
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding clothes
+  |
+  o  changeset:   0:38da43f0a2ea
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     Shopping list
+  
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	3	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=3,
+      		pin=true,
+      		pos="1,3!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 3	 [arrowhead=none,
+      		penwidth=2.0];
+      	4	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=4,
+      		pin=true,
+      		pos="1,4!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	3 -> 4	 [arrowhead=none,
+      		penwidth=2.0];
+      	5	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=5,
+      		pin=true,
+      		pos="1,5!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4 -> 5	 [arrowhead=none,
+      		penwidth=2.0];
+      	6	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=6,
+      		pin=true,
+      		pos="1,6!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	5 -> 6	 [arrowhead=none,
+      		penwidth=2.0];
+      	9	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=9,
+      		pin=true,
+      		pos="1,9!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	5 -> 9	 [arrowhead=none,
+      		penwidth=2.0];
+      	11	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=11,
+      		pin=true,
+      		pos="1,11!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	5 -> 11	 [arrowhead=none,
+      		penwidth=2.0];
+      	7	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=7,
+      		pin=true,
+      		pos="1,7!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	6 -> 7	 [arrowhead=none,
+      		penwidth=2.0];
+      	8	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=8,
+      		pin=true,
+      		pos="1,8!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	7 -> 8	 [arrowhead=none,
+      		penwidth=2.0];
+      	10	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=10,
+      		pin=true,
+      		pos="1,10!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	9 -> 10	 [arrowhead=none,
+      		penwidth=2.0];
+      	12	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=12,
+      		pin=true,
+      		pos="1,12!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	11 -> 12	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
 
   $ hg rebase
-  rebasing 6:183984ef46d1 "Adding hammer"
+  rebasing 6:183984ef46d1 "Adding hammer" (tools)
   merging shopping
   switching to topic tools
-  rebasing 7:cffff85af537 "Adding saw"
+  rebasing 7:cffff85af537 "Adding saw" (tools)
   merging shopping
-  rebasing 8:34255b455dac "Adding drill"
+  rebasing 8:34255b455dac "Adding drill" (tools)
   merging shopping
 
-But what about the other topic? You can use 'hg topic --verbose' to see
-information about all the topics::
+But what about the other topic? You can use 'hg topics --verbose' to see
+information about all the topics:
 
-  $ hg topic --verbose
+  $ 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 on the named
-branch of the topic. You need to merge or rebase to incorporate them.
+The "2 behind" is telling you that there are 2 new changesets over the base of the topic.
 
-Pushing that topic would create a new head, and therefore will be prevented::
+Pushing that topic would create a new head, and therefore will be prevented:
 
   $ hg push --rev drinks
   pushing to $TESTTMP/server (glob)
@@ -439,16 +1063,18 @@
   [255]
 
 
-Even after a rebase, pushing all active topics at the same time will complain
-about the multiple heads it would create on that branch::
+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
+multiple *public* heads it would create on that branch:
 
   $ hg rebase -b drinks
-  rebasing 9:8dfa45bd5e0c "Adding apple juice"
+  rebasing 9:8dfa45bd5e0c "Adding apple juice" (drinks)
   merging shopping
   switching to topic drinks
-  rebasing 10:70dfa201ed73 "Adding orange juice"
+  rebasing 10:70dfa201ed73 "Adding orange juice" (drinks)
   merging shopping
   switching to topic tools
+
   $ hg push
   pushing to $TESTTMP/server (glob)
   searching for changes
@@ -457,7 +1083,7 @@
   [255]
 
 Publishing only one of them is allowed (as long as it does not create a new
-branch head as we just saw in the previous case)::
+branch head as we just saw in the previous case):
 
   $ hg push -r drinks
   pushing to $TESTTMP/server (glob)
@@ -469,15 +1095,793 @@
   2 new obsolescence markers
 
 The published topic has now disappeared, and the other is now marked as
-"behind"::
+"behind":
+
+  $ hg topics --verbose
+   * tools (on branch: default, 3 changesets, 2 behind)
 
-  $ hg topic --verbose
+  $ hg stack
+  ### topic: tools
+  ### target: default (branch), 2 behind
+  t3@ Adding drill (current)
+  t2: Adding saw
+  t1: Adding hammer
+  t0^ add a pair of shoes (base)
+
+Working Within Your Stack
+===========================
+
+Navigating within your stack
+----------------------------
+
+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)
+
   $ hg stack
   ### topic: tools
-  ### branch: default, 2 behind
+  ### target: default (branch), 2 behind
+  t3@ Adding drill (current)
+  t2: Adding saw
+  t1: Adding hammer
+  t0^ add a pair of shoes (base)
+
+You can navigate in your current stack with `previous` and `next`.
+
+`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
+  [14] Adding saw
+
+  $ hg stack
+  ### topic: tools
+  ### target: default (branch), 2 behind
+  t3: Adding drill
+  t2@ Adding saw (current)
+  t1: Adding hammer
+  t0^ add a pair of shoes (base)
+
+`next` will move you forward to the topic head.
+
+  $ hg next
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  [15] Adding drill
+
+  $ hg stack
+  ### topic: tools
+  ### target: default (branch), 2 behind
   t3@ Adding drill (current)
   t2: Adding saw
   t1: Adding hammer
   t0^ add a pair of shoes (base)
 
+You can also directly jump to a changeset within your stack with the revset `t#`.
+
+  $ hg update t1
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg stack
+  ### topic: tools
+  ### target: default (branch), 2 behind
+  t3: Adding drill
+  t2: Adding saw
+  t1@ Adding hammer (current)
+  t0^ add a pair of shoes (base)
+
+Editing your work mid-stack
+---------------------------
+
+It's easy to edit your work inside your stack:
+
+  $ hg stack
+  ### topic: tools
+  ### target: default (branch), 2 behind
+  t3: Adding drill
+  t2: Adding saw
+  t1@ Adding hammer (current)
+  t0^ add a pair of shoes (base)
+
+  $ hg amend -m "Adding hammer to the shopping list"
+  2 new orphan changesets
+
+Understanding the current situation with hg log is not so easy, because
+it shows too many things:
+
+  $ hg log -G -r "t0::"
+  @  changeset:   18:b7509bd417f8
+  |  tag:         tip
+  |  topic:       tools
+  |  parent:      12:fbff9bc37a43
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding hammer to the shopping list
+  |
+  | o  changeset:   17:4cd7c1591a67
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     Adding orange juice
+  | |
+  | o  changeset:   16:20759cb47ff8
+  |/   parent:      12:fbff9bc37a43
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Adding apple juice
+  |
+  | o  changeset:   15:bb1e6254f532
+  | |  topic:       tools
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  instability: orphan
+  | |  summary:     Adding drill
+  | |
+  | o  changeset:   14:d4f97f32f8a1
+  | |  topic:       tools
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  instability: orphan
+  | |  summary:     Adding saw
+  | |
+  | x  changeset:   13:a8ab3599d53d
+  |/   topic:       tools
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    obsolete:    reworded using amend as 18:b7509bd417f8
+  |    summary:     Adding hammer
+  |
+  o  changeset:   12:fbff9bc37a43
+  |  user:        test
+  ~  date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     add a pair of shoes
+  
+
+#if docgraph-ext
+  $ hg docgraph -r "t0::" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	12	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=12,
+      		pin=true,
+      		pos="1,12!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	13	 [fillcolor="#DFDFFF",
+      		fixedsize=true,
+      		group=default_alt,
+      		height=0.5,
+      		label=13,
+      		pin=true,
+      		pos="2,13!",
+      		shape=pentagon,
+      		style="dotted, filled",
+      		width=0.5];
+      	12 -> 13	 [arrowhead=none,
+      		penwidth=2.0];
+      	18	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=18,
+      		pin=true,
+      		pos="1,18!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	12 -> 18	 [arrowhead=none,
+      		penwidth=2.0];
+      	16	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=16,
+      		pin=true,
+      		pos="1,16!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	12 -> 16	 [arrowhead=none,
+      		penwidth=2.0];
+      	13 -> 18	 [arrowhead=none,
+      		minlen=0,
+      		penwidth=2.0,
+      		style=dashed];
+      	14	 [fillcolor="#FF4F4F",
+      		fixedsize=true,
+      		group=default_alt,
+      		height=0.5,
+      		label=14,
+      		pin=true,
+      		pos="2,14!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	13 -> 14	 [arrowhead=none,
+      		penwidth=2.0];
+      	15	 [fillcolor="#FF4F4F",
+      		fixedsize=true,
+      		group=default_alt,
+      		height=0.5,
+      		label=15,
+      		pin=true,
+      		pos="2,15!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	14 -> 15	 [arrowhead=none,
+      		penwidth=2.0];
+      	17	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=17,
+      		pin=true,
+      		pos="1,17!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	16 -> 17	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
+
+Fortunately stack shows you a better visualization:
+
+  $ hg stack
+  ### topic: tools
+  ### target: default (branch), 2 behind
+  t3$ Adding drill (unstable)
+  t2$ Adding saw (unstable)
+  t1@ Adding hammer to the shopping list (current)
+  t0^ 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 `t2` and `t3` over the new `t1` without having
+to do that rebase by hand.:
+
+  $ hg next --evolve
+  move:[14] Adding saw
+  atop:[18] Adding hammer to the shopping list
+  working directory now at d5c51ee5762a
+
+  $ hg stack
+  ### topic: tools
+  ### target: default (branch), 2 behind
+  t3$ Adding drill (unstable)
+  t2@ Adding saw (current)
+  t1: Adding hammer to the shopping list
+  t0^ add a pair of shoes (base)
+
+One more to go:
+
+  $ hg next --evolve
+  move:[15] Adding drill
+  atop:[19] Adding saw
+  working directory now at bae3758e46bf
+
+  $ hg stack
+  ### topic: tools
+  ### target: default (branch), 2 behind
+  t3@ Adding drill (current)
+  t2: Adding saw
+  t1: Adding hammer to the shopping list
+  t0^ add a pair of shoes (base)
+
+Let's take a look at `hg log` once again:
+
+  $ hg log -G -r "t0::"
+  @  changeset:   20:bae3758e46bf
+  |  tag:         tip
+  |  topic:       tools
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding drill
+  |
+  o  changeset:   19:d5c51ee5762a
+  |  topic:       tools
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding saw
+  |
+  o  changeset:   18:b7509bd417f8
+  |  topic:       tools
+  |  parent:      12:fbff9bc37a43
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding hammer to the shopping list
+  |
+  | o  changeset:   17:4cd7c1591a67
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     Adding orange juice
+  | |
+  | o  changeset:   16:20759cb47ff8
+  |/   parent:      12:fbff9bc37a43
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Adding apple juice
+  |
+  o  changeset:   12:fbff9bc37a43
+  |  user:        test
+  ~  date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     add a pair of shoes
+  
+
+#if docgraph-ext
+  $ hg docgraph -r "t0::" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	12	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=12,
+      		pin=true,
+      		pos="1,12!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	16	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=16,
+      		pin=true,
+      		pos="1,16!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	12 -> 16	 [arrowhead=none,
+      		penwidth=2.0];
+      	18	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=18,
+      		pin=true,
+      		pos="1,18!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	12 -> 18	 [arrowhead=none,
+      		penwidth=2.0];
+      	17	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=17,
+      		pin=true,
+      		pos="1,17!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	16 -> 17	 [arrowhead=none,
+      		penwidth=2.0];
+      	19	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=19,
+      		pin=true,
+      		pos="1,19!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	18 -> 19	 [arrowhead=none,
+      		penwidth=2.0];
+      	20	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=20,
+      		pin=true,
+      		pos="1,20!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	19 -> 20	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
+Multi-headed stack
+------------------
+
+Stack is also very helpful when you have a multi-headed stack:
+
+  $ hg up t1
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ echo "nails" > new_shopping
+  $ cat shopping >> new_shopping
+  $ mv new_shopping shopping
+
+  $ hg commit -m 'Adding nails'
+
+  $ hg stack
+  ### topic: tools (2 heads)
+  ### target: default (branch), 2 behind
+  t4: Adding drill
+  t3: Adding saw
+  t1^ Adding hammer to the shopping list (base)
+  t2@ Adding nails (current)
+  t1: Adding hammer to the shopping list
+  t0^ add a pair of shoes (base)
+
+Solving this situation is easy with a topic: use merge or rebase.
+Merge within a multi-headed stack will use the other topic head as
+destination if the topic has two heads. But rebasing will yield a
+completely linear history so it's what we will do.
+
+  $ hg log -G
+  @  changeset:   21:f936c6da9d61
+  |  tag:         tip
+  |  topic:       tools
+  |  parent:      18:b7509bd417f8
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding nails
+  |
+  | o  changeset:   20:bae3758e46bf
+  | |  topic:       tools
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     Adding drill
+  | |
+  | o  changeset:   19:d5c51ee5762a
+  |/   topic:       tools
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Adding saw
+  |
+  o  changeset:   18:b7509bd417f8
+  |  topic:       tools
+  |  parent:      12:fbff9bc37a43
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding hammer to the shopping list
+  |
+  | o  changeset:   17:4cd7c1591a67
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     Adding orange juice
+  | |
+  | o  changeset:   16:20759cb47ff8
+  |/   parent:      12:fbff9bc37a43
+  |    user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     Adding apple juice
+  |
+  o  changeset:   12:fbff9bc37a43
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     add a pair of shoes
+  |
+  o  changeset:   11:f2d6cacc6115
+  |  parent:      5:2d50db8b5b4c
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     add a coat
+  |
+  o  changeset:   5:2d50db8b5b4c
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     adding fruits
+  |
+  o  changeset:   4:4011b46eeb33
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     adding condiments
+  |
+  o  changeset:   3:6104862e8b84
+  |  parent:      0:38da43f0a2ea
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     Adding clothes
+  |
+  o  changeset:   0:38da43f0a2ea
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     Shopping list
+  
+
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	3	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=3,
+      		pin=true,
+      		pos="1,3!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 3	 [arrowhead=none,
+      		penwidth=2.0];
+      	4	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=4,
+      		pin=true,
+      		pos="1,4!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	3 -> 4	 [arrowhead=none,
+      		penwidth=2.0];
+      	5	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=5,
+      		pin=true,
+      		pos="1,5!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4 -> 5	 [arrowhead=none,
+      		penwidth=2.0];
+      	11	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=11,
+      		pin=true,
+      		pos="1,11!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	5 -> 11	 [arrowhead=none,
+      		penwidth=2.0];
+      	12	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=12,
+      		pin=true,
+      		pos="1,12!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	11 -> 12	 [arrowhead=none,
+      		penwidth=2.0];
+      	16	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=16,
+      		pin=true,
+      		pos="1,16!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	12 -> 16	 [arrowhead=none,
+      		penwidth=2.0];
+      	18	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=18,
+      		pin=true,
+      		pos="1,18!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	12 -> 18	 [arrowhead=none,
+      		penwidth=2.0];
+      	17	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=17,
+      		pin=true,
+      		pos="1,17!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	16 -> 17	 [arrowhead=none,
+      		penwidth=2.0];
+      	19	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=19,
+      		pin=true,
+      		pos="1,19!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	18 -> 19	 [arrowhead=none,
+      		penwidth=2.0];
+      	21	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=21,
+      		pin=true,
+      		pos="1,21!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	18 -> 21	 [arrowhead=none,
+      		penwidth=2.0];
+      	20	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=20,
+      		pin=true,
+      		pos="1,20!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	19 -> 20	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
+
+  $ hg up t4
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg rebase
+  rebasing 19:d5c51ee5762a "Adding saw" (tools)
+  merging shopping
+  rebasing 20:bae3758e46bf "Adding drill" (tools)
+  merging shopping
+
+  $ hg stack
+  ### topic: tools
+  ### target: default (branch), 2 behind
+  t4@ Adding drill (current)
+  t3: Adding saw
+  t2: Adding nails
+  t1: Adding hammer to the shopping list
+  t0^ add a pair of shoes (base)
+
+Collaborating through a non-publishing server
+=============================================
+
+.. setup:
+
+.. Let's create a non-publishing server:
+
+  $ cd ..
+
+  $ hg clone server non-publishing-server
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ cd non-publishing-server
+  $ cat >> .hg/hgrc << EOF
+  > [phases]
+  > publish = false
+  > EOF
+
+.. And another client:
+
+  $ cd ..
+
+  $ hg clone server other-client
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ cd client
+
+We can now share these draft changesets:
+
+  $ hg push ../non-publishing-server -r tools
+  pushing to ../non-publishing-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 4 changesets with 4 changes to 1 files (+1 heads)
+  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
+complain about them.
+
+From another client, we will get them with their topic:
+
+  $ cd ../other-client
+
+  $ hg pull ../non-publishing-server
+  pulling from ../non-publishing-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 4 changesets with 4 changes to 1 files (+1 heads)
+  8 new obsolescence markers
+  new changesets b7509bd417f8:2d084ac00115
+  (run 'hg heads' to see heads)
+
+  $ hg topics --verbose
+     tools (on branch: default, 4 changesets, 2 behind)
+
+  $ hg up tools
+  switching to topic tools
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg stack
+  ### topic: tools
+  ### target: default (branch), 2 behind
+  t4@ Adding drill (current)
+  t3: Adding saw
+  t2: Adding nails
+  t1: Adding hammer to the shopping list
+  t0^ add a pair of shoes (base)
+
+We can also add new changesets and share them:
+
+  $ echo screws >> shopping
+
+  $ hg commit -A -m "Adding screws"
+
+  $ hg push ../non-publishing-server
+  pushing to ../non-publishing-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+
+And retrieve them on the first client:
+
+  $ cd ../client
+
+  $ hg pull ../non-publishing-server
+  pulling from ../non-publishing-server
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  new changesets 0d409663a1fd
+  (run 'hg update' to get a working copy)
+
+  $ hg update
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg stack
+  ### topic: tools
+  ### target: default (branch), 2 behind
+  t5@ Adding screws (current)
+  t4: Adding drill
+  t3: Adding saw
+  t2: Adding nails
+  t1: Adding hammer to the shopping list
+  t0^ add a pair of shoes (base)
--- a/tests/test-topic.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-topic.t	Tue Nov 14 23:04:04 2017 +0100
@@ -19,34 +19,46 @@
   see all topics.
   
       Clear topic on existing topiced revisions:
-          'hg topic --rev <related revset> --clear'
+  
+        hg topics --rev <related revset> --clear
   
       Change topic on some revisions:
-          'hg topic <newtopicname> --rev <related revset>'
+  
+        hg topics <newtopicname> --rev <related revset>
   
       Clear current topic:
-          'hg topic --clear'
+  
+        hg topics --clear
   
       Set current topic:
-          'hg topic <topicname>'
+  
+        hg topics <topicname>
   
       List of topics:
-          'hg topics'
+  
+        hg topics
   
-      List of topics with their last touched time sorted according to it:
-          'hg topic --age'
+      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
   
       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 --verbose version of this command display various information on the
       state of each topic.
   
-  options:
+  options ([+] can be repeated):
   
-      --clear   clear active topic if any
-   -r --rev REV revset of existing revisions
-   -l --list    show the stack of changeset in the topic
-      --age     show when you last touched the topics
+      --clear       clear active topic if any
+   -r --rev REV [+] revset of existing revisions
+   -l --list        show the stack of changeset in the topic
+      --age         show when you last touched the topics
+      --current     display the current topic only
   
   (some details hidden, use --verbose to show complete help)
   $ hg topics
@@ -72,6 +84,36 @@
 
 Still no topics
   $ hg topics
+  $ hg topics --current
+  no active topic
+  [1]
+  $ hg topics --current somerandomtopic
+  abort: cannot use --current when setting a topic
+  [255]
+  $ hg topics --current --clear
+  abort: cannot use --current and --clear
+  [255]
+  $ hg topics --clear somerandomtopic
+  abort: cannot use --clear when setting a topic
+  [255]
+
+Trying some invalid topicnames
+
+  $ hg topic '.'
+  abort: the name '.' is reserved
+  [255]
+  $ hg topic null
+  abort: the name 'null' is reserved
+  [255]
+  $ hg topic tip
+  abort: the name 'tip' is reserved
+  [255]
+  $ hg topic 12345
+  abort: cannot use an integer as a name
+  [255]
+  $ hg topic '   '
+  abort: topic name cannot consist entirely of whitespaces
+  [255]
 
 Test commit flag and help text
 
@@ -90,28 +132,44 @@
   [255]
   $ hg revert alpha
   $ hg topic
-   * topicflag
+   * topicflag (0 changesets)
 
 Make a topic
+
   $ hg topic narf
   $ hg topics
-   * narf
+   * narf (0 changesets)
+  $ hg topics -v
+   * narf (on branch: default, 0 changesets)
+  $ hg stack
+  ### topic: narf
+  ### target: default (branch)
+  (stack is empty)
+  t0^ Add file delta (base current)
+
+Add commits to topic
+
   $ echo topic work >> alpha
   $ hg ci -m 'start on narf'
+  active topic 'narf' grew its first changeset
   $ hg co .^
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg topic fran
+  marked working directory as topic: fran
   $ hg topics
-   * fran
-     narf
+   * fran (0 changesets)
+     narf (1 changesets)
+  $ hg topics --current
+  fran
   $ echo >> fran work >> beta
   $ hg ci -m 'start on fran'
+  active topic 'fran' grew its first changeset
   $ hg co narf
   switching to topic narf
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg topic
-     fran
-   * narf
+     fran (1 changesets)
+   * narf (1 changesets)
   $ hg log -r . -T '{topics}\n'
   narf
   $ echo 'narf!!!' >> alpha
@@ -260,7 +318,9 @@
   $ hg topic
   $ echo what >> alpha
   $ hg topic query
+  marked working directory as topic: query
   $ hg ci -m 'what is narf, pinky?'
+  active topic 'query' grew its first changeset
   $ hg log -Gl2
   @  changeset:   5:c01515cfc331
   |  tag:         tip
@@ -274,6 +334,7 @@
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     start on narf
   |
+
   $ hg push -f ../pinky -r query
   pushing to ../pinky
   searching for changes
@@ -281,6 +342,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
+
   $ hg -R ../pinky log -Gl 4
   o  changeset:   7:c01515cfc331
   |  tag:         tip
@@ -309,8 +371,9 @@
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    summary:     start on narf
   |
+
   $ hg topics
-   * query
+   * query (1 changesets)
   $ cd ../pinky
   $ hg co query
   switching to topic query
@@ -329,9 +392,9 @@
   $ hg topic narf
   $ hg ci -m 'Finish narf'
   $ hg topics
-     fran
-   * narf
-     query
+     fran  (1 changesets)
+   * narf  (2 changesets)
+     query (2 changesets)
   $ hg debugnamecomplete # branch:topic here is a buggy side effect
   default
   default:fran
@@ -342,13 +405,14 @@
   query
   tip
   $ hg phase --public narf
+  active topic 'narf' is now empty
 
 POSSIBLE BUG: narf topic stays alive even though we just made all
 narf commits public:
 
   $ hg topics
-     fran
-   * narf
+     fran (1 changesets)
+   * narf (0 changesets)
   $ hg log -Gl 6
   @    changeset:   9:ae074045b7a7
   |\   tag:         tip
@@ -387,9 +451,10 @@
   |    date:        Thu Jan 01 00:00:00 1970 +0000
   |    summary:     start on narf
   |
+
   $ cd ../brain
   $ hg topics
-   * query
+   * query (1 changesets)
   $ hg pull ../pinky -r narf
   pulling from ../pinky
   abort: unknown revision 'narf'!
@@ -401,9 +466,11 @@
   adding manifests
   adding file changes
   added 3 changesets with 3 changes to 1 files
+  new changesets 7c34953036d6:ae074045b7a7
+  active topic 'query' is now empty
   (run 'hg update' to get a working copy)
   $ hg topics
-   * query
+   * query (0 changesets)
 
 We can pull in the draft-phase change and we get the new topic
 
@@ -414,10 +481,11 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
+  new changesets 0469d521db49
   (run 'hg heads' to see heads)
   $ hg topics
-     fran
-   * query
+     fran  (1 changesets)
+   * query (0 changesets)
   $ hg log -Gr 'draft()'
   o  changeset:   9:0469d521db49
   |  tag:         tip
@@ -432,12 +500,9 @@
 disappear:
 
   $ hg topics --clear
+  clearing empty topic "query"
   $ hg topics
-     fran
-
---clear when we don't have an active topic isn't an error:
-
-  $ hg topics --clear
+     fran (1 changesets)
 
 Topic revset
   $ hg log -r 'topic()' -G
@@ -524,7 +589,7 @@
 
 Match current topic:
   $ hg topic
-     fran
+     fran (1 changesets)
   $ hg log -r 'topic(.)'
 (no output is expected)
   $ hg co fran
@@ -542,7 +607,7 @@
 
 Deactivate the topic.
   $ hg topics
-   * fran
+   * fran (1 changesets)
   $ hg topics --clear
   $ echo fran? >> beta
   $ hg ci -m 'fran?'
@@ -561,272 +626,36 @@
   |  date:        Thu Jan 01 00:00:00 1970 +0000
   |  summary:     start on fran
   |
+
   $ hg topics
-     fran
-Changing topic fails if we don't give a topic
-  $ hg topic --rev 9
-  abort: changing topic requires a topic name or --clear
-  [255]
-
-Can't change topic of a public change
-  $ hg topic --rev 1:: --clear
-  abort: can't change topic of a public change
-  [255]
-
-Can clear topics
-  $ hg topic --rev 9 --clear
-  changed topic on 1 changes
-  $ hg log -Gr 'draft() and not obsolete()'
-  o  changeset:   11:0beca5ab56c3
-  |  tag:         tip
-  |  parent:      3:a53952faf762
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     start on fran
-  |
-  | @  changeset:   10:4073470c35e1
-  | |  user:        test
-  | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  trouble:     unstable
-  | |  summary:     fran?
-  | |
-
-Normally you'd do this with evolve, but we'll use rebase to avoid
-bonus deps in the testsuite.
-
-  $ hg rebase -d tip -s .
-  rebasing 10:4073470c35e1 "fran?"
-
-Can add a topic to an existing change
-  $ hg topic
-  $ hg sum
-  parent: 12:18b70b8de1f0 tip
-   fran?
-  branch: default
-  commit: (clean)
-  update: 5 new changesets, 2 branch heads (merge)
-  phases: 2 draft
-  $ hg topic --rev 11 wat
-  changed topic on 1 changes
-  $ hg log -r .
-  changeset:   12:18b70b8de1f0
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  trouble:     unstable
-  summary:     fran?
-  
-  $ hg sum
-  parent: 12:18b70b8de1f0  (unstable)
-   fran?
-  branch: default
-  commit: (clean)
-  update: 5 new changesets, 2 branch heads (merge)
-  phases: 3 draft
-  unstable: 1 changesets
-  $ hg topic
-     wat
-  $ hg log -Gr 'draft() and not obsolete()'
-  o  changeset:   13:686a642006db
-  |  tag:         tip
-  |  topic:       wat
-  |  parent:      3:a53952faf762
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     start on fran
-  |
-  | @  changeset:   12:18b70b8de1f0
-  | |  user:        test
-  | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  trouble:     unstable
-  | |  summary:     fran?
-  | |
-
-Normally you'd do this with evolve, but we'll use rebase to avoid
-bonus deps in the testsuite.
-
-  $ hg topic
-     wat
-  $ hg rebase -d tip -s .
-  rebasing 12:18b70b8de1f0 "fran?"
-  switching to topic wat
-  $ hg topic
-     wat
-
-  $ hg log -Gr 'draft()'
-  @  changeset:   14:45358f7a5892
-  |  tag:         tip
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     fran?
-  |
-  o  changeset:   13:686a642006db
-  |  topic:       wat
-  |  parent:      3:a53952faf762
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     start on fran
-  |
-
-Amend a topic
-
-  $ hg topic watwat
-  $ hg ci --amend
-  $ hg log -Gr 'draft()'
-  @  changeset:   16:6c40a4c21bbe
-  |  tag:         tip
-  |  topic:       watwat
-  |  parent:      13:686a642006db
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     fran?
-  |
-  o  changeset:   13:686a642006db
-  |  topic:       wat
-  |  parent:      3:a53952faf762
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     start on fran
-  |
-
-Clear and amend:
-
-  $ hg topic --clear
-  $ hg ci --amend
-  $ hg log -r .
-  changeset:   18:0f9cd5070654
-  tag:         tip
-  parent:      13:686a642006db
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     fran?
-  
-Reading the same topic with topic --rev should work:
-  $ hg topic --rev . watwat
-  switching to topic watwat
-  changed topic on 1 changes
-
-Testing issue5441
-  $ hg co 19
-  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg log -Gr 'draft()'
-  @  changeset:   19:980a0f608481
-  |  tag:         tip
-  |  topic:       watwat
-  |  parent:      13:686a642006db
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     fran?
-  |
-  o  changeset:   13:686a642006db
-  |  topic:       wat
-  |  parent:      3:a53952faf762
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     start on fran
-  |
-
-  $ hg topics --rev '13::19' changewat
-  switching to topic changewat
-  changed topic on 2 changes
-  $ hg log -Gr 'draft()'
-  @  changeset:   21:56c83be6105f
-  |  tag:         tip
-  |  topic:       changewat
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     fran?
-  |
-  o  changeset:   20:ceba5be9d56f
-  |  topic:       changewat
-  |  parent:      3:a53952faf762
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     start on fran
-  |
-
-Case with branching:
-
-  $ hg up changewat
-  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg up t1
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ echo gamma >> gamma
-  $ hg ci -m gamma
-  $ hg log -Gr 'draft()'
-  @  changeset:   22:0d3d805542b4
-  |  tag:         tip
-  |  topic:       changewat
-  |  parent:      20:ceba5be9d56f
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     gamma
-  |
-  | o  changeset:   21:56c83be6105f
-  |/   topic:       changewat
-  |    user:        test
-  |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    summary:     fran?
-  |
-  o  changeset:   20:ceba5be9d56f
-  |  topic:       changewat
-  |  parent:      3:a53952faf762
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     start on fran
-  |
-  $ hg topics --rev 't1::' changewut
-  switching to topic changewut
-  changed topic on 3 changes
-  $ hg log -Gr 'draft()'
-  @  changeset:   25:729ed5717393
-  |  tag:         tip
-  |  topic:       changewut
-  |  parent:      23:62e49f09f883
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     gamma
-  |
-  | o  changeset:   24:369c6e2e5474
-  |/   topic:       changewut
-  |    user:        test
-  |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    summary:     fran?
-  |
-  o  changeset:   23:62e49f09f883
-  |  topic:       changewut
-  |  parent:      3:a53952faf762
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     start on fran
-  |
+     fran (1 changesets)
 
 Testing for updating to t0
 ==========================
 
+  $ hg up fran
+  switching to topic fran
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg stack
-  ### topic: changewut (2 heads)
-  ### branch: default, 5 behind
-  t3: fran?
-  t1^ start on fran (base)
-  t2@ gamma (current)
-  t1: start on fran
-  t0^ Add file delta (base)
-  $ hg up t0
-  preserving the current topic 'changewut'
-  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg topic
-   * changewut
-  $ hg stack
-  ### topic: changewut (2 heads)
-  ### branch: default, 5 behind
-  t3: fran?
-  t1^ start on fran (base)
-  t2: gamma
-  t1: start on fran
+  ### topic: fran
+  ### target: default (branch), ambigious rebase destination - branch 'default' has 2 heads
+  t1@ start on fran (current)
   t0^ Add file delta (base)
 
+  $ hg up t0
+  preserving the current topic 'fran'
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg topic
+   * fran (1 changesets)
+  $ hg stack
+  ### topic: fran
+  ### target: default (branch), ambigious rebase destination - branch 'default' has 2 heads
+  t1: start on fran
+  t0^ Add file delta (base current)
+
   $ hg topics --age
-   * changewut (1970-01-01)
+   * fran (1970-01-01 by test)
 
   $ cd ..
 
@@ -841,22 +670,22 @@
   > EOF
   $ cat <<EOF >> $HGRCPATH
   > [experimental]
-  > enforce-topic = yes
+  > topic-mode = enforce
   > EOF
   $ touch a b c d
   $ hg add a
   $ hg ci -m "Added a"
   abort: no active topic
-  (set a current topic or use '--config experimental.enforce-topic=no' to commit without a topic)
+  (see 'hg help -e topic.topic-mode' for details)
   [255]
 
 (same test, checking we abort before the editor)
 
   $ EDITOR=cat hg ci -m "Added a" --edit
   abort: no active topic
-  (set a current topic or use '--config experimental.enforce-topic=no' to commit without a topic)
+  (see 'hg help -e topic.topic-mode' for details)
   [255]
-  $ hg ci -m "added a" --config experimental.enforce-topic=no
+  $ hg ci -m "added a" --config experimental.topic-mode=off
   $ hg log
   changeset:   0:a154386e50d1
   tag:         tip
@@ -864,50 +693,64 @@
   date:        Thu Jan 01 00:00:00 1970 +0000
   summary:     added a
   
+
+Testing the --age flag for `hg topics`
+======================================
+
   $ hg topic topic1970 --rev 0
   switching to topic topic1970
   changed topic on 1 changes
+
   $ hg add b
   $ hg topic topic1990
-  $ hg ci -m "Added b" --config devel.default-date="631152000 0"
+  $ hg ci -m "Added b" --config devel.default-date="631152000 0" --user "foo"
+  active topic 'topic1990' grew its first changeset
   $ hg add c
   $ hg topic topic2010
-  $ hg ci -m "Added c" --config devel.default-date="1262304000 0"
-  $ hg log
-  changeset:   3:9048b194797d
-  tag:         tip
-  topic:       topic2010
-  user:        test
-  date:        Fri Jan 01 00:00:00 2010 +0000
-  summary:     Added c
-  
-  changeset:   2:186d493c7f8d
-  topic:       topic1990
-  user:        test
-  date:        Mon Jan 01 00:00:00 1990 +0000
-  summary:     Added b
-  
-  changeset:   1:e5a30a141954
-  topic:       topic1970
-  parent:      -1:000000000000
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     added a
+  $ hg ci -m "Added c" --config devel.default-date="1262304000 0" --user "bar"
+  active topic 'topic2010' grew its first changeset
+
+  $ hg log -G
+  @  changeset:   3:76b16af75125
+  |  tag:         tip
+  |  topic:       topic2010
+  |  user:        bar
+  |  date:        Fri Jan 01 00:00:00 2010 +0000
+  |  summary:     Added c
+  |
+  o  changeset:   2:bba5bde53608
+  |  topic:       topic1990
+  |  user:        foo
+  |  date:        Mon Jan 01 00:00:00 1990 +0000
+  |  summary:     Added b
+  |
+  o  changeset:   1:e5a30a141954
+     topic:       topic1970
+     parent:      -1:000000000000
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     added a
   
   $ hg topics
-     topic1970
-     topic1990
-   * topic2010
+     topic1970 (1 changesets)
+     topic1990 (1 changesets)
+   * topic2010 (1 changesets)
+
   $ hg topics --age
-   * topic2010 (2010-01-01)
-     topic1990 (1990-01-01)
-     topic1970 (1970-01-01)
+   * topic2010 (2010-01-01 by bar)
+     topic1990 (1990-01-01 by foo)
+     topic1970 (1970-01-01 by test)
+
   $ hg up topic1970
   switching to topic topic1970
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+
   $ hg topics --age
-     topic2010 (2010-01-01)
-     topic1990 (1990-01-01)
-   * topic1970 (1970-01-01)
+     topic2010 (2010-01-01 by bar)
+     topic1990 (1990-01-01 by foo)
+   * topic1970 (1970-01-01 by test)
 
+  $ hg topics --age random
+  abort: cannot use --age while setting a topic
+  [255]
   $ cd ..
--- a/tests/test-touch.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-touch.t	Tue Nov 14 23:04:04 2017 +0100
@@ -18,7 +18,7 @@
 Basic usage
 
   $ hg log -G
-  @  0:e93df3427f45 a
+  @  0:[0-9a-f]{12} a (re)
   
   $ hg touch .
   $ hg log -G
@@ -36,7 +36,7 @@
   working directory parent is obsolete! (*) (glob)
   (use 'hg evolve' to update to its successor: *) (glob)
   $ hg log -G
-  o  3:[0-9a-f]{12} ab (re)
+  o  2:[0-9a-f]{12} ab (re)
   
   @  1:[0-9a-f]{12} a (re)
   
@@ -44,22 +44,24 @@
   [1] a
   reviving this changeset will create divergence unless you make a duplicate.
   (a)llow divergence or (d)uplicate the changeset?  a
-  2 new divergent changesets
+  2 new content-divergent changesets
   $ hg log -G
-  @  4:[0-9a-f]{12} a (re)
+  @  3:[0-9a-f]{12} a (re)
   
-  o  3:[0-9a-f]{12} ab (re)
+  o  2:[0-9a-f]{12} ab (re)
   
   $ hg prune 3
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  working directory now at 000000000000
   1 changesets pruned
 
 Duplicate
 
   $ hg touch --duplicate .
   $ hg log -G
-  @  5:[0-9a-f]{12} a (re)
+  @  4:[0-9a-f]{12} (re)
   
-  o  4:[0-9a-f]{12} a (re)
+  o  2:[0-9a-f]{12} ab (re)
   
 
 Multiple touch
@@ -71,23 +73,23 @@
   $ hg add d
   $ hg commit -m d
   $ hg log -G
-  @  7:[0-9a-f]{12} d (re)
+  @  6:[0-9a-f]{12} d (re)
   |
-  o  6:[0-9a-f]{12} c (re)
+  o  5:[0-9a-f]{12} c (re)
   |
-  o  5:[0-9a-f]{12} a (re)
+  o  4:[0-9a-f]{12} (re)
   
-  o  4:[0-9a-f]{12} a (re)
+  o  2:[0-9a-f]{12} ab (re)
   
-  $ hg touch 6:7
+  $ hg touch .^:.
   $ hg log -G
-  @  9:[0-9a-f]{12} d (re)
+  @  8:[0-9a-f]{12} d (re)
   |
-  o  8:[0-9a-f]{12} c (re)
+  o  7:[0-9a-f]{12} c (re)
   |
-  o  5:[0-9a-f]{12} a (re)
+  o  4:[0-9a-f]{12} (re)
   
-  o  4:[0-9a-f]{12} a (re)
+  o  2:[0-9a-f]{12} ab (re)
   
 
 check move data kept after rebase on touch:
@@ -105,10 +107,36 @@
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
 
   $ hg touch
-  1 new unstable changesets
+  1 new orphan changesets
 
-  $ hg rebase -s 11 -d 12
-  rebasing 11:* "move" (glob)
+  $ hg log -G --hidden
+  @  11:[0-9a-f]{12} gna1 (re)
+  |
+  | o  10:[0-9a-f]{12} move (re)
+  | |
+  | x  9:[0-9a-f]{12} gna1 (re)
+  |/
+  o  8:[0-9a-f]{12} d (re)
+  |
+  o  7:[0-9a-f]{12} c (re)
+  |
+  | x  6:[0-9a-f]{12} d (re)
+  | |
+  | x  5:[0-9a-f]{12} c (re)
+  |/
+  o  4:[0-9a-f]{12} (re)
+  
+  x  3:[0-9a-f]{12} a (re)
+  
+  o  2:[0-9a-f]{12} ab (re)
+  
+  x  1:[0-9a-f]{12} a (re)
+  
+  x  0:[0-9a-f]{12} a (re)
+  
+
+  $ hg rebase -s 10 -d 11
+  rebasing 10:[0-9a-f]{12} "move" (re)
   $ hg st -C --change=tip
   A gna2
     gna1
@@ -116,12 +144,12 @@
 
 check that the --duplicate option does not create divergence
 
-  $ hg touch --duplicate 11 --hidden
-  1 new unstable changesets
+  $ hg touch --duplicate 10 --hidden
+  1 new orphan changesets
 
 check that reviving a changeset with no successor does not show the prompt
 
-  $ hg prune 14
+  $ hg prune 13
   1 changesets pruned
-  $ hg touch 14 --hidden
-  1 new unstable changesets
+  $ hg touch 13 --hidden
+  1 new orphan changesets
--- a/tests/test-tutorial.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-tutorial.t	Tue Nov 14 23:04:04 2017 +0100
@@ -3,6 +3,7 @@
 -------------
 
 This Mercurial configuration example is used for testing.
+
 .. Various setup
 
   $ cat >> $HGRCPATH << EOF
@@ -64,6 +65,10 @@
   > rebase =
   > EOF
 
+#if docgraph-ext
+  $ . "$TESTDIR/testlib/docgraph_setup.sh" #rest-ignore
+#endif
+
 -----------------------
 Single Developer Usage
 -----------------------
@@ -124,6 +129,51 @@
   |
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	1	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=1,
+      		pin=true,
+      		pos="1,1!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	0 -> 1	 [arrowhead=none,
+      		penwidth=2.0];
+      	2	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=2,
+      		pin=true,
+      		pos="1,2!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	1 -> 2	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
 
 But a typo was made in Babanas!
 
@@ -158,7 +208,53 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-hopefully. I can use `hg commit --amend` to rewrite my faulty changeset!
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	1	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=1,
+      		pin=true,
+      		pos="1,1!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	0 -> 1	 [arrowhead=none,
+      		penwidth=2.0];
+      	2	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=2,
+      		pin=true,
+      		pos="1,2!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	1 -> 2	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
+
+Hopefully. I can use `hg commit --amend` to rewrite my faulty changeset!
 
   $ sed -i'' -e s/Bananos/Banana/ shopping
   $ hg diff
@@ -184,6 +280,52 @@
   |
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	1	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=1,
+      		pin=true,
+      		pos="1,1!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	0 -> 1	 [arrowhead=none,
+      		penwidth=2.0];
+      	3	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=3,
+      		pin=true,
+      		pos="1,3!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	1 -> 3	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
+
   $ hg export tip
   # HG changeset patch
   # User test
@@ -207,7 +349,7 @@
 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
@@ -224,9 +366,10 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
+  new changesets 9ca060c80d74
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
-I now have a new heads. Note that this remote head is immutable
+I now have a new head. Note that this remote head is immutable.
 
   $ hg log -G
   o  9ca060c80d74 (public): SPAM
@@ -238,13 +381,71 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-instead of merging my head with the new one. I'm going to rebase my work
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	1	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=1,
+      		pin=true,
+      		pos="1,1!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	0 -> 1	 [arrowhead=none,
+      		penwidth=2.0];
+      	4	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=4,
+      		pin=true,
+      		pos="1,4!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 4	 [arrowhead=none,
+      		penwidth=2.0];
+      	3	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=3,
+      		pin=true,
+      		pos="1,3!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	1 -> 3	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
+
+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"
   merging shopping
-  rebasing 4:9d0363b81950 "adding fruit"
+  rebasing 3:9d0363b81950 "adding fruit"
   merging shopping
 
 
@@ -259,11 +460,68 @@
   |
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=4,
+      		pin=true,
+      		pos="1,4!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 4	 [arrowhead=none,
+      		penwidth=2.0];
+      	5	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=5,
+      		pin=true,
+      		pos="1,5!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	4 -> 5	 [arrowhead=none,
+      		penwidth=2.0];
+      	6	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=6,
+      		pin=true,
+      		pos="1,6!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	5 -> 6	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
 
 Removing changesets
 ------------------------
 
-I add new item to my list
+I add new items to my list.
 
   $ cat >> shopping << EOF
   > car
@@ -284,7 +542,7 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-I have a new commit but I realize that don't want it. (transport shop list does
+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)
 
   $ hg prune . # "." is for working directory parent
@@ -304,6 +562,64 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=4,
+      		pin=true,
+      		pos="1,4!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 4	 [arrowhead=none,
+      		penwidth=2.0];
+      	5	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=5,
+      		pin=true,
+      		pos="1,5!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	4 -> 5	 [arrowhead=none,
+      		penwidth=2.0];
+      	6	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=6,
+      		pin=true,
+      		pos="1,6!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	5 -> 6	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
+
 Reordering changesets
 ------------------------
 
@@ -349,7 +665,7 @@
   $ hg up 'p1(10b8aeaa8cc8)' # going on "bathroom stuff" parent
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg grab fac207dec9f5 # moving "SPAM SPAM" to the working directory parent
-  rebasing 10:fac207dec9f5 "SPAM SPAM" (tip)
+  rebasing 9:fac207dec9f5 "SPAM SPAM" (tip)
   merging shopping
   ? files updated, 0 files merged, 0 files removed, 0 files unresolved (glob)
   $ hg log -G
@@ -366,6 +682,88 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=4,
+      		pin=true,
+      		pos="1,4!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 4	 [arrowhead=none,
+      		penwidth=2.0];
+      	5	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=5,
+      		pin=true,
+      		pos="1,5!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	4 -> 5	 [arrowhead=none,
+      		penwidth=2.0];
+      	6	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=6,
+      		pin=true,
+      		pos="1,6!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	5 -> 6	 [arrowhead=none,
+      		penwidth=2.0];
+      	8	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=8,
+      		pin=true,
+      		pos="1,8!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	6 -> 8	 [arrowhead=none,
+      		penwidth=2.0];
+      	10	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=10,
+      		pin=true,
+      		pos="1,10!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	6 -> 10	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
+
 We have a new SPAM SPAM version without the bathroom stuff
 
   $ grep Spam shopping  # enough spam
@@ -405,12 +803,12 @@
   adding manifests
   adding file changes
   added 3 changesets with 3 changes to 1 files
-  6 new obsolescence markers
+  5 new obsolescence markers
 
 for simplicity sake we get the bathroom change in line again
 
   $ hg grab 10b8aeaa8cc8
-  rebasing 9:10b8aeaa8cc8 "bathroom stuff"
+  rebasing 8:10b8aeaa8cc8 "bathroom stuff"
   merging shopping
   ? files updated, 0 files merged, 0 files removed, 0 files unresolved (glob)
   $ hg phase --draft .
@@ -428,7 +826,87 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=4,
+      		pin=true,
+      		pos="1,4!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 4	 [arrowhead=none,
+      		penwidth=2.0];
+      	5	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=5,
+      		pin=true,
+      		pos="1,5!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4 -> 5	 [arrowhead=none,
+      		penwidth=2.0];
+      	6	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=6,
+      		pin=true,
+      		pos="1,6!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	5 -> 6	 [arrowhead=none,
+      		penwidth=2.0];
+      	10	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=10,
+      		pin=true,
+      		pos="1,10!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	6 -> 10	 [arrowhead=none,
+      		penwidth=2.0];
+      	11	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=11,
+      		pin=true,
+      		pos="1,11!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	10 -> 11	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
 
 Splitting change
 ------------------
@@ -513,7 +991,7 @@
 -----------------------
 
 
-sharing mutable changesets
+Sharing mutable changesets
 ----------------------------
 
 To share mutable changesets with others, just check that the repo you interact
@@ -524,7 +1002,7 @@
   $ hg -R ../local/ showconfig phases
   [1]
 
-the localrepo does not have any specific configuration for `phases.publish`. It
+The localrepo does not have any specific configuration for `phases.publish`. It
 is ``true`` by default.
 
   $ hg pull local
@@ -535,6 +1013,7 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files
   1 new obsolescence markers
+  new changesets 75954b8cd933
   (run 'hg update' to get a working copy)
   $ hg log -G
   o  75954b8cd933 (public): bathroom stuff
@@ -550,8 +1029,6 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-
-
 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.
@@ -570,7 +1047,7 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-Let's make the local repo "non publishing"
+Let's make the local repo "non publishing".
 
   $ echo '[phases]' >> ../local/.hg/hgrc
   $ echo 'publish=false' >> ../local/.hg/hgrc
@@ -592,6 +1069,7 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files
   1 new obsolescence markers
+  new changesets 75954b8cd933
   (run 'hg update' to get a working copy)
   $ hg log -G
   o  75954b8cd933 (draft): bathroom stuff
@@ -641,6 +1119,87 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=4,
+      		pin=true,
+      		pos="1,4!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 4	 [arrowhead=none,
+      		penwidth=2.0];
+      	5	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=5,
+      		pin=true,
+      		pos="1,5!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4 -> 5	 [arrowhead=none,
+      		penwidth=2.0];
+      	6	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=6,
+      		pin=true,
+      		pos="1,6!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	5 -> 6	 [arrowhead=none,
+      		penwidth=2.0];
+      	10	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=10,
+      		pin=true,
+      		pos="1,10!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	6 -> 10	 [arrowhead=none,
+      		penwidth=2.0];
+      	12	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=12,
+      		pin=true,
+      		pos="1,12!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	10 -> 12	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
 
 When we pull from remote again we get an unstable state!
 
@@ -650,9 +1209,10 @@
   adding changesets
   adding manifests
   adding file changes
-  added 1 changesets with 1 changes to 1 files (+1 heads)
-  (run 'hg heads' to see heads, 'hg merge' to merge)
-  1 new unstable changesets
+  added 1 changesets with 1 changes to 1 files
+  new changesets bf1b0d202029
+  (run 'hg update' to get a working copy)
+  1 new orphan changesets
 
 
 The new changeset "animal" is based on an old changeset of "bathroom". You can
@@ -676,6 +1236,116 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=4,
+      		pin=true,
+      		pos="1,4!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 4	 [arrowhead=none,
+      		penwidth=2.0];
+      	5	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=5,
+      		pin=true,
+      		pos="1,5!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4 -> 5	 [arrowhead=none,
+      		penwidth=2.0];
+      	6	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=6,
+      		pin=true,
+      		pos="1,6!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	5 -> 6	 [arrowhead=none,
+      		penwidth=2.0];
+      	10	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=10,
+      		pin=true,
+      		pos="1,10!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	6 -> 10	 [arrowhead=none,
+      		penwidth=2.0];
+      	11	 [fillcolor="#DFDFFF",
+      		fixedsize=true,
+      		group=default_alt,
+      		height=0.5,
+      		label=11,
+      		pin=true,
+      		pos="2,11!",
+      		shape=pentagon,
+      		style="dotted, filled",
+      		width=0.5];
+      	10 -> 11	 [arrowhead=none,
+      		penwidth=2.0];
+      	12	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=12,
+      		pin=true,
+      		pos="1,12!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	10 -> 12	 [arrowhead=none,
+      		penwidth=2.0];
+      	11 -> 12	 [arrowhead=none,
+      		minlen=0,
+      		penwidth=2.0,
+      		style=dashed];
+      	13	 [fillcolor="#FF4F4F",
+      		fixedsize=true,
+      		group=default_alt,
+      		height=0.5,
+      		label=13,
+      		pin=true,
+      		pos="2,13!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	11 -> 13	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
+
 The older version 75954b8cd933 never ceased to exist in the local repo. It was
 just hidden and excluded from pull and push.
 
@@ -687,28 +1357,26 @@
   $ hg push other
   pushing to $TESTTMP/other (glob)
   searching for changes
-  abort: push includes unstable changeset: bf1b0d202029!
+  abort: push includes orphan changeset: bf1b0d202029!
   (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.
 
 It has a --dry-run option to only suggest the next move.
 
   $ hg evolve --dry-run
-  move:[15] animals
-  atop:[14] bathroom stuff
+  move:[13] animals
+  atop:[12] bathroom stuff
   hg rebase -r bf1b0d202029 -d a44c85f957d3
 
 Let's do it
 
   $ hg evolve
-  move:[15] animals
-  atop:[14] bathroom stuff
+  move:[13] animals
+  atop:[12] bathroom stuff
   merging shopping
   working directory is now at ee942144f952
 
@@ -730,8 +1398,101 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=4,
+      		pin=true,
+      		pos="1,4!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 4	 [arrowhead=none,
+      		penwidth=2.0];
+      	5	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=5,
+      		pin=true,
+      		pos="1,5!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4 -> 5	 [arrowhead=none,
+      		penwidth=2.0];
+      	6	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=6,
+      		pin=true,
+      		pos="1,6!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	5 -> 6	 [arrowhead=none,
+      		penwidth=2.0];
+      	10	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=10,
+      		pin=true,
+      		pos="1,10!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	6 -> 10	 [arrowhead=none,
+      		penwidth=2.0];
+      	12	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=12,
+      		pin=true,
+      		pos="1,12!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	10 -> 12	 [arrowhead=none,
+      		penwidth=2.0];
+      	14	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=14,
+      		pin=true,
+      		pos="1,14!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	12 -> 14	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
 
-We can push this evolution to remote
+We can push this evolution to remote.
 
   $ hg push remote
   pushing to $TESTTMP/remote (glob)
@@ -740,10 +1501,11 @@
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 1 files (+1 heads)
-  3 new obsolescence markers
+  2 new obsolescence markers
   obsoleted 2 changesets
 
-remote get a warning that current working directory is based on an obsolete changeset
+Remote get a warning that current working directory is based on an obsolete
+changeset.
 
   $ cd ../remote
   $ hg pull local # we up again to trigger the warning. it was displayed during the push
@@ -753,7 +1515,7 @@
   working directory parent is obsolete! (bf1b0d202029)
   (use 'hg evolve' to update to its successor: ee942144f952)
 
-now let's see where we are, and update to the successor
+Now let's see where we are, and update to the successor.
 
   $ hg parents
   bf1b0d202029 (draft): animals
@@ -767,7 +1529,7 @@
 Relocating unstable change after prune
 ----------------------------------------------
 
-The remote guy keep working
+The remote guy keeps working.
 
   $ sed -i'' -e 's/Spam/Spam Spam Spam Spam/g' shopping
   $ hg commit -m "SPAM SPAM SPAM"
@@ -782,6 +1544,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
+  new changesets 99f039c5ec9e
   (run 'hg update' to get a working copy)
   $ hg log -G
   o  99f039c5ec9e (draft): SPAM SPAM SPAM
@@ -801,17 +1564,123 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=4,
+      		pin=true,
+      		pos="1,4!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 4	 [arrowhead=none,
+      		penwidth=2.0];
+      	5	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=5,
+      		pin=true,
+      		pos="1,5!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4 -> 5	 [arrowhead=none,
+      		penwidth=2.0];
+      	6	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=6,
+      		pin=true,
+      		pos="1,6!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	5 -> 6	 [arrowhead=none,
+      		penwidth=2.0];
+      	10	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=10,
+      		pin=true,
+      		pos="1,10!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	6 -> 10	 [arrowhead=none,
+      		penwidth=2.0];
+      	12	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=12,
+      		pin=true,
+      		pos="1,12!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	10 -> 12	 [arrowhead=none,
+      		penwidth=2.0];
+      	14	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=14,
+      		pin=true,
+      		pos="1,14!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	12 -> 14	 [arrowhead=none,
+      		penwidth=2.0];
+      	15	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=15,
+      		pin=true,
+      		pos="1,15!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	14 -> 15	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
+
 In the mean time I noticed you can't buy animals in a super market and I prune the animal changeset:
 
   $ hg prune ee942144f952
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   working directory now at a44c85f957d3
   1 changesets pruned
-  1 new unstable changesets
+  1 new orphan changesets
 
 
 The animals changeset is still displayed because the "SPAM SPAM SPAM" changeset
-is neither dead or obsolete.  My repository is in an unstable state again.
+is neither dead or obsolete. My repository is in an unstable state again.
 
   $ hg log -G
   o  99f039c5ec9e (draft): SPAM SPAM SPAM
@@ -831,12 +1700,140 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
-  $ hg log -r 'unstable()'
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=4,
+      		pin=true,
+      		pos="1,4!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 4	 [arrowhead=none,
+      		penwidth=2.0];
+      	5	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=5,
+      		pin=true,
+      		pos="1,5!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4 -> 5	 [arrowhead=none,
+      		penwidth=2.0];
+      	6	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=6,
+      		pin=true,
+      		pos="1,6!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	5 -> 6	 [arrowhead=none,
+      		penwidth=2.0];
+      	10	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=10,
+      		pin=true,
+      		pos="1,10!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	6 -> 10	 [arrowhead=none,
+      		penwidth=2.0];
+      	12	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=12,
+      		pin=true,
+      		pos="1,12!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	10 -> 12	 [arrowhead=none,
+      		penwidth=2.0];
+      	14	 [fillcolor="#DFDFFF",
+      		fixedsize=true,
+      		group=default_alt,
+      		height=0.5,
+      		label=14,
+      		pin=true,
+      		pos="2,14!",
+      		shape=pentagon,
+      		style="dotted, filled",
+      		width=0.5];
+      	12 -> 14	 [arrowhead=none,
+      		penwidth=2.0];
+      	15	 [fillcolor="#FF4F4F",
+      		fixedsize=true,
+      		group=default_alt,
+      		height=0.5,
+      		label=15,
+      		pin=true,
+      		pos="2,15!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	14 -> 15	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
+
+  $ hg log -r "orphan()"
   99f039c5ec9e (draft): SPAM SPAM SPAM
 
+#if docgraph-ext
+  $ hg docgraph -r "orphan()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	15	 [fillcolor="#FF4F4F",
+      		fixedsize=true,
+      		group=default_alt,
+      		height=0.5,
+      		label=15,
+      		pin=true,
+      		pos="1,15!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      }
+#endif
+
   $ hg evolve
-  move:[17] SPAM SPAM SPAM
-  atop:[14] bathroom stuff
+  move:[15] SPAM SPAM SPAM
+  atop:[12] bathroom stuff
   merging shopping
   working directory is now at 40aa40daeefb
 
@@ -856,6 +1853,99 @@
   o  7e82d3f3c2cb (public): Monthy Python Shopping list
   
 
+#if docgraph-ext
+  $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore
+  .. graphviz::
+  
+      strict digraph  {
+      	graph [rankdir=LR,
+      		splines=polyline
+      	];
+      	node [label="\N"];
+      	0	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=0,
+      		pin=true,
+      		pos="1,0!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=4,
+      		pin=true,
+      		pos="1,4!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	0 -> 4	 [arrowhead=none,
+      		penwidth=2.0];
+      	5	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=5,
+      		pin=true,
+      		pos="1,5!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	4 -> 5	 [arrowhead=none,
+      		penwidth=2.0];
+      	6	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=6,
+      		pin=true,
+      		pos="1,6!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	5 -> 6	 [arrowhead=none,
+      		penwidth=2.0];
+      	10	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=10,
+      		pin=true,
+      		pos="1,10!",
+      		shape=circle,
+      		style=filled,
+      		width=0.5];
+      	6 -> 10	 [arrowhead=none,
+      		penwidth=2.0];
+      	12	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=12,
+      		pin=true,
+      		pos="1,12!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	10 -> 12	 [arrowhead=none,
+      		penwidth=2.0];
+      	16	 [fillcolor="#9999FF",
+      		fixedsize=true,
+      		group=default,
+      		height=0.5,
+      		label=16,
+      		pin=true,
+      		pos="1,16!",
+      		shape=pentagon,
+      		style=filled,
+      		width=0.5];
+      	12 -> 16	 [arrowhead=none,
+      		penwidth=2.0];
+      }
+#endif
 
 Handling Divergent amend
 ----------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-uncommit-interactive.t	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,908 @@
+================================================
+||  The test for `hg uncommit --interactive`  ||
+================================================
+
+Repo Setup
+============
+
+  $ . $TESTDIR/testlib/common.sh
+  $ cat >> $HGRCPATH <<EOF
+  > [ui]
+  > interactive = true
+  > [extensions]
+  > evolve =
+  > EOF
+
+  $ glog() {
+  >   hg log -G --template '{rev}:{node|short}@{branch}({separate("/", obsolete, phase)}) {desc|firstline}\n' "$@"
+  > }
+
+  $ hg init repo
+  $ cd repo
+
+  $ touch a
+  $ cat >> a << EOF
+  > 1
+  > 2
+  > 3
+  > 4
+  > 5
+  > EOF
+
+  $ hg add a
+  $ hg ci -m "The base commit"
+
+Make sure aborting the interactive selection does no magic
+----------------------------------------------------------
+
+  $ hg status
+  $ hg uncommit -i<<EOF
+  > q
+  > EOF
+  diff --git a/a b/a
+  new file mode 100644
+  examine changes to 'a'? [Ynesfdaq?] q
+  
+  abort: user quit
+  [255]
+  $ hg status
+
+Make a commit with multiple hunks
+---------------------------------
+
+  $ cat > a << EOF
+  > -2
+  > -1
+  > 0
+  > 1
+  > 2
+  > 3
+  > foo
+  > bar
+  > 4
+  > 5
+  > babar
+  > EOF
+
+  $ hg diff
+  diff -r 7733902a8d94 a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,5 +1,11 @@
+  +-2
+  +-1
+  +0
+   1
+   2
+   3
+  +foo
+  +bar
+   4
+   5
+  +babar
+
+  $ hg ci -m "another one"
+
+Not selecting anything to uncommit
+==================================
+
+  $ hg uncommit -i<<EOF
+  > y
+  > n
+  > n
+  > n
+  > EOF
+  diff --git a/a b/a
+  3 hunks, 6 lines changed
+  examine changes to 'a'? [Ynesfdaq?] y
+  
+  @@ -1,3 +1,6 @@
+  +-2
+  +-1
+  +0
+   1
+   2
+   3
+  discard change 1/3 to 'a'? [Ynesfdaq?] n
+  
+  @@ -1,5 +4,7 @@
+   1
+   2
+   3
+  +foo
+  +bar
+   4
+   5
+  discard change 2/3 to 'a'? [Ynesfdaq?] n
+  
+  @@ -4,2 +9,3 @@
+   4
+   5
+  +babar
+  discard change 3/3 to 'a'? [Ynesfdaq?] n
+  
+  abort: nothing selected to uncommit
+  [255]
+  $ hg status
+
+Uncommit a chunk
+================
+
+  $ hg amend --extract -i<<EOF
+  > y
+  > y
+  > n
+  > n
+  > EOF
+  diff --git a/a b/a
+  3 hunks, 6 lines changed
+  examine changes to 'a'? [Ynesfdaq?] y
+  
+  @@ -1,3 +1,6 @@
+  +-2
+  +-1
+  +0
+   1
+   2
+   3
+  discard change 1/3 to 'a'? [Ynesfdaq?] y
+  
+  @@ -1,5 +4,7 @@
+   1
+   2
+   3
+  +foo
+  +bar
+   4
+   5
+  discard change 2/3 to 'a'? [Ynesfdaq?] n
+  
+  @@ -4,2 +9,3 @@
+   4
+   5
+  +babar
+  discard change 3/3 to 'a'? [Ynesfdaq?] n
+  
+The unselected part should be in the diff
+-----------------------------------------
+
+  $ hg diff
+  diff -r 678a59e5ff90 a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,3 +1,6 @@
+  +-2
+  +-1
+  +0
+   1
+   2
+   3
+
+The commit should contain the rest of part
+------------------------------------------
+
+  $ hg exp
+  # HG changeset patch
+  # User test
+  # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
+  # Node ID 678a59e5ff90754d5e94719bd82ad169be773c21
+  # Parent  7733902a8d94c789ca81d866bea1893d79442db6
+  another one
+  
+  diff -r 7733902a8d94 -r 678a59e5ff90 a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,5 +1,8 @@
+   1
+   2
+   3
+  +foo
+  +bar
+   4
+   5
+  +babar
+
+Uncommiting on dirty working directory
+======================================
+
+  $ hg status
+  M a
+  $ hg diff
+  diff -r 678a59e5ff90 a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,3 +1,6 @@
+  +-2
+  +-1
+  +0
+   1
+   2
+   3
+
+  $ hg uncommit -i<<EOF
+  > y
+  > n
+  > y
+  > EOF
+  diff --git a/a b/a
+  2 hunks, 3 lines changed
+  examine changes to 'a'? [Ynesfdaq?] y
+  
+  @@ -1,5 +1,7 @@
+   1
+   2
+   3
+  +foo
+  +bar
+   4
+   5
+  discard change 1/2 to 'a'? [Ynesfdaq?] n
+  
+  @@ -4,2 +6,3 @@
+   4
+   5
+  +babar
+  discard change 2/2 to 'a'? [Ynesfdaq?] y
+  
+  patching file a
+  Hunk #1 succeeded at 2 with fuzz 1 (offset 0 lines).
+
+  $ hg diff
+  diff -r 46e35360be47 a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,3 +1,6 @@
+  +-2
+  +-1
+  +0
+   1
+   2
+   3
+  @@ -5,3 +8,4 @@
+   bar
+   4
+   5
+  +babar
+
+  $ hg exp
+  # HG changeset patch
+  # User test
+  # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
+  # Node ID 46e35360be473bf761bedf3d05de4a68ffd9d9f8
+  # Parent  7733902a8d94c789ca81d866bea1893d79442db6
+  another one
+  
+  diff -r 7733902a8d94 -r 46e35360be47 a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,5 +1,7 @@
+   1
+   2
+   3
+  +foo
+  +bar
+   4
+   5
+
+Checking the obsolescence history
+
+  $ hg obslog
+  @  46e35360be47 (5) another one
+  |
+  x  678a59e5ff90 (3) another one
+  |    rewritten(content) as 46e35360be47 by test (Thu Jan 01 00:00:00 1970 +0000)
+  |
+  x  f70fb463d5bf (1) another one
+       rewritten(content) as 678a59e5ff90 by test (Thu Jan 01 00:00:00 1970 +0000)
+  
+
+Push the changes back to the commit and more commits for more testing
+
+  $ hg amend
+  $ glog
+  @  6:905eb2a23ea2@default(draft) another one
+  |
+  o  0:7733902a8d94@default(draft) The base commit
+  
+  $ touch foo
+  $ echo "hey" >> foo
+  $ hg ci -Am "Added foo"
+  adding foo
+
+Testing uncommiting a whole changeset and also for a file addition
+==================================================================
+
+  $ hg uncommit -i<<EOF
+  > y
+  > y
+  > EOF
+  diff --git a/foo b/foo
+  new file mode 100644
+  examine changes to 'foo'? [Ynesfdaq?] y
+  
+  @@ -0,0 +1,1 @@
+  +hey
+  discard this change to 'foo'? [Ynesfdaq?] y
+  
+  new changeset is empty
+  (use 'hg prune .' to remove it)
+
+  $ hg status
+  A foo
+  $ hg diff
+  diff -r 857367499298 foo
+  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/foo	Thu Jan 01 00:00:00 1970 +0000
+  @@ -0,0 +1,1 @@
+  +hey
+
+  $ hg exp
+  # HG changeset patch
+  # User test
+  # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
+  # Node ID 857367499298e999b5841bb01df65f73088b5d3b
+  # Parent  905eb2a23ea2d92073419d0e19165b90d36ea223
+  Added foo
+  
+  $ hg amend
+
+Testing to uncommit removed files completely
+============================================
+
+  $ hg rm a
+  $ hg ci -m "Removed a"
+  $ hg exp
+  # HG changeset patch
+  # User test
+  # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
+  # Node ID 219cfe20964e93f8bb9bd82ceaa54d3b776046db
+  # Parent  42cc15efbec26c14d96d805dee2766ba91d1fd31
+  Removed a
+  
+  diff -r 42cc15efbec2 -r 219cfe20964e a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,11 +0,0 @@
+  --2
+  --1
+  -0
+  -1
+  -2
+  -3
+  -foo
+  -bar
+  -4
+  -5
+  -babar
+
+Not examining the file
+----------------------
+
+  $ hg uncommit -i<<EOF
+  > n
+  > EOF
+  diff --git a/a b/a
+  deleted file mode 100644
+  examine changes to 'a'? [Ynesfdaq?] n
+  
+  abort: nothing selected to uncommit
+  [255]
+
+Examining the file
+------------------
+XXX: there is a bug in interactive selection as it is not letting to examine the
+file. Tried with curses too. In the curses UI, if you just unselect the hunks
+and the not file mod thing at the top, it will show the same "nothing unselected
+to uncommit" message which is a bug in interactive selection.
+
+  $ hg uncommit -i<<EOF
+  > y
+  > EOF
+  diff --git a/a b/a
+  deleted file mode 100644
+  examine changes to 'a'? [Ynesfdaq?] y
+  
+  new changeset is empty
+  (use 'hg prune .' to remove it)
+
+  $ hg diff
+  diff -r 737487f1e5f8 a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,11 +0,0 @@
+  --2
+  --1
+  -0
+  -1
+  -2
+  -3
+  -foo
+  -bar
+  -4
+  -5
+  -babar
+  $ hg status
+  R a
+  $ hg exp
+  # HG changeset patch
+  # User test
+  # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
+  # Node ID 737487f1e5f853e55decb73ea31522c63e7f5980
+  # Parent  42cc15efbec26c14d96d805dee2766ba91d1fd31
+  Removed a
+  
+
+  $ hg prune .
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  working directory now at 42cc15efbec2
+  1 changesets pruned
+  $ hg revert --all
+  undeleting a
+
+  $ glog
+  @  10:42cc15efbec2@default(draft) Added foo
+  |
+  o  6:905eb2a23ea2@default(draft) another one
+  |
+  o  0:7733902a8d94@default(draft) The base commit
+  
+
+Testing when a new file is added in the last commit
+===================================================
+
+  $ echo "foo" >> foo
+  $ touch x
+  $ echo "abcd" >> x
+  $ hg add x
+  $ hg ci -m "Added x"
+  $ hg uncommit -i<<EOF
+  > y
+  > y
+  > y
+  > n
+  > EOF
+  diff --git a/foo b/foo
+  1 hunks, 1 lines changed
+  examine changes to 'foo'? [Ynesfdaq?] y
+  
+  @@ -1,1 +1,2 @@
+   hey
+  +foo
+  discard change 1/2 to 'foo'? [Ynesfdaq?] y
+  
+  diff --git a/x b/x
+  new file mode 100644
+  examine changes to 'x'? [Ynesfdaq?] y
+  
+  @@ -0,0 +1,1 @@
+  +abcd
+  discard change 2/2 to 'x'? [Ynesfdaq?] n
+  
+
+  $ hg exp
+  # HG changeset patch
+  # User test
+  # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
+  # Node ID 25a080d13cb23dbd014839f54d99a96e57ba7e9b
+  # Parent  42cc15efbec26c14d96d805dee2766ba91d1fd31
+  Added x
+  
+  diff -r 42cc15efbec2 -r 25a080d13cb2 x
+  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/x	Thu Jan 01 00:00:00 1970 +0000
+  @@ -0,0 +1,1 @@
+  +abcd
+
+  $ hg diff
+  diff -r 25a080d13cb2 foo
+  --- a/foo	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/foo	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,1 +1,2 @@
+   hey
+  +foo
+
+  $ hg status
+  M foo
+
+  $ hg revert --all
+  reverting foo
+
+Testing between the stack and with dirty working copy
+=====================================================
+
+  $ glog
+  @  16:25a080d13cb2@default(draft) Added x
+  |
+  o  10:42cc15efbec2@default(draft) Added foo
+  |
+  o  6:905eb2a23ea2@default(draft) another one
+  |
+  o  0:7733902a8d94@default(draft) The base commit
+  
+  $ hg up 905eb2a23ea2
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+
+  $ touch bar
+  $ echo "foo" >> bar
+  $ hg add bar
+  $ hg status
+  A bar
+  ? foo.orig
+
+  $ hg exp
+  # HG changeset patch
+  # User test
+  # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
+  # Node ID 905eb2a23ea2d92073419d0e19165b90d36ea223
+  # Parent  7733902a8d94c789ca81d866bea1893d79442db6
+  another one
+  
+  diff -r 7733902a8d94 -r 905eb2a23ea2 a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,5 +1,11 @@
+  +-2
+  +-1
+  +0
+   1
+   2
+   3
+  +foo
+  +bar
+   4
+   5
+  +babar
+
+  $ hg uncommit -i<<EOF
+  > y
+  > n
+  > n
+  > y
+  > EOF
+  diff --git a/a b/a
+  3 hunks, 6 lines changed
+  examine changes to 'a'? [Ynesfdaq?] y
+  
+  @@ -1,3 +1,6 @@
+  +-2
+  +-1
+  +0
+   1
+   2
+   3
+  discard change 1/3 to 'a'? [Ynesfdaq?] n
+  
+  @@ -1,5 +4,7 @@
+   1
+   2
+   3
+  +foo
+  +bar
+   4
+   5
+  discard change 2/3 to 'a'? [Ynesfdaq?] n
+  
+  @@ -4,2 +9,3 @@
+   4
+   5
+  +babar
+  discard change 3/3 to 'a'? [Ynesfdaq?] y
+  
+  patching file a
+  Hunk #1 succeeded at 1 with fuzz 1 (offset -1 lines).
+  2 new orphan changesets
+
+  $ hg diff
+  diff -r 676366511f95 a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -8,3 +8,4 @@
+   bar
+   4
+   5
+  +babar
+  diff -r 676366511f95 bar
+  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/bar	Thu Jan 01 00:00:00 1970 +0000
+  @@ -0,0 +1,1 @@
+  +foo
+
+  $ hg exp
+  # HG changeset patch
+  # User test
+  # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
+  # Node ID 676366511f95ca4122413dcf79b45eaab61fb387
+  # Parent  7733902a8d94c789ca81d866bea1893d79442db6
+  another one
+  
+  diff -r 7733902a8d94 -r 676366511f95 a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,5 +1,10 @@
+  +-2
+  +-1
+  +0
+   1
+   2
+   3
+  +foo
+  +bar
+   4
+   5
+  $ hg status
+  M a
+  A bar
+  ? foo.orig
+
+More uncommit on the same dirty working copy
+=============================================
+
+  $ hg uncommit -i<<EOF
+  > y
+  > y
+  > n
+  > EOF
+  diff --git a/a b/a
+  2 hunks, 5 lines changed
+  examine changes to 'a'? [Ynesfdaq?] y
+  
+  @@ -1,3 +1,6 @@
+  +-2
+  +-1
+  +0
+   1
+   2
+   3
+  discard change 1/2 to 'a'? [Ynesfdaq?] y
+  
+  @@ -1,5 +4,7 @@
+   1
+   2
+   3
+  +foo
+  +bar
+   4
+   5
+  discard change 2/2 to 'a'? [Ynesfdaq?] n
+  
+
+  $ hg exp
+  # HG changeset patch
+  # User test
+  # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
+  # Node ID 62d907d0c4fa13b4b8bfeed05f13751035daf963
+  # Parent  7733902a8d94c789ca81d866bea1893d79442db6
+  another one
+  
+  diff -r 7733902a8d94 -r 62d907d0c4fa a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,5 +1,7 @@
+   1
+   2
+   3
+  +foo
+  +bar
+   4
+   5
+
+  $ hg diff
+  diff -r 62d907d0c4fa a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,3 +1,6 @@
+  +-2
+  +-1
+  +0
+   1
+   2
+   3
+  @@ -5,3 +8,4 @@
+   bar
+   4
+   5
+  +babar
+  diff -r 62d907d0c4fa bar
+  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/bar	Thu Jan 01 00:00:00 1970 +0000
+  @@ -0,0 +1,1 @@
+  +foo
+
+  $ hg status
+  M a
+  A bar
+  ? foo.orig
+
+Interactive uncommit with a pattern
+-----------------------------------
+
+(more setup)
+
+  $ hg ci -m 'roaming changes'
+  $ cat > b << EOF
+  > a
+  > b
+  > c
+  > d
+  > e
+  > f
+  > h
+  > EOF
+  $ hg add b
+  $ hg ci -m 'add b'
+  $ echo 'celeste' >> a
+  $ echo 'i' >> b
+  $ hg ci -m 'some more changes'
+  $ hg export
+  # HG changeset patch
+  # User test
+  # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
+  # Node ID be5c67225e80b050867862bbd9f4755c4e9207c5
+  # Parent  c280a907fddcef2ffe9fadcc2d87f29998e22b2f
+  some more changes
+  
+  diff -r c280a907fddc -r be5c67225e80 a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -9,3 +9,4 @@
+   4
+   5
+   babar
+  +celeste
+  diff -r c280a907fddc -r be5c67225e80 b
+  --- a/b	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/b	Thu Jan 01 00:00:00 1970 +0000
+  @@ -5,3 +5,4 @@
+   e
+   f
+   h
+  +i
+
+  $ hg uncommit -i a << DONE
+  > y
+  > y
+  > DONE
+  diff --git a/a b/a
+  1 hunks, 1 lines changed
+  examine changes to 'a'? [Ynesfdaq?] y
+  
+  @@ -9,3 +9,4 @@
+   4
+   5
+   babar
+  +celeste
+  discard this change to 'a'? [Ynesfdaq?] y
+  
+  $ hg status
+  M a
+  ? foo.orig
+  $ hg diff
+  diff -r c701d7c8d18b a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -9,3 +9,4 @@
+   4
+   5
+   babar
+  +celeste
+  $ hg export
+  # HG changeset patch
+  # User test
+  # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
+  # Node ID c701d7c8d18be55a92688f4458c26bd74fb1f525
+  # Parent  c280a907fddcef2ffe9fadcc2d87f29998e22b2f
+  some more changes
+  
+  diff -r c280a907fddc -r c701d7c8d18b b
+  --- a/b	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/b	Thu Jan 01 00:00:00 1970 +0000
+  @@ -5,3 +5,4 @@
+   e
+   f
+   h
+  +i
+
+(reset)
+
+  $ cat << EOF  > a
+  > -3
+  > -2
+  > -1
+  > 0
+  > 1
+  > 2
+  > 3
+  > foo
+  > bar
+  > 4
+  > 5
+  > babar
+  > celeste
+  > EOF
+  $ hg amend 
+
+Same but do not select some change in 'a'
+
+  $ hg uncommit -i a << DONE
+  > y
+  > y
+  > n
+  > DONE
+  diff --git a/a b/a
+  2 hunks, 2 lines changed
+  examine changes to 'a'? [Ynesfdaq?] y
+  
+  @@ -1,3 +1,4 @@
+  +-3
+   -2
+   -1
+   0
+  discard change 1/2 to 'a'? [Ynesfdaq?] y
+  
+  @@ -9,3 +10,4 @@
+   4
+   5
+   babar
+  +celeste
+  discard change 2/2 to 'a'? [Ynesfdaq?] n
+  
+  $ hg status
+  M a
+  ? foo.orig
+
+  $ hg diff
+  diff -r 28d5de12b225 a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,3 +1,4 @@
+  +-3
+   -2
+   -1
+   0
+
+  $ hg export
+  # HG changeset patch
+  # User test
+  # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
+  # Node ID 28d5de12b225d1e0951110cced8d8994227be026
+  # Parent  c280a907fddcef2ffe9fadcc2d87f29998e22b2f
+  some more changes
+  
+  diff -r c280a907fddc -r 28d5de12b225 a
+  --- a/a	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/a	Thu Jan 01 00:00:00 1970 +0000
+  @@ -9,3 +9,4 @@
+   4
+   5
+   babar
+  +celeste
+  diff -r c280a907fddc -r 28d5de12b225 b
+  --- a/b	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/b	Thu Jan 01 00:00:00 1970 +0000
+  @@ -5,3 +5,4 @@
+   e
+   f
+   h
+  +i
+
+  $ cat b
+  a
+  b
+  c
+  d
+  e
+  f
+  h
+  i
--- a/tests/test-uncommit.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-uncommit.t	Tue Nov 14 23:04:04 2017 +0100
@@ -244,7 +244,7 @@
   (use 'hg evolve' to update to its successor: e8db4aa611f6)
   $ hg --config extensions.purge= purge
   $ hg uncommit -I 'set:added() and e'
-  2 new divergent changesets
+  2 new content-divergent changesets
   $ hg st --copies
   A e
   $ hg st --copies --change .
@@ -287,10 +287,10 @@
   $ hg up -C 3 --hidden
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   working directory parent is obsolete! (5eb72dbe0cb4)
-  (5eb72dbe0cb4 has diverged, use 'hg evolve --list --divergent' to resolve the issue)
+  (5eb72dbe0cb4 has diverged, use 'hg evolve --list --content-divergent' to resolve the issue)
   $ hg --config extensions.purge= purge
   $ hg uncommit --all -X e
-  1 new divergent changesets
+  1 new content-divergent changesets
   $ hg st --copies
   M b
   M d
@@ -337,7 +337,7 @@
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   [8] touncommit
   $ hg uncommit aa
-  1 new unstable changesets
+  1 new orphan changesets
 
 Test uncommiting agains a different base
 
--- a/tests/test-unstable.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-unstable.t	Tue Nov 14 23:04:04 2017 +0100
@@ -42,7 +42,7 @@
   $ hg up "desc(_b)"
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg amend -m "bprime"
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg log -G
   @  3:36050226a9b9@default(draft) bprime
   |
@@ -53,7 +53,7 @@
   o  0:135f39f4bd78@default(draft) add _a
   
 
-  $ hg evo --all --any --unstable
+  $ hg evo --all --any --orphan
   move:[2] add _c
   atop:[3] bprime
   working directory is now at fdcf3523a74d
@@ -86,7 +86,7 @@
   $ hg up "desc(_a)"
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg amend -m "aprime"
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg log -G
   @  4:47127ea62e5f@default(draft) aprime
   |
@@ -99,7 +99,7 @@
   o  0:b4952fcf48cf@default(draft) add base
   
 
-  $ hg evo --all --any --unstable
+  $ hg evo --all --any --orphan
   move:[3] merge
   atop:[4] aprime
   working directory is now at 0bf3f3a59c8c
@@ -134,7 +134,7 @@
   $ hg up "desc(_a)"
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg amend -m "aprime"
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg up "desc(_c)"
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg amend -m "cprime"
@@ -152,7 +152,7 @@
   o  0:b4952fcf48cf@default(draft) add base
   
 
-  $ hg evo --all --any --unstable
+  $ hg evo --all --any --orphan
   warning: no support for evolving merge changesets with two obsolete parents yet
   (Redo the merge (6b4280e33286) and use `hg prune <old> --succ <new>` to obsolete the old one)
   $ hg log -G
@@ -185,7 +185,7 @@
   created new head
   $ hg prune "desc(_b)" -s "desc(bprimesplit1) + desc(bprimesplit2)" --split
   1 changesets pruned
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg log -G
   @  4:2a4ccc0bb20c@default(draft) add bprimesplit2
   |
@@ -198,7 +198,7 @@
   o  0:135f39f4bd78@default(draft) add _a
   
 
-  $ hg evo --all --any --unstable
+  $ hg evo --all --any --orphan
   move:[2] add _c
   atop:[4] add bprimesplit2
   working directory is now at 387cc1e837d7
@@ -230,14 +230,14 @@
   created new head
   $ hg prune "desc(_b)" -s "desc(bprimesplit1) + desc(bprimesplit2)" --split
   1 changesets pruned
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg up "desc(_a)"
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
   $ mkcommits bsecondsplit1 bsecondsplit2
   created new head
   $ hg prune "desc(bprimesplit1)" -s "desc(bsecondsplit2)"
   1 changesets pruned
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg prune "desc(bprimesplit2)" -s "desc(bsecondsplit1)"
   1 changesets pruned
   $ hg log -G
@@ -252,7 +252,7 @@
   o  0:135f39f4bd78@default(draft) add _a
   
 
-  $ hg evo --all --any --unstable
+  $ hg evo --all --any --orphan
   move:[2] add _c
   atop:[6] add bsecondsplit2
   working directory is now at 98e3f21461ff
@@ -288,7 +288,7 @@
   created new head
   $ hg prune "desc(_b)" -s "desc(bprimesplit1) + desc(bprimesplit2)" --split
   1 changesets pruned
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg log -G
   @  4:3c69ea6aa93e@default(draft) add bprimesplit2
   |
@@ -301,7 +301,7 @@
   o  0:135f39f4bd78@default(draft) add _a
   
 
-  $ hg evo --all --any --unstable
+  $ hg evo --all --any --orphan
   cannot solve split accross two branches
   $ hg log -G
   @  4:3c69ea6aa93e@default(draft) add bprimesplit2
--- a/tests/test-userguide.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-userguide.t	Tue Nov 14 23:04:04 2017 +0100
@@ -42,10 +42,8 @@
   (use --hidden to access hidden revisions; successor: 934359450037)
   [255]
   $ hg --hidden shortlog -G
-  @  3:934359450037  draft  implement feature Y
+  @  2:934359450037  draft  implement feature Y
   |
-  | x  2:6c5f78d5d467  draft  temporary amend commit for fe0ecd3bd2a4
-  | |
   | x  1:fe0ecd3bd2a4  draft  implement feature Y
   |/
   o  0:08c4b6f4efc8  draft  init
@@ -54,10 +52,8 @@
   $ hg rollback -q
   $ hg amend -u alice -d '2 0' -m 'implement feature Y'
   $ hg --hidden shortlog -G
-  @  3:934359450037  draft  implement feature Y
+  @  2:934359450037  draft  implement feature Y
   |
-  | x  2:6c5f78d5d467  draft  temporary amend commit for fe0ecd3bd2a4
-  | |
   | x  1:fe0ecd3bd2a4  draft  implement feature Y
   |/
   o  0:08c4b6f4efc8  draft  init
@@ -70,11 +66,11 @@
   working directory now at 934359450037
   1 changesets pruned
   $ hg parents --template '{rev}:{node|short}  {desc|firstline}\n'
-  3:934359450037  implement feature Y
-  $ hg --hidden shortlog -G -r 3:
-  x  4:a3e0ef24aaf0  draft  debug hack
+  2:934359450037  implement feature Y
+  $ hg --hidden shortlog -G -r 934359450037:
+  x  3:a3e0ef24aaf0  draft  debug hack
   |
-  @  3:934359450037  draft  implement feature Y
+  @  2:934359450037  draft  implement feature Y
   |
   ~
 
@@ -85,16 +81,16 @@
   $ hg uncommit file2.c
   $ hg status
   M file2.c
-  $ hg --hidden shortlog -G -r 'descendants(3) - 4'
-  @  6:c8defeecf7a4  draft  fix bug 234
+  $ hg --hidden shortlog -G -r 'descendants(934359450037) - a3e0ef24aaf0'
+  @  5:c8defeecf7a4  draft  fix bug 234
   |
-  | x  5:da4331967f5f  draft  fix bug 234
+  | x  4:da4331967f5f  draft  fix bug 234
   |/
-  o  3:934359450037  draft  implement feature Y
+  o  2:934359450037  draft  implement feature Y
   |
   ~
   $ hg parents --template '{rev}:{node|short}  {desc|firstline}\n{files}\n'
-  6:c8defeecf7a4  fix bug 234
+  5:c8defeecf7a4  fix bug 234
   file1.c
   $ hg revert --no-backup file2.c
 
@@ -105,32 +101,32 @@
   $ hg commit -m 'step 2'
   $ echo step3 >> file2.c
   $ hg commit -m 'step 3'
-  $ hg log --template '{rev}:{node|short}  {desc|firstline}\n' -r 7::
-  7:05e61aab8294  step 1
-  8:be6d5bc8e4cc  step 2
-  9:35f432d9f7c1  step 3
-  $ hg fold -d '0 0' -m 'fix bug 64' --from -r 7::
+  $ hg log --template '{rev}:{node|short}  {desc|firstline}\n' -r 05e61aab8294::
+  6:05e61aab8294  step 1
+  7:be6d5bc8e4cc  step 2
+  8:35f432d9f7c1  step 3
+  $ hg fold -d '0 0' -m 'fix bug 64' --from -r 05e61aab8294::
   3 changesets folded
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg --hidden shortlog -G -r 6::
-  @  10:171c6a79a27b  draft  fix bug 64
+  $ hg --hidden shortlog -G -r c8defeecf7a4::
+  @  9:171c6a79a27b  draft  fix bug 64
   |
-  | x  9:35f432d9f7c1  draft  step 3
+  | x  8:35f432d9f7c1  draft  step 3
   | |
-  | x  8:be6d5bc8e4cc  draft  step 2
+  | x  7:be6d5bc8e4cc  draft  step 2
   | |
-  | x  7:05e61aab8294  draft  step 1
+  | x  6:05e61aab8294  draft  step 1
   |/
-  o  6:c8defeecf7a4  draft  fix bug 234
+  o  5:c8defeecf7a4  draft  fix bug 234
   |
   ~
-  $ hg --hidden log -q -r 'successors(7) | successors(8) | successors(9)'
-  10:171c6a79a27b
-  $ hg --hidden log -q -r 'precursors(10)'
-  7:05e61aab8294
-  8:be6d5bc8e4cc
-  9:35f432d9f7c1
-  $ hg diff -c 10 -U 0
+  $ hg --hidden log -q -r 'successors(05e61aab8294) | successors(be6d5bc8e4cc) | successors(35f432d9f7c1)'
+  9:171c6a79a27b
+  $ hg --hidden log -q -r 'precursors(171c6a79a27b)'
+  6:05e61aab8294
+  7:be6d5bc8e4cc
+  8:35f432d9f7c1
+  $ hg diff -c 171c6a79a27b -U 0
   diff -r c8defeecf7a4 -r 171c6a79a27b file1.c
   --- a/file1.c	Thu Jan 01 00:00:10 1970 +0000
   +++ b/file1.c	Thu Jan 01 00:00:00 1970 +0000
@@ -150,50 +146,48 @@
   $ hg commit -u bob -d '4 0' -m 'cleanup'
   $ echo 'new feature' >> file1.c
   $ hg commit -u bob -d '5 0' -m 'feature 23'
-  $ hg --hidden shortlog -G -r 10::
-  @  13:dadcbba2d606  draft  feature 23
+  $ hg --hidden shortlog -G -r 171c6a79a27b::
+  @  12:dadcbba2d606  draft  feature 23
   |
-  o  12:debd46bb29dc  draft  cleanup
+  o  11:debd46bb29dc  draft  cleanup
   |
-  o  11:3e1cb8f70c02  draft  fix bug 17
+  o  10:3e1cb8f70c02  draft  fix bug 17
   |
-  o  10:171c6a79a27b  draft  fix bug 64
+  o  9:171c6a79a27b  draft  fix bug 64
   |
   ~
 
 example 7: amend an older changeset (figures 6, 7)
-  $ hg update -q 11
+  $ hg update -q -r 3e1cb8f70c02
   $ echo 'fix fix fix fix' > file2.c
   $ hg amend -u bob -d '6 0'
-  2 new unstable changesets
+  2 new orphan changesets
   $ hg shortlog -r 'obsolete()'
-  11:3e1cb8f70c02  draft  fix bug 17
-  $ hg shortlog -r 'unstable()'
-  12:debd46bb29dc  draft  cleanup
-  13:dadcbba2d606  draft  feature 23
-  $ hg --hidden shortlog -G -r 10::
-  @  15:395cbeda3a06  draft  fix bug 17
+  10:3e1cb8f70c02  draft  fix bug 17
+  $ hg shortlog -r "orphan()"
+  11:debd46bb29dc  draft  cleanup
+  12:dadcbba2d606  draft  feature 23
+  $ hg --hidden shortlog -G -r 171c6a79a27b::
+  @  13:395cbeda3a06  draft  fix bug 17
   |
-  | x  14:f7fab707e247  draft  temporary amend commit for 3e1cb8f70c02
+  | o  12:dadcbba2d606  draft  feature 23
+  | |
+  | o  11:debd46bb29dc  draft  cleanup
   | |
-  | | o  13:dadcbba2d606  draft  feature 23
-  | | |
-  | | o  12:debd46bb29dc  draft  cleanup
-  | |/
-  | x  11:3e1cb8f70c02  draft  fix bug 17
+  | x  10:3e1cb8f70c02  draft  fix bug 17
   |/
-  o  10:171c6a79a27b  draft  fix bug 64
+  o  9:171c6a79a27b  draft  fix bug 64
   |
   ~
   $ hg evolve -q --all
-  $ hg shortlog -G -r 10::
-  @  17:91b4b0f8b5c5  draft  feature 23
+  $ hg shortlog -G -r 171c6a79a27b::
+  @  15:91b4b0f8b5c5  draft  feature 23
   |
-  o  16:fe8858bd9bc2  draft  cleanup
+  o  14:fe8858bd9bc2  draft  cleanup
   |
-  o  15:395cbeda3a06  draft  fix bug 17
+  o  13:395cbeda3a06  draft  fix bug 17
   |
-  o  10:171c6a79a27b  draft  fix bug 64
+  o  9:171c6a79a27b  draft  fix bug 64
   |
   ~
 
@@ -204,38 +198,36 @@
   $ hg commit -u carl -d '8 0' -m 'debug hack'
   $ echo 'more useful' >> file1.c
   $ hg commit -u carl -d '9 0' -m 'more work'
-  $ hg shortlog -G -r 17::
-  @  20:ea8fafca914b  draft  more work
+  $ hg shortlog -G -r 91b4b0f8b5c5::
+  @  18:ea8fafca914b  draft  more work
   |
-  o  19:b23d06b457a8  draft  debug hack
+  o  17:b23d06b457a8  draft  debug hack
   |
-  o  18:1f33e68b18b9  draft  useful work
+  o  16:1f33e68b18b9  draft  useful work
   |
-  o  17:91b4b0f8b5c5  draft  feature 23
+  o  15:91b4b0f8b5c5  draft  feature 23
   |
   ~
 
 example 8: prune an older changeset (figures 8, 9)
-  $ hg prune 19
+  $ hg prune b23d06b457a8
   1 changesets pruned
-  1 new unstable changesets
-  $ hg --hidden shortlog -G -r 18::
-  @  20:ea8fafca914b  draft  more work
+  1 new orphan changesets
+  $ hg --hidden shortlog -G -r b23d06b457a8::
+  @  18:ea8fafca914b  draft  more work
   |
-  x  19:b23d06b457a8  draft  debug hack
-  |
-  o  18:1f33e68b18b9  draft  useful work
+  x  17:b23d06b457a8  draft  debug hack
   |
   ~
   $ hg evolve -q --all --any
-  $ hg --hidden shortlog -G -r 18::
-  @  21:4393e5877437  draft  more work
+  $ hg --hidden shortlog -G -r 1f33e68b18b9::
+  @  19:4393e5877437  draft  more work
   |
-  | x  20:ea8fafca914b  draft  more work
+  | x  18:ea8fafca914b  draft  more work
   | |
-  | x  19:b23d06b457a8  draft  debug hack
+  | x  17:b23d06b457a8  draft  debug hack
   |/
-  o  18:1f33e68b18b9  draft  useful work
+  o  16:1f33e68b18b9  draft  useful work
   |
   ~
 
@@ -246,35 +238,35 @@
   $ hg commit -u dan -d '11 0' -m 'fix bug 53'
   $ echo 'and this handles bug 67' >> file1.c
   $ hg commit -u dan -d '12 0' -m 'fix bug 67'
-  $ hg update 22
+  $ hg update -r f84357446753
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg shortlog -G -r 21::
-  o  23:4db2428c8ae3  draft  fix bug 67
+  $ hg shortlog -G -r 4393e5877437::
+  o  21:4db2428c8ae3  draft  fix bug 67
   |
-  @  22:f84357446753  draft  fix bug 53
+  @  20:f84357446753  draft  fix bug 53
   |
-  o  21:4393e5877437  draft  more work
+  o  19:4393e5877437  draft  more work
   |
   ~
   $ hg uncommit file2.c
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg status
   M file2.c
   $ hg revert file2.c
   $ hg evolve --all --any
-  move:[23] fix bug 67
-  atop:[24] fix bug 53
+  move:[21] fix bug 67
+  atop:[22] fix bug 53
   working directory is now at 0d972d6888e6
-  $ hg --hidden shortlog -G -r 21::
-  @  25:0d972d6888e6  draft  fix bug 67
+  $ hg --hidden shortlog -G -r 4393e5877437::
+  @  23:0d972d6888e6  draft  fix bug 67
   |
-  o  24:71bb83d674c5  draft  fix bug 53
+  o  22:71bb83d674c5  draft  fix bug 53
   |
-  | x  23:4db2428c8ae3  draft  fix bug 67
+  | x  21:4db2428c8ae3  draft  fix bug 67
   | |
-  | x  22:f84357446753  draft  fix bug 53
+  | x  20:f84357446753  draft  fix bug 53
   |/
-  o  21:4393e5877437  draft  more work
+  o  19:4393e5877437  draft  more work
   |
   ~
   $ rm file2.c.orig
@@ -286,48 +278,48 @@
   $ hg commit -u dan -d '11 0' -m 'fix a bug'
   $ echo 'new feature' >> file1.c
   $ hg commit -u dan -d '12 0' -m 'new feature'
-  $ hg update 26
+  $ hg update 5b31a1239ab9
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg --hidden shortlog -G -r 25::
-  o  27:fbb3c6d50427  draft  new feature
+  $ hg --hidden shortlog -G -r 0d972d6888e6::
+  o  25:fbb3c6d50427  draft  new feature
   |
-  @  26:5b31a1239ab9  draft  fix a bug
+  @  24:5b31a1239ab9  draft  fix a bug
   |
-  o  25:0d972d6888e6  draft  fix bug 67
+  o  23:0d972d6888e6  draft  fix bug 67
   |
   ~
   $ hg uncommit file2.c
-  1 new unstable changesets
+  1 new orphan changesets
   $ hg status
   M file2.c
   $ hg commit -m 'useful tweak'
-  $ hg --hidden shortlog -G -r 25::
-  @  29:51e0d8c0a922  draft  useful tweak
+  $ hg --hidden shortlog -G -r 0d972d6888e6::
+  @  27:51e0d8c0a922  draft  useful tweak
   |
-  o  28:2594e98553a9  draft  fix a bug
+  o  26:2594e98553a9  draft  fix a bug
   |
-  | o  27:fbb3c6d50427  draft  new feature
+  | o  25:fbb3c6d50427  draft  new feature
   | |
-  | x  26:5b31a1239ab9  draft  fix a bug
+  | x  24:5b31a1239ab9  draft  fix a bug
   |/
-  o  25:0d972d6888e6  draft  fix bug 67
+  o  23:0d972d6888e6  draft  fix bug 67
   |
   ~
   $ hg evolve --all --any
-  move:[27] new feature
-  atop:[28] fix a bug
+  move:[25] new feature
+  atop:[26] fix a bug
   working directory is now at 166c1c368ab6
-  $ hg --hidden shortlog -G -r 25::
-  @  30:166c1c368ab6  draft  new feature
+  $ hg --hidden shortlog -G -r 0d972d6888e6::
+  @  28:166c1c368ab6  draft  new feature
   |
-  | o  29:51e0d8c0a922  draft  useful tweak
+  | o  27:51e0d8c0a922  draft  useful tweak
   |/
-  o  28:2594e98553a9  draft  fix a bug
+  o  26:2594e98553a9  draft  fix a bug
   |
-  | x  27:fbb3c6d50427  draft  new feature
+  | x  25:fbb3c6d50427  draft  new feature
   | |
-  | x  26:5b31a1239ab9  draft  fix a bug
+  | x  24:5b31a1239ab9  draft  fix a bug
   |/
-  o  25:0d972d6888e6  draft  fix bug 67
+  o  23:0d972d6888e6  draft  fix bug 67
   |
   ~
--- a/tests/test-wireproto-bundle1.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-wireproto-bundle1.t	Tue Nov 14 23:04:04 2017 +0100
@@ -50,6 +50,7 @@
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 2 files
+  new changesets 8685c6d34325:4957bfdac07e
   (run 'hg update' to get a working copy)
   $ hg push -R ../other
   pushing to ssh://user@dummy/server
@@ -69,7 +70,7 @@
   remote: adding manifests
   remote: adding file changes
   remote: added 1 changesets with 1 changes to 1 files (+1 heads)
-  remote: 2 new obsolescence markers
+  remote: 1 new obsolescence markers
   remote: obsoleted 1 changesets
   $ hg push
   pushing to ssh://user@dummy/server
@@ -87,8 +88,9 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to [12] files \(\+1 heads\) (re)
-  2 new obsolescence markers
+  1 new obsolescence markers
   obsoleted 1 changesets
+  new changesets 9d1c114e7797
   (run 'hg heads' to see heads)
   $ hg -R ../other pull
   pulling from ssh://user@dummy/server
--- a/tests/test-wireproto.t	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/test-wireproto.t	Tue Nov 14 23:04:04 2017 +0100
@@ -53,6 +53,7 @@
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 2 files
+  new changesets 8685c6d34325:4957bfdac07e
   (run 'hg update' to get a working copy)
   $ hg push -R ../other
   pushing to ssh://user@dummy/server
@@ -72,8 +73,8 @@
   remote: adding manifests
   remote: adding file changes
   remote: added 1 changesets with 1 changes to 1 files (+1 heads)
-  remote: obsmarker-exchange: 151 bytes received
-  remote: 2 new obsolescence markers
+  remote: obsmarker-exchange: 92 bytes received
+  remote: 1 new obsolescence markers
   remote: obsoleted 1 changesets
   $ hg push
   pushing to ssh://user@dummy/server
@@ -91,9 +92,10 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to [12] files \(\+1 heads\) (re)
-  obsmarker-exchange: 151 bytes received
-  2 new obsolescence markers
+  obsmarker-exchange: 92 bytes received
+  1 new obsolescence markers
   obsoleted 1 changesets
+  new changesets 9d1c114e7797
   (run 'hg heads' to see heads)
   $ hg -R ../other pull
   pulling from ssh://user@dummy/server
@@ -115,8 +117,8 @@
   remote: adding manifests
   remote: adding file changes
   remote: added 1 changesets with 1 changes to 1 files
-  remote: obsmarker-exchange: 151 bytes received
-  remote: 2 new obsolescence markers
+  remote: obsmarker-exchange: 92 bytes received
+  remote: 1 new obsolescence markers
   $ hg -R ../other pull
   pulling from ssh://user@dummy/server
   searching for changes
@@ -124,8 +126,9 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  obsmarker-exchange: 151 bytes received
-  2 new obsolescence markers
+  obsmarker-exchange: 92 bytes received
+  1 new obsolescence markers
+  new changesets a5687ec59dd4
   (run 'hg update' to get a working copy)
 
 some common hidden
@@ -138,7 +141,7 @@
   remote: adding manifests
   remote: adding file changes
   remote: added 1 changesets with 0 changes to 1 files (+1 heads)
-  remote: obsmarker-exchange: 226 bytes received
+  remote: obsmarker-exchange: 167 bytes received
   remote: 1 new obsolescence markers
   remote: obsoleted 1 changesets
   $ hg -R ../other pull
@@ -148,9 +151,10 @@
   adding manifests
   adding file changes
   added 1 changesets with 0 changes to 1 files (+1 heads)
-  obsmarker-exchange: 226 bytes received
+  obsmarker-exchange: 167 bytes received
   1 new obsolescence markers
   obsoleted 1 changesets
+  new changesets * (glob)
   (run 'hg heads' to see heads)
 
 test discovery avoid exchanging known markers
@@ -173,7 +177,7 @@
   (skipping discovery of obsolescence markers, will exchange everything)
   (controled by 'experimental.evolution.obsdiscovery' configuration)
   no changes found
-  remote: obsmarker-exchange: 376 bytes received
+  remote: obsmarker-exchange: 258 bytes received
   [1]
   $ hg -R ../other pull --config experimental.evolution.obsdiscovery=no
   pulling from ssh://user@dummy/server
@@ -181,6 +185,68 @@
   no changes found
   (skipping discovery of obsolescence markers, will exchange everything)
   (controled by 'experimental.evolution.obsdiscovery' configuration)
-  obsmarker-exchange: 376 bytes received
+  obsmarker-exchange: 258 bytes received
 
   $ cd ..
+
+And disable it server side too:
+
+  $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log  --config experimental.evolution.obsdiscovery=no
+  $ cat hg.pid >> $DAEMON_PIDS
+
+  $ curl -s http://localhost:$HGPORT/?cmd=capabilities
+  _evoext_getbundle_obscommon batch branchmap bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Aobsmarkers%3DV0%2CV1%0Aphases%3Dheads%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps changegroupsubset compression=zstd,zlib getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash (no-eol)
+
+Check we cannot use pushkey for marker exchange anymore
+
+  $ hg debugpushkey http://localhost:$HGPORT/ obsolete
+  abort: HTTP Error 410: won't exchange obsmarkers through pushkey
+  [255]
+  $ hg debugpushkey ssh://user@dummy/server obsolete
+  remote: abort: won't exchange obsmarkers through pushkey
+  remote: (upgrade your client or server to use the bundle2 protocol)
+  abort: unexpected response: empty string
+  [255]
+
+(do some extra pulling to be sure)
+
+  $ hg -R client pull http://localhost:$HGPORT/
+  pulling from http://localhost:$HGPORT/
+  searching for changes
+  no changes found
+  obsmarker-exchange: 258 bytes received
+
+  $ hg -R client pull http://localhost:$HGPORT/ --config experimental.evolution=createmarkers
+  pulling from http://localhost:$HGPORT/
+  searching for changes
+  no changes found
+
+  $ hg -R client pull http://localhost:$HGPORT/ --config experimental.evolution=createmarkers --config extensions.evolve='!'
+  pulling from http://localhost:$HGPORT/
+  searching for changes
+  no changes found
+
+But we do let it goes fine on repository with exchange disabled:
+
+  $ $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ hg serve -R server -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log  --config experimental.evolution='!'
+  $ hg debugpushkey http://localhost:$HGPORT/ obsolete
+
+(do some extra pulling to be sure)
+
+  $ hg -R client pull http://localhost:$HGPORT/
+  pulling from http://localhost:$HGPORT/
+  searching for changes
+  no changes found
+
+  $ hg -R client pull http://localhost:$HGPORT/ --config experimental.evolution=createmarkers
+  pulling from http://localhost:$HGPORT/
+  searching for changes
+  no changes found
+
+  $ hg -R client pull http://localhost:$HGPORT/ --config experimental.evolution=createmarkers --config extensions.evolve='!'
+  pulling from http://localhost:$HGPORT/
+  searching for changes
+  no changes found
+
+  $ $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/testlib/docgraph_setup.sh	Tue Nov 14 23:04:04 2017 +0100
@@ -0,0 +1,6 @@
+. $TESTDIR/testlib/pythonpath.sh
+
+cat >> $HGRCPATH << EOF
+[extensions]
+docgraph=
+EOF
--- a/tests/testlib/topic_setup.sh	Tue Jul 25 02:29:28 2017 +0200
+++ b/tests/testlib/topic_setup.sh	Tue Nov 14 23:04:04 2017 +0100
@@ -1,4 +1,5 @@
 #!/bin/sh
+. $TESTDIR/testlib/pythonpath.sh
 
 # This file holds logic that is used in many tests.
 # It can be called in a test like this:
@@ -11,5 +12,5 @@
 
 [extensions]
 rebase=
+topic=
 EOF
-echo "topic=$(echo $(dirname $TESTDIR))/hgext3rd/topic" >> $HGRCPATH