Merge branch 'jk/push-force-with-lease-creation' into maint

"git push --force-with-lease" already had enough logic to allow
ensuring that such a push results in creation of a ref (i.e. the
receiving end did not have another push from sideways that would be
discarded by our force-pushing), but didn't expose this possibility
to the users.  It does so now.

* jk/push-force-with-lease-creation:
  t5533: make it pass on case-sensitive filesystems
  push: allow pushing new branches with --force-with-lease
  push: add shorthand for --force-with-lease branch creation
  Documentation/git-push: fix placeholder formatting
This commit is contained in:
Junio C Hamano 2016-09-08 21:35:53 -07:00
commit f34d900aa7
4 changed files with 46 additions and 7 deletions

View File

@ -198,10 +198,11 @@ branch we have for it.
+ +
`--force-with-lease=<refname>:<expect>` will protect the named ref (alone), `--force-with-lease=<refname>:<expect>` will protect the named ref (alone),
if it is going to be updated, by requiring its current value to be if it is going to be updated, by requiring its current value to be
the same as the specified value <expect> (which is allowed to be the same as the specified value `<expect>` (which is allowed to be
different from the remote-tracking branch we have for the refname, different from the remote-tracking branch we have for the refname,
or we do not even have to have such a remote-tracking branch when or we do not even have to have such a remote-tracking branch when
this form is used). this form is used). If `<expect>` is the empty string, then the named ref
must not already exist.
+ +
Note that all forms other than `--force-with-lease=<refname>:<expect>` Note that all forms other than `--force-with-lease=<refname>:<expect>`
that specifies the expected current value of the ref explicitly are that specifies the expected current value of the ref explicitly are

View File

@ -1544,8 +1544,7 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
* branch. * branch.
*/ */
if (ref->expect_old_sha1) { if (ref->expect_old_sha1) {
if (ref->expect_old_no_trackback || if (oidcmp(&ref->old_oid, &ref->old_oid_expect))
oidcmp(&ref->old_oid, &ref->old_oid_expect))
reject_reason = REF_STATUS_REJECT_STALE; reject_reason = REF_STATUS_REJECT_STALE;
else else
/* If the ref isn't stale then force the update. */ /* If the ref isn't stale then force the update. */
@ -2294,6 +2293,8 @@ int parse_push_cas_option(struct push_cas_option *cas, const char *arg, int unse
entry = add_cas_entry(cas, arg, colon - arg); entry = add_cas_entry(cas, arg, colon - arg);
if (!*colon) if (!*colon)
entry->use_tracking = 1; entry->use_tracking = 1;
else if (!colon[1])
hashclr(entry->expect);
else if (get_sha1(colon + 1, entry->expect)) else if (get_sha1(colon + 1, entry->expect))
return error("cannot parse expected object name '%s'", colon + 1); return error("cannot parse expected object name '%s'", colon + 1);
return 0; return 0;
@ -2343,7 +2344,7 @@ static void apply_cas(struct push_cas_option *cas,
if (!entry->use_tracking) if (!entry->use_tracking)
hashcpy(ref->old_oid_expect.hash, cas->entry[i].expect); hashcpy(ref->old_oid_expect.hash, cas->entry[i].expect);
else if (remote_tracking(remote, ref->name, &ref->old_oid_expect)) else if (remote_tracking(remote, ref->name, &ref->old_oid_expect))
ref->expect_old_no_trackback = 1; oidclr(&ref->old_oid_expect);
return; return;
} }
@ -2353,7 +2354,7 @@ static void apply_cas(struct push_cas_option *cas,
ref->expect_old_sha1 = 1; ref->expect_old_sha1 = 1;
if (remote_tracking(remote, ref->name, &ref->old_oid_expect)) if (remote_tracking(remote, ref->name, &ref->old_oid_expect))
ref->expect_old_no_trackback = 1; oidclr(&ref->old_oid_expect);
} }
void apply_push_cas(struct push_cas_option *cas, void apply_push_cas(struct push_cas_option *cas,

View File

@ -89,7 +89,6 @@ struct ref {
force:1, force:1,
forced_update:1, forced_update:1,
expect_old_sha1:1, expect_old_sha1:1,
expect_old_no_trackback:1,
deletion:1, deletion:1,
matched:1; matched:1;

View File

@ -191,4 +191,42 @@ test_expect_success 'cover everything with default force-with-lease (allowed)' '
test_cmp expect actual test_cmp expect actual
' '
test_expect_success 'new branch covered by force-with-lease' '
setup_srcdst_basic &&
(
cd dst &&
git branch branch master &&
git push --force-with-lease=branch origin branch
) &&
git ls-remote dst refs/heads/branch >expect &&
git ls-remote src refs/heads/branch >actual &&
test_cmp expect actual
'
test_expect_success 'new branch covered by force-with-lease (explicit)' '
setup_srcdst_basic &&
(
cd dst &&
git branch branch master &&
git push --force-with-lease=branch: origin branch
) &&
git ls-remote dst refs/heads/branch >expect &&
git ls-remote src refs/heads/branch >actual &&
test_cmp expect actual
'
test_expect_success 'new branch already exists' '
setup_srcdst_basic &&
(
cd src &&
git checkout -b branch master &&
test_commit F
) &&
(
cd dst &&
git branch branch master &&
test_must_fail git push --force-with-lease=branch: origin branch
)
'
test_done test_done