在两个不同的存储库中从 git diff 中排除目录

Exclude directories from git diff on two separate repositories

我正在尝试在两个独立的存储库之间进行 git 比较。单独使用 git diff ProjectA ProjectB 可以,但我必须滚动浏览 .git 目录中的所有差异。

我已经尝试 git diff ProjectA ProjectB -- . ':!.git' 排除 .git 目录,但出现以下错误。

Not a git repository
To compare two paths outside a working tree:
usage: git diff [--no-index] <path> <path>

我也试过 git diff --no-index ProjectA ProjectB -- . ':!.git' 但只收到消息:

usage: git diff --no-index <path> <path>

在排除某些目录的同时 git 区分两个不同的存储库的正确方法是什么?

我不知道以这种方式使用 git diff 时排除路径的方法。如果可以排除路径,那么您已经在问题中使用的魔术签名(:!)可能就是它。有关魔术签名的更多信息,请访问 man gitglossary

如果有任何帮助,您可以通过添加一个作为另一个的远程来区分每个 repo 的提交。

cd ProjectA
git remote add ProjectB ../ProjectB
git fetch ProjectB
git diff <commit-or-branch-in-ProjectA> <commit-or-branch-in-projectB>

完成比较后,您可以移除遥控器:

git remote remove ProjectB

再深入一点,看起来当 git diff 是带有 --no-index 选项的 运行 时(隐式或显式),它会触发不同的代码路径。 cmd_diff calls diff_no_index and returns early. From what I can tell, diff_no_index 不调用任何解析魔法路径规范的东西。

神奇的 pathspec 解析似乎发生在上述代码路径已经返回之后。具体来说,在 cmd_diff, there is a call chain builtin_diff_tree -> diff_tree_oid -> try_to_follow_renames -> parse_pathspec -> init_pathspec_item 的更下方,这似乎是神奇的 pathspec 解析发生的地方。

我建议您只使用 diff 而不是 git diff 来进行比较。您可以告诉 diff 从比较中排除某些路径以自定义输出。缺点是 diffgit diff 的输出格式不完全相同。通常,它是无关紧要的,但在某些情况下很重要。

我在这里要说的大部分内容都在其他答案和他们的评论中,但要填补一些空白,强调几点,并提供我希望的一般的、有条理的、有用的答案:


大多数形式的 git diff 都希望在 repo 工作树中 运行,以比较文件(或一组文件中的每一个)的两个版本。对于要比较的每个文件,您可能正在将工作树版本与索引版本进行比较,或者将提交 A 中的版本与提交 B 中的版本进行比较。

但是,在这些情况下,您无法与存储库之外的内容(例如工作树之外的路径)进行比较。如果您尝试引用当前 repo 工作树之外的内容,并且 git 认为您正在使用其中一种形式,那么它将引发错误。

有一种特定形式的 git diff 可以解除此限制:

git diff [--no-index] path1 path2

其中:(a) 您包含 --no-index 选项,或 (b) 其中一个路径在当前存储库的工作树之外。在这种情况下,git 将比较文件系统上的两个任意路径。但是,git 的各种与存储库相关的功能 - 例如与历史版本的比较 - 在​​使用此表单时无法访问。

所以,当你说

git diff projectA projectB

由于您提供的路径不在一个单一的 repo 工作树中,git 认为它必须切换到这种特殊形式,所以它有效。

但是:

这种特殊形式非常有限。你只能列出两个根路径——而不是任意数量的路径规范,就像你在一个 repo 中比较一个文件的版本一样。当您开始尝试提供更通用的 git diff 语法时,git 会说 "well, this isn't the filesystem-to-filesystem comparison syntax, so I can't have this path outside the work tree"... 并且您会收到错误消息。

所以你有两个选择。

您可以使用 git 以外的工具来比较目录。这样的工具可能具有 path-based 排除功能。

或者,您可以使用 git,但在单个存储库中进行比较。

mkdir compare
cd compare
git init
git remote add ProjectA ../ProjectA
git remote add ProjectB ../ProjectB
git fetch ProjectA
git fetch ProjectB
git diff ProjectA/master ProjectB/master

现在 git 了解您正在比较两个内容版本。

您也可以通过使 ProjectB 成为 ProjectA 的远程对象(反之亦然)并进行提取,以便两个存储库之一具有两组对象来实现此目的。需要注意的是,仅删除遥控器并不一定会删除从其他存储库中获取的所有对象。 (它绝对不会立即删除它们。)