Подтвердить что ты не робот

Что делает копия hg?

Недавно мы сделали hg copy каталога в нашем репозитории. Мы думали, что это делает что-то вроде cp -a и hg add и, возможно, как-то может этот файл был скопирован из другого файла внутри репо (поэтому hg annotate показывает исходный коммиттер). Но теперь кажется, что hg copy делает больше или отличается от этого. Я не мог найти как работает копирование. Итак:

  • Что именно делает hg copy и какое специальное лечение делает это в будущем?
  • Если для нашего случая получается "неправильная вещь (tm)", как мне unflag файл как копия другого файла?

(Этот вопрос задан в списке рассылки Mercurial, вы можете следовать за исходным потоком.)

4b9b3361

Ответ 1

  • Что именно делает hg copy и какое специальное лечение делает это в будущем?

Он добавляет новые файлы и отмечает их как копии старых файлов. Поскольку они являются копиями, изменение, внесенное в исходный файл, будет объединено в копию. Время течет слева направо:

(init) --- (edit a.txt) ---- (a.txt edit is copied to b.txt)
      \                     /
       (hg copy a.txt b.txt)
  • Если для нашего случая получается "неправильная вещь (tm)", как мне unflag файл как копия другого файла?

Этот механизм срабатывает только при слиянии. Если b.txt нет в общая версия предка (init в приведенном выше графике), тогда Mercurial будет выполните поиск в обратном порядке, чтобы увидеть, скопирован ли b.txt из другого места.

Продолжим приведенный выше график в сокращенном виде:

(i) -- (edit a) -- (a edit copied to b) -- (edit a) -- (merge)
   \              /                                   /
    (copy a b) --/------- (edit b) ------------------/

Вопрос заключается в том, как выполняется окончательное слияние. Общая точка предка теперь copy a b node, и здесь присутствуют как a, так и b. Это означает что не будет никакого поиска копий! Итак, второе редактирование на a wont быть объединены в b.

Чтобы дважды проверить, я попробовал:

$ hg init
$ echo a > a
$ hg add a
$ hg commit -m init
$ hg copy a b
$ hg commit -m "copy a b"

Это была копия, b теперь содержит только a.

$ 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"

Это было первое слияние, и редактирование на a было скопировано в b:

$ cat b
a
aa

Теперь мы вносим изменения параллельно:

$ 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)

Дальнейшее копирование не выполняется:

$ cat a
a
aa
aaa
$ cat b
a
aa
bbb

Что касается отключения этого... вы не можете явно отключить копию обнаружение. Но, как я надеюсь, чтобы проиллюстрировать выше, это не будет "беспокоить" вас снова после первого слияния.

Если первое слияние является проблемой, вы можете использовать hg resolve --tool internal:local to reset файлы обратно в их состояние перед вами начал слияние. Итак,

$ hg resolve --tool internal:local b

мы могли бы вернуть b обратно только к одной строке с a.

Ответ 2

Как мне пометить файл как копию другого файла?

Если вы вернете копию hg, скопированный файл останется в вашем рабочем каталоге и не будет отслеживаться. Вы просто должны добавить это нормально. На скопированный файл это никак не влияет.

% 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

Ссылка: Mercurial: полное руководство