Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fixing renames in a Mercurial repository after committing

Many files in our Mercurial repository were moved in a single commit, but these files were not marked as renamed. To make matters worse, some of the files were also modified in the same commit.

How can I backout the changeset and detect renames properly, while keeping the changes and the file moves?

like image 486
Petrus Theron Avatar asked Jul 30 '13 11:07

Petrus Theron


1 Answers

There's an alternative to history editing (aka mucking around in MQ) for fixing renames. The manual procedure is outlined here as the logic that the fixrenames extension uses.

The manual process is as follows. For each revision N for which there are renames not marked:

$ hg update n-1
$ hg revert --all --rev n
$ hg addremove -s 70
$ hg commit -m "Fix renames from n"
$ hg merge n

Note that the similarity flag sometimes requires fiddling. The reason is that renames almost never are pure renames. For example, renaming a class requires a change in the file as well as a change in the filename. Thus they aren't 100% the same. You'll have to review what addremove does and make sure that the added files are marked as "X (renamed from Y)".

In this fashion you can recover full history without a bunch of manual work. I had to do this today (without using the fixrenames extension) and it took me about 5 minutes to fix.

You can even apply this procedure where there are stacked changesets you need to fix.

The changeset graph would look like this. Consider changesets A, B, C & D. B and D had incorrect renames:

D
|
C
|
B
|
A

First we update to A, do an inplace revert to B, do the addremove and commit as E. Then we merge C into E as F since C didn't have anything wrong with it. You should see something like this:

F D
|\|
| C
| |
E B
|/
A

Now apply the same for D. We update to F, revert from D, addremove and commit to G. Now we just merge to close the extra head. You should see something like this:

H
|\
G |
| |
F D
|\|
| C
| |
E B
|/
A

If you want to convince your self that this worked you can always

hg diff -r D -r H

Depending on your tool, you'll see either no difference or renamed files listed but with no differences between them.

like image 166
Chris Scott Avatar answered Oct 19 '22 17:10

Chris Scott