Git子模块循环检出超级模块分支。

3
考虑一个名为Foo/的git仓库,它有子模块bar1/和bar2/。
每个子模块都有相同的分支:1和2。
我进入了超级模块,并想要从bar1和bar2的源更新超级模块中最新的提交。我已经完成了超级模块的init和update操作,因此bar1和bar2中有工作树,但它们处于分离状态。我可以执行以下操作:
cd foo;
git checkout 1
git submodule foreach git checkout 1
git pull

现在,令我困扰的是重复分支标识符。我能否执行类似“git submodule foreach git checkout $CURRENT_BRANCH_ID”的操作?有更好的替代方案吗?
2个回答

5

子模块默认始终处于 分离头指针模式

您可以使每个子模块跟随一个分支。
请参见 "如何使现有的子模块跟踪分支"。

cd /path/to/your/parent/repo/Foo
git config -f .gitmodules submodule.bar1.branch branch1
git config -f .gitmodules submodule.bar2.branch branch2

然后你需要做的就是:
git submodule update --remote

这将更新每个子模块到其各自上游分支的最新版本(执行fetch+checkout操作)。


从哪个版本的git开始支持这个功能?在1.8.4版中它似乎不起作用--或者我做错了什么。 - Spacemoose
这将具有HEAD -> 远程/分支1指向的引用。如果您想要HEAD -> 本地跟踪分支branch1 -> 远程/分支1指向的引用,那么您将不得不执行其他操作。我想不到除了bash脚本之外的其他方法。 - Ari Sweedler
1
@AriSweedler 我同意。这让我想起了新的 Git 2.36 (2022年4月) git branch --recurse-submodules - VonC

0

代码

这是我在评论中提到的脚本:

function checkout_branch_not_refs() {
  for line in $(git config --list | awk -F'[.=]' '/submodule.*branch/ {print $2","$4}'); do
    IFS=',' read -r submodule branch <<< "$line"
    if ! [ -d "$submodule" ]; then
      echo "Cannot switch branch to '$branch' for submodule '$submodule'"
      continue
    fi
    pushd "$submodule" && git switch "$branch" && popd
  done
}

用法如下

checkout_branch_not_refs
git submodule foreach git pull

差异的解释

原始答案

git submodule update --remote

它完全按照您的要求执行。它通过查看远程配置在.gitmodules中的子模块来更新子模块。 update --remote命令查找submodule.<submodule_name>.branch键并直接检出该提交。

ASCII艺术:

HEAD ------------\
                  \
                   V
remote branch --> Commit

我的答案

checkout_branch_not_refs

该命令将检出分支本身。 HEAD -> Branch -> commit

ASCII 艺术:

HEAD --> local branch --> Commit

理解本地分支和远程分支的区别是理解本答案的前提条件。这就是为什么我们在子模块中运行git pull的答案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接