imagine this scenario:
- Commit some work with e.g. "Added xy-option".
- After, you realize, that you have forgotten one little detail.
- You add the detail and commit again with "Added xy-option".
- You do some other changes and commit.
- Later you don't like the 2-step commit for xy-option.
So how can one cut out the first commit from history so that in result the changeset for the 2nd commit includes the changes of both?
hg help commit - --amend option (when you commit second changeset)
hg help -e histedit - fold command
Related
I'm using Mercurial with two named branches, foo and bar. Periodically, foo is merged into bar. How do I find the latest foo commit that was thus merged?
I think this would do it:
hg log -r `last(branch("foo") and ancestors("bar"))`
That finds the last commit that is on branch foo and and ancestor of the any commit on branch bar.
If that's not precisely right check the Mercurial Revsets Help -- they can do damn near anything and usually with clear syntax.
I have two branches branch A and branch B. I want to update the branch B with all the contents from branch A , without modifying anything in branch A.
I still want to be on branch B to commit the changes. How can i do that
hg checkout B
hg merge A
hg commit
That will merge A's changes into B and create a new commit on B with A entirely unchanged.
Is there a head to prefer when doing a merge?
What I mean is this: I've got, say, old rev 1000. Meanwhile I did 234 commits and I'm at rev 1234. Now I need to go back to rev 1000 to implement a bugfix for a customer. I commit the bugfix, give the release to the customer, and have the commit 1235.
It's only a tiny change: affecting only one file.
At this point I have two heads: 1235 (whose parent is 1000) and 1234. Their common (grand-grand-...-parent) is 1000.
If I issue an hg merge followed by an hg status, I receive a gigantic list of changes.
However if I do first hg update -C 1234, followed by an hg merge and an hg status, then I only see my unique change (unless I'm mistaken as to what just happened).
Basically, doing this:
hg update -C 1234
hg merge # (merging 1234 and 1235, my two only heads)
hg status
gives a different status than this:
hg update -C 1235
hg merge # (merging 1234 and 1235, my two only heads)
hg status
So basically, I'm asking the status (hg status) after merging the two same heads, but the output of hg status seems to depends on the head I'm currently at.
Is this the normal behavior and, if yes, is there one head to "prefer" over the other?
Do both operation result in the same repository / source code state at the end?
Yes, they both result in the same end state. Merges are almost 100% symmetric in Mercurial. The only non-symmetric part is named branches:
hg update branch-a
hg merge branch-b
hg commit
will create a changeset on branch-a. Updating to branch-b first will create it on branch-b. You can change the branch of the merge commit by issuing hg branch before you commit, though, so the default branch name more like a suggestion.
However, in your case, I would definitely update back to revision 1234 and then merge the bugfix into this revision. They way I'm thinking of it is that you have a main line of development — this is where you're working on new features for the next release.
When you make a bugfix to an old version you update back, make the bugfix, and make a bugfix release to your customer. You've then created another (tiny) branch for the bugfix. The question about where to update to before the merge is now this:
do I want to continue along the bugfix branch? If so, then stay at the bugfix and merge the main branch into it.
do I want to continue along the main branch? If so, then update back to the main branch and merge the bugfix branch into it.
In this case it only makes sense to update back to the main branch — you want your bugfix together with the new features, and you want to add more features.
Think about the named branches I mentioned above — there you would do
hg update 1.x
# fix bug
hg commit
hg tag 1.3
to go back to the 1.x series of your software, fix the bug, and make a 1.3 bugfix release. When done, you want to merge with the default branch. Since the branch name is inherited from the first parent in a merge, it's most smooth to update to default first:
hg update default
hg merge 1.x
hg commit
That's the recommended way to do it in Mercurial.
Case 1: Updating the Working Directory
$ hg update [-r REV]
This switches the working directory to the specified revision. However if my working directory has modified changes, the changes are merged back with REV. I realize I can use the -C flag to discard my changes but I am trying to put across my concern to the behavior of update command in different scenarios.
Case 2: Switching to a Branch
$ hg update <bname>
This switches my working directory to <bname> branch. However my uncommitted changes are not merged until I explicitly use the merge command.
Case 3: Updating pulled change sets from a Remote Repository
$ hg pull
$ hg update
This again merges my working directory with the change sets from the remote repository after a recent pull.
Mercurial 1.9.1
It has to do with the relationships between changesets. If there is a direct path between the parent changeset of the working directory and the target changeset you're updating to, Mercurial will try to transfer the changes in the working directory with a merge operation. So if the changeset you're on is either a direct descendant or direct ancestor of the changeset you want to update to, it will usually work.
In the following diagrams, letters represent branch names and the numbers are the sequential revision numbers. wd is the working directory.
When Mercurial will merge uncommitted changes:
Update on the same branch:
--A1----A3----A5---wd
\ /
A2------A4
Above, changes have been made based on A5. If you update to A4, Mercurial will merge the uncommitted changes to transfer them.
--A1----A3----A5---A6---wd
\ /
A2------A4
Also, if there are additional changesets (such as A6) this will still work, because A4
Update to different branch (this time, updating to B4):
--A1----A3----A5---wd
\ /
B2------B4
Above, revisions 2 and 4 are on a different branch B, which has been recently merged back to branch A. Mercurial will also transfer uncommitted changes, because A5 and B4 are so closely related. And also:
--A1----A3----A5---A6---wd
\ /
B2------B4
Likewise, when you pull new changes from the remote repo, usually they will be descendants of the changeset that is the parent of your working directory, so that provides the direct relation that makes the merge of uncommitted changes possible:
--A1----A3----A5---A6---wd
\ / \
A2------A4 A7---A8---A9 (A7 through A9 pulled)
When Mercurial will not merge uncommitted changes:
Update on the same branch:
--A1----A3----A5
\ /
A2------A4---A6---wd
Above, changes have been made based on A6. If you update to A5, Mercurial will refuse, saying either "outstanding uncommitted changes" or "crosses branches". This is because you're trying to merge uncommitted changes from one head to another head, and they are (by definition) not ancestors or descendants of each other. The same occurs with named branches, of course:
--A1----A3----A5
\ /
B2------B4---B6---wd
Getting around it
There's a few different ways you can move your changes to a new parent when Mercurial won't automatically try to merge the uncommitted changes:
Shelve the changes, update, then unshelve (manually handling conflicts).
Making a patch in MQ will do the same thing, as shelving uses the same patches, just not a queue of them. You'll refresh the patch, pop it, update to the other branch, and then push the patch (manually handling conflicts).
Commit the changeset, rebase it to the other branch (you will have to go through a merge process), and then import it into MQ so that it isn't a changeset anymore but a patch.
Forget about branch names, they are nothing more than metadata on the changesets. Your changes will be merged if you update to a revision which is either a descendant or ancestor of your current working parent, and they won't be merged otherwise.
Thus, you can update from A to B, if there is a way to get from A to B, moving along either parents only, or children only. E.g.:
-- A -- 1 -- 2 -- B --
Here, you can update from A to B and from B to A because they are descendant and ancestor of each other.
-- A -- 1 -- 2 -- C --
\
4 -- B --
Here, you also can update from A to B (or from B to A), even if they are on different branches. You cannot, however, update from B to C, because to do so, you'll first have to go backward, then forward.
Note you can work around it by doing the backward-forward maneuver yourself:
(on revision B)
$ hg up 2
$ hg up C
I have a long-running script that may or may not have an uncomitted transaction at the end. I would like to have something at the bottom to just clean up and if there is a transaction hanging out somewhere, just commit it, and if there is one another level up, commit that one, etc.
How can I do that?
Thanks!
Loop until all commuted. Strange situation to be in though...
WHILE XACT_STATE() = 1
COMMIT TRAN