How to correctly close a feature branch in Mercurial?

I’ve finished working on a feature branch feature-x. I want to merge results back to the default branch and close feature-x in order to get rid of it in the output of hg branches.

I came up with the following scenario, but it has some issues:

  • How to rename an SVN branch and update references in an existing sandbox?
  • Your configuration specifies to merge with the <branch name> from the remote, but no such ref was fetched.?
  • Is it possible to apply a commit to all branches in git?
  • How to Remove a Branch from the Middle of the Hierarchy?
  • Remove a single merged branch from master branch
  • Is there an easy way to change to previously active branch?
  • $ 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 (changests 4041) is closed, but there is one new head, the closing branch changeset 44, that will be listed in hg 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:

    • Is there a downside to this Mercurial workflow: named branch “dead” head?

  • Make shell prompt show current head when in a VCS
  • git: How to create a branch of my current work, but stay on my original branch
  • Jenkins Multibranch Pipelines - Configuring properties in branches?
  • Git: merge to master, then push back to all branches
  • Making local copy of git branch current
  • Easy GIT: When checking out another local branch, what happens to changes?
  • 4 Solutions collect form web for “How to correctly close a feature branch in Mercurial?”

    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:

    • Mercurial branching and bookmarks

    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.

    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 : )

    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.

    Git Baby is a git and github fan, let's start git clone.