1
+#!/bin/sh
2
+
3
+test_description='git branch submodule tests'
4
+
5
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
6
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
7
+
8
+. ./test-lib.sh
9
+. "$TEST_DIRECTORY"/lib-rebase.sh
10
+
11
+pwd=$(pwd)
12
+
13
+# Creates a clean test environment in "pwd" by copying the repo setup
14
+# from test_dirs.
15
+reset_test () {
16
+ rm -fr super &&
17
+ rm -fr sub-sub-upstream &&
18
+ rm -fr sub-upstream &&
19
+ cp -r test_dirs/* .
20
+}
21
+
22
+# Tests that the expected branch does not exist
23
+test_no_branch () {
24
+ DIR=$1 &&
25
+ BRANCH_NAME=$2 &&
26
+ test_must_fail git -C "$DIR" rev-parse "$BRANCH_NAME" 2>err &&
27
+ grep "ambiguous argument .$BRANCH_NAME." err
28
+}
29
+
30
+test_expect_success 'setup superproject and submodule' '
31
+ mkdir test_dirs &&
32
+ (
33
+ cd test_dirs &&
34
+ git init super &&
35
+ test_commit -C super foo &&
36
+ git init sub-sub-upstream &&
37
+ test_commit -C sub-sub-upstream foo &&
38
+ git init sub-upstream &&
39
+ # Submodule in a submodule
40
+ git -C sub-upstream submodule add "${pwd}/test_dirs/sub-sub-upstream" sub-sub &&
41
+ git -C sub-upstream commit -m "add submodule" &&
42
+ # Regular submodule
43
+ git -C super submodule add "${pwd}/test_dirs/sub-upstream" sub &&
44
+ # Submodule in a subdirectory
45
+ git -C super submodule add "${pwd}/test_dirs/sub-sub-upstream" second/sub &&
46
+ git -C super commit -m "add submodule" &&
47
+ git -C super config submodule.propagateBranches true &&
48
+ git -C super/sub submodule update --init
49
+ ) &&
50
+ reset_test
51
+'
52
+
53
+# Test the argument parsing
54
+test_expect_success '--recurse-submodules should create branches' '
55
+ test_when_finished "reset_test" &&
56
+ (
57
+ cd super &&
58
+ git branch --recurse-submodules branch-a &&
59
+ git rev-parse branch-a &&
60
+ git -C sub rev-parse branch-a &&
61
+ git -C sub/sub-sub rev-parse branch-a &&
62
+ git -C second/sub rev-parse branch-a
63
+ )
64
+'
65
+
66
+test_expect_success '--recurse-submodules should die if submodule.propagateBranches is false' '
67
+ test_when_finished "reset_test" &&
68
+ (
69
+ cd super &&
70
+ echo "fatal: branch with --recurse-submodules can only be used if submodule.propagateBranches is enabled" >expected &&
71
+ test_must_fail git -c submodule.propagateBranches=false branch --recurse-submodules branch-a 2>actual &&
72
+ test_cmp expected actual
73
+ )
74
+'
75
+
76
+test_expect_success '--recurse-submodules should fail when not creating branches' '
77
+ test_when_finished "reset_test" &&
78
+ (
79
+ cd super &&
80
+ git branch --recurse-submodules branch-a &&
81
+ echo "fatal: --recurse-submodules can only be used to create branches" >expected &&
82
+ test_must_fail git branch --recurse-submodules -D branch-a 2>actual &&
83
+ test_cmp expected actual &&
84
+ # Assert that the branches were not deleted
85
+ git rev-parse branch-a &&
86
+ git -C sub rev-parse branch-a
87
+ )
88
+'
89
+
90
+test_expect_success 'should respect submodule.recurse when creating branches' '
91
+ test_when_finished "reset_test" &&
92
+ (
93
+ cd super &&
94
+ git -c submodule.recurse=true branch branch-a &&
95
+ git rev-parse branch-a &&
96
+ git -C sub rev-parse branch-a
97
+ )
98
+'
99
+
100
+test_expect_success 'should ignore submodule.recurse when not creating branches' '
101
+ test_when_finished "reset_test" &&
102
+ (
103
+ cd super &&
104
+ git branch --recurse-submodules branch-a &&
105
+ git -c submodule.recurse=true branch -D branch-a &&
106
+ test_no_branch . branch-a &&
107
+ git -C sub rev-parse branch-a
108
+ )
109
+'
110
+
111
+# Test branch creation behavior
112
+test_expect_success 'should create branches based off commit id in superproject' '
113
+ test_when_finished "reset_test" &&
114
+ (
115
+ cd super &&
116
+ git branch --recurse-submodules branch-a &&
117
+ git checkout --recurse-submodules branch-a &&
118
+ git -C sub rev-parse HEAD >expected &&
119
+ # Move the tip of sub:branch-a so that it no longer matches the commit in super:branch-a
120
+ git -C sub checkout branch-a &&
121
+ test_commit -C sub bar &&
122
+ # Create a new branch-b branch with start-point=branch-a
123
+ git branch --recurse-submodules branch-b branch-a &&
124
+ git rev-parse branch-b &&
125
+ git -C sub rev-parse branch-b >actual &&
126
+ # Assert that the commit id of sub:second-branch matches super:branch-a and not sub:branch-a
127
+ test_cmp expected actual
128
+ )
129
+'
130
+
131
+test_expect_success 'should not create any branches if branch is not valid for all repos' '
132
+ test_when_finished "reset_test" &&
133
+ (
134
+ cd super &&
135
+ git -C sub branch branch-a &&
136
+ test_must_fail git branch --recurse-submodules branch-a 2>actual &&
137
+ test_no_branch . branch-a &&
138
+ grep "submodule .sub.: fatal: A branch named .branch-a. already exists" actual
139
+ )
140
+'
141
+
142
+test_expect_success 'should create branches if branch exists and --force is given' '
143
+ test_when_finished "reset_test" &&
144
+ (
145
+ cd super &&
146
+ git -C sub rev-parse HEAD >expected &&
147
+ test_commit -C sub baz &&
148
+ # branch-a in sub now points to a newer commit.
149
+ git -C sub branch branch-a HEAD &&
150
+ git -C sub rev-parse branch-a >actual-old-branch-a &&
151
+ git branch --recurse-submodules --force branch-a &&
152
+ git rev-parse branch-a &&
153
+ git -C sub rev-parse branch-a >actual-new-branch-a &&
154
+ test_cmp expected actual-new-branch-a &&
155
+ # assert that branch --force actually moved the sub
156
+ # branch
157
+ ! test_cmp expected actual-old-branch-a
158
+ )
159
+'
160
+
161
+test_expect_success 'should create branch when submodule is not in HEAD:.gitmodules' '
162
+ test_when_finished "reset_test" &&
163
+ (
164
+ cd super &&
165
+ git branch branch-a &&
166
+ git checkout -b branch-b &&
167
+ git submodule add ../sub-upstream sub2 &&
168
+ git -C sub2 submodule update --init &&
169
+ # branch-b now has a committed submodule not in branch-a
170
+ git commit -m "add second submodule" &&
171
+ git checkout branch-a &&
172
+ git branch --recurse-submodules branch-c branch-b &&
173
+ git checkout --recurse-submodules branch-c &&
174
+ git -C sub2 rev-parse branch-c &&
175
+ git -C sub2/sub-sub rev-parse branch-c
176
+ )
177
+'
178
+
179
+test_expect_success 'should not create branches in inactive submodules' '
180
+ test_when_finished "reset_test" &&
181
+ test_config -C super submodule.sub.active false &&
182
+ (
183
+ cd super &&
184
+ git branch --recurse-submodules branch-a &&
185
+ git rev-parse branch-a &&
186
+ test_no_branch sub branch-a
187
+ )
188
+'
189
+
190
+test_expect_success 'should set up tracking of local branches with track=always' '
191
+ test_when_finished "reset_test" &&
192
+ (
193
+ cd super &&
194
+ git -c branch.autoSetupMerge=always branch --recurse-submodules branch-a main &&
195
+ git -C sub rev-parse main &&
196
+ test_cmp_config -C sub . branch.branch-a.remote &&
197
+ test_cmp_config -C sub refs/heads/main branch.branch-a.merge
198
+ )
199
+'
200
+
201
+test_expect_success 'should set up tracking of local branches with explicit track' '
202
+ test_when_finished "reset_test" &&
203
+ (
204
+ cd super &&
205
+ git branch --track --recurse-submodules branch-a main &&
206
+ git -C sub rev-parse main &&
207
+ test_cmp_config -C sub . branch.branch-a.remote &&
208
+ test_cmp_config -C sub refs/heads/main branch.branch-a.merge
209
+ )
210
+'
211
+
212
+test_expect_success 'should not set up unnecessary tracking of local branches' '
213
+ test_when_finished "reset_test" &&
214
+ (
215
+ cd super &&
216
+ git branch --recurse-submodules branch-a main &&
217
+ git -C sub rev-parse main &&
218
+ test_cmp_config -C sub "" --default "" branch.branch-a.remote &&
219
+ test_cmp_config -C sub "" --default "" branch.branch-a.merge
220
+ )
221
+'
222
+
223
+reset_remote_test () {
224
+ rm -fr super-clone &&
225
+ reset_test
226
+}
227
+
228
+test_expect_success 'setup tests with remotes' '
229
+ (
230
+ cd test_dirs &&
231
+ (
232
+ cd super &&
233
+ git branch branch-a &&
234
+ git checkout -b branch-b &&
235
+ git submodule add ../sub-upstream sub2 &&
236
+ # branch-b now has a committed submodule not in branch-a
237
+ git commit -m "add second submodule"
238
+ ) &&
239
+ git clone --branch main --recurse-submodules super super-clone &&
240
+ git -C super-clone config submodule.propagateBranches true
241
+ ) &&
242
+ reset_remote_test
243
+'
244
+
245
+test_expect_success 'should get fatal error upon branch creation when submodule is not in .git/modules' '
246
+ test_when_finished "reset_remote_test" &&
247
+ (
248
+ cd super-clone &&
249
+ # This should succeed because super-clone has sub in .git/modules
250
+ git branch --recurse-submodules branch-a origin/branch-a &&
251
+ # This should fail because super-clone does not have sub2 .git/modules
252
+ test_must_fail git branch --recurse-submodules branch-b origin/branch-b 2>actual &&
253
+ grep "fatal: submodule .sub2.: unable to find submodule" actual &&
254
+ test_no_branch . branch-b &&
255
+ test_no_branch sub branch-b &&
256
+ # User can fix themselves by initializing the submodule
257
+ git checkout origin/branch-b &&
258
+ git submodule update --init --recursive &&
259
+ git branch --recurse-submodules branch-b origin/branch-b
260
+ )
261
+'
262
+
263
+test_expect_success 'should set up tracking of remote-tracking branches' '
264
+ test_when_finished "reset_remote_test" &&
265
+ (
266
+ cd super-clone &&
267
+ git branch --recurse-submodules branch-a origin/branch-a &&
268
+ test_cmp_config origin branch.branch-a.remote &&
269
+ test_cmp_config refs/heads/branch-a branch.branch-a.merge &&
270
+ # "origin/branch-a" does not exist for "sub", but it matches the refspec
271
+ # so tracking should be set up
272
+ test_cmp_config -C sub origin branch.branch-a.remote &&
273
+ test_cmp_config -C sub refs/heads/branch-a branch.branch-a.merge &&
274
+ test_cmp_config -C sub/sub-sub origin branch.branch-a.remote &&
275
+ test_cmp_config -C sub/sub-sub refs/heads/branch-a branch.branch-a.merge
276
+ )
277
+'
278
+
279
+test_expect_success 'should not fail when unable to set up tracking in submodule' '
280
+ test_when_finished "reset_remote_test" &&
281
+ (
282
+ cd super-clone &&
283
+ git remote rename origin ex-origin &&
284
+ git branch --recurse-submodules branch-a ex-origin/branch-a &&
285
+ test_cmp_config ex-origin branch.branch-a.remote &&
286
+ test_cmp_config refs/heads/branch-a branch.branch-a.merge &&
287
+ test_cmp_config -C sub "" --default "" branch.branch-a.remote &&
288
+ test_cmp_config -C sub "" --default "" branch.branch-a.merge
289
+ )
290
+'
291
+
292
+test_done