Краткий ответ: это индекс сходства Git . Подробное описание алгоритма вычисления подобия см. В Попытка понять механизм обнаружения переименования `git diff` и` git mv * .
Дольше: на самом деле это не git push
; Вы видели это из git pull
. Но это также не git pull
: это вывод, полученный в результате git pull
работы git merge
, и на самом деле это git diff --stat
, который его печатает. 1 Что печатает git diff --stat
здесь: 2
<em>verb path</em> (<em>percentage</em>)
, где verb
- это один из rename
, rewrite
или copy
, path
- это путь к файлу или его сокращенная версия или (для переименований) старые и новые пути и процент - индекс сходства. Git использует этот индекс сходства, чтобы определить, могут ли два файла с разными именами или два файла с одинаковым именем, но очень разным содержимым, на самом деле быть одинаковым файлом или различными файлами после всех .
То есть, предположим, что в коммите ba3c046
есть файлы A1.txt
и A2.txt
, а в коммите 50fcdab
есть A2.txt
и B1.txt
(и ни в одном коммите нет других файлов). вероятно - понятно, что два A2.txt
файла являются "одним и тем же" файлом, даже если его содержимое несколько изменилось. Возможно, кто-то проверил коммит ba3c046
и изменил файл, а затем сделал коммит 50fcdab
из измененного результата.
А как же A1.txt
против B1.txt
? Может быть, кто-то проверил ba3c046
, переименовал файл - с изменением или без него - и сделал коммит 50fcdab
. Если они это сделали, commit 50fcdab
s B1.txt
действительно тот же файл, что и commit ba3c046
s A1.txt
.
Способ, которым Git определяет, являются ли эти два файла действительно идентичными или «почти идентичными» (переименованными и слегка измененными) файлами, заключается в сравнении их по сходству. Для этого он вычисляет индекс сходства между A1.txt
и B1.txt
.
Теперь предположим, что мы сравниваем коммит ba3c046
(с двумя его файлами) с коммитом 0f3ac31
, который имеет A2.txt
, B1.txt
и C1.txt
. Git не имеет значения, когда был сделан каждый коммит; Git рассмотрит содержимое в A1.txt
и оценит их сходство с 0f3ac31
'B1.txt
и 0f3ac31
' * C1.txt
. Если файл достаточно похож, Git сопоставит его. Git выберет файл 0f3ac31
, который наиболее похож на A1.txt
in ba3c046
.
Этот процесс - сопоставление файлов по тому, насколько близко их содержимое соответствует - это то, как Git определяет, какие файлы "одинаковы" в двух коммитах с git diff
-едом. Термин, который я использовал для этого процесса, определяет файлы , что мне не нравится так, как мне бы хотелось, поскольку мы не пытаемся найти файлы, которые 100% идентичны (хотя это помогает lot , когда они есть, из-за внутренней системы хранения Git).
По умолчанию два файла в двух разных коммитах автоматически идентифицируются (как «один и тот же файл»), если они имеют одинаковые имена, даже если их содержимое сильно отличается. Таким образом, эти два файла предварительно спарены, а не спарены из-за вычисленного сходства. В этом случае их индекс сходства будет относительно плохим, и Git назовет это «переписать».
Git также имеет концепцию индекса различий , которая составляет всего 100 минус сходство: например, файлы, похожие на 75%, отличаются на 25%. Флаг -B
(разрыв пар) для git diff
может использоваться для прерывания автоматического спаривания из предположения Git по умолчанию, что файл с путем P в левом коммите должен быть идентичен файл, чей путь P в правостороннем коммите. Запуск git merge
вызывает git diff
без установки флага прерывания.
CalculПодобное сходство стоит дорого, поэтому это делается только для непарных файлов или под -B . The unpaired files are those without a partner on the other side initially, or those broken-apart by
-B . If you use the
-C or
- find-copy or
- find-copy-harder`, Git рассмотрит некоторые левые / исходные файлы, возможно, были скопированы в некоторые правые / целевые файлы, так что объединение исходного файла с целевым файлом не удаляет исходный файл из пул "источников". Для большого репозитория, где две стороны различий содержат много файлов, для этого требуется много вычислений подобия, и это может занять много времени.
1 Вы также можете получить индекс сходства из git apply
. Я думаю, что вывод diffstat из git merge
теперь встроен непосредственно в git merge
, но для реального слияния вы можете повторить его, запустив git diff --stat <merge>^1 <merge>
.
Для быстрой перемотки вперед (которая на самом деле не является слиянием, даже если git merge
сделает это), вам нужно указать правильную пару коммитов. Сразу после git pull
это HEAD@{1}
и HEAD
, поэтому git diff --stat HEAD@{1} HEAD
сделает свое дело, но поскольку это относительные имена, они через некоторое время перестанут работать.) Кроме того, несколько оболочек (PowerShell в Windows и, например, tcsh и zsh в Linux) затрудняют предоставление суффикса @{1}
, поскольку им нравится использовать синтаксис {...}
в своих целях.
2 Для этого есть несколько форматов. Например, в выводе git diff-tree
используются кодовые буквы и проценты, а не слова. Это все разные способы сказать одно и то же: Git спарил определенные файлы в левой и правой части коммитов, возможно, несмотря на некоторые изменения в содержимом этих файлов.