When getting the latest code from a Mercurial repo on the command line, if there are changesets that need to be merged Mercurial raises a warning:
hg up
abort: crosses branches (merge branches or use --check to force update)
This is what I expect, and from the Mercurial book it says "Mercurial is telling us that the hg update command won't do a merge; it won't update the working directory when it thinks we might want to do a merge, unless we force it to do so." At this point I know I need to merge.
How can I get the same behaviour using TortoiseHg? When I hit "Update", it happily updates me to the most recent changeset. Is there a way to warn me that a merge is probably needed? The "Always merge (when possible)" option seems to only apply when you have uncommitted changes.
The reason you get an error from hg update on the command-line is that it doesn't know which revision to pick. There are 2 divergent default heads.
If you were to execute hg update -r <specific rev>, the command completes without error.
When using TortoiseHg, you update by:
right-clicking a specific changeset
selecting Update...
This translates to hg update -r <rev>, so there is no error.
Using TortoiseHg, you always have the revision graph in front of you. The graph shows when newly pulled changesets create a new head.
The Mercurial abort you are seeing is occurring because you have outstanding (ie: non-committed) changes in your working directory, are trying to perform an update, and Mercurial has decided that you should probably perform a merge instead.
TortoiseHg should also warn you about this, but it will do so in a different way. It will spawn a dialogue that asks if you want to Discard, Merge, or Shelve your outstanding changes. This is what it looks like in TortoiseHg v2.X.X, but it should be similar in v1.1.X:
If you're not seeing this in TortoiseHg, you may not have any outstanding changes. Try it again - are you seeing these options?
Related
This is basically the same question as Temporarily switch working copy to a specific Git commit, but for Mercurial.
Say revision 500 is the last revision I've committed in Mercurial. I've worked some more, and realized something went wrong in an earlier revision. So, I've "git stashed", that is, hg shelved my current changes, so I am at a clean revision 500.
Now what I want to do is checkout revision 499, rebuild software, see if it still has error; if it does, checkout revision 498, rebuild software, see if it still has error; if it does, revision 497, rebuild software, see if it still has error; etc etc until I figure out which revision introduced the error.
Once I'm done with that, I want to go back to revision 500, unshelve my previous work, add to that a fix, and then make a new commit (which would be revision 501). That means when I go back in history I don't want to reset anything, nor stage anything from there.
In git I can just do git checkout HASH to go back in history, and once done, git checkout master to go back to the tip. Which commands should I use in Mercurial?
You can go to older revisions using hg update:
hg update 499 # The short id number or the full hash
or alternatively if you want to step to the parent changeset without needing to know the id, you can use a mercurial revset:
hg update .~1
once you have identified your issue you can simply:
hg update tip
and unshelve your changes, add your fix and commit.
I recommend you read the Mercurial: The Definitive Guide. Your question very basic / entry level mercurial usage.
Edit: the link to Mercurial: Definitive Guide is:
http://hgbook.red-bean.com/read/
or the 1.9 version of the boook:
https://book.mercurial-scm.org/read/index.html
I've searched the docs of Mercurial and still am confused. What I'm wanting to do is just reinstate the last commit I made i.e. I want my project to go back to being exactly the same as it was when I made the last commit. I see hg revert, rollback, etc. and still am not understanding which is correct for this situation. Which should I use?
The hg rollback command is used to undo the last action that modified Mercurial's internal store, usually a pull or commit. So, if you want to undo your last commit hg rollback will work.
But it sounds like you want to undo all your uncommitted changes. You have two options. The hg revert --all command will undo all uncommitted changes. Each changed file is saved/backed-up with a .orig extension before being reverted.
If you don't need to preserve your changes in .orig files, run hg update -C. This clears out all uncomitted changes, without preserving anything.
If you have commited changesets and wish to remove them, I like the strip extension, strip extension. With it, you can remove explicit changesets from your history.
However, strip is an unforgiving command, i.e. if you get it wrong there is no retrieval unless you have a backup of the repo. You might prefer the prune command which comes with the evolve extension. Using prune, you can mark changesets as obsolete and they will no longer normally be visible in logs or tortoise. [You can make them visible by adding --hidden on an hg log command line, or in tortoise by enabling the Filter toolbar (from the view menu) and selecting 'Show/Hide hidden changesets'.]
Is there a way to edit a commit message in Mercurial on a commit after other commits have occured using TortoiseHg? I've read these posts:
How to edit incorrect commit message in Mercurial?
Mercurial: how to amend the last commit?
and have been able to update a "regular" commit message when it is the latest commit on a branch (using TortoiseHg). However, I haven't been able to figure out how to edit a commit message when other commits have occurred after the one I want to edit. It always edits the last commit.
Based on Ed Cottrell's comment, I did a test where I made two commits without pushing to the central repo, and I still have the same issue - only the last commit message can be edited.
EDIT: I should clarify that I am looking to update a changeset that has been pushed.
Histedit extension (bundled with TortoiseHG now) has a mess command for changing the commit message of historical changesets.
Unfortunately, this command is not supported by the TortoiseHG GUI so you need to run the command from command line.
As long as the change in question is local and hasn't been pushed anywhere, it is possible.
The commit message is used to compute the globally unique hash id that is used for all repositories to determine whether or not they already have a changeset. If you change the commit message, you change the unique hash id and every repo will see it as a "new" changeset. All other repositories that had the old changeset will try to get the new one and ask that you merge it with itself.... This is not a good thing, so the short answer to your question is "don't do it".
If you could definitively purge that change from all other repos, so that only the local copy is left you could essentially get to the "draft" state. Note that if any repo has the "old" changeset, it will be pushed to the central repo someday and cause the mess that we are trying to avoid.
If the changeset is still local (e.g. in draft status), you can use hg commit --amend if it is the parent of the working directory.
If there are changes after it, I would use mq and hg qimport all the changes down to and including the one where you want to edit the commit message. hg qpop -a and then hg qpush to get to the patch that represents the changeset you want to edit. Then hg qrefresh -e and make your changes. Then just hg qfin -a and you should be good to go.
The advice from Edward is good — if you've pushed your changes to another repository, you should consider them set in stone and not update the commit message or any other aspect of them.
However, we're working on changing this in Mercurial. There is an experimental extension that will allow you to do more extensive history editing and push those edits to other repositories. It is called the Evolve Extension and it enables some behavior that is partly in the core of Mercurial and partly outside core.
When using evolve, you can edit the second-to-last commit message like this
$ hg update .^
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg commit --amend -m 'new commit message'
1 new unstable changesets
$ hg stabilize
more:[5] old tip changeset
atop:[6] new commit message
The extension allows you to do this as long as the changesets are in the draft phase. To keep them in the draft phase after pushing them somewhere, the repository you push to need to be configured as a non-publishing repository. You can read more about this in the Changeset Evolution Documentation.
I have successfully imported patches without having conflicting changes. But when I try to import patch with conflicting changes it throws an error saying "Hunk #1 FAILED at 11.. ". There is no option to merge changes. Is there any other way to accomplish this?
Failed hunks have to be fixed manually. There should be a *.rej file with the rejected hunk from the patch. You will have to apply it manually.
see: https://www.mercurial-scm.org/wiki/HandlingRejects
Manual resolution
The latest versions of TortoiseHg 2.1 have tools for helping you resolve rejected chunks from patches. When you apply a patch and it has rejections, for each file with rejections it asks if you want to resolve rejected chunks. If you click Yes, it shows you a screen with the content of the file (with successful chunks applied) as well as each chunk that was rejected, to allow you to manually do the changes a little easier and mark each as resolved.
Achieving 3-Way Merge
The way that I sometimes handle large rejections is to rebase the patch. In TortoiseHg 1.x I could select one node, right-click on another and actually rebase patches. In TortoiseHg 2.x they have not yet added that back in, but the workaround isn't so bad. You can still rebase patches on the commandline using hg rebase. In either case, you need the mq and rebase extensions enabled (and you probably already have the former enabled). This answer is not a place for teaching how to use mq or rebase (there are plenty of other answers and articles that do that), so I will be assuming some familiarity with them.
In both, you will need to apply the patch to the revision on which it was based (or to one where it applies cleanly or close to clean).
Commandline:
Run hg rebase -s patchRev -d tip. Along with whatever other switches you want on the rebase command.
This will bring up your 3-way merge tool to resolve conflicts, for each file.
Run hg qrefresh to make sure the merge results are updated into the patch.
TortoiseHg UI
Finish the patch as a normal changeset.
Rebase that changeset onto the tip:
Update to the tip. This is important as it used to set the target of the rebase operation.
Right-click on the temporary changeset and select Rebase to bring up the Rebase dialog.
Review that source and destination are correct, and click Continue. If there are merge conflicts, click on the resolved link that appears to open the Resolve dialog.
Click Mercurial Resolve to let Mercurial try to automatically resolve some conflicts.
For anything else that remains use Tool Resolve to bring up 3-way merge for selected files.
Once all are resolved, click Close on the Resolve dialog.
Click Continue and then Close on the Rebase dialog.
Right-click on the temporary changeset now at the tip and go to Modify History > Import to MQ. Now it is a patch again.
I prefer the latter method for the more troublesome instances because it by default prevents Mercurial from automatically resolving conflicts. It allows me to choose the order in which I resolve files and how I resolve them, showing the status of my progress with each step.
I've just recently moved a lot of my Views and Controllers into more appropriate locations and am now wanting to pull down recent changes from our central repo.
I've done a hg pull which worked fine and asked me to do a hg update to bring the changes down locally. This in turn informed me that I needed to do a hg merge however when I try this, I get a message stating that
abort: outstanding uncommitted changes
When I check this using hg status I see in the list all of the files that I've moved (so they're now deleted from their old location).
How do I tell Mercurial that I've removed these files? Do I have to go through each one of them and manually do a remove? Is this something that's possible using only the command line rather than doing it with a GUI tool?
From the command line to automatically hg rm the files you've removed you'd:
hg addremove
It's likely your GUI (you didn't say which you use) exposes that functionality too.
However, that's not what's causing your message. You have some already made local changes that mercurial does know about (unlike the removed files which it doesn't know about until you tell it), and you need a hg commit before you can merge.