Подтвердить что ты не робот

Git Rebase Conflict: Кто есть ГОЛОВА?

У меня есть этот проект, в котором удаленное репо имеет основную ветвь развития, и у меня есть вилка, содержащая экспериментальную ветвь. Мне нужно, чтобы изменения rebase от ветки разработки до моей экспериментальной ветки до того, как я надавил на свою вилку. Итак, это выглядит так:

git checkout experimentalbranch
git fetch remoterepo
git rebase remoterepo/developmentbranch

К этому моменту я столкнулся с конфликтами. Тем не менее, я не знаком ни с одним из этих изменений (я перестраиваю изменения недель, потому что они не сразу меняют мои изменения). Кроме того, это мой первый раз делать rebase. Я больше привык к merge.

В meld обычно это как <<LOCAL||REMOTE>> для merge, что звучит очень интуитивно. Но в rebase оно <<HEAD||COMMIT MESSAGE>>. Кто HEAD? Это HEAD ветки разработки? Это последний код в ветке разработки или где-то еще?

4b9b3361

Ответ 1

При слиянии (включая перезагрузку, что является частным случаем повторного "слияния" внутри), есть два "головы" (два конкретных ответвления). Назовите эти your-branch и origin/their-branch:

              G - H --------      <-- HEAD=your-branch
            /               \
... - E - F                   M   <-- desired merge commit [requires manual merge]
            \               /
              I - J - K - L       <-- origin/their-branch

Эта точка обычно (и неудивительно) запутывает, хотя, когда она помечена как это, достаточно ясно.

Ухудшись, однако, git использует --ours и --theirs для обозначения двух головных коммиттов во время слияния, причем "наш" является тем, на котором вы были (commit H), когда вы запускали git merge, а "их" - это, ну, их (commit L). Но когда вы делаете переустановку, обе головы меняются на противоположные, так что "наш" - это голова, которую вы перегружаете, т.е. Их обновленный код и "их" - это фиксация, которую вы в настоящее время перезагружаете, т.е. собственный код.

Это связано с тем, что rebase фактически использует серию операций вишневого захвата. Вы начинаете с той же картины:

              G - H           <-- HEAD=your-branch
            /
... - E - F
            \
              I - J - K - L   <-- origin/their-branch

Что нужно сделать git здесь, чтобы скопировать эффект коммитов G и H, т.е. git cherry-pick commit G, а затем сделать это снова с commit H. Но для этого git должен сначала переключиться на фиксацию L, внутренне (используя режим "снятый HEAD" ):

              G - H           <-- your-branch
            /
... - E - F
            \
              I - J - K - L   <-- HEAD, origin/their-branch

Теперь он может запустить операцию перезаписи, сравнивая деревья для commits F и G (чтобы увидеть, что вы изменили), а затем сравните F vs L (чтобы убедиться, что часть вашей работы уже в L) и вносите любые изменения, еще не находящиеся в L, и добавьте их. Это операция "слияния" внутри.

              G - H           <-- your-branch
            /
... - E - F                   G'   <-- HEAD
            \               /
              I - J - K - L   <-- origin/their-branch

Если слияние не идет хорошо, HEAD остается в commit L (поскольку commit G' еще не существует). Таким образом, да, HEAD является главой своей ветки развития - по крайней мере, сейчас.

Как только существует копия G, HEAD перемещается в G' и git пытается скопировать изменения из H таким же образом (diff G vs H, то diff F vs G' и объединить результаты):

              G - H           <-- your-branch
            /
... - E - F                   G' - H'   <-- HEAD
            \               /
              I - J - K - L   <-- origin/their-branch

Опять же, если слияние не удалось и вам нужна помощь, вы останетесь с HEAD, указывающим на G' вместо H', поскольку H' еще не существует.

Как только слияния всех преуспевают и совершают G' и H' существуют, git удаляет метку your-branch из commit H и вместо этого указывает на commit H':

              G - H
            /
... - E - F                   G' - H'   <-- HEAD=your-branch
            \               /
              I - J - K - L   <-- origin/their-branch

и вы теперь переустановлены, а HEAD - это снова то, что вы ожидаете. Но во время rebase HEAD - это либо их ответвление (commit L), либо один из новых коммитов, скопированных и присоединенных к их ветки; и --ours означает, что ветвь вырастает в конце L, а --theirs означает скопированную фиксацию - из (G или H выше).

(В основном это git, демонстрирующий необработанный механизм того, как он делает то, что он делает, что довольно часто происходит в git.)