3 test_description
='pull can handle submodules'
5 GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
=1
6 export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
9 .
"$TEST_DIRECTORY"/lib-submodule-update.sh
11 reset_branch_to_HEAD
() {
13 git checkout
-b "$1" HEAD
&&
14 git branch
--set-upstream-to="origin/$1" "$1"
18 reset_branch_to_HEAD
"$1" &&
19 may_only_be_test_must_fail
"$2" &&
23 # pulls without conflicts
24 test_submodule_switch_func
"git_pull"
27 reset_branch_to_HEAD
"$1" &&
28 may_only_be_test_must_fail
"$2" &&
32 test_submodule_switch_func
"git_pull_ff"
35 reset_branch_to_HEAD
"$1" &&
36 may_only_be_test_must_fail
"$2" &&
40 test_submodule_switch_func
"git_pull_ff_only"
43 reset_branch_to_HEAD
"$1" &&
44 may_only_be_test_must_fail
"$2" &&
48 if test "$GIT_TEST_MERGE_ALGORITHM" != ort
50 KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR
=1
51 KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES
=1
53 test_submodule_switch_func
"git_pull_noff"
55 test_expect_success
'pull --recurse-submodule setup' '
56 test_create_repo child &&
57 test_commit -C child bar &&
59 test_create_repo parent &&
60 test_commit -C child foo &&
62 git -C parent submodule add ../child sub &&
63 git -C parent commit -m "add submodule" &&
65 git clone --recurse-submodules parent super
68 test_expect_success
'recursive pull updates working tree' '
69 test_commit -C child merge_strategy &&
70 git -C parent submodule update --remote &&
71 git -C parent add sub &&
72 git -C parent commit -m "update submodule" &&
74 git -C super pull --no-rebase --recurse-submodules &&
75 test_path_is_file super/sub/merge_strategy.t
78 test_expect_success
"submodule.recurse option triggers recursive pull" '
79 test_commit -C child merge_strategy_2 &&
80 git -C parent submodule update --remote &&
81 git -C parent add sub &&
82 git -C parent commit -m "update submodule" &&
84 git -C super -c submodule.recurse pull --no-rebase &&
85 test_path_is_file super/sub/merge_strategy_2.t
88 test_expect_success
" --[no-]recurse-submodule and submodule.recurse" '
89 test_commit -C child merge_strategy_3 &&
90 git -C parent submodule update --remote &&
91 git -C parent add sub &&
92 git -C parent commit -m "update submodule" &&
94 git -C super -c submodule.recurse pull --no-recurse-submodules --no-rebase &&
95 test_path_is_missing super/sub/merge_strategy_3.t &&
96 git -C super -c submodule.recurse=false pull --recurse-submodules --no-rebase &&
97 test_path_is_file super/sub/merge_strategy_3.t &&
99 test_commit -C child merge_strategy_4 &&
100 git -C parent submodule update --remote &&
101 git -C parent add sub &&
102 git -C parent commit -m "update submodule" &&
104 git -C super -c submodule.recurse=false pull --no-recurse-submodules --no-rebase &&
105 test_path_is_missing super/sub/merge_strategy_4.t &&
106 git -C super -c submodule.recurse=true pull --recurse-submodules --no-rebase &&
107 test_path_is_file super/sub/merge_strategy_4.t
110 test_expect_success
"fetch.recurseSubmodules option triggers recursive fetch (but not recursive update)" '
111 test_commit -C child merge_strategy_5 &&
112 # Omit the parent commit, otherwise this passes with the
113 # default "pull" behavior.
115 git -C super -c fetch.recursesubmodules=true pull --no-rebase &&
116 # Check that the submodule commit was fetched
117 sub_oid=$(git -C child rev-parse HEAD) &&
118 git -C super/sub cat-file -e $sub_oid &&
119 # Check that the submodule worktree did not update
120 ! test_path_is_file super/sub/merge_strategy_5.t
123 test_expect_success
"fetch.recurseSubmodules takes precedence over submodule.recurse" '
124 test_commit -C child merge_strategy_6 &&
125 # Omit the parent commit, otherwise this passes with the
126 # default "pull" behavior.
128 git -C super -c submodule.recurse=false -c fetch.recursesubmodules=true pull --no-rebase &&
129 # Check that the submodule commit was fetched
130 sub_oid=$(git -C child rev-parse HEAD) &&
131 git -C super/sub cat-file -e $sub_oid &&
132 # Check that the submodule worktree did not update
133 ! test_path_is_file super/sub/merge_strategy_6.t
136 test_expect_success
'pull --rebase --recurse-submodules (remote superproject submodule changes, local submodule changes)' '
137 # This tests the following scenario :
138 # - local submodule has new commits
139 # - local superproject does not have new commits
140 # - upstream superproject has new commits that change the submodule pointer
143 test_commit -C child rebase_strategy &&
144 git -C parent submodule update --remote &&
145 git -C parent add sub &&
146 git -C parent commit -m "update submodule" &&
148 # also have local commits
149 test_commit -C super/sub local_stuff &&
151 git -C super pull --rebase --recurse-submodules &&
152 test_path_is_file super/sub/rebase_strategy.t &&
153 test_path_is_file super/sub/local_stuff.t
156 test_expect_success
'pull --rebase --recurse-submodules fails if both sides record submodule changes' '
157 # This tests the following scenario :
158 # - local superproject has new commits that change the submodule pointer
159 # - upstream superproject has new commits that change the submodule pointer
161 # local changes in submodule recorded in superproject:
162 test_commit -C super/sub local_stuff_2 &&
163 git -C super add sub &&
164 git -C super commit -m "local update submodule" &&
166 # and in the remote as well:
167 test_commit -C child important_upstream_work &&
168 git -C parent submodule update --remote &&
169 git -C parent add sub &&
170 git -C parent commit -m "remote update submodule" &&
172 # Unfortunately we fail here, despite no conflict in the
173 # submodule itself, but the merge strategy in submodules
174 # does not support rebase:
175 test_must_fail git -C super pull --rebase --recurse-submodules 2>err &&
176 test_i18ngrep "locally recorded submodule modifications" err
179 test_expect_success
'pull --rebase --recurse-submodules (no submodule changes, no fork-point)' '
180 # This tests the following scenario :
181 # - local submodule does not have new commits
182 # - local superproject has new commits that *do not* change the submodule pointer
183 # - upstream superproject has new commits that *do not* change the submodule pointer
184 # - local superproject branch has no fork-point with its remote-tracking counter-part
186 # create upstream superproject
187 test_create_repo submodule &&
188 test_commit -C submodule first_in_sub &&
190 test_create_repo superprojet &&
191 test_commit -C superprojet first_in_super &&
192 git -C superprojet submodule add ../submodule &&
193 git -C superprojet commit -m "add submodule" &&
194 test_commit -C superprojet third_in_super &&
197 git clone --recurse-submodules superprojet superclone &&
199 # add commits upstream
200 test_commit -C superprojet fourth_in_super &&
202 # create topic branch in clone, not based on any remote-tracking branch
203 git -C superclone checkout -b feat HEAD~1 &&
204 test_commit -C superclone first_on_feat &&
205 git -C superclone pull --rebase --recurse-submodules origin HEAD
210 # This test is particular because there is only a single commit in the upstream superproject
211 # 'parent' (which adds the submodule 'a-submodule'). The clone of the superproject
212 # ('child') hard-resets its branch to a new root commit with the same tree as the one
213 # from the upstream superproject, so that its branch has no merge-base with its
214 # remote-tracking counterpart, and then calls 'git pull --recurse-submodules --rebase'.
215 # The result is that the local branch is reset to the remote-tracking branch (as it was
216 # originally before the hard-reset).
218 # The only commit in the range generated by 'submodule.c::submodule_touches_in_range' and
219 # passed to 'submodule.c::collect_changed_submodules' is the new (regenerated) initial commit,
220 # which adds the submodule.
221 # However, 'submodule_touches_in_range' does not error (even though this commit adds the submodule)
222 # because 'combine-diff.c::diff_tree_combined' returns early, as the initial commit has no parents.
223 test_expect_success
'branch has no merge base with remote-tracking counterpart' '
224 rm -rf parent child &&
226 test_create_repo a-submodule &&
227 test_commit -C a-submodule foo &&
229 test_create_repo parent &&
230 git -C parent submodule add "$(pwd)/a-submodule" &&
231 git -C parent commit -m foo &&
233 git clone parent child &&
235 # Reset the current branch so that it has no merge base with
236 # the remote-tracking branch.
237 OTHER=$(git -C child commit-tree -m bar \
238 $(git -C child rev-parse HEAD^{tree})) &&
239 git -C child reset --hard "$OTHER" &&
241 git -C child pull --recurse-submodules --rebase