cherry-pick
реализован как слияние, при этом база слияния является родителем cmomit, который вы вносите. В случаях, когда нет конфликтов слияния, это должно иметь точно такой же эффект, как создание и применение исправления, как у вас (но см. ответ Торека для небольшого предостережения, где am
теоретически может сделать что-то не так).
Но, выполняя слияние, cherry-pick
может попытаться более изящно обрабатывать случаи, когда изменения могут конфликтовать. (На самом деле опция -3
, которую вы дали am
, говорит ему, что в случае необходимости он должен делать то же самое, если у него достаточно контекста в патче, чтобы сделать это. Я вернусь к этому моменту в конец...)
Когда вы применяете патч, по умолчанию, если он изменяет фрагмент кода, который не совпадает с тем коммитом, в котором вы его применяете, как и в родительском коммите, из которого он был сгенерирован, то применение завершится ошибкой. Но подход cherry-pick
/merge рассмотрит эти различия и создаст из них конфликт слияния, так что у вас есть шанс разрешить конфликт и продолжить работу.
Как часть обнаружения конфликтов, cherry-pick
выполняет обнаружение переименования. Так, например, скажем, у вас есть
o -- x -- x -- A <--(master)
\
B -- C -- D <--(feature)
и вы cherry-pick
передаете C
на master
. Предположим, в o
вы создали file.txt
, а в A
у вас есть модификации file.txt
. Но фиксация B
перемещает file.txt
в my-old-file.txt
, а фиксация C
изменяет my-old-file.txt
.
Изменение на my-old-file.txt
в C
может конфликтовать с изменением на file.txt
в A
; но чтобы увидеть эту возможность, git должен выполнить обнаружение переименования, чтобы он мог понять, что file.txt
и my-old-file.txt
- это «одно и то же».
Вы можете знать, что у вас нет такой ситуации, но git не знает, пока не попытается обнаружить переименования. Я не уверен, почему в данном случае это отнимает много времени; по моему опыту, обычно это не так, но в репозитории с большим количеством добавленных и удаленных путей (между B
и либо C
, либо A
в нашем примере) это может быть.
Когда вместо этого вы создаете и применяете исправление, оно пытается применить исправление, полагая, что конфликта нет. Только если это столкнется с проблемой (и только потому, что вы указали параметр -3
), он вернется к выполнению слияния с обнаружением конфликтов. Он может пропустить все это - и любое потенциальное обнаружение переименования - до тех пор, пока его первая попытка применяется чисто.
Обновление. Как отмечено в комментариях к вопросу, вы также можете отключить обнаружение переименования, если оно не помогает и работает медленно. Если вы используете это, когда на самом деле есть переименования, которые «имеют значение» для слияния, это может вызвать конфликты, в которых обнаружение переименования разрешит их. Хотя я не думаю, что это необходимо, я не могу исключить, что он также может просто вычислить неверный результат слияния и незаметно применить его — поэтому я редко использую эту опцию.
Для стратегии слияния по умолчанию параметр -X no-renames
отключает обнаружение переименования. Вы можете передать эту опцию cherry-pick
.
Согласно комментарию Торека, кажется, что обнаружение переименования не должно быть проблемой с am
. Тем не менее, я могу подтвердить, что он способен правильно обрабатывать случай, когда слияние работает только с обнаружением переименования. Я собираюсь вернуться к попыткам понять все тонкости этого как-нибудь, когда не будет вечер пятницы.
person
Mark Adelsberger
schedule
31.08.2018
-X no-renames
не отключает это? - person o11c   schedule 31.08.2018