如何删除子模块?

问题描述:

如何删除 Git 子模块?为什么我不能做git submodule rm module_name?

解决方案1:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

在现代 git 中(我在 2022 年写这篇文章,安装了更新的 git),这变得相当简单:

运行 git rm ,然后提交。

这将删除 处的文件树以及 .gitmodules 文件中的子模块条目。 即您的存储库中子模块的所有痕迹都将被删除。

但是,作为 the docs note,子模块的 .git 目录被保留在周围(在主项目的 .git 目录的 modules/ 目录中),“可以检查过去的提交而无需从另一个存储库”。如果您仍然想删除此信息,请手动删除 .git/modules/ 中的子模块目录,并删除文件 .git/config 中的子模块条目。这些步骤可以使用命令自动化

rm -rf .git/modules/,和

git config --remove-section submodule.。

较早的社区 wiki 说明:

通过页面Git Submodule Tutorial:

要删除子模块,您需要:

从 .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

另请参阅:alternative steps below。

“顺便说一句,我不能简单地 git submodule rm 有什么原因吗?” ?

@abernier 一个简短的答案可能是“因为不存在这样的命令。”我的猜测是,他们正试图明确删除子模块文件与子模块配置,以避免意外的数据丢失。也许有人会认为 git submodule rm 只是删除子模块注册,如果该命令还删除了本地存储库,他们会感到惊讶。任何本地更改都将无法挽回地丢失。也许另一个人会认为只有文件会被删除。

坦白说,我不知道为什么。不过,我希望他们添加一个命令。这4个步骤太复杂了。

这是一个删除子模块的 bash 脚本,只需为 submodule-rm 创建一个 git 别名;)gist.github.com/2491147

还需要 rm -rf .git\modules\submodule 名称吗?

解决方案2:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

自 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. 部分(或者对于所有已初始化的子模块,如果给定了 ‘.’)。如果当前工作树包含修改,则失败,除非强制执行。抱怨在命令行中给出的子模块的 url 设置无法在 .git/config 中找到,但仍然不会失败。

