git submodule foreach checkout supermodule branch
Asked Answered
H

2

3

Consider a git repository Foo/, which has submodules bar1/ and bar2/.

Each of these has the same branches: 1 & 2.

I enter the supermodule, and I want to update the supermodule to contain the most recent commits from bar1 and bar2's origin. I've already init'd and updated the supermodule, so there's working trees in bar1 and bar2, but they are in a detached state. I can do the following:

cd foo;
git checkout 1
git submodule foreach git checkout 1
git pull

Now, what bugs me is repeating the branch identifier. Can I do something like "git submodule foreach git checkout $CURRENT_BRANCH_ID"? Is there a better alternative?

Hampstead answered 24/11, 2015 at 13:24 Comment(0)
P
5

A submodule is always by default in detached HEAD mode.

You can make each submodule follow a branch.
See "How to make an existing submodule track a branch".

cd /path/to/your/parent/repo/Foo
git config -f .gitmodules submodule.bar1.branch branch1
git config -f .gitmodules submodule.bar2.branch branch2

Then all you need to do is:

git submodule update --remote

That will update each submodule to the latest of their respective upstream branch (fetch + checkout).

Pritchett answered 24/11, 2015 at 13:55 Comment(3)
From what version of git is this available? It doesn't seem to work in 1.8.4 -- or I'm doing something wrong.Hampstead
This will have HEAD -> ref that remote/branch1 points to. If you want HEAD -> local tracking branch branch1 -> ref that remote/branch1 points to, then you'll have to do something else. I can't think of how to do this other than a bash script.Mayence
@AriSweedler I agree. That reminds me of the new (Git 2.36, Apr. 2022) git branch --recurse-submodules.Pritchett
M
0

The code

Here is the script that I mentioned in my comment:

function checkout_branch_not_refs() {
  for line in $(git config --list | awk -F'[.=]' '/submodule.*branch/ {print $2","$4}'); do
    IFS=',' read -r submodule branch <<< "$line"
    if ! [ -d "$submodule" ]; then
      echo "Cannot switch branch to '$branch' for submodule '$submodule'"
      continue
    fi
    pushd "$submodule" && git switch "$branch" && popd
  done
}

to be used like

checkout_branch_not_refs
git submodule foreach git pull

Explanation of differences

Original answer

git submodule update --remote

does exactly what you ask of it. It updates the submodule by looking at the remote. The remote is configured in .gitmodules. The update --remote command looks for the submodule.<submodule_name>.branch key & checks out that commit directly.

ASCII art:

HEAD ------------\
                  \
                   V
remote branch --> Commit

My answer

checkout_branch_not_refs

This command will checkout the branch itself. HEAD -> Branch -> commit.

ASCII art:

HEAD --> local branch --> Commit

It is a prerequisite to this answer to understand the difference between a local branch and a remote branch. That's the answer to why we have to run git pull in the submodule after.

Mayence answered 25/4, 2022 at 20:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.