I'm not sure why this is so hard to figure out or google, but I am trying to take changes I made to a private branch and push them to the default branch.
In other words:
I pulled from the default branch a few weeks back and made major changes
Since then, I have finished my work
I then merged the code from the original default branch (just the code, the HG is still set to the "NewBranch"
Now that the code works, I want to commit and push these changes back to the default branch and continue my development from there.
But I can't find any information on how to do that. If I switch branches, I lose all my changesets since I am still in the NewBranch. I can't figure out what rebase or transplant do and can't find guides that explain scenarios on what they could be used for... So hopefully someone here knows what to do!
I am specifically using Mercurial on Eclipse but I am fine doing this on command line if its easier.
merge is the way to get changes from one branch into another. I know you merged default into feature, but now you go the other way. Here's an example where numbered changesets come from other people and lettered changesets comes from you:
Before you do anything you clone and have this:
[1]---[2]---[3]---[4] (default branch)
then you create your branch named 'feature' and do two commits on it, yielding:
[1]---[2]---[3]---[4] (default branch)
\
[A]---[B] ('feature' branch)
then you hg pull to get changes to default since you diverged down in your local repository:
[1]---[2]---[3]---[4]---[5]---[6] (default branch)
\
[A]---[B] ('feature' branch)
now you want their changes (5 and 6) integrated into your branch so you do:
hg checkout feature # make sure you're looking at the he head of your branch
hg merge default # merge default into your branch
which yields:
[1]---[2]---[3]---[4]---[5]---[6] (default branch)
\ \
[A]---[B]---[C] ('feature' branch)
If I'm understanding correctly, you've already done all that, so now you just need to bring your branch, including the new merge commit, C, into default, which again is done via a merge:
hg checkout default # hop back to default, files look like [6] and [A] and [B] are missing
hg merge feature # merge feature into default brining [A] and [B] in
that yields:
[1]---[2]---[3]---[4]---[5]---[6]---[7] (default branch)
\ \ /
[A]---[B]---[C] ('feature' branch)
That looks like a lot of work drawn out that way, but in practice it's usually just:
hg branch feature
....work....
hg commit
hg pull
hg merge default
hg checkout default
hg merge feature
and if the pull didn't bring down any new work from other you can skip the merging of default into yours.
That does create two new merge changesets. They're easily hidden on hg log if you find them unhelpful (some people love having a record of which direction each merge went), but if you want to avoid them entirely you can use bookmarks (very similar to git branches) instead of "named branches" for your features -- then you'll avoid a merge changeset when coming back since it would be the spiritual equivalent of what git calls a "fast forward" merge.
Related
I sometimes but not always end up with two heads on my default branch. The sequence of events is something like:
hg pull
hg update -C default
hg branch mybranch
hg merge default //merge in default
hg commit -m"merged mybranch into default"
hg heads -default //shows 2 heads
hg push --branch default //won't let ne. create 2 heads
The 'rival' head appears to be a changeset committed to default earlier in the day.
What I don't understand is why this happens sometimes and not other times.
The explanation I am usually offered is that the other guy pushed a change after I did a pull (my first action in the list above). But I think this happens in other cases e.g. when he pushed his changeset before I started.
I would have thought that when I pull default with his commit I get default with one head. My merge/commit should just create a new head after that. Why does it create a second head?
First of all, this is a totally normal situation. It's not a problem, or an error, or something to be avoided -- it's how a DVCS works.
In brief: you get two heads whenever two people start working from the same commit and do different things. It doesn't matter if they do it in their own (named) branch (as you're doing above) or on default. Once you merge your work back to default and someone else has done work on default you've got two heads and someone has to merge. It's just how things are.
Before you push do a hg pull and then a hg merge and you'll integrate your work with yours, by creating a new merge commit, with two parents -- your work and their work -- and then you push and you'll not see that warning.
Incidentally, you might want to check out the bookmarks feature. It's better suited for per-feature branches like you appear to be doing above than the named branches you're using, but it in no way saves you from having to deal with multiple heads.
check state of repository immediately after pull (pull can bring new head in default for you) with hg heads
hg branch without commit do nothing (you haven't mybranch)
Even if you'll create mybranch and merge it with default's tip (according to your syntax), it will not eliminate 2-nd head in default
I'm using hg bookmarks in my repo because they allow me to work with ease on different features. The thing with Mercurial is that, still, all commits are associated with a branch. So, what I did is that I have a lot of local changes, with a lot of pulled (but not updated changes) to the same branch. In other words, my local repo looks like this:
default -------E-F---------
newf -A-C-D---------J---
newf,bmark --\--------H-I----K
newf is a branch that is on remote, pulled up to J, and bmark is the bookmark I created. Everything in newf, marked with bmark is strictly local to my machine.
Now, I would like to re-assign H, I, and K (actually, there are ~20 changes) to a different branch, which I can push to the repo. Is there a way to do it in Mercurial, so that my working copy (I still have some uncommitted changes) remains as unaffected as possible?
Based on the suggestion to use 'rebase', I tried the following steps:
hg up -r A
hg branch newbranch && hg ci -m "will hold some development"
# This effectively made a commit X
hg up bmark
hg rebase -d newbranch
Apart from getting some errors about phases, the rebase gives me something I would not expect:
default -------E-F---------
newf -A-C-D---------J---
newf,bmark \ -----H-I----K
newbranch \X/
That is, H,I, and K are listed to still belong to newf and bmark, and they are on top on commit X that belongs to branch newbranch. Am I doing something wrong here?
I use rebase to move commits from one branch to another. Would it work in your case?
So, I have an Hg repo that looks like this:
O [default] [tip] Current repo
|
O Merging changes from named branch
|\
|O Something from a named branch
||
O| [prod-v1.2] Okay, version 1.2 is done
Now I've come across a problem in version 1.2. I can update to the tag prod-v1.2 and commit it, but when pushing, it warns me about multiple heads. Is there a way I can make my new "bugfix" branch the default temporarily? How can I manage this?
The best way to do this, is to create a new branch for your bugfix and then commit in it. The next time you will have to do changes on the version actually in production, you can just update to your branch and commit your change there.
If needed, you can easily merge the content of the branch to your development branch.
An example of this kind of workflow is described here : http://stevelosh.com/blog/2010/05/mercurial-workflows-stable-default/ but you can also find many more way to do this.
In your specific case, you can do something like this if you made only one commit :
hg rollback # rollbacking last commit to allow for branch creation
hg branch bugfix-v1.2
hg commit
hg push
You can now switch back to your default branch and continue to work on the next version... Next time you have a bugfix to do, just switch to your branch with hg update bugfix-v1.2 and commit here.
In my repo, I have the revisions 1 to 10. I've pushed up to 5 (so the next hg push would publish revisions 6-10).
But I have to interrupt my work now and the result isn't 100% complete. So I'd like to move the revisions 6-10 into a new "experimental" branch to allow someone else to complete the work without disrupting the sources for everyone.
How can I add a branch to a non-tip revision (in my case: Starting with revision 6)? Or should I use a completely different approach?
You cannot apply a branch name after the fact without modifying your history.
The most simple approach is to ask the other users to use revision 5 as the parent for any changes they create. For example, the other users would:
hg clone <your repo> or even hg clone --rev 5
hg update -r 5
work, work, work
hg commit
When they commit a change, it will create a second head on the default branch, but that should not create any problems. You will simply need to merge the two heads together once your experimental changes are complete.
That being said, moving your changesets onto a branch can be accomplished using Mercurial Queues (MQ). The following sequence shows how it be done:
hg qinit (Create a new patch queue)
hg qimport --rev 6:10 (import r6-10 into a new patch queue)
hg qpop -a (remove all patches from your working copy)
hg branch <branch name> (create your new experimental branch)
hg qpush -a (apply all the patches to your branch)
hg qfinish -a (convert all patches to permanent changesets)
Tim already has good suggestions. Additionally you could push your experimental changes into a distinct experimental clone on your central server (I guess you use one). This clone could also be used by other developers to push their not-yet-finished work in order to let others review or continue it. It is also clear that this clone's code is not ready to be used. Once some task is finished, the corresponding changesets can be pushed to the stable repository.
Actually named branches are a good idea for your case, but the fact that their names are burned into history mostly is more a problem than a feature. IMHO Git's branch names are more practically. However, to some extend you could also handle your case with bookmarks, which are pushable since Mercurial 1.7 (not sure here). That is you bookmark revision 5 with something like stable (or whatever you agree on in your team) and revision 10 gets bookmarked with something like Aarons-not-finished-work. The other developers would then just pull stable, except your colleague who is supposed to continue your work, who would pull the other bookmark. However, personally I did not use a such workflow yet, so I cannot say if it performs well in practice.
We converted everything to Mercurial coming from CVS and so far so good. An issue we encountered today though is this situation.
Before the move to Mercurial I had a few pending changes from a while back, features that were started and later postponed for various reason. Odds are that someone else will finish those features months from now picking up from where I left off.
After cloning the new Mercurial repository I created separate branches to isolate those features.
It left me with something like this (made up rev. number)
hg update default
hg branch feature1
hg commit -m "Description of what I was doing in feature1"
hg update default
hg branch feature2
hg commit -m "Description of what I was doing feature2" (my tip is now here)
hg update default
hg push -f (to force the creation of my new branches, w/o affecting default, I haven't merged them)
During this the team have been working and pushing to our central repository so the default branch is say rev 40 (tip)
Now my push -f worked fine but positioned (tip) to my latest change -> 50:feature3 (tip). I was expecting the tip to stay at default on the central repository and just have my branches in there for someone to pick them up whenever. The graph also looks pretty funny when I use hgwebdir so I am pretty sure that's the wrong approach.
How would I do this? Should I close the branch first? Is tip actually important or just meta-data.
tip is always the most recent changeset added to the repository. From hg help revs:
The reserved name "tip" is a special tag that always identifies the most recent revision.
So long as the head of the default branch is what you expect, you'll be OK. No need to close the branch (but it's better to use hg push --new-branch if your version of Mercurial is new enough to support it).
tip is just an automatically-applied label referring to (I think) the most recent commit. Not a big deal; it's just there for convenience.
The tip label is pure meta-data and always points to the changeset with the highest revision number -- there is no more logic than that.
However, the fact that tip now points to a changeset on the feature branch wont cause you any trouble. When people make a clone, they will automatically be updated to the tip-most changeset on the default branch. So they can begin working right away after a clone. Furthermore, people who already have a clone will stay on their named branch when they run hg update. Here hg update takes you to the tip-most changeset on that named branch, e.g., on default if that is where you started.
People may think that hg update tip is the same as hg update, but that is only when there are no named branches at play. With named branches, giving an explicit revision name such as tip can changeset your named branch -- a plain hg update cannot.