diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2009-04-24 09:06:38 +1000 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2009-04-24 01:20:25 -0700 |
commit | ca2cedba70e9356a1a20b0e39acd07ab92fee80e (patch) | |
tree | 4499831d6ce4549bf5cb25204c7b3f5813b52398 | |
parent | Merge branch 'jc/maint-read-tree-multi' (diff) | |
download | tgif-ca2cedba70e9356a1a20b0e39acd07ab92fee80e.tar.xz |
git-submodule: add support for --rebase.
'git submodule update --rebase' rebases your local branch on top of what
would have been checked out to a detached HEAD otherwise.
In some cases, detaching the HEAD when updating a submodule complicates
the workflow to commit to this submodule (checkout master, rebase, then
commit). For submodules that require frequent updates but infrequent
(if any) commits, a rebase can be executed directly by the git-submodule
command, ensuring that the submodules stay on their respective branches.
git-config key: submodule.$name.rebase (bool)
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r-- | Documentation/git-submodule.txt | 14 | ||||
-rw-r--r-- | Documentation/gitmodules.txt | 3 | ||||
-rwxr-xr-x | git-submodule.sh | 33 | ||||
-rwxr-xr-x | t/t7406-submodule-update.sh | 140 |
4 files changed, 184 insertions, 6 deletions
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt index 3b8df44673..0286409744 100644 --- a/Documentation/git-submodule.txt +++ b/Documentation/git-submodule.txt @@ -12,7 +12,7 @@ SYNOPSIS 'git submodule' [--quiet] add [-b branch] [--] <repository> <path> 'git submodule' [--quiet] status [--cached] [--] [<path>...] 'git submodule' [--quiet] init [--] [<path>...] -'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--] [<path>...] +'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase] [--] [<path>...] 'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...] 'git submodule' [--quiet] foreach <command> 'git submodule' [--quiet] sync [--] [<path>...] @@ -113,7 +113,8 @@ 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. + This will make the submodules HEAD be detached unless '--rebase' is + specified or the key `submodule.$name.rebase` is set to `true`. + If the submodule is not yet initialized, and you just want to use the setting as stored in .gitmodules, you can automatically initialize the @@ -177,6 +178,15 @@ OPTIONS This option is only valid for the update command. Don't fetch new objects from the remote site. +--rebase:: + This option is only valid for the update command. + Rebase the current branch onto the commit recorded in the + superproject. If this option is given, the submodule's HEAD will not + be detached. If a a merge failure prevents this process, you will have + to resolve these failures with linkgit:git-rebase[1]. + If the key `submodule.$name.rebase` is set to `true`, this option is + implicit. + <path>...:: Paths to submodule(s). When specified this will restrict the command to only operate on the submodules found at the specified paths. diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt index d1a17e2625..7c22c40949 100644 --- a/Documentation/gitmodules.txt +++ b/Documentation/gitmodules.txt @@ -30,6 +30,9 @@ submodule.<name>.path:: submodule.<name>.url:: Defines an url from where the submodule repository can be cloned. +submodule.<name>.rebase:: + Defines that the submodule should be rebased by default. + EXAMPLES -------- diff --git a/git-submodule.sh b/git-submodule.sh index 8e234a4028..3176226ac7 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -17,6 +17,7 @@ branch= quiet= cached= nofetch= +rebase= # # print stuff on stdout unless -q was specified @@ -294,6 +295,11 @@ cmd_init() git config submodule."$name".url "$url" || die "Failed to register url for submodule path '$path'" + test true != "$(git config -f .gitmodules --bool \ + submodule."$name".rebase)" || + git config submodule."$name".rebase true || + die "Failed to register submodule path '$path' as rebasing" + say "Submodule '$name' ($url) registered for path '$path'" done } @@ -321,6 +327,10 @@ cmd_update() shift nofetch=1 ;; + -r|--rebase) + shift + rebase=true + ;; --) shift break @@ -339,6 +349,7 @@ cmd_update() do name=$(module_name "$path") || exit url=$(git config submodule."$name".url) + rebase_module=$(git config --bool submodule."$name".rebase) if test -z "$url" then # Only mention uninitialized submodules when its @@ -359,6 +370,11 @@ cmd_update() die "Unable to find current revision in submodule path '$path'" fi + if test true = "$rebase" + then + rebase_module=true + fi + if test "$subsha1" != "$sha1" then force= @@ -374,11 +390,20 @@ cmd_update() die "Unable to fetch in submodule path '$path'" fi - (unset GIT_DIR; cd "$path" && - git-checkout $force -q "$sha1") || - die "Unable to checkout '$sha1' in submodule path '$path'" + if test true = "$rebase_module" + then + command="git-rebase" + action="rebase" + msg="rebased onto" + else + command="git-checkout $force -q" + action="checkout" + msg="checked out" + fi - say "Submodule path '$path': checked out '$sha1'" + (unset GIT_DIR; cd "$path" && $command "$sha1") || + die "Unable to $action '$sha1' in submodule path '$path'" + say "Submodule path '$path': $msg '$sha1'" fi done } diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh new file mode 100755 index 0000000000..3442c05d2a --- /dev/null +++ b/t/t7406-submodule-update.sh @@ -0,0 +1,140 @@ +#!/bin/sh +# +# Copyright (c) 2009 Red Hat, Inc. +# + +test_description='Test updating submodules + +This test verifies that "git submodule update" detaches the HEAD of the +submodule and "git submodule update --rebase" does not detach the HEAD. +' + +. ./test-lib.sh + + +compare_head() +{ + sha_master=`git-rev-list --max-count=1 master` + sha_head=`git-rev-list --max-count=1 HEAD` + + test "$sha_master" = "$sha_head" +} + + +test_expect_success 'setup a submodule tree' ' + echo file > file && + git add file && + test_tick && + git commit -m upstream + git clone . super && + git clone super submodule && + (cd super && + git submodule add ../submodule submodule && + test_tick && + git commit -m "submodule" && + git submodule init submodule + ) && + (cd submodule && + echo "line2" > file && + git add file && + git commit -m "Commit 2" + ) && + (cd super && + (cd submodule && + git pull --rebase origin + ) && + git add submodule && + git commit -m "submodule update" + ) +' + +test_expect_success 'submodule update detaching the HEAD ' ' + (cd super/submodule && + git reset --hard HEAD~1 + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update submodule && + cd submodule && + ! compare_head + ) +' + +test_expect_success 'submodule update --rebase staying on master' ' + (cd super/submodule && + git checkout master + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update --rebase submodule && + cd submodule && + compare_head + ) +' + +test_expect_success 'submodule update - rebase true in .git/config' ' + (cd super && + git config submodule.submodule.rebase true + ) && + (cd super/submodule && + git reset --hard HEAD~1 + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update submodule && + cd submodule && + compare_head + ) +' + +test_expect_success 'submodule update - rebase false in .git/config but --rebase given' ' + (cd super && + git config submodule.submodule.rebase false + ) && + (cd super/submodule && + git reset --hard HEAD~1 + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update --rebase submodule && + cd submodule && + compare_head + ) +' + +test_expect_success 'submodule update - rebase false in .git/config' ' + (cd super && + git config submodule.submodule.rebase false + ) && + (cd super/submodule && + git reset --hard HEAD^ + ) && + (cd super && + (cd submodule && + compare_head + ) && + git submodule update submodule && + cd submodule && + ! compare_head + ) +' + +test_expect_success 'submodule init picks up rebase' ' + (cd super && + git config submodule.rebasing.url git://non-existing/git && + git config submodule.rebasing.path does-not-matter && + git config submodule.rebasing.rebase true && + git submodule init rebasing && + test true = $(git config --bool submodule.rebasing.rebase) + ) +' + +test_done |