Вероятно, это связано с конфликтом исходного слияния.(Я не могу доказать , что это так, если у вас нет доступа к хранилищу и его коммитам.)
То, что вы видите, является побочным эффектом того факта, что иногда git rebase
может избегать некоторых или всех копий, а когда он может и действительно избегает всех копий, в конечном итоге он вообще ничего не делает.Бездействие означает отсутствие фиксации слияния, но «копирование» слияния, ранее имевшего конфликт слияния, означает, что вы снова видите такой же конфликт слияния.
Эту проблему можно обойти с помощью git rerere
(и сценарий rerere-train
, возможно: см. Разумная перебазировка, позволяющая избежать избыточной работы? ).
Long
Помните, что git rebase
работает путем копирования фиксирует.Простая интерактивная перебазировка начинается с перечисления всех коммитов для копирования с использованием pick
команд для каждого такого коммита.Этот простой вид rebase отбрасывает слияния.Добавление --rebase-merges
(или -r
) говорит о том, что сохраняет слияния вместе с исходным расположением коммитов. Но во всей этой концепции есть недостаток: хотя можно копировать коммит без слияния, не можно скопировать коммит слияния.
Что git rebase -r
(и его более старый, более бедный git rebase -p
кузен) делают вместо этого, потому что они не могут копировать слияния, повторно выполнить слияния при необходимости.То есть, после копирования некоторого количества старых коммитов в новые, с новыми и разными хеш-идентификаторами, они достигают момента, когда пора «копировать» слияние, и вместо этого они просто запускают git merge
напрямую.
Например, учитывая:
C--D
/ \
A--B G--H <-- source (HEAD)
/ \ /
/ E--F
/
...--o--o--*--o--o <-- target
и запрос командной строки git rebase -r target
сгенерирует серию команд pick
, label
, reset
и merge
длякопия A
, B
, C
, D
, E
и F
;затем объедините the copies of
D and
F ; then copy
G and
H`, чтобы получить:
C--D
/ \
A--B G--H <-- [abandoned]
/ \ /
/ E--F
/
...--o--o--*--o--o <-- target
\
\ C'-D'
\ / \
A'-B' G'-H' <-- source (HEAD)
\ /
E'-F'
, где commit A'
является копией A
, B'
является копией B
и т. д.
Но, с опцией -r
или без нее, рассмотрим операцию перебазирования, которая начинается с:
...--I--J <-- target
\
K--L <-- source (HEAD)
Теперь вы спрашиваете Gitчерез git rebase
скопировать коммит K
в новый улучшенный K
, который точно такой же, как K
, за исключением того, что он идет после J
, а не после J
.Затем вы говорите Git скопировать L
, чтобы вместо «1083» он шел после новой копии K
.
Git понимает, что существующая копия K
, который идет после J
, уже идет сразу после J
.Таким образом, «копия», которую нужно сделать, уже существует: git rebase
просто повторно использует K
напрямую.Теперь он должен скопировать L
после K
, но посмотрите: L
уже идет сразу после K
, поэтому Git просто повторно использует L
напрямую.В результате ничего не меняется.(Если по какой-то причине - и по некоторым причинам - вы действительно хотите Git для копирования K
, в любом случае, вы можете использовать --force-rebase
или --no-ff
или -f
, все из которых делаютто же самое.)
Если вы запустите эту же перезагрузку, обязательно используя интерактивный режим, и используйте reword
на K
, теперь Git действительно делает необходимо скопировать K
в новый K'
, который похож на K
, но имеет другое сообщение о коммите.В результате Git теперь действительно должен скопировать L
, чтобы он шел после нового K'
с новым сообщением.Результат:
K'-L' <-- source (HEAD)
/
...--I--J <-- target
\
K--L [abandoned]
Для простого линейного случая, подобного этому, ребазирование всегда проходит гладко, но когда вы добавляете -r
к миксу, вынуждаете Git «копировать» (т.е.-производить) слияние, если исходное слияние имело конфликты, то будет и новое слияние.