git-submodule add: Add --local-branch option
authorW. Trevor King <wking@tremily.us>
Mon, 22 Oct 2012 14:48:24 +0000 (10:48 -0400)
committerW. Trevor King <wking@tremily.us>
Mon, 26 Nov 2012 18:50:22 +0000 (13:50 -0500)
This option allows you to record a submodule.<name>.branch option in
.gitmodules.  Git does not currently use this configuration option for
anything, but users have used it for several things, so it makes sense
to add some syntactic sugar for initializing the value.

Current consumers:

Ævar uses this setting to designate the local branch to checkout when
pulling submodule updates:

  $ git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull'

as he describes in

  commit f030c96d8643fa0a1a9b2bd9c2f36a77721fb61f
  Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
  Date:   Fri May 21 16:10:10 2010 +0000

    git-submodule foreach: Add $toplevel variable

Gerrit uses the same interpretation for the setting, but because
Gerrit has direct access to the subproject repositories, it updates
the superproject repositories automatically when a subproject changes.
Gerrit also accepts the special value '.', which it expands into the
superproject's branch name.

Earlier version of this patch remained agnostic on the variable usage,
but this was deemed potentially confusing.  Future patches in this
series will extend the submodule command to use the stored value
internally.

[1] https://gerrit.googlesource.com/gerrit/+/master/Documentation/user-submodules.txt

Signed-off-by: W. Trevor King <wking@tremily.us>
Documentation/git-submodule.txt
Documentation/gitmodules.txt
git-submodule.sh
t/t7400-submodule-basic.sh

index b4683bba1bc0ea6561a2378c663cf431776a3f7a..d0b44364c6d24ce27f9d84d701eaa9cb436c0942 100644 (file)
@@ -9,8 +9,8 @@ git-submodule - Initialize, update or inspect submodules
 SYNOPSIS
 --------
 [verse]
-'git submodule' [--quiet] add [-b branch] [-f|--force]
-             [--reference <repository>] [--] <repository> [<path>]
+'git submodule' [--quiet] add [-b branch] [--local-branch[=<branch>]]
+             [-f|--force] [--reference <repository>] [--] <repository> [<path>]
 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
 'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
@@ -209,6 +209,14 @@ OPTIONS
 --branch::
        Branch of repository to add as submodule.
 
+--local-branch::
+       Record a branch name used as `submodule.<path>.branch` in
+       `.gitmodules` for future reference.  If you do not list an explicit
+       name here, the name given with `--branch` will be recorded.  If that
+       is not set either, `HEAD` will be recorded.  Because the branch name
+       is optional, you must use the equal-sign form
+       (`--local-branch=<branch>`), not `--local-branch <branch>`.
+
 -f::
 --force::
        This option is only valid for add and update commands.
index 4effd789026e48085d6b0834cbef990968bedbb2..840ccfed7d2e64d32a57f78da2ac2e28f3ff7f52 100644 (file)
@@ -47,6 +47,11 @@ submodule.<name>.update::
        This config option is overridden if 'git submodule update' is given
        the '--merge', '--rebase' or '--checkout' options.
 
+submodule.<name>.branch::
+       A local branch name for the submodule (to avoid headless operation).
+       Set with the "--local-branch" option to "git submodule add", or
+       directly using "git config".
+
 submodule.<name>.fetchRecurseSubmodules::
        This option can be used to control recursive fetching of this
        submodule. If this option is also present in the submodules entry in
index ab6b1107b6090494f192f361471ed5748ffa7dc1..6eed008f2f7a39513f289c91e1a5626f292d6d3c 100755 (executable)
@@ -5,7 +5,7 @@
 # Copyright (c) 2007 Lars Hjemli
 
 dashless=$(basename "$0" | sed -e 's/-/ /')
-USAGE="[--quiet] add [-b branch] [-f|--force] [--reference <repository>] [--] <repository> [<path>]
+USAGE="[--quiet] add [-b branch] [--local-branch[=<branch>]] [-f|--force] [--reference <repository>] [--] <repository> [<path>]
    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] init [--] [<path>...]
    or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
@@ -20,6 +20,8 @@ require_work_tree
 
 command=
 branch=
+local_branch=
+local_branch_empty=
 force=
 reference=
 cached=
@@ -257,6 +259,12 @@ cmd_add()
                        branch=$2
                        shift
                        ;;
+               --local-branch)
+                       local_branch_empty=true
+                       ;;
+               --local-branch=*)
+                       local_branch="${1#*=}"
+                       ;;
                -f | --force)
                        force=$1
                        ;;
@@ -328,6 +336,11 @@ cmd_add()
        git ls-files --error-unmatch "$sm_path" > /dev/null 2>&1 &&
        die "$(eval_gettext "'\$sm_path' already exists in the index")"
 
+       if test -z "$local_branch" && test "$local_branch_empty" = "true"
+       then
+               local_branch="${branch:=HEAD}"
+       fi
+
        if test -z "$force" && ! git add --dry-run --ignore-missing "$sm_path" > /dev/null 2>&1
        then
                eval_gettextln "The following path is ignored by one of your .gitignore files:
@@ -366,6 +379,10 @@ Use -f if you really want to add it." >&2
 
        git config -f .gitmodules submodule."$sm_path".path "$sm_path" &&
        git config -f .gitmodules submodule."$sm_path".url "$repo" &&
+       if test -n "$local_branch"
+       then
+               git config -f .gitmodules submodule."$sm_path".branch "$local_branch"
+       fi &&
        git add --force .gitmodules ||
        die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
 }
index 53970374913eaa6f1b5921b14b5f25043974e3a4..fc08647bfa330a377cf8c9e04c0d2e03f4902b54 100755 (executable)
@@ -133,6 +133,7 @@ test_expect_success 'submodule add --branch' '
        (
                cd addtest &&
                git submodule add -b initial "$submodurl" submod-branch &&
+               test -z "$(git config -f .gitmodules submodule.submod-branch.branch)" &&
                git submodule init
        ) &&
 
@@ -211,6 +212,30 @@ test_expect_success 'submodule add with ./, /.. and // in path' '
        test_cmp empty untracked
 '
 
+test_expect_success 'submodule add --local-branch' '
+       (
+               cd addtest &&
+               git submodule add --local-branch "$submodurl" submod-follow-head &&
+               test "$(git config -f .gitmodules submodule.submod-follow-head.branch)" = "HEAD"
+       )
+'
+
+test_expect_success 'submodule add --local-branch --branch' '
+       (
+               cd addtest &&
+               git submodule add --local-branch -b initial "$submodurl" submod-auto-follow &&
+               test "$(git config -f .gitmodules submodule.submod-auto-follow.branch)" = "initial"
+       )
+'
+
+test_expect_success 'submodule add --local-branch=<name> --branch' '
+       (
+               cd addtest &&
+               git submodule add --local-branch=final -b initial "$submodurl" submod-follow &&
+               test "$(git config -f .gitmodules submodule.submod-follow.branch)" = "final"
+       )
+'
+
 test_expect_success 'setup - add an example entry to .gitmodules' '
        GIT_CONFIG=.gitmodules \
        git config submodule.example.url git://example.com/init.git