Mercurial - Merge two branches into a 3rd new branch - mercurial

Is it possible to, instead of merging one branch into another existing branch, merge 2 branches into a 3rd new branch?

Just merge your 2 existing branches and consider the merge as the tip of the 3rd new branch and the previous heads of the merged branches as your 1st and 2nd branch:
o changeset: 3:92692c4a6b12
|\ bookmark: masala
| | summary: merge salt and pepper
| |
| o changeset: 2:a5f955adf03d
| | bookmark: pepper
| | summary: add some pepper
| |
o | changeset: 1:2b56f2dc115f
|/ bookmark: salt
| summary: add some salt
|
o changeset: 0:e992ce7dd508
summary: initial
Here bookmarks have been used to mark different lines in development. So if you want to work in the new 3rd branch, update to masala, if you want to work on your 1st branch, update to salt, and similar for the 2nd branch update to pepper before you continue to work and commit.
If you prefer working with named branches (instead of bookmarks), just issue a hg branch masala before you commit the merge of revision 2 and 1.
The basic message is that although the graph only has one head, you are free to interpret it as 3 different lines of development.
Now, let's say you want to continue the work in the 2nd branch, pepper:
$ hg up pepper
... hack ...
$ hg ci -m "need more pepper"
And then you have some ideas for the salt thing:
$ hg up salt
... hack ...
$ hg ci -m "less salt please"
Now the history graph shows your 3 branches more clearly:
o changeset: 5:d1f8eb72119a
| bookmark: salt
| summary: less salt please
|
| o changeset: 4:acc9b01f584f
| | bookmark: pepper
| | summary: need more pepper
| |
+---o changeset: 3:92692c4a6b12
| |/ bookmark: masala
| | summary: merge salt and pepper
| |
| o changeset: 2:a5f955adf03d
| | summary: add some pepper
| |
o | changeset: 1:2b56f2dc115f
|/ summary: add some salt
|
o changeset: 0:e992ce7dd508
summary: initial
An alternative to bookmarks and named branches is to use different clones for individual branches. That is you clone your repo with the unmerged branches and merge them in the clone. Which approach is best, depends on your specific workflow and personal preferences.

Related

Mercurial, simplifying a multi-headed monster

