Git子模块:指定一个分支/标签
  git submodule add -b如何git submodule add -b工作? 
  在添加具有特定分支的子模块之后,新的克隆回购(在git submodule update --init )将处于特定的提交,而不是分支本身(子模块上的git status显示“当前不在任何分支上”)。 
  我找不到有关子模块的分支或任何特定提交的.gitmodules或.git/config任何信息,那么git如何解决它? 
另外,是否可以指定标签而不是分支?
  PS:我正在使用1.6.5.2 。 
注意:Git 1.8.2增加了跟踪分支的可能性。 请参阅下面的一些答案。
习惯这一点有点令人困惑,但子模块不在分支上。 就像你说的那样,它们只是一个指向子模块存储库特定提交的指针。
这意味着,当其他人检出你的仓库,或者拉你的代码,并且执行git子模块更新时,子模块会被签出到特定的提交中。
对于不经常更改的子模块来说,这非常棒,因为项目中的每个人都可以在相同的提交下拥有子模块。
如果您想将子模块移动到特定的标签:
cd submodule_directory
git checkout v1.0
cd ..
git add submodule_directory
git commit -m "moved submodule to v1.0"
git push
然后,另一个想要将submodule_directory更改为该标记的开发人员,请执行此操作
git pull
git submodule update
  提交其子模块目录指向的git pull更改。  git submodule update实际上在新代码中合并。 
我想在这里添加一个答案,这个答案实际上只是其他答案的集合,但我认为它可能会更完整。
当你有这两件事情时,你知道你有一个git子模块。
  1)你的.gitmodules有这样一个条目: 
[submodule "SubmoduleTestRepo"]
    path = SubmoduleTestRepo
    url = https://github.com/jzaccone/SubmoduleTestRepo.git
  2)你的git仓库中有一个子模块对象(在本例中名为SubmoduleTestRepo)。  Github将这些显示为“子模块”对象。  或者从命令行执行git submodule status 。  Git子模块对象是特殊类型的git对象,它们为特定的提交保存SHA信息。 
  每当你做一个git submodule update ,它都会用你提交的内容填充你的子模块。  它知道在哪里可以找到提交,因为.gitmodules中的信息。 
  现在,所有-b都会在.gitmodules文件中添加一行。  所以遵循相同的例子,它看起来像这样: 
[submodule "SubmoduleTestRepo"]
    path = SubmoduleTestRepo
    url = https://github.com/jzaccone/SubmoduleTestRepo.git
    branch = master
编辑:上面只支持分支名称,而不支持SHA或TAG。
  子模块对象仍然指向特定的提交。  根据Vogella的回答, -b选项购买的唯一东西是能够为更新添加--remote标志: 
git submodule update --remote
不是将子模块的内容填充到子模块指向的提交中,而是使用主分支上的最新提交来替换该提交,然后用该提交填充子模块。 这可以通过djacobs7回答在两个步骤中完成。 由于您现在已经更新了子模块对象指向的提交,所以您必须将已更改的子模块对象提交到您的git存储库中。
  git submodule add -b并不是一种神奇的方式来保持一切与分支最新。  它只是在.gitmodules文件中添加关于分支的信息,并为您提供在填充指定分支之前将子模块对象更新为指定分支的最新提交的选项。 
请注意, 如果您有一个现有子模块尚未跟踪分支 ,那么(如果您有git 1.8.2+):
确保父代码库知道它的子模块现在跟踪一个分支:
cd /path/to/your/parent/repo
git config -f .gitmodules submodule.<path>.branch <branch>
确保你的子模块实际上是最新的那个分支:
cd path/to/your/submodule
git checkout -b branch --track origin/branch
  # if the master branch already exist:
  git branch -u origin/master master
  ('origin'是从子模块克隆而来的上游远程回购的名称。 
  该子模块内的git remote -v将显示它。  通常,它是'起源') 
不要忘记将您的子模块的新状态记录在您的父回购中:
cd /path/to/your/parent/repo
git add path/to/your/submodule
git commit -m "Make submodule tracking a branch"
  该子模块的后续更新将不得不使用--remote选项: 
# update your submodule
# --remote will also fetch and ensure that
# the latest commit from the branch is used
git submodule update --remote
# to avoid fetching use
git submodule update --remote --no-fetch 
  请注意,使用Git 2.10+(2016年第3季度),您可以使用' .  '作为分支名称: 
  分支的名称记录为submodule.<name>.branch以.gitmodules进行update --remote 。 
  一个特殊的价值.  用于指示子模块中分支的名称应与当前存储库中当前分支的名称相同 。 
如果你想更新分支之后的所有子模块:
    git submodule update --recursive --remote
  请注意,对于每个更新的子模块,结果将始终是分离的HEAD ,正如Dan Cameron在其答案中所指出的那样。 
  为了确保分支实际被检出(并且不会修改代表父回购子模块的特殊条目的SHA1),他建议: 
git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; git checkout $branch'
  每个子模块仍然会引用相同的SHA1,但是如果您确实进行了新的提交,您将能够推送它们,因为它们将被您希望子模块跟踪的分支引用。 
  在子模块内部进行推送之后,不要忘记返回父代码库,为这些修改的子模块添加,提交并推送新的SHA1。 
  注意在Alexander Pogrebnyak的评论中推荐使用$toplevel 。 
  $toplevel是在2010年5月的git1.7.2中引入的:提交f030c96。 
  它包含顶级目录(其中.gitmodules是)的绝对路径。 
  dtmland在评论中补充道: 
  foreach脚本将无法检出不在分支之后的子模块。 
  但是,这个命令给你两个: 
 git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; [ "$branch" = "" ] && git checkout master || git checkout $branch' –
相同的命令,但更容易阅读:
git submodule foreach -q --recursive 
    'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; 
     [ "$branch" = "" ] && 
     git checkout master || git checkout $branch' –
umläute用评论中的简化版本改进了dtmland的命令:
git submodule foreach -q --recursive 'git checkout $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'
多行:
git submodule foreach -q --recursive 
  'git checkout 
  $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'
上一篇: Git submodules: Specify a branch/tag
下一篇: Detach (move) subdirectory into separate Git repository
