如何删除子模块?

R. *_*des 3366 git git-submodules

如何删除Git子模块?

顺便说一句,有什么理由我不能干脆做到 git submodule rm whatever吗?

Joh*_*hat 3369

通过页面Git Submodule教程:

要删除子模块,您需要:

  1. .gitmodules文件中删除相关部分.
  2. 分阶段进行.gitmodules变革git add .gitmodules
  3. 删除相关部分.git/config.
  4. 运行git rm --cached path_to_submodule(没有尾部斜杠).
  5. .git
  6. 承诺 rm -rf .git/modules/path_to_submodule
  7. 删除现在未跟踪的子模块文件
    git commit -m "Removed submodule <name>"

另见:下面的替代步骤.

  • "顺便说一下,有什么理由我不能简单地给子模块做任何事情吗?" ? (398认同)
  • 坦率地说,我不知道为什么.但我希望他们能增加一个命令.这4个步骤太复杂了. (116认同)
  • @abernier一个简单的答案可能是"因为没有这样的命令存在." 我的猜测是他们试图明确删除子模块文件与子模块配置,以避免意外数据丢失.也许有人会认为`git submodule rm`只是删除子模块注册,如果命令也删除了本地存储库,会感到惊讶.任何局部变化都将无可挽回地丧失.也许另一个人会认为只会删除文件. (47认同)
  • 还需要rm -rf .git\modules\submodule名称? (32认同)
  • 这是一个删除子模块的bash脚本,只需为submodule-rm创建一个git别名;)https://gist.github.com/2491147 (24认同)
  • @dtan确保没有斜杠 (7认同)
  • 如果要将目录重新添加为普通子模块(还记得删除其内部.git文件夹),则需要删除.git/modules参考目录.请参阅下面Mark的答案:http://stackoverflow.com/a/9536504/149416 (7认同)
  • `git submodule rm`应该是一个命令.如果在子模块中有子模块,这种设置会变得更加复杂,因为`.git/config`的位置会发生变化. (4认同)
  • 你需要暂存.gitmodules.在提交之前运行git add .gitmodules. (3认同)
  • 好吧,我不得不再次`git rm --cached -f submodule_name`,现在它可以了. (2认同)
  • 还必须清理.git/modules以允许稍后使用相同的路径添加模块. (2认同)
  • “在现代 git 中(我在 2022 年写这篇文章,并更新了 git 安装)”——您能说出您正在使用的具体版本号吗?或者甚至更好,是 git 的最早版本,它变得更简单。 (2认同)

Von*_*onC 2067

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

一旦你表达了对带有" submodule init" 的子模块的兴趣,就没有瓷器方式说"我不再对这个子模块感兴趣".
" 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
Run Code Online (Sandbox Code Playgroud)

说明

rm -rf:Daniel Schroeder回答中提到了这一点,并在评论中Eonil总结:

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


git rm:请参阅commit 95c16418:

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

让" git rm"帮助用户不仅从工作树中删除子模块,而且还submodule.<submodule name>.gitmodules文件中删除" "部分并将两者都分段.


git submodule deinit:它来自这个补丁:

使用" git submodule init",用户可以告诉git他们关心一个或多个子模块,并希望在下次调用" git submodule update" 时填充它.
但目前没有简单的方法他们可以告诉git他们不再关心子模块并且想要摆脱本地工作树(除非用户知道很多关于子模块内部并且submodule.$name.url.git/config工作中删除" "设置树自己).

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

