Редактировать: клонирование хранилища подтверждает правильность теории;см. приложение ниже.
Проблема здесь в том, что rebase решил, что коммиты являются избыточными.В частности, git rebase
(с или без -i
) будет пропускать коммиты, которые имеют восходящий коммит, «эквивалентный патчу».
То есть предположим, что у нас есть:
...--F--G--H2--J2--K <-- upstream
\
H--I--J <-- branch
Здесь, если мы попросим Git перебазировать branch
на upstream
, Git обычно скопирует коммиты H
, затем I
, затем J
, чтобы новые копии шли после коммита K
:
H3--I2--J3 <-- branch
/
...--F--G--H2--J2--K <-- upstream
\
H--I--J [abandoned]
Однако, пока Git готовит список хеш-идентификаторов коммитов для копирования, он делает что-то немного хитрое: для каждого коммита H
, I
и J
он проверяет, есть лииз коммитов только для восходящего потока - здесь H2
, J2
и K
- имеют те же git patch-id
, что и коммиты H
, I
или J
:
git show <hash> | git patch-id
более или менее (попробуйте это, чтобы увидеть, как это работает, хотя это не совсем удобно для пользователя).
Если, как я подразумеваю под именами H2
и J2
, некоторые изУ коммитов есть апстрим, который «делает то же самое», процесс ребазирования будет отбрасывать этих коммитов.В этом случае, поскольку H
уже реплицируется H2
, а J
уже реплицируется J2
, фактическая перебазировка будет производить:
I2 <-- branch
/
...--F--G--H2--J2--K <-- upstream
\
H--I--J [abandoned]
Это, похоже, то, что вы наблюдаете,Это немного странно, так как это означает, что коммиты C4
и C5
должны иметь одинаковый идентификатор патча - на b1
есть только один восходящий коммит, а именно C6
.Их можно удалить, только если они оба имеют одинаковые идентификаторы патчей и , которые совпадают с идентификаторами патчей C6
.
(Очевидно, идентификатор патчей C7
отличается,Таким образом, ребаз сохраняет все коммиты.)
Приложение
$ git clone https://gist.github.com/arzyu/9c4a50257bd2be18ed1e9774b7600070 gri
$ git show master~3..master | git patch-id
c711e5dfe43107af9bcff6c00bed4211d3b60cf6 166caa401ede4f97841a2715a80b4d26c40c50b8
c711e5dfe43107af9bcff6c00bed4211d3b60cf6 27bb50839ee73bce4cbb97089306c5dfa04c4516
2ee54397f45e5f955fc7b5b6717544e526818ede 63aed5a10cf22e1dd1ba699dac9104f3605a3751
Хеш-идентификаторы слева - это идентификаторы патчей, а хэш-идентификаторы справа - это идентификаторы коммитов (для C3, C4 и C5 соответственно).Например:
$ git show master~2
commit 63aed5a10cf22e1dd1ba699dac9104f3605a3751
Author: arzyu <arzyu@live.cn>
Date: Mon Dec 17 17:17:01 2018 +0800
C3
diff --git a/test.txt b/test.txt
index 4b87763..a25c784 100644
--- a/test.txt
+++ b/test.txt
@@ -1,2 +1,4 @@
//
//
+
+//
Два совпадают с хэш-идентификатором кончика b1
:
$ git show origin/b1 | git patch-id
c711e5dfe43107af9bcff6c00bed4211d3b60cf6 be5dd192f9bed20036491915766be61d66eec8aa
$ git show origin/b1
commit be5dd192f9bed20036491915766be61d66eec8aa (origin/b1)
Author: arzyu <arzyu@live.cn>
Date: Mon Dec 17 17:19:09 2018 +0800
C6
diff --git a/test.txt b/test.txt
index 4b87763..b8e0885 100644
--- a/test.txt
+++ b/test.txt
@@ -1,2 +1,3 @@
//
//
+//
Поскольку все три коммита имеют идентификатор патча c711e5dfe43107af9bcff6c00bed4211d3b60cf6
, git rebase
опускает два, которые иначе были бы скопированы.
Идентификатор патча коммита, как git patch-ID
документация говорит:
ничего, кромесумма SHA-1 различий в файлах, связанных с патчем, с пропуском пробелов и номеров строк.
Поскольку все три патча просто , добавьте строку, состоящую из //
все они имеют одинаковые идентификаторы патчей, и Git предполагает, что он делает правильные вещи, когда пропускает их для перебазирования.