git diff .. returns 只有 git diff ... returns 变化时如何解决分支?

How to resolve branches when git diff .. returns nothing but git diff ... returns changes?

我认为我的 master 和 release 分支有某种分歧,我想知道让它们恢复同步的最佳方法是什么。

我有一个应该用于开发的 master 分支,但随后我会将这个 master 分支合并到 release 分支中以创建最终版本部署。它工作正常,但截至一周前,每当我尝试创建一个从 master 合并到 release 的拉取请求时,我都会得到一个应该已经在 [=16] 中的提交列表=].我将合并 PR,但是每一个试图从 master 合并到 release 的新 PR 都会发生这种情况。

我尝试查看更改以确保两个分支相同

git diff upstream/master..upstream/release 没有给我任何差异。

git diff upstream/release..upstream/master 也没有给我任何差异。

但是 git diff upstream/master...upstream/release 给出了自从我的两个分支可能发生分歧以来所有提交的更改。

我认为可能发生的情况是我的两个分支在原始代码上是相同的,但它们有不同的提交?我仍在学习 类 git 以及如何更有效地使用它,因此非常感谢任何帮助!

我敢打赌,如果你 运行 git diff upstream/release...upstream/master 你会得到与你在那里发布的第三条命令相同的输出......是的,分支已经分开,但它们具有相同的内容,这就是为什么你没有 2 个点的差异,但你得到 3 个点的输出。

这仍然没有回答您的问题。这真的取决于你怎么称呼 "bring them in sync".

  • 如果你的意思是have the same content:他们已经这样做了
  • 如果你的意思是get the branch histories together,你可以尝试合并它们。
  • 如果你的意思是get one branch to have the exact same history as the other,那意味着重置--hard(因此重写历史)和一些强制推动。

TIL : git diffgit log.

..... 有不同的解释
  • git diff a..b(两个点)等同于git diff a b
  • git diff a...b(三点)将ab的合并基础与b
  • 进行比较

请参阅 docs、"Description" 部分。

运行 : git log --oneline --graph upstream/master upstream/release,您将查看提交的布局方式。


你的两个点 diff 命令确实告诉你两个分支具有相同的内容。

"merge base" 是两个分支之间的分叉点,您在三个点 diff 中看到的是该提交与分支的头提交之间的差异。

I think what might be happening is that my two branches are identical in raw code, but they have different commits?

是的,这是正确的诊断,尽管您可以通过以下方式确认:

git log --left-right --boundary --decorate --oneline --graph
    upstream/master...upstream/release

(全部为一个,为了发布目的分成几个)。

请记住,Git 大约是 提交 。像 masterrelease 这样的分支名称,以及像 upstream/masterupstream/release 这样的远程跟踪名称,标识了一些特定的提交。我们说这些名称 指向 那些提交。

提交还指向 其他提交:特别是,每个提交都指向其直接父项。

当你有一个这样的提交的简单线性序列时,每个都有自己的哈希 ID,以我们可以称为 H 的某个最终哈希 ID 结尾,我们可以这样画:

... <-F <-G <-H   <-- master

name master 持有正确的散列 ID:它可以让你(或 Git,至少)轻松找到正确的散列 H 用于链中的 last 提交。换句话说,master 指向 H。提交 H 本身包含快照——你的所有文件,及时冻结——以及前一个 ("parent") 提交 G 的原始哈希 ID,因此 H 指向G。哈希让 Git 找到 G。提交 G 包含一个快照和另一个父哈希 F,它让 Git 找到 F,等等。

在这种情况下,你的情况是这样的:

          I--J   <-- upstream/master
         /
...--G--H
         \
          K--L   <-- upstream/release

无论出于何种原因,1 JL 中的快照匹配,因此比较 upstream/master(提交 J ) 到 upstream/release(提交 L)显示没有区别,无论您使用哪个方向进行比较。

在这里,了解以下内容很有帮助:

git diff A..B

就意味着:

git diff A B

即Git找到问题中的两个hash ID,提取出两个冻结的快照,进行比较(diff)。您会看到有关将 A 中的快照更改为 B

中的快照所需的信息

但是:

git diff A...B

并不意味着将A与B进行比较,而是在A与B之间找到一个合并基础,并将该合并基础快照与B进行比较.在这种情况下,考虑到我制作的绘图(可能与您拥有的实际提交集不完全匹配),upstream/masterupstream/release 的合并基础是提交 H,这与您一样可以看到,在两个历史记录中:如果从 J 开始并向后工作,您将找到提交 H,如果从 L 开始,您还将找到提交 H并向后工作。

所以在这里,这会将 H 中的快照与您放在右侧的名称指向的任何提交中的快照进行比较。由于 JL 中的快照匹配,因此无论您 运行 以何种方式,您都会看到相同的差异:

git 差异 upstream/master...upstream/release

比较 HL,同时:

git diff upstream/release...upstream/master

比较 HJ,但它们产生相同的差异。

如果您希望 历史记录 匹配——历史记录是从名称开始找到的提交集,然后向后工作——您必须:

  • 移动upstream/release,或
  • 移动upstream/master,或
  • 添加一个新的合并提交并移动两者,如图所示:

              I--J
             /    \
    ...--G--H      M   <-- upstream/release, upstream/master
             \    /
              K--L
    

例如。但是,由于这两个名称是 远程跟踪名称 ,所有这一切都变得复杂了。它们不是 分支名称

这些远程跟踪名称是你的,所以你可以移动它们——但是你的Git自动移动它们,匹配存储在某些 other Git 存储库分支名称中的哈希 ID。另一个 Git 存储库是您的 Git 调用 upstream 的存储库,并且 具有分支名称 masterrelease .你运行:

git fetch upstream

并且您的 Git 调用他们的 Git,找到他们有但您没有(您需要)的任何新提交,gets 这些提交,然后更新您的 upstream/* 远程跟踪名称以存储与它们的 branch 名称相同的哈希 ID。

因此,要更新您的远程跟踪名称,正确的方法是说服他们他们的分支机构 名称已更新。然后你只需 运行 git fetch upstream 更新你的匹配。


1在没有合并提交的情况下,让这些提交像这样匹配的最可能原因是有人使用了 git merge --squash,或者可能是点击 Git 标记为 "squash and merge".

的 Hub 网页按钮