Home

Branchident extension for Mercurial 1.4

Separating branch identity from branch name -- created by Adrian Buehlmann

Status: experimental, not to be used in production

See also BranchIdentityPlan.

The branchident extension adds an extra field 'branchid' in changesets if a branch name other than 'default' is committed (use 'hg log --debug' to print the extra fields).

The branch id is calculated as the sha-1 hash of the concatenation of date, username, branch name and the node id's of the parents. It is set on first commit of a new branch name.

Changesets having the same branch id are considered to be of the same branch.

The name of the branch is defined by the extra field 'branch' of the changeset with the highest revision number in the repo having that branch id. So the branch name of later changesets with the same branch id override earlier names of a branch.

A branch is continued on commit if the first parent already has a branch id. The new changeset gets the branch id of its first parent.

The branchident extension adds an additional option to the commit command:

    --rename-branch  rename the current branch

This option is to be used on commit after changing the branch name with 'hg branch <newname>' to rename the current branch. If --rename-branch is not specified on commit of a changed branch name, then a new branch with a new branch id is created.

To remove a branch name, just rename it to 'default' by doing:

    hg branch --force default
    hg ci --rename-branch

The branchident extension adds an additional option to the identify command:

    --branchid  show branch id

To show the branch id of a specific changeset use:

     hg identify --branchid --rev REV

This extension requires Mercurial version 1.4 or later.

Usage

Installation

Download branchident.py and enable the extension in your .hgrc (or mercurial.ini) with

[extensions]
branchident = /path/to/branchident.py

Creating a branch

To create a new branch forking off the default branch just use 'hg branch <name>' and commit. The branchid extension will then automatically assign a branch id:

$ hg branch green
marked working directory as branch green

To see the branch id of a changeset, you can use the identify command (abbreviated as 'id'):

$ hg id -r . --branchid
37405f2dafd1

By default, all commands print the short form of the branch id. Use --debug to see the full length branch id:

$ hg id -r . --branchid --debug
37405f2dafd128e0f37a7a821d714f45ffde7ac0

Use log --debug to see the branch id in the extra fields:

