Как Git записывает (или, скорее, представляет) пути к файлам и имена для своих больших двоичных объектов, а затем идентифицирует переименования?
Я пытаюсь понять, как git "запоминает" имя файла и его путь, учитывая, что он хранит только содержимое файла внутри большого двоичного объекта. Является ли объяснение в ссылке здесь Abizem хорошим? (это лучшее, что я видел до сих пор)
Следующий вопрос: как (где) git определяет, когда мы имеем сходство, особенно после "перемещения" или обновления имени пути? (в соответствии с моим переименованием подкаталога Q). Мне нужно иметь возможность поддерживать существующий рабочий процесс, использующий переименования путей, как часть низкоуровневой персональной VCS (у нас есть большая железная VCS для больших выпусков, но ничего для повседневного / круглосуточного использования)
2 ответа
git
определяет четыре вида объектов (Commit, Tag, Tree, Blob). Каждый объект идентифицируется после хеша его содержимого.
Три объекта, которые связаны с переименованием:
BLOB-объект: это соответствует зафиксированному файлу, содержимое объекта является сжатым содержимым исходного файла.
дерево: это соответствует списку каталогов, оно содержит сопоставление имени файла с другими объектами (либо BLOB-объектами, либо деревьями), а также записывает права доступа
commit: содержит сообщение о коммите, указатель на родительский коммит (ы) (кроме первого коммита) и объект дерева
Поэтому, когда вы переименовываете файл и фиксируете его, создается новый объект дерева (ну, и не один, если он находится в подкаталоге) с новым именем сопоставления для объекта, но объект остается тем же.
Тем не менее, git не отслеживает переименование, он пытается обнаружить их заново, сравнивая содержимое файла. Если два файла действительно похожи, но имеют разные имена, он считает, что это переименование. Это может занять много времени, и если файлов много, это может привести к сбою.
Редактировать: взгляните на Git Community Book, в которой есть действительно хорошее объяснение того, как git хранит информацию.
Почему git не "отслеживает" переименования?
Git должен взаимодействовать с множеством различных рабочих процессов, например, некоторые изменения могут вноситься в патчи, где информация о переименовании может быть недоступна. Использование явного отслеживания переименования делает невозможным объединение двух деревьев, которые сделали одно и то же, за исключением того, что один сделал это как патч (создать / удалить), а другой - с использованием другой эвристики.
Во-вторых, отслеживание переименований - это просто особый случай отслеживания движения контента в дереве. В некоторых случаях вас может заинтересовать запрос, когда функция была добавлена или перемещена в другой файл. Опираясь только на возможность воссоздания этой информации при необходимости, Git стремится предоставить более гибкий способ отслеживания изменений вашего дерева.
Однако это не означает, что Git не поддерживает переименования. Механизм diff в Git поддерживает автоматическое определение переименований, это включается переключателем '-M' для семейства команд git-diff-*. Механизм обнаружения переименования используется git-log(1) и git-whatchanged(1), поэтому, например, 'git log -M' выдаст историю коммитов с информацией о переименовании. Git также поддерживает ограниченную форму слияния через переименования. Два инструмента для назначения blame, git-blame(1) и git-annotate(1), используют автоматический код обнаружения переименования для отслеживания переименований.
В качестве особого случая в "git log" версии 1.5.3 и новее есть опция "--follow", которая позволяет вам следовать переименованиям, если указан один путь. Почта Линуса на эту тему.
Git имеет команду переименования git mv, но это только для удобства. Эффект неотличим от удаления файла и добавления другого с другим именем и тем же содержимым.
Я удивлен, что никто не связался с книгой Pro Git. Многое из того, что я узнал из этого.
Кроме того, если вы можете получить книгу Version Control with Git
, сделай это. Это очень хорошая книга, особенно для начинающих.
Вот ссылка - Контроль версий с помощью Git.
Также есть Git снизу вверх.