From: W. Trevor King Date: Mon, 26 Nov 2012 19:38:32 +0000 (-0500) Subject: git-submodule update: Add --branch option X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=95edff1c97c513c555652014f9c2bbf61c8e7560;p=git.git git-submodule update: Add --branch option This allows users to checkout the current superproject-recorded-submodule-sha as a branch, avoiding the detached head state that the standard submodule update creates. This may be useful for the existing --rebase/--merge workflows which already avoid detached heads. It is also useful if you want easy tracking of upstream branches. The particular upstream branch to be tracked is configured locally with .git/modules//config. With the new option Ævar's suggested $ git submodule foreach 'git checkout $(git config --file $toplevel/.gitm odules submodule.$name.branch) && git pull' reduces to a $ git submodule update --branch after each supermodule .gitmodules edit, and a $ git submodule foreach 'git pull' whenever you feel like updating the submodules. Your still on you're own to commit (or not) the updated submodule hashes in the superproject's .gitmodules. Signed-off-by: W. Trevor King --- diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt index d0b44364c..34392a142 100644 --- a/Documentation/git-submodule.txt +++ b/Documentation/git-submodule.txt @@ -13,7 +13,7 @@ SYNOPSIS [-f|--force] [--reference ] [--] [] 'git submodule' [--quiet] status [--cached] [--recursive] [--] [...] 'git submodule' [--quiet] init [--] [...] -'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase] +'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--branch] [--rebase] [--reference ] [--merge] [--recursive] [--] [...] 'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) ] [commit] [--] [...] @@ -136,11 +136,11 @@ init:: update:: Update the registered submodules, i.e. clone missing submodules and - checkout the commit specified in the index of the containing repository. - This will make the submodules HEAD be detached unless `--rebase` or - `--merge` is specified or the key `submodule.$name.update` is set to - `rebase`, `merge` or `none`. `none` can be overridden by specifying - `--checkout`. + checkout the commit specified in the index of the containing + repository. This will make the submodules HEAD be detached unless + `--branch`, `--rebase`, `--merge` is specified or the key + `submodule.$name.update` is set to `branch`, `rebase`, `merge` or + `none`. `none` can be overridden by specifying `--checkout`. + If the submodule is not yet initialized, and you just want to use the setting as stored in .gitmodules, you can automatically initialize the @@ -207,7 +207,13 @@ OPTIONS -b:: --branch:: - Branch of repository to add as submodule. + When used with the add command, gives the branch of repository to + add as submodule. ++ +When used with the update command, checks out a branch named +`submodule..branch` (as set by `--local-branch`) pointing at the +current HEAD SHA-1. This is useful for commands like `update +--rebase` that do not work on detached heads. --local-branch:: Record a branch name used as `submodule..branch` in diff --git a/git-submodule.sh b/git-submodule.sh index c51b6aeb1..28eb4b1a6 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -8,7 +8,7 @@ dashless=$(basename "$0" | sed -e 's/-/ /') USAGE="[--quiet] add [-b branch] [--local-branch[=]] [-f|--force] [--reference ] [--] [] or: $dashless [--quiet] status [--cached] [--recursive] [--] [...] or: $dashless [--quiet] init [--] [...] - or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference ] [--merge] [--recursive] [--] [...] + or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--branch] [--rebase] [--reference ] [--merge] [--recursive] [--] [...] or: $dashless [--quiet] summary [--cached|--files] [--summary-limit ] [commit] [--] [...] or: $dashless [--quiet] foreach [--recursive] or: $dashless [--quiet] sync [--] [...]" @@ -539,6 +539,9 @@ cmd_update() -f|--force) force=$1 ;; + -b|--branch) + update="branch" + ;; -r|--rebase) update="rebase" ;; @@ -593,6 +596,7 @@ cmd_update() fi name=$(module_name "$sm_path") || exit url=$(git config submodule."$name".url) + branch=$(git config submodule."$name".branch) if ! test -z "$update" then update_module=$update @@ -627,7 +631,7 @@ Maybe you want to use 'update --init'?")" die "$(eval_gettext "Unable to find current revision in submodule path '\$sm_path'")" fi - if test "$subsha1" != "$sha1" -o -n "$force" + if test "$subsha1" != "$sha1" -o -n "$force" -o "$update_module" = "branch" then subforce=$force # If we don't already have a -f flag and the submodule has never been checked out @@ -650,16 +654,21 @@ Maybe you want to use 'update --init'?")" case ";$cloned_modules;" in *";$name;"*) # then there is no local change to integrate - update_module= ;; + case "$update_module" in + rebase|merge) + update_module= + ;; + esac + ;; esac must_die_on_failure= case "$update_module" in rebase) command="git rebase" - die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$sm_path'")" + die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$sm_path'")" say_msg="$(eval_gettext "Submodule path '\$sm_path': rebased into '\$sha1'")" - must_die_on_failure=yes + must_die_on_failure=yes ;; merge) command="git merge" @@ -674,15 +683,30 @@ Maybe you want to use 'update --init'?")" ;; esac - if (clear_local_git_env; cd "$sm_path" && $command "$sha1") + if test "$subsha1" != "$sha1" -o -n "$force" then - say "$say_msg" - elif test -n "$must_die_on_failure" + if (clear_local_git_env; cd "$sm_path" && $command "$sha1") + then + say "$say_msg" + elif test -n "$must_die_on_failure" + then + die_with_status 2 "$die_msg" + else + err="${err};$die_msg" + continue + fi + fi + + if test "$update_module" = "branch" -a -n "$branch" then - die_with_status 2 "$die_msg" - else - err="${err};$die_msg" - continue + if (clear_local_git_env; cd "$sm_path" && + git branch -f "$branch" "$sha1" && + git checkout "$branch") + then + say "$(eval_gettext "Submodule path '\$sm_path': checked out branch '\$branch'")" + else + err="${err};$(eval_gettext "Unable to checkout branch '\$branch' in submodule path '\$sm_path'")" + fi fi fi diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index 15426530e..c876a8b82 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -6,7 +6,8 @@ test_description='Test updating submodules This test verifies that "git submodule update" detaches the HEAD of the -submodule and "git submodule update --rebase/--merge" does not detach the HEAD. +submodule and "git submodule update --branch/--rebase/--merge" does not +detach the HEAD. ' . ./test-lib.sh @@ -135,6 +136,53 @@ test_expect_success 'submodule update --force forcibly checks out submodules' ' ) ' +test_expect_success 'submodule update --branch detaches without submodule..branch' ' + (cd super/submodule && + git checkout master + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update --branch submodule && + (cd submodule && + test "$(git status -s file)" = "" + ) + ) +' + +test_expect_success 'submodule update --branch staying on master' ' + (cd super/submodule && + git checkout master + ) && + (cd super && + (cd submodule && + compare_head + ) && + git config submodule.submodule.branch master + git submodule update --branch submodule && + cd submodule && + test "refs/heads/master" = "$(git symbolic-ref -q HEAD)" && + compare_head + ) +' + +test_expect_success 'submodule update --branch creating a new branch' ' + (cd super/submodule && + git checkout master + ) && + (cd super && + (cd submodule && + compare_head + ) && + git config submodule.submodule.branch new-branch + git submodule update --branch submodule && + cd submodule && + test "refs/heads/new-branch" = "$(git symbolic-ref -q HEAD)" && + compare_head + ) +' + test_expect_success 'submodule update --rebase staying on master' ' (cd super/submodule && git checkout master