Skip to content

Commit ca2cedb

Browse files
whotgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ea0b767 commit ca2cedb

File tree

4 files changed

+184
-6
lines changed

4 files changed

+184
-6
lines changed

Documentation/git-submodule.txt

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ SYNOPSIS
1212
'git submodule' [--quiet] add [-b branch] [--] <repository> <path>
1313
'git submodule' [--quiet] status [--cached] [--] [<path>...]
1414
'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>...]
1616
'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
1717
'git submodule' [--quiet] foreach <command>
1818
'git submodule' [--quiet] sync [--] [<path>...]
@@ -113,7 +113,8 @@ init::
113113
update::
114114
Update the registered submodules, i.e. clone missing submodules and
115115
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`.
117118
+
118119
If the submodule is not yet initialized, and you just want to use the
119120
setting as stored in .gitmodules, you can automatically initialize the
@@ -177,6 +178,15 @@ OPTIONS
177178
This option is only valid for the update command.
178179
Don't fetch new objects from the remote site.
179180

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+
180190
<path>...::
181191
Paths to submodule(s). When specified this will restrict the command
182192
to only operate on the submodules found at the specified paths.

Documentation/gitmodules.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ submodule.<name>.path::
3030
submodule.<name>.url::
3131
Defines an url from where the submodule repository can be cloned.
3232

33+
submodule.<name>.rebase::
34+
Defines that the submodule should be rebased by default.
35+
3336

3437
EXAMPLES
3538
--------

git-submodule.sh

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ branch=
1717
quiet=
1818
cached=
1919
nofetch=
20+
rebase=
2021

2122
#
2223
# print stuff on stdout unless -q was specified
@@ -294,6 +295,11 @@ cmd_init()
294295
git config submodule."$name".url "$url" ||
295296
die "Failed to register url for submodule path '$path'"
296297

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+
297303
say "Submodule '$name' ($url) registered for path '$path'"
298304
done
299305
}
@@ -321,6 +327,10 @@ cmd_update()
321327
shift
322328
nofetch=1
323329
;;
330+
-r|--rebase)
331+
shift
332+
rebase=true
333+
;;
324334
--)
325335
shift
326336
break
@@ -339,6 +349,7 @@ cmd_update()
339349
do
340350
name=$(module_name "$path") || exit
341351
url=$(git config submodule."$name".url)
352+
rebase_module=$(git config --bool submodule."$name".rebase)
342353
if test -z "$url"
343354
then
344355
# Only mention uninitialized submodules when its
@@ -359,6 +370,11 @@ cmd_update()
359370
die "Unable to find current revision in submodule path '$path'"
360371
fi
361372

373+
if test true = "$rebase"
374+
then
375+
rebase_module=true
376+
fi
377+
362378
if test "$subsha1" != "$sha1"
363379
then
364380
force=
@@ -374,11 +390,20 @@ cmd_update()
374390
die "Unable to fetch in submodule path '$path'"
375391
fi
376392

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
380403

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'"
382407
fi
383408
done
384409
}

t/t7406-submodule-update.sh

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

0 commit comments

Comments
 (0)