如何删除子模块?
如何删除 Git 子模块? 为什么我做不到 git 子模块 rm module_name
?
How do I remove a Git submodule?
Why can't I dogit submodule rm module_name
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
如何删除 Git 子模块? 为什么我做不到 git 子模块 rm module_name
?
How do I remove a Git submodule?
Why can't I dogit submodule rm module_name
?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(30)
在现代 git 中(我在 2022 年写这篇文章,并更新了
git
安装),这已经变得相当简单了:git rm;
,然后提交。这将删除
处的文件树以及.gitmodules
文件中的子模块条目。 即存储库中子模块的所有痕迹都将被删除。作为文档说明 但是,子模块的
.git
目录保留在周围(在modules/
目录中)主项目的.git
目录),“无需从另一个存储库获取即可签出过去的提交”。如果您仍然想删除此信息,请手动删除
.git/modules/
中的子模块目录,并删除文件.git/config
中的子模块条目。 这些步骤可以使用命令较旧的社区 wiki 说明:
通过页面 Git 子模块教程< /em>:
要删除子模块,您需要:
.gitmodules
文件中删除相关部分。.gitmodules
更改:git add .gitmodules
.git/config
中删除相关部分。git rm --cached path_to_submodule
(无尾部斜杠)。.git
目录:rm -rf .git/modules/path_to_submodule
git commit -m "Removed submodule"
rm -rf path_to_submodule
另请参阅:以下替代步骤。
In modern git (I'm writing this in 2022, with an updated
git
installation), this has become quite a bit simpler:git rm <path-to-submodule>
, and commit.This removes the filetree at
<path-to-submodule>
, and the submodule's entry in the.gitmodules
file. I.e. all traces of the submodule in your repository proper are removed.As the docs note however, the
.git
dir of the submodule is kept around (in themodules/
directory of the main project's.git
dir), "to make it possible to checkout past commits without requiring fetching from another repository".If you nonetheless want to remove this info, manually delete the submodule's directory in
.git/modules/
, and remove the submodule's entry in the file.git/config
. These steps can be automated using the commandsrm -rf .git/modules/<path-to-submodule>
, andgit config --remove-section submodule.<path-to-submodule>
.Older community wiki instructions:
Via the page Git Submodule Tutorial:
To remove a submodule you need to:
.gitmodules
file..gitmodules
changes:git add .gitmodules
.git/config
.git rm --cached path_to_submodule
(no trailing slash)..git
directory:rm -rf .git/modules/path_to_submodule
git commit -m "Removed submodule <name>"
rm -rf path_to_submodule
See also: alternative steps below.
自 git1.8.3 ( 2013 年 4 月 22 日):
删除过程也使用
git rm
(自 2013 年 10 月 git1.8.5 起)。摘要
3步删除过程将是:
解释
rm -rf
:这在Daniel中提到施罗德的答案,并由Eonil 在git rm
:请参阅提交 95c16418:git submodule deinit
:它源于 此补丁:如果(反)初始化步骤(
.git/config
和.git/modules/xxx
)自 git1.8.5 开始,
git rm
code> 还负责:add
”步骤,该步骤在.gitmodules
文件中记录子模块的 url:需要为你删除。git rm --cached path_to_submodule
(无尾部斜杠)这将删除存储在索引中的特殊模式“160000”的目录,并将其标记为子模块根目录。
如果您忘记了最后一步,并尝试将子模块添加为常规目录,您将收到如下错误消息:
注意:自 Git 2.17 (Q2 2018) 起,git submodule deinit 不再是 shell 脚本。
这是对 C 函数的调用。
请参阅 提交 2e61273、提交 1342476(2018 年 1 月 14 日),作者:Prathamesh Chavan (
pratham-pc
)。(由 Junio C Hamano --
gitster
-- 合并于 提交 ead8dbe,2018 年 2 月 13 日)Since git1.8.3 (April 22d, 2013):
The deletion process also uses
git rm
(since git1.8.5 October 2013).Summary
The 3-steps removal process would then be:
Explanation
rm -rf
: This is mentioned in Daniel Schroeder's answer, and summarized by Eonil in the comments:git rm
: See commit 95c16418:git submodule deinit
: It stems from this patch:This takes care if the (de)initialization steps (
.git/config
and.git/modules/xxx
)Since git1.8.5, the
git rm
takes also care of the:add
' step which records the url of a submodule in the.gitmodules
file: it is need to removed for you.git rm --cached path_to_submodule
(no trailing slash)That will remove that directory stored in the index with a special mode "160000", marking it as a submodule root directory.
If you forget that last step, and try to add what was a submodule as a regular directory, you would get error message like:
Note: since Git 2.17 (Q2 2018), git submodule deinit is no longer a shell script.
It is a call to a C function.
See commit 2e61273, commit 1342476 (14 Jan 2018) by Prathamesh Chavan (
pratham-pc
).(Merged by Junio C Hamano --
gitster
-- in commit ead8dbe, 13 Feb 2018)要删除添加的子模块,请使用:
运行:
就是这样。
对于旧版本的 git(大约 1.8.5,实际上甚至在 2.26.2 中)使用:
To remove a submodule added using:
Run:
That's it.
For old versions of git (circa ~1.8.5, actually even in 2.26.2) use:
简单步骤
git config -f .git/config --remove-section submodule.$submodulename
git config -f .gitmodules --remove-section submodule.$submodulename
git rm --cached $submodulepath
rm - rf $submodulepath
rm -rf .git/modules/$submodulename
请注意:
$submodulepath
不包含前导斜杠或尾随斜杠。背景
当你执行
git submodule add
时,它只会将其添加到.gitmodules
,但是一旦你执行了 git submodule init ,它就会添加到 .git/config 。
因此,如果您希望删除模块,但能够快速恢复它,
然后这样做:
最好先执行 git rebase HEAD 并执行 git commit
最后,如果您将其放入脚本中。
另请查看我可以取消填充 Git 子模块吗?的答案。
Simple steps
git config -f .git/config --remove-section submodule.$submodulename
git config -f .gitmodules --remove-section submodule.$submodulename
git rm --cached $submodulepath
rm -rf $submodulepath
rm -rf .git/modules/$submodulename
Please note:
$submodulepath
doesn't contain leading or trailing slashes.Background
When you do
git submodule add
, it only adds it to.gitmodules
, butonce you did
git submodule init
, it added to.git/config
.So if you wish to remove the modules, but be able to restore it quickly,
then do just this:
It is a good idea to do
git rebase HEAD
first andgit commit
at the end, if you put this in a script.
Also have a look at an answer to Can I unpopulate a Git submodule?.
这个问题的大多数答案都是过时的、不完整的或不必要的复杂。
使用 git 1.7.8 或更高版本克隆的子模块将在本地存储库中最多留下四个痕迹。 删除这四个痕迹的过程由以下三个命令给出:
The majority of answers to this question are outdated, incomplete, or unnecessarily complex.
A submodule cloned using git 1.7.8 or newer will leave at most four traces of itself in your local repo. The process for removing those four traces is given by the three commands below:
只是一个注释。 从 git 1.8.5.2 开始,两个命令就可以了:
正如 @Mark Cheverton 的答案正确指出的那样,如果不使用第二行,即使您现在删除了子模块,剩余的 .git/modules/the_submodule 文件夹将阻止将来不会添加或替换相同的子模块。 另外,正如 @VonC 提到的, git rm 将在子模块上完成大部分工作。
--更新 (07/05/2017)--
澄清一下,
the_submodule
是项目内子模块的相对路径。 例如,如果子模块位于子目录subdir
内,则为subdir/my_submodule
。正如评论和其他答案中正确指出的那样,这两个命令(尽管功能上足以删除子模块),请保留
.git/config
的[submodule "the_submodule"]
部分中的跟踪(截至 2017 年 7 月),可以使用第三个命令将其删除:Just a note. Since git 1.8.5.2, two commands will do:
As @Mark Cheverton's answer correctly pointed out, if the second line isn't used, even if you removed the submodule for now, the remnant .git/modules/the_submodule folder will prevent the same submodule from being added back or replaced in the future. Also, as @VonC mentioned,
git rm
will do most of the job on a submodule.--Update (07/05/2017)--
Just to clarify,
the_submodule
is the relative path of the submodule inside the project. For example, it'ssubdir/my_submodule
if the submodule is inside a subdirectorysubdir
.As pointed out correctly in the comments and other answers, the two commands (although functionally sufficient to remove a submodule), do leave a trace in the
[submodule "the_submodule"]
section of.git/config
(as of July 2017), which can be removed using a third command:我发现
deinit
对我很有用:来自 git文档:
I found
deinit
works good for me:From git docs:
我必须按照 John Douthat 的步骤更进一步,
cd
进入子模块的目录,然后删除 Git 存储库:然后我可以将这些文件作为父 Git 存储库的一部分提交,而无需旧的引用一个子模块。
I had to take John Douthat's steps one step further and
cd
into the submodule's directory, and then remove the Git repository:Then I could commit the files as a part of the parent Git repository without the old reference to a submodule.
使用 git v2.7.4,简单的 3 个步骤就可以了。
With git v2.7.4 simple 3 steps worked just fine.
从 git 中删除子模块的最佳方法:
The best way to remove a submodule from git:
在我看来,您可以通过以下三个步骤来完成此
操作此命令将删除内容
现在删除目录
最后一步是从子模块文件中删除条目
这不是从.git层次结构中删除模块目录
In my opinion you can do this with below three steps
This command will delete content
Now remove the directory
The last step is to remove entry from submodule file
This is not it delete module directory from .git hierarchy
以下是我认为必要或有用的 4 个步骤(首先是重要的步骤):
理论上,步骤 1 中的
git rm
应该注意它。 希望OP问题的第二部分有一天能够得到积极的回答(这可以通过一个命令完成)。但截至 2017 年 7 月,需要执行第 2 步来删除 .git/modules/ 中的数据,否则您以后将无法添加子模块。
正如 tinlyx 的回答 所指出的,对于 git 1.8.5+,您可能可以摆脱上述两个步骤,正如所有
git submodule
命令似乎有效。步骤 3 删除文件
.git/config
中的the_submodule
部分。 为了完整性,应该这样做。 (该条目可能会导致较旧的 git 版本出现问题,但我没有要测试的版本)。为此,大多数答案建议使用 git submodule deinit 。 我发现使用 git config -f .git/config --remove-section 更明确且更容易混淆。 根据 git-submodule 文档,
git deinit
:最后但并非最不重要的一点是,如果您不
git commit
,那么在执行git submodule summary
时您将/可能会收到错误(从 git 2.7 开始):这与无论您执行步骤 2 还是步骤 3。
Here are the 4 steps that I found necessary or useful (important ones first):
In theory,
git rm
in step 1 should take care of it. Hopefully, the second part of OP question can be answered positively one day (that this can be done in one command).But as of July 2017, step 2 is necessary to remove data in
.git/modules/
for otherwise, you can't e.g. add the submodule back in the future.You can probably get away with the above two steps for git 1.8.5+ as tinlyx's answer noted, as all
git submodule
commands seem to work.Step 3 removes the section for
the_submodule
in the file.git/config
. This should be done for completeness. (The entry may cause problems for older git versions, but I don't have one to test).For this, most answers suggest using
git submodule deinit
. I find it more explicit and less confusing to usegit config -f .git/config --remove-section
. According to the git-submodule documentation,git deinit
:Last but not least, if you don't
git commit
, you will/may get an error when doinggit submodule summary
(as of git 2.7):This is regardless of whether you do steps 2 or 3.
我按照同一指南中的说明进行操作
如何删除子模块?
但它一直说:
所以我所做的就是在 .gitignore 中包含路径,如下所示(路径末尾没有星号):
然后我修改了任何文件并进行了简单推送:
I followed the instructions from this very same guide
How do I remove a submodule?
But it kept saying:
So what I did is including the path in .gitignore like this (With no asterisk in the end of the path):
Then I modified any file and did a simple push:
我刚刚找到了 .gitmodules 隐藏文件,它有一个列表...您可以通过这种方式单独删除它们。 我只有一张,所以我把它删除了。 很简单,但它可能会弄乱 Git,因为我不知道子模块是否附加了任何东西。 到目前为止看起来还不错,除了 libetpan 常见的升级问题之外,但这(希望)无关。
I just found the
.gitmodules
hidden file, it has a list... you can erase them individually that way. I just had one, so I deleted it. Simple, but it might mess up Git, since I don't know if anything's attached to the submodule. Seems ok so far, aside from libetpan's usual upgrade issue, but that's (hopefully) unrelated.对于 git 2.17 及更高版本,它只是:
With git 2.17 and above it's just:
如果您刚刚添加了子模块,例如,您只是添加了错误的子模块或将其添加到了错误的位置,只需执行 git stash 然后删除该文件夹即可。 这是假设添加子模块是您在最近的存储库中所做的唯一事情。
If you have just added the submodule, and for example, you simply added the wrong submodule or you added it to the wrong place, simply do
git stash
then delete the folder. This is assuming that adding the submodule is the only thing you did in the recent repo.总而言之,这是你应该做的:
设置path_to_submodule var(无尾部斜杠):
从.gitmodules文件中删除相关行:
从.git/config中删除相关部分
取消阶段并删除$path_to_submodule仅从索引中(以防止丢失信息)
跟踪对 .gitmodules 所做的更改
提交超级项目
删除现在未跟踪的子模块文件
另请参阅:替代指南
To summarize, this is what you should do :
Set path_to_submodule var (no trailing slash):
Delete the relevant line from the .gitmodules file:
Delete the relevant section from .git/config
Unstage and remove $path_to_submodule only from the index (to prevent losing information)
Track changes made to .gitmodules
Commit the superproject
Delete the now untracked submodule files
See also : Alternative guide lines
除了建议之外,我还必须 rm -Rf .git/modules/path/to/submodule 才能添加具有相同名称的新子模块(在我的例子中,我正在替换用原来的叉子)
In addition to the recommendations, I also had to
rm -Rf .git/modules/path/to/submodule
to be able to add a new submodule with the same name (in my case I was replacing a fork with the original)您可以使用别名来自动化其他人提供的解决方案:
将其放入您的 git 配置中,然后您可以执行以下操作:
git rms path/to/submodule
You can use an alias to automate the solutions provided by others:
Put that in your git config, and then you can do:
git rms path/to/submodule
总而言之,这就是您应该做的:
设置
path_to_submodule
var(无尾部斜杠):path_to_submodule=path/to/submodule
从 .gitmodules 文件中删除相关行:
git config -f .gitmodules --remove-section submodule.$path_to_submodule
从.git/config中删除相关部分
git config -f .git/config --remove-section submodule.$path_to_submodule
仅从索引中取消暂存并删除 $path_to_submodule(以防止丢失信息)
git rm --cached $path_to_submodule
跟踪对 .gitmodules 所做的更改
git add .gitmodules
提交超级项目
git commit -m "Remove submodule submodule_name"
删除现在未跟踪的子模块文件
rm -rf $path_to_submodule
rm -rf .git/modules/$path_to_submodule
To summarize, this is what you should do :
Set
path_to_submodule
var (no trailing slash):path_to_submodule=path/to/submodule
Delete the relevant line from the .gitmodules file:
git config -f .gitmodules --remove-section submodule.$path_to_submodule
Delete the relevant section from .git/config
git config -f .git/config --remove-section submodule.$path_to_submodule
Unstage and remove $path_to_submodule only from the index (to prevent losing information)
git rm --cached $path_to_submodule
Track changes made to .gitmodules
git add .gitmodules
Commit the superproject
git commit -m "Remove submodule submodule_name"
Delete the now untracked submodule files
rm -rf $path_to_submodule
rm -rf .git/modules/$path_to_submodule
如果由于您添加、提交和推送已经是 Git 存储库(包含
.git
)的文件夹而意外添加了子模块,则您将不会有要编辑的 .gitmodules
文件,或 .git/config 中的任何内容。 在这种情况下,您需要的只是:FWIW,在执行
git add< 之前,我还删除了
.git
文件夹/代码>。If the submodule was accidentally added because you added, committed and pushed a folder that was already a Git repository (contained
.git
), you won’t have a.gitmodules
file to edit, or anything in.git/config
. In this case all you need is :FWIW, I also removed the
.git
folder before doing thegit add
.git submodule deinit
.gitmodules
中删除该部分git rm
git add .gitmodules
git submodule deinit <path to submodule>
.gitmodules
git rm <path to submodule>
git add .gitmodules
在尝试了该站点上的所有不同答案之后,我最终得到了这个解决方案:
这将恢复与添加子模块之前完全相同的状态。 您可以立即再次添加子模块,这对于此处的大多数答案来说是不可能的。
这使您可以进行干净的结账,无需提交任何更改。
这是用以下方法测试的:
After experimenting with all the different answers on this site, I ended up with this solution:
This restores the exact same state as before you added the submodule. You can right away add the submodule again, which was not possible with most of the answers here.
This leaves you with a clean checkout with no changes to commit.
This was tested with:
2012 年 12 月我目前正在做的事情(结合了大部分答案):
What I'm currently doing Dec 2012 (combines most of these answers):
这是我所做的:
1.) 从 .gitmodules 文件中删除相关部分。 您可以使用以下命令:
2.) 暂存
.gitmodules
更改3.) 从
.git/config
中删除相关部分。 您可以使用以下命令:4.) 删除 gitlink (无尾部斜杠):
5.) 清理
.git/modules
:6.) 提交:
7.) 删除现在未跟踪的子模块文件
Here is what I did :
1.) Delete the relevant section from the .gitmodules file. You can use below command:
2.) Stage the
.gitmodules
changes3.) Delete the relevant section from
.git/config
. You can use below command:4.) Remove the gitlink (no trailing slash):
5.) Cleanup the
.git/modules
:6.) Commit:
7.) Delete the now untracked submodule files
所有答案看起来都已经过时了。 我正在使用 git 版本
2.28.0
。 一行答案是,但是,即使子模块已从源代码管理中删除,.git/modules/path-to-submodule 仍然包含子模块存储库,并且 .git/config 包含其 URL,因此您仍然需要手动删除它们:
有时,您必须使用
-f
标志:例如,因为您可能会收到如下错误:
All the answers look outdated. I am using git version
2.28.0
. One line answer is,However, even though the submodule is removed from source control, .git/modules/path-to-submodule still contains the submodule repository and .git/config contains its URL, so you still have to remove those manually:
Sometimes, you have to use the
-f
flag:For example, because you might get an error like this:
我最近发现一个 git 项目,其中包含许多有用的 git 相关命令: https://github.com/visionmedia /git-extras
安装它并输入:
然后事情就完成了。 子模块目录将从您的存储库中删除,但仍然存在于您的文件系统中。 然后,您可以提交更改,例如:
git commit -am "Remove the submodule"
。I recently find out a git project which include many useful git related command: https://github.com/visionmedia/git-extras
Install it and type :
Then things are done. The submodule directory will be removed from your repo and still exist in your filesystem. You can then commit the change like:
git commit -am "Remove the submodule"
.为了读者的利益,本文试图对其进行总结,并提供有关如何在事情未按预期进行时进行操作的分步指南。 以下是
git
版本2.17
及更高版本经过测试且安全的方法,用于删除子模块:2.20.1
和 Ubuntu 18.042.17.1
进行测试。"$submodule"
只是强调在哪里放置名称,并且必须小心空格等"$submodule"< /code> 使用 Windows 方式正确指定子模块的路径。 (我不是Windows)
请注意,这
是直接相反的
,但
也完全相反,
因为有些命令基本上需要做的不仅仅是一件事:
.git/config
git rm
.gitmodules
git submodule add
.git/modules/NAME/
git submodule init
,因此更新.git/config
git 子模块更新
,因此,非递归地检查模块.gitmodules
git submodule update --init --recursive --模块
这不能完全对称,因为保持严格对称没有多大意义。 根本不需要两个以上的命令。 此外,“拉入数据”是隐式的,因为您需要它,但不会删除缓存的信息,因为这根本不需要,并且可能会擦除宝贵的数据。
这确实让新手感到困惑,但基本上是一件好事:
git
只是做了明显的事情并且做得正确,甚至没有尝试做更多的事情。git
是一个工具,它必须完成可靠的工作,而不仅仅是另一个“Eierlegende Wollmilchsau”(“Eierlegende Wollmilchsau”对我来说是“某种邪恶版本的瑞士军刀”)。所以我理解人们的抱怨,“为什么不做 git 对我来说显而易见的事情”。 这是因为这里的“显而易见”取决于观点。 在每种情况下的可靠性都更为重要。 因此,对您来说显而易见的事情通常并不是在所有可能的技术情况下都是正确的。 请记住:AFAICS
git
遵循技术路径,而不是社交路径。 (因此有一个聪明的名字:git)如果失败
上述命令可能会因以下原因失败:
git
太旧了。 然后使用更新的git
。 (请参阅下面的操作方法。)git
不支持的事情。 那么你就处于黑暗的一面,事情会变得丑陋和复杂。 (也许使用另一台机器可以修复它。)git
高级用户。)可能的修复如下。
使用较新的
git
如果您的机器太旧,则
git
中没有submodule deinit
。 如果您不想(或可以)更新您的git
,那么只需使用另一台具有较新git
的计算机即可!git
意味着完全分布式,因此您可以使用另一个git
来完成工作:workhorse:~/path/to/worktree$ git status - -porcelain
不得输出任何内容! 如果是这样,请先清理东西!workhorse:~/path/to/worktree$ ssh account@othermachine
othermachine:~$ git clone --recursive me@workhorse path/to/worktree/.git TMPWORK && cd TMPWORK
othermachine:~/TMPWORK$ git commit 。 -m。 && 退出
workhorse:~/path/to/worktree$ git fetch account@othermachine:TMPWORK/.git
workhorse:~/path/to/worktree$ git merge --ff -仅 FETCH_HEAD
。 如果这不起作用,请使用 git reset --soft FETCH_HEAD这个
othermachine
可以是某个VM,也可以是Windows下的某个Ubuntu WSL,等等。 甚至是chroot
(但我假设您不是 root,因为如果您是root
,更新到较新的git
应该更容易>)。请注意,如果您无法通过 ssh 登录,可以使用多种方法来传输 git 存储库。 您可以将工作树复制到某个 USB 记忆棒(包括
.git
目录)上,然后从该记忆棒进行克隆。 克隆副本,只是为了再次以干净的方式获取内容。 这可能是 PITA,以防您的子模块无法从其他机器直接访问。 但也有一个解决方案:您可以使用这个乘法,并将其保存到
$HOME/.gitconfig
中。 事情类似重写 URL 之类的
就很容易了
如果您开始习惯像这样强大的
git
功能,那么。 首先清理东西
手动清理是很好的,因为这样你可能会发现一些你忘记的东西。
git status
和git clean -ixfd
是你的朋友rm
和deinit 选项
只要你可以。 如果您是专业人士,git
的选项(如-f
)非常有用。 但当您来到这里时,您可能在submodule
领域没有那么丰富的经验。 因此,安全总比后悔好。示例:
您会看到,
submodule deinit
上不需要-f
。 如果事情是干净的,从git clean
的意义上来说。 另请注意,不需要 git clean -x 。 这意味着git submodule deinit
无条件删除被忽略的未跟踪文件。这通常是您想要的,但不要忘记它。 有时被忽略的文件可能很宝贵,例如缓存的数据需要数小时到数天才能再次计算。为什么永远不要删除
$GIT_DIR/modules//
?人们可能想删除缓存的存储库,因为他们担心以后会遇到问题。 确实如此,但遇到那个“问题”才是解决问题的正确方法! 因为修复很容易,而且做得正确,您将能够永远幸福地生活。 这样就避免了比你自己删除数据更麻烦的麻烦。
示例:
最后一行输出以下错误:
为什么会出现此错误? 因为
.git/modules/two/
之前是从 https://github 填充的。 com/hilbix/empty.git 现在应该从其他内容重新填充,即 https: //github.com/hilbix/src.git。 如果您从 https://github.com/hilbix/empty 重新填充它,您将不会看到此内容。 git现在该怎么办? 好吧,就按照吩咐去做吧! 使用
--name someunusedname
.gitmodules
然后看起来像ls -1p .git/modules/
给出这种方式将来你可以切换分支/向前和向后提交,并且永远不会再遇到任何麻烦,因为
two/
有两个不同的(并且可能不兼容的)上游存储库。 最好的是:您也可以将两者缓存在本地。git
)。但是,如果您删除了缓存目录,则两个不同的签出都会互相绊倒,因为您不会使用
--name
选项,对吧? 因此,每次进行结帐时,您可能都必须一次又一次地删除.git/modules//
目录。 这非常麻烦,并且很难使用像 git bisect 这样的东西。因此,保留此模块目录作为占位符是有非常技术性的原因的。 建议删除
.git/modules/
下面的内容的人要么不了解,要么忘记告诉您,这使得像git bisect
这样的强大功能几乎无法使用,如果这样的话跨越了这样的子模块不兼容性。进一步的原因如上所示。 查看
ls
。 你在那里看到什么?嗯,模块
two/
的第二个变体不在.git/modules/two/
下,而是在.git/modules/someunusedname/
下>! 所以像 git rm $module; 这样的东西 rm -f .git/module/$module 完全错误! 您必须查阅module/.git
或.gitmodules
才能找到要删除的正确内容!因此,不仅大多数其他答案都落入了这个危险的陷阱,甚至非常流行的
git 扩展程序有此错误
(现已修复)! 因此,如果您不确切知道您在做什么,最好保留
.git/
目录!仅供参考,您可能已经猜到了:hilbix 是我的 GitHub 帐户。
For the benefit of the reader, this here tries to sum it up and give a step-by-step guide on how to do it if things do not work as expected. Following is the tested and safe way for
git
version2.17
and above to get rid of a submodule:2.20.1
and Ubuntu 18.042.17.1
."$submodule"
is just to emphasize where to put the name, and that you have to be careful with spaces and the like"$submodule"
with the Windows way of a properly specified path to the submodule. (I am not Windows)Note that
is the direct inverse to
but
also is quite the inverse to
because some commands basically need to do more than just a single thing:
git submodule deinit -- module
.git/config
git rm
.gitmodules
git submodule add
.git/modules/NAME/
git submodule init
, so updates.git/config
git submodule update
, so, nonrecursively checks out the module.gitmodules
git submodule update --init --recursive -- module
This cannot be fully symmetric, as keeping it strictly symmetric does not make much sense. There simply is no need for more than two commands. Also "pulling in the data" is implicit, because you need it, but removing the cached information is not done, because this is not needed at all and might wipe precious data.
This truly is puzzling to newcomers, but basically is a good thing:
git
just does the obviously thing and does that right, and does not even try to do more.git
is a tool, which must do a reliable job, instead of being just another "Eierlegende Wollmilchsau" ("Eierlegende Wollmilchsau" translates for me to "some evil version of a Swiss army knife").So I understand complaints of people, saying "Why doesn't do
git
the obvious thing for me". This is because "obvious" here depends from the point of view. Reliability in each and every situation is far more important. Hence what's obvious for you often is not the right thing in all possible technical situations. Please remember that: AFAICSgit
follows the technical path, not the social one. (Hence the clever name: git)If this fails
The commands above may fail due to following:
git
is too old. Then use a newergit
. (See below how to.)git clean
sense. Then first clean your submodule using that command. (See below.)git
. Then you are on the dark side and things get ugly and complicated. (Perhaps using another machine fixes it.)git
power-user.)Possible fixes follow.
Use a newer
git
If your machine is too old there is no
submodule deinit
in yourgit
. If you do not want (or can) update yourgit
, then just use another machine with a newergit
!git
is meant to be fully distributed, so you can use anothergit
to get the job done:workhorse:~/path/to/worktree$ git status --porcelain
must not output anything! If it does, cleanup things first!workhorse:~/path/to/worktree$ ssh account@othermachine
othermachine:~$ git clone --recursive me@workhorse path/to/worktree/.git TMPWORK && cd TMPWORK
othermachine:~/TMPWORK$ git commit . -m . && exit
workhorse:~/path/to/worktree$ git fetch account@othermachine:TMPWORK/.git
workhorse:~/path/to/worktree$ git merge --ff-only FETCH_HEAD
. If this does not work, usegit reset --soft FETCH_HEAD
git status
is clean again. You are able to do so, because you have had it clean before, thanks to the first step.This
othermachine
can be some VM, or some Ubuntu WSL under Windows, whatever. Even achroot
(but I assume that you are non-root, because if you areroot
it should be more easy to update to the newergit
).Note that if you cannot
ssh
in, there are trainloads of ways to transportgit
repositories. You can copy your worktree on some USB stick (including the.git
directory), and clone from the stick. Clone the copy, just to get things in a clean fashion again. This might be a PITA, in case your submodules are not accessible from othermachine directly. But there is a solution for this, too:You can use this multiply, and this is saved into
$HOME/.gitconfig
. Something likerewrites URLs like
into
It's easy if you start to become accustomed to powerful
git
features like this.Cleanup things first
Cleaning manually up is good, because this way you perhaps detect some things you forgot about.
git status
andgit clean -ixfd
is your friendrm
anddeinit
as long as you can. Options (like-f
) forgit
are good if you are a Pro. But as you came here, you probably are not so experienced in thesubmodule
area. So better be safe than sorry.Example:
You see, there is no
-f
needed onsubmodule deinit
. If things are clean, in agit clean
sense. Also note thatgit clean -x
is not needed. This meansgit submodule deinit
unconditionally removes untracked files which are ignored. This is usually what you want, but do not forget about it. Sometimes ignored files might be precious, like cached data which takes hours to days to be calculated again.Why never remove
$GIT_DIR/modules/<name>/
?Probably people want to remove the cached repository, because they are afraid to run into a problem later. This is true, but running into that "problem" is the correct way to solve it! Because the fix is easy, and done right you will be able to live happily ever after. This avoids more cumbersome trouble than when you remove the data yourself.
Example:
The last line outputs following error:
Why this error? Because
.git/modules/two/
previously was populated from https://github.com/hilbix/empty.git and now shall be re-populated from something else, namely https://github.com/hilbix/src.git. You won't see this if you re-populate it from https://github.com/hilbix/empty.gitWhat to do now? Well, just do exactly as told! Use
--name someunusedname
.gitmodules
then looks likels -1p .git/modules/
givesThis way in future you can switch branches/commit forward and backward and will never get into any trouble again, due to
two/
having two different (and possibly incompatible) upstream repositories. And the best is: You keep both cached locally, too.git
).However if you removed the cached directory, both different checkouts will stumble upon each other, because you will not use the
--name
options, right? So each time you do the checkout you perhaps have to remove the.git/modules/<module>/
directory again and again. This is extremely cumbersome and makes it hard to use something likegit bisect
.So there is a very technical reason to keep this module directory as a placeholder. People who recommend to remove something below
.git/modules/
either do not know better or forget to tell you that this makes powerful features likegit bisect
nearly impossible to use if this crosses such a submodule incompatibility.A further reason is shown above. Look at the
ls
. What do you see there?Well, the 2nd variant of module
two/
is not under.git/modules/two/
, it is under.git/modules/someunusedname/
! So things likegit rm $module; rm -f .git/module/$module
are totally wrong! You must either consultmodule/.git
or.gitmodules
to find the right thing to remove!So not only most other answers fall into this dangerous trap, even very popular
git
extensions had this bug (it's now fixed there)! So better keep your hands of the.git/
directory if you do not exactly, what you are doing!FYI you probably guessed it: hilbix is my GitHub account.
您必须删除
.gitmodules
和.git/config
中的条目,并从历史记录中删除该模块的目录:如果您在 git 的邮件列表上写下,可能有人将为您编写一个 shell 脚本。
You must remove the entry in
.gitmodules
and.git/config
, and remove the directory of the module from the history:If you'll write on git's mailing list probably someone will do a shell script for you.