我在Git仓库中有几个具有功能的分支。每个功能都是一些外部仓库,作为子模块插入。在有子模块和无子模块的情况下,如何纠正分支之间的切换?
示例:
$ git init
$ git commit -m "empty" --allow-empty
$ git checkout -b feature
$ git submodule init
$ git submodule add git://feature.git feature
$ git commit -a -m "add feature"
$ git checkout master
warning: unable to rmdir feature: Directory is not empty
并且我们在master
分支工作目录中具有一项功能。如何预防?
似乎最简单的方法是手动删除子模块目录。价格是您每次结帐后必须git submodule init && git submodule update
。
与.gitmodules
中的目录匹配:
grep path .gitmodules | sed 's/.*= //'
*来自Prelang/gist/git-submodule-names
要删除它:
grep path .gitmodules | sed 's/.*= //' | xargs rm -rf
git submodule deinit .
可以解决问题
使用Git 2.27(2020年第二季度),情况应该会有所改善,并且“ git checkout --recurse-submodules
”在嵌套的子模块层次结构中效果更好。
由commit 846f34d参见commit e84704f,commit 16f2b6b,commit 8d48dd1,commit d5779b6,commit bd35645,Philippe Blain (phil-blain
)(2020年2月17日)。[(由phil-blain
在Junio C Hamano -- gitster
--中合并,2020年3月27日)>
gitster
:检查commit fe87060中缺少的子模块目录>报告人:Philippe Blain
[报告人:达米恩·罗伯特签名人:Philippe Blain使用
unpack-trees
至在没有子模块的分支和具有初始化嵌套子模块的分支之间切换当前会导致致命错误:unpack-trees
检出成功,但是第一级子模块的工作树和索引为左空
:merged_entry
签出期间发生致命错误的原因是,子git进程试图将
git checkout --recurse-submodules
插入尚不存在的嵌套子模块目录中。顺序如下:
主git进程(在超级项目中运行的那个进程)最终到达
$ git checkout --recurse-submodules branch-with-nested-submodules fatal: exec '--super-prefix=submodule/nested/': cd to 'nested' failed: No such file or directory error: Submodule 'nested' could not be updated. error: Submodule 'submodule/nested' cannot checkout new HEAD. error: Submodule 'submodule' could not be updated. M submodule Switched to branch 'branch-with-nested-submodules'
中的$ cd submodule $ git -c status.submoduleSummary=1 status HEAD detached at b3ce885 Changes to be committed: (use "git restore --staged <file>..." to unstage) deleted: .gitmodules deleted: first.t deleted: nested fatal: not a git repository: 'nested/.git' Submodule changes to be committed: * nested 1e96f59...0000000: $ git ls-files -s $ # empty $ ls -A .git
,这将创建一级子模块目录,然后在cd
中调用write_entry()
,从而在entry.c
中生成entry.c
子模块目录。第一个子git进程(超级项目子模块中的子进程)最终在
submodule_move_head()
处调用submodule.c
,后者在空运行模式下调用submodule.c
,在嵌套的子模块目录中产生git read-tree
。第二个子git进程尝试在
check_submodule_move_head()
处unpack_trees.c:2021
尚未存在的嵌套子模块目录中进行submodule_move_head
,并在执行前死亡。之所以在第一个孩子而不是在主进程中到达
git read-tree
的原因是,它在chdir()
构造内部,并且start_command()
返回有效的结构子模块指针,而在C主要git程序。
run-command.c
在主run-command.c
主进程中返回空指针的原因是,由于[hashmap [],对check_submodule_move_head()
中的if(submodule_from_ce())
的调用(从submodule_from_ce()
中的submodule_from_ce()
调用)返回了空指针。git
的cache_lookup_path()
中的C0]尚未填充。由于在此操作的此阶段,config_from()
和submodule_from_path()
中的submodule_from_ce()
中的"for_path"
和submodule_cache
都返回the_repository
,因此未填充该文件,因此超级项目的HEAD或其索引均不包含任何repo_get_oid(repo, GITMODULES_INDEX, &oid)
文件。[相反,在第一个子节点中,填充哈希图是因为
repo_get_oid(repo, GITMODULES_HEAD, &oid)
返回0,因为第一级子模块的HEAD,即config_from_gitmodules()
指向存在submodule-config.c
的提交,并将“嵌套”记录为子模块。通过在
submodule-config.c
分支的-1
中的.gitmodules
中调用repo_get_oid(repo, GITMODULES_HEAD, &oid)
之前检查子模块目录是否存在,即从无子模块的提交转到有子模块的提交来解决此错误。[即使在当前的bug中代码的
.git/modules/submodule/HEAD
分支都没有起作用,也可以用更安全的方式保护.gitmodules
中对check_submodule_move_head()
的另一个调用。
merged_entry()
中其他功能中对if(!old)
的其他调用已全部受到程序流中某处对check_submodule_move_head()
的调用的保护,因此我们不需要为其提供额外的保护。
merged_entry()
机制中的所有命令都会受到影响,即,当使用else if (!(old->ce_flags & CE_CONFLICTED))
标志调用时,检出,重置和读取树。此错误是
check_submodule_move_head()
。