Git cherry-pick действительно такой же, как git show + git apply?
Может ли быть так
git cherry-pick <rev>
на самом деле точно так же, как
git show <rev> | git apply -3 -
???
Поскольку запуск любого из них приводит к абсолютно одинаковому результату для меня, и если бы я знал, что они действительно эквивалентны, я мог бы получить гораздо лучшее понимание того, как на самом деле работает сбор вишни с помощью GIT, поскольку это не всегда дает мне результат, который я ожидать, но это, вероятно, потому что единственное изменение не может быть применено, и сбор вишни сводится к тройному слиянию (вот что -3
делает по второй команде), и это объясняет неожиданный результат.
3 ответа
Помимо правильного ответа Эдмундо, и я проголосовал за него, есть еще куча других подробностей, включая комментарий ephemient о двоичных файлах (git show
потребности --binary
произвести бинарный патч) и что вам может понадобиться --full-index
а также, в некоторых редких случаях, когда сокращенное Index:
линия недостаточна.1
Также, конечно, git apply
(с или без -3
) не против грязного индекса и рабочего дерева, пока git cherry-pick
требует чистого индекса и рабочего дерева, если вы не добавите -n
, И, если вы пропустите -n
, git cherry-pick
продолжает делать коммит, который git apply
никогда не делает
Все сказанное, однако, да, эти два должны быть функционально эквивалентны для нормальных случаев.
1 Чтобы это произошло, хэши больших двоичных объектов должны быть неуникальными при сокращении. Это было сделано автоматически-корректно в Git версии 1.7.2, хотя, если вы используете определенную длину аббревиатуры с помощью core.abbrev
или флаг командной строки, вы все равно можете получить неуникальные сокращения хеша. Добавление --full-index
гарантирует, что вы получите уникальные.
(Если вы хотите сохранить diff в течение длительного периода, добавьте кучу новых объектов в хранилище, а затем попробуйте git apply -3
Дифф, это возможно для сокращенного Index:
линии, которые были однозначны, прежде чем стать неоднозначными сейчас.)
С технической точки зрения, git cherry-pick работает как git merge, где вместо поиска "лучшей ревизии, присутствующей в обеих ветвях", чтобы проверить различия и объединить их, "общая ревизия" для логики слияния вынуждена быть родитель ревизии вы выбираете вишню.
Примечание: для двоичных файлов все равно не будет работать, только не ранее Git 2.34 (4 квартал 2021 г.): "git apply
" (man) неправильно подсчитал байты и не смог прочитать до конца двоичных блоков.
См. (09 августа 2021 г.) Джеффа Кинга (
peff
).
(Слияние Junio C Hamano -
gitster
- в коммите 7e3b9d1, 30 августа 2021 г.)
Коммит 46d723c
apply
: синхронизировать пару буфер / размер при разборе бинарных блоковАвтор отчета: Синман Чен.
Подпись: Джефф Кинг.
Мы анализируем двоичные блоки, просматривая буфер в цикле с таким кодом, как:
llen = linelen(buffer, size); ...do something with the line... buffer += llen; size -= llen;
Однако перед тем, как мы войдем в цикл, есть один вызов, который увеличивает «буфер», но забывает об уменьшении «».
В результате наш "size
"отключен из-за длины этой строки, и последующие вызовыlinelen()
может заглянуть за конец буфера в поисках новой строки.Исправить это просто: нам просто нужно уменьшить размер, как мы это делаем в других случаях.
Эта ошибка восходит к 0660626 («двоичный diff: дальнейшие обновления.», 2006-05-05, Git v1.4.1-rc1 - слияние ).
По-видимому, никто не заметил, потому что он срабатывает только в том случае, если патч поврежден, и даже в этом случае нас часто «спасает» удача.
Мы используемstrbuf
чтобы сохранить входящий патч, поэтому мы перераспределяем его, плюс мы добавляем 16-байтовый прогон NUL в качестве задержки для сравнения памяти.
Так что, если это произошло случайно, обычно мы просто считываем несколько неинициализированных байтов с конца strbuf перед тем, как выдать ожидаемую жалобу на ошибку «этот патч поврежден».Однако можно тщательно сконструировать регистр, считывающий конец буфера.
Включенный тест делает это.
Он будет проходить как до, так и после этого патча при обычном запуске, но использование такого инструмента, как ASan, показывает, что мы получаем сообщение о выходе за пределы до этого патча, но не после него.