如何删除子模块?

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

1336364 次浏览

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

git rm --cached path/to/submodule

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

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

  • 运行#0并提交.

这将删除<path-to-submodule>处的文件树和子模块在.gitmodules文件中的条目。删除存储库中子模块的所有跟踪。

然而,作为文档说明,子模块的.git目录保留在(主项目.git目录的modules/目录中)“可以在不需要从另一个存储库获取的情况下签出过去的提交”。
如果您仍然想删除此信息,请手动删除.git/modules/中的子模块目录,并删除文件.git/config中的子模块条目。这些步骤可以使用命令

自动执行
  • rm -rf .git/modules/<path-to-submodule>
  • git config --remove-section submodule.<path-to-submodule>


旧社区wiki说明:

通过页面Git子模块教程

要删除子模块,您需要:

  1. .gitmodules文件中删除相关部分。
  2. 执行.gitmodules更改:
    git add .gitmodules
  3. .git/config中删除相关部分。
  4. 从工作树中删除子模块文件并索引:
    git rm --cached path_to_submodule(没有尾随斜杠)。
  5. 删除子模块的.git目录:
    rm -rf .git/modules/path_to_submodule
  6. 提交更改:
    git commit -m "Removed submodule <name>"
  7. 删除现在未跟踪的子模块文件:
    rm -rf path_to_submodule

另见以下替代步骤

简单的步骤

  1. 删除配置条目:
    git config -f .git/config --remove-section submodule.$submodulename
    git config -f .gitmodules --remove-section submodule.$submodulename
  2. 从索引中删除目录:
    git rm --cached $submodulepath
  3. 提交
  4. 删除未使用的文件:
    rm -rf $submodulepath
    rm -rf .git/modules/$submodulename

请注意:$submodulepath不包含前导斜杠或尾随斜杠。

背景

当您执行git submodule add时,它只将其添加到.gitmodules,但是一旦你做了git submodule init,它就会添加到.git/config

因此,如果您希望删除模块,但能够快速恢复它,然后这样做:

git rm --cached $submodulepathgit config -f .git/config --remove-section submodule.$submodulepath

先做git rebase HEADgit commit是个好主意最后,如果你把它放在脚本中。

再看看我可以取消填充Git子模块吗?

除了建议之外,我还必须rm -Rf .git/modules/path/to/submodule才能添加一个同名的新子模块(在我的例子中,我用原来的分支替换了一个分支)

如果子模块是意外添加的,因为您添加、提交和推送了一个已经是Git存储库(包含.git)的文件夹,您将没有.gitmodules文件要编辑,也没有.git/config中的任何内容。在这种情况下你所需要的是:

git rm --cached subfoldergit add subfoldergit commit -m "Enter message here"git push

FWIW,在执行git add之前,我还删除了.git文件夹。

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

  1. 设置path_to_submodule var(没有尾随斜杠):

    path_to_submodule=path/to/submodule

  2. 从. git模块文件中删除相关行:

    git config -f .gitmodules --remove-section submodule.$path_to_submodule

  3. 从. git/config中删除相关部分

    git config -f .git/config --remove-section submodule.$path_to_submodule

  4. 仅从索引中取消阶段并删除$path_to_submodule(以防止丢失信息)

    git rm --cached $path_to_submodule

  5. 跟踪对. git模块所做的更改

    git add .gitmodules

  6. 提交超级项目

    git commit -m "Remove submodule submodule_name"

  7. 删除现在未跟踪的子模块文件

    rm -rf $path_to_submodule

    rm -rf .git/modules/$path_to_submodule

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

