Объединение ветвей, последний общий предок которых был затронут перемещением - PullRequest
0 голосов
/ 01 августа 2020

У меня есть ветка master и ветвь topic, которые расходились с master в какой-то фиксации «последнего общего предка».

Я переписал историю в своей основной ветке, используя git rebase, но забыл, что это включало фиксацию, которая была «последним общим предком» с моей веткой topic. Другими словами, если я теперь git log ветвь master, она больше не перечисляет фиксацию «последнего общего предка» с topic.

Я предполагаю, что «последний общий предок» зафиксирован сборщик мусора еще не прошел, так как на него все еще ссылается ветка topic. Но он больше не является частью ветки master.

Что произойдет, если я сейчас попытаюсь объединить topic с master?

Ответы [ 3 ]

2 голосов
/ 01 августа 2020

Для подобных вещей, я считаю, помогает рисовать коммиты. Конечно, поскольку вы не можете найти точную фиксацию, вы застрянете в рисовании некоторого приближения, но, возможно, это поможет вам найти правильные фиксации.

У меня есть ветка 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 ...).

2 голосов
/ 01 августа 2020

Я предлагаю вам переустановить topi c поверх нового мастера, используя флаг --onto. Вам нужно будет указать точку topic, отличную от мастера. Найдите «последнего общего предка», я назову его abcd. Теперь сделайте следующее:

git rebase --onto master abcd

EDIT: только что понял, что вы сказали, что не можете найти эту фиксацию. Это очень странно. Попробуйте перейти к последней фиксации на topic, а затем следуйте за родителями, пока не найдете эту фиксацию. Он должен где-то быть. Попробуйте использовать git rev-list --parents topic

1 голос
/ 01 августа 2020

Я уверен, что в ответе Торека будут все подробности ... вот мой короткий ответ: найдите как новый, так и старый идентификатор той ревизии, которая была общим предком.

git rebase --onto new-id old-id topic

То есть чтобы получить ветку в позиции, где она была .... но могла также запустить

git rebase --onto master old-id topic

Чтобы поместить ее поверх новой основной ветки

...