如何消除Git子模块未跟踪的状态?

190
我似乎无法摆脱Git子模块中未跟踪的内容。 运行git status会显示以下消息:
# 在分支主分支上
# 未提交的更改:
#    (使用“git add…”更新将要提交的内容)
#    (使用“git checkout --…”放弃工作目录中的更改)
#    (提交或丢弃子模块中未跟踪或修改的内容)
#
#    修改: bundle / snipmate(未跟踪的内容)
#    修改: bundle / surround(未跟踪的内容)
#    修改: bundle / trailing-whitespace(未跟踪的内容)
#    修改: bundle / zencoding(未跟踪的内容)
#
未添加任何更改以提交(使用“git add”和/或“git commit -a”)
添加--ignore-submodules参数可以隐藏这些消息;但我想知道是否有一种更合适、更核心的方法来消除这些问题。

3
这个回答:https://dev59.com/gm435IYBdhLWcg3w7k2b#5127213 引发了更多选择。 - charlax
12个回答

179

我发现这篇博客文章总体上是可行的。通过在.gitmodules文件中的每个条目中添加ignore = dirty选项。

[submodule "zen-coding-gedit3"]
    path = zen-coding-gedit3
    url = git://github.com/leafac/zen-coding-gedit3.git
    ignore = dirty

我的首选方案,因为它很容易自动化。 - lethal-guitar
40
值得一提的是 ignore = untracked 也存在,可以显示修改后的被追踪文件,但不包括未被追踪的文件。如果所有子模块都可以设置这个全局选项就好了。 - naught101
1
毫不意外,经过将近十年,博客文章的链接已经失效了。 :) - Jesse Adelman

118

由于git状态报告未跟踪的内容,实现干净状态的实际方法是进入每个子模块并执行以下操作:

  • add and commit the untracked contents,
  • or reference the untracked contents in a .gitignore specific to each module.
  • or you can add the same ignored content to the submodule's .git/info/exclude, as peci1 reports in the comments.
  • or add dirty to the submodule specification, as mentioned in ezraspectre's answer (upvoted).

    git config -f .gitmodules submodule.<path>.ignore untracked
    
  • or add a global .gitignore file (often ~/.gitignore-global). Like for example .DS_Store or in my case Carthage/Build as reported by Marián Černý in the comments. See .gitginore man page:

用户希望Git在所有情况下忽略的模式(例如,用户选择的编辑器生成的备份或临时文件)通常放在由core.excludesFile指定的文件中,该文件位于用户的~/.gitconfig中。其默认值为$XDG_CONFIG_HOME/git/ignore。如果$XDG_CONFIG_HOME未设置或为空,则使用$HOME/.config/git/ignore

7
+1,我差点就要尖叫了,直到找到这个......然后意识到在我的子模块中自动创建了一个.DS_Store文件(由OS X创建),阻止我提交主项目。烦死了!是时候更新.gitignore了... - Courtney Christensen
如果您没有子模块的推送权限,则无法与父存储库的其他用户共享对子模块所做的更改。@quincyglenn的解决方案似乎在这种情况下有效。 - Drew Noakes
@DrewNoakes 我同意。只是我更喜欢通过将它们添加到.gitignore或将它们添加到源代码控制来处理脏更改,而不是通过本地配置选项“隐藏”它们。 - VonC
1
@VonC,根据情况和个人喜好,两种答案都有道理。我想在这里强调这个区别,供其他人参考。顺便说一句,感谢您在SO上关于Git的众多回答--您帮助过我很多次。 - Drew Noakes
3
甚至可以不进行提交和创建 .gitignore 文件(它自己也会变成未跟踪状态)。打开子模块的.git/info/exclude文件,在这里添加忽略行(它的工作方式类似于 .gitignore,但不是共享存储库的一部分)。 - Martin Pecka
显示剩余3条评论

21

你也可以进入每个子模块的目录,像独立的git一样操作。

cd my/project/submodule
git status

... /获取修改过的文件列表/

git add .  //to add all of them to commit into submodule
git commit -m "message to your submodule repo"

你也可以使用以下命令更新远程子模块库:

git submodule update --remote

git submodule update

毕竟


5
如果没有审核修改过的文件,你可能不想执行 git add . 操作。大多数情况下,所做的更改是添加了 .DS_Store 文件,这应该被你的 .gitignore 拦截,如zourtney在答案的第一条评论中提到的那样。 - gregoltsov
2
如果你实际上并不想更新子模块,并且想要恢复到原始状态,那么你可能希望运行 git submodule update --force - Tom

11

这对我来说很完美地解决了问题:

git update-index --skip-worktree <path>

如果pathname不起作用,请尝试文件名。 如果这对你有用,请让我知道。


5

可能是由于子模块分支中的detached HEAD。如果是这种情况,请进入您的子模块路径(例如:./bundle/snipmate),然后运行git checkout master


1
但我不想要一个主分支,只是想找到一个特定的提交。 - V B

3
这可能是因为你在特定文件夹内有另一个隐藏的.git文件夹。如果出现以下情况:modified: ./../..(修改内容,未跟踪内容),请确保子目录中不包含此.git文件夹。如果确实存在这种情况,可以通过手动从子目录中删除.git文件夹来解决问题。"最初的回答"

2

昨天我遇到了一个问题,这个项目有近12个子模块。

git status 显示了输出。

# On branch master
# Changes not staged for commit:
#   (use "git add ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#   (commit or discard the untracked or modified content in submodules)
#
#   modified:   proj1 (untracked content)
#   modified:   proj1 (modified content, untracked content)
#   ...

为解决未跟踪内容错误,我需要使用 .gitignore 从所有子模块中删除未跟踪的文件(所有文件都是 python 生成的 *.pyc 和 *.pyo 文件)。
为解决另一个问题,我需要运行 git submodule update 命令来更新每个子模块。

1
在我的情况下,我会将模块克隆作为ZF2环境中新模块的起点。这样做会将自己的.git文件夹放入目录中。
解决方案是删除.git文件夹(您可能需要显示隐藏文件才能查看它)。

1
我更喜欢使用SourceTree,所以对我来说解决方案是在SourceTree中打开子模块存储库,这会显示所有未跟踪文件的列表。然后我将它们全部分组选择,再使用“删除”功能。我能够做到这一点是因为我知道所有未跟踪的文件实际上都不需要。

0
如果这只是一个临时问题,您可以进入子模块文件夹并运行git reset HEAD --hard,但您将失去子模块内所有的更改。

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