Git:我能否在状态、差异等操作中抑制“修改内容”/脏子模块条目的列出?

158

在某个时候(我想大约在1.6.x版本发布时),git开始意识到子模块内部的更改。这只会让我感到恼火:

$ git status vendor | grep modified:
#       modified:   vendor/rails (modified content)
$ git diff vendor/
diff --git a/vendor/rails b/vendor/rails
--- a/vendor/rails
+++ b/vendor/rails
@@ -1 +1 @@
-Subproject commit 046c900df27994d454b7f906caa0e4226bb42b6f
+Subproject commit 046c900df27994d454b7f906caa0e4226bb42b6f-dirty

请停止这种行为?

编辑:

好的,我有一个答案。现在我有另一个问题:

我能把这个放在~/.gitconfig吗?从我的初步了解来看,似乎我不能,而且在快速浏览补丁时也没有找到任何有希望的东西。(我猜我仍然可以创建一个别名。)

9个回答

214

甚至可以在.gitmodules文件中为每个添加的子模块设置忽略模式。

今天我遇到了这个问题,并在找到解决方案后立即在我的博客中撰写了一篇文章:如何忽略 git 子模块中的更改

它的要点是:

一旦你添加了一个子模块,你的仓库根目录下就会有一个名为 .gitmodules 的文件。

只需在 .gitmodules 文件中添加一行:

[submodule "bundle/fugitive"]
    path = bundle/fugitive
    url = git://github.com/tpope/vim-fugitive.git
    ignore = dirty

