How to correctly close a feature branch in Mercurial?
Solution 1
One way is to just leave merged feature branches open (and inactive):
$ hg up default
$ hg merge feature-x
$ hg ci -m merge
$ hg heads
(1 head)
$ hg branches
default 43:...
feature-x 41:...
(2 branches)
$ hg branches -a
default 43:...
(1 branch)
Another way is to close a feature branch before merging using an extra commit:
$ hg up feature-x
$ hg ci -m 'Closed branch feature-x' --close-branch
$ hg up default
$ hg merge feature-x
$ hg ci -m merge
$ hg heads
(1 head)
$ hg branches
default 43:...
(1 branch)
The first one is simpler, but it leaves an open branch. The second one leaves no open heads/branches, but it requires one more auxiliary commit. One may combine the last actual commit to the feature branch with this extra commit using --close-branch
, but one should know in advance which commit will be the last one.
Update: Since Mercurial 1.5 you can close the branch at any time so it will not appear in both hg branches
and hg heads
anymore. The only thing that could possibly annoy you is that technically the revision graph will still have one more revision without childen.
Update 2: Since Mercurial 1.8 bookmarks have become a core feature of Mercurial. Bookmarks are more convenient for branching than named branches. See also this question:
Solution 2
imho there are two cases for branches that were forgot to close
Case 1: branch was not merged into default
in this case I update to the branch and do another commit with --close-branch, unfortunatly this elects the branch to become the new tip and hence before pushing it to other clones I make sure that the real tip receives some more changes and others don't get confused about that strange tip.
hg up myBranch
hg commit --close-branch
Case 2: branch was merged into default
This case is not that much different from case 1 and it can be solved by reproducing the steps for case 1 and two additional ones.
in this case I update to the branch changeset, do another commit with --close-branch and merge the new changeset that became the tip into default. the last operation creates a new tip that is in the default branch - HOORAY!
hg up myBranch
hg commit --close-branch
hg up default
hg merge myBranch
Hope this helps future readers.
Solution 3
EDIT ouch, too late... I know read your comment stating that you want to keep the feature-x changeset around, so the cloning approach here doesn't work.
I'll still let the answer here for it may help others.
If you want to completely get rid of "feature X", because, for example, it didn't work, you can clone. This is one of the method explained in the article and it does work, and it talks specifically about heads.
As far as I understand you have this and want to get rid of the "feature-x" head once and for all:
@ changeset: 7:00a7f69c8335
|\ tag: tip
| | parent: 4:31b6f976956b
| | parent: 2:0a834fa43688
| | summary: merge
| |
| | o changeset: 5:013a3e954cfd
| |/ summary: Closed branch feature-x
| |
| o changeset: 4:31b6f976956b
| | summary: Changeset2
| |
| o changeset: 3:5cb34be9e777
| | parent: 1:1cc843e7f4b5
| | summary: Changeset 1
| |
o | changeset: 2:0a834fa43688
|/ summary: Changeset C
|
o changeset: 1:1cc843e7f4b5
| summary: Changeset B
|
o changeset: 0:a9afb25eaede
summary: Changeset A
So you do this:
hg clone . ../cleanedrepo --rev 7
And you'll have the following, and you'll see that feature-x is indeed gone:
@ changeset: 5:00a7f69c8335
|\ tag: tip
| | parent: 4:31b6f976956b
| | parent: 2:0a834fa43688
| | summary: merge
| |
| o changeset: 4:31b6f976956b
| | summary: Changeset2
| |
| o changeset: 3:5cb34be9e777
| | parent: 1:1cc843e7f4b5
| | summary: Changeset 1
| |
o | changeset: 2:0a834fa43688
|/ summary: Changeset C
|
o changeset: 1:1cc843e7f4b5
| summary: Changeset B
|
o changeset: 0:a9afb25eaede
summary: Changeset A
I may have misunderstood what you wanted but please don't mod down, I took time reproducing your use case : )
Solution 4
It is strange, that no one yet has suggested the most robust way of closing a feature branches... You can just combine merge commit with --close-branch flag (i.e. commit modified files and close the branch simultaneously):
hg up feature-x
hg merge default
hg ci -m "Merge feature-x and close branch" --close-branch
hg branch default -f
So, that is all. No one extra head on revgraph. No extra commit.
Related videos on Youtube
Andrey Vlasovskikh
Updated on December 02, 2020Comments
-
Andrey Vlasovskikh over 3 years
I've finished working on a feature branch
feature-x
. I want to merge results back to thedefault
branch and closefeature-x
in order to get rid of it in the output ofhg branches
.I came up with the following scenario, but it has some issues:
$ hg up default $ hg merge feature-x $ hg ci -m merge $ hg up feature-x $ hg ci -m 'Closed branch feature-x' --close-branch
So the
feature-x
branch (changests40
-41
) is closed, but there is one new head, the closing branch changeset44
, that will be listed inhg heads
every time:$ hg log ... o 44 Closed branch feature-x | | @ 43 merge |/| | o 42 Changeset C | | o | 41 Changeset 2 | | o | 40 Changeset 1 |/ o 39 Changeset B | o 38 Changeset A |
Update: It appears that since version 1.5 Mercurial doesn't show heads of closed branches in the output of
hg heads
anymore.Is it possible to close a merged branch without leaving one more head? Is there more correct way to close a feature branch?
Related questions:
-
SyntaxT3rr0r over 14 years@Andrey: but the article pointed out does NOT only talk about "--close-branch". It shows four ways to prune your branch. If you really don't want it anymore, you can clone as explained in the article. The only 'problem' is if for whatever reason you want to close it, yet keep it around.
-
Andrey Vlasovskikh over 14 years@WizardOfOdds Yes, I've read the whole article on pruning dead branches. I want the branch to stay in the revision history, not to throw it away. Previously I just merged feature branches into
default
without "closing" them. It resulted in 0 new heads but such branches were visible inhg branches
forever (as inactive branches). -
DanMan about 10 yearsTo develop features I tend to clone the whole repository and then merge it back in once the feature is finished. I don't like to have the remains of (closed) branches in the history.
-
-
MB. almost 12 yearsGood clear answer for a Mercurial newbie like me. And thank you for not using "ci" which isn't listed as one of the commands by hg help, so I don't know what it means :)
-
Chris Morgan about 11 years@MB.: in such cases,
hg help ci
will explain it to you. -
Gili over 9 yearsIt is not necessarily true that
Bookmarks are more convenient for branching than named branches
. Hg bookmarks are not the same thing as Git branches. They are full of many edge cases which make them unsuitable as feature branches. For example: when you clone a repository you will end up with the latest commit in thedefault
branch. If you use bookmarks, this changeset corresponds to a random (unstable) bookmark. If you use named branches, you will get the latest commit in the stable/default branch, which is usually what you want. Bookmarks will get there one day, but they're not there yet. -
Gili over 9 yearsI use bookmarks as private tags that are only visible in my local repository. They act as reminders of changesets I need to revisit.
-
Andrey Vlasovskikh over 9 yearsI've mentioned it in my answer: """One may combine the last actual commit to the feature branch with this extra commit using --close-branch, but one should know in advance which commit will be the last one."""
-
tav over 9 yearsOk, I see. I just don't quite understand the last part of the sentence ("but one should know ..."), so I thought it means something different. Also I would like to note that this method is not supported by most GUI tools (TortoiseHG, SourceTree etc.).
-
kasperd over 8 years@AndreyVlasovskikh The point of this answer is to close the branch in the merge rather than in the last commit of the feature branch.
-
kasperd over 8 years@tav Before issuing the
merge
command it may be a good idea to usehg branch
to verify that the branch name of the merge is the one that you want to keep open. -
kasperd over 8 yearsI created a test project with a handful of commits to test this, and it worked great. Then I tried to use it on a real project, and it ended up closing
default
instead of the feature branch. Now I am confused. -
kasperd over 8 yearsOn a closer look it appears the merge will always be on the closed branch. The desired outcome would be that is on the branch of one of its parents and closes the branch of its other parent. That seems not to be possible. So this doesn't look like a workable solution after all. Too bad, I really wanted to use a merge as the closing point of a branch.
-
kasperd over 8 yearsI tried to follow this approach, but I still get an error when trying to push:
abort: push creates new remote branches:
. What could I have done wrong? -
Kosta_Arnorsky about 5 yearsLooks like this should work because it resets branch name using --force key, but you should be careful about using it on any shared repository. I've just started using Mercurial, but experience with other SCCS tells me that renaming default/main/trunk can easily make you fellow devs unhappy.
-
Chip Grandits almost 5 yearsI believe as the 'hg merge' command will tell you, there is still another commit at the end