Обработка переименований: svn vs. git vs. mercurial - PullRequest
46 голосов
/ 08 октября 2009

Как каждый из этих VCS обрабатывает переименования?

Я обнаружил много противоречивой информации о том, что git отслеживает LOC (строки кода) вместо файлов, поэтому переименования не имеют для него никакого значения.

Ответы [ 6 ]

42 голосов
/ 08 октября 2009
  • Git вообще не отслеживает переименования, но использует эвристику для повторного обнаружения их во время слияния и т. Д.
  • Mercurial отслеживает переименования (записывается исходная версия и исходный файл) и использует эту информацию во время слияний. Поэтому вы должны явно сообщить hg о переименованиях с hg mv или использовать hg addremove --similarity для автоматического обнаружения. Говорили и о добавлении эвристики во время слияния.
  • Svn отслеживает переименования, но я не знаю, насколько хорошо они справляются с ними во время слияний (фактически никогда не проверял).
23 голосов
/ 09 октября 2009

1001 * Гит * Git отличается тем, что не выполняет отслеживание переименования , что означает, что ему не нужно сообщать о переименованиях с помощью команд SCM для выполнения переименования (или запуска сценария автоопределения для пометки переименований). перед фиксацией), и не сохраняет такую ​​информацию в хранилище, но делает обнаружение переименования . Это означает, что он находит переименования с использованием эвристического алгоритма на основе сходства имен файлов и файлов, как во время слияния, так и для diff, когда запрашивается с помощью параметра -M (или настраивается с использованием параметра diff.renames config). Преимущества этого метода следующие: переименования не должны быть помечены (или обнаружены) явно: переименования могут происходить из патча, или могут быть сделаны через файловый менеджер или графический интерфейс алгоритм обнаружения подобия может быть улучшен и не заморожен во время фиксации, как в случае обнаружения переименований, чтобы пометить их перед фиксацией, и сохранения этой информации в хранилище; также легче справляться с ошибками обнаружения переименования, если они не зафиксированы в истории из офилософии Гита следует, что важно содержание; посмотрите, как git blame (и графические интерфейсы к нему, такие как "git gui blame") могут следовать за перемещением блоков кода через границы файлов, что является более общим, чем полное переименование файлов . тот же механизм отвечает за обработку переименований во время слияний; Использование обнаружения переименования означает, что это может быть сделано за 3 коммита, на которых в конечном счете основано слияние, и нет необходимости тщательно следить за историей, отмечая каждое переименование - или нераспределенную концепцию канонического имени файла Обратите внимание, что фильтрация путей не работает хорошо с обнаружением переименования; если вы хотите проследить историю файла по переименованиям, используйте "git log --follow <filename>"

10 голосов
/ 26 июня 2010

На практике:

Git обнаруживает переименования автоматически. (Кстати, я слышал заявления о том, что git может обнаружить, когда вы перемещаете функцию из одного файла в другой. Мои первоначальные тесты , похоже, указывают, что это не так.)

В Mercurial вы должны явно сообщить ему о переименованиях, либо hg mv, либо параметром --similarity, равным hg addremove, либо параметром TortoiseHg «угадайте переименования», либо некоторыми инструментами, например VisualHg пометит переименования для вас. Если вы хотите использовать подход Git с Mercurial, я написал расширение для обнаружения переименований во время фиксации , но на данный момент оно находится на очень экспериментальной стадии.

Subversion вообще не обрабатывает переименования . Записывает переименование как удаление одного файла и добавление другого файла. Это означает, например, что если Алиса изменяет файл, а Боб переименовывает его, вы получаете конфликт дерева. Это происходит независимо от того, выполняете ли вы полноценное ветвление и слияние или просто svn update. Отслеживание переименования запланировано для Subversion 1.8, которая должна выйти в следующем году.

6 голосов
/ 08 октября 2009

Вы слышали правильно, вроде.

Git работает с содержимым файлов, а не с самими файлами, поэтому переименования для него технически бессмысленны. Для git переименование выглядит так, как будто файл A исчез, а файл B появился с тем же содержимым, что и A. Но git на самом деле довольно хорошо понимает, когда файл был фактически переименован.

Попробуйте: переименуйте файл, затем запустите 'git rm oldname' и 'git add newname', чтобы сказать git о необходимости внесения изменений, а затем запустите 'git status', чтобы увидеть, что думает Git о своих действиях - вы увидите что он говорит вам, что файл был переименован. Я не уверен, что это что-то значит позже. Посмотрите на коммит с помощью 'git show', и вы не увидите упоминаний о переименовании, просто группа строк, удаленных из одного пути и добавленных в другой.

Кроме того, вы также можете использовать команду 'git mv' для переименования файла. Он не меняет то, как git видит операцию, он просто эффективно выполняет «mv oldname newname», «git rm oldname» и «git add newname» за один шаг.

Обзор Mercurial см. tonfa's answer .

С другой стороны, SVN не может обнаружить переименования, но необходимо сообщить о них командой 'svn mv'. Однако, когда ему сообщают, он отслеживает переименования как изменения «первого класса», поэтому при последующем просмотре журнала изменений вы увидите, что это было переименованием.

Я бы не советовал выбирать SVN вместо git или mercurial на основе этой функции. Есть намного большие и более важные различия между инструментами. Сначала я бы решил, хотите ли вы распределенную систему контроля версий (git или mercurial) или централизованную систему контроля версий (svn).

3 голосов
/ 10 октября 2009

Еще одна вещь о git, которая еще не упоминалась, помимо использования эвристики для определения того, произошло ли переименование:

Если файл или даже целое дерево каталогов переименовано, скопировано или перемещено, а ничто внизу не изменено каким-либо образом, то файл или дерево фактически сохраняются как один и тот же объект внутри хранилища и не занимает дополнительного места.

Если вы измените его, он будет сохранен как новый объект, как обычно.

Я не уверен насчет hg и svn, но подозреваю, что их архитектуры, ориентированные на список изменений, означают, что в этом сценарии они ведут себя по-разному. На самом деле это никак не влияет на использование, за исключением того, что оно может дать вам причину избегать перемещения или копирования огромных деревьев внутри вашего хранилища.

0 голосов
/ 08 октября 2009

git отслеживает содержимое, а не файлы. я не уверен насчет меркуриала, но svn должен быть точно объяснен о переименованиях

...