Xtroce
Xtroce

Reputation: 1824

moving files in several branches in mercurial

I'm trying to find out how to move several files in mercurial from one directory to another in all branches at once. The idea is that i have some files in a directory

a/some_file

which should be moved to

b/a/some_file

but do this in the branchstructure

 10   9
 |    |
 |    8
 |    |
 |____/
 7
 |
 ...

to keep in mind is that some of the files in node 9 already have changed but should also be moved upwards one directory. Also I would like to add some files at node 7 so that they exist in both branches. But the important thing is to move the files.

Upvotes: 0

Views: 122

Answers (1)

Giorgos Keramidas
Giorgos Keramidas

Reputation: 1848

Renames propagate across merges, so if you check out the files at changeset 7, rename them there and then merge the rename change to the rest of the branches, Mercurial should do the right thing.

See for example what happens in the following trace of commands. I start by creating a test repository:

saturn:/tmp$ hg init test
saturn:/tmp$ cd test

Then, I make sure that a file called 'foo.txt' exists at the toplevel directory on a branch called br.7:

saturn:/tmp/test$ echo foo > foo.txt
saturn:/tmp/test$ hg commit -Am 'add foo'
adding foo.txt
saturn:/tmp/test$ hg branch br.7
marked working directory as branch br.7
(branches are permanent and global, did you want a bookmark?)
saturn:/tmp/test$ hg commit -m 'br.7 opened'

Then I fork two other branches, br.8 and br.9 from the latest changeset of the `br.7' branch:

saturn:/tmp/test$ hg up -C br.7
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
saturn:/tmp/test$ hg branch br.8
marked working directory as branch br.8
(branches are permanent and global, did you want a bookmark?)

saturn:/tmp/test$ hg commit -m 'br.8 opened'
saturn:/tmp/test$ hg up -C br.7
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
saturn:/tmp/test$ hg branch br.9
marked working directory as branch br.9
(branches are permanent and global, did you want a bookmark?)
saturn:/tmp/test$ hg commit -m 'br.9 opened'

Now the changeset graph looks like this:

saturn:/tmp/test$ hg log --graph --style=compact
@  3[tip]:1   f3f155b61aa8   2013-01-09 23:48 +0100   gkeramidas
|    br.9 opened
|
| o  2   ad3b03105da7   2013-01-09 23:48 +0100   gkeramidas
|/     br.8 opened
|
o  1   9cfed898c77b   2013-01-09 23:48 +0100   gkeramidas
|    br.7 opened
|
o  0   9a6f15da68d7   2013-01-09 23:47 +0100   gkeramidas
     add foo

So if I try renaming the file in branch br.7 first and then merge the rename upwards, here's what happens:

saturn:/tmp/test$ hg up -C br.7
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
saturn:/tmp/test$ mkdir subdir
saturn:/tmp/test$ hg rename foo.txt subdir/foo.txt
saturn:/tmp/test$ hg commit -m 'Rename foo.txt'

saturn:/tmp/test$ hg branches
br.7                           4:d57b57b98f19
br.9                           3:f3f155b61aa8
br.8                           2:ad3b03105da7
default                        0:9a6f15da68d7 (inactive)

Then, finally, I merge the rename changeset from branch br.7 to the higher branches:

saturn:/tmp/test$ hg up -C br.8
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
saturn:/tmp/test$ hg merge br.7
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
(branch merge, don't forget to commit)

and the result of the merge looks like this in git-style diff output:

saturn:/tmp/test$ hg diff --git
diff --git a/foo.txt b/foo.txt
deleted file mode 100644
--- a/foo.txt
+++ /dev/null
@@ -1,1 +0,0 @@
-foo
diff --git a/subdir/foo.txt b/subdir/foo.txt
--- /dev/null
+++ b/subdir/foo.txt
@@ -0,0 +1,1 @@
+foo

If I commit this change, the history now looks like this:

saturn:/tmp/test$ hg log --graph --style=compact
@    5[tip]:2,4   22b095e35b43   2013-01-10 00:02 +0100   gkeramidas
|\     Merge rename of foo.txt
| |
| o  4:1   d57b57b98f19   2013-01-09 23:49 +0100   gkeramidas
| |    Rename foo.txt
| |
| | o  3:1   f3f155b61aa8   2013-01-09 23:48 +0100   gkeramidas
| |/     br.9 opened
| |
o |  2   ad3b03105da7   2013-01-09 23:48 +0100   gkeramidas
|/     br.8 opened
|
o  1   9cfed898c77b   2013-01-09 23:48 +0100   gkeramidas
|    br.7 opened
|
o  0   9a6f15da68d7   2013-01-09 23:47 +0100   gkeramidas
     add foo

Notice how the rename looks like a real actual 'merge' operation now, and see how log --copies can go back through the rename operation to the original change that added foo.txt in this output:

saturn:/tmp/test$ hg log --copies --style=compact foo.txt subdir/foo.txt
4:1   d57b57b98f19   2013-01-09 23:49 +0100   gkeramidas
  Rename foo.txt

0   9a6f15da68d7   2013-01-09 23:47 +0100   gkeramidas
  add foo

This way, you can have a single changeset (changeset d57b57b98f19 in this example) that does the rename operation at the oldest possible place, and you can merge this changeset to all upper branches too. You'd still have to do each branch separately, but I like the idea of being able to track all of: what was renamed, who did the rename, when it happened and when it was merged to a derivative branch.

Upvotes: 1

Related Questions