Mercurial push problem - mercurial

I've just got a problem with hg push command. What I did - Firstly I created 2 branches hot-fix-1 and hot-fix-2 made some changes in each branche, merged it back to default and closed those branches with the command:
hg commit --close-branch
If I start hg branches I have the following output:
default 29:e62a2c57b17c
hg branches -c gives me:
default 29:e62a2c57b17c
hot-fix-2 27:42f7bf715392 (closed)
hot-fix-1 26:dd98f50934b0 (closed)
Thus hot-fix-* branches seems to be closed. However if I try to push the changes I have the next error message:
pushing to /Users/user1/projects/mercurial/mytag
searching for changes
abort: push creates new remote branches: hot-fix-1, hot-fix-2!
(use 'hg push --new-branch' to create new remote branches)
and it does not matter which command I use hg push -b . or hg push -b default
So the question is how I can push those changes to repository without creating new branches.
P.S I used to work with git and was hoping that similar branching model can be used in Mercurial. Thanks

First, as many others have pointed out, using a named branch for short lived work is not a recommended practice. Named branches are predominantly for long lived features, or for release management.
Given that you are in this situation, there are a few options available. All of them involve modifying history (as you're obviously trying to change something you've done).
One is to just push the branches as is, learn from the experience, and move on. If the rest of the team is fine with this, then it's a case of adding --new-branch to your push command.
If the rest of the team, or you, really want the history to be clean, then you'll need to dig deeper.
If you aren't pushing, then definitely make a clone of your current repo. This way you have a copy of the original work to fall back on.
I see 2 main approaches here. Strip off the merges and rebase your branches onto default. This will get rid of the named branches or graft/transplant your changes. Both will be the same end result, but the implementation is slightly different.
If you merely want to use graft, that is now a built-in function starting with HG 2.0. It replaces the transplant plugin, and is much nicer to work with as it uses your usual merge tool if there are conflicts.
To use it, update to the default branch. Then, use the command:
hg graft -D "2085::2093 and not 2091"
the string after -D is an hg revision selection query. In your case, you'd likely only need '{start}::{end}' where start is the changeset at the start of the branch, and end is the end changeset of the branch (ignoring the merge).
If you did several merges, you'd have to pick and choose the changesets more precisely.
The other option is to strip the final merges, and use the rebase command that is part of the mq plugin.
You'll have to strip your merge changesets to get rid of them, and then update to the tip of the branch you want to keep. Select the start of the first named branch, and do a rebase. This will change the parentage of the branch (if you're familiar with Git, then this is very much like it's rebase).
Then repeat for the second branch. You should now have one long branch with the name default.

Just do the:
hg push --new-branch
It will send over those branches, but they'll be closed on the receiving end too, so no one should be bothered.
See my comment on the question for why Named Branches are best saved for long-lived entities like 'stable' and anonymous branches, bookmarks, or clones are more suitable for short lived things like hot-fixes and new features.

