topic extension#

support for topic branches

Topic branches are lightweight branches which fade out when changes are finalized (move to the public phase).

Compared to bookmark, topic is reference carried by each changesets of the series instead of just the single head revision. Topic are quite similar to the way named branch work, except they eventually fade away when the changeset becomes part of the immutable history. Changeset can belong to both a topic and a named branch, but as long as it is mutable, its topic identity will prevail. As a result, default destination for 'update', 'merge', etc... will take topic into account. When a topic is active these operations will only consider other changesets on that topic (and, in some occurrence, bare changeset on same branch). When no topic is active, changeset with topic will be ignored and only bare one on the same branch will be taken in account.

There is currently two commands to be used with that extension: 'topics' and 'stack'.

The 'hg topics' command is used to set the current topic, change and list existing one. 'hg topics --verbose' will list various information related to each topic.

The 'stack' will show you information about the stack of commit belonging to your current topic.

Topic is offering you aliases reference to changeset in your current topic stack as 's#'. For example, 's1' refers to the root of your stack, 's2' to the second commits, etc. The 'hg stack' command show these number. 's0' can be used to refer to the parent of the topic root. Updating using hg up s0 will keep the topic active.

Push behavior will change a bit with topic. When pushing to a publishing repository the changesets will turn public and the topic data on them will fade away. The logic regarding pushing new heads will behave has before, ignore any topic related data. When pushing to a non-publishing repository (supporting topic), the head checking will be done taking topic data into account. Push will complain about multiple heads on a branch if you push multiple heads with no topic information on them (or multiple public heads). But pushing a new topic will not requires any specific flag. However, pushing multiple heads on a topic will be met with the usual warning.

The 'evolve' extension takes 'topic' into account. 'hg evolve --all' will evolve all changesets in the active topic. In addition, by default. 'hg next' and 'hg prev' will stick to the current topic.

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#

Topics vanish when changesets move to the public phase. Moving to the public phase usually happens on push, but it is possible to modify this behavior. The server needs to have specific config for this.

  • everything pushed becomes public (the default):

    [phases]
    publish = yes
    
  • nothing pushed turns public:

    [phases]
    publish = no
    
  • topic branches are not published, changesets without topic are:

    [phases]
    publish = no
    [experimental]
    topic.publish-bare-branch = yes
    

In addition, `hg push` command has a --publish flag. When used, the pushed revisions are published if the push succeeds. It also applies to common revisions selected by the push.

One can prevent any publishing from happening in a repository using:

[experimental]
topic.allow-publish = no

Server side visibility#

Serving changesets with topics to clients without topic extension can get confusing. Such clients will have multiple anonymous heads without a clear way to distinguish them. They will also "lose" the canonical heads of the branch.

To avoid this confusion, server can be configured to only serve changesets with topics to clients with the topic extension (version 9.3+). This might become the default in future:

[experimental]
topic.server-gate-topic-changesets = yes

Explicitly merging in the target branch#

By default, Mercurial will not let your merge a topic into its target branch if that topic is already based on the head of that branch. In other word, Mercurial will not let your create a merge that will eventually have two parents in the same branches, one parent being the ancestors of the other parent. This behavior can be lifted using the following config:

[experimental]
topic.linear-merge = allow-from-bare-branch

When this option is set to allow-from-bare-branch, it is possible to merge a topic branch from a bare branch (commit an active topic (eg: public one)) regardless of the topology. The result would typically looks like that:

@    summary: resulting merge commit
|\   branch:  my-branch
| |
| o  summary: some more change in a topic, the merge "target"
| |  branch:  my-branch
| |  topic:   my-topic
| |
| o  summary: some change in a topic
|/   branch:  my-branch
|    topic:   my-topic
|
o    summary: previous head of the branch, the merge "source"
|    branch:  my-branch

Commands

  • stack: list all changesets in a topic and other information

  • topics: View current topic, set current topic, change topic for a set of revisions, or see all topics.