What does hg copy do?
Martin Geisler
mg at lazybytes.net
Fri Dec 16 09:06:15 UTC 2011
Christoph Mathys <eraserix at gmail.com> writes:
> We recently did a 'hg copy' of a directory in our repo. We thought it
> does something like 'cp -a' and 'hg add' and maybe flag somehow that
> this file has been copied from another file inside the repo (so 'hg
> annotate' shows the original committer). But it now seems that 'hg
> copy' does more or different stuff than that. I couldn't really find
> much on how exactly copy works. So:
>
> - What exactly does hg copy do and what special treatment does this
> cause in the future?
It adds new files and mark them as copies of the old files. Because they
are copies, a change made in the original file will be merged into copy.
Time flows from left to right:
(init) --- (edit a.txt) ---- (a.txt edit is copied to b.txt)
\ /
(hg copy a.txt b.txt)
> - If it turns out to do 'the wrong thing(tm)' for our case, how do I
> unflag the file as beeing a copy of another file?
This mechanism kicks in when you merge. If b.txt is not present in the
common ancestor revision (init in the above graph), then Mercurial will
do a search backwards to see if b.txt is copied from somewhere else.
Let us continue the above graph in abbreviated form:
(i) -- (edit a) -- (a edit copied to b) -- (edit a) -- (merge)
\ / /
(copy a b) --/------- (edit b) ------------------/
The question is how the final merge is done. The common ancestor point
is now the "copy a b" node and here both a and b are present. This means
that there wont be any search for copies! So the second edit to a wont
be merged into b.
To double-check that the above is right, I tries it out:
$ hg init
$ echo a > a
$ hg add a
$ hg commit -m init
$ hg copy a b
$ hg commit -m "copy a b"
This was the copy, b now contains "a" only.
$ hg update 0
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ echo aa >> a
$ hg commit -m "edit a"
created a new head
$ hg merge
merging a and b to b
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg commit -m "a edit copied to b"
This was the first merge and the edit to a has been copied into b:
$ cat b
a
aa
We now make changes in parallel:
$ echo aaa >> a
$ hg commit -m "edit a again"
$ hg update 3
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo bbb >> b
$ hg commit -m "edit b"
created new head
$ hg merge
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
There are no futher copying done:
$ cat a
a
aa
aaa
$ cat b
a
aa
bbb
As for disabling this... you can't really explicitly disable the copy
detection. But as I hope to have illustrated above, it wont "bother" you
again after the first merge.
If the first merge is a problem, then you can use 'hg resolve --tool
internal:local' to reset the files back to their state before you
started the merge. So with
hg resolve --tool internal:local b
we could have brought b back to just containing one line with "a".
--
Martin Geisler
Mercurial links: http://mercurial.ch/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: not available
URL: <http://lists.mercurial-scm.org/pipermail/mercurial/attachments/20111216/ed61c4d9/attachment.asc>
More information about the Mercurial
mailing list