How to move some revisions from one branch to another? - mercurial

hg convert --branchmap allows moving all revisions in a branch to a different branch. In a branch with multiple heads (e.g. one path leads to a "closed branch") how do I move some of the revisions to a different branch while leaving others unchanged?

According to Pierre-Yves David
You should be able to achieve this using "histedit". Use the "edit" action on the first changesets and set up branch name before committing.
So for example, say we have:
# changeset: 3:acd042300874
| tag: tip
| user: user#name.com
| date: Tue Sep 27 11:22:33 2016 -0400
| summary: commit4
|
o changeset: 2:6cd4bf5a3e25
| parent: 0:7f1fbf9d8623
| user: user#name.com
| date: Tue Sep 27 11:22:33 2016 -0400
| summary: commit3
|
| o changeset: 1:5cf7adbb92ea
|/ user: user#name.com
| date: Tue Sep 27 11:22:32 2016 -0400
| summary: commit2
|
o changeset: 0:7f1fbf9d8623
user: user#name.com
date: Tue Sep 27 11:22:32 2016 -0400
summary: commit1
and we want to move revisions 2, 3 onto a different branch we would do the following:
hg update 3
hg histedit 2
Change both revisions from "pick" to "edit"
hg branch "new-branch"
hg commit -m "old commit message for rev2"
hg histedit --continue
hg commit -m "old commit message for rev3"
hg histedit --continue

Use a combination of branchmap and splicemap options to hg convert. Possibly in more than one step, depending on exactly what you need to do.

Related

Mercurial merging default into named branch

