@matheusbsbs / matheus-bagliano / commits / ca2cedba70
Fork 0

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>

Peter Hutterer committed Apr 24, 2009 at 09:06 UTC ca2cedba70e9356a1a20b0e39acd07ab92fee80e
4 files changed +184 -6
Documentation/git-submodule.txt
+12 -2
@@ -12,7 +12,7 @@ SYNOPSIS
12 'git submodule' [--quiet] add [-b branch] [--] <repository> <path>
13 'git submodule' [--quiet] status [--cached] [--] [<path>...]
14 'git submodule' [--quiet] init [--] [<path>...]
15 -'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--] [<path>...]
15 +'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase] [--] [<path>...]
16 'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
17 'git submodule' [--quiet] foreach <command>
18 'git submodule' [--quiet] sync [--] [<path>...]
@@ -113,7 +113,8 @@ init::
113 update::
114 Update the registered submodules, i.e. clone missing submodules and
115 checkout the commit specified in the index of the containing repository.
116 - This will make the submodules HEAD be detached.
116 + This will make the submodules HEAD be detached unless '--rebase' is
117 + specified or the key `submodule.$name.rebase` is set to `true`.
118 +
119 If the submodule is not yet initialized, and you just want to use the
120 setting as stored in .gitmodules, you can automatically initialize the
@@ -177,6 +178,15 @@ OPTIONS
178 This option is only valid for the update command.
179 Don't fetch new objects from the remote site.
180
181 +--rebase::
182 + This option is only valid for the update command.
183 + Rebase the current branch onto the commit recorded in the
184 + superproject. If this option is given, the submodule's HEAD will not
185 + be detached. If a a merge failure prevents this process, you will have
186 + to resolve these failures with linkgit:git-rebase[1].
187 + If the key `submodule.$name.rebase` is set to `true`, this option is
188 + implicit.
189 +
190 <path>...::
191 Paths to submodule(s). When specified this will restrict the command
192 to only operate on the submodules found at the specified paths.
Documentation/gitmodules.txt
+3
@@ -30,6 +30,9 @@ submodule.<name>.path::
30 submodule.<name>.url::
31 Defines an url from where the submodule repository can be cloned.
32
33 +submodule.<name>.rebase::
34 + Defines that the submodule should be rebased by default.
35 +
36
37 EXAMPLES
38 --------
git-submodule.sh
+29 -4
@@ -17,6 +17,7 @@ branch=
17 quiet=
18 cached=
19 nofetch=
20 +rebase=
21
22 #
23 # print stuff on stdout unless -q was specified
@@ -294,6 +295,11 @@ cmd_init()
295 git config submodule."$name".url "$url" ||
296 die "Failed to register url for submodule path '$path'"
297
298 + test true != "$(git config -f .gitmodules --bool \
299 + submodule."$name".rebase)" ||
300 + git config submodule."$name".rebase true ||
301 + die "Failed to register submodule path '$path' as rebasing"
302 +
303 say "Submodule '$name' ($url) registered for path '$path'"
304 done
305 }
@@ -321,6 +327,10 @@ cmd_update()
327 shift
328 nofetch=1
329 ;;
330 + -r|--rebase)
331 + shift
332 + rebase=true
333 + ;;
334 --)
335 shift
336 break
@@ -339,6 +349,7 @@ cmd_update()
349 do
350 name=$(module_name "$path") || exit
351 url=$(git config submodule."$name".url)
352 + rebase_module=$(git config --bool submodule."$name".rebase)
353 if test -z "$url"
354 then
355 # Only mention uninitialized submodules when its
@@ -359,6 +370,11 @@ cmd_update()
370 die "Unable to find current revision in submodule path '$path'"
371 fi
372
373 + if test true = "$rebase"
374 + then
375 + rebase_module=true
376 + fi
377 +
378 if test "$subsha1" != "$sha1"
379 then
380 force=
@@ -374,11 +390,20 @@ cmd_update()
390 die "Unable to fetch in submodule path '$path'"
391 fi
392
377 - (unset GIT_DIR; cd "$path" &&
378 - git-checkout $force -q "$sha1") ||
379 - die "Unable to checkout '$sha1' in submodule path '$path'"
393 + if test true = "$rebase_module"
394 + then
395 + command="git-rebase"
396 + action="rebase"
397 + msg="rebased onto"
398 + else
399 + command="git-checkout $force -q"
400 + action="checkout"
401 + msg="checked out"
402 + fi
403
381 - say "Submodule path '$path': checked out '$sha1'"
404 + (unset GIT_DIR; cd "$path" && $command "$sha1") ||
405 + die "Unable to $action '$sha1' in submodule path '$path'"
406 + say "Submodule path '$path': $msg '$sha1'"
407 fi
408 done
409 }
t/t7406-submodule-update.sh new
+140
@@ -0,0 +1,140 @@
1 +#!/bin/sh
2 +#
3 +# Copyright (c) 2009 Red Hat, Inc.
4 +#
5 +
6 +test_description='Test updating submodules
7 +
8 +This test verifies that "git submodule update" detaches the HEAD of the
9 +submodule and "git submodule update --rebase" does not detach the HEAD.
10 +'
11 +
12 +. ./test-lib.sh
13 +
14 +
15 +compare_head()
16 +{
17 + sha_master=`git-rev-list --max-count=1 master`
18 + sha_head=`git-rev-list --max-count=1 HEAD`
19 +
20 + test "$sha_master" = "$sha_head"
21 +}
22 +
23 +
24 +test_expect_success 'setup a submodule tree' '
25 + echo file > file &&
26 + git add file &&
27 + test_tick &&
28 + git commit -m upstream
29 + git clone . super &&
30 + git clone super submodule &&
31 + (cd super &&
32 + git submodule add ../submodule submodule &&
33 + test_tick &&
34 + git commit -m "submodule" &&
35 + git submodule init submodule
36 + ) &&
37 + (cd submodule &&
38 + echo "line2" > file &&
39 + git add file &&
40 + git commit -m "Commit 2"
41 + ) &&
42 + (cd super &&
43 + (cd submodule &&
44 + git pull --rebase origin
45 + ) &&
46 + git add submodule &&
47 + git commit -m "submodule update"
48 + )
49 +'
50 +
51 +test_expect_success 'submodule update detaching the HEAD ' '
52 + (cd super/submodule &&
53 + git reset --hard HEAD~1
54 + ) &&
55 + (cd super &&
56 + (cd submodule &&
57 + compare_head
58 + ) &&
59 + git submodule update submodule &&
60 + cd submodule &&
61 + ! compare_head
62 + )
63 +'
64 +
65 +test_expect_success 'submodule update --rebase staying on master' '
66 + (cd super/submodule &&
67 + git checkout master
68 + ) &&
69 + (cd super &&
70 + (cd submodule &&
71 + compare_head
72 + ) &&
73 + git submodule update --rebase submodule &&
74 + cd submodule &&
75 + compare_head
76 + )
77 +'
78 +
79 +test_expect_success 'submodule update - rebase true in .git/config' '
80 + (cd super &&
81 + git config submodule.submodule.rebase true
82 + ) &&
83 + (cd super/submodule &&
84 + git reset --hard HEAD~1
85 + ) &&
86 + (cd super &&
87 + (cd submodule &&
88 + compare_head
89 + ) &&
90 + git submodule update submodule &&
91 + cd submodule &&
92 + compare_head
93 + )
94 +'
95 +
96 +test_expect_success 'submodule update - rebase false in .git/config but --rebase given' '
97 + (cd super &&
98 + git config submodule.submodule.rebase false
99 + ) &&
100 + (cd super/submodule &&
101 + git reset --hard HEAD~1
102 + ) &&
103 + (cd super &&
104 + (cd submodule &&
105 + compare_head
106 + ) &&
107 + git submodule update --rebase submodule &&
108 + cd submodule &&
109 + compare_head
110 + )
111 +'
112 +
113 +test_expect_success 'submodule update - rebase false in .git/config' '
114 + (cd super &&
115 + git config submodule.submodule.rebase false
116 + ) &&
117 + (cd super/submodule &&
118 + git reset --hard HEAD^
119 + ) &&
120 + (cd super &&
121 + (cd submodule &&
122 + compare_head
123 + ) &&
124 + git submodule update submodule &&
125 + cd submodule &&
126 + ! compare_head
127 + )
128 +'
129 +
130 +test_expect_success 'submodule init picks up rebase' '
131 + (cd super &&
132 + git config submodule.rebasing.url git://non-existing/git &&
133 + git config submodule.rebasing.path does-not-matter &&
134 + git config submodule.rebasing.rebase true &&
135 + git submodule init rebasing &&
136 + test true = $(git config --bool submodule.rebasing.rebase)
137 + )
138 +'
139 +
140 +test_done