Git diff说子项目很脏

时间:2011-02-02 11:36:51

标签: git git-submodules

我刚刚运行了一个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

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

10 个答案:

答案 0 :(得分:240)

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

  

版本1.7.0及更高版本的git在git子模块的行为中包含annoying change
  如果子模块有任何已修改的文件或未跟踪的文件,则现在认为它们是脏的,而之前只有在子模块中的HEAD指向错误的提交时才会出现这种情况。

     

git子模块输出中加号(+)的含义已经改变,第一次遇到这个问题需要花一点时间来弄清楚出了什么问题,例如通过查找通过更改日志或在git.git上使用git bisect来查找更改。对于用户来说,为“在指定的版本中引入不同的符号,但是很脏”会更加友好。

你可以通过以下方式修复它:

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

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

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

Git 1.7.2中的新功能

作为Noam comments belowthis question提到,自git版本1.7.2起,您可以忽略脏子模块:

git status --ignore-submodules=dirty

答案 1 :(得分:18)

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

答案 2 :(得分:14)

编辑:这个答案(以及大多数其他答案)已经过时;见Devpool's answer instead

最初,没有配置选项来制作" git diff --ignore-submodules"和" git status --ignore-submodules"全局默认值(但另见Setting git default flags on commands)。另一种方法是在ignore文件中为git diffgit status设置要忽略的每个子模块的默认.git/config配置选项(仅限本地) )或.gitmodules(将由git版本化)。例如:

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

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

答案 3 :(得分:13)

这种情况是因为您对子模块的指针不是子模块目录中的实际指针。要解决此问题,您必须再次运行git submodule update

答案 4 :(得分:8)

git submodule foreach --recursive git checkout .

这对我来说不起作用,但是它给了我一个文件列表(在我的情况下只有一个)在子模块中已被更改(没有我在那里做任何事情)。

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

答案 5 :(得分:6)

我最终删除了子模块目录并再次初始化

cd my-submodule
git push
cd ../
rm -rf my-submodule
git submodule init
git submodule update

答案 6 :(得分:6)

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

git config --global diff.ignoreSubmodules dirty

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

[diff]
  ignoreSubmodules = dirty

可以找到更多信息here

答案 7 :(得分:5)

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

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

[core]
  filemode = false

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

答案 8 :(得分:1)

您对您的存储库有足够的权限吗?

我的解决方案与 git 无关,但是我看到了相同的错误消息,以及子模块的 dirty 状态。

根本原因是 .git 文件夹中的某些文件归 root 所有,因此 git 没有写入权限,因此 git 无法更改 <以我的用户身份运行时子模块的 em>dirty 状态。

你有同样的问题吗?

从存储库的根文件夹中,使用 find 列出根拥有的文件 [可选]

find .git -user root

解决方案 [Linux]

.git 文件夹中的所有文件更改为作为所有者

sudo chown -R $USER:$USER .git

# alternatively, only the files listed in the above command...
sudo find .git -user root -exec chown $USER:$USER {} +

这是怎么发生的?

就我而言,我在 docker 容器的子模块中构建了库,docker 守护进程传统上作为 root 运行,因此创建的文件属于 root:root 所有权。

我的用户通过该服务通过代理获得 root 权限,因此即使我没有 sudo 任何内容,我的 git 存储库仍然拥有 root 拥有的更改。

我希望这对某人有所帮助,请移步这里。

答案 9 :(得分:0)

在我的情况下,我不确定导致这种情况发生的原因,但我知道我只是想将子模块重置为最新的远程提交并完成它。这包括在这里结合几个不同问题的答案:

git submodule update --recursive --remote --init

来源:

How do I revert my changes to a git submodule?

Easy way to pull latest of all git submodules