We recently did a hg copy
of a directory in our repository. 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:
hg copy
do and what special treatment does this
cause in the future?(This question was asked on the Mercurial mailinglist, you may want to follow the original thread too.)
hg folder keeps track of one repo only. If you've got one in your home directory it means your home directory is under version control.
Once you decide that a file no longer belongs in your repository, use the hg remove command. This deletes the file, and tells Mercurial to stop tracking it (which will occur at the next commit). A removed file is represented in the output of hg status with a “ R ”.
Create a local Mercurial repository Open the project you want to store in a repository. From the main menu, choose Hg | Create Mercurial Repository. Specify the location of the new repository.
- What exactly does hg copy do and what special treatment does this cause in the future?
It adds new files and marks 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 only 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, I tried 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 further 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
.
How do I unflag the file as being a copy of another file?
If you revert a hg copy, the copied-to file remains in your working directory afterwards, untracked. You just have to add it normally. The copied-from file isn't affected at all.
% hg copy file new-file
% hg status -C
A new-file
__file
% hg revert new-file
% hg add new-file
% hg status -C
A new-file
Reference: Mercurial: The definitive guide
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