Git diff说子项目很脏


227

我刚刚运行了git diff,我的大约10个子模块都得到了以下输出

diff --git a/.vim/bundle/bufexplorer b/.vim/bundle/bufexplorer
--- a/.vim/bundle/bufexplorer
+++ b/.vim/bundle/bufexplorer
@@ -1 +1 @@
-Subproject commit 8c75e65b647238febd0257658b150f717a136359
+Subproject commit 8c75e65b647238febd0257658b150f717a136359-dirty

这是什么意思?我如何解决它?

Answers:


268

如Mark Longair的博客文章Git Submodules Explained中所述

git的1.7.0及更高版本在git子模块的行为中包含一个令人讨厌的更改
现在,如果子模块具有任何已修改的文件或未跟踪的文件,则它们被视为脏文件,而以前,只有子模块中的HEAD指向错误的提交时,情况才会如此。

+git子模块的输出中加号()的含义已更改,并且您第一次遇到此问题需要花费一些时间来找出问题所在,例如通过查看changelog或在git上使用git bisect .git查找更改。对于用户来说,为“在指定的版本,但脏的”引入一个不同的符号本来会好得多。

您可以通过以下方法修复它:

  • 在返回父仓库之前(在diff不再报告“脏”文件的地方)之前,提交或撤消每个子模块中的更改/更改。要将子模块的所有更改撤消到子模块cd的根目录中,然后执行git checkout .

    dotnetCarpenter 评论您可以执行以下操作:git submodule foreach --recursive git checkout .

  • 或添加--ignore-submodules到中git diff,以暂时忽略那些“脏”子模块。

Git版本1.7.2的新功能

正如Noam 在下面的评论中这个问题提到,从git版本1.7.2开始,您可以使用以下命令忽略脏的子模块:

git status --ignore-submodules=dirty

2
还要知道的一件好事:您仍然可以执行,git commit -a而不必担心添加这些更改。尽管它们M在前面带有标记,但它们最终不会出现在您的提交中。
gitaarik 2014年

1
对我来说,我必须进入每个脏的子模块并运行git clean -id
GDP2

1
@ GDP2,您可以在同一行中使用git submodule foreach --recursive git clean -id(必须先在备份存储库中进行测试;))
VonC

1
在我一直莫名其妙地看到这种情况的情况下,发生的事情是我有未跟踪的文件,该文件不在子模块的中.gitignore。将它们添加到此处或添加到我的全局忽略列表中已解决的问题。

21

同样,删除子模块然后运行git submodule initgit submodule update显然可以解决问题,但可能并不总是合适或可能的。


1
当我将一些现有的文件夹转换为子模块,然后拉到仍然具有旧文件夹的另一台机器上时,这对我有用。
Roger Lipscombe

18

要忽略任何子模块中的所有未跟踪文件,请使用以下命令忽略这些更改。

git config --global diff.ignoreSubmodules dirty

它将以下配置选项添加到本地git配置中:

[diff]
  ignoreSubmodules = dirty

可以在这里找到更多信息


16

编辑:这个答案(和大多数其他答案)已经过时了;请参阅Devpool的答案


最初,没有配置选项可以使“ git diff --ignore-submodules”和“ git status --ignore-submodules”成为全局默认值(但另请参见在命令上设置git default标志)。一种替代方法是在文件(仅适用于本地)或(将由git版本化)中ignore为每个要忽略的子模块(git diff和和git status)设置默认配置选项。例如:.git/config.gitmodules

[submodule "foobar"]
    url = git@bitbucket.org:foo/bar.git
    ignore = untracked

ignore = untracked只忽略未跟踪的文件,ignore = dirty也忽略修改的文件,也忽略ignore = all提交。显然没有办法对所有子模块使用通配符。


13

之所以如此,是因为子模块的指针实际上不是子模块目录中的指针。要解决此问题,必须git submodule update再次运行:


9
git submodule foreach --recursive git checkout .

这对我来说并没有解决问题,但它给了我一个在子模块中更改过的文件列表(在我的情况下,只有一个文件)(我在那里没有做任何事情)。

所以我可以转到子模块,git status显示我的HEAD已分离-> git checkout master,git status再次查看修改后的文件,git checkout> filename <,git pull,一切正常。



6

如果启用了文件模式设置并且您在子模块子树中更改了文件权限,则子模块可能被标记为脏。

要在子模块中禁用文件模式,您可以编辑/.git/modules/path/to/your/submodule/config并添加

[core]
  filemode = false

如果要忽略所有脏状态,则可以ignore = dirty/.gitmodules文件中设置属性,但我认为最好只禁用filemode。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.