如果(de)初始化步骤(.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.txt 
Path 'mysubmodule/file.txt' is in submodule 'mysubmodule'
Run Code Online (Sandbox Code Playgroud)

注意:自Git 2.17(2018年第二季度)以来,git子模块deinit不再是shell脚本.
它是对C函数的调用.

参见Prathamesh Chavan()提交2e61273,提交1342476(2018年1月14日).(由Junio C Hamano合并- -提交ead8dbe,2018年2月13日)pratham-pc
gitster

git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit \
  ${GIT_QUIET:+--quiet} \
  ${prefix:+--prefix "$prefix"} \
  ${force:+--force} \
  ${deinit_all:+--all} "$@"
Run Code Online (Sandbox Code Playgroud)

  • 你能给出一个用于`submodule deinit`的例子吗? (16认同)
  • @yourfriendzak这里是成功使用它的一个例子:http://stackoverflow.com/a/16161950/6309.但请记住,与我原先认为的相反,1.8.3还没有发布!在Unix上,您可以从源代码编译它. (4认同)
  • @HamishDowner 特殊条目应该消失(该目录不再是子模块),并且 `.gitmodules` 应该没问题,但我仍然会仔细检查 `.git` 目录的任何内容(即 *local* 配置, 在您的本地存储库中:不会被 `git pull` 修改) (2认同)
  • @Jayen 是的,如果您提交删除 `.gitmodules` 条目并删除索引中的特殊条目,并推送该 repo,其他人可以拉它并且该子模块将消失。 (2认同)
  • 在当前的git(v1.9 +)中,普通的旧`git rm子模块'完全按照你想要的那样做,正如其他人已经说过的那样. (2认同)

tin*_*lyx 442

只是一张纸条.从git 1.8.5.2开始,有两个命令可以:

git rm the_submodule
rm -rf .git/modules/the_submodule
Run Code Online (Sandbox Code Playgroud)

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

- 更新(07/05/2017) -

只是为了澄清,the_submodule是项目内子模块的相对路径.例如,subdir/my_submodule如果子模块位于子目录中subdir.

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

git config -f .git/config --remove-section submodule.the_submodule 2> /dev/null
Run Code Online (Sandbox Code Playgroud)

  • 这不会从`.git/config`中删除子模块条目.有关删除子模块的完整方法,请参见http://stackoverflow.com/a/36593218/1562138. (17认同)
  • 我正在使用git版本2.4.9(Apple Git-60),而我所要做的只是rm the_submodule.我推了一下,然后重新添加了一个名为与子模块相同的文件夹,它没有问题. (3认同)
  • 这是100%绝对辉煌和工作.哇. (3认同)
  • @drevicko 我刚刚用 Git 2.11.1 测试了这个,我观察到与以前相同的行为。`git init &amp;&amp; git submodule add &lt;repository&gt; &amp;&amp; git rm &lt;name&gt;` 留下了 `.git/config` 条目和 `.git/modules/&lt;name&gt;` 目录及其内容。也许您在删除之前没有初始化子模块? (2认同)
  • 我觉得更安全地运行第一个.. git submodule deinit -f the_submodule (2认同)

fvg*_*vgs 417

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

使用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
Run Code Online (Sandbox Code Playgroud)

  • 为什么这个答案有这么少的赞成?所有那些受欢迎的答案都会遗漏一些东西,这是唯一能够以最简单的方式真正消除子模块所有痕迹的答案.请注意:命令的顺序很重要. (30认同)
  • *.gitmodules*文件似乎仍然不受影响运行这些命令 (8认同)
  • 这是2018年的不复杂答案吗? (7认同)
  • @mbdevpl在接受答案后3年,我想没有人设法说服OP接受这个 (5认同)
  • 2019 年这行不通了。最后一行实际上尝试从“.git/modules”文件夹中删除,您已经在上面的行中删除了该文件夹。像接受的答案一样在第一行添加“--”似乎可以使这项工作成功。 (5认同)
  • 回答我自己的问题:http://stackoverflow.com/questions/97875/rm-rf-equivalent-for-windows (2认同)
  • @Thomas `rm -rf` 仅表示“删除整个文件夹”,因此您可以从 Windows 中的资源管理器 GUI 执行此操作。或者,如果您在 Windows 中使用 git,您也可以使用 git bash,因此您可以在那里运行所有这些命令,它们将按原样工作 (2认同)
  • @Fmstrat `git v2.20.1` 仍然把 `.git/modules/submodule` 留在我身边,所以现在或以后似乎需要 `rm`。如果较新的 git 想要删除它,没问题,**只需交换最后两个命令**。另请注意,`git deinit`和`git rm`相对安全,但**`rm -rf .git/modules/submodule`很危险,因为它可能会删除错误的目录**。您可以重命名和移动子模块,它们仅包含要在“.git”文件(和“.git/config”)中删除的正确路径。另外,如果您在历史记录中跳转,则删除模块的副本可能是错误的。事情很复杂.. (2认同)

err*_*per 200

简单的步骤

  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
Run Code Online (Sandbox Code Playgroud)

这是一个好主意,做git rebase HEAD第一,git commit 在最后,如果你把这个脚本.

还看看我可以解开一个Git子模块的答案吗?.

  • 获取没有进行本地更改的模块列表 - `git submodule | grep'^ +'| cut -d'' - f2` (2认同)

Mar*_*ton 82

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


Dou*_*oug 56

要删除使用以下内容添加的子模块:

git submodule add blah@blah.com:repos/blah.git lib/blah
Run Code Online (Sandbox Code Playgroud)

跑:

git rm lib/blah
Run Code Online (Sandbox Code Playgroud)

而已.

对于旧版本的git(大约~1.8.5),请使用:

git submodule deinit lib/blah
git rm lib/blah
git config -f .gitmodules --remove-section submodule.lib/blah
Run Code Online (Sandbox Code Playgroud)

  • `git rm`仍然在`.git/modules /`中留下了东西.(2.5.4) (6认同)
  • +1确实。这是 git 1.8.3 以后的唯一正确答案。应该被接受为正确的。 (2认同)
  • 这个答案并不完全正确。`git rm` 将内容留在 `.git/modules/` 目录和 `.git/config` 文件(ubuntu,git 2.7.4)中。其他答案 100% 有效:http://stackoverflow.com/a/36593218/4973698 (2认同)

Car*_*ino 49

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

git rm --cached path/to/submodule
Run Code Online (Sandbox Code Playgroud)

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


lui*_*all 41

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

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

    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. Unstage并仅从索引中删除$ 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


Cha*_*les 41

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

[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"
Run Code Online (Sandbox Code Playgroud)

把它放在你的git配置中,然后你就可以: git rms path/to/submodule


Oli*_*lme 39

如果由于您添加,提交并推送了一个已经是Git存储库(包含)的文件夹而意外添加了子模块.git,则您将无法.gitmodules编辑或编辑任何文件.git/config.在这种情况下,您只需要:

git rm --cached subfolder
git add subfolder
git commit -m "Enter message here"
git push
Run Code Online (Sandbox Code Playgroud)

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


Dam*_*ica 30

我发现deinit作品对我有好处:

git submodule deinit <submodule-name>    
git rm <submodule-name>
Run Code Online (Sandbox Code Playgroud)

来自git docs:

DEINIT

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

  • 我们可以承认 Git 的子模块太复杂了吗? (2认同)

udo*_*dan 20

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

#!/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
Run Code Online (Sandbox Code Playgroud)

这将恢复与添加子模块之前完全相同的状态.您可以立即再次添加子模块,这在大多数答案中是不可能的.

git submodule add $giturl test
aboveScript test
Run Code Online (Sandbox Code Playgroud)

这样您就可以获得干净的结账,而无需更改提交.

测试结果如下:

$ git --version
git version 1.9.3 (Apple Git-50)
Run Code Online (Sandbox Code Playgroud)

  • -1 如果您尝试删除子模块中的子模块,则不起作用(子模块可以形成树!)。另外**由于缺少引用,这是危险的错误**!示例 `git submodule add https://github.com/hilbix/empty.git 'dangerous .. submodule'` -&gt; 当您尝试使用脚本删除 'dangerous .. submodule' 时,这将是 `rm -rf .. ` 这很可能不是您想要的.. (2认同)

Lan*_*ing 17

我目前正在做什么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}"
Run Code Online (Sandbox Code Playgroud)


