[RFC v3 1/4] submodule: Add helpers for configurable local branches
- From
W. Trevor King <wking@tremily.us>
- Date
- Jan 9, 2014, 06:17 UTC
- Message-ID
- <684f061e58bd16e617f438be9d6ed7b8d913463b.1389247320.git.wking@tremily.us>
- In-Reply-To
- <cover.1389247320.git.wking@tremily.us>
From: "W. Trevor King" <wking@tremily.us>
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 masterIn 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 functions:
* 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-2this 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 get_submodule_config. --- git-submodule.sh | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+)
diff --git a/git-submodule.sh b/git-submodule.sh index 2677f2e..56fc3f1 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -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 superproject."$superproject_branch".local-branch) + 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
-- 1.8.5.2.237.g01c62c6