Your hot-fix changes were made on branches. Regardless of whether the branch is active or closed, it does exist.
To push the changes to the server (without rewriting history), you must use the --new-branch option (e.g. hg push --new-branch`).
Since you merged the branches into default, there will still only be one head (as you have already seen in your local repo).
If you really can't live with pushing the branches to the server, then you must rewrite your local history as suggested in Mikezx6r's answer.
In addition to the methods he mentioned, you can also import the changesets into a patch queue and apply them to the tip of your default.

Related

Mercurial: abandoning multiple, contiguous commits, on the `default` branch

Requirement
I'd like to abandon a line of development on the default branch, winding back to a revision from about 15 change sets back, and have default proceed from there.
My setup
This is a solo development project with one other guy testing infrequently. I push (frequently) to bitbucket for backups and sharing with the tester. Several of the changes I want to abandon are pushed to BitBucket.
Options
Any of these would be fine…
The abandoned change sets to continue to exist in the repo. It would be nice if they could live on their own branch abandoned-experiment-1, say, that I can close and ignore, but this would need them to move on to a retrospectively created branch (which seems like it would be an awesome feature?).
Some kind of merge to happen where I add a new revision to default that is the rollback to the revision I want to continue from.
The change sets to be destroyed, but I suspect there's no way to achieve that without replacing the BitBucket repo and my tester's repo, which I'm not keen on.
I'm not too sure how to evaluate which options are possible, which is best, or whether there are other, better options. I'm also not sure how to actually proceed with the repo update!
Thank you.
You do have several options (Note that I'm assuming that you are dispensing with all changes in the 15 or so revisions and not trying to keep small bits of them):
Easiest is kinda #2: You can close anonymous branches just like named branches; Tag the tip first with abandoned-development if you wish; hg update to the point you wish to continue from; and continue to code as normal. (You may need to create the new head for new development before you can close the old one. I haven't tested it yet.)
Regarding #3: Based on my cursory read, it does appear that bitbucket has a strip command. If you (both locally and on bitbucket) and your tester strip the offending changesets, you can carry on your merry way and pretend like they never existed.
Achieving #1: If you are definitely set on getting them to a named branch, you could strip them at the remote repos and then hg rebase them onto a new branch locally and then close that branch.
Personally, I try not to mess with history when I can avoid it, so I'd go with the easiest.
Mercurial now has (yet experimental) support for changeset evolution. That is you are able to abandon or rebase already pushed changesets. Internally this works by hiding obsolete changesets (i.e. practically nothing is stripped, only new replacement revisions are added to the history, that is why it works across multiple clones).
To extend #Edward's suggestions, you could also update to the last good revision, continue to commit from there and then merge in the head of the bad changesets using a null-merge:
hg up <good-revision>
... work ... commit ...
hg merge <head-of-bad-revisions>
hg revert --all -r .
hg commit -m 'null-merge of abandoned changesets'
This may be what you thought of as option 2.

How do I put a bunch of uncommitted changes aside while working on something else

If I have a bunch of uncommitted changes and want to set it aside while working on something else instead, and then later (f.i. after several days) come back to it and proceed working. What would be the easiest workflow to accomplish this? (So far I have only experience with Mercurial's basic functionality). My usual method was to create a new branch using clone, but there might be better ways.
You have a handful options:
Shelve the items. This saves the changes and removes them from the working directory so the branch can continue. It doesn't create a change-set.
hg shelve --all --name "UnfinishedChanges"
hg unshelve --name "UnfinishedChanges"
Update/Edit: Newer versions of mercurial may need to use
hg shelve -n "UnfinishedChanges"
hg unshelve "UnfinishedChanges"
You can still use --name as an alternative to -n, but mercurial doesn't seem to like --name anymore. Additionally, the --all is no longer required and mercurial will in fact freak out over it.
Patch queue the items using mq. This isn't too dissimilar to shelve in some respects, but behaves differently. The end result is the same, changes are removed and can be optionally re-applied later. When pushed, the patches are logical change-sets, when popped they are saved elsewhere and are not part of change-set history.
hg qnew "UnfinishedWork"
hg qrefresh
hg qpop
hg qpush "UnfinishedWork"
Commit them locally, update to the previous change-set and continue working and make use of anonymous branches (or multiple heads). If you then want the changes, you can merge heads. If you don't want the changes, you can strip the change-set.
hg commit -m"Commiting unfinished work in-line."
hg update -r<previous revision>
hg strip -r<revision of temporary commit>
Commit them to a named branch. The workflow then becomes the same as option 3 - merge or strip when you are ready.
hg branch "NewBranch"
hg commit -m"Commiting unfinished work to temporary named branch."
hg update <previous branch name>
Personally I use option 3 or 4 as I don't mind stripping change-sets or checking-in partial code (so long as that doesn't eventually get pushed). This can be used in conjunction with the new Phase stuff to hide your local change-sets from other users if need-be.
I also use the rebase command to move change-sets around to avoid merges where a merge wouldn't add anything to the history of the code. Merges I tend to save for activity between important branches (such as release branches), or activity from a longer-lived feature branch. There is also the histedit command I use for compressing change-sets where the "chattiness" of them reduces the value.
Patch queues are also a common mechanism for doing this, but they have stack semantics. You push and pop patches, but a patch that is "underneath" another patch in the stack requires that the one on top of it be pushed also.
Warning, as with all these options, if the files have more changes since the temporary changes that you've shelved / queued / branched, there will be merge resolution required when un-shelving / pushing / merging.
Personally, I don't like any of the answers posted so far:
I don't like clone branching because I like each project to have only one directory. Working on different directories at the same time completly messes the history of recent files of my editors. I always end up changing the wrong file. So I don't do that anymore.
I use shelve for quick fixes (just to move my uncommited changes to another branch, if I realize I'm at the wrong one). You are talking about days, no way I'd shelve something for days.
I think mq is too complicated for such an ordinary sittuation
I think the best way is to simply commit your changes, than you go back to the changeset before you start these changes and work from there. There are some minor issues, let me illustrate:
Let's say you have the changeset A. Than you start your changes. At this point you want set it aside for a while. First of all, commit your work:
hg ci -m "Working on new stuff"
If you want, you can add a bookmark to make it easier to come back later. I always create bookmarks to my anonymous branches.
hg bookmark new-stuff
Go back to the changeset before these modifications
hg update A
From here, you work and generate the changeset C. Now you have 2 heads (B and C), you'll be warned when you try to push. You can push only one branch by specifying the head of that branch:
hg push -r C
Or you can change the phase of the new-stuff branch to secret. Secret changesets won't be pushed.
hg phase -r new-stuff --secret --force
To keep local uncommited changes, easiest way for me is just to save them as a patch file.
hg diff > /tmp/`hg id -i`.patch
and when you need to return to previous state:
hg up <REV_WHERE_SAVED>
hg patch --no-commit /tmp/<REV_WHERE_SAVED>.patch
You can just clone your repo multiple times. I tend to have a root clone, then multiple childs from there. Example:
MyProject.Root
MyProject.BugFix1
MyProject.BugFix2
MyProject.FeatureChange1
MyProject.FeatureChange2
The 4 childs are all cloned from the root and push/pull to/from the root. The root then push/pulls from the master repo on the network/internet somewhere. The root acts as your sort of personal staging area.
So in your case, you'd just clone up a new repo and start working. Leave your 'shelved' work alone in the other repo. It's that simple.
The only downside is disk space usage, but if that were a concern you'd not be using DVCS at all anyway ;) Oh and it does kind of pollute your Visual Studio "recent projects" list, but what the hey.
[Edit following comments] :-
To conclude then... what you're doing is completely fine and normal. I would argue it is the best possible way to work when the following are true: 1) it is short-lived 2) you don't need to collaborate with other developers 3) the changes don't need to leave your PC until commit/push time.

how to undo a commit pull

I faced today my first mercurial problem. I was in my repo, I modified a file and I did a
hg commit
hg pull
followed by
hg update
hg rollback
to repair what I've done, (but actually I didn't push anything)
The problem is that when I did the pull (that I should do before the commit, the head changed and so hg heads looks like :
- Modif from yesterday
- My modif
- Modif from last week
and now I see that someone also did another modification (via the http interface). What should I do to repair my local repo, (if possible modifying my summary) and push it after the 2 others modifications.
Thanks a lot. Quiet confusing, was easier on my "one-man" repo..
Your local repo doesn't need "repairing". This is a very standard case that you will see often if you use Mercurial a lot.
The issue is multiple heads.
You can either merge your heads, assuming your working directory is your version and there is only the other head:
hg merge
This will result in a merge changeset (same as if you were merging across branches).
Or you can enable the rebase extension to re-base your version onto the tip of the branch (the other head):
hg rebase --source<YourVersionNumber> --dest<TipVersionNumber>
This will not result in a merge changeset, and will simply transplant your changes on top of the changeset you specify as if they were born of that changeset all along (hence rebase or "new"basing).
Multiple heads is a funny sort of inner-branch branching... you can continue checking stuff in against your own head and change between heads using hg update. We block multiple heads per branch on our server, so our push would fail. I'd advise keeping multiple heads local as they are less clear-cut than branches.
I tend to work with Mercurial in one of two ways:
If the work is large in scale I will branch it off and follow Continuous Integration practices (constantly merging the main branch into my own etc). I then re-merge back into main when I am happy with the end result.
If the work is small in scale I will simply work against main branch and "merge" heads every so often. I say "merge" as I usually use rebase. Re-basing works great if the changes are simple and conflicts are unlikely.
My hard and fast rule: if I can't use rebase I put it on a branch born of main.

Force pushing to new head when already pulled all changes

Is it possible to forcibly create new remote head when pushing ?
Suppose I have done some local commits on branch "default" then pulled and merged from remote.
Now, I would like to push my commits to remote creating new head and a bookmark but preserve existing remote head and tip - ie. my coworkers should not get my changes yet when doing hg fetch.
Basically this should be a short lived branch (thus not a named branch) for purpose of backup and code review by other before being fully merged into "main" head of default branch.
I've tried --new-branch but it didn't help - no new head was created and remote tip moved to my head.
You can use the --force option to force the creation of a new head.
The --new-branch option is used for named branch, in your case, we are talking of anonymous branching.
The reason why the "tip is moved" is because you merged the changeset recently pulled. Doing that, there's no way to do what you want.
You should just pull the new changes from the remote, and force push everything without merging, this will create a new head (called an anonymous branch), which can later be merged to the default branch by you or someone else after the code review.
You can also use a second repository to push your changes, but this is a totally different workflow.
You cannot preserve tip when you push: it is a pseudo-tag that always points to the newest changeset in a repository. The concept of tip is deprecated in Mercurial because tip can change meaning more or less randomly depending on the order of pushes — as you've seen.
The only way to create a new head is to, well, create it :-) By this I mean that you need two heads — one with your changes and one with the main code you want the colleges to pull and merge with. With only a single head (the one you got after running hg merge) there's no way to signal to the colleges that they shouldn't use it.
A much better approach is to use a separate repository on the server. Go to your repository management software and create a fork for your changes. Then push into that and tell your colleges to review it. They'll pull from your clone and look the changes over. If they like them, then they can merge with the main code and push to the normal repo. If they don't like the changes, then they can throw away their local clone, strip the changesets, or maybe just rollback the pull.
My solution to this issue is to use a previous revision for the start of the bookmark, if there is none or you just do not want to, you can make a dummy commit (like a small change to a README file, etc.) and bookmark the revision before that.
I think hg bookmarks need a lot of fine tuning before they become like git branches, but the process I describe is pretty much what is explained in the mercurial bookmarks kick starter.
For example, if your currently at revision 250.
echo >>README
hg ci -m "enabling bookmark branch_xyz"
hg book my-tip # optional but nice to have
hg book -r 250 branch_xyz
hg up branch_xyz
# hack ... hack hack
hg ci -m "awesome feature xyz (in progress)"
hg push -fB branch_xyz
now this bookmark lives on the server for others to work with ... but can be easily pruned later

What is the standard commit process for Hg?

Is it
pull
update
merge
commit
push
? Or can you do the commit first?
I don't like the idea of pulling and merging without having a version of my local code backed up somewhere in case the merge explodes, but presumably you have to do the merge before you can do a push, because you can't have conflicts in the central repo. Not quite understanding this whole process yet; used to my nice simple SVN.
I recommend to always commit before pulling in changes to your working directory, unless you are 100% sure that your changes and the changes to be merged into your working directory will not conflict.
If you do an updating pull (hg pull; hg update, or shorter hg -u pull) and have any outstanding non-committed changes, any changes coming from outside will be combined with your changes. When conflicts happen, it might be difficult to decide how the merge result should look like, because you can't easily distinguish between your changes and the changes merged in.
When you did commit first, it is much easier to decide how the merge result should look like, because you can always look at both parents of the merge.
So, in effect it is:
hg commit
hg pull -u (if no merge necessary, go to 5)
hg merge
hg commit
hg push
Update: As Martin Geisler has pointed out, it is possible to get at the "original" changed version of a file using:
hg resolve --unmark the-file
hg resolve --tool internal:local the-file
or for all files at the same time:
hg resolve --unmark --all
hg resolve --tool internal:local -all
Still, I find the "commit first" system nicer. At the end, it is personal preference...
I don't know as there's a standard per se, but one of the ideas behind Mercurial is that you can commit as often as you like since it goes to your local repository. So you can commit to your heart's content as much as you like before you pull updates.
I tend not to commit very often, saving up for when I'm preparing to push, but that's me. I can see the utility of committing early and often. I do pull updates frequently as I work to cut down on merge fun.
One other thing I do is to keep a parallel clone of my working repo (cloned from the same repository as my working repo, not cloned from my working repo) so that I can check the original state of a file easily, and if need-be check in an out-of-band emergency fix or what-have-you without complicating my current change set.
Do edits
Commit
Goto 1 until satisfied
Pull
Merge & commit
Push if you want to.
Definitely commit before trying to do something complex like a merge. I don't think mercurial will allow you to merge before committing, but even if it did, what if the merge goes wrong. You have no pre-merge revision to go back to.
Commit early, commit often.
If you don't, you are missing out on a huge benefit of a DVCS.
but presumably you have to do the merge before you can do a push, because you can't have conflicts in the central repo
Wrong statement and poor understanding of distributed workflow and parallel development.
You can merge heads before push, but not have or must. Push can put any data to repo, if it needed and intended to be so
By default, push will not allow creation of new heads at the destination,
since multiple heads would make it unclear which head to use. In this
situation, it is recommended to pull and merge before pushing.
(NB: "recommended to pull and merge before" statement)
You can use commit-pull-merge, stash-pull-unstash-merge, perform fetch with modified WC and merge on the fly, don't merge heads at all or sporadically and push --force with +1 heads - there are not common rule for everybody. And any and every such workflow doesn't produce "conflicts in the central repo", but only different DAG.
Each point of divergence, which appear in case of existing your and other changeset from commmon parent in your (or even central) repo is a point of starting anonymous branches in Hg, which (technically) are absolutely legal, applicable and usual way. How they handled is defined by policy and agreement between developers, PM, QA-team and others
I, personally, prefer finish my task (in one or more amount of commits), after it pull and maybe merge, when it approved by development-policy