Очиститель находится в глазу (или руках?) Наблюдателя / работника, но вы можете использовать git rebase --onto
, чтобы отделить , который обязуется скопировать из , гдечтобы поместить копии .
Помните, что git rebase
означает: 1 У меня есть линейная цепочка коммитов, как показано на рисунке 1, которую я хотел бы скопироватьна новую линейную цепочку коммитов, как показано на рисунке 2. Как только копии будут сделаны, я бы хотел, чтобы имя моей ветви указывало на последний скопированный коммит.Оригинальная цепочка A-B-C
больше не нужна, даже если она все еще там.
[drawing 1]
...--o--*--o <-- upstream/master
\
A--B--C <-- topic
[drawing 2]
...--o--*--o <-- upstream/master
\
A'-B'-C' <-- topic
Различия между оригинальными коммитами и копиями заключаются в том, что оригиналы основаны на коммите *
, который был верхушкой upstream/master
раньше.Копии основаны на (новом) наконечнике upstream/master
.Фраза на основе здесь имеет буквально два значения: родитель commit A
- это commit *
, а parent commit A'
- этоболее поздняя фиксация, и снимок в commit A
равен *
-plus-some-changes, тогда как снимок в commit A'
добавляет то же самое изменения позже коммита.
Поскольку мы используем наш новый блестящий коммит A'
(который имеет другой хэш) в пользу старого скучного A
, нам нужно скопироватьB
до B'
и C
до C'
, и как только мы закончим, нам нужно, чтобы наше имя topic
указывало не на C
, а на последний скопированный коммит C'
.
Обычный старый git rebase
делает именно это.Мы говорим:
git checkout topic; git rebase upstream/master
, что говорит Git:
- Перечислять все коммиты, начиная с
C
и работая в обратном направлении. Это C
затем B
, затем A
, затем *
, затем все до *
. - Перечислите все коммиты, начиная с
upstream/master
и работая в обратном направлении. Это второй o
, затем*
, а затем все до *
. - Вычеркните все из списка second из списка first . Так, что выбиваетout
*
и все предыдущие коммиты.Второго o
нет в первом списке, но это нормально: мы бы выбили его, если бы оно было , но это не так, мы ничего не делаем.Наш список теперь идет C
, B
и A
. - Переверните список, чтобы упорядочить его в правильном порядке, затем по одному копируйте каждый коммит в новыйместо.Новое место начинается с коммита, на который
upstream/master
указывает. Таким образом, это копирует A
в A'
, B
в B'
и C
в C'
. - Снимите текущее имя ветки
topic
со своего предыдущего местоположения и прикрепите его к новой цепочке коммитов, как обычно в конце. Так что topic
указывает на C'
вместоC
.
В вашем новом случае, однако, вы имели:
...--o--* <-- upstream/master
\
A--B--C <-- feature1
\
D--E--F--G <-- feature2
Они, в своем верхнем течении, не взяли вашу A-B-C
цепочку.Вместо этого они сделали свой собственный коммит ABC
сквош.Вы взяли его из верхнего хранилища, и теперь у вас есть:
...--o--*--ABC <-- upstream/master
\
A--B--C <-- feature1
\
D--E--F--G <-- feature2
Если вы просто запустите git checkout feature2; git rebase upstream/master
, ваш Git будет перечислять коммиты G-F-E-D-C-B-A-*-...
, перечислять ABC-*-...
, вычитать второе из первогои оставьте инструкции по копированию цепочки G-F-E-D-C-B-A
.
Командой сбитого любителя:
git checkout feature2
git rebase --onto upstream/master feature1
То, что это делает, является отдельным аргументом target -место, где Git начнет копирование - из аргумента limit . target теперь upstream/master
(документация Git называет это аргументом to ).Аргумент limit теперь feature1
.Вы можете использовать необработанный хэш-идентификатор commit C
, если хотите.Git просто нужно знать: С чего мне начать перечисление «нокаут-эти-коммиты»? (В документации по Git этот аргумент называется upstream .)
Как вы можете видеть, это теперь выбивает коммиты C-B-A-*
, а не просто *
, так что после копирования вы получите:
D'-E'-F'-G' [in progress]
/
...--o--*--ABC <-- upstream/master
\
A--B--C <-- feature1
\
D--E--F--G <-- feature2
и теперь Git может очистить ярлык feature2
с G
и прикрепить вместо него G2
.
1 Технически, есть гораздо больше git rebase
, особенно теперь с новой модной опцией --rebase-merges
.Это У меня есть линейная цепочка коммитов все еще ее основное использование, хотя.
Как хороший бонус, ребаз обычно может сказать, взяли ли они ваш A-B-C
цепи и скопировал его в собственную A'-B'-C'
цепь.Но это просто обычно .Rebase может никогда сказать, что они взяли ваш A-B-C
и раздавили его до своего ABC
, поэтому в этом случае вы застряли с --onto
.