I share an online Mercurial repository with one colleague. Came to a complicated situation:
On station A, made a mess and had to back up a few revisions. Created a clone, added new code there, and manually merged changes INTO that clone.
Can't push, I now have multiple heads. Giving one of these a name as a named branch fixes nothing, to my dismay. After some study, I responded by closing all but the head I really wanted. Good idea? Bad idea?
Push will create a new remote head. Having spent more than enough time on this, I went for push -f. It worked. But I really would rather have CONVINCED it that this is the true and rightful continuation of the head that was already there. But NOT a real merge, a full replacement with my new set of code files. How?
Going to Station B and doing a pull, I don't get my newest, wanted head, I get the original head which I had closed, at its last real version. I'm looking around for how to tell the "pull" command to get the other head. How do I do that? How do I query the server as to what heads or branches it contains, so that I can intelligently pick one?
More information:
Station A view:
Station B view after pull:
There are a number of issues I see:
1) you attempted to use clone to git rid of the issue. Once you get familiar with Mercurial, you will find that there are better ways to fix the type of issues you describe.
Your description is unclear what steps you took with the clone. For example, did you clone from the master remote repo or from your local repo with the bad code.
2) When you tried to push, it stopped you with the warning about creating multiple heads on the remote repo. By using the -f option to hg push, your problem escalated. You ended up with two heads in your remote repository. Be careful with push -f. It overrides Mercurials attempt at preventing you from creating a problem. There may be good reasons for creating multiple heads on a remote repository, but it is best be be very clear that that is exactly what you want to do.
For the follow, I will assume that you pushed multiple heads to your remote repo.
At this point, the best solution would be to merge the two heads into one.
From you description, it sounds line you have something similar to this:
hg log -G
# changeset: 4:fa78b78c5094
| tag: tip
| user: Craig
| date: Sun Oct 21 10:38:15 2018 -0600
| summary: Good commit 2
|
o changeset: 3:af5cfaf651ff
| parent: 0:f46808ac779b
| user: Craig
| date: Sun Oct 21 10:38:02 2018 -0600
| summary: Good commit 1
|
| o changeset: 2:aabb053f11a9
| | user: Craig
| | date: Sun Oct 21 10:37:44 2018 -0600
| | summary: Bad commit 2
| |
| o changeset: 1:9168cd930d40
|/ user: Craig
| date: Sun Oct 21 10:37:32 2018 -0600
| summary: Bad commit 1
|
o changeset: 0:f46808ac779b
user: Craig
date: Sun Oct 21 10:18:32 2018 -0600
summary: Commit some work
In my test repo, I would do the following to merge the heads together:
hg update 4
hg merge 2
Note: hg merge without the number will work if there are only two heads.
You will likely need to resolve merge conflicts.
Once the merge is complete, it will leave your repository with modified files (the merge results). Make sure that these modifications contain the changes you want only.
once you are completely sure that the changes (as a result of the merge) are what you want, you can commit the merge:
hg merge -m "Merge heads"
At this point you should now have just one heads that looks like the following:
# changeset: 5:8f9e6a947b3a
|\ tag: tip
| | parent: 4:fa78b78c5094
| | parent: 2:aabb053f11a9
| | user: Craig
| | date: Sun Oct 21 11:14:43 2018 -0600
| | summary: Merge heads
| |
| o changeset: 4:fa78b78c5094
| | user: Craig
| | date: Sun Oct 21 10:38:15 2018 -0600
| | summary: Good commit 2
| |
| o changeset: 3:af5cfaf651ff
| | parent: 0:f46808ac779b
| | user: Craig
| | date: Sun Oct 21 10:38:02 2018 -0600
| | summary: Good commit 1
| |
o | changeset: 2:aabb053f11a9
| | user: Craig
| | date: Sun Oct 21 10:37:44 2018 -0600
| | summary: Bad commit 2
| |
o | changeset: 1:9168cd930d40
|/ user: Craig
| date: Sun Oct 21 10:37:32 2018 -0600
| summary: Bad commit 1
|
o changeset: 0:f46808ac779b
user: Craig
date: Sun Oct 21 10:18:32 2018 -0600
summary: Commit some work
Before pushing the merged code to the remote repository, it is very important that you verify that the changes are correct and tested. pushing a bad merge just compounds the problem.
My best advice is to take you time with this and verify each step does what you expect and want.

How to get all parents changeset in Mercurial

Currently I am struggling with the Mercurial (v. 2.6.2) log feature. For creation of a change log of our software I have to collect the following set of changeset:
|
O A First interested revision on default
|
O B start of branch
|\
| \
| O C Commit on branch
O | D commit on default
| /
|/
O E Merge from branch to default
|
|
O F start of release branch
|\
| \
O | G on-going development on default
| O H Patch fix on release branch
| |
So what I try to get is a collection of changeset that contain A,(B),(C),D,E,(F),H.
The changesets in brackets would not harm if they are part of the log, but they would not be necessary. The changeset G must not be part of the log.
$ hg help revsets
$ hg log -r A::H

TortoiseHG: Only pull selected changesets?

