From: "W. Trevor King" <>

There are three branches that submodule folks usually care about:

1. The linked $sha1 in the superproject (set explicitly for every
   superproject commit, and thus for every superproject branch).
2. The remote-tracking submodule.<name>.branch that tracks a branch in
   upstream submodule.<name>.url repository.
3. The submodule's locally checked out branch, which we currently let
   the developer setup by hand, which is integrated with one of the
   other two branches by non-checkout update modes.

Git is currently a bit weak on conveniently handling branch #3.  "Just
use what the developer has setup" works well for many basic workflows,
but falls short for:

* Cloning-updates, where we currently always setup a detached HEAD.
  This is easy to fix if you accept submodule.<name>.branch or the
  branch pointed to by the cloned repository's HEAD as a guess, but
  this conflates branch #2 and branch #3, which may confuse users.

* Workflows where the preferred #3 branch depends on the superproject
  branch.  For example, if the remote subproject has only a master
  branch, but the local superproject needs to develop several
  submodule feature branches simultaneously, you can have a situation
  like this:

    Superproject branch  Submodule branch  Subproject branch
    ===================  ================  =================
    master               master            master
    feature-1            feature-1         master
    feature-2            feature-2         master
    feature-3            feature-2         master

In order to checkout the appropriate submodule branch for a given
superproject branch, we need a way to specify the preferred submodule
branch for a given superproject branch.  This commit adds two helper

* get_current_branch, to determine which superproject branch you're
  on, and
* get_local_branch, to determine the preferred submodule branch for
  that superproject branch.

The lookup chain for the local-branch is:

1. superproject.<superproject-branch>.local-branch in the submodule's
   config (superproject/.git/modules/<submodule-name>/config).  This
   is where the developer can store local per-superproject-branch
   overrides (e.g. if they wanted to use submodule branch feature-1
   with superproject branch feature-3).
2. submodule.<submodule-name>.local-branch in the superproject's
   config.  This is where the developer can store local
   cross-superproject-branch overrides (e.g. if they wanted to use
   submodule branch master for any superproject branch that didn't
   have a per-superproject-branch override).
3. submodule.<submodule-name>.local-branch in the superproject's
   .gitmodules file.  Because the gitmodules file is stored in the
   superproject's versioned tree, it is automatically
   superproject-branch-specific.  For example:

     $ git cat-file -p feature-1:.gitmodules
     [submodule "submod"]
         local-branch = feature-1
     $ git cat-file -p feature-3:.gitmodules
     [submodule "submod"]
         local-branch = feature-2

   this is where the project-wide defaults are setup and shared
   between developers.
4. The default local-branch is 'master'.

The new get_local_branch function handles the first step in this
chain.  The next two steps are already covered by the existing
--- | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/ b/
index 2677f2e..56fc3f1 100755
--- a/
+++ b/
@@ -220,6 +220,39 @@ get_submodule_config () {
        printf '%s' "${value:-$default}"
+# Print a submodule's configured local branch name
+# $1 = superproject branch
+# $2 = default (from the superproject's .gitmodules)
+# To be called from the submodule root directory.
+get_local_branch ()
+       superproject_branch="$1"
+       default="${2:-master}"
+       if test -z "${superproject_branch}"
+       then
+               value=""
+       else
+               value=$(git config 
+       fi
+       printf '%s' "${value:-$default}"
+# Print the currently checked out branch of the current repository
+# $1 = default
+get_current_branch ()
+       default="$1"
+       branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null) ||
+       branch=""
+       printf '%s' "${branch:-$default}"
 # Map submodule path to submodule name

To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to
More majordomo info at

Reply via email to