Переименование файлов vs pull request squa sh merge - PullRequest
0 голосов
/ 03 марта 2020

Из того, что я узнал, git может обрабатывать переименования / перемещения файлов, когда вы фиксируете переименование / перемещение в одном коммите, и вносить изменения в другой коммит.

Но как это работает, когда вы работаете sh объединить вашу ветку PR?

т.е.

  1. В вашей ветви функций: переименовать файлы и зафиксировать
  2. В вашей ветви функций: изменить файлы и зафиксировать
  3. Создать PR
  4. Squa sh объединить его с мастером

В то же время кто-то еще изменил те же файлы в своей собственной ветви функций.

Что происходит, когда они объединяют мастера в свою ветвь функций? Из того, что я понимаю, переименование и изменение файла находятся в одном коммите в master (из-за squa sh merge), верно? Так как же git будет относиться к этому?

1 Ответ

1 голос
/ 03 марта 2020

Из того, что я узнал, git может обрабатывать переименования / перемещения файлов, когда вы фиксируете переименование / перемещение в одном коммите и вносите изменения в другой коммит.

Что ж, да, но также нет.

Ключ в том, что Git не сохраняет изменений . Git хранит снимков . Другими словами, каждый коммит имеет полную и полную копию вашего исходного кода. Если вы переименуете группу файлов, не внося никаких других изменений и сделав новый снимок, старый снимок будет иметь содержимое под старыми именами, а новый снимок будет иметь то же самое содержимое, но под новым набором. из names .

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

Что Git делает с git log --follow и git diff --find-renames, делает два снимка - скажем, «до» и «после» интересного события, причем интересным событием в этом случае является переименуйте - и сравните их. Внутренне зафиксированные файлы хранятся как пары (или, точнее, утраивает):

$ git ls-tree -r HEAD
[snippage]
100644 blob 41b718c29e1b9fc2981d7d14a3d25e69c31a3030    version.c
100644 blob 7c62e80577154d79bec050424945eb500d262a0f    version.h
100644 blob 069ee94a4d79422ea659a7ebe3923662f0626afa    versioncmp.c
100644 blob bb010f7a2b3c1090bc9c62f613cede7bbda86e97    walker.c
[snippage]

Здесь blob фактически является текстовым представлением части mode (100644 всегда является объектом BLOB-объекта), поэтому каждая из этих строк является результатом чтение записи tree , в которой хранится это имя-и-ха sh -ID.

Идентификатор ha sh идентификатора содержимого каждого файла основан исключительно на данных файла, отсутствует в файле name . Например, если имя файла было walker.c или funny.name, при условии, что content одинаково, ha sh ID также будет одинаковым.

Итак, с учетом снимка с левой и правой стороны - до и после - если га sh идентификаторов совпадают, содержимое также совпадает. Это делает его очень быстрым для git diff --find-renames до поиска переименований: мы просто выстраиваем все совпадающие идентификаторы ha sh, а имена слева переименовываются в имена, которые находятся на правильно.

Если файлы были слегка изменены , этот трюк быстрого переименования не работает. Теперь Git должен фактически извлечь все левые файлы и все правые файлы и сравнить их. В отличие от быстрого трюка «посмотрите на ha sh ID», на самом деле это очень сложно (это O (n 2 ) в количестве файлов, которые нужно объединить в пару). Git сначала сделает все возможное, чтобы спарить все левые и правые файлы, которые он может, без проверки их содержимого, чтобы список «возможно переименованных» файлов был как можно меньшим, а затем только смотреть на те файлы, которые не в паре.

Итак, Git может обрабатывать обе ситуации - до тех пор, пока содержимое не изменилось слишком , так что Детектор сходства может сжечь много процессорного времени для сопоставления файлов по индексу сходства, но для поиска совпадения по переименованию требуется намного меньше вычислительной мощности, если событие, через которое git diff передает два коммита, просто событие переименования. Это означает, что все идентификаторы ha sh совпадают, а код быстрого совпадения выполняет всю работу.

Но как это работает, когда вы объединяетесь в sh слияние вашей PR-ветви?

Это не так.

Squa sh слияния инструменты . Используйте их, когда они уместны. Используйте другие инструменты, когда слияния squa sh не подходят.

(Помните, squa sh -merge означает run git merge, но затем фиксируйте результат как обычный коммит , а не как коммит слияния. Из командной строки git merge --squash действует так, как если бы вы также включали опцию --no-commit каждый раз, поэтому вы должны сами запускать команду git commit. GitHub clicky "squa * 1112 Кнопка * and merge "не использует команды командной строки, поэтому она немного отличается, но окончательный набор коммитов, который вы получаете, такой же, как если бы вы сделали все это в командной строке.)

...