Bla*_*ack 16

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

  • 对我来说,调用 `git submodule deinit &lt;submodule_name&gt;` 和 `git rm &lt;path_to_submodule&gt;` 就足够了。最后一个命令会自动删除 `.gitmodules` 中的条目。git 2.17 (12认同)

gis*_*gis 16

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

git rm path-to-submodule
Run Code Online (Sandbox Code Playgroud)

但是,即使子模块已从源代码管理中删除,.git/modules/path-to-submodule 仍然包含子模块存储库,并且 .git/config 包含其 URL,因此您仍然需要手动删除它们:

git config --remove-section submodule.path-to-submodule
rm -rf .git/modules/path-to-submodule
Run Code Online (Sandbox Code Playgroud)

有时,您必须使用该-f标志:

$ git rm -f img2vec
Run Code Online (Sandbox Code Playgroud)

例如,因为您可能会收到如下错误:

$ 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)
Run Code Online (Sandbox Code Playgroud)


Ish*_*age 14

这是我做的:

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

git config -f .gitmodules --remove-section "submodule.submodule_name"
Run Code Online (Sandbox Code Playgroud)

2.)分阶段进行.gitmodules变革

git add .gitmodules
Run Code Online (Sandbox Code Playgroud)

3.)删除相关部分.git/config.您可以使用以下命令:

git submodule deinit -f "submodule_name"
Run Code Online (Sandbox Code Playgroud)

4.)删除gitlink(没有尾部斜杠):