5
+1,但我在您在SO上的回答中包括了您博客文章的主要部分:您的外部链接可能会在某一天失效,而与之相反的是SO的答案将永存(通过SO数据转储:http://blog.stackoverflow.com/2009/06/stack-overflow-creative-commons-data-dump/)。 - VonC
5
在执行 git status 命令前,我发现需要先提交 .gitmodules 文件才能如预期般工作。此外,我相信你至少需要 1.7.4 或更高版本的 Git。 - aleemb
2
我无法使用子模块跟踪分支来使其工作。这是不支持的吗?[submodule "smstack/ansible/hosts"] path = smstack/ansible/hosts url = https://... branch = master ignore = dirty - Marc Abramowitz
1
@MarcAbramowitz 我想我也遇到了同样的问题 - 你找到任何解决办法了吗? - Sebastian G. Marinescu
外部链接有可能在某一天失效。 例如:该外部链接目前已经失效。 - evantkchong
显示剩余2条评论

93

有两种变更通知可以被抑制。

第一种是 未跟踪的内容(untracked content) ,当您对子模块进行更改但尚未提交时会出现这种情况。父存储库会注意到这些更改,并相应地报告到git status:

modified: modules/media (untracked content)

您可以使用以下方式来抑制这些变更通知:

[submodule "modules/media"]
   path = modules/media
   url = git@github.com:user/media.git
   ignore = dirty

然而,一旦你提交这些更改,父存储库将再次注意到并相应地报告它们:

modified:   modules/media (new commits)

如果您想要抑制这些内容,您需要忽略所有更改。

[submodule "modules/media"]
   path = modules/media
   url = git@github.com:user/media.git
   ignore = all

2
对于 .gitignore 文件,有一个名为 exclude 的私有版本,位于 .git/info/ 中,它不受版本控制。是否有一个相应的文件用于 .gitmodules 文件,可以让您仅在父存储库的实例中抑制子模块中的更改,而无需更改 .gitmodules - HelloGoodbye
2
HelloGoodbye:如果您检查.git/modules/$MODULENAME/,您会看到似乎是该模块的.git目录。在该位置更改info/exclude文件即可完成工作。 - PaulW
我想给你一个吻。 - Sasino
对于像我一样想要仅在本地忽略子模块更改(即不更改.gitmodules)的任何人,请在.git/config中的子模块部分添加ignore = all或您想要的任何模式。 - Nicolas

66

更新:有关向.gitmodules文件添加配置参数以忽略给定子模块的脏状态的可能性,请参见(并点赞)nilshaldenwang回答

ignore = dirty
所以 git 1.7.2 已经发布,包含 --ignore-submodules 选项用于 status
git help status 中可以看到:
--ignore-submodules[=<when>] 查找更改时忽略子模块的更改。 <when> 可以是 "untracked"、"dirty" 或 "all",默认为 "all"。 当使用 "untracked" 时,仅当子模块只包含未跟踪内容时,才不会将其视为脏(但仍会扫描已修改内容)。 使用 "dirty" 忽略所有对子模块工作树的更改,仅显示存储在父项目中的提交的更改(这是 1.7.0 之前的行为)。 使用 "all" 隐藏所有子模块更改(并且当设置了配置选项 status.submodulesummary 时,禁止输出子模块摘要)。
我想要的值是 dirty
git status --ignore-submodules=dirty

我使用别名是因为懒:

alias gst='git status --ignore-submodules=dirty'

3
既然这是一个被接受的答案,我认为你应该在这里添加将 ignore=dirty 添加到 .gitmodules 文件中各个条目的选项。 - Andriy Drozdyuk

21

正如你所提到的,这个补丁 git submodule: ignore dirty submodules for summary and status正在制作中。

同时在Git 1.7.2-rc2版本发布公告中也有宣布:

Git v1.7.2 Release Notes (draft)
================================

Updates since v1.7.1
--------------------

"git status" 学习了 "--ignore-submodules" 选项。

含义:

git config --global diff.ignoreSubmodules dirty

目前并未采用以下作为选项的做法(点击此处):

在这个系列之后,我计划在.gitmodules中添加一个配置选项 'ignore',可以为每个子模块设置为 "all"、"dirty"、"untracked" 或 "none" (默认值)。

"git diff"和"git status"将使用该配置值来处理每个子模块。
使用"--ignore-submodule"会覆盖此默认值(新参数"none"将被添加到该选项中,以便能够覆盖配置设置)。

为了避免每次更改该选项时都必须执行"git submodule sync",我想首先在.git/config中搜索它。
如果在那里没有找到,就会从.gitmodules中读取(如果存在)。

因此,用户可以覆盖设置,但如果他们不这样做,上游可以轻松更改它(例如,当子模块.gitignore已更新,因此不再需要 "ignore=untracked" 时,它可以被删除)。
还有,如果.gitmodules中的 'ignore' 条目在分支之间不同,则切换分支将立即生效。


另一种让git status(或任何git命令)忽略特定子模块的方法是使用Git 2.13(Q2 2017)实现的:

git config submodule.<name>.active false

请参阅 "在git中忽略子模块的新提交"。


我在问题中更新了一个gitconfig位。只是想问一下,如果你知道答案的话。 - kch
@kch:我已经更新了答案,使用目前提出的方法来存储这种设置。 - VonC
@drozzy:正如您在其他评论中提到的:“ignore = dirty”。 - VonC
谢谢,没有个人恩怨,但我只是想让更有用的答案排在前面,因为我最初错过了它! - Andriy Drozdyuk

13

你也可以使用

% git config [--global] submodule.ignore dirty

.git/config文件中设置 submodule.ignore = dirty。如果使用--global,则会在~/.gitconfig中设置忽略标志,并适用于您的所有存储库。否则,它应该在.git/config中设置,仅适用于您当前所在的存储库。

我能找到的唯一文档是git-config文档中的submodule.<name>.ignore。我将其从.gitmodules文件移到了我的~/.gitconfig文件中,它仍然对我有效。


@PawełGościcki 我可以确认它在Git 2.0.0上运行正常。 - Ciro Santilli OurBigBook.com

9
您需要添加:
ignore = dirty

.gitmodules文件


1
在 .gitmodules 文件中,你要把它加到哪里? - Andriy Drozdyuk
@drozzy 您可以在每个子模块的忽略部分中添加它,其中定义了“路径”和“URL”值。 - jsdalton

4

我已经在这里详细回答了这个问题。

只需运行

git config --global diff.ignoreSubmodules dirty

添加本地配置选项以忽略这些更改。


2

所以git v1.7.2-rc2有我想要的功能:

$ git diff --ignore-submodules=dirty vendor
# 没有输出
$ git status --ignore-submodules=dirty vendor
# 在分支上...
没有要提交的内容(工作目录干净)

自己构建git的步骤:

# get git
git clone git://git.kernel.org/pub/scm/git/git.git git
cd git
git checkout v1.7.2-rc2

# make git. beware of setting prefix
make configure
./configure --prefix=/usr/local
make
sudo make install

# you REALLY don't want to `make doc`, use this instead
sudo make quick-install-man
sudo make quick-install-html

1
我在这里数了七个git:git clone git://git.kernel.org/pub/scm/git/git.git git - dotancohen

1

你可能不想在.gitmodules中添加ignore = dirty,你可能希望更有选择性地忽略你想要忽略的更改。

为此,请将模式添加到.git/submodule_foo/bar/info/exclude中,其中submodule_foo/bar/是子模块的路径。

这些模式类似于您要添加到.gitignore的模式,根目录是子模块目录。例如,此模式忽略了子模块submodule_foo/bar/中的build目录:

# in .git/submodule_foo/bar/info/exclude:
/build/

3
我认为这将隐藏更改,即使在子模块内部。我只想在子模块外部隐藏更改。当我在子模块上积极工作时,如果它们出现在内部,那也没关系。 - Raphael Schweikert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接