Вопрос по git – Как определяются BASE (или «предок»), LOCAL и REMOTE в конфликте Git cherry-pick или rebase merge merge?

26

В обычном конфликте слияния Git три версии файла для воспроизведения для трехстороннего слияния примерно таковы:

LOCAL: the version from my branch REMOTE: the version from the other branch BASE: the version from the common ancestor of the two branches (in particular, the common ancestor of my branch's HEAD and the other branch's HEAD)

Когда Git cherry-pick выбирает конфликт слияния, то, собственно говоря, общего предка нет, так как же эти вещи определяются? То же самое можно спросить о ребазе.

Ваш Ответ

1   ответ
35

cherry-pick

Если я не введу себя в заблуждение, то если вы выполните git cherry-pick & lt; commit C & gt; & quot ;, то вы получите:

  • LOCAL: the commit you're merging on top of (ie the HEAD of your branch)
  • REMOTE: the commit you're cherry picking (i.e. <commit C>)
  • BASE: the parent of the commit you're cherry-picking (ie C^, ie the parent of C)

Если сразу не ясно, почему BASE должен быть C ^, см. "Почему" раздел ниже.

А пока давайте возьмем пример и посмотрим, что BASEcan be но частоwon't be общий предок во время вишни. Предположим, что граф фиксации выглядит так

E <-- master
|
D 
| C <-- foo_feature(*)
|/
B
|
A

а вы в ветке foo_feature (отсюда и звездочка). Если вы выполните «git cherry-pick & lt; commit D», тогда BASE для этого cherry-pick будет коммит B, который является общим предком C и D. (C будет LOCAL, а D будет REMOTE. ) Однако, если вы вместо этого выполните git cherry-pick & lt; commit E & gt;, тогда BASE будет коммитом D. (C будет МЕСТНЫМ, а E будет УДАЛЕННЫМ.)

rebase

Для фонового контекста rebase - это итеративный сбор вишни. В частности, перебазирование темы поверх мастера (то есть «тема git checkout; мастер git rebase») означает примерно:

git checkout master # switch to master's HEAD commit
git checkout -b topic_rebased # create new branch rooted there
for each commit C in master..topic # for each topic commit not already in master...
    git cherry-pick C # bring it over to the new branch
finally, forget what "topic" used to mean and now defined "topic" as the HEAD of topic_rebased.

Метки, которые применяются во время этого процесса, являются продолжением обычных правил выбора вишни:

  • LOCAL: the commit you're cherry-picking on top of
    • This is the HEAD of the new topic_rebased branch
    • For the first commit only, this will be the same as the HEAD of master
  • REMOTE: the commit you're cherry picking (i.e. <commit C>)
  • BASE: the parent of the commit you're cherry-picking (C^, ie the parent of C)

Это подразумевает, что нужно помнить о LOCAL vs REMOTE, если вы хотите избежать путаницы:

Even though you were on branch topic when you initiated the rebase, LOCAL never refers to a commit on the topic branch while a rebase is in progress. Instead, LOCAL always refers to a commit on the new branch being created (topic_rebased).

(Если не помнить об этом, то во время неприятного слияния можно начать спрашивать себя: «Подождите, почему он говорит, что этоlocal изменения? Клянусь, это были изменения, сделанные на мастере, а не на моей ветке. & Quot;)

Чтобы быть более конкретным, вот пример:

Скажем, у нас есть график

D <-- foo_feature(*)
|
| C <-- master
B |
|/
|
A

и мы в настоящее время находимся на ветке foo_feature (обозначено как "*"). Если мы запустим «git rebase master», перебазирование будет продолжено в два этапа:

Во-первых, изменения от B будут воспроизведены поверх C. Во время этого, C является ЛОКАЛЬНЫМ, B является УДАЛЕННЫМ, и A является ОСНОВНЫМ. Обратите внимание, что A является реальным общим предком B и C. После этого первого шага у вас есть примерно такой график:

   B' <-- foo_feature
D  |
|  |
|  C <-- master
B /
|/
|
A

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

Во-вторых, изменения из D будут воспроизведены поверх B '. Во время этого B & a; является локальным, D является удаленным, а B является базовым. Обратите внимание, что B не является значимым общим предком чего-либо. (Например, он не является общим предком нынешних LOCAL и REMOTE, B 'и D. И он не является общим предком исходных головок ветвей, C и D). После этого шага у вас есть ветка примерно так:

   D' <-- foo_feature
   |
   B'
D  |
|  |
|  C <-- master
B /
|/
|
A

Для полноты заметки к концу ребазы B и D удаляются с графика, давая:

D' <-- foo_feature
|
B'
|
C <-- master
|
A

Why is BASE defined as it is?

Как отмечено выше, и для вишни, и для перебазирования BASE является родителем (C ^) коммита C, в который вытягивается. В общем случае C ^ не является общим предком, так зачем называть его BASE? (При обычном слиянии BASEis общий предок. И часть успехов git в слиянии обусловлена его способностью находить хорошего общего предка.)

По сути, это делается для того, чтобы реализовать «исправление». функциональность через обычныйтрехстороннее слияние алгоритм. В частности, вы получаете эти «пятнистые» свойства:

  • If <commit C> doesn't modify a given given region of the file, then the version of that region from your branch will prevail. (This is, regions that the "patch" doesn't call for changing don't get patched.)
  • If <commit C> modifies a given region of the file and your branch leaves that region alone, then the version of that region from <commit x> will prevail. (That is, regions that the "patch" calls for changing get patched.)
  • If <commit C> modifies a given region of the file but your branch has also modified that region, then you get a merge conflict.
Error: User Rate Limit ExceededthinkError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Chris
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededmanpage hereError: User Rate Limit Exceeded Chris
Error: User Rate Limit Exceeded

Похожие вопросы