git rm --cached path_to_submodule
Run Code Online (Sandbox Code Playgroud)

5.)清理.git/modules:

rm -rf .git/modules/path_to_submodule
Run Code Online (Sandbox Code Playgroud)

6.)承诺:

git commit -m "Removed submodule <name>"
Run Code Online (Sandbox Code Playgroud)

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

rm -rf path_to_submodule
Run Code Online (Sandbox Code Playgroud)


Chi*_*ang 13

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

安装并输入:

git-delete-submodule submodule
Run Code Online (Sandbox Code Playgroud)

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


Ash*_*gar 11

从 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>'
Run Code Online (Sandbox Code Playgroud)


Kyl*_*egg 10

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

cd submodule
rm -fr .git
Run Code Online (Sandbox Code Playgroud)

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


Tin*_*ino 9

为了读者的利益,这里尝试对其进行总结,并提供有关如果事情未按预期工作时如何执行此操作的分步指南。以下是测试和安全的方式git版本2.17及以上摆脱子模块

submodule="path/to/sub"              # no trailing slash!
git submodule deinit -- "$submodule"
git rm -- "$submodule"
Run Code Online (Sandbox Code Playgroud)
  • 如果这对您不起作用,请参见下文。
  • 没有选择。没什么危险。甚至不考虑做更多!
  • 使用 Debian Buster2.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
Run Code Online (Sandbox Code Playgroud)

是正反

git module init
Run Code Online (Sandbox Code Playgroud)

git submodule deinit -- module
git rm -- module
Run Code Online (Sandbox Code Playgroud)

也完全相反

git submodule add -- URL module
git submodule update --init --recursive -- module
Run Code Online (Sandbox Code Playgroud)

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

  • 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为我做显而易见的事情”。这是因为这里的“明显”取决于观点。在每种情况下的可靠性要重要得多。因此,在所有可能的技术情况下,对您来说显而易见的事情往往不是正确的。请记住:AFAICSgit遵循技术路径,而不是社会路径。(因此聪明的名字:git)

如果这失败

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

  • git太老了。然后使用较新的git. (请参阅下面的方法。)
  • 您有未提交的数据,可能会丢失数据。然后最好先提交它们。
  • git clean某种意义上说,您的子模块并不干净。然后首先使用该命令清理您的子模块。(见下文。)
  • 您过去做了一些不受git. 然后你就处于黑暗的一面,事情变得丑陋和复杂。(也许使用另一台机器修复它。)
  • 也许有更多我不知道的失败方法(我只是一些git高级用户。)

可能的修复如下。

使用较新的 git

如果您的机器太旧submodule deinit,您的git. 如果你不希望(或可以)更新您做git,那么就用另一台机器用较新的gitgit旨在完全分布式,因此您可以使用另一个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
Run Code Online (Sandbox Code Playgroud)

您可以使用此乘法,并将其保存到$HOME/.gitconfig. 就像是

git config --add 'url./mnt/usb/repo/.insteadof' https://github.com/
Run Code Online (Sandbox Code Playgroud)

重写 URL,如

https://github.com/XXX/YYY.git
Run Code Online (Sandbox Code Playgroud)

进入

/mnt/usb/repo/XXX/YYY.git
Run Code Online (Sandbox Code Playgroud)

如果您开始习惯这样的强大git功能,这很容易。

先清理东西

手动清理是好的,因为这样你可能会发现一些你忘记的东西。

  • 如果 git 抱怨未保存的东西,提交并将其推送到安全的地方。
  • 如果 git 抱怨一些剩菜,git status并且git clean -ixfd是你的朋友
  • 尝试从选项弃权rmdeinit,只要你能。如果您是专业人士-fgit则选项(如)很好。但是当您来到这里时,您可能在该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'
Run Code Online (Sandbox Code Playgroud)

你看,上-f不需要submodule deinit。如果事情是干净的,在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
Run Code Online (Sandbox Code Playgroud)

最后一行输出以下错误:

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.
Run Code Online (Sandbox Code Playgroud)

为什么会出现这个错误?因为.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
Run Code Online (Sandbox Code Playgroud)

.gitmodules 然后看起来像

[submodule "someunusedname"]
    path = two
    url = https://github.com/hilbix/src.git
Run Code Online (Sandbox Code Playgroud)

ls -1p .git/modules/

someunusedname/
two/
Run Code Online (Sandbox Code Playgroud)

