Git:这个分叉是怎么发生的?

Git: how this bifurcation happen?

情况

问题

正如我提到的,没有任何指向它,我做了一个 git -gc 来清理任何挂起的提交。

There is no tag nor any other [commit] pointing to c79dc19

历史不是这样的。

试试 运行 git show HEAD - 它会显示合并的两个父项是什么。从你的图表来看,其中一个是 c79dc19,这就是它出现在你的历史记录中的原因。

最有可能的是,分支确实是从 c79dc19 开始的(所以在 master 上 已经 ),或者分支作为快进合并到 master当 c79dc19 是它的头时。


已完成的插图:

  1. 初始状态

    fe62 <=master <=HEAD
    
  2. 新提交

    fe62 <- c79d <=master <=HEAD
    
  3. 签出新分支

    fe62 <- c79d <=master <=branch <=HEAD
    
  4. amend(在分支上)给出了一个新的提交 0c81 replaces c79d 在该分支上但是 没有改变 master

    fe62 <- c79d <=master
         \- 0c81 <=branch <=HEAD
    

您在 c79 从 master 创建了新分支,因此 master 继续指向那里。然后你从新分支提交了修改,因此主分支和新分支有不同的历史。

需要注意的一点是,修改实际上并没有修改提交。提交是不可变的。一个修正案基于另一个修正案创建一个新的提交。

如果你想压扁它,那么将 master 指向上一个提交并合并到 tip。

git checkout -b temp
git branch -f master fe6263e
git checkout master
git merge f6429eb

很难 100% 确定,但这种情况经常发生,所以这 可能 是正确答案。

您提到您只有一个 b运行ch,名为 master。我相信你!但是您不只有一个 存储库 — 或者更准确地说,您有您的克隆,然后还有其他克隆,可能在您调用 origin 的遥控器上中央服务器,例如 GitHub 或企业服务器。您将提交发送到服务器,并从服务器获取提交。

您还提到使用 git commit --amend。有关详细信息,请参阅 How does git commit --amend work, exactly? (as in ),但简而言之,这不会 更改 提交,它只是 将其推到一边 以支持新的替换提交。不过,据推测,您已经推送了原始提交——所以现在它位于 other 存储库中的 master b运行ch 中。

所以你现在有 0c81926 作为你 master 的尖端,而他们(来源)有 c79dc19。然后你做了新的提交 f6429eb,所以你的 master 指向那个。

那么,我打赌你 运行 git pull(很可能你没有配置或指示你的 git pullgit rebase)。这个 运行 git fetch 后跟 git mergegit fetch 检查了您的遥控器 origin,发现 its master 指向提交 c79dc19git pull运行合并他们的b运行ch和你的bgit merge =82=]ch,生成合并提交 706b1ef.

最后,这意味着你确实有两个不同的b运行ches:master和master。只不过其中一个是的师父,一个是别人的师父

请注意,您可以摆脱提交 c79dc19 合并,例如,使用 git rebase -i fe6263e (混乱开始之前的那个点):删除不需要的额外提交,并让 git rebase 展平剩余的历史记录并省略合并。 (或者,使用 中的方法。)但是,一旦你这样做,你的历史将与 origin 上的历史 不同 :他们有一个提交(与您试图摆脱的 c79dc19 相同)您没有。因此,您将无法在不强制推送的情况下推送(可选,"force with lease",期望他们的 masterc79dc19,以确保自上次以来他们没有获得更多提交你检查的时间)。