Git diff说子项目很脏

mrw*_*ter 214 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
Run Code Online (Sandbox Code Playgroud)

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

Von*_*onC 252

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

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

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

您可以通过以下方式修复:

  • 在返回到父repo之前提交或撤消每个子模块中的更改/演变(其中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
Run Code Online (Sandbox Code Playgroud)

  • 你十年后的回答让我很困惑。不过,您 10 年前的原始答案仍然有效:“git submodule foreach --recursive git checkout”。 (3认同)
  • 还要知道的一件好事:您仍然可以执行git commit -a,而不必担心添加这些更改。尽管它们在前面标记有“ M”,但它们不会最终落入您的提交中。 (2认同)
  • 对我来说,我必须进入每个脏子模块并运行 `git clean -id`。 (2认同)
  • @GDP2 您可以在一行中完成,使用 `git submodule foreach --recursive git clean -id`(首先在备份存储库中进行测试;)) (2认同)
  • 解决此问题的方法是在受影响的子模块中执行“隐藏更改”(TortoiseGit 菜单项)。这应该会删除您未跟踪的文件并将它们保存到您的隐藏列表中。然后你应该能够很好地提交它,而不会显得很脏。提交后,您可以使用“Stash pop”恢复文件。 (2认同)

use*_*907 19

同时删除子模块然后运行git submodule init,git submodule update显然会做到这一点,但可能并不总是合适或可能.

  • 当我将一些现有文件夹转换为子模块然后拉到另一台仍然有旧文件夹的机器上时,这对我有用。 (2认同)

Ral*_*gen 16

不幸的是,似乎没有配置选项使"git diff --ignore-submodules"和"git status --ignore-submodules"成为全局默认值(但另请参阅在命令上设置git default flags).但是,您可以设置默认ignore您要忽略(适用于每个个体子模块配置选项git diffgit status)时,无论是在.git/config文件(仅限本地)或.gitmodules(将git的进行版本).例如:

[submodule "foobar"]
    url = git@bitbucket.org:foo/bar.git
    ignore = untracked
Run Code Online (Sandbox Code Playgroud)

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


小智 13

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


Jus*_*Bit 8

git submodule foreach --recursive git checkout .
Run Code Online (Sandbox Code Playgroud)

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

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


Dev*_*ool 8

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

git config --global diff.ignoreSubmodules dirty
Run Code Online (Sandbox Code Playgroud)

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

[diff]
  ignoreSubmodules = dirty
Run Code Online (Sandbox Code Playgroud)

可以在这里找到更多信息


dry*_*obs 6

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

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

[core]
  filemode = false
Run Code Online (Sandbox Code Playgroud)

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


Szy*_*ski 6

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

cd my-submodule
git push
cd ../
rm -rf my-submodule
git submodule init
git submodule update
Run Code Online (Sandbox Code Playgroud)

  • 我宁愿了解发生了什么,但这也是唯一对我有用的东西...... (4认同)