如何删除子模块?

如何删除 Git 子模块?

顺便说一句,有一个原因我不能简单地做git submodule rm whatever吗?

答案

通过页面Git Submodule Tutorial

要删除子模块,您需要:

  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 日)

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

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

摘要

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模块内部知识了解很多,并删除 “ submodule.$name.url.git/config设置以及工作树本身)。

通过提供 “ deinit ” 命令来帮助那些用户。
消除了整个submodule.<name>从部.git/config或者对于给定的子模块(一个或多个)(或所有那些已被初始化,如果 “ ” 给出)。 .
如果当前工作树包含修改,则该操作失败,除非强制执行。
对于在命令行上给出的子模块,如果在.git/config找不到 url 设置,则应进行投诉,但不要失败。

如果(取消)初始化步骤( .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'

注意:从 Git 2.17(Q2 2018)开始,git 子模块 deinit 不再是 Shell 脚本。
这是对 C 函数的调用。

参见Prathamesh Chavan( pratham-pc )的 commit 2e61273commit 1342476 (2018 年 1 月 14 日
(由Junio C gitster - gitstercommit 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.8.5.2 开始,将执行以下两个命令:

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

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

- 更新(07/05/2017)-

为了明确the_submodulethe_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

该问题的大多数答案已经过时,不完整或不必要地复杂。

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

简单步骤

  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

另请参阅 “我可以不填充 Git 子模块吗?”的答案

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

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

git submodule add blah@blah.com:repos/blah.git lib/blah

跑:

git rm lib/blah

而已。

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

git submodule deinit lib/blah
git rm lib/blah
git config -f .gitmodules --remove-section submodule.lib/blah

您必须删除.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 配置中,然后您可以执行以下操作: git rms path/to/submodule