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
Related
So I was reading about this two phase commit:
http://docs.couchbase.com/couchbase-devguide-2.5/#performing-two-phase-commits
AFAIK, Couchbase operation is atomic.
Article explains when performing two phase commit I should create a Trans:1 document, which contains the state of the Transaction progress.
1) First is start at Init state.
2) When Transaction start begin process, I should switch Trans:1's state to pend.
By switching to pend state, we can prevent other process pickup the same transaction.
3) Then update the target document's content (in example is dipti and karen) to include a trans the same time.
*If anything fail during the update on either document, we can do a rollback, by checking the trans:1 document's state is equals to pend *
So here is my questions:
a) Since Couchbase operation is atomic, if there is multiple processes try to come pickup the transaction trans:1, there is chance say process A got trans:1's state = init, before process A update trans:1's state = pend, process B may also got the same result trans:1's state = init and try to perform the update.
b) Same reason, when a process updated trans::1 state to pend, update dipti and karen. Because operation is atomic, they cannot really update the same time, only can be update one after another.
Then how can we prevent other process not getting/updating the value of dipti and karen? Because their values is not completely updated.
c) Couchbase is not versioning like Couchdb, how do we do rollback actually?
d) What is the point of keeping trans:1 and set to state:done? Why not just delete the whole document when we know is done?
e) Last question, actually how should I make the transaction document being pickup? I mean like should I run a service that will constantly checking all the Transition document in Linux or something? Running everytime when machine got rebooted?
(The example and codes there using cas() method, I have no idea what is the equivalent in PHP SDK, I imagine is means get()? )
Currently my approach is:
When trans:1 is state:init the process will getAndLock all necessary documents (dipti and karen) and create copy of each of the documents (trans:1::dipti etc)
When trans:1 is state:pend the process will update each document with state:Processed, so I know which documents got updated and need to rollback (from the copy of documents) if any failure.
And rollback will remove all copy documents and as well as the trans:1.
But it still doesn't prevent other process able to get dipti and karen while both is being updating. (i.e. Get total of amount of all people).
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
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.