How do I merge two Mercurial repos into a single one - mercurial

I have to separate Mercurial repositories. One is the main trunk for the project, while the other is a branch with a set of additional changes.
There is one central location for the project repository, in which I'd like both the trunk and the branch to be available. What I'd like to do is merge the two repositories into a single one, but still allow the branch to be accessed via tags, or something similar. This would allow developers to check out the main code, but also be able to switch to working on the branch if it requires further changes. I also want to make sure that any code in the trunk doesn't accidentally make it into the branch. Any changes to the branch should be explicit and intentional.
What is the best way to accomplish this?

As Brandon says, just push from the branch repo to the trunk, or pull the branch into the trunk.
You can then choose if you want to merge branch & trunk together, or keep them separate. If you push from branch to trunk, you may get a warning about multiple heads. Just do a push -f if you want to keep them separate. (pull may not give a warning)
You can merge the branch changes to the trunk and still be able to do further work on the branch later if you want. In general, I tag every release so I can easily get back to anything that went out the door.
When you created the branch, did you clone it to another directory? If so, it will be harder to find the branch after pulling it into the trunk repo. You may want to read up on bookmarks to label the branch. Also look at how multiple heads work.
Note: The other option is to use named branches which labels the branch permanently. You wouldn't need to do anything extra to switch over to it later.

Related

Paralell branches/clones in 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).

How to graft from other repository?

I have two repositories with tho different mercurual named branches, say V1 and V2. The branches are divergent since about one-two years. I'd like to graft some changesets from one repo into the other, without pulling the changes.
I don't want to pull the changes for multiple reasons.
I don't want to conflict developers with history of multiple branches, because there will be enough local branches to care about.
I want to have single branch central repos and developers could accidently push the second branch. The central branches would interact with SVN and should have only one branch per repo. I know I could use central hooks, to prevent such a push, but I don't want questions like, can't push, or how can I do that.
The size of the repo would grow to multiple gigabytes (before pull about 700MB). As I understand, it's because of deficites of current mercurial storage format.
I know, the transplant extension can do the work. I tried it, but I can't force other developers to handle rejects instead of simply use a merge tool. Is there an other way?
In fact there are more then two repos with each a branch, but for the example simplicity two should be enough.
You might be able to do the work in an intermediate repo:
Pull in the changes
Do whatever grafting/rebasing/transplanting you need
Strip out the things you pulled in step 1. or if that doesn't work:
Pull only the changes from the branch you want into the actual repo
You'd end up with a repository that includes your desired change sets, but not all the history from the unwanted branch.
Follow-up to #DanMan
Pull needed branch into intermediate repo
Strip unwanted changesets in clone
hg pull CLONE in real target
Write a tool, a hg-extension or extend the graft command so it can graft from a second repository, similar to the transplant extension.
Yes, the implementation is not so easy as adding the second-repo-functionality in the transplant command. The transplant extension simply uses a patch from an other repo instead of one from own repo. But I think also for graft there is no technical reason, not to do that.
If I understand right, grafting of a single file change is not more than calling the merge tool with the files:
(base) the parent of the to-graft changeset
(my changes) the target revision, on which to graft
(theirs) the to-graft refision
So in order to graft a file change from an other repo, the whole file from other repo is needed before the to-graft changeset was applied (base) and after it was applied (theirs). Technically it should be no problem.
Additionally the implementation
need to determine, which files are affected by the changeset to graft
need to handle deletions correctly
need to handle file renamings (not sure, how complicated it is)
All that should be possible, I see no real technical problems.

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.

TortoiseHG merging local into branch head

I have a repo in TortoiseHG with a single branch (next version development), but modifications to the local (bug fixes)... something like...
Local 0-------3--4
\
Branch 1--2
I want to do some more development on the branch version but with the subsequent Local changes merged into it. And I want to leave the local version in a state where I can continue development without the branch changed.
I'm not sure if what I'm asking is actually possible, or whether coming from a Visual SourceSafe environment is just clouding my ability to see something that should be obvious.
In fact, thinking about it a bit more (as I was writing the above) I'm wondering if my approach is the wrong way around. I should probably have continued with the future development in the local version and then create a bug-fix branch that I could have merged back into local one.
So the question is, is there a way to get around what I want to do with the current repo setup, or should I export the individual revisions and rebuild the repo from scratch? (Or any other options?)
This seems like pretty normal Mercurial handling to me.
You have:
Two branches
Want to make sure one of the two branches have all the updates of the other
Want to make sure that other branch does not have any of the updates from the first (yet)
You basically just have to merge the Local branch into the Branch branch at regular intervals, but not the other way around.
Whenever you merge to a branch, you first update to the head of that branch. This makes the changeset you commit to persist that merge be on that branch as well.
In other words, you would do this:
Update to the head of Branch
Right-click on the head of Local and select "Merge with local..." and go through with the merge
Commit, this new changeset ends up being on the Branch branch
The Local branch is still blissfully unaware of the changes on the Branch branch.

Proper command flow for branching strategy

So I have a mercurial repository that is the "blessed" repository that I will have open release cycle branches, for example Release1, Release2 etc.
When a dev is working on a release cycle they will pull down Release1, then on their local machine branch for Bug1, Bug2 and fix those.
What command sequence needs to happen for the devs to correctly close their Bug branches, merge the changes into the Release1 branch so that when the changes are pushed to the server no branch information about Bug1, Bug2 etc will be pushed to the server?
If you're using named branches the branch information about bug1 will always be pushed to the server. Named branch names are parts of their changesets and never go away or get changed. You can cause them to not show up in default branch lists by using the --close-branch option to commit, but they're still there and listable.
If you want a branching model where the branch names don't escape Mercurial provides some other branch options that may suit your needs better:
http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/
If someone suggests using the 'TransplantExtension' to merge the branches in and hide the branch information, don't listen -- it's a terrible idea.