繁体   English   中英

如何删除子模块?

[英]How do I remove a submodule?

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

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

  • 运行git rm <path-to-submodule>并提交

这将删除<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

另请参阅下面的替代步骤

git1.8.3(2013 年 4 月 22 日)开始

一旦您使用“ git submodule init ”表达您对子模块的兴趣,就没有瓷器方式说“我不再对这个子模块感兴趣”。
git submodule deinit ” 是这样做的方法。

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

概括

3 步删除过程将是:

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回答中提到,并由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 他们不再关心子模块并想要摆脱本地工作树(除非用户对子模块内部有很多了解并删除“ submodule.$name.url.git/config以及工作树本身的设置)。

通过提供“ deinit ”命令来帮助这些用户。
会从.git/config中删除给定子模块的整个submodule.<name>部分(或者对于所有已初始化的子模块(如果给出了 ' . ')。
如果当前工作树包含修改,则失败,除非强制执行。
抱怨在命令行中给出的子模块的 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 )提交 2e61273提交 1342476 (2018 年 1 月 14 日)。
(由Junio C Hamano -- gitster --提交 ead8dbe中合并,2018 年 2 月 13 日)

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

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

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

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

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

简单的步骤

  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 $submodulepath
git config -f .git/config --remove-section submodule.$submodulepath

如果您将其放入脚本中,最好先执行git rebase HEAD并在最后执行git commit

还可以查看Can I unpopulate a Git 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

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

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

git rm --cached path/to/submodule

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

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

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

    path_to_submodule=path/to/submodule

  2. 从 .gitmodules 文件中删除相关行:

    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. 跟踪对 .gitmodules 所做的更改

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

我发现deinit对我很有用:

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

来自git 文档

去初始化

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

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

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

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

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

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

#!/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)

我目前在 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"

这是我所做的:

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

为了读者的利益,这里试图对其进行总结,并提供一个分步指南,说明如果事情没有按预期工作时如何做到这一点。 以下是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/<name>/ 在我的理解中,这不仅是完全错误的,而且是极其危险的,并且会在未来引起重大的头痛! 见下文。

注意

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 -- 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是一个工具,它必须做一个可靠的工作,而不是只是另一个“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不能输出任何东西! 如果是这样,请先清理东西!
  • 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可以是某个 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 statusgit clean -ixfd是你的朋友
  • 尽量避免使用rmdeinit的选项。 如果您是专业人士,则git的选项(如-f )很好。 但是当你来到这里时,你可能在submodule领域没有那么有经验。 所以最好是安全而不是抱歉。

例子:

$ 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/<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.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 git rm $module; rm -f .git/module/$module完全错误! 您必须查阅module/.git.gitmodules以找到要删除的正确内容!

因此,不仅大多数其他答案落入了这个危险的陷阱,甚至非常流行的git扩展也有这个错误现在已经修复了)! 因此,如果您不完全了解您在做什么,最好将您的手放在.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)

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

cd submodule
rm -fr .git

然后我可以将文件作为父 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 的回答所指出的,您可能可以摆脱 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-rm[1]代替

最后但并非最不重要的一点是,如果您不git commit ,您将/可能在执行git submodule summary时出错(从 gi​​t 2.7 开始):

fatal: Not a git repository: 'the_submodule/.git'
* the_submodule 73f0d1d...0000000:

这与您执行第 2 步还是第 3 步无关。

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

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

对于 git 2.17 及更高版本,它只是:

git submodule deinit -f {module_name}
git add {module_name}
git commit
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 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

另请参阅: 替代指南

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

'fatal: not removing 'demolibapp' recursively without -r'
  1. demolibapp是我要删除的子模块名称
  2. git 子模块 deinit demolibapp
  3. git rm --cached demolibapp -r
  4. rm -rf .git/modules/demolibapp
  5. git add --all
  6. git commit -m "删除多余的子模块"
  7. git 推送
  8. rm -rf demolibapp

我创建了一个 bash 脚本来简化删除过程。 它还会检查 repo 中是否有未保存的更改并要求确认。 它已经在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目录中创建名为remove_submodule.sh的 bash 脚本文件:

#!/bin/bash

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

使用 Magit 的简单解决方案

如果你在 Emacs 下使用Magit ,你可以进行如下操作:

转到您的项目根目录,然后

Mx , magit-list-submodules

然后

Mx , magit-submodule-remove

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

而已!


(我的 Magit 版本是 v3.3.0)

如果您想删除子模块而不从本地文件系统中删除文件夹,这对我有用:

MOD=example
git rm --cached -f apps/$MOD
git config -f .gitmodules --remove-section submodule.$MOD

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

  • 删除.gitmodules中的对应条目
  • 阶段更改git add .gitmodules
  • 删除子模块目录git rm --cached <path_to_submodule>
  • 提交git commit -m "Removed submodule xxx"
  • 可以通过运行git rm <submodule path> && git commit删除子模块。 这可以使用git revert撤消。
    • 删除删除了超级项目的跟踪数据,这些数据既是 gitlink 条目,也是.gitmodules文件中的部分。
    • 子模块的工作目录已从文件系统中删除,但 Git 目录保留在原处,以便可以检查过去的提交,而无需从另一个存储库中获取。
  • 要完全删除子模块,请另外手动删除$GIT_DIR/modules/<name>/

来源: git help submodules

删除 git 子模块

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

  1. 删除.gitmodules文件中的相应条目。 条目可能如下所述
[submodule "path_to_submodule"]
    path = path_to_submodule
    url = 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 步不会创建任何需要提交的更改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM