Can I branch in Mercurial without cloning the repository? - mercurial

Recently, I've started experimenting with Mercurial, due to the fact that it always attracted it because of its simplicity and "just works" principle. Or at least, that's how others always described it.
They also usually described it as "practically the same as git with just a few minor changes you won't notice" - only for me to discover it isn't quite so.
I'm having problem with Hg branches. Pardon me if this is an overly simple question, but in git one has a working directory and a repo (.git). In the repo one has revisions, and branches, and can jump from one to another.
I'm having trouble finding a similar model in Hg. As far as I can see, for Hg to have a "branch" one needs to clone a repo to another directory? Is there a way Hg could work just like git does - i.e. one working dir., and one repo, in which you can do things as regard to branching and revs?

Mercurial supports a very rich set of ways to branch. See http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/
In brief, you can create a named branch by running
hg branch NewBranch
and switch to that branch using
hg up NewBranch
or switch back to trunk using
hg up default

In Mercurial, if you go to any particular revision, you can always edit your working copy and commit, thereby making another "head." Merging works on head revisions by default. You can use hg head to see what heads are in your repository. This seems to be the most "idiomatic" way I have found branching to work in Mercurial.

Take a look at section about branches in my answer to "Git and Mercurial - Compare and Contrast" here on StackOverflow.
The information about various options available for branching in Mercurial (anonymous heads, not-propagated (I think yet still) bookmarks, and global (world-wide) commit labels aka named branches) was taken from http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/, and expanded using feedback on #mercurial IRC channel on FreeNode.

Related

HgFlow and multiple developers

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.

Mercurial: graft vs. record vs. qrecord vs. shelve vs. transplant vs. dirstate vs. queue

I am new to Mercurial and still somehow in the evaluation process, so these four concepts are kind of confusing for me. Some are mentioned to be an equivalent to Git's Staging/Index concept, or some even a better one than Git's Staging.
How do the four commands hg graft, hg record, hg qrecord and hg shelve (and hg transplant, but this is explained in Graft vs. Transplant already) compare to each other, and how the concepts of queues and the dirstate? In which use cases is one choosen over the other?
I know there are help pages for each one, but it still is difficult to figure out what each one does as VCS in general is a new topic for me.
The design of Mercurial simply does not include the concept of a staging area. That is, there is no intermediate state between local modification and commit.
Here is an overview of each of the concepts you mentioned:
hg graft is the equivalent of git cherry-pick. It copies a commit from one branch to another. A typical use case for this feature is to copy a bug fix from one release branch to another. This command replaces the older (and now obsolete) hg transplant extension.
hg record and hg qrecord are similar to git add --patch. They allow you to interactively select hunks for commit. So if you modified several different areas of one file, you could select which areas (i.e. hunks) you actually want to commit and which you want to leave as local modifications.
qrecord is only available if you have mq enabled. It commits to an mq patch rather than a standard commit.
hg shelve is similar to git stash. It allows you to temporarily set aside local modifications to your files (or hunks of a file). These modifications can then be unshelved when you are ready for them.
dirstate is an internal class of of the Mercurial source code. It is not exposed to the user.
Mercurial Queues (also know as mq) are probably the closest you will get to a staging area in Mercurial. Here is a description from the Mercurial wiki:
Changes are maintained as patches which are committed into Mercurial.
Commits can be removed or reordered, and the underlying patch can be
refreshed based on changes made in the working directory. The patch
directory can also be placed under revision control, so you can have a
separate history of changes made to your patches.
mq is often used to polish/rework commits that you are testing locally, but have not pushed to a public location. Some people also use it to maintain a set of modifications to 3rd party code.

Using Mercurial local clones for branched development?

