Для подобных вещей, я считаю, помогает рисовать коммиты. Конечно, поскольку вы не можете найти точную фиксацию, вы застрянете в рисовании некоторого приближения, но, возможно, это поможет вам найти правильные фиксации.
У меня есть ветка master
и ветвь topic
, которая отошла от master
в каком-то коммите «последнего общего предка».
Итак, давайте нарисуем это как своего рода грубый набросок:
...--c1--c2--c3--c4--m1--...--mn <-- master
\
t1--...--tn <-- topic
, где коммиты c
являются общими для обеих веток, коммиты m
только master
, а коммиты t
только topic
. Фиксация c4
- последняя общая.
Я переписал историю в своей основной ветке, используя git rebase
, но забыл, что это включает фиксацию, которая была «последним общим предком» с моим topic
филиал. Другими словами, если я сейчас git log
master branch
, я больше не смогу найти идентификатор фиксации «последнего общего предка» фиксации с topic
.
Так как rebase работает по копирование коммитов, затем перемещение имени ветки, чтобы указывать на последний скопированный коммит, давайте нарисуем это сейчас, используя суффиксы '
для отображения скопированных коммитов:
c2'-c3'-c4'-m1'-...--mn' <-- master
/
...--c1--c2--c3--c4--m1--...--mn [abandoned]
\
t1--...--tn <-- topic
Пока вы можно использовать git log
на topic
, чтобы найти фиксацию c4
, на самом деле общий с master
больше не
Я предполагаю коммит «последнего общего предка» еще не был обработан сборщиком мусора, поскольку на него все еще ссылается ветвь topic
. Но он больше не является частью ветки master
.
Совершенно верно: в то время как m1-...-mn
«заброшены», c4
не . (Обратите внимание, что идентификаторы ha sh этих коммитов, вероятно, присутствуют как минимум в двух журналах рефлога: один для master
и один для HEAD
. Эти записи рефлога будут поддерживать коммиты до истечения срока действия самих записей рефлога. )
Что произойдет теперь, если я сейчас попытаюсь объединить topic
с master
?
Операция слияния найдет первую действительно распространенную фиксацию, которая теперь c1
, и сравните содержимое c1
(его снимок) с содержимым mn
(подсказка мастера), чтобы увидеть, что вы изменили на master
, затем сравните c1
с tn
на посмотрите, что вы изменили на topic
. Затем он объединит два изменения и, в случае успеха, самостоятельно сделает коммит слияния:
c2'-c3'-c4'-m1'-...--mn'
/ \
...--c1--c2--c3--c4 M <-- master (HEAD)
\ /
t1--...--tn <-- topic
(Заброшенные коммиты все еще там, если они не были G C -ed , но они мешали, поэтому я перестал их рисовать.) A git log
of master
теперь будет показывать дублированные c4
-and- c4'
коммиты, c3
-and- c3'
и т. on.
Чтобы их устранить, найдите c4
и c4'
с помощью некоторого процесса - например, вручную git log
и на глаз, или используя git cherry
, или используя git log --left-right --cherry-mark topic...master
, или как угодно. Как только вы узнаете, где находятся c4
и c4'
, вы можете использовать команду Омер предложил :
git checkout topic
git rebase --onto master <hash-of-c4>
(или даже просто поместите topic
в конец git rebase
, но я предпочитаю этого не делать - сложно начинать на master
и заканчивать topic
...).