Внутренне, git cherry-pick <em>commit</em>
реализовано как трехстороннее слияние с:
- база слияния, установленная в качестве родителя коммита, обозначенного
commit
;
- текущий коммит установлен на текущий коммит, как всегда;
- другой коммит установлен на
commit
.
Это объединяющее действие, или, как я люблю его называть, «объединить как глагол», происходит как обычно:
- запустить
git diff --find-renames <em>base</em> HEAD
, чтобы узнать, что мы изменили
- запустить
git diff --find-renames <em>base</em> <em>other</em>
, чтобы узнать, что они изменили
- объединить два набора изменений, применяя объединенные изменения к
base
Если это удается, Git делает новый обычный (без слияния) коммит как обычно. Если это не удается, Git останавливается с конфликтом слияния, оставляя коммит other
, идентифицируемый CHERRY_PICK_HEAD
вместо MERGE_HEAD
, так что ваш окончательный коммит - при условии, что вы выбрали коммит - делает обычный (без слияния) commit.
Это --find-renames
шаг, который находит или не может найти, переименовывает. Это делается обычным способом. Например, при сравнении base
с HEAD
, если в base
существуют файлы, которые не существуют в HEAD
в то же самое Имена, Git будет сравнивать все несопоставленные base
файлы со всеми несопоставленными HEAD
файлами, чтобы увидеть, какие из этих файлов имеют похожее содержимое. Два файла с большинством аналогичным содержимым будут объединены в пару при условии, что вычисленный индекс подобия соответствует или превышает минимальный требуемый индекс сходства, выбранный -X find-renames=<em>value</em>
. Если такого аргумента -X
нет, по умолчанию используется значение 50 (то есть 50% аналогичное).
Поэтому, когда я пытаюсь выбрать вишню, переход от B к A,
git cherry-pick commit-hash
Давайте закончим эту мысль. Когда вы пытаетесь выбрать этот конкретный коммит, Git находит родителя этого коммита, выбирает его в качестве базы слияния и запускает указанную выше команду git diff
. HEAD
имеет значение name A
, так что текущий коммит является коммитом tip для ветви A
, каким бы ни был этот хэш-идентификатор. Git поэтому запускает эквивалент git diff --find-renames hash A
. Сделайте это самостоятельно, если хотите, с помощью --name-status
(чтобы получить только имена и статусы файлов, включая переименования), и вы увидите, какие файлы Git были в паре между hash
и HEAD
. Если вы прочитали предыдущий абзац, вы уже знаете, какой алгоритм Git использует для этого спаривания: он ищет достаточно похожих файлов, которые иначе не были бы спарены.
Если таких файлов не может быть никогда, Git не найдет таких файлов. В этом случае вам необходимо изменить любые имена файлов, если / как необходимо.