I was wondering, what is the purpose of closing a branch. As for issue-1 branch, I had already close. But
I still can see issue1-1 in my revision graph
I still can switch to branch issue1-1, and continue to commit.
So, what is the whole point of closing a branch?
See: https://www.mercurial-scm.org/wiki/PruningDeadBranches
It is informational so that hg branches will show that these branches are closed. And hg heads --active will not display any heads that are marked closed.
In a long run, number of branches can be considerable and can add to informational noise. This is a good way to prune some of those noise.
This is exactly why named branches probably aren't the right choice for per-feature and per-issue branches -- you can hide them but you can't eliminate them. Consider reserving named branches for long-lived concepts like 'stable', 'experimental', etc. For per-issue and per-feature branching either anonymous branches, clone branches, or bookmarks are better solutions. They're all described wonderfully here:
A Guide to Branching In Mercurial.
Related
I really like the Hg Flow for Mercurial repositories. we are currently using Bitbucket, and in each product multiple developers are working. basically they can work as below:
a team might work on a single feature.
another team might work on a release/hot fix.
So do i keep the "develop" branch in BitBucket or local repositories. and how about feature branches, should i push them to the central repository and remove when required. i assume we should do so right?
Thanks
I personally neither use git flow or hg flow as tools, but I do use some of the methods for my own projects (manually).
Before going into detail, you always need to provide branches in the main/bitbucket repository when multiple people need to merge or branch from them.
This definately includes "develop" and probably also features/fixes multiple people need to work on (unless you have another repository or method to exchange branches/commits between them)
The difference between using git and mercurial/hg is relevant here, since the branching models are quite different.
See A Guide to Branching in Mercurial for details. Using hg bookmarks would be quite similar to what git does with branches, but there is no full support for the bookmark branching model on BitBucket (see this ticket).
hg flow (the tool) uses named branches. In contrast to git branches, these are not at all light-weight, but permanent and global (they can at least be closed now).
This means whenever any commit created on any (named) branch other than "default" is pushed to bitbucket (even after merging) this will create the branch in the bitbucket repository.
So you don't have any other choice than keeping all branches in the main repository.
However, You can decide when to push and when to close these.
I would advise using hg push -r to push only the branches/heads you want to push and only pushing these when they are either needed by somebody else or finished and merged.
Branches should be closed as soon they are not needed anymore. (This is probably done by hg flow automatically)
You should close branches locally whenever possible. This way they might not even appear in the bitbucket interface. Some might reach the bitbucket repository only in closed state (which hides them from the interface).
Obviously you should often push any branches multiple people need to merge from.
In my understanding of the workflow the "develop" branch is always exactly one branch per project that should be pushed frequently (after local testing).
In case you are either not using hg-flow or named branches things are a bit different.
Both, using forks/clones or bookmarks as a branching method doesn't generate permanent or necessarily global branches.
Like mentioned above, you can't use bookmarks (reliably) when you also want to use bitbucket pull requests. You have to push bookmarks separately. A normal push will only update (a head of) the branch so you might miss commits from other team members when marging later. Hg will tell you when a new head is created. In that case you might want to merge the branch with the remote bookmark into your branch before pushing.
When using forks as branches it works a bit like with bookmarks, but bitbucket has full support for that. You need to have a new fork on bitbucket for every branch.
You naturally only want to create extra forks if you need different people to work on it and you don't have other means of commit exchange for them. You will need at least a separate "develop" repository then.
I personally wouldn't use the full "flow" with hg on bitbucket.
For my projects the "develop" branch is the same as master/default, since I don't roll out releases with git (other than development builds, that wouldn't use the release branch anyways). I don't need a separate "production" branch, since tags can mostly be used for production usage.
I also don't create a separate "release-preparation" branch. There is only a point in time when I only apply bugfixes on develop and stop merging features. That obviously won't work when you need to work at the same time on features that are dependendant on features not to be released in the next release.
Always using the full "git flow" is easy because git branching is easy and light-weight.
Depending on the branching model you use and how supportive the other tools are,
using the full "hg flow" might not be "worth it".
The hg guide actually discourages use of named branches for short-lived branches.
See Feature separation through named branches.
The "easy" branching concept promoted in the guide is forking/cloning. Bookmarks would be the natural way to translate git flow if the tool/bitbucket support would be better (and bookmarks longer a core hg feature).
Disclaimer:
I prefer git when I can choose. I do use hg, but not as my personal choice.
You also might have considered most of this, but since you didn't state any of these details and accept an answer (in the comments) that is quite different to what you are asking, I wanted to elaborate a bit.
Edit:
To follow-up on the comments:
I think hg bookmarks are comparable to git branches because both are just movable pointers to commits.
The main difference is, that when you delete a branch in git, the commits are possibly lost (when not part of other branches or pointed to in a another branch before they are garbage collected). When you delete a bookmark in hg, then the commits are still part of the repository (part of the (named or default) branch) unless manually stripped.
Anonymous heads are related, but only as something the bookmarks point to. Without bookmarks pointing to them the anonymous heads are not usable as a branch to work with (for more than just a local merge) and share. When you have anonymous heads in a repository you don't know what they are supposed to be or where they came from, unless you remember or have other clues. In my eyes anonymous heads are only a workaround for late implementation of bookmarks and no good implementation of remotes/remote heads.
Named branches are rather unrelated, as the only thing they have in common with git branches is having a name. They are light-weight in comparision to cloning the whole repository (forking as branch model), but not in terms of "you can't get rid of them". They are permanent.
Most places tell you not to use named branches unless you have a very good reason or it is a long-running branch.
I've noticed that some answers to questions about branch names quote the Mercurial wiki to indicate that the branch-per-feature or branch-per-bug naming conventions may cause performance problems.
Does the ability to mark branches as closed with the --close-branch flag on commits have any effect on this performance claim?
Does the ability to mark branches as closed with the --close-branch flag on commits have any affect on this performance claim?
Marking a branch closed with hg commit --close-branch merely creates a new changeset with a close=1 marker in the changeset meta data. Commands like hg branches and hg heads will then know not to show this branch/head. These commands use a branch cache to speed things up and we expect that cache to scale well with the number of branches.
However, there are some operations that have a complexity that is linear in the number of topological heads. This includes the discovery protocol used before version 1.9. The new discovery protocol in version 1.9 will still exchange topological heads in its "samples", but the sample size is capped at 200 changesets.
There might be other code paths that still scale linearly in the number of heads and this is why we suggest close-before-merge:
$ hg update bug-123
$ hg commit --close-branch -m "All fixed"
$ hg update default
$ hg merge bug-123
instead merge-before-close:
$ hg update default
$ hg merge bug-123
$ hg update bug-123
$ hg commit --close-branch -m "All fixed"
The latter approach leaves a dangling head in the graph (a topological head).
Closed branches probably won't make any difference in performance, but that's not the point. The performance implications are small, and certainly not the reason I suggested you avoid permanent branch names for short-lived lines of development. Here's the relevant quote from the wiki:
Mercurial is designed to work well with hundreds of branches. It still works quite well with ten thousand branches, but some commands might show noticeable overhead which you will only see after your workflow already stabilized.
The reason both MG and I (we're the primary answerers in both of your linked questions) is because time and time again we watch people get really annoyed when they learn that branch names are permanent in Mercurial. Here's the usual exchange, that acts itself out in IRC a few times a week:
Person A: "I've got 100 branches and I want to get rid of them!"
Person B: "You can't. You can hide them, but Mercurial branches are forever."
A: "But in git I have have 1000s of branches and get rid of them whenever I want!"
B: "Yes, in Mercurial those are called bookmarks."
or similarly:
Person C: "I named a branch 'stupid feature marketing made me add' and I want to push that change w/o pushing the branch name."
Person B: "You can't. You can merge it into default, but that name is permanent on the changeset. You'd have to re-create the changeset to get rid of it!"
C: "But in git my branch names are local only!"
B: "Yes, in Mercurial those are called bookmarks."
If you want permanent, forever branch names on your changes (and MG, my co-answerer on both of those questions does like exactly that) then by all means use them, and don't worry a bit about performance. But do worry about how your tools represent the branches: like Mercurial itself, tools are typically built to scale in the number of changesets, not the number of branches. So they often do naive things like putting all branch names into a single drop-down menu. This GUI problem will eventually be fixed when named branches become more popular.
Steve Losh's excellent Guide to Branching in Mercurial does a great job spelling out your (four!) options. Pick what you like and be confident there are plenty of folks who like whichever one you selected, and at least a few of them have more branches than you ever will.
I decide to start an experiment in a branch
[default] $ hg branch experiment
[experiment] $ [... some commits ...]
Aargh! does not work! I want to throw it away.
[experiment] $ hg commit -m "did not work; closing ..." --close-branch
[experiment] $ hg update default
To get the real tip back -
[default] $ [... some commits ...]
[default] $ hg push
Is this a correct workflow to destroy an experimental branch?
You've got two fine answers on how to undo your branch, but the bigger point is don't use named branches for temporary concepts. Named branches are for long lived entities like 'development' and 'stable'. For features, expiriments, etc. you want either clones, bookmarks, or anonymous branches. All three are contrasted with named branches in this excellent article by Steve Losh:
http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/
You can see similar advice from the Mercurial project here:
https://www.mercurial-scm.org/wiki/StandardBranching
The Mercurial wiki covers all the options for Pruning Dead Branches. Briefly, these options include:
Closing the branch (as done in your original post)
Create a new clone that does not include the dead branch
Use a no-op merge
Use the strip command that is bundled with the mq extension
Closing a branch will leave it in the repository, and the closed branch will be pushed with other changesets next time you do a push.
If you don't want this to happen, and your branch is local, just strip it.
On the other hand, if you have already pushed the experimental branch, stripping it won't help, so you can either close it or do a dummy merge (or both).
In my opinion, you should just close the branch and forget about it.
In the long run, there's no harm in a "dead" branch being present in the repository. Any given branch is almost certainly tiny in comparison to the contents of your repository and any additional "noise" created by the additional changesets is going to fade into the past relatively quickly.
However, by not worrying about cleaning up the branch, you achieve two things:
You don't have to deal with any of the potential issues associated with altering history in a DVCS.
(More importantly) You have a permanent record of your attempt.
That second point is key -- you can actually make use of what you learned if the branch is still around: any fellow developers can learn from it; you can go back and try again if you learn something else; you can prevent trying the same thing again by seeing this branch in history.
A lot of developers have a hard time with keeping history that isn't "pristine" in their DVCS, especially when they recently came from a centralized VCS.* Over time, I've come to realize that there's nothing bad or wrong about that "other" history and in fact it can turn out to be remarkably useful if kept around.
*I'm not necessarily implying that you fall into either of these camps, just making an observation.
What's the difference between a tag and a bookmark in Mercurial? I can't seem to find any discussion of how the two differ.
Lets consider your repository as a "choose your own adventure books", with different points of view.
A tag is like a stamp that the editor put on your manuscript to say "ok, we keep a trace of your current work, in case shit happens."
A named branch would be a chapter. You have to choose at one point which chapter you'll have to write, and they are there to stay. Some will merge back, some will end (sorry, you died.)
A bookmark is, well, a bookmark. It follows you while you're reading (committing) the book. It helps you to keep tracks of "what you were reading at that time", so you can remove them, move them to a different "chapter". When you share the book (push), you usually don't share your bookmarks, unless you explicitly want to. So you usually use them on anonymous branches because their life cycle is shorter than named branches.
Bookmarks are used when you want a mnemonic (foo_feature) that points to a changing commit id as your work progresses. They're more light-weight that regular Mercurial branches, and somewhat similar to the way git branches work.
Tags generally point to fixed commit ids. They can be reassigned manually, but this is discouraged.
There are actually five concepts to play with:
tags
local tags
bookmarks
lightweight branches
named branches
Lightweight branches are what happens if you just use mercurial. Your repository history forks and sometimes merges as you change things and move around your history.
The other four are ways of annotating lightweight branches and the changesets that make them up.
named branches and tags are mercurial-only concepts where the branch names and tags actually get recorded in the repository by making more commits to the repository. They'll tend to propagate to other repositories in ways which are not necessarily obvious.
local tags and bookmarks are much more like what git calls tags and branches. They're metadata rather than being mixed in with the versioned objects. So they're not represented as part of the repository history. They tend to be local to your repository, and won't propagate unless you propagate them deliberately.
At least I think that's how they all work. After about twelve months of using mercurial daily I haven't really got to grips with its model(s). If anyone knows better than me then feel free to edit this answer so it's correct.
How I actually use these things in practice.
I'm working on a single shared repository with about 20 other people. I make many experiments and lightweight branches in my own private repository, which never get pushed to our main central repository. Occasionally once an experiment has worked out I'll modify the main line and push a changeset into the central repository, from which it will find its way to everyone else's machine.
I'll occasionally push some changesets to a co-worker if they're one of the people who's comfy with how mercurial works. But several people are a bit scared of it and prefer if I send them diffs that they can apply with patch.
For experiments I expect to be short lived and private, I just let lightweight branches happen where they may, and remember what's going on. If I feel my memory slipping about a twig that's been around for a bit, I bookmark it.
I use local tags to mark revisions I might like to come back to one day. They make interesting past states easier to find.
I myself almost never make non-local tags or named branches (except by accident, and I destroy them if I do). But our release people do. Our released major versions all have their own named branches off from the main line, and minor versions have tags on those branches. That ensures that these important branches and tags look the same to everyone.
Again, I've no idea whether this is how one's supposed to use mercurial, but it seems to be a model that works well for our size of team.
If three or four of us wanted to collaborate on an experiment, that would probably be worth a named branch, which we'd probably share between ourselves but not push to the central repo. I don't know how well that would work out!
The biggest difference is that a bookmark is automatically moved forward when you commit. Here's an example:
hg init
..edit a file..
hg commit -m 'my commit' # creates revision 0
hg tag -r 0 mytag # creates revision 1
hg bookmark -r 0 mybookmark # doesn't create a revision
hg update 0 # get back to r0
..edit a file..
hg commit -m 'another commit' # creates revision 2
At that point mytag is still pointing to revision 0 and mybookmark is now pointing at revision 2. Also the tagging created a changeset and the bookmark didn't.
Also, of course, the bookmark created a revisio
I have been using named branches both as feature branches and long lived branches. I just merged a bunch of feature branches into a long-lived branch, so I no longer need those feature branches muddling up the history graph (although I still want to keep the commit messages of course).
How do I do this?
Checkout the branch (hg co branchname) then hg commit --close-branch to mark the branch "closed".
Branches in mercurial are permanent, which is why they're a good choice for things that live forever like "release 1.0" and "experimental". For features you might want to consider something more transitory like bookmarks, clones, or anonymous branches. All four options are very well described here: http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/
As #wolvever shows you can hide it from a list, but you can't get rid of it without making your repo a different repo entirely (and thus breaking all clones).