Why is my GIT HEAD SUBODULLE disconnected from the master?

I am using GIT submodules. After receiving the changes from the server, my submodule head was disconnected many times from the main branch.

Why is this happening?

I should always do:

git branch git checkout master 

How can I make sure my submodule always points to the main branch?

+128
git git-submodules
Sep 12 '13 at 17:18
source share
7 answers

EDIT:

See @Simba's Answer for a Correct Solution

.

submodule.<name>.update is what you want to change, see the docs - default checkout
submodule.<name>.branch specify remote branch to be tracked - default master




OLD RESPONSE:

Personally, I hate answers here that are aimed at external links that may stop working with time, and check my answer here (if the question does not repeat itself) - moving to a question that covers the topic between the lines of another topic, but in general it’s equal to: "I I don’t answer, read the documentation. "

So, back to the question: why is this happening?

Situation you described

After receiving the changes from the server, my submodule head was disconnected many times from the main branch.

This is a common case when someone does not use submodules too often or just started with submodules. I believe that I correctly state that we were all there at some point when our HEAD submodule disconnected.

  • Cause. Your submodule does not track the correct branch (default wizard).
    Solution: make sure your submodule is tracking the correct branch
 $ cd <submodule-path> # if the master branch already exists locally: # (From git docs - branch) # -u <upstream> # --set-upstream-to=<upstream> # Set up <branchname> tracking information so <upstream> # is considered <branchname> 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> 
  • Cause. Your parent repository is not configured to track the submodule branch.
    Decision. Make your submodule track its remote branch by adding new submodules using the following two commands.
    • First you tell git to track your <branch> remote.
    • you tell git to rebase or merge instead of fetching
    • you tell git to update your submodule from the remote.
  $ git submodule add -b <branch> <repository> [<submodule-path>] $ git config -f .gitmodules submodule.<submodule-path>.update rebase $ git submodule update --remote 
  • If you haven't added your submodule like this yet, you can easily fix this:
    • First, you want to make sure that the branch you want to track is marked in your submodule.
  $ 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> 

In normal cases, you have already fixed your DETACHED HEAD, as it was due to one of the configuration problems above.

fix DETACHED HEAD when .update = checkout

 $ cd <submodule-path> # and make modification to your submodule $ git add . $ git commit -m"Your modification" # Let 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. 

But if you manage to make some changes locally for the submodule and the committed changes, send them to the remote computer, and then when you have done the “git checkout”, Git will notify you:

 $ 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: 

It is recommended that you create a temporary branch, and then you can simply merge these branches, etc. However, in this case, I personally would use only 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> 

Although there are a few more cases where you can put your submodules in the DETACHED HEAD state, I hope that now you understand a little more how to debug your specific case.

+170
Apr 02 '16 at 15:38
source share

I'm tired of the fact that it always shuts down, so I just use a shell script to create it for all my modules. I assume all submodules are on master: here is the script:

 #!/bin/bash echo "Good Day Friend, building all submodules while checking out from MASTER branch." git submodule update git submodule foreach git checkout master git submodule foreach git pull origin master 

execute it from the parent module

+30
Apr 24 '18 at 8:42
source share

Adding the branch parameter to .gitmodule NOT related to the detached behavior of the submodules. The old answer from @mkungla is incorrect or out of date.

From git submodule --help HEAD detaches - this is the default behavior from git submodule update --remote .

First, you do not need to specify a trackable branch . origin/master is the default tracked branch.

--remote

Instead of using the superproject written to SHA-1 to update the submodule, use the status of the remote submodule tracking branch. The remote branch ( branch.<name>.remote ) is used, default origin . The remote branch used master by default .

Why

So why does HEAD disconnect after update ? This is caused by the default module update behavior: checkout .

--checkout

Extract the commit recorded in the superproject on a separate HEAD in the submodule. This is the default behavior , the main use of this parameter is to override submodule.$name.update when a value other than checkout .