I'm an ex SVN user trying to work out the best way to do branched development in hg. My project is fairly new currently has no branches. A friend of mine suggested that making a local clone of the repos. then working in that was better than using a named branch.
So if I use this model, would the workflow be:
[say original project has been cloned to be in c:\projects\sk\tracker]
hg clone https:[url of repos] tracker_featurex [to be issued from c:\projects\sk]
change to subdir tracker_featurex
checkin and push as per normal
[optional, how do I pull changes from the main repos. into this one?]
[final step, how do I get changes from this clone back into the main trunk?]
I need help on whether this workflow is correct and what the exact commands would be for the two steps in the [] braces.
Thanks a great deal to anyone who can help,
Fred
I would recommend you take a look at Steve Losh's post on branching in Mercurial: http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/
He goes over various types of branches (clones, bookmarks, named branches, anonymous branches) as well as the commands you would run for each. There are pros and cons to all of them. Local clones are ok if you are the only developer but they are not as useful in a workflow where more than one developer needs to work on a branch. The claim that clones are universally better than named branches is a myth. You should find a branching model that fits your workflow.
Update:
If you do want to do local clones you can move you changes using hg push from the new workspace (Assuming you have a Projects folder and a repo named test):
Projects> hg clone test test-new-feature
Projects> cd test-new-feature
Projects/test-new-feature> <do some work>
Projects/test-new-feature> hg commit -m "Work is done."
Projects/test> <Might need a pull/merge here>
Projects/test-new-feature> hg push
If there are changes in the test repo you need to pull/merge them before pushing.
You can also hg pull from the original workspace:
Projects> hg clone test test-new-feature
Projects> cd test-new-feature
Projects/test-new-feature> <do some work>
Projects/test-new-feature> hg commit -m "Work is done."
Projects/test-new-feature> cd ../test
Projects/test> hg pull ../test-new-feature
This might create multiple heads in the test repo and you would need to merge/commit.
Projects/test> hg merge
Projects/test> hg commit -m "Merged in new-feature."
Either are good options. I might recommend pulling rather than pushing. The main difference to me is the location of the merge step. I think pulling from the feature repo makes the history a little more readable.
I am fledgling to Hg, so take what I say with a word of caution :-)
I love having named branches, but use them very judiciously! There are downsides to the approach I use below, but it works well for my current environment which is a small shop. I don't mind preserving history forever and I'm not concerned with reducing the number of commits (but Mq/record/etc can address this latter bit).
This is how I use branches in the code I work on:
Default branch.
This is built on the build server.
This should only have one head.
This should always compile.
This should always be the "best effort" at completing bugs/features.
"Workbench" branch.
This can have multiple heads.
Anonymous branches are encouraged. Shared bookmarks used to "name" active anonymous branches.
The state should be almost always compilable, but it is not a requirement.
Represents "work in progress".
Okay, so this is what my process might look like this: (I've excluded pull/push/merge-theirs steps).
I get a bug report in.
I switch to "workbench" tip (or whatever revision is appropriate).
I fix the bug, possibly committing several times. (I really should learn to use queues or record, etc.)
(If I am interrupted in the above process, e.g. have to work on a different bug, or am otherwise side-tracked I will create a new head above where #2, or as appropriate. I may give the current anonymous branch tip a name with a bookmark, or I may not.)
Once complete, I merge the relevant branch/changes into "default" and hopefully the build server still loves me :-)
I think the best thing to do is forget about how branches in SVN worked. They are not liked named branches at all and anyone who says otherwise is latching onto the fact they both have "names" and not much more. Every branch in Hg is part of a "named branch" (that is, has a name associated with it, be it "default" or "workbench" or otherwise). But it doesn't matter, except for organization: a branch is a branch and it doesn't matter if it's referring to the "tip" of an anonymous branch or the tip of the only head (really an anonymous branch itself) in a named branch.
Try a few things, use what works best :)
making a local clone of the repos. then working in that was better than using a named branch.
Overly dramatic and ambitious statement in common. When you clone-per-feature, you have only one branch (named branch) per repo, but nothing more (practically, briefly speaking).
When feature is finished, you have to "push to parent"|"pull from clone" in order to return changes back. At this stage, if some work was done in parent repo after clone, anonymous branch will appear (+1 head) and merge is a must (same as for work in named brach in one repo), but, it named brach can tells something fast later (you use good names, isn't it?), anonymous branch tells almost nothing without additional tricks (bookmarks, f.e). Part of my repo below as example of work in clone with intermediate pulls and must-merges after pulls/ (sorry, russian commit-messages) and even I can't recall now, why I had repo cloned for editorials - maybe I just play with Clones-Workflow

Mercurial push problem

I've just got a problem with hg push command. What I did - Firstly I created 2 branches hot-fix-1 and hot-fix-2 made some changes in each branche, merged it back to default and closed those branches with the command:
hg commit --close-branch
If I start hg branches I have the following output:
default 29:e62a2c57b17c
hg branches -c gives me:
default 29:e62a2c57b17c
hot-fix-2 27:42f7bf715392 (closed)
hot-fix-1 26:dd98f50934b0 (closed)
Thus hot-fix-* branches seems to be closed. However if I try to push the changes I have the next error message:
pushing to /Users/user1/projects/mercurial/mytag
searching for changes
abort: push creates new remote branches: hot-fix-1, hot-fix-2!
(use 'hg push --new-branch' to create new remote branches)
and it does not matter which command I use hg push -b . or hg push -b default
So the question is how I can push those changes to repository without creating new branches.
P.S I used to work with git and was hoping that similar branching model can be used in Mercurial. Thanks
First, as many others have pointed out, using a named branch for short lived work is not a recommended practice. Named branches are predominantly for long lived features, or for release management.
Given that you are in this situation, there are a few options available. All of them involve modifying history (as you're obviously trying to change something you've done).
One is to just push the branches as is, learn from the experience, and move on. If the rest of the team is fine with this, then it's a case of adding --new-branch to your push command.
If the rest of the team, or you, really want the history to be clean, then you'll need to dig deeper.
If you aren't pushing, then definitely make a clone of your current repo. This way you have a copy of the original work to fall back on.
I see 2 main approaches here. Strip off the merges and rebase your branches onto default. This will get rid of the named branches or graft/transplant your changes. Both will be the same end result, but the implementation is slightly different.
If you merely want to use graft, that is now a built-in function starting with HG 2.0. It replaces the transplant plugin, and is much nicer to work with as it uses your usual merge tool if there are conflicts.
To use it, update to the default branch. Then, use the command:
hg graft -D "2085::2093 and not 2091"
the string after -D is an hg revision selection query. In your case, you'd likely only need '{start}::{end}' where start is the changeset at the start of the branch, and end is the end changeset of the branch (ignoring the merge).
If you did several merges, you'd have to pick and choose the changesets more precisely.
The other option is to strip the final merges, and use the rebase command that is part of the mq plugin.
You'll have to strip your merge changesets to get rid of them, and then update to the tip of the branch you want to keep. Select the start of the first named branch, and do a rebase. This will change the parentage of the branch (if you're familiar with Git, then this is very much like it's rebase).
Then repeat for the second branch. You should now have one long branch with the name default.
Just do the:
hg push --new-branch
It will send over those branches, but they'll be closed on the receiving end too, so no one should be bothered.
See my comment on the question for why Named Branches are best saved for long-lived entities like 'stable' and anonymous branches, bookmarks, or clones are more suitable for short lived things like hot-fixes and new features.
Your hot-fix changes were made on branches. Regardless of whether the branch is active or closed, it does exist.
To push the changes to the server (without rewriting history), you must use the --new-branch option (e.g. hg push --new-branch`).
Since you merged the branches into default, there will still only be one head (as you have already seen in your local repo).
If you really can't live with pushing the branches to the server, then you must rewrite your local history as suggested in Mikezx6r's answer.
In addition to the methods he mentioned, you can also import the changesets into a patch queue and apply them to the tip of your default.

Mercurial Experimentation Workflow

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.