Как мне восстановить / повторно синхронизировать после того, как кто-то отправил перебазирование или сброс в опубликованную ветку?
-
28-09-2019 - |
Вопрос
Мы все слышали, что никогда не следует переделывать опубликованные работы, что это опасно и т.д.Однако я не видел опубликованных рецептов того, как справиться с ситуацией в случае перебазирования является опубликовано.
Теперь обратите внимание, что это действительно возможно только в том случае, если репозиторий клонирован только известной (и предпочтительно небольшой) группой людей, так что тот, кто запускает перебазирование или сброс, может уведомить всех остальных, что им нужно будет обратить внимание при следующей загрузке (!).
Одно очевидное решение, которое я видел, будет работать, если у вас нет локальных коммитов на foo
и он будет перебазирован:
git fetch
git checkout foo
git reset --hard origin/foo
Это просто отбросит локальное состояние foo
в пользу его истории в соответствии с удаленным репозиторием.
Но как справиться с ситуацией, если кто-то внес существенные локальные изменения в эту ветку?
Решение
Возвращаясь в синхронизацию после того, как нажатой ребазе на самом деле не так сложно в большинстве случаев.
git checkout foo
git branch old-foo origin/foo # BEFORE fetching!!
git fetch
git rebase --onto origin/foo old-foo foo
git branch -D old-foo
Т.е. Сначала вы настроили закладку, где изначально была удаленная ветвь, затем вы используете это, чтобы воспроизвести свои локальные коммиты с этого момента на протяжении всей удаленной ветви.
Ресирование похоже на насилие: если это не решает вашу проблему, вам просто нужно больше этого. ☺.
Вы можете сделать это без закладки, конечно, если вы посмотрите на добеду origin/foo
Примите удостоверение личности и используйте это.
Это также как вы занимаетесь ситуацией, когда вы забыли сделать закладку до забрать. Ничего не потеряно - вам просто нужно проверить Refricge для удаленной ветви:
git reflog show origin/foo | awk '
PRINT_NEXT==1 { print $1; exit }
/fetch: forced-update/ { PRINT_NEXT=1 }'
Это будет распечатать идентификатор фиксации, который origin/foo
указал до самой последней приемы, которая изменила свою историю.
Вы можете просто просто
git rebase --onto origin/foo $ Commit. foo
Другие советы
Я бы сказал Восстановление из Upstream Rabase Раздел страницы человека GIT-REBASE охватывает в значительной степени все это.
Это действительно не отличается от восстановления от вашей собственной ребазы - вы перемещаете одну ветку и передайте все ветви, которые имели его в своей истории на свою новую позицию.
Начиная с git 1.9 / 2.0 Q1 2014, вам не нужно будет отмечать источник вашей предыдущей ветви перед ее повторным размещением в перезаписанной восходящей ветви, как описано в Аристотель Пагальцис's ответ:
Видишь фиксация 07d406b и зафиксировать d96855f :
После работы над
topic
ветвь, созданная с помощьюgit checkout -b topic origin/master
, история филиала удаленного отслеживанияorigin/master
возможно, они были перемотаны назад и перестроены заново, что привело к появлению истории такой формы:
o---B1
/
---o---o---B2--o---o---o---B (origin/master)
\
B3
\
Derived (topic)
где
origin/master
используется для указания на коммитыB3
,B2
,B1
и теперь он указывает наB
, и вашtopic
ветка была начата поверх него еще тогда, когдаorigin/master
был вB3
.В этом режиме используется повторный журнал
origin/master
чтобы найтиB3
в качестве точки развилки, так чтоtopic
может быть переустановлен поверх обновленногоorigin/master
Автор::
$ fork_point=$(git merge-base --fork-point origin/master topic)
$ git rebase --onto origin/master $fork_point topic
Вот почему git merge-base
у команды появилась новая опция:
--fork-point::
Найдите точку, в которой ветвь (или любая история, ведущая к
<commit>
) разветвленный из другой ветви (или любой ссылки)<ref>
.
Это не просто поиск общего предка двух коммитов, но также учитывается повторный журнал<ref>
чтобы увидеть, ведет ли история к<commit>
разветвленная от более раннего воплощения ветви<ref>
.
Тот самый "
git pull --rebase
" команда вычисляет точку разветвления перебазируемой ветви, используя записи reflog из "base
" ветвь (обычно ветвь с удаленным отслеживанием), на которой была основана работа ветви, чтобы справиться со случаем, в котором "базовая" ветвь была перемотана и перестроена заново.
Например, если история выглядела так, где:
- текущий наконечник "
base
" филиал находится вB
, но ранее fetch заметил , что его кончик раньше былB3
а потомB2
а потомB1
прежде чем перейти к текущему коммиту, и- ветвь, переназначаемая поверх последней "базы", основана на фиксации
B3
,он пытается найти
B3
пройдя через выходные данные "git rev-list --reflog base
" (т.е.B
,B1
,B2
,B3
) до тех пор , пока он не найдет коммит, который является предком текущего tip " .Derived (topic)
".Внутренне мы имеем
get_merge_bases_many()
который может вычислить это за один раз.
Мы бы хотели, чтобы база слияния междуDerived
и фиктивная фиксация слияния, которая привела бы к объединению всех исторических подсказок "base (origin/master)
".
Когда такая фиксация существует, мы должны получить единственный результат, который в точности соответствует одной из записей reflog "base
".
Git 2.1 (3 квартал 2014) добавит, сделает эту функцию более надежной для этого:видишь зафиксировать 1e0dacd Автор: Джон Кипинг (johnkeeping
)
правильно обработайте сценарий, в котором у нас есть следующая топология:
C --- D --- E <- dev
/
B <- master@{1}
/
o --- B' --- C* --- D* <- master
где:
B'
является исправленной версиейB
это не патч, идентичныйB
;C*
иD*
идентичны ли патчиC
иD
соответственно и конфликтуют текстуально, если применяются в неправильном порядке;E
текстуально зависит отD
.
Правильный результат git rebase master dev
это что B
идентифицируется как точка развилки dev
и master
, так что C
, D
, E
есть ли коммиты, которые необходимо воспроизвести master
;но C
и D
идентичны ли патчи с C*
и D*
и поэтому может быть отброшен, так что конечным результатом будет:
o --- B' --- C* --- D* --- E <- dev
Если точка развилки не определена, то сбор B
на ветку , содержащую B'
приводит к конфликту, и если коммиты, идентичные патчу, неправильно идентифицированы, то выбор C
на ветку , содержащую D
(или эквивалентно D*
) приводит к конфликту.