这需要注意(取消)初始化步骤(.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 的用法吗?

@yourfriendzak 这里是某人成功使用它的一个例子:stackoverflow.com/a/16161950/6309。但请记住,与我最初认为的相反,1.8.3 尚未发布!在 Unix 上,您可以从源代码编译它。

@HamishDowner 特殊条目应该消失(该目录不再是子模块),并且 .gitmodules 应该没问题,但我仍然会仔细检查 .git 目录的任何内容(即 local config,在您的本地存储库中:未被 git pull 修改)

@Jayen 是的,如果您提交删除 .gitmodules 条目并删除索引中的特殊条目,并推送该存储库,其他人可以拉它并且该子模块将消失。

在当前的 git (v1.9+) 中,普通的旧 git rm submodule 完全按照其他人已经说过的那样做。

解决方案3:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

这个问题的大多数答案都是过时的、不完整的或不必要的复杂。

使用 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

为什么这个答案的赞成票这么少?所有这些流行的答案都遗漏了一些东西,这是唯一以最简单的方式真正删除子模块所有痕迹的答案。请注意:命令的顺序很重要。

@mbdevpl 在接受答案 3 年后出现,我想没有人能说服 OP 接受这个答案

这是2018年不复杂的答案吗?

运行这些命令的 .gitmodules 文件似乎仍然不受影响

在 2019 年,这行不通。最后一行实际上尝试从 .git/modules 文件夹中删除,您已经在上面的行中删除了该文件夹。像接受的答案一样将 -- 添加到第一行似乎可以使这项工作。

解决方案4:

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

只是一个注释。从 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 版本 2.4.9 (Apple Git-60),我所要做的就是 rm the_submodule。我推了那个然后重新添加了一个与子模块同名的文件夹,它没有问题。

这不会从 .git/config 中删除子模块条目。有关删除子模块的完整方法,请参阅 stackoverflow.com/a/36593218/1562138。

@drevicko 我刚刚用 Git 2.11.1 测试了这个,我观察到与以前相同的行为。 git init && git submodule add && git rm 留下 .git/config 条目和 .git/modules/ 目录及其内容。也许您在删除子模块之前没有初始化它?

我觉得先运行这个更安全.. git submodule deinit -f the_submodule

@danday74 如果签出子模块,则实际上需要您的命令。否则你会得到一个错误Unlink of file '...' failed

解决方案5:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

简单的步骤

删除配置条目: git config -f .git/config --remove-section submodule. s u b m o d u l e n a m e g i t c o n f i g − f . g i t m o d u l e s − − r e m o v e − s e c t i o n s u b m o d u l e . submodulename git config -f .gitmodules --remove-section submodule. submodulenamegitconfigf.gitmodulesremovesectionsubmodule.submodulename 从索引中删除目录: git rm --cached $submodulepath 提交删除未使用的文件: rm -rf s u b m o d u l e p a t h r m − r f . g i t / m o d u l e s / submodulepath rm -rf .git/modules/ submodulepathrmrf.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 循环来传递它们。因为它们中的大多数在特定目录下,并且 ls 输出包含尾部斜杠。我做了类似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 文件

简单的。高效的。在 2.25.0 中,在第 1 步之后,您需要在第 2 步之前暂存 .gitmodules 更改。

解决方案6:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

除了建议之外,我还必须 rm -Rf .git/modules/path/to/submodule 才能添加具有相同名称的新子模块(在我的情况下,我用原来的叉子替换)

我也遇到了麻烦。如果您尝试将子模块重新安装到相同的路径,它会将分支信息缓存在您提到的位置,这会使事情变得混乱。

谢谢,我也需要这个。 @Anton,我同意,并且我已经编辑了最高投票的答案以添加此信息。

我使用 --name 选项使替换工作...参见 stackoverflow.com/questions/14404704/…

解决方案7:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

要删除使用添加的子模块:

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

确实+1。这是从 git 1.8.3 开始的唯一正确答案。应该被接受为正确的。

git rm 仍然在 .git/modules/ 中留下一些东西。 (2.5.4)

@RudolfAdamkovic 它对我有用吗?请注意,如果确切路径匹配,它只会删除子模块条目;如果您移动了一个子模块然后使用 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

deinit 会删除子模块但保留文件吗?我希望它删除 git 中的所有残余物,但保留实际文件夹。

解决方案8:

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

您必须删除 .gitmodules 和 .git/config 中的条目,并从历史记录中删除模块的目录:

git rm --cached path/to/submodule

如果你在 git 的邮件列表上写邮件,可能有人会为你编写一个 shell 脚本。

不需要任何 shell 脚本,其他答案有删除子模块所有痕迹的命令:stackoverflow.com/a/36593218/4973698

解决方案9:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

您可以使用别名来自动化其他人提供的解决方案:

[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

-1 因为这太错误了。第一:这假设子模块的名称和路径是相同的通常情况并非如此。即 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 通常是那里的文件。

解决方案10:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

总而言之,这是你应该做的:

设置 path_to_submodule var(没有尾部斜杠): path_to_submodule=path/to/submodule 从 .gitmodules 文件中删除相关行: git config -f .gitmodules --remove-section submodule. p a t h t o s u b m o d u l e 从 . g i t / c o n f i g 中 删 除 相 关 部 分 g i t c o n f i g − f . g i t / c o n f i g − − r e m o v e − s e c t i o n s u b m o d u l e . path_to_submodule 从 .git/config 中删除相关部分git config -f .git/config --remove-section submodule. pathtosubmodule.git/configgitconfigf.git/configremovesectionsubmodule.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 p a t h t o s u b m o d u l e r m − r f . g i t / m o d u l e s / path_to_submodule rm -rf .git/modules/ pathtosubmodulermrf.git/modules/path_to_submodule

所以其他所有拉下我更改的人都必须运行 rm -rf $path_to_submodule rm -rf .git/modules/$path_to_submodule 来删除子模块缓存?

我建议更新,git submodule update。如果子模块路径没有正确更新(git 抛出错误),请删除它们:rm -rf .git/modules/ && rm -rf && git submodule update

解决方案11:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

我发现 deinit 对我有用:

git submodule deinit     
git rm 

从 git docs:

deinit 取消注册给定的子模块,即从 .git/config 中删除整个 submodule.$name 部分及其工作树。

同意找到相同的解决方案。这是2018年今天最好的方式)

它没有删除 .git/modules/.. 。您应该删除它们,请参阅@fvgs 的答案

不知道为什么这个简单易行的解决方案不是第一

AFAICS 对于知道 deinit 的较新的 gits 来说,这似乎是最安全的答案,因为 the other answer 过早地删除了 .git/modules/submodule 目录,这似乎使 git s 时不时地失败。另外(请参阅我的评论)删除 .git/modules/submodule 可能是错误的路径,因此这是一个危险的步骤,最好稍后仅在 git 抱怨时采取(或者如果您 299% 确定这是您想要的,是正确的路径并且真的需要)。

我还需要 git commit 在工作目录 modified .gitmodules 和 deleted 中提交分阶段更改。

原文链接:https://www.huntsbot.com/qa/VdjD/how-do-i-remove-a-submodule?lang=zh_CN

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值