这样,将来您可以向前和向后切换分支/提交,并且永远不会再遇到任何麻烦,因为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找到要删除的正确内容!

因此,不仅大多数其他答案都落入了这个危险的陷阱,甚至非常流行的git扩展也有这个错误现在已在那里修复)!所以最好保持你手中的.git/目录,如果你不完全,你在做什么!

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

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


小智 9

我按照同一指南中的说明进行操作 如何删除子模块?

$ 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>'
Run Code Online (Sandbox Code Playgroud)

但它一直说:

fatal: no submodule mapping found in .gitmodules for path
Run Code Online (Sandbox Code Playgroud)

所以我所做的是将路径包含在 .gitignore 中,如下所示(路径末尾没有星号):

<path>
Run Code Online (Sandbox Code Playgroud)

然后我修改了任何文件并做了一个简单的推送

$ git add .
$ git commit -m "Ignoring sharedlibs folder <path> on .gitignore"
$ git push -u origin master
Run Code Online (Sandbox Code Playgroud)


小智 8

以下是我发现必要或有用的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 "..."
Run Code Online (Sandbox Code Playgroud)

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

但是截至2017年7月,步骤2是必要的,以删除数据,.git/modules/否则,您不能在以后添加子模块.

正如tinlyx的回答所指出的那样,你可以通过git 1.8.5+的上述两个步骤逃脱,因为所有git submodule命令似乎都有效.

第3步删除the_submodule文件中的部分.git/config.这应该是为了完整性.(该条目可能会导致较旧的git版本出现问题,但我没有测试版本).

为此,大多数答案建议使用git submodule deinit.我发现它更明确,使用起来也更少混乱git config -f .git/config --remove-section.根据git-submodule文档,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:
Run Code Online (Sandbox Code Playgroud)

无论您是执行步骤2还是3,都可以执行此操作.


Yur*_*iak 8

使用 git v2.7.4 简单的 3 个步骤就可以了。

git submodule deinit -f -- a/submodule    
git rm -f a/submodule
git commit
Run Code Online (Sandbox Code Playgroud)


Ste*_*n J 7

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

注意到没有人发布手动擦除,所以补充说


小智 7

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
Run Code Online (Sandbox Code Playgroud)


Alb*_*bac 6

在git 2.17及更高版本中,它只是:

git submodule deinit -f {module_name}
git add {module_name}
git commit
Run Code Online (Sandbox Code Playgroud)


bot*_*bot 5

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


小智 5

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

设置path_to_submodule var(无尾部斜杠):

path_to_submodule=path/to/submodule
Run Code Online (Sandbox Code Playgroud)

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

git config -f .gitmodules --remove-section submodule.$path_to_submodule
Run Code Online (Sandbox Code Playgroud)

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

git config -f .git/config --remove-section submodule.$path_to_submodule
Run Code Online (Sandbox Code Playgroud)

仅从索引中取消暂存并删除 $path_to_submodule (以防止丢失信息)

git rm --cached $path_to_submodule
Run Code Online (Sandbox Code Playgroud)

跟踪对 .gitmodules 所做的更改

git add .gitmodules
Run Code Online (Sandbox Code Playgroud)

提交超级项目

git commit -m "Remove submodule submodule_name"
Run Code Online (Sandbox Code Playgroud)

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

rm -rf $path_to_submodule

rm -rf .git/modules/$path_to_submodule
Run Code Online (Sandbox Code Playgroud)

另请参阅:替代指南

  • 我认为你需要交换 `git rm --cached $path_to_submodule` 和 `git add .gitmodules` 不是吗?我确实在第一个命令上遇到了错误:“致命:请将您的更改暂存到 .gitmodules 或将它们存储以继续”,因为我对“.gitmodules”进行了未暂存的更改。首先执行 `git add .gitmodules` 可以解决这个问题。 (2认同)

Poo*_*ngh 5

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

'fatal: not removing 'demolibapp' recursively without -r'
Run Code Online (Sandbox Code Playgroud)
  1. demolibapp是我要删除的子模块名称
  2. git 子模块 deinit demolibapp
  3. git rm --cached demolibapp -r
  4. rm -rf .git/modules/demolibapp
  5. git add --全部
  6. git commit -m“删除额外的子模块”
  7. git 推送
  8. rm -rf demolibapp


jus*_*ase 5

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

MOD=example
git rm --cached -f apps/$MOD
git config -f .gitmodules --remove-section submodule.$MOD
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

826052 次

最近记录:

5 年,9 月 前