В одном предложении то, что -m
или --merge
делает для git rebase
, состоит в том, чтобы убедиться, что rebase использует git cherry-pick
внутри.
Флаг -m
для принудительного выбора вишни часто, но не всегда, излишним.В частности, любая интерактивная перебазировка всегда использует cherry-pick.* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *.Как и -k
, как отмечено ниже.
Long (или, по крайней мере, более длинный)
Rebase имеет длинную историю в Git: первые операции rebase были выполнены путем форматирования каждого коммита набыть перебазирован в патч, затем применить патч к другому коммиту.То есть изначально git rebase
был в основном просто:
branch=$(git symbolic-ref --short HEAD)
target=$(git rev-parse ${onto:-$upstream})
git format-patch $upstream..HEAD > $temp_file
git checkout $target
git am -3 $temp_file
git checkout -B $branch HEAD
(за исключением обработки аргументов, всей проверки ошибок и того факта, что git am
может останавливаться с ошибкой, требующей ручного исправленияи git rebase --continue
; кроме того, приведенный выше сценарий является моей версией с ограниченной читабельностью и, вероятно, не очень похож на исходный сценарий).
Этот вид перебазирования справляется с большинством случаев достаточно хорошо.Наиболее распространенный случай, когда он плохо обрабатывает , включает перебазирование некоторых переименований файлов.Он также не может скопировать «пустой» коммит - тот, чей патч пуст, т. Е. git format-patch
не разрешено пропускать часть патча.
Эти пустые коммиты обычно опускаются git rebase
, даже когдаиспользуя -m
;Вы должны добавить -k
, чтобы сохранить их.Чтобы сохранить их, git rebase
должен переключиться на вариант выбора вишни, если это еще не сделано.
Чтобы передать -s
или -X
аргументов, rebase должен вызывать git cherry-pick
вместо git am
, поэтому для любого из этих флагов также требуется вариант cherry-pick.
Использование git format-patch
никогда не приводит к обнаружению переименования.Следовательно, если поток копируемых вами коммитов должен иметь обнаружение переименования в отношении HEAD
, флаг -m
очень важен.В качестве конкретного примера рассмотрим следующую серию коммитов:
B--C--D <-- topic
/
...--o--A--E--F--G <-- mainline
Предположим, что разница от A
до B
, B
до C
и C
до D
равнавсе обрабатывается в файле с именем lib-foo.ext
.Но в коммите F
этот файл переименован в , вместо lib/foo.ext
.git format-patch
из A..D
покажет изменения, которые должны быть внесены в файл lib-foo.ext
, ни одно из которых не будет корректно применено для фиксации G
, поскольку файла lib-foo.ext
нет.Перебазирование в целом завершится неудачей.
A git cherry-pick
commit B
, когда HEAD
идентифицирует commit G
, однако найдет переименование и применит A
-vs- B
изменяет версию lib/foo.ext
в коммите G
:
B--C--D <-- topic
/
...--o--A--E--F--G <-- mainline
\
B' <-- HEAD [detached]
Следующий вишневый пик, C
, в то время как HEAD
идентифицирует B'
, обнаружит, что B
-to- C
изменение на libfoo.ext
должно применяться к переименованному lib/foo.ext
, и последний вишневый пик D
сделает то же самое, так что перебазировка будет успешной.
Код обнаружения переименования идет медленно, поэтому ребаз, который имеет no , переименовывает в «делать», и «пустые» коммиты не сохраняются, может работать намного быстрее при запуске через систему git format-patch | git am
.Это единственный способ, с помощью которого оригинальный метод лучше, чем вариант «черешни»: он быстрее в ограниченных случаях.(Однако улучшение скорости происходит только тогда, когда имеется много переименованных кандидатов , но ни один из них не является действительным переименовывает , либо ни один из них не имеет значения.)
(Примечание: аргумент -3
, или --3way
, чтобы использовать более длинное написание, говорит git am
передать этот флаг каждому git apply
, где apply будет пытаться выполнить трехстороннее слияние, если необходимо,использование хэшей больших двоичных объектов в строке index
в diff. В некоторых условиях кажется, что может быть достаточным для обработки переименованных файлов, в частности, если хэш больших двоичных объектов точно совпадает. Метод cherry-pick делаетполное обнаружение переименования, которое обрабатывает неточные совпадения; -3
не может этого сделать. См. также В чем разница между git cherry-pick и git format-patch | git am? , как отметил Юрген .)