3 test_description='compare & swap push force/delete safety'
7 setup_srcdst_basic () {
9 git clone --no-local . src &&
10 git clone --no-local src dst &&
12 cd src && git checkout HEAD^0
16 # For tests with "--force-if-includes".
17 setup_src_dup_dst () {
19 git init --bare dst &&
20 git clone --no-local dst src &&
21 git clone --no-local dst dup
32 git merge origin/master &&
33 git switch -c branch master~2 &&
42 git branch branch --track origin/branch &&
43 git rebase origin/master
56 test_expect_success setup '
57 # create template repository
63 test_expect_success 'push to update (protected)' '
68 test_must_fail git push --force-with-lease=master:master origin master 2>err &&
71 git ls-remote . refs/heads/master >expect &&
72 git ls-remote src refs/heads/master >actual &&
73 test_cmp expect actual
76 test_expect_success 'push to update (protected, forced)' '
81 git push --force --force-with-lease=master:master origin master 2>err &&
82 grep "forced update" err
84 git ls-remote dst refs/heads/master >expect &&
85 git ls-remote src refs/heads/master >actual &&
86 test_cmp expect actual
89 test_expect_success 'push to update (protected, tracking)' '
93 git checkout master &&
97 git ls-remote src refs/heads/master >expect &&
101 git ls-remote . refs/remotes/origin/master >expect &&
102 test_must_fail git push --force-with-lease=master origin master &&
103 git ls-remote . refs/remotes/origin/master >actual &&
104 test_cmp expect actual
106 git ls-remote src refs/heads/master >actual &&
107 test_cmp expect actual
110 test_expect_success 'push to update (protected, tracking, forced)' '
111 setup_srcdst_basic &&
114 git checkout master &&
121 git ls-remote . refs/remotes/origin/master >expect &&
122 git push --force --force-with-lease=master origin master
124 git ls-remote dst refs/heads/master >expect &&
125 git ls-remote src refs/heads/master >actual &&
126 test_cmp expect actual
129 test_expect_success 'push to update (allowed)' '
130 setup_srcdst_basic &&
134 git push --force-with-lease=master:master^ origin master
136 git ls-remote dst refs/heads/master >expect &&
137 git ls-remote src refs/heads/master >actual &&
138 test_cmp expect actual
141 test_expect_success 'push to update (allowed, tracking)' '
142 setup_srcdst_basic &&
146 git push --force-with-lease=master origin master 2>err &&
147 ! grep "forced update" err
149 git ls-remote dst refs/heads/master >expect &&
150 git ls-remote src refs/heads/master >actual &&
151 test_cmp expect actual
154 test_expect_success 'push to update (allowed even though no-ff)' '
155 setup_srcdst_basic &&
158 git reset --hard HEAD^ &&
160 git push --force-with-lease=master origin master 2>err &&
161 grep "forced update" err
163 git ls-remote dst refs/heads/master >expect &&
164 git ls-remote src refs/heads/master >actual &&
165 test_cmp expect actual
168 test_expect_success 'push to delete (protected)' '
169 setup_srcdst_basic &&
170 git ls-remote src refs/heads/master >expect &&
173 test_must_fail git push --force-with-lease=master:master^ origin :master
175 git ls-remote src refs/heads/master >actual &&
176 test_cmp expect actual
179 test_expect_success 'push to delete (protected, forced)' '
180 setup_srcdst_basic &&
183 git push --force --force-with-lease=master:master^ origin :master
185 git ls-remote src refs/heads/master >actual &&
186 test_must_be_empty actual
189 test_expect_success 'push to delete (allowed)' '
190 setup_srcdst_basic &&
193 git push --force-with-lease=master origin :master 2>err &&
196 git ls-remote src refs/heads/master >actual &&
197 test_must_be_empty actual
200 test_expect_success 'cover everything with default force-with-lease (protected)' '
201 setup_srcdst_basic &&
204 git branch naster master^
206 git ls-remote src refs/heads/\* >expect &&
209 test_must_fail git push --force-with-lease origin master master:naster
211 git ls-remote src refs/heads/\* >actual &&
212 test_cmp expect actual
215 test_expect_success 'cover everything with default force-with-lease (allowed)' '
216 setup_srcdst_basic &&
219 git branch naster master^
224 git push --force-with-lease origin master master:naster
226 git ls-remote dst refs/heads/master |
227 sed -e "s/master/naster/" >expect &&
228 git ls-remote src refs/heads/naster >actual &&
229 test_cmp expect actual
232 test_expect_success 'new branch covered by force-with-lease' '
233 setup_srcdst_basic &&
236 git branch branch master &&
237 git push --force-with-lease=branch origin branch
239 git ls-remote dst refs/heads/branch >expect &&
240 git ls-remote src refs/heads/branch >actual &&
241 test_cmp expect actual
244 test_expect_success 'new branch covered by force-with-lease (explicit)' '
245 setup_srcdst_basic &&
248 git branch branch master &&
249 git push --force-with-lease=branch: origin branch
251 git ls-remote dst refs/heads/branch >expect &&
252 git ls-remote src refs/heads/branch >actual &&
253 test_cmp expect actual
256 test_expect_success 'new branch already exists' '
257 setup_srcdst_basic &&
260 git checkout -b branch master &&
265 git branch branch master &&
266 test_must_fail git push --force-with-lease=branch: origin branch
270 test_expect_success 'background updates of REMOTE can be mitigated with a non-updated REMOTE-push' '
272 git init --bare src.bare &&
273 test_when_finished "rm -rf src.bare" &&
274 git clone --no-local src.bare dst &&
275 test_when_finished "rm -rf dst" &&
279 git remote add origin-push ../src.bare &&
280 git push origin-push master:master
282 git clone --no-local src.bare dst2 &&
283 test_when_finished "rm -rf dst2" &&
293 test_must_fail git push --force-with-lease origin-push &&
294 git fetch origin-push &&
295 git push --force-with-lease origin-push
299 test_expect_success 'background updates to remote can be mitigated with "--force-if-includes"' '
301 test_when_finished "rm -fr dst src dup" &&
302 git ls-remote dst refs/heads/master >expect.master &&
303 git ls-remote dst refs/heads/branch >expect.branch &&
311 test_must_fail git push --force-with-lease --force-if-includes --all
313 git ls-remote dst refs/heads/master >actual.master &&
314 git ls-remote dst refs/heads/branch >actual.branch &&
315 test_cmp expect.master actual.master &&
316 test_cmp expect.branch actual.branch
319 test_expect_success 'background updates to remote can be mitigated with "push.useForceIfIncludes"' '
321 test_when_finished "rm -fr dst src dup" &&
322 git ls-remote dst refs/heads/master >expect.master &&
330 git config --local push.useForceIfIncludes true &&
331 test_must_fail git push --force-with-lease=master origin master
333 git ls-remote dst refs/heads/master >actual.master &&
334 test_cmp expect.master actual.master
337 test_expect_success '"--force-if-includes" should be disabled for --force-with-lease="<refname>:<expect>"' '
339 test_when_finished "rm -fr dst src dup" &&
340 git ls-remote dst refs/heads/master >expect.master &&
347 remote_head="$(git rev-parse refs/remotes/origin/master)" &&
349 test_must_fail git push --force-if-includes --force-with-lease="master:$remote_head" 2>err &&
350 grep "stale info" err
352 git ls-remote dst refs/heads/master >actual.master &&
353 test_cmp expect.master actual.master
356 test_expect_success '"--force-if-includes" should allow forced update after a rebase ("pull --rebase")' '
358 test_when_finished "rm -fr dst src dup" &&
365 git pull --rebase origin master &&
366 git push --force-if-includes --force-with-lease="master"
370 test_expect_success '"--force-if-includes" should allow forced update after a rebase ("pull --rebase", local rebase)' '
372 test_when_finished "rm -fr dst src dup" &&
379 git pull --rebase origin master &&
380 git rebase --onto HEAD~4 HEAD~1 &&
381 git push --force-if-includes --force-with-lease="master"
385 test_expect_success '"--force-if-includes" should allow deletes' '
387 test_when_finished "rm -fr dst src dup" &&
391 git pull --rebase origin branch &&
392 git push --force-if-includes --force-with-lease="branch" origin :branch