1

我在 .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. 因此,用户不仅需要运行这两个命令,还需要运行一个额外的命令。

我调查了这个:为什么我的 GIT 子模块 HEAD 与主模块分离?

但是任何关于已接受答案的建议似乎都无济于事:我在.gitmodules文件中添加了我想要的分支,我添加了远程上游作为主控(这仅适用于在我必须结帐以掌握自己之后已经克隆/更新的存储库)。

那么,如果有人克隆我的存储库并想要设置子模块,这是否旨在始终分离 HEAD?

4

2 回答 2

2

你是对的。用户 mkungla 从为什么我的 GIT 子模块 HEAD 与主模块分离?是胡说八道。

添加一个branch选项.gitmodule根本子模块的分离行为无关。

git submodule --helpHEAD 分离是 的默认git submodule update --remote行为。

首先,不需要指定要跟踪的分支origin/master是要跟踪的默认分支。

- 偏僻的

不要使用超级项目记录的 SHA-1 来更新子模块,而是使用子模块的远程跟踪分支的状态。使用的遥控器是分支的遥控器 ( branch.<name>.remote),默认为origin. 使用的远程分支默认为master.

为什么

那么为什么 HEAD 之后分离update呢?因为默认行为submodule.$name.updatecheckout.

- 查看

签出子模块中分离的 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 updatesubmodule.$name.updatemergerebase

这是一个关于如何在.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.

于 2019-07-20T04:39:09.350 回答
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。但是,您可以通过设置“分支”值来配置子模块以结帐并拉出分支;例如:git config -f .gitmodules submodule.NAME.branch master将导致子模块 NAME 签出并拉出分支 master 而不是当前的 SHA1。然后它还将更新父项目以指向该分支的 HEAD。

于 2016-12-29T16:37:41.550 回答