So somebody on our team moved an entire folder into a subdirectory without using hg's rename feature. The directory structure is like we need it, but the history is now gone prior to the move. It shows it as a new file when the move occurred. Numerous large merges have happened since then, and so it is not really practical to go back in time and do it right.
I have tried hg log --follow
and it does not help, since hg does not know about the rename. Is there any way to manually link the files to the old removed versions after the fact, or is there some facility like the way git can infer moves and renames based on hueristics? It would be nice if there was some way to explicitly say, "this file is a continuation of this old deleted file.", even though that would still take some time to fix it all up right.
We have all but given up on ever getting that history back, but it would be really nice to have it.
You need to redo the move correctly by explicitly telling Mercurial what files were moved, then merge the broken changesets. This way you will restore the history path to the original files.
Steps, assuming <x>
is the move revision, and <y>
is the current head revision.
hg update <x-1>
hg rename
or hg rename --after
hg merge <x>
), this should have no conflicts but if there are discard all changes.hg merge <y>
)Here is the basic process shown on the command line:
$ mkdir move-merge-test
$ cd move-merge-test
$ hg init
$ echo "x" > a
$ hg add a
$ hg commit -m "initial revision"
Move incorrectly:
$ mv a b
$ hg remove a
$ hg add b
$ hg status --copies
A b
R a
$ hg commit -m "incorrect move"
$ hg log --follow b
changeset: 1:b22f3e94133b
tag: tip
user: Laurens Holst <...>
date: Wed Oct 19 14:41:37 2011 +0200
summary: incorrect move
Correct the move:
$ hg update 0
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ hg rename a b
$ hg status --copies
A b
a
R a
$ hg commit -m "correct move"
created new head
$ hg log --follow b
changeset: 2:5deabbcb5480
tag: tip
parent: 0:b82f89f0c7d9
user: Laurens Holst <...>
date: Wed Oct 19 14:46:35 2011 +0200
summary: correct move
changeset: 0:b82f89f0c7d9
user: Laurens Holst <...>
date: Wed Oct 19 14:36:35 2011 +0200
summary: initial revision
Merge it with the broken move:
$ hg merge 1
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg commit -m "merge with broken move"
$ hg log --follow b
changeset: 3:ce65fc7b35e4
tag: tip
parent: 2:5deabbcb5480
parent: 1:b22f3e94133b
user: Laurens Holst <...>
date: Wed Oct 19 14:47:13 2011 +0200
summary: merge broken branch
changeset: 2:5deabbcb5480
parent: 0:b82f89f0c7d9
user: Laurens Holst <...>
date: Wed Oct 19 14:46:35 2011 +0200
summary: correct move
changeset: 1:b22f3e94133b
user: Laurens Holst <...>
date: Wed Oct 19 14:41:37 2011 +0200
summary: incorrect move
changeset: 0:b82f89f0c7d9
user: Laurens Holst <...>
date: Wed Oct 19 14:36:35 2011 +0200
summary: initial revision
As you can see, the history now correctly shows all affected changesets. If the files are moved in several commits, the basic principle stays the same just merge across more than just 1 commit. If you have any commits made after the move, I recommend to merge them in separately (step 6 in the steps above) in order to avoid spurious conflicts.
I had good luck with this kind of thing by deleting the new (the "moved") file, then going back to a revision when the file was still in place, doing the move properly (including commit) and merging the two heads.
There's a --after
option to hg rename
which lets you tell Mercurial about a rename after the fact, but it has to be done before you commit the rename.
You could try doing hg convert
on the repository and specify the --filemap
parameter, which will let you rename a files and directories.
https://www.mercurial-scm.org/wiki/ConvertExtension#A--filemap
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With