TL; DR То, что вы видите, напрямую связано с тем, как Git записывает и хранит историю ваших файлов по сравнению с другими VCS.
Основы
Самый простой способ понять это - рассмотреть концепцию ревизия (или версия ).
Традиционно системы контроля версий записывают ревизию файлов в вашем рабочем каталоге, сохраняя различия между тем, как файлы находятся сейчас, и как они были в предыдущей ревизии (это также известно как delta или Δ).
Git, с другой стороны, записывает ревизию, сохраняя снимок всех файлов в вашем рабочем каталоге, как они есть сейчас.
Это лучше всего иллюстрируется изображением , используемым в Pro Git книге:
Здесь вы видите, как традиционная VCS хранит различия в каждом файле только между ревизиями.
В Git это выглядит примерно так (снова из книги Pro Git ):
Вы видите, что каждая ревизия связана с снимком всех файлов в рабочем каталоге. Однако документация гласит:
Для эффективности, если файлы не изменились, Git больше не сохраняет файл - просто ссылка на предыдущий идентичный файл, который он уже сохранил.
Однако концептуально вы все еще можете думать о каждом коммите, указывающем на снимок всего вашего рабочего каталога.
Cherry-сбор
Теперь рассмотрим, что происходит, когда вы выбираете коммит. Предположим, мы хотим выбрать коммит, соответствующий Version 5
:
git cherry-pick <version-5>
Git собирается merge
снимок, связанный с коммитом, на который ссылается HEAD
(то есть файлы в вашем рабочем каталоге) со снимком, связанным с version-5
.
Теперь, если version-4
изменил строку в file B
(в результате file B1
) таким образом, что конфликтует с тем, как file B
выглядит в вашем рабочем каталоге, вы получите конфликт. Вот важная часть:
Конфликт может произойти, даже если version-5
(тот, который вы собираете вишню) изменил тот же file B
таким образом, чтобы ни с чем не конфликтовать.
Это потому, что снимок, связанный с version-5
, содержит file B2
, который является результатом всех изменений, которые file B
прошел через предыдущие ревизии.