如何删除 Git 子模块?为什么我不能做git submodule rm module_name
?
.git/config
中删除子模块条目的问题。接受的答案显示了完全删除 aa 子模块的最新方法。在这个答案中也更简洁地解释了它:stackoverflow.com/a/36593218/1562138
在现代 git 中(我在 2022 年写这篇文章,安装了更新的 git
),这变得相当简单:
运行 git rm
这将删除 <path-to-submodule>
处的文件树以及 .gitmodules
文件中的子模块条目。 即您的存储库中子模块的所有痕迹都将被删除。
但是,作为 the docs note,子模块的 .git
目录被保留在周围(在主项目的 .git
目录的 modules/
目录中),“可以检查过去的提交而无需从另一个存储库”。
如果您仍然想删除此信息,请手动删除 .git/modules/
中的子模块目录,并删除文件 .git/config
中的子模块条目。这些步骤可以使用命令自动化
rm -rf .git/modules/
git config --remove-section submodule.
较早的社区 wiki 说明:
要删除子模块,您需要:
从 .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
另请参阅:alternative steps below。
自 git1.8.3 (April 22d, 2013) 起:
一旦您使用“git submodule init”表达您对子模块的兴趣,就没有瓷器方式说“我不再对这个子模块感兴趣”。 “git submodule deinit”是这样做的方法。
删除过程也使用 git rm
(自 2013 年 10 月 git1.8.5 起)。
概括
步删除过程将是:
0. mv a/submodule a/submodule_tmp
1. git submodule deinit -f -- a/submodule
2. rm -rf .git/modules/a/submodule
3. git rm -f a/submodule
# Note: a/submodule (no trailing slash)
# or, if you want to leave it in your working tree and have done step 0
3. git rm --cached a/submodule
3bis mv a/submodule_tmp a/submodule
解释
rm -rf
:这在 Daniel Schroeder 的 answer 中有所提及,并由 the comments 中的 Eonil 总结:
这使 .git/modules/
git rm
:见 commit 95c16418:
当前在子模块上使用“git rm”会从超级项目的工作树中删除子模块的工作树,并从索引中删除 gitlink。但是 .gitmodules 中的子模块部分保持不变,这是现在删除的子模块的剩余部分,可能会激怒用户(与 .git/config 中的设置相反,这必须提醒用户对该子模块表现出兴趣因此稍后在签出较旧的提交时将重新填充)。
让“git rm”帮助用户,不仅可以从工作树中删除子模块,还可以从 .gitmodules 文件中删除“submodule.
git submodule deinit
:源于this patch:
使用“git submodule init”,用户可以告诉 git 他们关心一个或多个子模块,并希望在下一次调用“git submodule update”时填充它。但是目前没有简单的方法可以告诉 git 他们不再关心子模块并想要摆脱本地工作树(除非用户对子模块内部有很多了解并删除“submodule.$name.url” .git/config 以及工作树本身的设置)。
通过提供“deinit”命令来帮助这些用户。这将从 .git/config 中删除给定子模块的整个 submodule.
这需要注意(取消)初始化步骤(.git/config
和 .git/modules/xxx
)
从 git1.8.5 开始,git rm
还 负责:
'add' 步骤,它在 .gitmodules 文件中记录子模块的 url:它需要为您删除。
子模块特殊条目(如this question所示): git rm 将其从索引中删除: git rm --cached path_to_submodule (没有尾部斜杠)这将删除存储在索引中的具有特殊模式“160000”的目录,标记它作为子模块根目录。
如果您忘记了最后一步,并尝试将子模块添加为常规目录,您将收到如下错误消息:
git add mysubmodule/file.txt
Path 'mysubmodule/file.txt' is in submodule 'mysubmodule'
注意:从 Git 2.17(2018 年第二季度)开始, git submodule deinit 不再是一个 shell 脚本。它是对 C 函数的调用。
请参阅 Prathamesh Chavan (pratham-pc
) 的 commit 2e61273、commit 1342476(2018 年 1 月 14 日)。
(由 Junio C Hamano -- gitster
-- 在 commit ead8dbe 中合并,2018 年 2 月 13 日)
git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit \
${GIT_QUIET:+--quiet} \
${prefix:+--prefix "$prefix"} \
${force:+--force} \
${deinit_all:+--all} "$@"
submodule deinit
的用法吗?
.gitmodules
应该没问题,但我仍然会仔细检查 .git
目录的任何内容(即 local i> config,在您的本地存储库中:未被 git pull
修改)
.gitmodules
条目并删除索引中的特殊条目,并推送该存储库,其他人可以拉它并且该子模块将消失。
git rm submodule
完全按照其他人已经说过的那样做。
这个问题的大多数答案都是过时的、不完整的或不必要的复杂。
使用 git 1.7.8 或更高版本克隆的子模块将在本地存储库中最多留下四个痕迹。删除这四个痕迹的过程由以下三个命令给出:
# Remove the submodule entry from .git/config
git submodule deinit -f path/to/submodule
# Remove the submodule directory from the superproject's .git/modules directory
rm -rf .git/modules/path/to/submodule
# Remove the entry in .gitmodules and remove the submodule directory located at path/to/submodule
git rm -f path/to/submodule
.git/modules
文件夹中删除,您已经在上面的行中删除了该文件夹。像接受的答案一样将 --
添加到第一行似乎可以使这项工作。
只是一个注释。从 git 1.8.5.2 开始,有两个命令可以:
git rm -r the_submodule
rm -rf .git/modules/the_submodule
正如@Mark Cheverton 的回答正确指出的那样,如果不使用第二行,即使您现在删除了子模块,剩余的 .git/modules/the_submodule 文件夹也会阻止将来添加或替换相同的子模块.此外,正如@VonC 提到的,git rm
将在子模块上完成大部分工作。
--更新 (07/05/2017)--
澄清一下,the_submodule
是项目中子模块的相对路径。例如,如果子模块位于子目录 subdir
内,则为 subdir/my_submodule
。
正如评论和 other answers 中正确指出的那样,这两个命令(尽管在功能上足以删除子模块)确实在 .git/config
的 [submodule "the_submodule"]
部分留下了痕迹(截至 2017 年 7 月),可以删除使用第三个命令:
git config -f .git/config --remove-section submodule.the_submodule 2> /dev/null
.git/config
中删除子模块条目。有关删除子模块的完整方法,请参阅 stackoverflow.com/a/36593218/1562138。
git init && git submodule add <repository> && git rm <name>
留下 .git/config
条目和 .git/modules/<name>
目录及其内容。也许您在删除子模块之前没有初始化它?
Unlink of file '...' failed
简单的步骤
删除配置条目: 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 rm --cached $submodulepath
git config -f .git/config --remove-section submodule.$submodulepath
如果将其放入脚本中,最好先执行 git rebase HEAD
,最后执行 git commit
。
另请查看 an answer to Can I unpopulate a Git submodule?。
for dir in directory/*; do git rm --cached $dir; done
的事情。
git config -f .git/config -l | cut -d'=' -f1 | grep "submodule.$MODPATH" | sed 's/^submodule\.//' | sed 's/\.url$//'
- - 看起来你必须真的这样做以防万一出现问题,否则只需 git submodule | grep -v '^+' | cut -d' ' -f3
git submodule | grep '^+' | cut -d' ' -f2
"submodulename"
中包含 submodulename
.. 引用 .git/config
文件
除了建议之外,我还必须 rm -Rf .git/modules/path/to/submodule
才能添加具有相同名称的新子模块(在我的情况下,我用原来的叉子替换)
要删除使用添加的子模块:
REPOSITORY=blah@blah.com:repos/blah.git
MOD_DIR=lib/blah
git submodule add $REPOSITORY $MOD_DIR
跑:
git rm $MOD_DIR
而已。
对于旧版本的 git(大约 ~1.8.5,实际上甚至在 2.26.2 中)使用:
git submodule deinit $MOD_DIR
git rm $MOD_DIR
git config -f .gitmodules --remove-section submodule.$MOD_DIR
git rm
仍然在 .git/modules/
中留下一些东西。 (2.5.4)
git rm
它不会;在我的 mac 上使用 2.5.4 进行快速测试会更新 .gitmodules 文件,如此处的文档中所述:git-scm.com/docs/git-rm#_submodules ...但如果您发现某种平台/版本的组合不会发生这种情况,您可能应该提出一个关于它的错误。
git rm
将内容留在 .git/modules/
目录和 .git/config
文件(ubuntu,git 2.7.4)中。其他答案 100% 有效:stackoverflow.com/a/36593218/4973698
您必须删除 .gitmodules
和 .git/config
中的条目,并从历史记录中删除模块的目录:
git rm --cached path/to/submodule
如果你在 git 的邮件列表上写邮件,可能有人会为你编写一个 shell 脚本。
您可以使用别名来自动化其他人提供的解决方案:
[alias]
rms = "!f(){ git rm --cached \"$1\";rm -r \"$1\";git config -f .gitmodules --remove-section \"submodule.$1\";git config -f .git/config --remove-section \"submodule.$1\";git add .gitmodules; }; f"
把它放在你的 git config 中,然后你可以这样做:git rms path/to/submodule
git clone https://github.com/hilbix/empty.git; cd empty; git submodule add https://github.com/hilbix/empty.git one; git mv one two; git rms two
。第二:您必须从正确的路径执行此操作。 git
别名应该可以在工作树中的任何位置工作(或正常失败)。第三:git config -f .git/config
在子模块中失败,因为 .git
通常是那里的文件。
总而言之,这是你应该做的:
设置 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
git submodule update
。如果子模块路径没有正确更新(git 抛出错误),请删除它们:rm -rf .git/modules/<submodule> && rm -rf <submodule> && git submodule update
我发现 deinit
对我有用:
git submodule deinit <submodule-name>
git rm <submodule-name>
从 git docs:
deinit 取消注册给定的子模块,即从 .git/config 中删除整个 submodule.$name 部分及其工作树。
deinit
的较新的 git
s 来说,这似乎是最安全的答案,因为 the other answer 过早地删除了 .git/modules/submodule
目录,这似乎使 git
s 时不时地失败。另外(请参阅我的评论)删除 .git/modules/submodule
可能是错误的路径,因此这是一个危险的步骤,最好稍后仅在 git
抱怨时采取(或者如果您 299% 确定这是您想要的,是正确的路径并且真的需要)。
git commit
在工作目录 modified .gitmodules
和 deleted <submodule-path>
中提交分阶段更改。
如果子模块是意外添加的,因为您添加、提交和推送了一个已经是 Git 存储库(包含 .git
)的文件夹,那么您将没有要编辑的 .gitmodules
文件或任何东西在 .git/config
。 In this case all you need 是:
git rm --cached subfolder
git add subfolder
git commit -m "Enter message here"
git push
FWIW,在执行 git add
之前,我还删除了 .git
文件夹。
git submodule deinit
git submodule deinit <submodule_name>
和 git rm <path_to_submodule>
就足够了。最后一个命令会自动删除 .gitmodules
内的条目。吉特 2.17
-r
和 git rm
:git rm -r <path_to_submodule>
在这个网站上尝试了所有不同的答案后,我最终得到了这个解决方案:
#!/bin/sh
path="$1"
if [ ! -f "$path/.git" ]; then
echo "$path is no valid git submodule"
exit 1
fi
git submodule deinit -f $path &&
git rm --cached $path &&
rm -rf .git/modules/$path &&
rm -rf $path &&
git reset HEAD .gitmodules &&
git config -f .gitmodules --remove-section submodule.$path
这将恢复与添加子模块之前完全相同的状态。您可以立即再次添加子模块,这对于这里的大多数答案都是不可能的。
git submodule add $giturl test
aboveScript test
这使您可以进行干净的结帐,而无需提交任何更改。
对此进行了测试:
$ git --version
git version 1.9.3 (Apple Git-50)
git rm --cached $path
然后使用 rm -rf $path
而不是 git rm -r $path
?
git submodule add https://github.com/hilbix/empty.git 'dangerous .. submodule'
->当您尝试使用脚本删除“危险的 .. 子模块”时,这将 rm -rf ..
这很可能不是您想要的..
我目前在 2012 年 12 月所做的事情(结合了这些答案中的大部分):
oldPath="vendor/example"
git config -f .git/config --remove-section "submodule.${oldPath}"
git config -f .gitmodules --remove-section "submodule.${oldPath}"
git rm --cached "${oldPath}"
rm -rf "${oldPath}" ## remove src (optional)
rm -rf ".git/modules/${oldPath}" ## cleanup gitdir (optional housekeeping)
git add .gitmodules
git commit -m "Removed ${oldPath}"
我最近发现了一个 git 项目,其中包含许多有用的 git 相关命令:https://github.com/visionmedia/git-extras
安装它并输入:
git-delete-submodule submodule
然后事情就完成了。子模块目录将从您的存储库中删除,并且仍然存在于您的文件系统中。然后您可以提交更改,例如:git commit -am "Remove the submodule"
。
git delete-submodule
,因为 git-extras
需要在工作路径中。另请注意,我建议不要使用 git-extras
,因为它的许多部分非常容易出错和危险。 IE git-delete-submodule
可能会删除 .git/modules/*
下的错误路径,因为它假定模块和路径是相同的(通常情况并非如此),如果您尝试删除子模块。 git-extras
可能有 99% 的帮助,但如果使用它完全出错,请不要抱怨。 您已被警告!
apt install git-extras && git delete-submodule submodule
。 @Chien-Wei Huang 在帖子中有额外的 -
这是我所做的:
1.) 从 .gitmodules 文件中删除相关部分。您可以使用以下命令:
git config -f .gitmodules --remove-section "submodule.submodule_name"
2.) 暂存 .gitmodules
更改
git add .gitmodules
3.) 从 .git/config
中删除相关部分。您可以使用以下命令:
git submodule deinit -f "submodule_name"
4.)删除 gitlink (没有尾部斜杠):
git rm --cached path_to_submodule
5.) 清理 .git/modules
:
rm -rf .git/modules/path_to_submodule
6.) 提交:
git commit -m "Removed submodule <name>"
7.) 删除现在未跟踪的子模块文件
rm -rf path_to_submodule
fatal: no submodule mapping found in .gitmodules for path 'submodule_name'
。但这两个步骤都是必要的。 (git v2.8.2)
为了读者的利益,这里试图对其进行总结,并提供一个分步指南,说明如果事情没有按预期工作时如何做到这一点。以下是 git
版本 2.17
及更高版本删除子模块的经过测试且安全的方法:
submodule="path/to/sub" # no trailing slash!
git submodule deinit -- "$submodule"
git rm -- "$submodule"
如果这对您不起作用,请参见下文。
没有选项。没有什么危险的。甚至不考虑做更多!
使用 Debian Buster 2.20.1 和 Ubuntu 18.04 2.17.1 进行测试。
"$submodule" 只是为了强调名称的放置位置,并且您必须小心空格等
如果在 Windows 上忽略第一行并将“$submodule”替换为正确指定子模块路径的 Windows 方式。 (我不是 Windows)
警告!永远不要自己触摸 .git 目录的内部!在 .git 中进行编辑进入了黑暗的一面。不惜一切代价远离!是的,您可以为此责怪 git,因为过去 git 中缺少许多方便的东西。就像再次删除子模块的正确方法一样。我认为 git submodule 的文档中有一个非常危险的部分。它建议您自己删除 $GIT_DIR/modules/
注意
git module deinit
是直接倒数
git module init
但
git submodule deinit -- module
git rm -- module
也完全相反
git submodule add -- URL module
git submodule update --init --recursive -- module
因为有些命令基本上需要做的不仅仅是一件事情:
git submodule deinit -- 模块 (1) 更新 .git/config
(1) 更新 .git/config
git rm (2) 删除模块 (3) 的文件,从而递归删除子模块的子模块 (4) 更新 .gitmodules
(2) 移除模块的文件
(3) 从而递归删除子模块的子模块
(4) 更新.gitmodules
git submodule add 将数据拉入 .git/modules/NAME/ (1) 执行 git submodule init,因此更新 .git/config (2) 执行 git submodule update,因此,非递归地签出模块 (4) 更新 .gitmodules
将数据拉入 .git/modules/NAME/
(1) 执行 git submodule init,所以更新 .git/config
(2) 执行 git submodule 更新,因此,非递归地检出模块
(4) 更新.gitmodules
git submodule update --init --recursive -- 如果需要,模块会提取更多数据 (3) 递归检查子模块的子模块
如果需要,可以提取更多数据
(3)递归地检出子模块的子模块
这不能完全对称,因为保持严格对称没有多大意义。根本不需要两个以上的命令。 “拉入数据”也是隐含的,因为您需要它,但没有删除缓存的信息,因为这根本不需要并且可能会擦除宝贵的数据。
这确实让新手感到困惑,但基本上是一件好事:git
只是做了明显的事情并且做对了,甚至没有尝试做更多。 git
是一种工具,它必须完成可靠的工作,而不仅仅是另一个“Eierlegende Wollmilchsau”(“Eierlegende Wollmilchsau”在我看来是“瑞士军刀的某种邪恶版本”)。
所以我理解人们的抱怨,他们说“为什么不为我做git
显而易见的事情”。这是因为这里的“明显”取决于观点。在每一种情况下的可靠性都更为重要。因此,在所有可能的技术情况下,对您来说显而易见的事情往往不是正确的事情。请记住:AFAICS git
遵循技术路径,而不是社交路径。 (因此聪明的名字:git)
如果这失败了
由于以下原因,上述命令可能会失败:
你的 git 太旧了。然后使用更新的 git。 (见下文如何。)
您有未提交的数据,可能会丢失数据。然后最好先提交它们。
您的子模块在 git clean 意义上不干净。然后首先使用该命令清理您的子模块。 (见下文。)
你过去做过一些 git 不支持的事情。然后你就处于黑暗面,事情变得丑陋和复杂。 (也许使用另一台机器修复它。)
也许还有更多我不知道的失败方式(我只是一些 git 高级用户。)
可能的修复如下。
使用较新的 git
如果您的机器太旧,则 git
中没有 submodule deinit
。如果您不想(或不能)更新您的 git
,那么只需使用另一台具有较新 git
的机器! git
是完全分布式的,因此您可以使用另一个 git
来完成工作:
workhorse:~/path/to/worktree$ git status --porcelain 不能输出任何东西!如果是这样,请先清理东西!
主力:~/path/to/worktree$ ssh account@othermachine
othermachine:~$ git clone --recursive me@workhorse path/to/worktree/.git TMPWORK && cd TMPWORK
现在做子模块的东西
其他机器:~/TMPWORK$ git commit 。 -m 。 && 出口
主力:~/path/to/worktree$ git fetch account@othermachine:TMPWORK/.git
主力:~/path/to/worktree$ git merge --ff-only FETCH_HEAD。如果这不起作用,请使用 git reset --soft FETCH_HEAD
现在清理东西,直到 git status 再次清理。你可以这样做,因为你之前已经把它清理干净了,这要归功于第一步。
这个 othermachine
可以是某个 VM,也可以是 Windows 下的某个 Ubuntu WSL,等等。甚至是 chroot
(但我假设您不是 root,因为如果您是 root
,则应该更容易更新到较新的 git
)。
请注意,如果您无法 ssh
进入,有很多方法可以传输 git
存储库。您可以将工作树复制到某个 U 盘(包括 .git
目录)上,然后从 U 盘克隆。克隆副本,只是为了再次以干净的方式获取内容。这可能是一个 PITA,以防您的子模块无法直接从其他机器访问。但也有一个解决方案:
git config --add url.NEWURLPREFIX.insteadOf ORIGINALURLPREFIX
您可以使用此乘法,并将其保存到 $HOME/.gitconfig
。就像是
git config --add 'url./mnt/usb/repo/.insteadof' https://github.com/
重写 URL,如
https://github.com/XXX/YYY.git
进入
/mnt/usb/repo/XXX/YYY.git
如果您开始习惯这种强大的 git
功能,那就很容易了。
先收拾东西
手动清理很好,因为这样你可能会发现一些你忘记的东西。
如果 git 抱怨未保存的内容,请提交并将其推送到安全的地方。
如果 git 抱怨一些剩菜, git status 和 git clean -ixfd 是你的朋友
尽量避免使用 rm 和 deinit 的选项。如果您是专业人士,则 git 的选项(如 -f)很好。但是当你来到这里时,你可能在子模块领域没有那么有经验。所以最好是安全而不是抱歉。
例子:
$ git status --porcelain
M two
$ git submodule deinit two
error: the following file has local modifications:
two
(use --cached to keep the file, or -f to force removal)
fatal: Submodule work tree 'two' contains local modifications; use '-f' to discard them
$ cd two
$ git submodule deinit --all
error: the following file has local modifications:
md5chk
(use --cached to keep the file, or -f to force removal)
fatal: Submodule work tree 'md5chk' contains local modifications; use '-f' to discard them
$ cd md5chk
$ git submodule deinit --all
error: the following file has local modifications:
tino
(use --cached to keep the file, or -f to force removal)
fatal: Submodule work tree 'tino' contains local modifications; use '-f' to discard them
$ cd tino
$ git status --porcelain
?? NEW
$ git clean -i -f -d
Would remove the following item:
NEW
*** Commands ***
1: clean 2: filter by pattern 3: select by numbers 4: ask each
5: quit 6: help
What now> 1
Removing NEW
$ cd ../../..
$ git status --porcelain
$ git submodule deinit two
Cleared directory 'two'
Submodule 'someunusedname' (https://github.com/hilbix/src.git) unregistered for path 'two'
您看,submodule deinit
上不需要 -f
。如果事情是干净的,在 git clean
的意义上。另请注意,不需要 git clean -x
。 这意味着 git submodule deinit
无条件删除被忽略的未跟踪文件。这通常是您想要的,但不要忘记它。有时被忽略的文件可能很宝贵,例如需要数小时到数天才能重新计算的缓存数据。
为什么从不删除 $GIT_DIR/modules/
可能人们想删除缓存的存储库,因为他们害怕以后遇到问题。这是真的,但遇到那个“问题”是解决它的正确方法!因为修复很容易,并且做得对,你将能够从此过上幸福的生活。这避免了比您自己删除数据时更麻烦的麻烦。
例子:
mkdir tmptest &&
cd tmptest &&
git init &&
git submodule add https://github.com/hilbix/empty.git two &&
git commit -m . &&
git submodule deinit two &&
git rm two &&
git commit -m . &&
git submodule add https://github.com/hilbix/src.git two
最后一行输出以下错误:
A git directory for 'two' is found locally with remote(s):
origin https://github.com/hilbix/empty.git
If you want to reuse this local git directory instead of cloning again from
https://github.com/hilbix/src.git
use the '--force' option. If the local git directory is not the correct repo
or you are unsure what this means choose another name with the '--name' option.
为什么会出现这个错误?因为 .git/modules/two/
以前是从 https://github.com/hilbix/empty.git 填充的,现在应该从其他东西(即 https://github.com/hilbix/src.git)重新填充。如果您从 https://github.com/hilbix/empty.git 重新填充它,您将看不到它
现在要做什么?好吧,就按照说的做吧!使用--name someunusedname
git submodule add --name someunusedname https://github.com/hilbix/src.git two
.gitmodules
然后看起来像
[submodule "someunusedname"]
path = two
url = https://github.com/hilbix/src.git
ls -1p .git/modules/
给出
someunusedname/
two/
这样将来您可以向前和向后切换分支/提交,并且再也不会遇到任何麻烦,因为 two/
有两个不同的(并且可能不兼容的)上游存储库。最好的是:您也可以将两者都缓存在本地。
这不仅适用于你。对于使用您的存储库的所有其他人来说也是如此。
你不会失去历史。如果您忘记推送旧子模块的最新版本,您可以输入本地副本,稍后再执行。请注意,有些人忘记推送一些子模块是很常见的(因为这是新手的 PITA,直到他们习惯了 git)。
但是,如果您删除了缓存目录,则两个不同的签出项会相互碰撞,因为您不会使用 --name
选项,对吧?因此,每次您进行结帐时,您可能必须一次又一次地删除 .git/modules/<module>/
目录。这是非常麻烦的,并且很难使用像 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
才能找到要删除的正确内容!
因此,不仅大多数其他答案都落入了这个危险的陷阱,even very popular git
extensions had this bug (it's now fixed there)!因此,如果您不完全了解您在做什么,最好保留 .git/
目录!
而从哲学的角度来看,抹杀历史永远是错误的!除了量子力学,像往常一样,但这是完全不同的东西。
仅供参考,您可能已经猜到了:hilbix 是我的 GitHub 帐户。
所有的答案看起来都过时了。我正在使用 git 版本 2.28.0
。一条线的答案是,
git rm path-to-submodule
但是,即使从源代码管理中删除了子模块, .git/modules/path-to-submodule 仍然包含子模块存储库, .git/config 包含其 URL,因此您仍然必须手动删除它们:
git config --remove-section submodule.path-to-submodule
rm -rf .git/modules/path-to-submodule
有时,您必须使用 -f
标志:
$ git rm -f img2vec
例如,因为您可能会收到如下错误:
$ git rm img2vec/
error: the following file has changes staged in the index:
img2vec
(use --cached to keep the file, or -f to force removal)
git rm
选项和相关的配置更改。
.gitmodules
文件。 2. 通过调用 git rm --cached -r <path-to-submodule-dir>
从索引中删除相关数据
我不得不将 John Douthat 的步骤更进一步,cd
进入子模块的目录,然后删除 Git 存储库:
cd submodule
rm -fr .git
然后我可以将文件作为父 Git 存储库的一部分提交,而不需要对子模块的旧引用。
git rm --cache
步骤时,我也必须这样做才能通过“致命:不是 git 存储库:”错误。
使用 git v2.7.4 简单的 3 个步骤就可以了。
git submodule deinit -f -- a/submodule
git rm -f a/submodule
git commit
以下是我认为必要或有用的 4 个步骤(首先是重要的):
git rm -f the_submodule
rm -rf .git/modules/the_submodule
git config -f .git/config --remove-section submodule.the_submodule
git commit -m "..."
理论上,步骤 1 中的 git rm
应该会处理好它。希望有一天可以肯定地回答 OP 问题的第二部分(这可以在一个命令中完成)。
但截至 2017 年 7 月,第 2 步 是删除 .git/modules/
中的数据的必要条件,否则,您将来无法重新添加子模块。
正如 tinlyx's answer 所指出的,对于 git 1.8.5+,您可能可以摆脱上述两个步骤,因为所有 git submodule
命令似乎都有效。
步骤 3 删除文件 .git/config
中的 the_submodule
部分。为了完整性,应该这样做。 (该条目可能会导致旧 git 版本出现问题,但我没有要测试的)。
为此,大多数答案建议使用 git submodule deinit
。我发现使用 git config -f .git/config --remove-section
更加明确且不那么混乱。根据 git-submodule documentation、git deinit
:
取消注册给定的子模块...如果您真的想从存储库中删除子模块并提交,请改用 git-rm[1] 。
最后但并非最不重要的一点是,如果您不 git commit
,您将/可能在执行 git submodule summary
时出错(从 git 2.7 开始):
fatal: Not a git repository: 'the_submodule/.git'
* the_submodule 73f0d1d...0000000:
这与您执行第 2 步还是第 3 步无关。
我刚刚找到了 .submodule (忘记了确切名称)隐藏文件,它有一个列表......你可以这样单独删除它们。我只有一个,所以我删除了它。很简单,但它可能会弄乱 Git,因为我不知道子模块是否附加了任何东西。到目前为止似乎还可以,除了 libetpan 通常的升级问题,但这(希望)是无关的。
注意到没有人发布手动擦除,所以添加
.gitmodules
对于 git 2.17 及更高版本,它只是:
git submodule deinit -f {module_name}
git add {module_name}
git commit
git 2.17.1
和 git 2.20.1
都不起作用。但是,使用 git rm
而不是 git add
对两者都有效。注意:如果东西干净,则不需要 -f
。如果您想防止意外的数据丢失,请务必永远不要使用带有 git
的选项。另请注意,这会留下 .git/modules/{module_name}
。 最好将其保留在此处,因为 git
会打印正确的(!) 帮助,如果某事因此而被阻止,则如何继续。
project dir: ~/foo_project/
submodule: ~/foo_project/lib/asubmodule
- - - - - - - - - - - - - - - - - - - - - - - - -
run:
1. cd ~/foo_project
2. git rm lib/asubmodule &&
rm .git/modules/lib/asubmodule &&
git submodule lib/asubmodule deinit --recursive --force
从 git 中删除子模块的最佳方法:
$ git submodule deinit -f <submodule-name>
$ rm -rf .git/modules/<submodule-name>
$ git config -f .gitmodules --remove-section submodule.<submodule-name>
$ git config -f .git/config --remove-section submodule.<submodule-name>
$ git rm --cached <submodule-name>
$ git commit -m 'rm submodule: <submodule-name>'
git add .gitmodules
吗?
git add .gitmodules
如果您刚刚添加了子模块,例如,您只是添加了错误的子模块或将其添加到错误的位置,只需执行 git stash
然后删除该文件夹。这是假设添加子模块是您在最近的回购中所做的唯一事情。
总而言之,这是你应该做的:
设置 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
git rm --cached $path_to_submodule
和 git add .gitmodules
否?我确实收到了第一个命令的错误:fatal: Please stage your changes to .gitmodules or stash them to proceed
,因为我对 .gitmodules
进行了未暂存的更改。首先执行 git add .gitmodules
解决了这个问题。
这对我有用。上面的答案在终端中显示了这一点,没有其他任何事情发生
'fatal: not removing 'demolibapp' recursively without -r'
demolibapp 是我要删除的子模块名称 git submodule deinit demolibapp git rm --cached demolibapp -r rm -rf .git/modules/demolibapp git add --all git commit -m "removing extra submodules" git push rm -rf demolibapp
我创建了一个 bash 脚本来简化删除过程。它还会检查 repo 中是否有未保存的更改并要求确认。它已经在 os x
上进行了测试,如果它在常见的 linux 发行版上也能正常工作,会很有趣:
https://gist.github.com/fabifrank/cdc7e67fd194333760b060835ac0172f
git submodule rm
只是删除子模块注册,如果该命令还删除了本地存储库,他们会感到惊讶。任何本地更改都将无法挽回地丢失。也许另一个人会认为只有文件会被删除。