Defining and manipulating a WIP feature branch
Andrew Halberstadt
ahalberstadt at mozilla.com
Fri Feb 27 21:46:39 UTC 2015
Hi,
I recently switched from mq to a multi-headed development workflow. The
new workflow is much better, but there were still some things missing,
namely the concept of a "feature branch" (like a git-style branch).
Bookmarks come close, but it is difficult to guess what they are based
on, there is no concept of "ownership" from a commit to a bookmark. The
revset "only(<bookmark>) and not public()" comes pretty close, but
doesn't quite get there. I want to be able to rebase bookmarks on top of
one another, and have a convenient shortcut for expanding a bookmark
label to the full revset of commits within that bookmark.
E.g, with:
o rev: 5
| bookmark: C
|
o rev: 4
|
o rev: 3
| bookmark: B
|
o rev: 2
|
o rev: 1
| bookmark: A
|
o rev: 0
I want "hg log -r B" to return 2:3. I came up with an informal
definition for a WIP feature. A commit /C/ is "within" a WIP feature
branch ending at revision /R/ if:
1. /C /is/R/ or /C/ is an ancestor of /R/
2. /C/ is not public
3. /C/ is not a merge commit
4. no bookmarks exist in [/C/, /R/) for /C/ != /R/
There's no requirement that /R/ be a head, nor any requirement that /R/
have a bookmark. This definition can be implemented by a somewhat
complicated revset (thanks to smacleod for coming up with it):
[revsetalias]
feature($1) = ($1 or (ancestors($1) and not (excludemarks($1) or hg ancestors(excludemarks($1))))) and not public() and not merge()
excludemarks($1) = ancestors(parents($1)) and bookmark()
This lets you manipulate a feature* as a series of commits:
hg log -r 'feature(B)'
That revset is a bit tricky to grok, and it requires some extra typing,
so I wrote an extension:
https://bitbucket.org/halbersa/bookbinder
Bookbinder does two things:
1. It defines an actual 'feature' revset (not an alias)
2. It wraps (almost) all commands with a --rev argument. If --rev
<bookmark> is detected, <bookmark> is replaced with
'feature(<bookmark>)'. It is still possible to treat the bookmark as
a label by escaping it with a period.
Bookbinder makes it really convenient to do things like:
hg log -r <bookmark>
hg fold -r <bookmark>
hg rebase -r <bookmark> -d <dest>
hg graft -r <bookmark>
etc..
I'd like to get feedback on this approach. Is the definition sane? Is
the extension sane? Would others find it useful? What things could be
done in mercurial core to make the situation better? I'm pretty new to
the world of mercurial extensions/development, so please bear with me as
I figure out what is or isn't a good approach.
Cheers,
Andrew
* I'm not too happy with the name feature, but couldn't think of
anything better.. suggestions welcome!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://selenic.com/pipermail/mercurial/attachments/20150227/f4c6349f/attachment.html>
More information about the Mercurial
mailing list