我在.gitmodules文件中有子模块的配置:
[submodule "sub"]
shallow = true
branch = master
path = sub
url = https://path/to/repo.git
现在我想要有人克隆我的仓库然后运行这些命令:
git submodule init
git submodule update
是获得子模块的浅层主分支。但是发生的事情是它没有签到master
分支。它总是会分离头,所以我需要手动运行git checkout master
。因此,用户只需运行一个命令,而不仅仅是这两个命令。
我调查了这个:Why is my GIT Submodule HEAD detached from master?
但任何关于已接受答案的建议似乎都没有帮助:我在.gitmodules
文件中添加了我想要的分支,我添加了远程上游作为master(这仅适用于已经克隆/更新的存储库后)不得不结账以掌握自己)。
如果有人克隆了我的存储库并且想要设置子模块,那么这是否总是会分离HEAD?
答案 0 :(得分:1)
是的,您是对的。用户mkungla从Why is my GIT Submodule HEAD detached from master?做出的最高答案是胡说八道。
在branch
中添加 .gitmodule
选项 与子模块的分离行为完全无关。
在git submodule --help
中,默认行为是从git submodule update --remote
断开。
首先,无需指定要跟踪的分支。 origin/master
是要跟踪的默认分支。
-远程
代替使用超级项目的记录的SHA-1更新子模块,而要使用子模块的远程跟踪分支的状态。使用的遥控器是分支机构的遥控器(
branch.<name>.remote
),默认为origin
。远程分支使用的默认值为master
。
那为什么在update
之后分离HEAD?因为submodule.$name.update
的默认行为是checkout
。
-结帐
在子模块中的分离的HEAD 上签出超级项目中记录的提交。这是默认行为,此选项的主要用途是在设置为
submodule.$name.update
以外的值时覆盖checkout
。
如果您希望子模块自动与远程分支合并,请使用--merge
或--rebase
。
-合并
此选项仅对更新命令有效。将超级项目中记录的提交合并到子模块的当前分支中。如果指定了此选项,则子模块的HEAD将不分离。
-重新设置
将当前分支重新基于超级项目中记录的提交。如果指定了此选项,则子模块的HEAD将不分离。
您需要做的就是
git submodule update --remote --merge
# or
git submodule update --remote --rebase
通过将--merge
设置为--rebase
或git submodule update
,还可以选择将submodule.$name.update
或merge
设置为rebase
的默认行为
这是一个有关如何在.gitmodule
中配置子模块更新的默认更新行为的示例。
[submodule "bash/plugins/dircolors-solarized"]
path = bash/plugins/dircolors-solarized
url = https://github.com/seebi/dircolors-solarized.git
update = merge # <-- this is what you need to add
我的全部答案都基于手册。 git submodule --help
。
答案 1 :(得分:0)
我还在调查这个问题,但这是我提出并正在使用的脚本:
#! /bin/bash
# Written by Carlo Wood 2016
echo "In \"$(pwd)\", entering $0 $*"
# This script should be run from the root of the parent project.
if ! test -e .git; then
echo "$0: $(pwd) is not a git repository."
exit 1
fi
# Parse command line parameters.
opt_init=
opt_recursive=
do_foreach=0
initial_call=1
while [[ $# -gt 0 ]]
do
case $1 in
--init)
opt_init=$1
;;
--recursive)
opt_recursive=$1
do_foreach=1
;;
--reentry)
initial_call=0
;;
--)
break;
;;
-*)
echo "Unknown option $1"
exit 1
;;
*)
break
;;
esac
shift
done
# Determine the full path to this script.
if [[ ${0:0:1} = / ]]; then
FULL_PATH="$0"
else
FULL_PATH="$(realpath $0)"
fi
if test "$initial_call" -eq 1; then
do_foreach=1
else
# Script is called from git submodule foreach ...'
name="$1"
path="$2"
sha1="$3"
toplevel="$4"
# Make sure we are in the right directory.
cd "$toplevel/$path" || exit 1
# Does the parent project want us to checkout a branch for this module?
SUBMODULE_BRANCH=$(git config -f "$toplevel/.gitmodules" submodule.$name.branch)
if test -n "$SUBMODULE_BRANCH"; then
echo "Calling 'git checkout $SUBMODULE_BRANCH' in $(pwd)"
git checkout $SUBMODULE_BRANCH || exit 1
echo "Calling 'git pull' in $(pwd)"
git pull || exit 1
if test $(git rev-parse HEAD) != "$sha1"; then
# Update the parent project to point to the head of this branch.
pushd "$toplevel" >/dev/null
SN1=$(git stash list | grep '^stash' | wc --lines)
git stash save --quiet Automatic stash of parent project by update_submodules.sh
SN2=$(git stash list | grep '^stash' | wc --lines)
git add $name
git commit -m "Update of submodule $name to current $SUBMODULE_BRANCH"
if test $SN1 -ne $SN2; then
git stash pop --quiet
fi
popd >/dev/null
fi
elif test $(git rev-parse HEAD) != "$sha1"; then
# No submodule.$name.branch for this submodule. Just checkout the detached HEAD.
git checkout $sha1
fi
fi
echo "do_foreach=$do_foreach; opt_init=$opt_init; opt_recursive=$opt_recursive; name=$name; path=$path; sha1=$sha1; toplevel=$toplevel; pwd=$(pwd)"
if test $do_foreach -eq 1; then
if test -n "$opt_init"; then
echo "Calling 'git submodule init'"
git submodule init
fi
# Make sure the submodules even exist.
echo "Calling 'git submodule update'"
git submodule update
# Call this script recursively for all submodules.
echo 'Calling '"'"'git submodule foreach '"$FULL_PATH --reentery $opt_init $opt_recursive"' $name $path $sha1 $toplevel'"'"
git submodule foreach "$FULL_PATH --reentry $opt_init $opt_recursive"' $name $path $sha1 $toplevel'
fi
调用此脚本将与'git submodule update'和
甚至支持--init和--recursive。但是,您可以通过设置'branch'值来配置子模块以结帐并拉取分支;例如:git config -f .gitmodules submodule.NAME.branch master
将导致子模块NAME检出并拉出分支主控,而不是当前的SHA1。然后它还会更新父项目以指向该分支的HEAD。