繁体   English   中英

git pull 后显示“强制更新”

[英]"Forced update" shown after git pull

在我的存储库中执行git pull后,它显示

6cca7ee...32eb5b2 bug/12 -> origin/bug/12  (forced update)

以前,我从父分支parent/1.2.3创建了bug/12分支,对代码进行了更改,并将bug/12分支合并到了parent/1.2.3分支并完成了bug/12 branch 但是由于某些问题,我需要再次重新打开 bug 12,因此我再次从parent/1.2.3创建了一个bug/12分支,并进行了代码更改并将更改推送到bug/12分支。 但是现在当我拉动parent/1.2.3分支时,它显示我强制更新。

因此,如果我将新创建的bug/12分支合并到parent/1.2.3分支中,它会产生任何问题还是会删除强制更新?

这种“强制更新”的事情可能会非常令人困惑,但您已经提出了一个重要的问题。

是否有任何实际的问题就在这里,我怀疑有isn't,取决于是什么意思时,你说:

...并完成了bug/12 branch

Git 没有一个叫做完成的概念。 因此,您导致在哪些存储库中发生的实际 Git 操作并不明显。

Git 是分布式的,所以存储库不止一个

如果只有一个存储库,并且它有各种分支名称,例如bug/12并且您执行了以下操作:

git checkout master
git merge bug/12
git branch -d bug/12

(这会将bug/12尖端的提交合并到master ,然后删除分支名称bug/12 )这种问题永远不会出现:删除了名称,它不再存在。

但不只有一个存储库。 你:

  • 您的存储库中创建了名称bug/12
  • 您的存储库中做了一些工作,创建提交
  • 将这些提交发送到另一个存储库,并让他们他们的存储库中创建名称bug/12
  • 让你的 Git 从他们那里获得新的提交和/或分支名称:这发现他们现在在他们的存储库中有一个bug/12 ,所以你的 Git 在你的存储库中创建了一个origin/bug/12来记住他们的bug/12

