Git Rebase Conflict: кто такой HEAD?

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

git checkout experimentalbranch
git fetch remoterepo
git rebase remoterepo/developmentbranch

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

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

2 ответа

Решение

TL;DR (добавлено в мае 2018 г.)

Все это, по крайней мере, немного сбивает с толку, потому что Git позволяет понять всю его внутреннюю работу.

Обратите внимание, что случаи, которые нас интересуют, возникают при запуске:

git checkout somebranch; git rebase origin/their-branch

или похожие. Перебазирование временно приостановлено, чтобы заставить вас разрешить конфликт слияния, после чего вы должны git add разрешенный конфликт и бежать git rebase --continue, (Если вы используете какой-либо инструмент слияния с git mergetool или причудливый интерфейс с графическим интерфейсом, этот интерфейс может сделать некоторые или все это для вас каким-то другим способом, но под git add в разрешенных файлах и работает git rebase --continue.)

В самом начале HEAD commit это их ветка, так что если вы используете git checkout --ours или же git checkout --theirs, --ours означает их - окончательное совершение origin/their-branch -в то время как --theirs означает твой, первый коммит ты перебазируешь. Это обычная повседневная путаница в Git (см. Что означает "наши" и "их" в git?), И это не то, что привело к первоначальному вопросу.

Позже, однако, HEAD коммит на самом деле является своего рода смесью. Это результат копирования некоторого количества ваших коммитов поверх их последнего коммита. Теперь вы сталкиваетесь с конфликтом между вашими новыми частями коммитов и вашими оригинальными коммитами. Источником этого конфликта обычно является то, что "они" сделали (что-то, что изменилось по пути в origin/their-branch). Вы все еще должны разрешить этот конфликт. Когда вы это сделаете, вы можете увидеть тот же самый конфликт, повторяющийся в последующих коммитах.

Снова, HEAD или же local или же --ours это коммит, созданный rebase путем объединения ваших изменений и их изменений и другого коммита (remote или же >>>>>>> или же --theirs) это ваш собственный коммит, который rebase пытается скопировать поверх HEAD,

дольше

При слиянии (включая перебазирование, которое является частным случаем повторного "слияния" внутри), присутствуют две "головы" (две конкретные ветви). Давайте назовем это 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 ссылаться на два главных коммита во время слияния, при этом "наш" - тот, на котором вы были (коммит H) когда ты побежал git merge и "их" существо, ну их L). Но когда вы делаете ребаз, две головы меняются местами, так что "наша" - это голова, на которую вы перебазируете, то есть их обновленный код, а "их" - это коммит, который вы в настоящее время опровергаете, т. е. ваш собственный код.

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

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

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

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

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

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

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

Однажды копия G существует, хотя, HEAD движется к G' и git пытается скопировать изменения из H таким же образом G против H затем F против 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 от коммита H и указывает на то, чтобы совершить H' вместо:

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

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

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

Определения

В этом разделе мы увидим недостатки, которые нам задают в ответ:

Кто глава?

HEAD: текущий коммит вашего репо включен. В большинстве случаев HEAD указывает на последний коммит в вашей ветке, но это не обязательно так. HEAD на самом деле просто означает "на что сейчас указывает мой репо".

В случае, если совершить HEAD относится не к вершине какой-либо ветви, это называется " detached head ".

Это руководитель отдела развития?

В момент, когда производится слияние или перебазирование HEAD немедленно переходит к указателю на созданный или реорганизованный коммит и, следовательно, будет указывать на ветку разработки.

В git bash мы можем увидеть HEAD ситуация, листинг коммит:

# Normal commit list
git log
# List of commit in a single line
git log --oneline 
# All commits graphically-linear (Recommended as alias)
git log --all --graph --decorate --oneline

практика

В этом разделе мы увидим, как _how_ работает некоторые действия, выполняемые пользователем.

Когда пользователь переходит к:

# Command to change from the branch to the current one to experimentalbranch
git checkout experimentalbranch
# Command that traverses the typical workflow to synchronize its local repository with the main branch of the central repository (remoterepo)
git fetch remoterepo
# git fetch origin
# git fetch origin branch:branch
# With the command git rebase, you can take all the changes confirmed in one branch (remoterepo), and reapply them over another developmentbranch
git rebase remoterepo/developmentbranch

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

Объединение ветвей осуществляется двумя способами:

  • мерзавец слияния

  • git rebase.

Примечание:

Для примеров мы будем использовать следующее дерево:

* a122f6d (HEAD -> remoterepo) Commit END
* 9667bfb Commit MASTER
| * b9bcaf0 (origin/experimentalbranch, experimentalbranch) Commit 3
| * 110b2fb Commit 2
| * e597c60 Commit 1
|/
* 0e834f4 (origin/remoterepo) First commit

мерзавец слияния

Самая известная форма git merge, который выполняет объединение трех полос между двумя последними снимками каждой ветви и общим предком обоих, создавая новый коммит со смешанными изменениями.

Например:

git checkout remoterepo
git merge experimentalbranch

Это произвело бы нас:

*   003e576 (HEAD -> remoterepo) Merge branch 'experimentalbranch' in remoterepo
|\
| * b9bcaf0 (origin/experimentalbranch, experimentalbranch) Commit 3
| * 110b2fb Commit 2
| * e597c60 Commit 1
* | a122f6d Commit END
* | 9667bfb Commit MASTER
|/
* 0e834f4 (origin/remoterepo) First commit

мерзавец

git rebase в основном он собирает поочередно подтвержденные изменения в одной ветви и повторно применяет их в другой.

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

Например:

git checkout remoterepo
git rebase experimentalbranch


* f8a74be (HEAD -> remoterepo) Commit END
* 4293e9d Commit MASTER
* b9bcaf0 (origin/experimentalbranch, experimentalbranch) Commit 3
* 110b2fb Commit 2
* e597c60 Commit 1
* 0e834f4 (origin/remoterepo) First commit

Каково происхождение?

origin: имя по умолчанию, которое git дает вашему главному удаленному репо. У вашего ящика есть свое собственное репо, и вы, скорее всего, продвигаетесь к какому-либо удаленному репо, к которому вы и все ваши коллеги продвигаетесь. Это удаленное хранилище почти всегда называется источником, но это не обязательно.

Другие вопросы по тегам