I have a pretty simple Mercurial repo that has one named branch in addition to the default branch.
Changes have been made and committed to the default branch and I want to merge those into my named branch. However, a hg merge default does not seem to be merging in all of the changes.
for example:
hg update working
99 files updated, 0 files merged, 0 files removed, 0 files unresolved
hg status -m --rev default:working
there are about 20 files with modifications
M ... some list of files...
hg merge default
merging path/to/a/file/foo.java
3 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
hg status -m --rev default:working
Now there are still file with modifications that I would have expected to get merged.
I can do an hg diff -r default and see that there are changes that are not getting merged.
This is what the repo looks like
# changeset: 4:d41da580b434
| branch: working
| tag: tip
| parent: 1:3ed1c8bf91cf
| user: bob costas
| date: Tue Mar 24 10:13:25 2015 -0500
| summary: pr-1243 and minor updates
|
| o changeset: 2:ea0c249218fa
| | parent: 0:385565af3c13
| | user: bob costas
| | date: Mon Mar 23 15:09:42 2015 -0500
| | summary: bunch of updated files and fixes
| |
o | changeset: 1:3ed1c8bf91cf
|/ branch: working
| user: bob costas
| date: Mon Mar 23 13:38:59 2015 -0500
| summary: pr-1231
|
o changeset: 0:385565af3c13
user: bob costas
date: Thu Mar 19 18:15:52 2015 -0500
summary: initial commit
You didn't commit your merge.. Mercurial told you :
hg merge default
merging path/to/a/file/foo.java 3 files updated, 1
files merged, 0 files removed, 0 files unresolved (branch merge,
don't forget to commit)
When you merge, all files stay modified in your sources, and you need to commit them
hg commit -m "merge with default"
Then your branch will appear merged in the log.

Mercurial usage to merge multiple heads

I'm mercurial newbie and want to learn how to use my repository. Can you tell me how to merge my friend's work with mine? Thanks
$ hg update tip
abort: crosses branches (merge branches or use --clean to discard changes)
$ hg heads
changeset: 265:ac5d3c3a03ac
tag: tip
user: roberto.cr
date: Thu Oct 06 07:32:15 2011 +0000
summary: fixing "redirects" links
changeset: 261:6acd1aaef950
user: niklasro
date: Thu Oct 06 07:53:19 2011 +0000
summary: auth backend + js
$ hg update
abort: crosses branches (merge branches or use --clean to discard changes)
Could I use hg resolve?
$ hg resolve
abort: no files or directories specified; use --all to remerge all file
$ hg glog | more
# changeset: 266:2bf5b62720fc
| tag: tip
| parent: 261:6acd1aaef950
| user: niklasro
| date: Thu Oct 06 12:48:20 2011 +0000
| summary: added
|
| o changeset: 265:ac5d3c3a03ac
| | user: roberto.cr
| | date: Thu Oct 06 07:32:15 2011 +0000
| | summary: fixing "redirects" links
| |
| o changeset: 264:2fd0bf24e90f
| | user: roberto.cr
| | date: Thu Oct 06 07:29:58 2011 +0000
| | summary: fixing "redirects" links
| |
| o changeset: 263:29a373aae81e
| | user: roberto.cr
| | date: Thu Oct 06 07:25:05 2011 +0000
| | summary: fixing "redirects" links
| |
| o changeset: 262:d75cd4d3e77a
| | parent: 260:dfb54b99f84d
| | user: roberto.cr
| | date: Thu Oct 06 07:24:55 2011 +0000
| | summary: fixing "redirects" links
| |
o | changeset: 261:6acd1aaef950
|/ user: niklasro
| date: Thu Oct 06 07:53:19 2011 +0000
| summary: auth backend + js
|
o changeset: 260:dfb54b99f84d
| user: niklasro
| date: Wed Oct 05 05:34:37 2011 +0000
| summary: FB buggfix example.html
|
o changeset: 259:92fb6b1bc492
| user: niklasro
| date: Thu Sep 29 16:42:33 2011 +0000
| summary: changes
The solution was hg revert -a and it looks like a success now
$ hg glog | more
# changeset: 267:3b2bb6de33eb
|\ tag: tip
| | parent: 266:2bf5b62720fc
| | parent: 265:ac5d3c3a03ac
| | user: niklasro
| | date: Thu Oct 06 16:06:21 2011 +0000
| | summary: merge
| |
| o changeset: 266:2bf5b62720fc
| | parent: 261:6acd1aaef950
| | user: niklasro
| | date: Thu Oct 06 12:48:20 2011 +0000
| | summary: added
| |
o | changeset: 265:ac5d3c3a03ac
| | user: roberto.cr
| | date: Thu Oct 06 07:32:15 2011 +0000
| | summary: fixing "redirects" links
| |
o | changeset: 264:2fd0bf24e90f
| | user: roberto.cr
| | date: Thu Oct 06 07:29:58 2011 +0000
| | summary: fixing "redirects" links
| |
o | changeset: 263:29a373aae81e
| | user: roberto.cr
| | date: Thu Oct 06 07:25:05 2011 +0000
| | summary: fixing "redirects" links
| |
o | changeset: 262:d75cd4d3e77a
| | parent: 260:dfb54b99f84d
| | user: roberto.cr
| | date: Thu Oct 06 07:24:55 2011 +0000
| | summary: fixing "redirects" links
| |
| o changeset: 261:6acd1aaef950
|/ user: niklasro
| date: Thu Oct 06 07:53:19 2011 +0000
| summary: auth backend + js
|
o changeset: 260:dfb54b99f84d
| user: niklasro
| date: Wed Oct 05 05:34:37 2011 +0000
| summary: FB buggfix example.html
|
o changeset: 259:92fb6b1bc492
| user: niklasro
| date: Thu Sep 29 16:42:33 2011 +0000
| summary: changes
The basic problem here is that your working directory is not clean. Mercurial prevents people from accidentally jumping between branches with uncommitted changes as this is generally a bad idea.
Let's start with that first command:
$ hg update tip
abort: crosses branches (merge branches or use --clean to discard changes)
This is telling you two important things:
you're trying to cross branches
you have uncommitted changes
And that you have two options:
merge
use hg update --clean to lose your changes
So what are your changes? The first step is to run 'hg status'. As you say 'hg status outputs many files prepended by 1 or ?'. Well those '1s' are actually '!' indicating deleted/missing files (get a better font!). You should doublecheck against summary, which will give you output like this:
parent: 15200:fa6f93befffa
patch: use more precise pattern for diff header color styling (issue3034)
branch: default
commit: 1 deleted, 1 unknown (clean) <- your changes
update: (current)
If you try to merge at this point, you'll get a message like:
$ hg merge stable
abort: outstanding uncommitted changes (use 'hg status' to list changes)
If you have changes other than missing files, you'll want to consider committing them.
If these missing files are your only changes, it's probably ok to discard them:
hg revert -a
After you've done that, you're in a state where Mercurial will let you update or merge without complaining.
Finally, you say "hg status output many files from other projects since it starts at .. The file I added is the only file that should get added.". This is a basic misunderstanding of how Mercurial works. Unlike CVS or SVN, there is only one project as far as Mercurial is concerned and actions (commit/update/merge/status) work on the entire project tree at once. Subdirectories are not independent projects with separate histories.
What about merging these two heads?
hg merge
Since this was discussed in greater depth on the mercurial mailing list, it appears that the problem was that, as mpm suggested, the working directory wasn't clean.
To summarise that thread, before version 1.9m Mercurial would say nothing changed to an hg ci if files had just been deleted.
At 1.9 this was changed to say nothing changed (1 missing files, see 'hg status') to make it more explicit that while no filed had changed, there were still deletions and you need to tell hg what you want to do about them. Either use hg revert -a to discard the changes, or hg addremove plus hg commit to tell hg about the changes and commit them.
Also, as Matt Mackall says:
It might help to ask status to show only deleted files:
$ hg st -d
! setup.py

Finding a repository LOC's added in a specific commit

Is it possible to find a repository's total lines of code added in a specific commit?
The churn extension does what I need:
hg churn --rev 100
See also the --stat flag to hg log in newer versions of Mercurial. That gives you "diffstat" output:
% hg log -l 3 --stat
changeset: 304:eb7e19e5021c
tag: tip
user: Martin Geisler
date: Wed Mar 30 12:26:41 2011 +0200
summary: po-da: translated about
po/da.po | 26 ++++++++++++++++++++++----
1 files changed, 22 insertions(+), 4 deletions(-)
changeset: 303:0104b63e904b
user: Martin Geisler
date: Wed Mar 30 00:03:47 2011 +0200
summary: po-cs: remove unknown (illegal) escape sequence
po/cs.po | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
changeset: 302:3b23518c9723
user: Martin Geisler
date: Wed Mar 30 00:03:23 2011 +0200
summary: po-cs: remove extra newline
po/cs.po | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

Help with mercurial repo problem

I have a repo in a condition I don't understand. 2 weeks ago, I tagged a release to mark a particular point I may have needed to go back to. Later, I decided to branch, and have also been pulling in changes from another repo (the repo that I originally cloned).
The original rev that is of interest is 52:
changeset: 52:5044a88ba2a9
date: Mon Jan 10 18:09:30 2011 -0500
A few commits later, I branched into "MultiPartition" (I should have done this immediately, but I didn't anticipate needing it).
After some more work, I pull changes from the sister repo (all the changes do not conflict with my work in the branch, so it's safe).
Here's what I see now:
$ hg branches
MultiPartition 75:9fd803c56505
default 72:3939850a77e2 (inactive)
Where I'm working in MultiPartition, and default is the tip from the sister repo.
If I look at the heads:
$ hg heads
changeset: 75:9fd803c56505
branch: MultiPartition
tag: tip
date: Tue Jan 18 18:32:38 2011 -0500
changeset: 72:3939850a77e2
parent: 69:997a5b43216d
date: Tue Jan 18 13:26:48 2011 -0500
changeset: 54:4ad1d36a79aa
date: Thu Jan 13 19:14:57 2011 -0500
there's rev 54 hanging out there, which I didn't (knowingly) mean to leave behind.
Here's where it gets strange: The changeset 52 isn't in my current MultiPartition tip (though it was actually in the source on my disk, as I expected). I've attached a graphlog of the changesets at the bottom.
If I use the hgcontains extension, I see:
$ hg headscontaining 52
changeset: 75:9fd803c56505
branch: MultiPartition
tag: tip
date: Tue Jan 18 18:32:38 2011 -0500
which tells me that the contents of rev 52 (which has new files I want in the current branch) should be in the tip of this branch. However, an hg update -C MultiPartition removes the new files from the directory I want them in.
If I use hgtk log and filter by the directory of interest, I see the 52 changeset which adds the files, but no newer changesets have any files removed from this directory.
The only thing that makes me wonder is this: Changeset 71 was the merge from the original repo. In that repo, those new files don't exist. The log for that changset is:
| o changeset: 71:ba4c67a24185
|/| branch: MultiPartition
| | parent: 70:2dcbf69c325d
| | parent: 69:997a5b43216d
| | date: Mon Jan 17 17:55:10 2011 -0500
Here's my core question:
If parent 70: has what I expected, but parent 69: didn't, how is that resolved?
How can I check for other omissions? Is there a way to see this sort of behavior?
I want to not have multiple heads, but I can't seem to "merge" them. Technically, they are already merged (I think). How should I clean this up?
Sorry if this is complex, but I don't know how else to ask the question except for giving a ton of info.
Full graphlog:
o changeset: 75:9fd803c56505
| branch: MultiPartition
| tag: tip
| date: Tue Jan 18 18:32:38 2011 -0500
|
o changeset: 74:be7df4e2579c
|\ branch: MultiPartition
| | parent: 73:3e7ac80ab37a
| | parent: 72:3939850a77e2
| | date: Tue Jan 18 18:31:24 2011 -0500
| |
| o changeset: 73:3e7ac80ab37a
| | branch: MultiPartition
| | parent: 71:ba4c67a24185
| | date: Tue Jan 18 18:28:51 2011 -0500
| |
o | changeset: 72:3939850a77e2
| | parent: 69:997a5b43216d
| | date: Tue Jan 18 13:26:48 2011 -0500
| |
| o changeset: 71:ba4c67a24185
|/| branch: MultiPartition
| | parent: 70:2dcbf69c325d
| | parent: 69:997a5b43216d
| | date: Mon Jan 17 17:55:10 2011 -0500
| |
| o changeset: 70:2dcbf69c325d
| | branch: MultiPartition
| | parent: 66:79272b7e7c01
| | date: Mon Jan 17 17:42:04 2011 -0500
| |
o | changeset: 69:997a5b43216d
| | date: Mon Jan 17 12:00:09 2011 -0500
| |
o | changeset: 68:b39f8a7af0c5
| | date: Sun Jan 16 20:23:43 2011 -0500
| |
o | changeset: 67:63d3b40427e0
| | parent: 58:29029a74e351
| | date: Sun Jan 16 18:07:49 2011 -0500
| |
| o changeset: 66:79272b7e7c01
| | branch: MultiPartition
| | date: Mon Jan 17 09:43:32 2011 -0500
| |
| o changeset: 65:b33eb978d647
| | branch: MultiPartition
| | date: Mon Jan 17 09:39:54 2011 -0500
| |
| o changeset: 64:1fdafb6d0e84
| | branch: MultiPartition
| | date: Sun Jan 16 17:48:09 2011 -0500
| |
| o changeset: 63:74942ab5113d
| | branch: MultiPartition
| | date: Sun Jan 16 17:46:15 2011 -0500
| |
| o changeset: 62:2cd5a6d9d120
| | branch: MultiPartition
| | date: Sun Jan 16 01:55:23 2011 -0500
| |
| o changeset: 61:acc73e7a35fc
|/| branch: MultiPartition
| | parent: 60:c10e217081f0
| | parent: 58:29029a74e351
| | date: Sun Jan 16 01:53:01 2011 -0500
| |
| o changeset: 60:c10e217081f0
| | branch: MultiPartition
| | date: Sun Jan 16 01:45:16 2011 -0500
| |
| o changeset: 59:2709b82b3ac0
| | branch: MultiPartition
| | parent: 54:4ad1d36a79aa
| | date: Sun Jan 16 01:42:34 2011 -0500
| |
o | changeset: 58:29029a74e351
| | date: Sun Jan 16 01:36:44 2011 -0500
| |
o | changeset: 57:48840b75e37b
| | date: Fri Jan 14 11:04:06 2011 -0500
| |
o | changeset: 56:dab5f0d40be9
| | date: Thu Jan 13 15:51:11 2011 -0500
| |
o | changeset: 55:214ac45834fd
| | parent: 51:7d0a1da31199
| | date: Wed Jan 12 16:49:00 2011 -0500
| |
| # changeset: 54:4ad1d36a79aa
| | date: Thu Jan 13 19:14:57 2011 -0500
| |
| o changeset: 53:8f06d69177d6
| | date: Thu Jan 13 14:02:42 2011 -0500
| |
| o changeset: 52:5044a88ba2a9
| date: Mon Jan 10 18:09:30 2011 -0500
|
o
You actually still have two heads on the default branch, and one head on the MultiPartition branch, as hg heads has shown you. Use hg heads -t to see actual heads, regardless of branch. It looks like you use the graphlog extension, so use hg glog -r "branch(default)" to visualize your default branch.
As for your questions:
If parent 70: has what I expected, but parent 69: didn't, how is that resolved?
You can hg export -r 52 >52.patch then hg import 52.patch at the tip. This will reapply the changes. One of your merges must have dropped the content.
How can I check for other omissions? Is there a way to see this sort of behavior?
Not really. As far as Mercurial is concerned 52 is an ancestor of your tip. If the changes were dropped in a later changeset Mercurial doesn't really know. You can hg diff two different changesets and track down where it got removed (probably in the merge).
I want to not have multiple heads, but I can't seem to "merge" them. Technically, they are already merged (I think). How should I clean this up?
default is typically where you want all your development to end up. You can merge the two default heads, then hg ci --closebranch on MultiPartition and merge it into default.
1: If parent 70: has what I expected, but parent 69: didn't, how is that resolved?
I guess the files got removed in either the 61 or 71 merge. You can check this in hgtk with the "diff to second parent" option.
3: I want to not have multiple heads, but I can't seem to "merge" them. Technically, they are already merged (I think). How should I clean this up?
On your default branch are two anonymous heads (54 and 72, where 72 is the tip of default), and they will stay open as long as the MultiPartition branch is not merged back into default. Depite being later merged in the MultiPartition branch, they are still heads of the default branch, because mercurial does not consider a follow-up branch as a new head of a branch. The reason for this treatment is that you typically want the latest revision the a branch when you hg update branch.
You can get rid of the two default heads when you merge MultiPartition back into default. When you are done with MultiPartition you can also close this branch with hg ci --close-branch (technically you cant remove the MultiPartition head, but when it is closed hg heads wont consider it as active head).

Mercurial: How to make HG LOG to show trivial parent?

According to HG manual:
By default this command prints
revision number and changeset id,
tags, non-trivial parents, user, date
and time, and a summary for each
commit. When the -v/--verbose switch
is used, the list of changed files and
full commit message are shown.
I have tried hg log -v but still it does not show the trivial parents.
You can use the --debug option.
$ hg log --template '{parents}\n' --debug
12:49f2f93d2efdd41c9ffb9dccf4d451e2d8bfbc5f -1:0000000000000000000000000000000000000000
7:012b1bb5d99549a5a7c1a280755fa6336c0b472a -1:0000000000000000000000000000000000000000
10:d6dc52582cfaa0e8be17a5b9da61b55692353afc 11:8ee9fa792548fc30669a34cf39fcc7185aabaa19
8:d589ca45072469148f833f38918861e8de406e64 -1:0000000000000000000000000000000000000000
You can see them visually in 'hg log -G' once you've turned on the Graphlog Extension.
In this context "trivial" just means "is the current revision number minus one", so in a situation like this:
o changeset: 1440:fe26f69d4b84
| user: dan#scofield.bx.psu.edu
| date: Fri Jul 18 12:11:58 2008 -0400
| summary: Typo in last commit.
|
o changeset: 1439:74cbef36b62f
| user: dan#scofield.bx.psu.edu
| date: Fri Jul 18 12:10:23 2008 -0400
| summary: Fix bug in JobWrapper.get_input_fnames(), used by pbs runner, when an input dataset was optional and left empty.
|
o changeset: 1438:1e111ebb2664
| user: James Taylor <james#jamestaylor.org>
| date: Thu Jul 17 22:14:40 2008 -0400
| summary: Workflows (owned and shared) can now be added to the tool menu.
|
o changeset: 1437:4a4de494fbf6
|\ parent: 1436:37a7f508eb30
| | parent: 1431:8b83b7250224
| | user: James Taylor <james#jamestaylor.org>
| | date: Thu Jul 17 20:42:00 2008 -0400
| | summary: Merge.
| |
| o changeset: 1436:37a7f508eb30
| | user: James Taylor <james#jamestaylor.org>
| | date: Thu Jul 17 20:40:20 2008 -0400
| | summary: Allow loading a specific controller/action in the root middle frame, and use
| |
| o changeset: 1435:96e1cda02414
| | user: James Taylor <james#jamestaylor.org>
| | date: Thu Jul 17 20:16:13 2008 -0400
| | summary: Fix for scroll panel when dropping while still overlapping the edge.
| |
A parent list is only shown for 1437 because for the rest have a single parent that is revision number minus one.
The template keyword parents is empty when the only parent is the next node
hg log --template "{parents}\n" -l 20
with this simple patch to mercurial sources you'll get all parents in the log:
file cmdutil.py: (line 990 in hg 3.1.2)
def _meaningful_parentrevs(self, log, rev):
"""Return list of meaningful (or all if debug) parentrevs for rev.
For merges (two non-nullrev revisions) both parents are meaningful.
Otherwise the first parent revision is considered meaningful if it
is not the preceding revision.
"""
parents = log.parentrevs(rev)
return parents #<=================add this line
if not self.ui.debugflag and parents[1] == nullrev:
if parents[0] >= rev - 1:
parents = []
else:
parents = [parents[0]]
return parents
In mercurial 4.0 find in the file scmutil.py:
def meaningfulparents(repo, ctx):
"""Return list of meaningful (or all if debug) parentrevs for rev.
For merges (two non-nullrev revisions) both parents are meaningful.
Otherwise the first parent revision is considered meaningful if it
is not the preceding revision.
"""
parents = ctx.parents()
return parents #<===========================add this line
if len(parents) > 1:
return parents
if repo.ui.debugflag:
return [parents[0], repo['null']]
if parents[0].rev() >= intrev(ctx.rev()) - 1:
return []
return parents
you'll get something like:
$ hg log
changeset: 62355:2722bdc1f0fc
branch: ALL-3158-fortran-memkind
tag: tip
parent: 62354:82da46786838
parent: -1:000000000000
user: Marcos Mayorga <mm#mm-studios.com>
date: Mon Jan 30 09:12:13 2017 +0000
summary: memkind smoke tests for FORTRAN
changeset: 62354:82da46786838
branch: ALL-3158-fortran-memkind
parent: 62194:c98a4c8295ab
parent: -1:000000000000
user: Marcos Mayorga <mm#mm-studios.com>
date: Fri Jan 27 14:38:53 2017 +0000
summary: create branch
...