为什么本地和远程存储库之间的区别与提交的不一样?

Why difference between the local and remote repository is not the same as committed?

我有一个合并冲突,我想知道的第一件事是文件的本地版本和远程版本之间有什么区别。为此,我执行了以下操作:

git diff origin:path/to/my/file.py path/to/my/file.py

这样我看到我的本地版本有一些额外的块。

然后我想看看我到底提交了什么。所以我执行了:

git diff --staged path/to/my/file.py

令我惊讶的是,我看到了另一个变化块,它与上一个命令返回的块不同。

我在文本编辑器中打开了我的文件,看到了两个块。现在我不知道如何解释它。

看起来本地和远程版本之间存在差异,这个差异不是我提交的。

您的某些更改已暂存,其他更改未暂存。这两个都由第一个命令显示。第二个仅显示已上演的更改。

请执行:

git add path/to/my/file.py

然后 git diff --staged 将显示与第一个命令相同的输出。

我不确定您为什么首先期望这些差异相同。

记住origin:path/to/my/file.py是指从origin解析到的提交中提取的path/to/my/file.py的版本,一般是origin/HEAD,一般是[=18] =]. git diff 命令然后将从该提交中提取的那个文件与你现在的工作树中的任何内容进行比较,如果你正在解决合并冲突,这通常是带有冲突标记的版本冲突。

旁白:git diff

请注意 运行宁 git diff 在合并冲突期间喜欢尝试显示 组合差异 。但是 运行ning git diff <commit-specifier>:<path> <path> 避免了这种情况。同时,运行ning git diff --staged <path> 只是说:

$ git diff --staged path/to/file
* Unmerged path path/to/file

(除非您从工作树中 git add 编辑了 path/to/file 的一个版本,以告诉 Git 您已经正确合并了文件,在这种情况下它比较将 HEAD 版本更改为您通过 git adding 复制到索引中的版本。

git merge 正在做什么

那不是 git merge 正在查看和合并的内容。 git merge 正在查看的是 两个 差异:

  • 一个差异来自您的合并基础,以 HEAD.
  • 的提交为准
  • 第二个差异是从你的合并基础到你的另一个头,无论哪个提交(可能 origin/master,也可能不是)。

您可以通过先获取合并基础提交哈希来获取这两个差异。比方说,为了简化事情,您 运行 git merge origin/master 现在正在查看 path/to/my/file.py 上的合并冲突。你的 Git 首先是 运行:

git merge-base --all HEAD origin/master

运气好的话,这只会产生一个提交哈希 ID。1 您可以将其保存在一个变量中:

base=$(git merge-base --all HEAD origin/master)

然后在两个特定的差异中使用它:

git diff $base HEAD -- path/to/my/file.py           # what git thinks I changed
git diff $base origin/master -- path/to/my/file.py  # what git thinks they changed

如果你想直接比较所有三个文件,你可以将它们解压到临时文件中。这就是 git mergetool 所做的,例如:它从这三个提交中的每一个中提取基础 path/to/my/file.py、本地(HEAD)文件和另一个("remote head")文件,并且然后 运行 在所有三个文件上使用您选择的合并工具。


如果 git merge-base --all 产生了多个哈希 ID,您的 git merge -s recursive 对所有这些提交进行了内部合并,将结果作为临时提交提交,并使用 提交的散列作为合并基础。