[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配置中,然后你可以这样做:git rms path/to/submodule

我不得不将John Douthat的步骤更进一步,并cd进入子模块的目录,然后删除Git存储库:

cd submodulerm -fr .git

然后我可以将文件作为父Git存储库的一部分提交,而无需对子模块的旧引用。

我目前在做什么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 .gitmodulesgit commit -m "Removed ${oldPath}"

git1.8.3(2013年4月22d日)

没有瓷器的方式说“我不再对这个子模块感兴趣”,一旦你用“git submodule init”表达了你对一个子模块的兴趣。
#0”是这样做的方式。

删除过程也使用git rm(自git1.8.5 2013年10月以来)。

总结

然后,3个步骤的移除过程将是:

0. mv a/submodule a/submodule_tmp
1. git submodule deinit -f -- a/submodule2. rm -rf .git/modules/a/submodule3. 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 03.   git rm --cached a/submodule3bis mv a/submodule_tmp a/submodule

补充说明

rm -rf:这在丹尼尔施罗德回答中提到,并在的评论中由Eonil总结:

这样.git/modules/<path-to-submodule>/保持不变。
因此,如果您使用此方法删除子模块并再次重新添加它们,则不可能,因为存储库已经损坏。


git rm:见提交95c16418

当前在子模块上使用“git rm”会将子模块的工作树从超级项目的工作树中删除,并将gitlink从索引中删除。
但是子模块在.gitmodules中的部分保持不变,这是现已删除的子模块的剩余部分,可能会激怒用户(与.git/config中的设置相反,这必须保持提醒用户对此子模块表现出兴趣,以便稍后在签出旧提交时重新填充)。

让“git rm”帮助用户,不仅从工作树中删除子模块,还从.gitmodules文件中删除“submodule.<submodule name>”部分并同时执行。


git submodule deinit:它源于此补丁

使用“git submodule init”,用户可以告诉git他们关心一个或多个子模块,并希望在下次调用“git submodule update”时填充它。
但目前没有简单的方法可以告诉git他们不再关心子模块,并希望摆脱本地工作树(除非用户对子模块内部有很多了解并从.git/config中删除“submodule.$name.url”设置以及工作树本身)。

通过提供“#0”命令来帮助这些用户。
这个.git/config中删除了整个submodule.<name>部分,对于给定的子模块(s)(或者如果给出'.',则所有已初始化的子模块)。
如果当前工作树包含修改,则失败,除非强制。
当命令行上给出的子模块的url设置在.git/config中找不到时,抱怨,但仍然不会失败。

这需要注意(取消)初始化步骤(.git/config.git/modules/xxx

从git1.8.5开始,git rm负责

  • add”步骤,在.gitmodules文件中记录子模块的url:需要为您删除。
  • 子模块特殊条目(如这个问题所示):git rm将其从索引中删除:
    git rm --cached path_to_submodule(无尾随斜杠)
    这将以特殊模式“160000”删除存储在索引中的目录,将其标记为子模块根目录。

如果您忘记了最后一步,并尝试将子模块添加为常规目录,您会收到错误消息,例如:

git add mysubmodule/file.txtPath 'mysubmodule/file.txt' is in submodule 'mysubmodule'

注意:自Git 2.17(Q2 2018)以来,git子模块deinit不再是外壳脚本。
这是对C函数的调用。

提交2e61273提交1342476(2018年1月14日)byPrathamesh Chavan(#0)
(由Junio C Hamano----#0----合并于提交ead8dbe,13 Feb 2018)

git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit \${GIT_QUIET:+--quiet} \${prefix:+--prefix "$prefix"} \${force:+--force} \${deinit_all:+--all} "$@"

我最近发现了一个git项目,其中包含许多有用的git相关命令:https://github.com/visionmedia/git-extras

安装它并键入:

git-delete-submodule submodule

然后事情就完成了。子模块目录将从您的存储库中删除,并仍然存在于您的文件系统中。然后您可以提交更改,如:git commit -am "Remove the submodule"

删除使用以下方法添加的子模块:

REPOSITORY=blah@blah.com:repos/blah.gitMOD_DIR=lib/blahgit submodule add $REPOSITORY $MOD_DIR

运行:

git rm $MOD_DIR

就这样了。

对于旧版本的git(大约1.8.5,实际上甚至在2.26.2中)使用:

git submodule deinit $MOD_DIRgit rm $MOD_DIRgit config -f .gitmodules --remove-section submodule.$MOD_DIR

只是一个注释。由于git1.8.5.2,两个命令将执行:

git rm -r the_submodulerm -rf .git/modules/the_submodule

正如@Mark Cheverton正确指出的那样,如果不使用第二行,即使你现在删除了子模块,剩余的. git/模块/the_submodule文件夹也会阻止将来添加或替换相同的子模块。此外,正如@VonC提到的,git rm将完成子模块的大部分工作。

--更新(07/05/2017)--

澄清一下,the_submodule是项目中子模块的相对路径。例如,如果子模块在子目录subdir中,则为subdir/my_submodule

正如注释和其他答案中正确指出的那样,这两个命令(尽管功能上足以删除子模块)确实在.git/config[submodule "the_submodule"]部分留下了痕迹(截至2017年7月),可以使用第三个命令删除:

git config -f .git/config --remove-section submodule.the_submodule 2> /dev/null

我刚刚找到了. sub模块(忘记了确切的名称)隐藏文件,它有一个列表……你可以通过这种方式单独擦除它们。我只有一个,所以我删除了它。很简单,但它可能会弄乱Git,因为我不知道是否有任何附加到子模块的东西。到目前为止,除了libetpan通常的升级问题之外,似乎还可以,但这(希望)无关。

注意到没有人发布手动擦除,所以添加

在这个网站上尝试了所有不同的答案后,我最终得到了这个解决方案:

#!/bin/shpath="$1"if [ ! -f "$path/.git" ]; thenecho "$path is no valid git submodule"exit 1figit 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 testaboveScript test

这使您有一个干净的签出,没有任何更改要提交。

这是通过以下方式测试的:

$ git --versiongit version 1.9.3 (Apple Git-50)
project dir:     ~/foo_project/submodule:       ~/foo_project/lib/asubmodule- - - - - - - - - - - - - - - - - - - - - - - - -run:1.   cd ~/foo_project2.   git rm lib/asubmodule &&rm .git/modules/lib/asubmodule &&git submodule lib/asubmodule deinit --recursive --force

以下是我所做的:

1.)从. git模块文件中删除相关部分。您可以使用以下命令:

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

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

使用git 1.7.8或更高版本克隆的子模块最多会在您的本地存储库中留下四个自身痕迹。删除这四个痕迹的过程由以下三个命令给出:

# Remove the submodule entry from .git/configgit submodule deinit -f path/to/submodule
# Remove the submodule directory from the superproject's .git/modules directoryrm -rf .git/modules/path/to/submodule
# Remove the entry in .gitmodules and remove the submodule directory located at path/to/submodulegit rm -f path/to/submodule

如果您刚刚添加了子模块,例如,您只是添加了错误的子模块或将其添加到错误的位置,只需执行git stash然后删除文件夹。这是假设添加子模块是您在最近存储库中唯一做的事情。

我发现deinit对我有好处:

git submodule deinit <submodule-name>git rm <submodule-name>

git文档

deinit

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

以下是我认为必要或有用的4个步骤(首先是重要的步骤):

git rm -f the_submodulerm -rf .git/modules/the_submodulegit config -f .git/config --remove-section submodule.the_submodulegit commit -m "..."

理论上步骤1中的git rm应该照顾它。希望OP问题的第二部分有一天能得到肯定的回答(这可以在一个命令中完成)。

但截至2017年7月,步骤2必须删除.git/modules/中的数据,否则您无法在将来添加子模块。

正如tinlyx的回答所指出的,对于git 1.8.5+,您可能可以通过上述两个步骤逃脱,因为所有git submodule命令似乎都可以工作。

步骤3删除文件.git/configthe_submodule的部分。为了完整性,应该这样做。(该条目可能会导致旧版本的git问题,但我没有要测试的)。

对此,大多数答案建议使用git submodule deinit。我发现使用git config -f .git/config --remove-section更明确,更少混淆。根据git子模块留档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步。

在最新的git中,只需4次操作即可删除git子模块。

  • 删除.gitmodules中的相应条目
  • 阶段变化git add .gitmodules
  • 删除子模块目录git rm --cached <path_to_submodule>
  • 提交git commit -m "Removed submodule xxx"

对于git 2.17及以上版本,它只是:

git submodule deinit -f {module_name}git add {module_name}git commit

我创建了一个bash脚本来简化删除过程。它还检查存储库中是否有未保存的更改并要求确认。它已经在os x上进行了测试,想知道它是否也能在常见的linux发行版上运行:

https://gist.github.com/fabifrank/cdc7e67fd194333760b060835ac0172f

如果您需要在单行命令中使用bash脚本执行此操作,如下所示:

$ cd /path/to/your/repo && /bin/bash $HOME/remove_submodule.sh /path/to/the/submodule

在名为$HOME的dir中创建bash脚本文件,即remove_submodule.sh

#!/bin/bash
git config -f .gitmodules --remove-section submodule.$1git config -f .git/config --remove-section submodule.$1git rm --cached $1git add .gitmodulesgit commit -m "Remove submodule in $1"rm -rf $1rm -rf .git/modules/$1git push origin $(git rev-parse --abbrev-ref HEAD) --force --quiet

删除git子模块

要删除git子模块,需要以下4个步骤。

  1. 删除.gitmodules文件中的相应条目。条目可能如下所述
[submodule "path_to_submodule"]path = path_to_submoduleurl = url_path_to_submodule
  1. 阶段变化git add .gitmodules
  2. 删除子模块目录git rm --cached <path_to_submodule>
  3. 提交git commit -m "Removed submodule xxx"并推送。

下面提到的另外2个步骤需要在本地克隆副本中完全清理子模块。

  1. 删除.git/config文件中的相应条目。条目可能如下所述
[submodule "path_to_submodule"]url = url_path_to_submodule
  1. rm -rf .git/modules/path_to_submodule

第5步和第6步不会创建任何需要提交的更改。

  • 可以通过运行git rm <submodule path> && git commit删除子模块。这可以使用git revert撤消。
    • 删除会删除超级项目的跟踪数据,这些数据既是gitlink条目,也是.gitmodules文件中的部分。
    • 子模块的工作目录从文件系统中删除,但Git目录保留,因为它可以结帐过去的提交,而无需从另一个存储库获取。
  • 要完全删除子模块,还需要手动删除#0.

来源:git help submodules

为了读者的利益,这里试图总结一下,并给出一个分步指南,说明如果事情没有按预期工作,如何做到这一点。以下是git版本2.17及以上版本去掉一个子模块测试和安全的方式

submodule="path/to/sub"              # no trailing slash!git submodule deinit -- "$submodule"git rm -- "$submodule"
  • 如果这对你不起作用,见下文。
  • 没有选择。没有危险。甚至不要考虑做更多!
  • 使用Debian Buster2.20.1和Ubuntu 18.042.17.1进行测试。
  • "$submodule"只是为了强调在哪里放置名称,并且您必须小心使用空格等
  • 如果在Windows上忽略第一行并将"$submodule"替换为正确指定子模块路径的Windows方式。(我不是Windows)

警告!

永远不要自己触摸#0目录的内部!编辑.git进入黑暗面,不惜一切代价远离!

是的,你可以为此责怪git,因为过去git中缺少许多方便的东西。就像再次删除子模块的正确方法一样。

我认为git submodule的留档中有一个非常危险的部分。建议自己删除$GIT_DIR/modules/<name>/在我看来,这不仅是完全错误的,而且是极其危险的,将来会引起严重的头痛!

注意

git module deinit

是与

git module init

git submodule deinit -- modulegit rm -- module

也与此相反

git submodule add -- URL modulegit submodule update --init --recursive -- module

因为有些命令基本上需要做的不仅仅是一件事:

  • git submodule deinit -- module
    • (1)更新.git/config
  • git rm
    • (2)删除模块的文件
    • (3)从而递归地删除子模块的子模块
    • (4)更新.gitmodules
  • git submodule add
    • 将数据拉至.git/modules/NAME/
    • (1)做git submodule init,所以更新.git/config
    • (2)git submodule update,所以,非递归地检查模块
    • (4)更新.gitmodules
  • git submodule update --init --recursive -- module
    • 如果需要的话可以获取更多数据
    • (3)递归地检查子模块的子模块

这不能完全对称,因为保持严格对称没有多大意义。根本不需要超过两个命令。“拉入数据”也是隐式的,因为你需要它,但删除缓存的信息并没有完成,因为这根本不需要,可能会擦除宝贵的数据。

这确实令新手感到困惑,但基本上是一件好事:git只是做了明显的事情并做对了,甚至没有尝试做更多的事情。

所以我理解人们的抱怨,说“为什么不做git对我来说显而易见的事情”。这是因为这里的“显而易见”取决于观点。在每种情况下的可靠性都要重要得多。因此,对你来说显而易见的东西往往不是在所有可能的技术情况下都是正确的。请记住: AFAICSgit遵循的是技术路径,而不是社交路径。(因此有了聪明的名字: git)

如果这次失败了

由于以下原因,上述命令可能会失败:

  • 你的git太旧了。那就用一个更新的git。(见下面的方法。)
  • 您有未提交的数据并且可能会丢失数据。那最好先提交它们。
  • 您的子模块在git clean意义上不干净。然后首先使用该命令清理您的子模块。(见下文。)
  • 你过去做了一些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 . && exit
  • workhorse:~/path/to/worktree$ git fetch account@othermachine:TMPWORK/.git
  • workhorse:~/path/to/worktree$ git merge --ff-only FETCH_HEAD。如果这不起作用,请使用git reset --soft FETCH_HEAD
  • 现在清理东西,直到git status再次清理干净。你可以这样做,因为你以前已经清理过了,这要归功于第一步。

这个othermachine可以是一些虚拟机,或者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 statusgit clean -ixfd是你的朋友
  • 尽量避免选择rmdeinit。如果你是专业人士,选择git(如-f)是很好的。但是当你来到这里时,你可能在submodule领域没有那么丰富的经验。所以最好是安全而不是遗憾。

示例:

$ git status --porcelainM two$ git submodule deinit twoerror: 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 --allerror: 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 --allerror: 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 -dWould remove the following item:NEW*** Commands ***1: clean                2: filter by pattern    3: select by numbers    4: ask each5: quit                 6: helpWhat now> 1Removing NEW$ cd ../../..$ git status --porcelain$ git submodule deinit twoCleared directory 'two'Submodule 'someunusedname' (https://github.com/hilbix/src.git) unregistered for path 'two'

你看,在submodule deinit上不需要-f。如果事情很干净,在git clean的意义上。还要注意,不需要git clean -x这意味着#4无条件地删除被忽略的未跟踪文件。这通常是你想要的,但不要忘记它。有时被忽略的文件可能很珍贵,比如缓存的数据,需要几个小时到几天才能再次计算。

为什么从不删除$GIT_DIR/modules/<name>/

可能人们想要删除缓存的存储库,因为他们害怕以后遇到问题。这是真的,但遇到那个“问题”是解决它的正确方法!因为修复很容易,做得对,你将能够从此过上幸福的生活。这避免了比你自己删除数据更麻烦的麻烦。

示例:

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.gitIf you want to reuse this local git directory instead of cloning again fromhttps://github.com/hilbix/src.gituse the '--force' option. If the local git directory is not the correct repoor 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 = twourl = 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才能找到正确的东西来删除!

因此,不仅大多数其他答案落入这个危险的陷阱,即使是非常流行的#0扩展也有这个bug现在已经修好了)!所以,如果你不完全清楚你在做什么,最好保持你的手在.git/目录!

从哲学的角度来看,抹去历史总是错误的!除了量子力学,像往常一样,但这是完全不同的东西。

仅供参考,你可能已经猜到了:Hilbix是我的GitHub帐户。

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

设置path_to_submodulevar(无尾随斜杠):

path_to_submodule=path/to/submodule

从. git模块文件中删除相关行:

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

跟踪对. git模块所做的更改

git add .gitmodules

提交超级项目

git commit -m "Remove submodule submodule_name"

删除现在未跟踪的子模块文件

rm -rf $path_to_submodule
rm -rf .git/modules/$path_to_submodule

另见:替代指导线

  1. git submodule deinit <path to submodule>
  2. .gitmodules中删除该部分
  3. git rm <path to submodule>
  4. 删除您需要从项目中删除的模块文件。
  5. 将删除的文件添加到git并调用git add .gitmodules
  6. 提交并推送

使用git v2.7.4简单的3个步骤工作得很好。

git submodule deinit -f -- a/submodulegit rm -f a/submodulegit commit

这对我有用。上面的答案在终端中显示了这一点,没有其他事情发生

'fatal: not removing 'demolibapp' recursively without -r'
  1. demolibapp是我想要删除的子模块名称
  2. git子模块deinit demolibapp
  3. git rm--cache demolibapp-r###########################################################下载安装
  4. 代码库rm-rf. git/demolibapp
  5. 添加失败
  6. #删除额外的子模块#删除额外的子模块
  7. git推送
  8. rm-rf demolibapp

所有答案看起来都过时了。我使用的是git版本2.28.0。一行答案是,

git rm path-to-submodule

但是,即使子模块从源代码控制中删除,. git/模块/路径到子模块仍然包含子模块存储库,. git/config包含其URL,因此您仍然必须手动删除这些:

git config --remove-section submodule.path-to-submodulerm -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中删除子模块的最佳方法:

$ 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>'

使用Magit的简单解决方案

如果您在Emacs下使用Magit,您可以按以下方式进行:

然后转到您的项目根

M-xmagit-list-submodules

然后

M-xmagit-submodule-remove

系统会询问您要删除哪个子模块。

就是它了!


(我的Magit版本是v3.3.0)

如果您想在不从本地文件系统中删除文件夹的情况下删除子模块,这里对我有用:

MOD=examplegit rm --cached -f apps/$MODgit config -f .gitmodules --remove-section submodule.$MOD

我遵循了同样的指南的说明如何删除子模块?

$ 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>'

但它一直在说:

fatal: no submodule mapping found in .gitmodules for path

所以我所做的是像这样包含. gitignore中的路径(路径末尾没有星号):

<path>

然后我修改了任何文件并执行了简单推送

$ git add .$ git commit -m "Ignoring sharedlibs folder <path> on .gitignore"$ git push -u origin master