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