Ответ 1
Моя рекомендация (или, "что бы я сделала, если бы была мистер Ориндж" ), начинаем с git fetch
. Теперь у меня будет это в моем репо, что и было у мистера Блонда после его перезагрузки и перед тем, как он побежал "git push -f".
M1 - M2 - M3
\ \
\ \
A1 - A2 A1' - A2'
Единственное важное отличие: у меня будет локальная метка A
, указывающая на rev A2, и удаленная метка remotes/origin/A
, указывающая на A2 '(г-н Блонд имел это наоборот, локальная метка A
указывая на A2 'и remotes/origin/A
, указывающие на A2).
Если я работаю над своей копией ветки с именем "А", у меня будет это:
M1 ---- M2 ---- M3
\ \
\ \
A1 - A2 - A3 A1' - A2'
(с моей локальной меткой, указывающей на A3, а не на A2 или A4 или A5 и т.д., в зависимости от того, сколько изменений я применил.) Теперь мне нужно только перезагрузить мой A3 (и, если необходимо, A4) на A2 '. Один очевидный прямой путь:
$ git branch -a
master
* A
remotes/origin/master
remotes/origin/A
$ git branch new_A remotes/origin/A
$ git rebase -i new_A
а затем полностью отбрасывать обороты A1 и A2, так как модифицированные находятся в new_A как A1 'и A2'. Или:
$ git checkout -b new_A remotes/origin/A
$ git format-patch -k --stdout A3..A | git am -3 -k
(метод git am -3 -k
описан на странице руководства git-format-patch
).
Они требуют выяснить, что у меня есть, что мистер Блонд не сделал, прежде чем он сделал свой rebase
, то есть идентифицировал A1, A2, A3 и т.д.
Если второй подход успешный, я получаю:
M1 ---- M2 ---- M3
\ \
\ \
A1 - A2 - A3 A1' - A2' - A3'
где мое имя ветки new_A
указывает на A3 '(моя существующая ветка A
все еще указывает на старый A3). Если я использую первый подход, и он преуспеет, я получаю то же самое, просто мое существующее имя ветки A
теперь будет указывать на A3 '(и у меня нет имени старой ветки с A1-A2-A3, даже несмотря на то, что он все еще находится в моем репо, поэтому для его поиска требуется просмотр журналов или подобных).
(Если мой A3 нуждается в модификации, чтобы стать A3 ', как интерактивная rebase, так и метод git am), конечно, потребуют меня.)
Конечно, также возможно просто git merge
(как в ответе Гэри Фикслера), но это создаст слияние ( "М" без номера ниже) и сохранит обороты A1 и A2, что дает:
M1 ---- M2 ---- M3
\ \
\ \
A1 - A2 - A3 A1' - A2' -- M
\_______________/
Если вы хотите сохранить оригинальные A1 и A2, это хорошо; если вы хотите избавиться от них, это плохо. Поэтому "что делать" зависит от того, "что вы хотите, чтобы результат был".
Изменить для добавления: мне нравится метод format-patch лучше, поскольку он оставляет мое имя ветки A, пока я уверен, что все хорошо. Предполагая, что все это работает и хорошо, вот последние несколько шагов:
$ git branch -m A old_A
$ git branch -m new_A A
а затем, если old_A можно полностью отбросить:
$ git branch -D old_A
или, что то же самое, начните с удаления ветки, а затем переименуйте new_A в A.
(Редактировать: см. также документацию git rebase --onto
, для цели переадресации A3 и т.д.) на ветку new_A.)