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 этой ветви.

Другие вопросы по тегам