I have 2 repositories A and B. I make 5 changes to A, but only 2 of them should also appear in B. So this is what I tried:
Pushed the 5 changes to repo A
Changed the path of repo B to that of repo A
Clicked the "Check for incoming changesets" button for repo B
Now I see the 5 changes I made for repo A. This is where I am stuck, how can I only get 2 of the 5 changesets now? I tried "Pull to here", but this does not work in my case, it gets all changesets below the one I selected.
How can I get for example the first and third changeset from the list? Possible at all?
Thanks! :)
When you pull changesets between repositories you cannot skip changesets in between. If a changeset has different parents in two repositories, it is not the same changeset.
You can accomplish what you are after by exporting patches of the changesets you want and then import them into the other repository. That way, you have the changes you want from repo A in B, but the changesets will not have the same nodeid in the two repositories.
It sounds like A and B were clones of the same repository. If that is the case, branching is probably what you need. If you have a history where A contains:
C:\example>hg glog --template "rev{rev}:{desc}\r\n"
# rev6:change7
|
o rev5:change6
|
o rev4:change5
|
o rev3:change4
|
o rev2:change3
|
o rev1:change2
|
o rev0:change1
If your B was originally just rev0 and rev1 and you wanted rev3 and rev5 added to it, you can just update to rev1 and graft rev3 and rev5 onto it:
C:\example>hg update 1
0 files updated, 0 files merged, 5 files removed, 0 files unresolved
C:\example>hg glog --template "rev{rev}:{desc}\r\n"
o rev6:change7
|
o rev5:change6
|
o rev4:change5
|
o rev3:change4
|
o rev2:change3
|
# rev1:change2
|
o rev0:change1
C:\example>hg graft 3 5
grafting revision 3
grafting revision 5
C:\example>hg glog --template "rev{rev}:{desc}\r\n"
# rev8:change6 <--- contains change 1, 2, 4, 6
|
o rev7:change4
|
| o rev6:change7 <--- contains changes 1-7.
| |
| o rev5:change6
| |
| o rev4:change5
| |
| o rev3:change4
| |
| o rev2:change3
|/
o rev1:change2
|
o rev0:change1
To avoid duplication of changesets and a little pre-planning, the changes that need to be on both A and B branches can be checked into B and merged into A, whereas changesets that only belong on A can be directly checked into A:
C:\example>hg glog --template "rev{rev}:{branch}:{desc}\r\n"
# rev8:A:change7 <--- contains changes 1-7.
|
o rev7:A:Merge
|\
| o rev6:B:change6 <--- contains change 1, 2, 4, 6
| |
o | rev5:A:change5
| |
o | rev4:A:Merge
|\|
| o rev3:B:change4
| |
o | rev2:A:change3
|/
o rev1:default:change2
|
o rev0:default:change1

how to work with other developers using hg's defaut stable branch workflow

I found an article talking about git's workflow here, And tried to apply it to my own hg project, seems that it's kind of mess when I create a branch for each feature, cause in git, the branch could be deleted, and in hg, it can only be closed. so this will lead to a huge amount of closed branches in the repo, and that's what I don't want to see.
later, I googled another article which talks about a Hg workflow here I tried it, and it seems good when I am the only developer of the project, but when I tried to add another developer, the history became a little complicated.
I tested this with three repos
1, Base
2, devA ---> stands for developer A's repo
3, devB ---> stands for developer B's repo
first I worked on devA, making changes on devA's default branch, and bugfix's on devA's stable branch. After that, I push devA to Base.
devA's graph:
in case the image broken, the text based graph is here:
# summary: Merge with stable
|\ tag: tip
| | parent: 4:d2973e149720
| | parent: 5:3788143e99fc
| | date: Mon Jul 30 13:17:44 2012 +0800
| |
| |
| o changeset: 5:3788143e99fc
| | branch: stable
| | parent: 3:4a955d01ea44
| | date: Mon Jul 30 13:17:19 2012 +0800
| | summary: fix a bug in featureA
| |
o | changeset: 4:d2973e149720
| | parent: 2:8e106fcfa9bf
| | date: Mon Jul 30 13:16:46 2012 +0800
| | summary: finish featureA advance
| |
| o changeset: 3:4a955d01ea44
|/| branch: stable
| | parent: 1:7b81b986d485
| | parent: 2:8e106fcfa9bf
| | date: Mon Jul 30 13:16:01 2012 +0800
| | summary: Merge with default
| |
o | changeset: 2:8e106fcfa9bf
| | parent: 0:7d7dc422ec7c
| | date: Mon Jul 30 13:15:43 2012 +0800
| | summary: finish feature A
| |
| o changeset: 1:7b81b986d485
|/ branch: stable
| date: Mon Jul 30 13:14:49 2012 +0800
| summary: Create stable branch
|
o changeset: 0:7d7dc422ec7c
date: Mon Jul 30 13:14:21 2012 +0800
summary: Init commit
and then I switched to devB, because I want to emulate a parallel work, so I did not pull from Base, instead I begin to work on devB's default branch, and do bugfix on devB's stable branch.
devB's graph is similar with devA's graph
Here comes the problem, when I try to push devB's changes to Base, it said there is a conflict, and I need to merge it locally, I pulled the changes and then my history graph in devB became kind of messy because I got devA's default and stable so in devB there is now two default branches and two stable branches.
what confused me is how real projects use this kind of workflow, mecurial's branch graph is here. It seems pretty clean, but how did they do this?
Don't split repository into "developer branches", branch "feature branches" instead. Each branch should have reasonably small number of commits all devoted to implementation of particular feature. On each build/release, you select branches ready to be deployed and merge them to default.
The latest hgflow (0.9.5, not yet released officially, but it works great) actually allows you to completely delete a feature branch. Excerpt from its Wiki:
Added --erase for the finish action. With this option, you erase (i.e., completely delete from the repository) the branch after it is successfully finished. The final effect is as if all changes in the branch were collapsed and then committed as a single changeset to the destination branch which the branch was merged to. Check out hg flow help #finish for a bit more detail.

