1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-05-09 02:06:12 +02:00

t, doc: update tests, reference for "--force-if-includes"

Update test cases for the new option, and document its usage
and update related references.

Update test cases for the new option, and document its usage
and update related references.

 - t/t5533-push-cas.sh:
   Update test cases for "compare-and-swap" when used along with
   "--force-if-includes" helps mitigate overwrites when remote
   refs are updated in the background; allows forced updates when
   changes from remote are integrated locally.

 - Documentation:
   Add reference for the new option, configuration setting
   ("push.useForceIfIncludes") and advise messages.

Signed-off-by: Srinidhi Kaushik <shrinidhi.kaushik@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Srinidhi Kaushik 2020-10-03 17:40:46 +05:30 committed by Junio C Hamano
parent 3b990aa645
commit 3b5bf96573
4 changed files with 174 additions and 4 deletions

View File

@ -10,9 +10,8 @@ advice.*::
that the check is disabled.
pushUpdateRejected::
Set this variable to 'false' if you want to disable
'pushNonFFCurrent',
'pushNonFFMatching', 'pushAlreadyExists',
'pushFetchFirst', and 'pushNeedsForce'
'pushNonFFCurrent', 'pushNonFFMatching', 'pushAlreadyExists',
'pushFetchFirst', 'pushNeedsForce', and 'pushRefNeedsUpdate'
simultaneously.
pushNonFFCurrent::
Advice shown when linkgit:git-push[1] fails due to a
@ -41,6 +40,10 @@ advice.*::
we can still suggest that the user push to either
refs/heads/* or refs/tags/* based on the type of the
source object.
pushRefNeedsUpdate::
Shown when linkgit:git-push[1] rejects a forced update of
a branch when its remote-tracking ref has updates that we
do not have locally.
statusAheadBehind::
Shown when linkgit:git-status[1] computes the ahead/behind
counts for a local ref compared to its remote tracking ref,

View File

@ -114,3 +114,9 @@ push.recurseSubmodules::
specifying '--recurse-submodules=check|on-demand|no'.
If not set, 'no' is used by default, unless 'submodule.recurse' is
set (in which case a 'true' value means 'on-demand').
push.useForceIfIncludes::
If set to "true", it is equivalent to specifying
`--force-if-includes` as an option to linkgit:git-push[1]
in the command line. Adding `--no-force-if-includes` at the
time of push overrides this configuration setting.

View File

@ -13,7 +13,7 @@ SYNOPSIS
[--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-v | --verbose]
[-u | --set-upstream] [-o <string> | --push-option=<string>]
[--[no-]signed|--signed=(true|false|if-asked)]
[--force-with-lease[=<refname>[:<expect>]]]
[--force-with-lease[=<refname>[:<expect>]] [--force-if-includes]]
[--no-verify] [<repository> [<refspec>...]]
DESCRIPTION
@ -320,6 +320,14 @@ seen and are willing to overwrite, then rewrite history, and finally
force push changes to `master` if the remote version is still at
`base`, regardless of what your local `remotes/origin/master` has been
updated to in the background.
+
Alternatively, specifying `--force-if-includes` as an ancillary option
along with `--force-with-lease[=<refname>]` (i.e., without saying what
exact commit the ref on the remote side must be pointing at, or which
refs on the remote side are being protected) at the time of "push" will
verify if updates from the remote-tracking refs that may have been
implicitly updated in the background are integrated locally before
allowing a forced update.
-f::
--force::
@ -341,6 +349,22 @@ one branch, use a `+` in front of the refspec to push (e.g `git push
origin +master` to force a push to the `master` branch). See the
`<refspec>...` section above for details.
--[no-]force-if-includes::
Force an update only if the tip of the remote-tracking ref
has been integrated locally.
+
This option enables a check that verifies if the tip of the
remote-tracking ref is reachable from one of the "reflog" entries of
the local branch based in it for a rewrite. The check ensures that any
updates from the remote have been incorporated locally by rejecting the
forced update if that is not the case.
+
If the option is passed without specifying `--force-with-lease`, or
specified along with `--force-with-lease=<refname>:<expect>`, it is
a "no-op".
+
Specifying `--no-force-if-includes` disables this behavior.
--repo=<repository>::
This option is equivalent to the <repository> argument. If both
are specified, the command-line argument takes precedence.

View File

@ -13,6 +13,46 @@ setup_srcdst_basic () {
)
}
# For tests with "--force-if-includes".
setup_src_dup_dst () {
rm -fr src dup dst &&
git init --bare dst &&
git clone --no-local dst src &&
git clone --no-local dst dup
(
cd src &&
test_commit A &&
test_commit B &&
test_commit C &&
git push origin
) &&
(
cd dup &&
git fetch &&
git merge origin/master &&
git switch -c branch master~2 &&
test_commit D &&
test_commit E &&
git push origin --all
) &&
(
cd src &&
git switch master &&
git fetch --all &&
git branch branch --track origin/branch &&
git rebase origin/master
) &&
(
cd dup &&
git switch master &&
test_commit F &&
test_commit G &&
git switch branch &&
test_commit H &&
git push origin --all
)
}
test_expect_success setup '
# create template repository
test_commit A &&
@ -256,4 +296,101 @@ test_expect_success 'background updates of REMOTE can be mitigated with a non-up
)
'
test_expect_success 'background updates to remote can be mitigated with "--force-if-includes"' '
setup_src_dup_dst &&
test_when_finished "rm -fr dst src dup" &&
git ls-remote dst refs/heads/master >expect.master &&
git ls-remote dst refs/heads/branch >expect.branch &&
(
cd src &&
git switch branch &&
test_commit I &&
git switch master &&
test_commit J &&
git fetch --all &&
test_must_fail git push --force-with-lease --force-if-includes --all
) &&
git ls-remote dst refs/heads/master >actual.master &&
git ls-remote dst refs/heads/branch >actual.branch &&
test_cmp expect.master actual.master &&
test_cmp expect.branch actual.branch
'
test_expect_success 'background updates to remote can be mitigated with "push.useForceIfIncludes"' '
setup_src_dup_dst &&
test_when_finished "rm -fr dst src dup" &&
git ls-remote dst refs/heads/master >expect.master &&
(
cd src &&
git switch branch &&
test_commit I &&
git switch master &&
test_commit J &&
git fetch --all &&
git config --local push.useForceIfIncludes true &&
test_must_fail git push --force-with-lease=master origin master
) &&
git ls-remote dst refs/heads/master >actual.master &&
test_cmp expect.master actual.master
'
test_expect_success '"--force-if-includes" should be disabled for --force-with-lease="<refname>:<expect>"' '
setup_src_dup_dst &&
test_when_finished "rm -fr dst src dup" &&
git ls-remote dst refs/heads/master >expect.master &&
(
cd src &&
git switch branch &&
test_commit I &&
git switch master &&
test_commit J &&
remote_head="$(git rev-parse refs/remotes/origin/master)" &&
git fetch --all &&
test_must_fail git push --force-if-includes --force-with-lease="master:$remote_head" 2>err &&
grep "stale info" err
) &&
git ls-remote dst refs/heads/master >actual.master &&
test_cmp expect.master actual.master
'
test_expect_success '"--force-if-includes" should allow forced update after a rebase ("pull --rebase")' '
setup_src_dup_dst &&
test_when_finished "rm -fr dst src dup" &&
(
cd src &&
git switch branch &&
test_commit I &&
git switch master &&
test_commit J &&
git pull --rebase origin master &&
git push --force-if-includes --force-with-lease="master"
)
'
test_expect_success '"--force-if-includes" should allow forced update after a rebase ("pull --rebase", local rebase)' '
setup_src_dup_dst &&
test_when_finished "rm -fr dst src dup" &&
(
cd src &&
git switch branch &&
test_commit I &&
git switch master &&
test_commit J &&
git pull --rebase origin master &&
git rebase --onto HEAD~4 HEAD~1 &&
git push --force-if-includes --force-with-lease="master"
)
'
test_expect_success '"--force-if-includes" should allow deletes' '
setup_src_dup_dst &&
test_when_finished "rm -fr dst src dup" &&
(
cd src &&
git switch branch &&
git pull --rebase origin branch &&
git push --force-if-includes --force-with-lease="branch" origin :branch
)
'
test_done