Skip to content

Commit 46bdfa3

Browse files
committed
Merge branch 'ab/push-cas-doc-n-test'
Doc update. * ab/push-cas-doc-n-test: push: document & test --force-with-lease with multiple remotes
2 parents fa86d5c + f17d642 commit 46bdfa3

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

Documentation/git-push.txt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,47 @@ with this feature.
217217
+
218218
"--no-force-with-lease" will cancel all the previous --force-with-lease on the
219219
command line.
220+
+
221+
A general note on safety: supplying this option without an expected
222+
value, i.e. as `--force-with-lease` or `--force-with-lease=<refname>`
223+
interacts very badly with anything that implicitly runs `git fetch` on
224+
the remote to be pushed to in the background, e.g. `git fetch origin`
225+
on your repository in a cronjob.
226+
+
227+
The protection it offers over `--force` is ensuring that subsequent
228+
changes your work wasn't based on aren't clobbered, but this is
229+
trivially defeated if some background process is updating refs in the
230+
background. We don't have anything except the remote tracking info to
231+
go by as a heuristic for refs you're expected to have seen & are
232+
willing to clobber.
233+
+
234+
If your editor or some other system is running `git fetch` in the
235+
background for you a way to mitigate this is to simply set up another
236+
remote:
237+
+
238+
git remote add origin-push $(git config remote.origin.url)
239+
git fetch origin-push
240+
+
241+
Now when the background process runs `git fetch origin` the references
242+
on `origin-push` won't be updated, and thus commands like:
243+
+
244+
git push --force-with-lease origin-push
245+
+
246+
Will fail unless you manually run `git fetch origin-push`. This method
247+
is of course entirely defeated by something that runs `git fetch
248+
--all`, in that case you'd need to either disable it or do something
249+
more tedious like:
250+
+
251+
git fetch # update 'master' from remote
252+
git tag base master # mark our base point
253+
git rebase -i master # rewrite some commits
254+
git push --force-with-lease=master:base master:master
255+
+
256+
I.e. create a `base` tag for versions of the upstream code that you've
257+
seen and are willing to overwrite, then rewrite history, and finally
258+
force push changes to `master` if the remote version is still at
259+
`base`, regardless of what your local `remotes/origin/master` has been
260+
updated to in the background.
220261

221262
-f::
222263
--force::

t/t5533-push-cas.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,4 +229,33 @@ test_expect_success 'new branch already exists' '
229229
)
230230
'
231231

232+
test_expect_success 'background updates of REMOTE can be mitigated with a non-updated REMOTE-push' '
233+
rm -rf src dst &&
234+
git init --bare src.bare &&
235+
test_when_finished "rm -rf src.bare" &&
236+
git clone --no-local src.bare dst &&
237+
test_when_finished "rm -rf dst" &&
238+
(
239+
cd dst &&
240+
test_commit G &&
241+
git remote add origin-push ../src.bare &&
242+
git push origin-push master:master
243+
) &&
244+
git clone --no-local src.bare dst2 &&
245+
test_when_finished "rm -rf dst2" &&
246+
(
247+
cd dst2 &&
248+
test_commit H &&
249+
git push
250+
) &&
251+
(
252+
cd dst &&
253+
test_commit I &&
254+
git fetch origin &&
255+
test_must_fail git push --force-with-lease origin-push &&
256+
git fetch origin-push &&
257+
git push --force-with-lease origin-push
258+
)
259+
'
260+
232261
test_done

0 commit comments

Comments
 (0)