编辑:
请参阅@Simba Answer 以获得有效解决方案
submodule.<name>.update 是您要更改的内容,请参阅docs - 默认 checkout
submodule.<name>.branch 指定要跟踪的远程分支 - 默认 master
旧答案:
我个人讨厌这里直接指向外部链接的答案,这些链接可能会随着时间的推移而停止工作,并检查我的答案here(除非问题是重复的) - 指向确实涵盖行间主题的问题其他主题,但总体等于:“我不回答,请阅读文档。”
回到这个问题:为什么会这样?
你描述的情况
从服务器拉取更改后,我的子模块头多次与主分支分离。
当一个人不经常使用 submodules 或刚开始使用 submodules 时,这是一种常见的情况。我相信我的说法是正确的,我们都在某个时候我们的 子模块 的 HEAD 被分离了。
- 原因:您的子模块未跟踪正确的分支(默认主模块)。
解决方案:确保您的子模块正在跟踪正确的分支
$ 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>
-
原因:您的父仓库未配置为跟踪子模块分支。
解决方案:通过使用以下两个命令添加新的子模块,使您的子模块跟踪其远程分支。
- 首先你告诉 git 跟踪你的远程
<branch>。
- 你告诉 git 执行 rebase 或 merge 而不是 checkout
- 你告诉 git 从远程更新你的子模块。
$ git submodule add -b <branch> <repository> [<submodule-path>]
$ git config -f .gitmodules submodule.<submodule-path>.update rebase
$ 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>
$ git config -f .gitmodules submodule.<submodule-path>.update <rebase|merge>
在常见情况下,您现在已经修复了 DETACHED HEAD,因为它与上述配置问题之一有关。
修复 .update = checkout 时的 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:
创建临时分支的推荐选项可能很好,然后您可以合并这些分支等。但是在这种情况下,我个人只会使用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 状态,但我希望你现在能更多地了解如何调试你的特殊情况。