Git diff 忽略子模块中的 textconv

Git diff ignores textconv in submodules

我的项目结构如下:

/project
  - file.json
  - /submodule
    - submodule-file.json

其中 /submodule 目录是 git 子模块。

我已经设置了 textconv 来对 json 文件进行一些简单的预处理以进行比较 - 我的本地 .git/config 文件包含

[diff "json"]
    textconv = jq -S .

这对主项目中的文件非常有效 - git diff file.json 按预期工作。但它不适用于子模块中的文件。

git diff submodule/submodule-file.json 根本没有输出。

cd submodule && git diff submodule-file.json 在没有应用 textconv 的情况下产生差异。

我不希望将这些设置设为全局设置,如果我能让它们只应用于子模块,我会很高兴。

这可能吗?

git 版本 2.26.1

是的,符合预期。

每个子模块本质上都是一个单独的 git 存储库。您仅提供对父仓库中子模块仓库的特定提交的引用。如果您在子模块中检出一个新提交,父模块会跟踪该更改,但几乎所有其他事情都会发生,就好像您切换到另一个仓库一样。子模块命令只是在多个子模块中重复相同的 git 命令(如果添加了标志,甚至可能递归)。

因此,正如 LeGEC 在评论中的问题中提到的那样,设置 textconv 语句的位置很重要。如果它在父 .git/config 中,则它将不适用于子模块。另请注意,出于安全原因,此设置通常不会被推送到远程(或获取),因此在大多数情况下您需要在本地设置它(尽管您可以共享一个将在其他地方设置它的脚本)。

如果你想进行全局转换,你可以将以下内容添加到你的全局(或者我认为的系统).gitconfig。您可以使用 git config -e --global:

编辑全局
[core]
    attributesfile = C:/Users/<home>/.gitattributes

我的 .gitattributes 文件是这样的:

*.csv diff=csv
*.xls diff=unzip

注意:= 符号周围没有空格!!很重要!! :)

然后回到 .gitconfig 我有:

[diff "unzip"]
    textconv = unzip -c -a
[diff "csv"]
    tool = csv
    guitool = csv
[difftool "csv"]
    cmd = code --wait --diff \"$LOCAL\" \"$REMOTE\"
[mergetool "csv"]
    prompt = false
    cmd = code --wait \"$MERGED\"

(在区分 xls 之前使用解压缩并将 csv 抛出到 VS Code)

它适用于全球,包括子模块。如果您只是在寻找全局应用程序,那应该可以为您提供所需的模式。

I would prefer not to make these settings global, and would be happy if I could have them only apply to the submodule.

是的,它隐藏在文档描述的底部,但是 top-priority 属性的来源是 repo-local .git/info/attributes,那里指定的任何内容都会覆盖任何已提交的属性,并且你自己的默认值。

因此,找到您想要应用此差异的存储库,在您可能必须制作的 info/attributes 文件的末尾添加 \*.json diff=myjson,这将覆盖其他地方为此指定的任何差异回购。

您可以使用

找到已初始化子模块的实际存储库
git -C that/submodule rev-parse --absolute-git-dir

或者全部完成,例如

git submodule foreach --quiet --recursive git rev-parse --absolute-git-dir

这是您要更新其 info/attributes 文件的目录。