为什么我的GIT子模块HEAD与主控制器分离?

我正在使用GIT子模块。 从服务器拉动更改后,多次我的子模块头从主分支分离。

为什么会发生?

我必须经常这样做:

git branch git checkout master 

我怎样才能确保我的子模块总是指向主分支?

Muchas Gracias

就我个人而言,我讨厌这里的答案,它指向可能停止工作的外部链接,并在这里检查我的答案(除非问题是重复的) – 指导问题涵盖其他科目之间的主题,但总体上等于:“我不回答,请阅读文件。“

所以回到这个问题:为什么会发生?

你描述的情况

从服务器拉动更改后,多次我的子模块头从主分支分离。

当不经常使用子模块或刚开始使用子模块时,这是常见的情况。 我相信我是正确的,说我们都在那里,在我们的子模块的HEAD被分离的地方。

  • 原因:您的子模块没有跟踪任何或正确的分支。 解决scheme:确保您的子模块正在跟踪正确的分支
 $ cd <submodule-path> # if the master branch already exists locally: # (From git docs - branch) # -u <upstream> # --set-upstream-to=<upstream> # Set up <branchname>'s tracking information so <upstream> # is considered <branchname>'s upstream branch. # If no <branchname> is specified, then it defaults to the current branch. $ git branch -u <origin>/<branch> <branch> # else: $ git checkout -b <branch> --track <origin>/<branch> 
  • 原因:您的父回购没有configuration为跟踪子模块分支。 解决scheme:通过添加具有以下两个命令的新子模块,使您的子模块跟踪其远程分支。
    • 首先告诉git跟踪你的远程<branch>
    • 其次,你告诉git从远程更新你的子模块。
  $ git submodule add -b <branch> <repository> [<submodule-path>] $ git submodule update --remote 
  • 如果您尚未像这样添加现有子模块,则可以轻松修复:
    • 首先,您要确保您的子模块已检出您要跟踪的分支。
  $ cd <submodule-path> $ git checkout <branch> $ cd <parent-repo-path> # <submodule-path> is here path releative to parent repo root # without starting path separator $ git config -f .gitmodules submodule.<submodule-path>.branch <branch> 

但是,即使你已经configuration你的子模块来跟踪正确的分支,你仍然可以发现你的子模块HEAD detached at <commit-hash>

在常见情况下,您现在已经修复了DETACHED HEAD,因为它与上面的configuration问题之一有关。 但请记住,您的父库现在不再pipe理​​您的子模块的状态(使用提交给父库的提交哈希),因为您的子模块正在跟踪其自己的远程分支,这就为失败开辟了新的可能性。

在你的父母和子模块的path中运行$ git status来validation所有东西都被正确的跟踪,并且所有东西都是最新的,然后运行$ cd <parent-repo>git submodule update --remote 。 正如你所看到的,如果你再次运行git status,现在一切都很好。

为了演示一切正确的configuration,你不希望得到DETACHED HEAD的东西可能会出错,让我们来看看以下几点:

 $ cd <submodule-path> # and make modification to your submodule $ git add . $ git commit -m"Your modification" # Let's say you forgot to push it to remote. $ cd <parent-repo-path> $ git status # you will get Your branch is up-to-date with '<origin>/<branch>'. Changes not staged for commit: modified: path/to/submodule (new commits) # As normally you would commit new commit hash to your parent repo $ git add -A $ git commit -m"Updated submodule" $ git push <origin> <branch>. $ git status Your branch is up-to-date with '<origin>/<branch>'. nothing to commit, working directory clean # If you now update your submodule $ git submodule update --remote Submodule path 'path/to/submodule': checked out 'commit-hash' $ git status # will show again that (submodule has new commits) $ cd <submodule-path> $ git status HEAD detached at <hash> # as you see you are DETACHED and you are lucky if you found out now # since at this point you just asked git to update your submodule # from remote master which is 1 commit behind your local branch # since you did not push you submodule chage commit to remote. # Here you can fix it simply by. (in submodules path) $ git checkout <branch> $ git push <origin>/<branch> # which will fix the states for both submodule and parent since # you told already parent repo which is the submodules commit hash # to track so you don't see it anymore as untracked. 

但是,如果你已经在本地为子模块做了一些改变,并提交到远程,那么当你执行'git checkout'时,Git会通知你:

 $ git checkout <branch> Warning: you are leaving 1 commit behind, not connected to any of your branches: If you want to keep it by creating a new branch, this may be a good time to do so with: 

build议创build一个临时分支的选项可以很好,然后你可以合并这些分支等等。但是我个人会在这种情况下使用git cherry-pick <hash>

 $ git cherry-pick <hash> # hash which git showed you related to DETACHED HEAD # if you get 'error: could not apply...' run mergetool and fix conflicts $ git mergetool $ git status # since your modifications are staged just remove untracked junk files $ rm -rf <untracked junk file(s)> $ git commit # without arguments # which should open for you commit message from DETACHED HEAD # just save it or modify the message. $ git push <origin> <branch> $ cd <parent-repo-path> $ git add -A # or just the unstaged submodule $ git commit -m"Updated <submodule>" $ git push <origin> <branch> 

虽然还有更多的情况可以让你的子模块进入DETACHED HEAD状态,但是我希望你现在能更多地了解如何debugging你的特定情况。

看看我的答案在这里: Git submodules:指定一个分支/标签

如果你愿意,你可以手动将“branch = master”行添加到你的.gitmodule文件中。 阅读链接,看看我的意思。

编辑:跟踪在一个分支现有的子模块项目按照VonC的说明在这里,而不是:

Git子模块:指定分支/标记

让子模块检出分支的另一种方法是转到根文件夹中的.gitmodules文件,并在模块configuration中添加字段branch ,如下所示:

branch = <branch-name-you-want-module-to-checkout>