Search code examples
gitgit-submodulesgit-detached-head

Git - submodules HEAD is always detached after running update?


I have this configuration for submodule in .gitmodules file:

[submodule "sub"]
    shallow = true
    branch = master
    path = sub
    url = https://path/to/repo.git

Now I want when someone clones my repo and then runs these commands:

git submodule init
git submodule update

Is to get shallow master branch of submodule. But what happens is it does not checkout to master branch. It will always get to detached head, so then I need to manually run git checkout master. So instead of just those two commands, user needs to run one additional.

I looked into this: Why is my GIT Submodule HEAD detached from master?

But any advice that was on accepted answers, does not seem to help: I added branch I want in .gitmodules file, I added remote upstream to be master (this only works for already cloned/updated repository after I had to checkout to master myself).

So is this intended to always get detached HEAD if someone clones my repository and wants to set up submodule?


Solution

  • Yes, you're right. The top answer maded by user mkungla from Why is my GIT Submodule HEAD detached from master? is nonsense.

    Adding a branch option in .gitmodule is NOT related to the detached behavior of submodules at all.

    From git submodule --help, HEAD detached is the default behavior of git submodule update --remote.

    First, there's no need to specify a branch to be tracked. origin/master is the default branch to be tracked.

    --remote

    Instead of using the superproject's recorded SHA-1 to update the submodule, use the status of the submodule's remote-tracking branch. The remote used is branch's remote (branch.<name>.remote), defaulting to origin. The remote branch used defaults to master.

    Why

    So why is HEAD detached after update? Because the default behavior of submodule.$name.update is checkout.

    --checkout

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

    How

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

    --merge

    This option is only valid for the update command. Merge the commit recorded in the superproject into the current branch of the submodule. If this option is given, the submodule's HEAD will not be detached.

    --rebase

    Rebase the current branch onto the commit recorded in the superproject. If this option is given, the submodule's HEAD will not be detached.

    All you need to do is,

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

    There's also an option to make --merge or --rebase as the default behavior of git submodule update, by setting submodule.$name.update to merge or rebase.

    Here's an example about how to config the default update behavior of submodule update 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
    

    My whole answer is based on the manual. git submodule --help.