现在,在这一切之后,我怀疑你所做的——所说的“完成的bug/12 branch ”——是你在使用 GitHub 或 Bitbucket 或 GitLab 或类似的东西,你进入了他们的网络界面并使用了各种小按钮将bug/12合并到他们存储库中的master ,然后删除他们的bug/12 name 这与上面显示的三个假设命令非常相似,除了 `git merge bug/12 可以执行快进操作而不是真正的合并,而 GitHub合并拉取请求按钮永远不会执行快进操作。

但我不知道这就是你所做的。 我只是怀疑而已。

陈旧的远程跟踪名称

假设这就是您所做的,您可能会继续从您自己的存储库中手动删除分支名称bug/12

git branch -D bug/12

从那时起,您可能已经运行了git fetch (或者以一种可以解决问题的方式运行git pull运行git fetch ),但您可能没有fetch.prune设置为true 当您运行git fetch ,您的 Git 会在origin调用 Git 并让它们列出它们的分支名称。 他们此时没有bug/12分支名称,但是您的 Git 更早创建了您自己的origin/bug/12 ,当时他们确实有他们的bug/12分支名称。 因此,您的 Git 不会对您自己的origin/bug/12名称执行任何操作:此名称没有新值,但您没有指示您的 Git删除不再具有其他名称的origin/*名称。

这意味着就您的 Git 而言, origin/bug/12仍在记住另一个 Git 存储库中的有效bug/12名称,即使不再有这样的名称 如果您将fetch.prune设置为true或运行git fetch --prune ,您的 Git 将删除此origin/bug/12 所以在这一点上,你的origin/bug/12是一个陈旧的 name (Git 没有定义这个术语——它没有被称为陈旧名称的概念——但这对于这种名称来说似乎是一个很好的术语。)

同样,所有这些都是从事实中推断出来的,实际上并不存在证据。 真的是这样吗? 我不知道:你告诉我的还不够多。

陈旧的名称可能会导致这种行为

现在,假设以上所有内容都是正确的,您自己的origin/bug/12还记得前段时间在origin记住的bug/12 那是您单击合并变基和合并挤压和合并Web 浏览器单击按钮之前。 在这一点上,我必须至少再做一个假设:您使用的按钮不是纯粹的合并,而是rebase 和 mergesquash 和 merge

让我们画出 rebase-and-merge 或 squash-and-merge 操作之前的情况。 在 GitHub 上的 Git 存储库中(此时我将假设为 GitHub),您有一系列提交,每个提交都以某个分支名称指向的提交结束:

...--A--B--C--D   <-- parent/1.2.3
         \
          E--F   <-- bug/12

这里EF是修复错误的两个提交。 您现在单击变基并合并压缩并合并并获得两个或一个新提交:

...--A--B--C--D--E'-F'  <-- parent/1.2.3
         \
          E--F   <-- bug/12

或者:

...--A--B--C--D--G   <-- parent/1.2.3
         \
          E--F   <-- bug/12

(我会用这张图,因为它更简单)。 你现在让 GitHub 删除它的bug/12名称:

...--A--B--C--D--G   <-- parent/1.2.3
         \
          E--F   [abandoned]

在某个时候,在您的存储库中,您更新自己的 Git 对 GitHub Git 分支的内存:

...--A--B--C--D--G   <-- origin/parent/1.2.3
         \
          E--F   <-- origin/bug/12

请注意您的陈旧origin/bug/12名称如何仍然记住提交F

此时,您可能会也可能不会向origin/parent/1.2.3添加更多提交和/或更新您自己的parent/1.2.3名称。 让我们再画一个提交并同步显示这两个提交:

...--A--B--C--D--G--H   <-- parent/1.2.3, origin/parent/1.2.3
         \
          E--F   <-- origin/bug/12

请记住,这是存储库中内容的绘图。 GitHub 存储库有这个:

...--A--B--C--D--G--H   <-- parent/1.2.3

它没有origin/*名称:它只有它的分支名称。 您的Git 是具有origin/*名称的 Git,包括陈旧的origin/bug/12 到目前为止,他们的Git 已经完全丢弃了提交EF 由于您的origin/bug/12名称,您的Git 仍在保留其他不需要的EF提交。

现在你在他们的Git 中做一些创建名称bug/12事情,指向提交H

...--A--B--C--D--G--H   <-- parent/1.2.3, bug/12

您现在在您的存储库中运行git fetch (通过git pull )。 你的 Git 看到他们的bug/12指向提交H 你的 Git目前有这个:

...--A--B--C--D--G--H   <-- parent/1.2.3, origin/parent/1.2.3
         \
          E--F   <-- origin/bug/12

但是您的 Git 现在将获取您的origin/bug/12并将其从提交F拉出并将其移至指向提交H

...--A--B--C--D--G--H   <-- parent/1.2.3, origin/parent/1.2.3, origin/bug/12
         \
          E--F   [abandoned]

你的 Git 现在你的名字origin/bug/12执行这个不寻常的动作,将它从你仍然保留的提交中拉出来——提交F到提交H ,它不是提交F后代 (提交H的唯一父级是G G的父级是D ,其父级是C ,其父级是B 。因此,提交H不是F后代,尽管它们在提交B共享相同的祖先。)操作是非快进的,因此您的Git 打印:

+ 6cca7ee...32eb5b2   bug/12 -> origin/bug/12  (forced update)

前面的加号(您省略了)表示这是强制更新,因为它是非快进的

这里的两个散列 ID 6cca7ee32eb5b2是我在上面调用FH的提交的完整散列 ID 的缩写版本。 从输出git fetch包括这两个散列ID之间的三个点,表明6cca7ee不是的祖先32eb5b2

箭头左侧的名称bug/12是在他们的存储库中看到的分支名称(在 GitHub 上,或任何地方)。 名称origin/bug/12您的 Git对其bug/12的记忆

最后的(forced update)与加号和三个点表示相同的事情:这是一个非快进,因此作为强制更新完成。

因此, git fetch命令已经三次告诉您有强制更新。

这里有问题吗?

答案可能不是,但这取决于对origin/bug/12更改,而是取决于您自己的分支名称。 在上面的图中,我们已经绘制了一些分支名称、一些远程跟踪origin/*名称和一些其他 Git 的分支名称,具体取决于我们正在讨论的 Git 存储库。 但是我们还没有绘制所有的分支名称。

你的分支名称是你的 他们可以指向你在你的存储库中的任何提交——包括其他Git,在 GitHub 上或任何地方,已经放弃的EF提交。 如果您允许您的分支名称之一重新引入那些旧提交,那可能不太好。 如果您不允许这样做,那很好。 如果你没有任何分支名称指向这老提交,你会不小心再推出他们。

这就是解开谜题的关键。 提交才是最重要的。 提交有提交哈希 ID,世界各地的每个 Git 都同意这些提交获得这些哈希 ID。 没有其他提交,无论何时何地,都可以拥有这些哈希 ID! 您的Git 仍然在您的远程跟踪名称origin/bug/12下保留它们。 它不再使用该名称:该名称已更新以记住其他一些提交哈希 ID。 但是你仍然有你的分支名称。 这些中的任何一个都记得与您的陈旧origin/bug/12相同的哈希 ID,直到您的git pull运行的git fetch更新它,就在最近?

只有可以回答这个问题,因为只有您拥有自己的Git 存储库。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM