Mercurial via TortoiseHg - Merge a named branch then close it - mercurial

I have a named branch, NewFeature, that I made off of the default branch. I've made a couple commits to that branch, and now I'd like to merge it to rejoin the default branch.
Now (each letter is a commit):
default: A---B
NewFeature: \--C---D
What I'd like:
default: A---B-----------E
NewFeature: \--C---D--/
I tried right clicking the directory and selecting "Hg Commit...". I then selected "Close Current Named Branch". I got this error: abort: can only close branch heads
I also looked for a "close branch" option in the repository explorer, but I couldn't find anything.
Could someone please help?
Thanks in advance!
Edit: I posted an issue to TortoiseHg

The example you give is more a Merge than really a Close. Also, if it's that simple, you probably don't want/need to create a named branch.
But if you really want to close a branch through TortoiseHg, eg
you created the NewFeature branch
then both the Default branch and NewFeature branches were modified
then if the NewFeature branch takes quite some time you might have also already merged several time Default into NewFeature (to avoid having too many differences when you'll want to finally merge the NewFeature branch into the Default one)
eventually your new feature is entirely implemented or stable enough, you merged the NewFeature branch into the Default one
From now on, no one is supposed to commit anything on the NewFeature branch, so you'd like to close it.
You can do so in TortoiseHg (I have version 2.3.2):
click Hg Commit... when you are on your NewFeature branch (no need to have anything to commit - or you do it with your final merge)
click "Branch: NewFeature" (it's at the top in bold)
select "Close current branch".

To merge, you need a clean working copy - no uncommitted changes. The merge will be placed in the working copy for review and then you commit the working copy to "complete" the merge.
If you have uncommitted changes you are not prepared to commit, you can see about shelving those changes temporarily (if you have that appropriate extension) or checkout a new working copy somewhere else to use for the merge.
Using the Repository Explorer:
Update the working copy to rev B.
Select rev D row in the revision history.
Right-click on rev D and choose Merge with.... The dialog should show rev B should be the local rev and D should be the other rev.
Click Merge in the merge dialog and resolve any conflicts, if any.
Up to now, nothing has been changed in the repository - your merge is in the working copy. So if something is wrong, you can cancel the merge, revert your working directory, and start over at later time or after making some other additional branch or trunk changes.
If everything is good after steps 1-4, click Commit in the merge dialog to commit the merge.

For anyone that's confused by the answers to this question, here are the instructions on how to do this from within the TortoiseHg Workbench:
How to Merge Feature Branch and Close Branch
Open TortoiseHg Workbench.
Select your repository from the Registry Repository.
Switch to the branch that you would like merge your branch into (default in this example):
Right mouse click the branch that you'd like to merge and close (NewFeature in this example) and choose Merge with Local. This will merge the branch changes from the NewFeature branch into default:
You will see a confirmation box that confirms that your changes will be merged from one branch to another, click through the steps Next, Commit Now and Finish:
Now you can see from the Graph that the changes have been merged in, we can now close the NewFeature branch as we no longer need it:
Update your local to the branch you would like to close, in this case it is NewFeature:
Click commit, the big green tick at the top of the workbench.
In the commit window, you should see the branch that you want to close above the comment text box. Click the branch name:
A window will pop up and select close current branch:
Now click commit. Your graph should show that the branch is closed:

In TortoiseHg, your working copy must be updated to the tip of the branch you want to close before using the commit dialog.
Closing a branch will create a new changeset on top of the branch tip.
The error you described (abort: can only close branch heads) typically occurs if you have updated to a changeset not at the tip of a named branch.

You also seem to get this error is the branch is already closed, i.e. trying to close a closed branch. A more helpful error message would be useful.

Related

Overwriting branch with default in Mercurial

Let say I had a feature branch called feature_x that was worked on, then changesets cherry-picked and transplanted to default, then the branch was closed. Not the best flow, but it's Mercurial, so there is no way of changing the history.
Now I'm going to work again on the feature X, and I feel reusing feature_x branch would be least confusing. However, if I reopen that branch and merge default to it, I've got two problems. First merge conflicts, second changes that were modified in that branch, but never merged into default. So what I'd like to have is clean slate, branch feature_x, but with exact copy of what's currently in the default. Is there a cleaner way of doing that, than creating new branch which will shadow the name?
I think your best bet is to start a new branch off of the current tip of default called feature_x2 or feature_y and leave the past in the past.
But here are some other options:
Is the old feature_x branch confined locally to your repo only or was it pushed? If the former, you could hg strip it and start the branch again at the current default.
If the feature_x name is really, really important, you could do the merge default into it using the internal merge tools and force it to reflect the default branch exactly by doing
hg merge -r default --tool internal:other
Or you could just commit a (file system) copy of default on top of the tip of branch_x. Then you could continue on that branch along your merry way.
I don't know if 2. or 3. will cause strange merge issues down the road. I would test to see if the merge back over to default (or another graft?) could cause issues later.

How to revert to the future?

I started a named branch several months ago which I then abandoned. Now I want to "restart" it. Specifically, I want to bring it up to the latest version of default and start working on it again.
I tried updating to the branch, and then reverting it to default,
hg revert -a -r default
But when I swap back and forth between this branch and the actual default I see 112 files have changed, so clearly they are not the same.
I ended up closing the branch, updating to default, force-switching back to my named branch again, and then force pushed (because it creates a new head).
Now my named branch is the same as default, but I have this short dead branch in my history now.
My questions are:
What was hg reverting to default doing? Was it reverting to the closest default ancestor rather than the tip of default? Even when I tried reverting to the tip via an explicit changeset, the two branches ended up different.
What is the "proper" way to do this?
What was hg reverting to default doing?
For your (really bad )syntax:
Using the -r/--rev or -d/--date options, revert the given files or directories to their states as of a specific revision
i.e to the state of latest ancestor in default branch for all files in repo
I see 112 files have changed, so clearly they are not the same
Wrong assumption
Because revert does not change the working directory parents, this will cause these files to appear modified.
I.e you must commit this modified Working Directory and diff (for testing) heads of branches after it only
What is the "proper" way to do this?
Proper ways is
If you want to save branch-specific changes and only update with latest changes
Update to the head of abandoned branch
Merge default branch to your branch
Resolve all (if any) conflicts
Commit mergeset
If you want to have empty branch only and remove all changes from it
Backout all changesets from branch
Commit backout-changeset
Merge default to branch

Mercurial Checkout without removing changes

I am attempting to work with two separate branches. The first branch is a closer to deployment phase while the second branch is an early development phase. For one reason or another the second branch does not contain some of the developments from the first branch. When I attempt to checkout the first branch while working on the second branch I receive the following error:
abort: crossed branches (use 'hg merge' to merge or use 'hg update -c' to discard changes)
Now my problem is I don't want to get rid of the second branch or really edit it in anyway. When are my options, am I missing some fundamental fact with Mercurial?
You need to either commit your changes or otherwise save them (e.g. with hg shelve) before checking out a new branch.
Mercurial (and most CVSes AFAIK) doesn't save the state of the working directory until you commit the changes, so switching branches effectively discards anything you haven't commited. You can work around this with the hg shelve extension, or by having one working copy for each branch you're working on.

Mercurial merge / remove a feature branch

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'

Mercurial update will overwrite my changes instead of merging

I am coming from CVS background.
Currently, I have 2 mercurial repositories developed parallel. hello-world-bugfix and hello-world-feature (This one is being cloned from hello-world-bugfix)
Now, I want to merge the bug fixed code from hello-world-bugfix into hello-world-feature, so that end of the day, I will get a merged file.
[BUG2 BUG2 BUG2]
START
[BUG1 BUG1 BUG1]
[FEATURE2 FEATURE2 FEATURE2]
Here is how all the things looks like before, pulling and merging. The below two files had already been committed.
Now, I perform pull from hello-world-feature, to pull changes from hello-world-bugfix.
Then, I perform update, with always merge options turned on.
Here is my merged file???
[BUG2 BUG2 BUG2]
START
[BUG1 BUG1 BUG1]
It seems that my previous committed [FEATURE2 FEATURE2 FEATURE2] being overwritten.
It seems that I shouldn't perform update step, which will not merge feature with bug, but overwrite feature away with bug. What is the next correct step I should do after pulling? (through TortoiseHg), so that I can get bug fix code, and remain feature code there?
Here is the final repository view of hello-world-feature
The "always merge" option doesn't do what you think it does.
It only merges uncommitted changes.
When you update, committed files are replaced with the new version.
To merge committed changes, ie. merge branches, you need to do an explicit merge.
So, I would select the BUG2 BUG2 BUG2 changeset in the log, then right-click on the FEATURE2 FEATURE2 FEATURE2 changeset and click Merge, and follow the instructions.
Let me expand on what the "Always merge" checkbox does.
Let's say I have two changesets in my repository, I update to the first of them, then I start modifying one of the files.
At some point I decide it would be better to have started from the other changeset instead, so I want to update to it, keeping my modifications.
If I simply do an update, with uncommitted changes, I get this dialog box when I try to update:
However, if I check the "Always merge (when possible)" checkbox, it will simply assume that I clicked on the Merge button in that dialog and not prompt me.
So the "Always merge" does not have any function at all on committed files, it won't introduce merges for you, it will only try to move your local changes along with the update.