mercurial log of changests on merged named branches, but not unmerged

I want to be able to get a "hg log" of every changeset that appears in the graph between
changeset1 and changeset2. I cannot find a way to do it without either
a) omitting nodes on named branches that ARE merged between changeset1:changset2
or b) including nodes on named branches that ARE NOT ancestors of changeset2
Here's a "hg glog" of a simple example with 2 named branches plus the default branch. One named branch gets merged and so its nodes are relevant, the other is irrelevant:
# changeset: 5:e384fe418e9b
|\ tag: tip
| | parent: 2:7dc7af503071
| | parent: 3:0a9be59d576e
| | summary: merge somefeature branch into default
| |
| | o changeset: 4:4e8c9ca127c9
| | | branch: unmerged_feature
| | | parent: 1:ef98ad136fa8
| | | summary: change that is not merged into ending changeset
| | |
| o | changeset: 3:0a9be59d576e
| |/ branch: somefeature
| | parent: 1:ef98ad136fa8
| | summary: changed b.txt
| |
o | changeset: 2:7dc7af503071
| summary: changed a.txt
|
o changeset: 1:ef98ad136fa8
| summary: added b.txt
|
o changeset: 0:271b22b4ad30
summary: added a.txt
I want a log command that will give me all the nodes that are descendent of rev 0 and ancestors of rev 5. This is everything except rev 4.
I can get too much info:
hg log -r 0:5 --template "{rev}:branch={branches},desc={desc}\n"
This gives me a log entry for rev 4, which is not an ancestor of rev 5:
0:branch=,desc=added a.txt
1:branch=,desc=added b.txt
2:branch=,desc=changed a.txt
3:branch=somefeature,desc=changed b.txt
4:branch=unmerged_feature,desc=change that is not merged into ending changeset
5:branch=,desc=merge somefeature branch into default
I can get too little info:
hg log -b default -r 0:5 --template "{rev}:branch={branches},desc={desc}\n"
omits rev 3, which is a descendent of rev 0 and ancestor of rev 5
0:branch=,desc=added a.txt
1:branch=,desc=added b.txt
2:branch=,desc=changed a.txt
5:branch=,desc=merge somefeature branch into default
If you're using a newer version of Mercurial (1.6.0 or higher), you can use the revsets feature. In this case, you need the ancestors() operator:
hg log --rev ancestors(5)
See hg help revsets for more information.