gpt4 book ai didi

Git Rebase 冲突 : Who is HEAD?

转载 作者:IT王子 更新时间:2023-10-29 00:43:37 27 4
gpt4 key购买 nike

我有这个项目,其中远程仓库有主要的开发分支,我有一个包含实验分支的分支。我需要rebase在我推送到我的分支之前,从开发分支更改为我的实验分支。所以它是这样的:

git checkout experimentalbranch
git fetch remoterepo
git rebase remoterepo/developmentbranch

这时,我遇到了冲突。但是,我对这些更改中的任何一个都不熟悉(我正在重新调整数周的更改,因为它们没有立即 merge 我的更改)。另外,这是我第一次做 rebase .我比较习惯 merge .

在融合中,它通常是这样的 <<LOCAL||REMOTE>>merge ,这听起来很直观。但在 rebase ,它是 <<HEAD||COMMIT MESSAGE>> .谁是 HEAD ?是不是 HEAD开发分支?它是开发分支或其他地方的最新代码吗?

最佳答案

TL;DR(2018 年 5 月添加)

整个事情从根本上说至少有点令人困惑,因为 Git 让其内部工作直接向您展示。

请注意,当您运行时,我们在这里关注的情况会发生:

git checkout somebranch; git rebase origin/their-branch

或类似。 rebase 暂时停止以强制您解决 merge 冲突,之后您应该 git add解决冲突并运行 git rebase --continue . (如果你使用一些带有 git mergetool 的 merge 工具,或者一个花哨的 GUI 界面,该界面可能会以其他方式为你做一些或全部,但在下面,它是 git add 解析文件并运行 git rebase --continue 。 )

一开始, HEAD commit 是他们的分支,所以如果你使用 git checkout --oursgit checkout --theirs , --ours意味着他们的——最后一次提交 origin/their-branch ——同时 --theirs意味着你的,你正在 rebase 的第一个提交。这是正常的日常 Git 混淆(请参阅 What is the precise meaning of "ours" and "theirs" in git? ),而不是导致原始问题的原因。

然而后来, HEAD commit 实际上是一种混合物。这是在最新提交上复制一些提交的结果。你现在在你自己部分构建的新提交系列和你自己的原始提交之间发生冲突。这种冲突的根源通常是“他们”所做的事情(在 origin/their-branch 中发生了变化)。您仍然必须解决此冲突。当您这样做时,您可能会在以后的提交中看到完全相同的冲突。

再次, HEADlocal--ours是 rebase 通过组合您的更改及其更改构建的提交,另一个提交( remote>>>>>>>--theirs )是您自己的提交,rebase 试图复制 HEAD .

更长

merge 时(包括 rebase ,这是内部重复“merge ”的一种特殊情况),涉及两个“头”(两个特定的分支提示)。让我们称这些 your-branchorigin/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引用 merge 期间的两个主要提交,“我们的”是您运行时所在的提交(提交 H ) git merge ,而“他们的”是他们的(提交 L)。但是当你在做 rebase 时,两个 head 是颠倒的,所以“ours”是你正在 rebase 的 head——即他们更新的代码——而“theirs”是你当前正在 rebase 的提交,即,您自己的代码。

这是因为 rebase 实际上使用了一系列挑选操作。你从几乎相同的图片开始:
              G - H           <-- HEAD=your-branch
/
... - E - F
\
I - J - K - L <-- origin/their-branch

这里git需要做的就是复制commits的效果 GH ,即 git cherry-pick提交 G ,然后再次提交 H .但要做到这一点,git 必须切换到提交 L首先,内部(使用“分离头”模式):
              G - H           <-- your-branch
/
... - E - F
\
I - J - K - L <-- HEAD, origin/their-branch

现在它可以通过比较提交的树来启动 rebase 操作 FG (看看你改变了什么),然后比较 F对比 L (查看您的某些工作是否已经在 L 中)并进行任何尚未在 L 中的更改并添加它。这是内部的“merge ”操作。
              G - H           <-- your-branch
/
... - E - F G' <-- HEAD
\ /
I - J - K - L <-- origin/their-branch

如果 merge 不顺利, HEAD仍然留在提交 L (因为提交 G' 尚不存在)。因此,是的, HEAD是他们开发部门的负责人——至少,现在是。

曾经的副本 G虽然存在, HEAD移至 G'并且 git 尝试从 H 复制更改,以同样的方式(diff G vs H ,然后 diff F vs G' ,并 merge 结果):
              G - H           <-- your-branch
/
... - E - F G' - H' <-- HEAD
\ /
I - J - K - L <-- origin/their-branch

同样,如果 merge 失败并需要帮助,您将剩下 HEAD指向 G'而不是 H'H'还不存在。

一旦 merge 成功并提交 G'H'确实存在,git 删除标签 your-branch来自提交 H ,并使其指向提交 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表示被复制的提交(上面的 GH)。

(这基本上是 git 公开了它如何做的原始机制,这在 git 中发生得相当多。)

关于Git Rebase 冲突 : Who is HEAD?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23207791/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com