I converted a Subversion repository to Mercurial a few months back and I wound up leaving two meaningless gaps in my revision history. I'm trying to figure out if I can just splice over the gaps, but I haven't been able to get the tools to do precisely what I want.
I had reorganized the Subversion repo twice in the early days of the project: first to convert a single project root to trunk/branches/tags layout, and then to add a second related project in a second root folder with it's own trunk/branches/tags.
By the time I decided to switch to Mercurial there had been no significant development activity outside of the trunk of the first, original project. I was able to use the Mercurial conversion utilities and path mapping to reassemble a single sensible trunk in the new Mercurial repository, or so I thought.
Now I realize that I have two extra heads, each corresponding to where the change history essentially starts over:
r0 ... r16 | (r17) r18 ... r61 | (r62) r63 ... tip
The results of the two revisions after the breaks, r17 and r62, are identical in content to the corresponding revision before the breaks -- they consist entirely of file add operations with exactly the same contents as the previous revisions. Meaningful changes only start at the next revisions (r18 and r63 respectively).
I've messed with the Mercurial Transplant extension in an attempt to splice over r17 and r62, but it winds up concatenating the spliced changesets all the way at the tip of the default branch (r405 at this point).
These extra heads are not really hurting my development activities, so I've let it go for a while. What's pushing me to resolve this is that MercurialEclipse complains about these extra heads every time I pull from my remote repository.
Can anyone offer any advice on how to approach this? Am I just getting the command flags wrong, or am I using the wrong tool? Should I be using the Rebase extension instead? What about some sort of dump-edit dumpfile-reload process that we all used to do with Subversion?
While I've published the project to my development server, there are only a couple of clones out there, so destroying those copies and recloning shouldn't be a big deal.
The extension commands rebase and collapse should do the trick. Consider the following small repository as an example:
$ hg glog -p
o changeset: 3:bc701d12d956
| tag: tip
| summary: hack
|
| diff --git a/file b/file
| --- a/file
| +++ b/file
| ## -1,1 +1,1 ##
| -hello world
| +hello big world
|
o changeset: 2:2bb8c95d978e
parent: -1:000000000000
summary: history breaking svn reorganization
diff --git a/file b/file
new file mode 100644
--- /dev/null
+++ b/file
## -0,0 +1,1 ##
+hello world
# changeset: 1:b578b2ec776b
| summary: hack
|
| diff --git a/file b/file
| --- a/file
| +++ b/file
| ## -1,1 +1,1 ##
| -hello
| +hello world
|
o changeset: 0:c3d20f0b7072
summary: initial
diff --git a/file b/file
new file mode 100644
--- /dev/null
+++ b/file
## -0,0 +1,1 ##
+hello
It basically resembles your situation, i.e. there are two unrelated lines of history, where the first revision of the second line (r2) is a plain add of everything present at the last revision of the first line (r1).
You can put the second line onto the first one with rebase:
$ hg rebase -s 2 -d 1
$ hg glog
# changeset: 3:020d1b20caa8
| summary: hack
|
o changeset: 2:2a44eb4b74c3
| summary: history breaking svn reorganization (empty changeset now)
|
o changeset: 1:b578b2ec776b
| summary: hack
|
o changeset: 0:c3d20f0b7072
summary: initial
As you see, the two lines have been joined. Revision 2 now is an obsolete empty changeset. You can get rid of it by using the collapse command to combine revisions 1 and 2:
$ hg collapse -r 1:2
<edit commit message>
$ hg glog -p
# changeset: 2:d283fe96a5e6
| tag: tip
| summary: hack
|
| diff --git a/file b/file
| --- a/file
| +++ b/file
| ## -1,1 +1,1 ##
| -hello world
| +hello big world
|
o changeset: 1:c486d8191bf0
| summary: hack
|
| diff --git a/file b/file
| --- a/file
| +++ b/file
| ## -1,1 +1,1 ##
| -hello
| +hello world
|
o changeset: 0:c3d20f0b7072
summary: initial
diff --git a/file b/file
new file mode 100644
--- /dev/null
+++ b/file
## -0,0 +1,1 ##
+hello
Now the unrelated lines of history are joined in a meaningful way.
Related
I have tried this:
$ hg bundle -b my-branch ../my-branch-bundle.hg
searching for changes
no changes found
Then this:
$ hg bundle --all --branch my-branch ../my-branch-bundle.hg
7191 changesets found
... but my branch has only 3 commits? Then also this:
$ hg bundle --base null --branch my-branch ../my-branch-bundle.hg
7191 changesets found
How to hg bundle only the changes for a given branch?!
hg bundle bundles each specified revision (-r) and assumes the destination repository has all the revisions (and their ancestors) specified by the --base option.
So one way to get only a small branch of 3 changesets is to specify with --base the first changeset branched from, and specify of the first changeset of the branch and its descendants.
For example, given:
o changeset: 5:f429f686e698
| branch: test
|
o changeset: 4:e02923c7302b
| branch: test
|
o changeset: 3:076f442d4d3b
| branch: test
|
| # changeset: 2:dab4279642cb
|/
o changeset: 1:233d09b80d63
|
o changeset: 0:6818527e85ac
Use:
hg bundle --base 1 --rev heads(descendants(3))
In HG, is there any command such that i can get the file content of the file from another branch without switching/checkout to the particular branch?
Similar to the other answer, you can use the cat command but in a slightly different way:
hg cat --rev=11204 path/to/file
This will pick the file from revision #11204 which can be any branch.
You may want to add the --output switch lets you use whatever filename and/or location you want:
hg cat --output=C:/new/path/to/file/filename#11204.ext --rev=11204 path/to/file
If you are using TortoiseHG, you can use the "save at revision" command to do this.
Steps:
Run Tortoise Workbench
Find the changeset in history which has the file revision you want (could be in any branch)
Say its changeset #abcd1234
Right click on the specific file in the file list for that changeset
Select "Save at revision..." and tell it where to put the file.
The file would typically be named filename#abcd1234.ext so that you don't mix it up with the current version.
Use the cat subcommand with the revision number of the commit you're looking for.
Here's an example. I create two branches with the contents of the file file indicating which branch it's on. Then I use cat to examine the contents on both branches
% hg init foo
% cd foo
% echo "default branch" > file
% hg add file
% hg ci -m 'default' file
% echo "default 2nd rev" > file
% hg ci -m 'default 2nd rev' file
% hg glog
# changeset: 1:305b2b5ccbd9
| tag: tip
| user: dj
| date: Mon Sep 17 14:11:20 2018 -0400
| summary: default 2nd rev
|
o changeset: 0:6d22c68d8abc
user: dj
date: Mon Sep 17 14:10:56 2018 -0400
summary: default
% hg co -r 0
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
% echo "new branch" > file
% hg branch 'new branch'
marked working directory as branch new branch
(branches are permanent and global, did you want a bookmark?)
% hg ci -m 'new branch'
% hg glog
# changeset: 2:4c8d2181526c
| branch: new branch
| tag: tip
| parent: 0:6d22c68d8abc
| user: dj
| date: Mon Sep 17 14:12:30 2018 -0400
| summary: new branch
|
| o changeset: 1:305b2b5ccbd9
|/ user: dj
| date: Mon Sep 17 14:11:20 2018 -0400
| summary: default 2nd rev
|
o changeset: 0:6d22c68d8abc
user: dj
date: Mon Sep 17 14:10:56 2018 -0400
summary: default
% hg branches
new branch 2:4c8d2181526c
default 1:305b2b5ccbd9
% hg cat -r 2 file
new branch
% hg cat -r 1 file
default 2nd rev
I'm looking to view all the changesets that have been tested by an hg bisect.
I want them in a simple, easy to read format like:
2391928719e - good
7321374343e - good
3232738237e - bad
4873487473e - bad
39732197132 - bad
39732197132 - bad
I know about hg log -r bisect(range), but I don't think that gives me the status?
bisect(range) just gives you the revisions that participated, yes. Your problem is with the output, not with the revset, so look at hg help template instead to get output options.
There you'll find:
$ hg help template | grep ' bisect '
bisect String. The commit bisection status.
Use that in a -T template:
hg log -r 'bisect(range)' -T '{node|short} - {bisect}\n'
This then gives you your list of nodes participating, with their status; one of good, bad, untested, ignored or skipped.
There is even a built-in template for this, named bisect; this is just the default template with a bisect: {bisect} line added:
hg log -r 'bisect(range)' -T bisect
There's also a shortbisect filter; it'll return a single letter for a given bisection status rather than the full text. This is helpful in a -G graph, set the ui.graphnodetemplate option to {bisect|shortbisect} to have the node 'icon' be the status:
hg log -r 'bisect(range)' -G \
--config "ui.graphnodetemplate={bisect|shortbisect}"
-T compact
which produces something like
G 1011 2391928719e 2017-09-21 15:58 +0530 author
| first line of commit message
|
G 1010 7321374343e 2017-09-21 15:58 +0530 author
| first line of commit message
|
B 1009 3232738237e 2017-09-21 15:58 +0530 author
| first line of commit message
|
B 1008 4873487473e 2017-09-21 15:58 +0530 author
| first line of commit message
|
B 1007 39732197132 2017-09-21 15:58 +0530 author
| first line of commit message
|
B 1006 39732197132 2017-09-21 15:58 +0530 author
| first line of commit message
~
Let's say I have this:
hg init
touch a
hg add a
hg commit -m a
touch b
hg add b
hg commit -m b
hg up -r 0
touch c
hg add c
hg commit -m c
Now I will have multiple heads, because of the last commit. If, for example I want to keep the last head, the one created by commit c ( effectively discarding b, and all other commits made after the first ) , how could I do it? I played a little with mq's strip command, and I'm able to achieve what I want, but I'd like to know if there's another way.
Yes, there is another way. From your example above, the output of hg glog looks a bit like this:
# changeset: 2:925573c7103c
| tag: tip
| parent: 0:4fe26dfe856d
| user: Joel B Fant
| date: Thu Jul 28 23:20:45 2011 -0400
| summary: c
|
| o changeset: 1:9dc928176506
|/ user: Joel B Fant
| date: Thu Jul 28 23:20:24 2011 -0400
| summary: b
|
o changeset: 0:4fe26dfe856d
user: Joel B Fant
date: Thu Jul 28 23:20:12 2011 -0400
summary: a
If you clone test but specify a revision, it will only clone that revision and its ancestors. So if your repo's directory is TwoHeadsMightNotBeBetter, you can go to its parent directory and issue:
hg clone TwoHeadsMightNotBeBetter OneHeadIsFine -r 925573c7103c
I specified changeset id in that, but you could also use -r 2 instead, or even -r tip since it is currently the tip of that repo. Now when you go into the new clone and do hg glog, you have only one head:
# changeset: 1:925573c7103c
| tag: tip
| user: Joel B Fant
| date: Thu Jul 28 23:20:45 2011 -0400
| summary: c
|
o changeset: 0:4fe26dfe856d
user: Joel B Fant
date: Thu Jul 28 23:20:12 2011 -0400
summary: a
If you had 3 heads and wanted to keep 2, it would be a little different. You'd have to clone one of them with -r and the also specify -r on hg pull to pull specific branches.
You can also perform a dummy merge of the changeset containing b (changeset 1 in this case):
$ hg --config ui.merge=internal:fail merge 1
resolving manifests
getting b
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg revert --all --no-backup --rev .
removing b
$ hg status
R b
$ hg commit -m "Dummy merge -- eliminate b"
committed changeset 3:c163151f19df
$ ls
a c
Note that in this case you haven't rewritten any history or created any new repos -- particularly important if b had already been pushed to a centralized repo and pulled by others.
I have a number of changes that I committed to my local repository, but have not yet been pushed. Since on a feature is taking longer than expected, I want to swap these changes onto a named branch before I push. How can I do this?
As suggested by Mark, the MqExtension is one solution for you problem. IMHO a simpler workflow is to use the rebase extension. Suppose you have a history like this:
# changeset: 2:81b92083cb1d
| tag: tip
| summary: my new feature: edit file a
|
o changeset: 1:8bdc4508ac7b
| summary: my new feature: add file b
|
o changeset: 0:d554afd54164
summary: initial
This means, revision 0 is the base on which you started to work on your feature. Now you want to have revisions 1-2 on a named branch, let's say my-feature. Update to revision 0 and create that branch:
$ hg up 0
$ hg branch my-feature
$ hg ci -m "start new branch my-feature"
The history now looks like this:
# changeset: 3:b5939750b911
| branch: my-feature
| tag: tip
| parent: 0:d554afd54164
| summary: start new branch my-feature
|
| o changeset: 2:81b92083cb1d
| | summary: my new feature: edit file a
| |
| o changeset: 1:8bdc4508ac7b
|/ summary: my new feature: add file b
|
o changeset: 0:d554afd54164
summary: initial
Use the rebase command to move revisions 1-2 onto revision 3:
$ hg rebase -s 1 -d 3
This results in the following graph:
# changeset: 3:88a90f9bbde7
| branch: my-feature
| tag: tip
| summary: my new feature: edit file a
|
o changeset: 2:38f5adf2cf4b
| branch: my-feature
| summary: my new feature: add file b
|
o changeset: 1:b5939750b911
| branch: my-feature
| summary: start new branch my-feature
|
o changeset: 0:d554afd54164
summary: initial
That's it .. as mentioned in the comments to Mark's answer, moving around already pushed changesets generally is a bad idea, unless you work in a small team where you are able to communicate and enforce your history manipulation.
You can use the MqExtension. Let's say the changesets to move are revisions 1-3:
hg qimport -r 1:3 # convert revisions to patches
hg qpop -a # remove all them from history
hg branch new # start a new branch
hg qpush -a # push them all back into history
hg qfin -a # finalize the patches
I prefer the patch solution describe here by Mark Tolonen
What I have:
hg log -G
#default branch
# changeset: 3:cb292fcdbde1
|
o changeset: 2:e746dceba503
|
o changeset: 1:2d50c7ab6b8f
|
o changeset: 0:c22be856358b
What I want:
# changeset: 3:0e85ae268e35
| branch: feature/my_feature
|
o changeset: 2:1450cb9ec349
| branch: feature/my_feature
|
o changeset: 1:7b9836f25f28
| branch: feature/my_feature
|
/
|
o changeset: 0:c22be856358b
mercurials commands:
hg export -o feature.diff 1 2 3
hg update 0
hg branch feature/my_feature
hg import feature.diff
Here is the state of my local repository
# changeset: 6:0e85ae268e35
| branch: feature/my_feature
|
o changeset: 5:1450cb9ec349
| branch: feature/my_feature
|
o changeset: 4:7b9836f25f28
| branch: feature/my_feature
|
| o changeset: 3:cb292fcdbde1
| |
| o changeset: 2:e746dceba503
| |
| o changeset: 1:2d50c7ab6b8f
|/
|
o changeset: 0:c22be856358b
Now I need to delete the revisions 1 2 and 3 from my default branch.
You can do this with strip command from mq's extension.
hg strip removes the changeset and all its descendants from the repository.
Enable the extension by adding following lines to your configuration file (.hgrc or Mercurial.ini):
vim ~/.hgrc and add :
[extensions]
mq =
And now strip this repository on revision 1.
hg strip 1
and here we are
# changeset: 3:0e85ae268e35
| branch: feature/my_feature
|
o changeset: 2:1450cb9ec349
| branch: feature/my_feature
|
o changeset: 1:7b9836f25f28
| branch: feature/my_feature
|
o changeset: 0:c22be856358b
note: changesets are different but revisions are the same
For those inclined to use GUI
Go to Tortoise Hg -> File -> Settings then tick rebase .
Restart tortoise UI
Create new branch where you will be moving changes. Click on current branch name -> choose Open a new named branch -> choose branch name.
If changes you want to move have not been made public (e.g draft) go to 5. (If changes have already been published and you are not a senior dev you should talk to someone senior (get a scapegoat) as you might screw things up big time, I don't take any responsibility :) ).
Go to View -> Show Console (or Ctrl + L)
then write in console hg phase -f -d 2 - where 2 is lowest revision you will be moving to new branch.
Go to branch and revision (should be topmost revision if you are moving changes to new branch created in step 3.) Right Mouse -> Update
Go to branch and revsion you will be moving changes from Right Mouse -> Modify History -> Rebase
Click Rebase and pray there are no conflicts, merge if you must.
Push changes, at this point all revisions should still be draft.
Go to topmost revision in branch you were moving changes to Right Mouse -> Change Phase to -> Public.
Hope this saves you some time.