为什么 git Submodule 显示错误的分支

问题描述 投票:0回答:2

我们有一个超级项目和一个包含在其中的子模块。两者都有相同的分支

master, staging, featureBranch

我希望

master
上的超级项目跟踪
master
上的子模块,
staging
上的超级项目跟踪
staging
上的子模块。

对于超级项目中的 master

.gitmodules
看起来像这样:

[submodule "submodule"]
        path = submodule
        url = http://fpr-dev/submodule.git
        branch = master

和分期

[submodule "submodule"]
        path = submodule
        url = http://fpr-dev/submodule.git
        branch = staging

现在当我在 master 上做一个

git submodule
我看到以下输出:

$ git submodule
+e3782f37b1ae23aa0d5537ef3061dfdfec70f77f submodule (heads/Staging)

请注意它说的是分期。但是当我在子模块中执行 git status 时,我看到:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean

为什么会这样,我该如何解决?

现在,当我切换到

staging
并尝试拉 (
git.exe pull -v --progress  "origin"
) 子模块时,我收到以下错误:

You asked to pull from the remote 'origin', but did not specify
a branch. Because this is not the default configured remote
for your current branch, you must specify a branch on the command line.

我只想做:

  • 超级项目和子模块应该有相同的分支(Staging,feature,...)。
  • 当将超级项目切换到不同的分支时,我希望子模块跟随超级项目分支(即也切换到那个分支)我不在乎这是自动完成的还是我必须运行 1000 行脚本
  • 在子模块中进行推或拉时,它应该可以正常工作(即推/拉正确的分支)

实现这种行为的最简单方法是什么?

git version-control git-submodules
2个回答
0
投票

当您运行

git submodule
时,它会为您的子模块显示正确的提交 SHA,因为这是您在超级项目中设置的。该命令不会告诉您当前本地子模块代码引用的提交 SHA;它告诉你想要超级项目想要参考。

不幸的是,你必须采取额外的步骤来告诉你的超级项目在本地拉下那个特定的子模块代码。这是通过运行这些命令来完成的:

git submodule init

git submodule update

在此之后,您应该在本地的子模块中看到正确的代码。您唯一可以绕过这些额外命令的时间是您第一次克隆存储库时。你可以这样称呼:

git clone <repo_name> --recursive

并且所有子模块都将在正确的提交 SHA 处检出。但是,一旦签出新分支,就必须再次运行

init
update
命令。

要自动执行此行为,您可以创建一个脚本来运行,而不是直接使用

git checkout
命令。该脚本可以接受一个分支名称,看起来像这样:

git checkout <branch_name>

git submodule init

git submodule update


0
投票

我不确定你是否成功过,但我们使用了一个涉及 Git 钩子的解决方案,特别是结帐后钩子。这样一来,当您在超级项目中切换分支时,它将尝试检出子模块中的同名分支;如果子模块中不存在该分支,它将尝试签出“开发”(在您的情况下,您可能需要不同的分支名称,如“暂存”)。 注意:无论检出哪个分支,超级项目仍将确保子模块在分支检出后位于正确的提交 $SHA 上。

例如如果超级项目在

staging
上时期望子模块 A 在 commit_hash=848f7b,那么无论子模块 A 是否正在跟踪分支,都会发生这种情况。

在你的超级项目的 .git/hooks 文件夹中,添加一个名为

post-checkout
的文件并将以下代码放入其中。

#!/bin/bash

# NOTE: This hook runs before the --recursive part of
# the checkout.  This means that the submodules have not
# yet been updated to their required commit.

PREV_COMMIT=$1;
POST_COMMIT=$2;
CURRENT_DIRECTORY=$(pwd);

# If we update the parent repo to a named branch that
# should also exist in the child repos, checkout that
# branch in the child repos
# [parent checks out Develop, children should also check
# out develop... not just move HEAD ref]
#
if git branch | grep -Eqx '^\* [^ ]*$'; #if we just checked out a named branch(not a HEAD checkout)
then
    BRANCH_NAME=$(git branch | sed -E 's/^\* ([^ ]*)$/\1/;t;d');
    # if the branch exists in a submodule, check out that branch.
    #If the branch doesn't exist, but the hash of the commit to
    # checkout is the same as develop, then checkout develop instead of the hash

    git submodule foreach "
    develop_sha=\$(git rev-parse develop);
    if git branch | grep -Eq '$BRANCH_NAME'; then
        git checkout '$BRANCH_NAME';
    elif [ \"\$sha1\" = \"\$develop_sha\" ]; then
        git checkout develop;
    fi || :";
fi
© www.soinside.com 2019 - 2024. All rights reserved.