$ hg log -r . --debug
changeset:   1:c4e3f51005d1550f1204cc59a1120d9910174ea0
branch:      green
tag:         tip
parent:      0:d84beb0b6d77d9acedb56e596c400c24bc72cc00
parent:      -1:0000000000000000000000000000000000000000
manifest:    1:439538110d472411c6156668ed7fefc5658fe982
user:        Joe Tester <joe@example.com>
date:        Thu Jan 01 00:00:00 1970 +0000
extra:       branch=green
extra:       branchid=7@_-\xaf\xd1(\xe0\xf3zz\x82\x1dqOE\xff\xdez\xc0
description:
create green branch

The extension adds a new command 'branchids' which prints all branch ids in the repository with their effective branch name:

$ hg help branchids
hg branchids

aliases: brids

print branch ids with branch names

    Print all branch ids of the repository, together with their branch names.

    Note that branchids with branch names that have been renamed to 'default'
    are not shown (i.e. removed branch names are not shown).

So let's use that to see what happened:

$ hg branchids
37405f2dafd1 green

Again, use --debug to see the full length branch ids:

$ hg branchids --debug
37405f2dafd128e0f37a7a821d714f45ffde7ac0 green

Note that branch ids are not changeset ids. To print the changeset ids of the branch tips, just use 'hg branches' as you always did:

$ hg branches
green                          1:c4e3f51005d1
default                        0:d84beb0b6d77 (inactive)

Renaming a branch

If you have used that branch name for some time:

$ hg log
changeset:   3:3b8011fe22a5
branch:      green
tag:         tip
user:        Joe Tester <joe@example.com>
date:        Thu Jan 01 00:00:00 1970 +0000
summary:     another tweak

changeset:   2:face4c569e0d
branch:      green
user:        Joe Tester <joe@example.com>
date:        Thu Jan 01 00:00:00 1970 +0000
summary:     hacked something

changeset:   1:c4e3f51005d1
branch:      green
user:        Joe Tester <joe@example.com>
date:        Thu Jan 01 00:00:00 1970 +0000
summary:     create green branch

changeset:   0:d84beb0b6d77
user:        Joe Tester <joe@example.com>
date:        Thu Jan 01 00:00:00 1970 +0000
summary:     start

you can change the name of the existing green branch with:

$ hg branch blue
marked working directory as branch blue

$ hg ci -m"change branch name of green to blue" --rename-branch

Let's see the effect:

$ hg branchids
37405f2dafd1 blue

$ hg branches
blue                           4:a792e1b2b8f9
default                        0:d84beb0b6d77 (inactive)

$ hg log
changeset:   4:a792e1b2b8f9
branch:      blue
tag:         tip
user:        Joe Tester <joe@example.com>
date:        Thu Jan 01 00:00:00 1970 +0000
summary:     change branch name of green to blue

changeset:   3:3b8011fe22a5
branch:      blue
user:        Joe Tester <joe@example.com>
date:        Thu Jan 01 00:00:00 1970 +0000
summary:     another tweak

changeset:   2:face4c569e0d
branch:      blue
user:        Joe Tester <joe@example.com>
date:        Thu Jan 01 00:00:00 1970 +0000
summary:     hacked something

changeset:   1:c4e3f51005d1
branch:      blue
user:        Joe Tester <joe@example.com>
date:        Thu Jan 01 00:00:00 1970 +0000
summary:     create green branch

changeset:   0:d84beb0b6d77
user:        Joe Tester <joe@example.com>
date:        Thu Jan 01 00:00:00 1970 +0000
summary:     start

This assigns the new branch name to all changesets having the respective branch id. Note that this does not alter the previous changesets. The history of the repository is not altered.

The branch name is merely treated as a view into the repository and may thus be overriden by later changesets with the same branch id.

Assuming you have the following style in the file 'mystyle'

changeset = '{rev}:{node|short}{branches}, {tags}\"{desc|firstline|strip}\"\n{extras}\n'
start_tags = '['
tag = '{tag},'
last_tag = '{tag}] '
branch = ', branch:{branch}'
extra = 'extra: {key}={value|stringescape}\n'

you can see how the branch name change was done in the extra fields of the changesets by doing:

$ hg glog --style mystyle
@  4:a792e1b2b8f9, branch:blue, [tip] "change branch name of green to blue"
|  extra: branch=blue
|  extra: branchid=7@_-\xaf\xd1(\xe0\xf3zz\x82\x1dqOE\xff\xdez\xc0
|
o  3:3b8011fe22a5, branch:blue, "another tweak"
|  extra: branch=green
|  extra: branchid=7@_-\xaf\xd1(\xe0\xf3zz\x82\x1dqOE\xff\xdez\xc0
|
o  2:face4c569e0d, branch:blue, "hacked something"
|  extra: branch=green
|  extra: branchid=7@_-\xaf\xd1(\xe0\xf3zz\x82\x1dqOE\xff\xdez\xc0
|
o  1:c4e3f51005d1, branch:blue, "create green branch"
|  extra: branch=green
|  extra: branchid=7@_-\xaf\xd1(\xe0\xf3zz\x82\x1dqOE\xff\xdez\xc0
|
o  0:d84beb0b6d77, "start"
   extra: branch=default

(assuming you have the graphlog extension enabled).

Removing a branch name

Simply rename the branch to 'default' again by doing:

$ hg branch --force default
marked working directory as branch default

$ hg ci -m"remove branch name" --rename-branch

Now, hg branchids prints nothing, since there are no branch names other than 'default' left. Branch ids of branches that have been removed are not shown by 'hg branchids'.

$ hg branchids

But the branch id is still there:

$ hg id -r . --branchid --debug
37405f2dafd128e0f37a7a821d714f45ffde7ac0

but the name of the branch is now 'default'

$ hg id -r . --branch
default

$ hg branches
default                        5:f7d2f13a8a08

$ hg glog --style mystyle
@  5:f7d2f13a8a08, [tip] "remove branch name"
|  extra: branch=default
|  extra: branchid=7@_-\xaf\xd1(\xe0\xf3zz\x82\x1dqOE\xff\xdez\xc0
|
o  4:a792e1b2b8f9, "change branch name of green to blue"
|  extra: branch=blue
|  extra: branchid=7@_-\xaf\xd1(\xe0\xf3zz\x82\x1dqOE\xff\xdez\xc0
|
o  3:3b8011fe22a5, "another tweak"
|  extra: branch=green
|  extra: branchid=7@_-\xaf\xd1(\xe0\xf3zz\x82\x1dqOE\xff\xdez\xc0
|
o  2:face4c569e0d, "hacked something"
|  extra: branch=green
|  extra: branchid=7@_-\xaf\xd1(\xe0\xf3zz\x82\x1dqOE\xff\xdez\xc0
|
o  1:c4e3f51005d1, "create green branch"
|  extra: branch=green
|  extra: branchid=7@_-\xaf\xd1(\xe0\xf3zz\x82\x1dqOE\xff\xdez\xc0
|
o  0:d84beb0b6d77, "start"
   extra: branch=default

Testing

Clone the repo with:

$ hg clone http://bitbucket.org/abuehl/hgext-branchident/

Then cd into the repo root and execute 'run-test'

$ cd hgext-branchident
$ ./run-test

This should produce no output. run-test executes test-branchident and diffs test-branchident.out.

Updated

Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.