如何删除Git子模块?为什么不能直接使用git submodule rm module_name
命令?
如何删除Git子模块?为什么不能直接使用git submodule rm module_name
命令?
总之,这是你应该采取的步骤:
设置 path_to_submodule
变量(没有尾随斜杠):
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
git submodule
:git submodule update
。如果子模块的路径没有正确更新(git 抛出错误),请将它们删除:rm -rf .git/modules/ && rm -rf && git submodule update
- luissquall如果子模块是因为您添加、提交和推送包含.git
的文件夹而意外添加的,那么您将没有.gitmodules
文件可以编辑,或者在.git/config
中找到任何东西。在这种情况下,您所需要的仅仅是:
git rm --cached subfolder
git add subfolder
git commit -m "Enter message here"
git push
FWIW,我在执行git add
命令之前也删除了.git
文件夹。
git submodule deinit <path to submodule>
.gitmodules
文件中移除该模块的配置信息。git rm <path to submodule>
git add .gitmodules
命令。git submodule deinit <submodule_name>
和 git rm <path_to_submodule>
即可。最后一个命令会自动删除 .gitmodules
文件中的相关条目。此操作适用于 Git 2.17 及以上版本。 - Dmytro Ovdiienkogit rm
命令中使用 -r
参数:git rm -r <path_to_submodule>
。 - william_grisaitis通过尝试该网站上提供的所有不同答案,我最终得出了这个解决方案:
#!/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)
git rm --cached $path
然后 rm -rf $path
而不是 git rm -r $path
? - bfontainegit submodule add https://github.com/hilbix/empty.git 'dangerous .. submodule'
->当您尝试使用脚本删除'dangerous .. submodule'时,这将rm -rf ..
,这很可能不是您想要的.. - Tino我目前正在做的事情(截至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}"
以下是我所做的:
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.) 移除 Git 链接(不包含尾部斜杠):
git rm --cached path_to_submodule
五.) 清理 .git/modules
目录:
rm -rf .git/modules/path_to_submodule
6.) 提交:
git commit -m "Removed submodule <name>"
7.) 删除现在未被跟踪的子模块文件
rm -rf path_to_submodule
所有的回答看起来都已经过时了。我正在使用 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)
.gitmodules
文件。git rm --cached -r <path-to-submodule-dir>
从索引中删除相关数据。我最近发现了一个包含许多有用的git相关命令的git项目:https://github.com/visionmedia/git-extras
安装它并输入:
git-delete-submodule submodule
然后就完成了。子模块目录将从你的仓库中移除,但仍存在于你的文件系统中。你可以执行以下命令提交修改:git commit -am "Remove the submodule"
。
git delete-submodule
,因为需要将git-extras
置于路径中才能使用。另外请注意,我建议不要使用git-extras
,因为其中很多部分都是极其有缺陷和危险的。例如,git-delete-submodule
可能会删除.git/modules/*
下错误的路径,因为它假定模块和路径是相同的(这通常不是这种情况),并且如果您尝试删除子模块内的子模块,则无法正常工作。git-extras
可能会有99%的帮助,但如果使用它时出现问题,请不要抱怨。你已经被警告了! - Tinoapt install git-extras && git delete-submodule submodule
。@Chien-Wei Huang的帖子中额外添加了一个“-”符号。 - Machinexagit
版本2.17
及以上版本摆脱子模块的经过测试和安全的方法:submodule="path/to/sub" # no trailing slash!
git submodule deinit -- "$submodule"
git rm -- "$submodule"
git module deinit
是直接的反向操作
git module init
git submodule deinit -- module
git rm -- module
也正好相反{{to}}
git submodule add -- URL module
git submodule update --init --recursive -- module
因为一些命令基本上需要做的不仅仅是一件事情:
git submodule deinit -- module
.git/config
git rm
.gitmodules
git submodule add
.git/modules/NAME/
git submodule init
,因此更新.git/config
git submodule update
,所以非递归地检出模块.gitmodules
git submodule update --init --recursive -- module
这不能完全对称,因为严格保持对称并没有太多意义。只需要两个命令就足够了。而“拉取数据”是隐含的,因为你需要它,但不需要删除缓存信息,因为这根本不需要,可能会删除宝贵的数据。
这对新手来说确实很困惑,但基本上是一件好事:{{git}}只做明显的事情并且做得正确,甚至不试图去做更多。{{git}}是一个必须要可靠完成工作的工具,而不是另一个“Eierlegende Wollmilchsau”(“Eierlegende Wollmilchsau”翻译成中文是“瑞士军刀的邪恶版本”)。上面的命令可能会因以下原因失败:
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
存储库。您可以将工作树复制到某个USB驱动器上(包括.git
目录),然后从该驱动器克隆。再次克隆该副本,以便以干净的方式获取内容。如果您的子模块不能直接从其他机器访问,则可能会很麻烦。但是也有解决方案: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 status
和git clean -ixfd
。rm
和deinit
选项。如果您是专业人士,则可以使用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/
具有两个不同(可能不兼容)的上游存储库。最好的是:您也在本地保留了两者的缓存。
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帐户。
我必须进一步跟随John Douthat的步骤,并cd
到子模块的目录,然后删除Git仓库:
我需要更进一步地跟随John Douthat的步骤,进入子模块目录并使用cd
命令,接着删除Git仓库:
cd submodule
rm -fr .git
然后我可以将这些文件提交到父级 Git 存储库中,而无需保留之前子模块的引用。
git rm --cache
步骤时克服“fatal: Not a git repository:”错误。 - RickDT
.git/config
中删除子模块条目的问题。被采纳的回答展示了完全移除子模块的最新方法。这个回答也在这里更简洁地解释了:https://dev59.com/QHM_5IYBdhLWcg3wt1k0#36593218 - fvgs