Git - подмодули HEAD всегда отключаются после запуска обновления?
У меня есть эта конфигурация для подмодуля в файле.gitmodules:
[submodule "sub"]
shallow = true
branch = master
path = sub
url = https://path/to/repo.git
Теперь я хочу, чтобы кто-то клонировал мой репозиторий и затем выполнил следующие команды:
git submodule init
git submodule update
Это получить мелкую ветку master подмодуля. Но что происходит, это не оформить заказ master
ветка. Он всегда попадет в отсоединенную головку, поэтому мне нужно вручную запустить git checkout master
, Поэтому вместо этих двух команд пользователю необходимо выполнить еще одну команду.
Я посмотрел на это: почему мой GIT Submodule HEAD отделен от мастера?
Но любой совет, который был о принятых ответах, похоже, не помогает: я добавил ветку, которую хочу в .gitmodules
файл, я добавил удаленный апстрим, чтобы быть мастером (это работает только для уже клонированного / обновленного репозитория после того, как я должен был оформить заказ, чтобы освоить себя).
Так это всегда предназначено для отключения HEAD, если кто-то клонирует мой репозиторий и хочет настроить субмодуль?
1 ответ
Да, ты прав. Самый популярный ответ, сделанный пользователем mkungla из статьи: Почему моя голова подмодуля GIT отсоединена от мастера? ерунда.
Добавление branch
вариант в.gitmodule
вообще НЕ связан с независимым поведением подмодулей.
От git submodule --help
, HEAD detached - поведение по умолчаниюgit submodule update --remote
.
Во-первых, нет необходимости указывать ветку для отслеживания.origin/master
отслеживаемая ветвь по умолчанию.
--удаленный
Вместо использования записанного SHA-1 суперпроекта для обновления подмодуля используйте статус ветви удаленного отслеживания подмодуля. Используемый пульт - это пульт филиала (
branch.<name>.remote
), по умолчаниюorigin
. Удаленная ветка по умолчанию использовалаmaster
.
Почему
Итак, почему HEAD отсоединяется после update
? Поскольку поведение по умолчаниюsubmodule.$name.update
является checkout
.
--проверять, выписываться
Извлеките фиксацию, записанную в суперпроекте, на отсоединенной HEAD в подмодуле. Это поведение по умолчанию, основное использование этой опции - переопределить
submodule.$name.update
когда установлено значение, отличное отcheckout
.
Как
Если вы хотите, чтобы подмодуль автоматически объединялся с удаленной веткой, используйте --merge
или --rebase
.
- объединить
Эта опция действительна только для команды обновления. Объединить фиксацию, записанную в суперпроекте, в текущую ветвь подмодуля. Если задана эта опция, HEAD подмодуля не отключается.
--rebase
Переустановите текущую ветвь на фиксацию, записанную в суперпроекте. Если задана эта опция, 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
.
Я все еще исследую это, но вот сценарий, который я придумал и сейчас использую:
#! /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", и даже поддерживает --init и --recursive. Однако вы можете настроить подмодули для извлечения и извлечения ветви, установив значение "ветви"; например: git config -f .gitmodules submodule.NAME.branch master
приведет к проверке субмодуля NAME и извлечению мастера ветвления вместо текущего SHA1. Затем он также обновит родительский проект, указав на HEAD этой ветви.