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.
Related
I made some changes to a file and committed it. (In fact there were several commits).
Then I wanted to revert to the earlier version and lose all those changes.
I did something like:
hg update -r nnn where nnn was the reversion number of the changeset I wanted to go back to.
That worked. I was happy.
Then, later, I had to push my local repository to the remote. But when I did hg push I got a message about there being two heads on this branch and one of them not being known to the remote repositiory. It suggested I merge before pushing. (I think).
I googled this and found a page that suggested I do "hg merge". I did that. Now the resultant file is back to where I started. I.e. it contains all the changes I wanted to throw away.
Where did i go wrong?
EDIT:
I have found this post Mercurial — revert back to old version and continue from there
where it says:
If later you commit, you will effectively create a new branch. Then
you might continue working only on this branch or eventually merge the
existing one into it.
That sounds like my case. Something went wrong at the merging stage it seems. Was I on the wrong branch when I did "hg merge"?
You're past this point now but if it happens again, and it's just a single file you want to revert then consider:
hg revert --rev REVISION_YOU_LIKED path/to/just/one/file.txt
That doesn't update you whole repository to a different revision, and it doesn't create any commits. It just takes a single file in your working directory and makes it look like it used to. After doing that you can just commit and you're set.
That's not the way to go if you want to undo all the changes you've made to all files, but for reverting a single file use revert and avoid multiple heads and merging entirely.
No, nothing went wrong at the merge stage – Mercurial did exactly what you asked it to...
What merge means is that you take the changes on your current branch, and the changes on the 'other' branch, and you merge them. Since your original changes were in the 'other' branch, Mercurial carefully merged them back into your current branch.
What you needed to do was to discard the 'other' branch. There are various ways of doing that. The Mercurial help pages discuss the various techniques, but there are pointers in other SO questions: see for example Discard a local branch in Mercurial before it is pushed and Remove experimental branch.
(Edit) Afterthought: the reason you got a warning about there being two heads on the branch is because having two heads is often a temporary situation, so pushing them to a remote repository is something you don't want to do accidentally. Resolutions are (i) you did mean to push them, so use --force to create two heads in the remote repository; (ii) ooops!, you meant to merge them before pushing, so do that; or (iii) ooops!, you'd abandoned the 'other' one, so get rid of it. Your case was (iii).
I have a hg clone of a repository into which I have done numerous changes locally over a few months and pushed them to my clone at google code. Unfortunately as a noob I committed a whole bunch of changes on the default branch.
Now I would like to make sure my current default is EXACTLY as upstream and then I can do proper branching off default and only working on the branches..
However how do I do that cleanup though?
For reference my clone is http://code.google.com/r/mosabua-roboguice/source/browse
PS: I got my self into the same problem with git and got that cleaned up: Cleanup git master branch and move some commit to new branch?
First, there's nothing wrong with committing on the default branch. You generally don't want to create a separate named branch for every task in Mercurial, because named branches are forever. You might want to look at the bookmark feature for something closer to git branches ("hg help bookmarks"). So if the only thing wrong with your existing changesets is that they are on the default branch, then there really is nothing wrong with them. Don't worry about it.
However, if you really want to start afresh, the obvious, straightforward thing to do is reclone from upstream. You can keep your messy changesets by moving the existing repo and recloning. Then transplant the changesets from the old repo into the new one on a branch of your choosing.
If you don't want to spend the time/bandwidth for a new clone, you can use the (advanced, dangerous, not for beginners) strip command. First, you have to enable the mq extension (google it or see the manual -- I'm deliberately not explaining it here because it's dangerous). Then run
hg strip 'outgoing("http://upstream/path/to/repo")'
Note that I'm using the revsets feature added in Mercurial 1.7 here. If you're using an older version, there's no easy way to do this.
The best way to do this is with two clones. When working with a remote repo I don't control I always keep a local clone called 'virgin' to which I make no changes. For example:
hg clone -U https://code.google.com/r/mosabua-roboguice-clean/ mosabua-roboguice-clean-virgin
hg clone mosabua-roboguice-clean-virgin mosabua-roboguice-clean-working
Note that because Mercurial uses hard links for local clones and because that first clone was a clone with -U (no working directory (bare repo in git terms)) this takes up no additional disk space.
Work all you want in robo-guice working and pull in robo-guice virgin to see what's going on upstream, and pull again in roboguice-working to get upstream changes.
You can do something like this after the fact by creating a new clone of the remote repo and if diskspace is precious use the relink extension to associate them.
Preface - all history changes have sense only for non-published repos. You'll have to push to GoogleCode's repo from scratch after editing local history (delete repo on GC, create empty, push) - otherwise you'll gust get one more HEAD in default branch
Manfred
Easy (but not short) way - default only+MQ
as Greg mentioned, install MQ
move all your commits into MQ-patches on top of upstream code
leave your changes as pathes forever
check, edit if nesessary and re-integrate patches after each upstream pull (this way your own CG-repo without MQ-patches will become identical to upstream)
More complex - MQ in the middle + separate branches
above
above
create named branch, switch to it
"Finish" patches
Pull upstream, merge with your branch changes (from defaut to yourbranch)
Commit your changes only into yourbranch
Rebasing
Enable rebase extension
Create named branch (with changeset in it? TBT)
Rebase your changesets to the new ancestor, test results
See 5-6 from "More complex" chapter
Perhaps you could try the Convert extension. It can bring a repository in a better shape, while preserving history. Of course, after the modifications have been done, you will have to delete the old repo and upload the converted one.
I am trying to work out how to use the Branch-per-feature approach in mercurial but having created a branch to work in, and merged it back to default, am unable to push my changes back up to my master repository. What is best to do?
I created a branch "Gauge customisation", did some work in that branch and then merged it back into the default. Carried on with a few more changes in default and now I want to commit this back to my master repository. But when I try I get:
abort: push creates new remote branches: Gauge customisation!
hint: use 'hg push --new-branch' to create new remote branches
I didn't think the branching would show up in the master repo and that by merging it locally I could somehow work in the branch (or potentially branches) and then when I've tested everything, push it up to the master repo.
Should the Gauge customisation branch still show up? Really I thought I'd only see default at this stage? But is that me not understanding the tools properly? Should I be creating the remote branch?
Ideally I'd like to be able to open a branch per feature and have 3 or 4 such branches running at any one time (it's the way my company works) so I'd like to get a solid grasp of things now.
Technically you could just commit the new branch to the master repo using --new-branch. As displayed in your screenshot, there is not really a new branch with a head from a topological view, but from a namespace view, i.e. when hg aborts your push, it just wants your explicit acknowledgement to add a new branch (name) to the remote repo.
However, for tasks like your's -- temporary feature branches -- a more common workflow is to not use named branches but anonymous/bookmarked branches or separate clones. Named branches usually are used for long-living branches like stable, legacy, and so on. If you create an anonymous/bookmarked branch and merge it back when its feature is finished, hg won't complain when pushing.
An often recommended reading in that context is A Guide to Branching in Mercurial.
Merging two branches does not get rid of either of them. You will need to close your feature branch manually by switching to it and doing:
hg commit --close-branch -m 'Closing branch'
I have a repository with a master and a develop branch.
I want to create a third named branch, say it's called bugfixes.
I want to be able to update to bugfixes and then have the tip of bugfixes be the same as a previous tag on master. (Say that tag is called Release5.1).
I've tried updating to the branch, and then updating to the tag, but that switches the branch back to master (where the tag is). I've also tried merging
hg merge -r Release5.1
but that only brought in the changes and didn't cause the branch to "go back in time".
How do I get that tag to the the tip of the named branch?
I'm asking this question because my CruiseControl.net guy tells me that we can only do builds off of the tips of branches and not off of specific revisions. (Maybe that is another question....)
First some basics:
Merges are directional:
When you merge bugfixes into master, then master gets the changesets that were committed on the bugfixes branch.
When you merge master into bugfixes, then the reverse happens.
If you want two branches to mirror each other, then you must do the merge in both directions.
I would argue that you don't need the bugfixes branch at all. Instead, I would set a policy that says:
master should always be in a state that may be released
Bug fixes are committed to master
All releases are tags on master
New features are committed to develop
When it is time to release, develop is merged into master
After every release, master is merged into develop to insure that new features are based on the latest release.
This would result in something like this:
If you must have a bugfixes branch, then I set a policy like this:
master should always be in a state that may be released
All releases are tags on master
Bug fixes are committed to bugfixes
New features are committed to develop
When it is time to for a bug fix release:
Merge bugfixes into master
Tag master
Merge master into bugfixes to make them match
Merge master into develop to make sure new features are based on the latest release.
When it is time for a major release:
Merge bugfixes into master
Merge develop into master
Tag master
Merge master into bugfixes to make them match
Merge master into develop to make sure new features are based on the latest
This will result in something that looks like this:
To fix a bug in an old revision, you should:
hg update <TAG>
hg branch Release1.x
<fix the bug>
hg commit -m "Bug fix to older version"
hg tag Release1.2
...if the bug is present in master, then you should also:
hg update master
hg merge Release1.x
hg commit -m "merged bug fix in Release1.x to master"
This would result in something like this:
NOTE 1: At this point, master has commits which should never be part of a Release1.x release. Due to this, you should never merge master into Release1.x.
NOTE 2: If you must support multiple releases of a product in the field, it is common to have a named branch for each major release. These long-running named branches are then used only for bug fixes. If you are very careful, you can merge bug fixes from one release branch to another, but in my experience it is more common to use hg transplant to copy the changes between branches.
I would suggest that you keep the bugfixes branch essentially a mirror of the master branch except for when you are fixing a bug, and once the bug is fixed, merge bugfix back into master to again sync them up.
If you need to maintain multiple old versions of master, you will probably need to have a bugfix named branch for each old version you need to maintain.
Ideally, you wouldn't need a named branch dedicated to bug fixes. Much of Mercurial's power comes from how easy it is to branch from a previous revision (un-named branch). I am not too familiar with CruiseControl.net, but if you can build off of unnamed branches, then all you would have to do is:
Update to the tag you want to base the fix on
Make the changes
Commit (this will make an unnamed branch)
Build / test the tip of the new, unnamed branch
Tag the new version
Merge as needed to make sure all code lines get the bug fix
Due to how Mercurial's internal hash structure works, unwinding changes off of the "stack" (or inserting new changesets into the stack, depending on how you look at it) is a really, really hard thing to do and is likely to break any repositories that were clones of the one you are working on.
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.