Browse Source

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>
maint
Peter Hutterer 16 years ago committed by Junio C Hamano
parent
commit
ca2cedba70
  1. 14
      Documentation/git-submodule.txt
  2. 3
      Documentation/gitmodules.txt
  3. 33
      git-submodule.sh
  4. 140
      t/t7406-submodule-update.sh

14
Documentation/git-submodule.txt

@ -12,7 +12,7 @@ SYNOPSIS @@ -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:: @@ -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 @@ -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.

3
Documentation/gitmodules.txt

@ -30,6 +30,9 @@ submodule.<name>.path:: @@ -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
--------

33
git-submodule.sh

@ -17,6 +17,7 @@ branch= @@ -17,6 +17,7 @@ branch=
quiet=
cached=
nofetch=
rebase=

#
# print stuff on stdout unless -q was specified
@ -294,6 +295,11 @@ cmd_init() @@ -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() @@ -321,6 +327,10 @@ cmd_update()
shift
nofetch=1
;;
-r|--rebase)
shift
rebase=true
;;
--)
shift
break
@ -339,6 +349,7 @@ cmd_update() @@ -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() @@ -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() @@ -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
}

140
t/t7406-submodule-update.sh

@ -0,0 +1,140 @@ @@ -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
Loading…
Cancel
Save