Обработка переименований: svn vs. git vs. mercurial

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

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

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

Гит

Git отличается тем, что он не выполняет переименование , что означает, что ему не нужно рассказывать о переименованиях с помощью команд SCM для выполнения переименования (или запускать сценарий автоопределения для отметки переименований перед фиксацией) и не сохраняет такая информация в репозитории, но она переименовывает обнаружение . Это означает, что он находит переименования, используя эвристический алгоритм схожести на основе имени файла и содержимого файла, как во время слияния, так и для diff при запросе через параметр -M (или настроен с использованием diff.renames конфигурации diff.renames ).

Преимущества этого метода заключаются в следующем:

  • переименования не обязательно должны быть отмечены (или обнаружены) явно: переименование может происходить из патча или может быть выполнено vie filemanager или графический интерфейс
  • алгоритм обнаружения сходства может быть улучшен и не блокируется во время фиксации, как в случае обнаружения переименований, чтобы пометить их перед фиксацией, и сохранения этой информации в репозитории; также легче справляться с ошибками обнаружения переименования, если они не заморожены в истории
  • следует Git ophilosophy, что это содержание имеет значение; посмотрите, как git-винить (и графические интерфейсы к нему, например, «git gui wame») могут отслеживать движение блоков кода через границы файлов, что более общее, чем переименование файлов.
  • тот же механизм отвечает за обработку переименований во время слияний; использование переименования означает, что это можно сделать для 3 коммитов, которые в конечном итоге основаны на слиянии, и нет необходимости внимательно следить за историей, отмечая каждое переименование – или нераспространенную концепцию канонического имени файла

Обратите внимание, что фильтрация pathspec не работает с обнаружением переименования; если вы хотите следить за историей файла через переименования, используйте « git log --follow <filename> »,

На практике:

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

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

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

Вы слышали правду.

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 .

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

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

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

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

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

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

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