Почему конфликт git cherry-pick включает изменения по сравнению с предыдущим коммитом - PullRequest
1 голос
/ 29 апреля 2019

У меня есть промежуточная ветвь, в которой я сделал несколько коммитов для функции, мне нужно сделать эти коммиты из основной ветки. Я пытался оформить ветку из главной ветки, используя git checkout -b branch_name, затем взял первый коммит, который я хотел выбрать из промежуточной ветви git cherry-pick hash. По какой-то причине существует конфликт с выбором вишни, но конфликт включает в себя изменения с коммита, предшествующего тому, который был выбран вишней, почему?

1 Ответ

8 голосов
/ 29 апреля 2019

TL; DR То, что вы видите, напрямую связано с тем, как Git записывает и хранит историю ваших файлов по сравнению с другими VCS.

Основы

Самый простой способ понять это - рассмотреть концепцию ревизия (или версия ).

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

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

Это лучше всего иллюстрируется изображением , используемым в Pro Git книге:

enter image description here

Здесь вы видите, как традиционная VCS хранит различия в каждом файле только между ревизиями.

В Git это выглядит примерно так (снова из книги Pro Git ):

enter image description here

Вы видите, что каждая ревизия связана с снимком всех файлов в рабочем каталоге. Однако документация гласит:

Для эффективности, если файлы не изменились, 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 прошел через предыдущие ревизии.

...