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.
Related
I'd like to move the "tip" tag to revision 272 on the following graph. Is it possible without commiting on that head?
o changeset: 273:40cf2237a3d5
| bookmark: push-notification
| tag: tip
| parent: 271:3640ade1df38
| user: xxxxxxxxx <xxxxx#zzzz.com>
| date: Mon May 12 16:11:01 2014 -0300
| summary: Lorem
|
| # changeset: 272:70f0a3f3b74a
| | parent: 269:b125e398bd69
| | user: yyyyyyyy <yyyyyyy#zzzzz.com>
| | date: Fri May 09 17:58:35 2014 -0300
| | summary: Ipsum
| |
o | changeset: 271:3640ade1df38
| | user: yyyyyyyy <yyyyyyy#zzzzz.com>
| | date: Fri May 09 17:58:35 2014 -0300
| | summary: Dolor
| |
o | changeset: 270:d064bf9ffad6
| | parent: 268:01563b587c71
| | user: xxxxxxxxx <xxxxx#zzzz.com>
| | date: Fri May 09 11:00:47 2014 -0300
| | summary: Sit
| |
| o changeset: 269:b125e398bd69
| | parent: 267:602390d3eeb1
| | user: xxxxxxxxx <xxxxx#zzzz.com>
| | date: Fri May 09 08:13:06 2014 -0300
| | summary: Amet
| |
o | changeset: 268:01563b587c71
|/ user: xxxxxxxxx <xxxxx#zzzz.com>
| date: Tue May 06 17:47:32 2014 -0300
| summary: Consectur
|
o changeset: 267:602390d3eeb1
| user: yyyyyyyy <yyyyyyy#zzzzz.com>
| date: Fri May 02 14:24:29 2014 -0300
| summary: Abc
|
You can't. tip is simply "most recent commit". If you want the branch with the head at 272, you should give it another bookmark. It's definitely advisable to just ignore tip completely.
As #moswald said, it is not possible to change the tip in itself, as it is pointing to the tipmost changeset of your repository. As such, tip is not necessarily a good reference to use.
However, there is something that you can do, to change the tip here. This has no real value, but I explain it for theoretical reasons only. The solution to your problem, without doing any other commit on the other branch, is to push (for backup, e.g. you need a cloned or main repo), strip and re-pull the commit you want as tip.
hg push -r 70f0a3f3b74a
hg strip -r 70f0a3f3b74a
hg pull -r 70f0a3f3b74a
Then, simply update again to the same changeset, if needed, and you can either do
hg update -r 70f0a3f3b74a
Or...
hg update -r tip
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.
In a repo I'm working, we created a named branch at some time to try a different approach in a certain issue. We continued to work in the default branch as well.
Now that the named branch has matured so to speak, we would like to make that branch, the default one, and give a different name for the (old) default branch.
Is something like that possible?
I've found this question, Mercurial: Can I rename a branch? and I can rename the default branch successfully, but afterwards when I try to rename the named branch to default, it fails with an error
abort: a branch of the same name already exists
Yes, you can.
You need to close all the branches and then give them the required name
PS: seems like you just needed to add -f flag to the branch command
Sample scenario
hg init
echo "123" > file
hg addremove
hg commit -m "init default"
hg branch new
echo "new" >> file
hg commit -m "init new"
hg up default
echo "default" >> file
hg commit -m "default 2nd"
hg commit --close-branch -m "close default"
hg up new
hg commit --close-branch -m "close new"
hg branches # none
hg log # see where to update if haven't saved id/hash somewhere
hg up 3 # this changset was the "close default" one
hg branch new -f
hg commit -m "new new"
hg up 4 # the changeset we closed "new" at
hg branch default -f
hg commit -m "new default"
The result:
>hg log -G
o changeset: 6:af87a53292cf
| tag: tip
| parent: 4:700a73ac7cad
| user: Ivan Kurnosov
| date: Tue Jun 05 17:22:27 2012 +1200
| summary: new default
|
| # changeset: 5:4ee990605ba1
| | branch: new
| | parent: 3:6ebccfc3e630
| | user: "Ivan Kurnosov
| | date: Tue Jun 05 17:18:01 2012 +1200
| | summary: new new
| |
o | changeset: 4:700a73ac7cad
| | branch: new
| | parent: 1:4a149d3fe86e
| | user: "Ivan Kurnosov
| | date: Tue Jun 05 17:15:18 2012 +1200
| | summary: close new
| |
| o changeset: 3:6ebccfc3e630
| | user: "Ivan Kurnosov
| | date: Tue Jun 05 17:14:49 2012 +1200
| | summary: close default
| |
| o changeset: 2:92669a82423b
| | parent: 0:05657f61324b
| | user: "Ivan Kurnosov
| | date: Tue Jun 05 17:13:07 2012 +1200
| | summary: default 2nd
| |
o | changeset: 1:4a149d3fe86e
|/ branch: new
| user: "Ivan Kurnosov
| date: Tue Jun 05 17:12:30 2012 +1200
| summary: init new
|
o changeset: 0:05657f61324b
user: "Ivan Kurnosov
date: Tue Jun 05 17:11:51 2012 +1200
summary: init default
We use hg to control the sources for a large project. Whenever we do a release, we tag the version in hg.
Now say I take a specific revision (where I've fixed a bug for example). I want to know which releases contain this fix, i.e. which tags "cover" this revision.
How do I find this? In hg tags seem to refer only to the tagged changeset. I remember that in ClearCase every ancestor of the tagged revision would be marked too, is there a way to see this information in hg?
Thanks!
Revsets without any additional extensions can give you something. like
hg log -r "id(hash):tip and tag()" or shorter and nicer (maybe) version hg log -r "descendants(hash) and tag()"
Just and example of shortened revset from my repo with merges after revision in question
>hg glog -r "descendants(c9e3b41ec78f)"
# changeset: 65:f202d72d6397
| tag: tip
| parent: 63:c778bae76563
| user: Alex Bream
| date: Wed Nov 09 21:42:50 2011 +0600
| summary: 2-9 яюыэюёЄ№■ фю 2769
|
| o changeset: 64:625d08492555
| | branch: Cleanup
| | parent: 62:eed6619dadb8
| | user: Alex Bream
| | date: Wed Nov 09 21:38:44 2011 +0600
| | summary: ╟рўшёЄър яю 1-1 155
| |
o | changeset: 63:c778bae76563
|\| parent: 61:e7ae9e5f725a
| | parent: 62:eed6619dadb8
| | user: Alex Bream
| | date: Wed Nov 09 21:33:22 2011 +0600
| | summary: Merge with Cleanup
| |
| o changeset: 62:eed6619dadb8
| | branch: Cleanup
| | parent: 59:c9e3b41ec78f
| | user: Alex Bream
| | date: Thu Mar 03 19:19:34 2011 +0500
| | summary: ╟рўшёЄър яю 1-1 131
| |
o | changeset: 61:e7ae9e5f725a
| | user: Alex Bream
| | date: Thu Mar 03 05:40:34 2011 +0500
| | summary: 2-9 яю 2745
| |
o | changeset: 60:1393fe759096
|\| parent: 57:a38258cac9b8
| | parent: 59:c9e3b41ec78f
| | user: Alexander
| | date: Thu Mar 03 04:59:22 2011 +0500
| | summary: Merge ё ўшёЄшыъющ
| |
| o changeset: 59:c9e3b41ec78f
| | branch: Cleanup
| | user: Alexander
| | date: Thu Mar 03 04:54:11 2011 +0500
| | summary: ╟рўшёЄър яЁюыюу яюыэюёЄ№■
| |
And comparing output of two forms of revsets (same output anyway)
descendants()
>hg log -r "descendants(c9e3b41ec78f)" --template "{rev}:{node|short}\n"
59:c9e3b41ec78f
60:1393fe759096
61:e7ae9e5f725a
62:eed6619dadb8
63:c778bae76563
64:625d08492555
65:f202d72d6397
Direct range definition
>hg log -r "id(c9e3b41ec78f):tip" --template "{rev}:{node|short}\n"
59:c9e3b41ec78f
60:1393fe759096
61:e7ae9e5f725a
62:eed6619dadb8
63:c778bae76563
64:625d08492555
65:f202d72d6397
This gives the output similar to hg tags:
hg log -r "reverse(descendants(8bb6)) and tag()" --template "{tags}\t{rev}:{node|short}\n"
You can use the Nearest extension to find the nearest forward tag to your revision. Then, depending on your workflow, you should be able to easily deduce which other tag also contains your change.
You can also use the following to print the latest backward tag from the current revision :
hg log -l 1 --template "{latesttag}\n"
And then also deduce the "covering" tag.
I've just realize that I don't understand how to work with such situation:
I have trunk and make a new branch. I'm working with this branch but Also I have to change something in trunk. I switch to trunk, make changes, commit, push. Everything's OK but if I want to want to add all changes from trunk to my branch and I need trunk and branch to exist separately. Because I don't finish with branch but at that time I want fresh changes from branch to be integrated in my branch. If I make merge than I will have just one trunk or just one branch.
And in real life I will have 10-30 different branches which should be synchronized with trunk. And every branch can be created in different time with different changeset.
Is there easy way?
Er, no, merge is the way. You merge changes from the trunk into your branch, and then you can carry on on the trunk with no problem (update to last trunk changeset, and then commit like you'd always do) — merging does not destroy/close branches. And merge points in the history are the indicators of when and what did you move between development lines.
Just to add note and example
hg glog is your best friend in order to see repository tree and find target for hg up
hg glog (part of) from my repo with 2 active parallel branches and merge-branching in process
o changeset: 62:eed6619dadb8
| branch: Cleanup
| tag: tip
| parent: 59:c9e3b41ec78f
| user: Alex Bream <...>
| date: Thu Mar 03 19:19:34 2011 +0500
| summary: Зачистка по 1-1 131
|
| # changeset: 61:e7ae9e5f725a
| | user: Alex Bream <...>
| | date: Thu Mar 03 05:40:34 2011 +0500
| | summary: 2-9 по 2745
| |
| o changeset: 60:1393fe759096
|/| parent: 57:a38258cac9b8
| | parent: 59:c9e3b41ec78f
| | user: Alexander <...>
| | date: Thu Mar 03 04:59:22 2011 +0500
| | summary: Merge с чистилкой
| |
o | changeset: 59:c9e3b41ec78f
| | branch: Cleanup
| | user: Alexander <...>
| | date: Thu Mar 03 04:54:11 2011 +0500
| | summary: Зачистка пролог полностью
| |
o | changeset: 58:f7f288c9e72b
| | branch: Cleanup
| | parent: 55:acadd1e83fba
| | user: Alexander <...>
| | date: Thu Mar 03 04:50:11 2011 +0500
| | summary: Зачистка по 47
| |
| o changeset: 57:a38258cac9b8
| | user: Alexander <...>
| | date: Thu Mar 03 04:37:49 2011 +0500
| | summary: 2-9 по 2737
| |
| o changeset: 56:c838826fadb8
|/ user: Alexander <...>
| date: Thu Mar 03 04:27:40 2011 +0500
| summary: 2-9 по 2692
|
o changeset: 55:acadd1e83fba
| user: Alex Bream <...>
| date: Wed Mar 02 00:39:27 2011 +0500
| summary: 2-9 по 2640
|
Same part on screenshot from TortoiseHG