克隆超级项目后如何保持git子模块的on-branch状态?

时间:2014-01-06 00:20:43

标签: git branch git-submodules

我正在测试新的git submodule add -b功能(在git 1.8.2之后),它会创建据称跟踪分支而不是提交的子模块。我正在使用git version 1.8.4.msysgit.0。子模块的分支跟踪功能似乎在原始超级项目中正常工作,但只要克隆超级项目就会失败。更具体一点:

我所做的是典型的,大致如下,

1. create a git repo (called common): ...
2. create a main project (called main), which uses common as a library/submodule.
 mkdir main && cd main
 git init
 git submodule add -b master url_to_common.git
 git commit -m "initial commit"
 cd common
 git status

正如所宣传的那样,添加的子模块跟踪子模块仓库的主分支。我得到了:

# On branch master
nothing to commit, working directory clean

此外,如果我git pullgit push,我会

Already up-to-date.
Everything up-to-date

,分别。

但是,如果我以任何方式克隆main项目,克隆项目中的common子模块将失去“On branch”状态。我在git pull文件夹中的git pushcommon不能像原型main项目那样。当然,我可以添加origin master来为克隆项目中的common拉动和推送工作,但这似乎打败了跟踪子模块(子模块添加-b)的目的。

我用来克隆和检查子模块的命令是:

cd main
git clone . ../main2 --recursive
cd ../main2/common
git status

我得到了:

# HEAD detached at 0259d75
nothing to commit, working directory clean

我也尝试了git clone . ../main3 --recurse-submodules,以及

git clone . ../main4.git --bare
git clone url_to_main4.git --recursive

同样的事情发生在main3main4上。

总而言之,我创建了一个超级项目,其子模块跟踪其主分支。一旦我尝试克隆它并在其他地方处理它,分支跟踪功能就会丢失。在我看来,保持分支跟踪子模块的唯一方法是压缩原始的main项目并将其复制。我是否在这种情况下遗漏了一些东西,或者是否正在以最好的方式复制原始项目?

我的问题是,如何在克隆超级项目后保持分支跟踪功能。我对使main4.git工作特别感兴趣,因为它涉及远程服务器上的裸克隆。

注意:在分支丢失后指定分支(例如Git submodules: Specify a branch/tag)不是我想要的,因为git submodule add -b中给出的信息仍然丢失,我们又回到原点。我们不妨删除子模块并重新添加。

3 个答案:

答案 0 :(得分:1)

对于遇到此问题的其他人:

正如答案所述,您的子模块会跟踪提交。这实际上不是问题,子模块表示单个时间点(即提交)的外部依赖,而不是活动的开发流(分支)。您可以根据自己的选择手动更新此依赖项(理论上,只在Master分支上)

在提交时,您只关心您的分支。在不在分支机构的情况下进行承诺会让人失去理智,并且您的团队很容易失去工作。

我在我们的工作室通过添加预提交钩子来解决这个问题,如果不在分支上则拒绝提交:

#!/bin/sh

function parse_git_branch_check {
    if [[ ${branch_name} == "* (detached from "* ]]; then
        echo "********************************************"
        echo "You need to be on a branch before committing"
        echo "********************************************"
        exit 1
    else
        echo "-- You are on branch $branch_name --"
        exit 0
    fi
}
function parse_git_branch {
  git branch --no-color 2> /dev/null | sed -e '/^[^*]/d'
}

branch_name=$(parse_git_branch)
parse_git_branch_check;

这个钩子致力于超级回购,以及这个BAT(是的,我知道,对不起)脚本来安装钩子

REM - Create links for all submodules to our pre-commit hooks for preventing submissions without a branch

if EXIST .git\hooks\pre-commit (
    del .git\hooks\pre-commit
)
mklink /h .git\hooks\pre-commit pre-commit

FOR /F "tokens=*" %%i IN ('DIR .git\modules /A:D /b') do (
    if EXIST .git\modules\%%i\hooks\pre-commit (
        del .git\modules\%%i\hooks\pre-commit
    )
    mklink /h .git\modules\%%i\hooks\pre-commit pre-commit
)

新克隆需要运行脚本,这不是完美的,但最接近我能想到的自动解决方案。

答案 1 :(得分:0)

通过特定的提交引用跟踪Git子模块。不通过分支机构。因此,即使您位于HEAD的{​​{1}},您的master项目也会跟踪main的特定提交。这就是为什么子模块在引用中非常静态的原因,这有时会引起混淆和问题:)

This blog相当好地描述了这个概念。

答案 2 :(得分:0)

git有不同的用例。但对于我的情况,以下适用于git 1.8.5.2(可能稍后)。基本上,首先完成子模块,然后再将其添加回来。当然,子模块是最新的和正常的。

cd main
git rm common
rm -rf .git/modules/common
git submodule add -b master url_to_common.git
cd common
git status

注意,第三行rm ...是必要的,因为git(从1.8.5.2开始)会在超级项目中留下.git/modules/common,这会阻止子模块被重新添加。