To explain this strange update behavior, we need to understand how submodules work?

Quote from the Submodules section of Pro Git

Although sbmodule DbConnector is a subdirectory in your working directory, Git sees it as a submodule and does not track its contents when you are not in that directory. Instead, Git sees this as a special commit from this repository .

The main repository monitors the submodule with its state at a certain point , with a commit identifier. Therefore, when you update modules, you update the commit identifier to a new one.

how

If you want the submodule to automatically merge with the remote branch, use --merge or --rebase .

--merge

This parameter is valid only for update command . Combine the commit recorded in the superproject with the current submodule branch. If this parameter is specified, the HEAD submodule will not be disconnected .

--rebase

Relocate the current branch to the commit recorded in the superproject. If this parameter is specified, the HEAD submodule will not be disconnected .

All you have to do is

 git submodule update --remote --merge # or git submodule update --remote --rebase 

Recommended nickname:

 git config alias.supdate 'submodule update --remote --merge' # do submodule update with git supdate 

It is also possible to make --merge or --rebase default behavior for git submodule update by setting submodule.$name.update to merge or rebase .

Here is an example of how to configure the default submodule update behavior in .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 

Or configure it on the command line,

 # replace $name with a real submodule name git config -f .gitmodules submodule.$name.update merge 

References

+24
Apr 08 '19 at 10:10
source share

Check my answer here: Git submodules: Specify a branch / tag

If you want, you can add the line "branch = master" to your .gitmodules file manually. Read the link to understand what I mean.

EDIT: To track an existing submodule project in the branch, follow the VonC instructions here:

Git submodules: specify branch / tag

+10
Sep 14 '13 at 2:37
source share

Another way to make your submodule check the branch is to go to the .gitmodules file in the root folder and add the branch field to the module configuration as follows:

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

+8
May 9 '17 at 14:30
source share

Do this, then cd sudmodule&git co thebranche & cd.. , then git submodule update --remote and it works!

0
Apr 04 '19 at 13:20
source share

As other people have already said, the reason this happens is because the parent repo only contains a link to the (SHA1 of) specific commit in the submodule - it does not know anything about branches. Here's how it should work: the branch that was in this commit could go forward (or backward), and if the parent repo was referring to the branch, then this could easily break when that happens.

However, especially if you are actively developing both in the parent repo and in the submodule, the detached HEAD state can be confusing and potentially dangerous. If you make commits in a submodule while it is in the detached HEAD state, they become hanging, and you can easily lose your job. (Dangling commits can usually be saved using git reflog , but they are best avoided first.)

If you are like me, then most of the time , if there is a branch in the submodule that points to the commit being extracted, you would rather check this branch than to be in the disabled state of HEAD with the same commit. You can do this by adding the following alias to your gitconfig file:

 [alias] submodule-checkout-branch = "!f() { git submodule -q foreach 'branch=$(git branch --no-column --format=\"%(refname:short)\" --points-at 'git rev-parse HEAD' | grep -v \"HEAD detached\" | head -1); if [[ ! -z $branch && -z 'git symbolic-ref --short -q HEAD' ]]; then git checkout -q \"$branch\"; fi'; }; f" 

Now, after executing the git submodule update , you just need to call git submodule-checkout-branch , and any submodule retrieved by the commit pointed to by the branch will check this branch. If you do not often have multiple local branches pointing to the same commit, then this will usually do what you want; if not, then at least it guarantees that any commits you make will go to the real branch, and not remain hanging.

Alternatively, if you configured git to automatically update submodules when git config --global submodule.recurse true order (using git config --global submodule.recurse true , see this answer ), you can create a trap after validation that automatically calls this alias:

 $ cat .git/hooks/post-checkout #!/bin/sh git submodule-checkout-branch 

Then you do not need to call either git submodule update or git submodule-checkout-branch , just doing git checkout update all submodules to their respective commits and check the corresponding branches (if they exist).

0
Aug 28 '19 at 0:31
source share



All Articles