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 г.)

Коммит 46d723capply: синхронизировать пару буфер / размер при разборе бинарных блоков

Автор отчета: Синман Чен.
Подпись: Джефф Кинг.

Мы анализируем двоичные блоки, просматривая буфер в цикле с таким кодом, как:

       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, показывает, что мы получаем сообщение о выходе за пределы до этого патча, но не после него.

Другие вопросы по тегам