Paralell branches/clones in Mercurial? - mercurial

This question is not only technical. I want to get into the concept itself, too.
There is a foreign project on BitBucket (e.g. ObjectListView). And I need to work on two problems at the same time. In git I would just create to branches in my local repository after clonening.
But how would I does this with Mercurial?
When I create branches there I am not able to push my local commits back to the remote repository because of the missing '--allow-new-branch' option.
So it doesn't want me to branch.
In my current understanding I would just create a clone for each new feauter (branch). So this means I have to create two forks on BitBucket for one project when I want to work on two different problems.
How would you solve this?

There is some missing information here, so I'm not sure I know what your problem is. I'll try to take some educated guesses and cover a number of possibilities. Feel free to ask back if I failed to address your problem adequately.
First, you can definitely just create new branches if you wish to do that. You'll need to use hg push -f or hg push --new-branch (if you used a named rather than an anonymous branch) to make the remote server accept them (that's to prevent you from pushing new branches by accident). You will, of course, need write access to the repository (or fork the repository and work on that fork).
Second, if you just want to push the current revision/branch (and any associated revisions of a feature branch) and not sync the entire repository, then hg push -r . will do that (here, . denotes the current revision, you can also specify others). If you use that frequently, you may want to create an alias, e.g. submit = push -r ..
Third, if you actually need separate workspaces, it's probably more convenient to use hg share instead of cloning the repository. (Note that you'll first have to enable the share "extension" for that; the word "extension" is in quotes because it's actually a part of core Mercurial and not really an extension in the traditional sense.) hg share creates a separate directory that is still linked to the same repository, but has a separate checkout with separate files.
It is also important to understand that branches in Git and Mercurial are completely different things. Branches in Git, aside from naming specific commits, exist to keep revisions alive (so they don't get garbage-collected). In Mercurial, nothing ever gets garbage-collected, so you don't need Git-like branches for that purpose; instead, Mercurial has anonymous branches (which are sort of like detached HEADs in Git -- sort of) and named branches (which are used to label sets of revisions with a permanent name). Bookmarks can be used to put temporary labels on either type of branch (or specific revisions). Bookmarks + anonymous branches can be made to feel fairly Git-like if you desire that.
So, if you want a Git-like approach, you'd just create anonymous branches (and optionally put a bookmark on them for ease of reference, though having them as branch heads in two directories created with hg share can be the better choice if you wish to work on both concurrently without having to switch. You'd then use hg push -r . to push that specific branch to the remote repository (you may also need -f if you're creating a new head).
However, if it is not your repository, you may want to check with the owner what structure they prefer; for example, plenty of Mercurial users prefer named branches in order to be able to tell later which revisions belong together (sort of like a tag that spans multiple revisions).

Related

Rename a local-only mercurial branch?

I find a lot of questions about renaming hg branches that have already been pushed/pulled by other people, but I've got a situation here where work has been done on a set of branhces (10 in total) that all have the "wrong" name - wrong in the sense that the repo (on bitbucket.org) has restrictions on the naming of branches.
Any developer can open a new branch named app-feature-xxxx (where xxxx can be anything), but a boatload of work has been done by a new dev, and none of the branches follow this naming pattern (the branches are effectively the xxxx part without the app-feature- prefix)
Currently these branches are known only on his machine - they've never been pushed to BitBucket.org, nor pulled by anyone else
Can they be renamed in-situ, before they're pushed? Right now hg is attempting to commit his history to BitBucket with these branch names and it's failing. If the branches can be renamed before that happens, everything should be golden.. And there aren't the usual "but what about everyone else's history?" problems, because only one person has these commits..
The easiest I've been able to come up with right now is to clone the repo again, just make one app-feature-lotsofupdates branch, and then keep switching working copy in the original repo, and use a diff tool to apply the code from the original repo (with the wrong names) to this newly cloned repo, committing after every diff/copy - effectively a manual merge of all the various features into one branch (that will then be merged into production)
You can do this using the convert extension to Mercurial, and the branchmap option.
The branchmap is a file that allows you to rename a branch when it is
being brought in from whatever external repository. When used in
conjunction with a splicemap, it allows for a powerful combination to
help fix even the most badly mismanaged repositories and turn them
into nicely structured Mercurial repositories. The branchmap contains
lines of the form
original_branch_name new_branch_name
original_branch_name is the name
of the branch in the source repository, and new_branch_name is the
name of the branch is the destination repository.
The command line to do this would be something like:
hg convert --branchmap branchmap.txt path\to\source\repo path\to\converted\repo
Documentation.

Mercurial: devs work on separate folders, why do they have to merge all the time

I have four devs working in four separate source folders in a mercurial repo. Why do they have to merge all the time and pollute the repo with merge changesets? It annoys them and it annoys me.
Is there a better way to do this?
Assuming the changes really don't conflict, you can use the rebase extension in lieu of merging.
First, put this in your .hgrc file:
[extensions]
rebase =
Now, instead of merging, just do hg rebase. It will "detach" your local changesets and move them to be descendants of the public tip. You can also pass various arguments to modify what gets rebased.
Again, this is not a good idea if your developers are going to encounter physical merge conflicts, or logical conflicts (e.g. Alice changed a feature in file A at the same time as Bob altered related functionality in file B). In those cases, you should probably use a real merge in order to properly represent the relevant history. hg rebase can be easily aborted if physical conflicts are encountered, but it's a good idea to check for logical conflicts by hand, since the extension cannot detect those automatically.
Your development team are committing little and often; this is just what you want so you don't want to change that habit for the sake of a clean line of commits.
#Kevin has described using the rebase extension and I agree that can work fine. However, you'll also see all the work sequence of each developer squished together in a single line of commits. If you're working on a stable code base and just submitting quick single-commit fixes then that may be fine - if you have ongoing lines of development then you might not won't want to lose the continuity of a developer's commits.
Another option is to split your repository into smaller self-contained repositories.
If your developers are always working in 4 separate folders, perhaps the contents of these folders can be modularised and stored as separate Mercurial repositories. You could then have a separate master repository that brought all these smaller repositories together within the sub-repository framework.
Mercurial is distributed, it means that if you have a central repository, every developer also has a private repository on his/her workstation, and also a working copy of course.
So now let's suppose that they make a change and commit it, i.e., to their private repository. When they want to hg push two things can happen:
either they are the first one to push a new changeset on the central server, then no merge will be required, or
either somebody else, starting from the same version, has committed and pushed before them. We can see that there is a fork here: from the same starting point Mercurial has two different directions, thus a merge is required, even if there is no conflict, because we do not want four different divergent contexts on the central server (which by the way is possible with Mercurial, they are called heads and you can force the push without merge, but you still have the divergence, no magic, and this is probably not what you want because you want to be able to checkout the sum of all the contributions..).
Now how to avoid performing merges is quite simple: you need to tell your developers to integrate others changes before committing their own changes:
$ hg pull
$ hg update
$ hg commit -m"..."
$ hg push
When the commit is made against the latest central version, no merge should be required.
If they where working on the same code, after pull and update some running of tests would be required as well to ensure that what was working in isolation still works when other developers work have been integrated. Taking others contributions frequently and pushing our own changes also frequently is called continuous integration and ensures that integration issues are discovered quickly.
Hope it'll help.

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.

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

best practices in mercurial: branch vs. clone, and partial merges?

...so I've gotten used to the simple stuff with Mercurial (add, commit, diff) and found out about the .hgignore file (yay!) and have gotten the hang of creating and switching between branches (branch, update -C).
I have two major questions though:
If I'm in branch "Branch1" and I want to pull in some but not all of the changes from branch "Branch2", how would I do that? Particularly if all the changes are in one subdirectory. (I guess I could just clone the whole repository, then use a directory-merge tool like Beyond Compare to pick&choose my edits. Seems like there ought to be a way to just isolate the changes in one file or one directory, though.)
Switching between branches with update -C seems so easy, I'm wondering why I would bother using clone. I can only think of a few reasons (see below) -- are there some other reasons I'm missing?
a. if I need to act on two versions/branches at once (e.g. do a performance-metric diff)
b. for a backup (clone the repository to a network drive in a physically different location)
c. to do the pick&choose merge like I've mentioned above.
I use clone for:
Short-lived local branches
Cloning to different development machines and servers
The former use is pretty rare for me - mainly when I'm trying an idea I might want to totally abandon. If I want to merge, I'll want to merge ALL the changes. This sort of branching is mainly for tracking different developers' branches so they don't disturb each other. Just to clarify this last point:
I keep working on my changes and pull my fellow devs changes and they pull mine.
When it's convenient for me I'll merge ALL of the changes from one (or all) of these branches into mine.
For feature branches, or longer lived branches, I use named branches which are more comfortably shared between repositories without merging. It also "feels" better when you want to selectively merge.
Basically I look at it this way:
Named branches are for developing different branches or versions of the app
Clones are for managing different contributions to the same version of the app.
That's my take, though really it's a matter of policy.
For question 1, you need to be a little clearer about what you mean by "changes". Which of these do you mean:
"I want to pull some, but not all, of the changesets in a different branch into this one."
"I want to pull the latest version of some, but not all, of the files in a different branch into this one."
If you mean item 1, you should look into the Transplant extension, specifically the idea of cherrypicking a couple of changesets.
If you mean item 2, you would do the following:
Update to the branch you want to pull the changes into.
Use hg revert -r <branch you want to merge> --include <files to update> to change the contents of those files to the way they are on the other branch.
Use hg commit to commit those changes to the branch as a new changeset.
As for question 2, I never use repository clones for branching myself, so I don't know. I use named branches or anonymous branches (sometimes with bookmarks).
I have another option for you to look into: mercurial queues.
The idea is, to have a stack of patches (no commits, "real" patches) ontop of your current working directory. Then, you can add or remove the applied patches, add one, remove it, add another other one, etc. One single patch or a subset of them ends up to be a new "feature" as you probably want to do with branches. After that, you can apply the patch as usual (since it is a change). Branches are probably more useful if you work with somebody else... ?