How do I list all unmerged branches?
That is, I want a list of all branches that are not closed, and their head is not merged into some other branch.
You can use the branches command
hg branches --active
Branches are considered active if their last commit has not been merged into another branch. Closed branches won't appear in the output at all.
If you need to handle the list programmatically, and can use .NET, there is also a Mercurial .NET library that can make this easy.
According to http://bugs.python.org/issue15917 this should work:
hg log -r "head()-parents(merge())-closed()-tag(tip)" --template "{branch}\n"
The corresponding TortoiseHg filter is
head() and not closed() and not parents(merge()) and not tag(tip)
Related
How can I duplicate a branch in Mercurial? I need the new branch to be against head (as the first one is).
The GIT equivalent (if I was in branch-a) would be:
git checkout -b branch-b
A Mercurial branch is a named entity that consists of all the commits contained within the branch. So in order to duplicate some existing branch, you must also duplicate all of its commits to new commits that are in the new branch. We then get into metaphysics arguments about commit identity. It's probably not a good idea to go here at all, but if you do want to go here, use hg graft to copy all the desired commits into the new branch.
A Git branch consists of a name containing a raw commit hash ID. So duplicating a Git branch under a new name is trivial. Note that the set of branches that contain any given commit changes dynamically over time: a branch that was only on feature/tall may now only be on master, even though that commit is still that commit, even via most of these metaphysical arguments. (Only the "no identity over time" argument lets us claim that this is not the same commit.)
Another way to put it is that Mercurial's branches actually mean something, but Git's don't. If you need true branches, you can't use Git in the first place. Don't try to import Git's bizzareness into Mercurial: you'll just make your own life miserable.
Meanwhile, though, Mercurial contains a DAG just like Git. If you use Mercurial bookmarks, those work like Git branches. It's probably wiser, then, to just use bookmarks and be done with it.
If all else fails, see hg graft.
the new branch to be against head
What is this (in usual business-term, not Git-lingua)? While in common (and in details) #torek is totally right, he forgot to write exact command-set, something like
hg up <rev-id>
hg branch <new-branch-name>
hg graft -r "branch(old-branch-name)" --log
I know Rebase is a (bundled) extension, while Graft is a core feature (that replaced the Transplant (bundled) extension).
graft is documented as:
copy changes from other branches onto the current branch
This command uses Mercurial's merge logic to copy individual changes from other branches without merging branches in the history graph. This is sometimes known as 'backporting' or 'cherry-picking'.
rebase is documented as:
Rebase allows moving commits around in Mercurial's history (using a series of internal merges). This has many uses:
moving changesets between branches
"linearizing" history
reordering changesets
collapsing multiple changes into one changeset
Both seem to use merging to move or copy changesets between branches.
Graft copies. Rebase moves. But rebase --keep copies.
So often it seems I can accomplish my goal of copying a changeset either way.
Does it matter which one I use? When should I prefer one over the other?
E.g. should graft only be used when copying to a different named branch? Or only when there's just a single changeset?
Edit: Could it be that rebase is a potentially unsafe superset of graft, but can only be used with draft changesets during development for editing local history, while graft is a safe subset of rebase that can be used with public changesets during maintenance for backporting?
hg graft allows "cherry-picking," as you noted in your question. For example, you can run hg graft -D "2085::2093 and not 2091" to copy only some changes from another revision. By comparison, hg rebase (with or without --keep) will grab whatever changeset you specify and all of its decendant changes.
Also, rebase allows you to collapse changesets (with --collapse). As far as I can tell, graft does not.
One more difference I have noticed: hg graft --edit 123 lets you graft revision 123 to the working directory and edit the commit message. I can't find an hg rebase equivalent. I should point out, though, that hg histedit also allows for editing the commit message while rebasing.
There are probably other differences that I am not thinking of. SO community: feel free to point those out in the comments, and I will happily revise this answer to make it more complete.
See the graft documentation and the Rebase Extension documentation for more details.
I am currently using Mercurial for sub-version control in my project. Now I am suppose to work on a new branch 2.7 but I confuse to work with branch 2.6, I have developed the new feature which the feature on 2.7 but I build on 2.6. And now I want to move this feature to branch 2.7 properly but I don't know how can I move it properly. Is there any way?
I would recommend using hg graft, which copies changes from one branch to another and unlike hg rebase is not destructive (relevant if you're doing this for the first time and may be making mistakes or if you need the feature to be present on both branches).
To copy changes to a branch dest-branch, do the following. First update to the branch you want to copy the changes to:
hg update dest-branch
Then, use graft to copy the revisions you want from the original branch, e.g.:
hg graft -r start..end
where start is the first revision you want to graft from the source branch and end is the last revision.
You may encounter conflicts if they can't be merged cleanly, which you have to resolve them (as you'd do in a merge), then use hg graft --continue to graft the remaining revisions.
The magic word is RTFM - hg help rebase
I'd like to get an hg status list for a range of revisions, and also filter the list for a given branch name.
e.g. The issue with this command is that it includes changes from multiple branches, and I'm only interested in a particular branch:
hg status --rev 150:175
Is there a way to add an additional filter by branch for this list with hg or a mainstream hg tool?
You can do this using revsets:
hg status --rev "150:175 and branch(<BRANCH_NAME>)"
I believe that you can use revsets (hg help revsets) to do this. There are a large number of options for selecting revisions, but I think that what you want would be something along these lines:
hg status --rev "150:175 and branch(mybranch)"
Revsets can be tricky at times, but they are very powerful, and so well worth reading about them in hg help.
I've encountered a problem in my Mercurial workflow when experimenting with implementing a certain feature. I was trying three different approaches to implementing the feature by commiting each update followed by updating to the previous changeset - so I end up with three different branches.
Once I have chosen one of the branches to be the "correct" implementation of the feature, I want to remove the other branches so that I don't have multiple heads. How do I do this in a simple way? I ended up merging the three branches together which was pointless because I only ever wanted the code from one branch.
In addition to hg strip from the mq extension, you can simply use the standard clone command:
$ hg clone -r the-good-head . ../pruned
to get a clone in ../pruned that holds only the good head (and all its ancestors). This is the safe, built-in way to prune things in Mercurial and it has the advantage that you still have both repositories intact after the command. So if you make a mistake, then just delete the ../pruned clone.
The following closes a branch
hg commit --close-branch
It will not show up in
hg branches or hg heads
Enable the built-in mq extension and run hg strip.
#pyfunc's answer keeps the closed branches in revision history, which is what I would actually do unless your unwanted branches are huge.