{"thread":{"id":"42912","subject":"[PATCH] push: allow pushing new branches with --force-with-lease","startedAt":"2016-07-23T15:32:21Z","lastAt":"2016-07-26T21:21:36Z","messageCount":19,"participants":["John Keeping","Junio C Hamano","Jakub Narębski"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"292039","messageId":"6b401124e734d4f5486003459e586cc05c7843e8.1469287889.git.john@keeping.me.uk","threadId":"42912","inReplyTo":null,"subject":"[PATCH] push: allow pushing new branches with --force-with-lease","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2016-07-23T15:31:57Z","receivedAt":"2016-07-23T15:32:21Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"If there is no upstream information for a branch, it is likely that it\nis newly created and can safely be pushed under the normal fast-forward\nrules.  Relax the --force-with-lease check so that we do not reject\nthese branches immediately but rather attempt to push them as new\nbranches, using the null SHA-1 as the expected value.\n\nIn fact, it is already possible to push new branches using the explicit\n--force-with-lease=<branch>:<expect> syntax, so all we do here is make\nthis behaviour the default if no explicit \"expect\" value is specified.\n\nSigned-off-by: John Keeping <john@keeping.me.uk>\n---\n remote.c            |  7 +++----\n remote.h            |  1 -\n t/t5533-push-cas.sh | 38 ++++++++++++++++++++++++++++++++++++++\n 3 files changed, 41 insertions(+), 5 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex a326e4e..cd2ee52 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -1544,8 +1544,7 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,\n \t\t * branch.\n \t\t */\n \t\tif (ref->expect_old_sha1) {\n-\t\t\tif (ref->expect_old_no_trackback ||\n-\t\t\t    oidcmp(&ref->old_oid, &ref->old_oid_expect))\n+\t\t\tif (oidcmp(&ref->old_oid, &ref->old_oid_expect))\n \t\t\t\treject_reason = REF_STATUS_REJECT_STALE;\n \t\t\telse\n \t\t\t\t/* If the ref isn't stale then force the update. */\n@@ -2343,7 +2342,7 @@ static void apply_cas(struct push_cas_option *cas,\n \t\tif (!entry->use_tracking)\n \t\t\thashcpy(ref->old_oid_expect.hash, cas->entry[i].expect);\n \t\telse if (remote_tracking(remote, ref->name, &ref->old_oid_expect))\n-\t\t\tref->expect_old_no_trackback = 1;\n+\t\t\tmemset(&ref->old_oid_expect, 0, sizeof(ref->old_oid_expect));\n \t\treturn;\n \t}\n \n@@ -2353,7 +2352,7 @@ static void apply_cas(struct push_cas_option *cas,\n \n \tref->expect_old_sha1 = 1;\n \tif (remote_tracking(remote, ref->name, &ref->old_oid_expect))\n-\t\tref->expect_old_no_trackback = 1;\n+\t\tmemset(&ref->old_oid_expect, 0, sizeof(ref->old_oid_expect));\n }\n \n void apply_push_cas(struct push_cas_option *cas,\ndiff --git a/remote.h b/remote.h\nindex c21fd37..9248811 100644\n--- a/remote.h\n+++ b/remote.h\n@@ -89,7 +89,6 @@ struct ref {\n \t\tforce:1,\n \t\tforced_update:1,\n \t\texpect_old_sha1:1,\n-\t\texpect_old_no_trackback:1,\n \t\tdeletion:1,\n \t\tmatched:1;\n \ndiff --git a/t/t5533-push-cas.sh b/t/t5533-push-cas.sh\nindex c732012..4276b1b 100755\n--- a/t/t5533-push-cas.sh\n+++ b/t/t5533-push-cas.sh\n@@ -191,4 +191,42 @@ test_expect_success 'cover everything with default force-with-lease (allowed)' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'new branch covered by force-with-lease' '\n+\tsetup_srcdst_basic &&\n+\t(\n+\t\tcd dst &&\n+\t\tgit branch branch master &&\n+\t\tgit push --force-with-lease=branch origin branch\n+\t) &&\n+\tgit ls-remote dst refs/heads/branch >expect &&\n+\tgit ls-remote src refs/heads/branch >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'new branch covered by force-with-lease (explicit)' '\n+\tsetup_srcdst_basic &&\n+\t(\n+\t\tcd dst &&\n+\t\tgit branch branch master &&\n+\t\tgit push --force-with-lease=branch:0000000000000000000000000000000000000000 origin branch\n+\t) &&\n+\tgit ls-remote dst refs/heads/branch >expect &&\n+\tgit ls-remote src refs/heads/branch >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'new branch already exists' '\n+\tsetup_srcdst_basic &&\n+\t(\n+\t\tcd src &&\n+\t\tgit checkout -b branch master &&\n+\t\ttest_commit c\n+\t) &&\n+\t(\n+\t\tcd dst &&\n+\t\tgit branch branch master &&\n+\t\ttest_must_fail git push --force-with-lease=branch origin branch\n+\t)\n+'\n+\n test_done\n-- \n2.9.2.637.g8b832fc\n\n"},{"id":"292107","messageId":"xmqq4m7d7hlq.fsf@gitster.mtv.corp.google.com","threadId":"42912","inReplyTo":"6b401124e734d4f5486003459e586cc05c7843e8.1469287889.git.john@keeping.me.uk","subject":"Re: [PATCH] push: allow pushing new branches with --force-with-lease","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-25T17:28:01Z","receivedAt":"2016-07-25T17:28:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Keeping <john@keeping.me.uk> writes:\n\n> If there is no upstream information for a branch, it is likely that it\n> is newly created and can safely be pushed under the normal fast-forward\n> rules.  Relax the --force-with-lease check so that we do not reject\n> these branches immediately but rather attempt to push them as new\n> branches, using the null SHA-1 as the expected value.\n>\n> In fact, it is already possible to push new branches using the explicit\n> --force-with-lease=<branch>:<expect> syntax, so all we do here is make\n> this behaviour the default if no explicit \"expect\" value is specified.\n\nI like the loss of an extra field from \"struct ref\".\n\nI suspect that the if/else cascade in the loop in apply_cas() can\nalso be taught that ':' followed by an empty string asks to check\nthat the target ref does not exist, in order to make it a bit more\nuseful for folks who do not rely on the \"use the last observed\nstatus of the tracking branch\".\n\nThat would make the \"explicit\" test much less cumbersome to read.\n\n\n> +test_expect_success 'new branch covered by force-with-lease (explicit)' '\n> +\tsetup_srcdst_basic &&\n> +\t(\n> +\t\tcd dst &&\n> +\t\tgit branch branch master &&\n> +\t\tgit push --force-with-lease=branch:0000000000000000000000000000000000000000 origin branch\n> +\t) &&\n"},{"id":"292148","messageId":"cover.1469483499.git.john@keeping.me.uk","threadId":"42912","inReplyTo":"xmqq4m7d7hlq.fsf@gitster.mtv.corp.google.com","subject":"[PATCH v2 0/3] push: allow pushing new branches with --force-with-lease","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2016-07-25T21:59:54Z","receivedAt":"2016-07-25T22:00:27Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"On Mon, Jul 25, 2016 at 10:28:01AM -0700, Junio C Hamano wrote:\n> John Keeping <john@keeping.me.uk> writes:\n> \n> > If there is no upstream information for a branch, it is likely that it\n> > is newly created and can safely be pushed under the normal fast-forward\n> > rules.  Relax the --force-with-lease check so that we do not reject\n> > these branches immediately but rather attempt to push them as new\n> > branches, using the null SHA-1 as the expected value.\n> >\n> > In fact, it is already possible to push new branches using the explicit\n> > --force-with-lease=<branch>:<expect> syntax, so all we do here is make\n> > this behaviour the default if no explicit \"expect\" value is specified.\n> \n> I like the loss of an extra field from \"struct ref\".\n> \n> I suspect that the if/else cascade in the loop in apply_cas() can\n> also be taught that ':' followed by an empty string asks to check\n> that the target ref does not exist, in order to make it a bit more\n> useful for folks who do not rely on the \"use the last observed\n> status of the tracking branch\".\n> \n> That would make the \"explicit\" test much less cumbersome to read.\n\nYes, that's nicer and it mirrors the syntax for deleting a remote\nbranch.\n\nI've pulled it out as a preparatory step because I like the fact that\nthe \"explicit\" test passes even before the patch that is the main point\nof the series.\n\n> > +test_expect_success 'new branch covered by force-with-lease (explicit)' '\n> > +   setup_srcdst_basic &&\n> > +   (\n> > +           cd dst &&\n> > +           git branch branch master &&\n> > +           git push --force-with-lease=branch:0000000000000000000000000000000000000000 origin branch\n> > +   ) &&\n\nJohn Keeping (3):\n  Documentation/git-push: fix placeholder formatting\n  push: add shorthand for --force-with-lease branch creation\n  push: allow pushing new branches with --force-with-lease\n\n Documentation/git-push.txt |  5 +++--\n remote.c                   |  9 +++++----\n remote.h                   |  1 -\n t/t5533-push-cas.sh        | 38 ++++++++++++++++++++++++++++++++++++++\n 4 files changed, 46 insertions(+), 7 deletions(-)\n\n-- \n2.9.2.639.g855ae9f\n\n"},{"id":"292149","messageId":"bb37a70b0a47a72d38e29d34b3dd66ef9f018655.1469483499.git.john@keeping.me.uk","threadId":"42912","inReplyTo":"cover.1469483499.git.john@keeping.me.uk","subject":"[PATCH v2 1/3] Documentation/git-push: fix placeholder formatting","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2016-07-25T21:59:55Z","receivedAt":"2016-07-25T22:00:32Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"Format the placeholder as monospace to match other occurrences in this\nfile and obey CodingGuidelines.\n\nSigned-off-by: John Keeping <john@keeping.me.uk>\n---\nNew in v2.\n\n Documentation/git-push.txt | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-push.txt b/Documentation/git-push.txt\nindex 93c3527..bf7c9a2 100644\n--- a/Documentation/git-push.txt\n+++ b/Documentation/git-push.txt\n@@ -198,7 +198,7 @@ branch we have for it.\n +\n `--force-with-lease=<refname>:<expect>` will protect the named ref (alone),\n if it is going to be updated, by requiring its current value to be\n-the same as the specified value <expect> (which is allowed to be\n+the same as the specified value `<expect>` (which is allowed to be\n different from the remote-tracking branch we have for the refname,\n or we do not even have to have such a remote-tracking branch when\n this form is used).\n-- \n2.9.2.639.g855ae9f\n\n"},{"id":"292150","messageId":"4e07ff23715b53fcd29564be1c74a9f66dd74e1e.1469483499.git.john@keeping.me.uk","threadId":"42912","inReplyTo":"cover.1469483499.git.john@keeping.me.uk","subject":"[PATCH v2 2/3] push: add shorthand for --force-with-lease branch creation","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2016-07-25T21:59:56Z","receivedAt":"2016-07-25T22:00:35Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"Allow the empty string to stand in for the null SHA-1 when pushing a new\nbranch, like we do when deleting branches.\n\nThis means that the following command ensures that `new-branch` is\ncreated on the remote (that is, is must not already exist):\n\n\tgit push --force-with-lease=new-branch: origin new-branch\n\nSigned-off-by: John Keeping <john@keeping.me.uk>\n---\nNew in v2.\n\n Documentation/git-push.txt |  3 ++-\n remote.c                   |  2 ++\n t/t5533-push-cas.sh        | 12 ++++++++++++\n 3 files changed, 16 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-push.txt b/Documentation/git-push.txt\nindex bf7c9a2..927a034 100644\n--- a/Documentation/git-push.txt\n+++ b/Documentation/git-push.txt\n@@ -201,7 +201,8 @@ if it is going to be updated, by requiring its current value to be\n the same as the specified value `<expect>` (which is allowed to be\n different from the remote-tracking branch we have for the refname,\n or we do not even have to have such a remote-tracking branch when\n-this form is used).\n+this form is used).  If `<expect>` is the empty string, then the named ref\n+must not already exist.\n +\n Note that all forms other than `--force-with-lease=<refname>:<expect>`\n that specifies the expected current value of the ref explicitly are\ndiff --git a/remote.c b/remote.c\nindex a326e4e..af94892 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -2294,6 +2294,8 @@ int parse_push_cas_option(struct push_cas_option *cas, const char *arg, int unse\n \tentry = add_cas_entry(cas, arg, colon - arg);\n \tif (!*colon)\n \t\tentry->use_tracking = 1;\n+\telse if (!colon[1])\n+\t\tmemset(entry->expect, 0, sizeof(entry->expect));\n \telse if (get_sha1(colon + 1, entry->expect))\n \t\treturn error(\"cannot parse expected object name '%s'\", colon + 1);\n \treturn 0;\ndiff --git a/t/t5533-push-cas.sh b/t/t5533-push-cas.sh\nindex c732012..5e7f6e9 100755\n--- a/t/t5533-push-cas.sh\n+++ b/t/t5533-push-cas.sh\n@@ -191,4 +191,16 @@ test_expect_success 'cover everything with default force-with-lease (allowed)' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'new branch covered by force-with-lease (explicit)' '\n+\tsetup_srcdst_basic &&\n+\t(\n+\t\tcd dst &&\n+\t\tgit branch branch master &&\n+\t\tgit push --force-with-lease=branch: origin branch\n+\t) &&\n+\tgit ls-remote dst refs/heads/branch >expect &&\n+\tgit ls-remote src refs/heads/branch >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n2.9.2.639.g855ae9f\n\n"},{"id":"292151","messageId":"665bb0aaaac14790521738efe93904bfeabf38f1.1469483499.git.john@keeping.me.uk","threadId":"42912","inReplyTo":"cover.1469483499.git.john@keeping.me.uk","subject":"[PATCH v2 3/3] push: allow pushing new branches with --force-with-lease","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2016-07-25T21:59:57Z","receivedAt":"2016-07-25T22:00:41Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"If there is no upstream information for a branch, it is likely that it\nis newly created and can safely be pushed under the normal fast-forward\nrules.  Relax the --force-with-lease check so that we do not reject\nthese branches immediately but rather attempt to push them as new\nbranches, using the null SHA-1 as the expected value.\n\nIn fact, it is already possible to push new branches using the explicit\n--force-with-lease=<branch>:<expect> syntax, so all we do here is make\nthis behaviour the default if no explicit \"expect\" value is specified.\n\nSigned-off-by: John Keeping <john@keeping.me.uk>\n---\nChanges in v2:\n- The \"explicit\" test was previously in this patch but is now added in\n  patch 2/3.\n\n remote.c            |  7 +++----\n remote.h            |  1 -\n t/t5533-push-cas.sh | 26 ++++++++++++++++++++++++++\n 3 files changed, 29 insertions(+), 5 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex af94892..20e174d 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -1544,8 +1544,7 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,\n \t\t * branch.\n \t\t */\n \t\tif (ref->expect_old_sha1) {\n-\t\t\tif (ref->expect_old_no_trackback ||\n-\t\t\t    oidcmp(&ref->old_oid, &ref->old_oid_expect))\n+\t\t\tif (oidcmp(&ref->old_oid, &ref->old_oid_expect))\n \t\t\t\treject_reason = REF_STATUS_REJECT_STALE;\n \t\t\telse\n \t\t\t\t/* If the ref isn't stale then force the update. */\n@@ -2345,7 +2344,7 @@ static void apply_cas(struct push_cas_option *cas,\n \t\tif (!entry->use_tracking)\n \t\t\thashcpy(ref->old_oid_expect.hash, cas->entry[i].expect);\n \t\telse if (remote_tracking(remote, ref->name, &ref->old_oid_expect))\n-\t\t\tref->expect_old_no_trackback = 1;\n+\t\t\tmemset(&ref->old_oid_expect, 0, sizeof(ref->old_oid_expect));\n \t\treturn;\n \t}\n \n@@ -2355,7 +2354,7 @@ static void apply_cas(struct push_cas_option *cas,\n \n \tref->expect_old_sha1 = 1;\n \tif (remote_tracking(remote, ref->name, &ref->old_oid_expect))\n-\t\tref->expect_old_no_trackback = 1;\n+\t\tmemset(&ref->old_oid_expect, 0, sizeof(ref->old_oid_expect));\n }\n \n void apply_push_cas(struct push_cas_option *cas,\ndiff --git a/remote.h b/remote.h\nindex c21fd37..9248811 100644\n--- a/remote.h\n+++ b/remote.h\n@@ -89,7 +89,6 @@ struct ref {\n \t\tforce:1,\n \t\tforced_update:1,\n \t\texpect_old_sha1:1,\n-\t\texpect_old_no_trackback:1,\n \t\tdeletion:1,\n \t\tmatched:1;\n \ndiff --git a/t/t5533-push-cas.sh b/t/t5533-push-cas.sh\nindex 5e7f6e9..5f29664 100755\n--- a/t/t5533-push-cas.sh\n+++ b/t/t5533-push-cas.sh\n@@ -191,6 +191,18 @@ test_expect_success 'cover everything with default force-with-lease (allowed)' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'new branch covered by force-with-lease' '\n+\tsetup_srcdst_basic &&\n+\t(\n+\t\tcd dst &&\n+\t\tgit branch branch master &&\n+\t\tgit push --force-with-lease=branch origin branch\n+\t) &&\n+\tgit ls-remote dst refs/heads/branch >expect &&\n+\tgit ls-remote src refs/heads/branch >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'new branch covered by force-with-lease (explicit)' '\n \tsetup_srcdst_basic &&\n \t(\n@@ -203,4 +215,18 @@ test_expect_success 'new branch covered by force-with-lease (explicit)' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'new branch already exists' '\n+\tsetup_srcdst_basic &&\n+\t(\n+\t\tcd src &&\n+\t\tgit checkout -b branch master &&\n+\t\ttest_commit c\n+\t) &&\n+\t(\n+\t\tcd dst &&\n+\t\tgit branch branch master &&\n+\t\ttest_must_fail git push --force-with-lease=branch origin branch\n+\t)\n+'\n+\n test_done\n-- \n2.9.2.639.g855ae9f\n\n"},{"id":"292154","messageId":"xmqq37mx4bct.fsf@gitster.mtv.corp.google.com","threadId":"42912","inReplyTo":"xmqq4m7d7hlq.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH] push: allow pushing new branches with --force-with-lease","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-25T22:11:14Z","receivedAt":"2016-07-25T22:11:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> I suspect that the if/else cascade in the loop in apply_cas() can\n> also be taught that ':' followed by an empty string asks to check\n> that the target ref does not exist, in order to make it a bit more\n> useful for folks who do not rely on the \"use the last observed\n> status of the tracking branch\".\n>\n> That would make the \"explicit\" test much less cumbersome to read.\n\nIn other words, something like this, perhaps?\n\n remote.c            |  2 ++\n t/t5533-push-cas.sh | 12 ++++++++++++\n 2 files changed, 14 insertions(+)\n\ndiff --git a/remote.c b/remote.c\nindex b35ffd9..55812d8 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -2303,6 +2303,8 @@ int parse_push_cas_option(struct push_cas_option *cas, const char *arg, int unse\n \tentry = add_cas_entry(cas, arg, colon - arg);\n \tif (!*colon)\n \t\tentry->use_tracking = 1;\n+\telse if (!colon[1])\n+\t\thashclr(entry->expect);\n \telse if (get_sha1(colon + 1, entry->expect))\n \t\treturn error(\"cannot parse expected object name '%s'\", colon + 1);\n \treturn 0;\ndiff --git a/t/t5533-push-cas.sh b/t/t5533-push-cas.sh\nindex 4276b1b..04f4636 100755\n--- a/t/t5533-push-cas.sh\n+++ b/t/t5533-push-cas.sh\n@@ -215,6 +215,18 @@ test_expect_success 'new branch covered by force-with-lease (explicit)' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'new branch covered by force-with-lease (less cumbersome)' '\n+\tsetup_srcdst_basic &&\n+\t(\n+\t\tcd dst &&\n+\t\tgit branch another master &&\n+\t\tgit push --force-with-lease=another: origin another\n+\t) &&\n+\tgit ls-remote dst refs/heads/another >expect &&\n+\tgit ls-remote src refs/heads/another >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'new branch already exists' '\n \tsetup_srcdst_basic &&\n \t(\n-- \n2.9.2-629-gdd92683\n\n"},{"id":"292158","messageId":"xmqqtwfd2wbp.fsf@gitster.mtv.corp.google.com","threadId":"42912","inReplyTo":"cover.1469483499.git.john@keeping.me.uk","subject":"Re: [PATCH v2 0/3] push: allow pushing new branches with --force-with-lease","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-25T22:21:14Z","receivedAt":"2016-07-25T22:21:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Keeping <john@keeping.me.uk> writes:\n\n> On Mon, Jul 25, 2016 at 10:28:01AM -0700, Junio C Hamano wrote:\n>> John Keeping <john@keeping.me.uk> writes:\n>> \n>> > If there is no upstream information for a branch, it is likely that it\n>> > is newly created and can safely be pushed under the normal fast-forward\n>> > rules.  Relax the --force-with-lease check so that we do not reject\n>> > these branches immediately but rather attempt to push them as new\n>> > branches, using the null SHA-1 as the expected value.\n>> >\n>> > In fact, it is already possible to push new branches using the explicit\n>> > --force-with-lease=<branch>:<expect> syntax, so all we do here is make\n>> > this behaviour the default if no explicit \"expect\" value is specified.\n>> \n>> I like the loss of an extra field from \"struct ref\".\n>> \n>> I suspect that the if/else cascade in the loop in apply_cas() can\n>> also be taught that ':' followed by an empty string asks to check\n>> that the target ref does not exist, in order to make it a bit more\n>> useful for folks who do not rely on the \"use the last observed\n>> status of the tracking branch\".\n>> \n>> That would make the \"explicit\" test much less cumbersome to read.\n>\n> Yes, that's nicer and it mirrors the syntax for deleting a remote\n> branch.\n>\n> I've pulled it out as a preparatory step because I like the fact that\n> the \"explicit\" test passes even before the patch that is the main point\n> of the series.\n\nAh, our mails crossed ;-)\n\nThanks, I'll read these three patches.\n"},{"id":"292160","messageId":"xmqqpoq12w93.fsf@gitster.mtv.corp.google.com","threadId":"42912","inReplyTo":"4e07ff23715b53fcd29564be1c74a9f66dd74e1e.1469483499.git.john@keeping.me.uk","subject":"Re: [PATCH v2 2/3] push: add shorthand for --force-with-lease branch creation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-25T22:22:48Z","receivedAt":"2016-07-25T22:23:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Keeping <john@keeping.me.uk> writes:\n\n> Allow the empty string to stand in for the null SHA-1 when pushing a new\n> branch, like we do when deleting branches.\n>\n> This means that the following command ensures that `new-branch` is\n> created on the remote (that is, is must not already exist):\n>\n> \tgit push --force-with-lease=new-branch: origin new-branch\n>\n> Signed-off-by: John Keeping <john@keeping.me.uk>\n> ---\n> New in v2.\n>\n>  Documentation/git-push.txt |  3 ++-\n>  remote.c                   |  2 ++\n>  t/t5533-push-cas.sh        | 12 ++++++++++++\n>  3 files changed, 16 insertions(+), 1 deletion(-)\n>\n> diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt\n> index bf7c9a2..927a034 100644\n> --- a/Documentation/git-push.txt\n> +++ b/Documentation/git-push.txt\n> @@ -201,7 +201,8 @@ if it is going to be updated, by requiring its current value to be\n>  the same as the specified value `<expect>` (which is allowed to be\n>  different from the remote-tracking branch we have for the refname,\n>  or we do not even have to have such a remote-tracking branch when\n> -this form is used).\n> +this form is used).  If `<expect>` is the empty string, then the named ref\n> +must not already exist.\n>  +\n>  Note that all forms other than `--force-with-lease=<refname>:<expect>`\n>  that specifies the expected current value of the ref explicitly are\n> diff --git a/remote.c b/remote.c\n> index a326e4e..af94892 100644\n> --- a/remote.c\n> +++ b/remote.c\n> @@ -2294,6 +2294,8 @@ int parse_push_cas_option(struct push_cas_option *cas, const char *arg, int unse\n>  \tentry = add_cas_entry(cas, arg, colon - arg);\n>  \tif (!*colon)\n>  \t\tentry->use_tracking = 1;\n> +\telse if (!colon[1])\n> +\t\tmemset(entry->expect, 0, sizeof(entry->expect));\n\nhashclr()?\n\n>  \telse if (get_sha1(colon + 1, entry->expect))\n>  \t\treturn error(\"cannot parse expected object name '%s'\", colon + 1);\n>  \treturn 0;\n> diff --git a/t/t5533-push-cas.sh b/t/t5533-push-cas.sh\n> index c732012..5e7f6e9 100755\n> --- a/t/t5533-push-cas.sh\n> +++ b/t/t5533-push-cas.sh\n> @@ -191,4 +191,16 @@ test_expect_success 'cover everything with default force-with-lease (allowed)' '\n>  \ttest_cmp expect actual\n>  '\n>  \n> +test_expect_success 'new branch covered by force-with-lease (explicit)' '\n> +\tsetup_srcdst_basic &&\n> +\t(\n> +\t\tcd dst &&\n> +\t\tgit branch branch master &&\n> +\t\tgit push --force-with-lease=branch: origin branch\n> +\t) &&\n> +\tgit ls-remote dst refs/heads/branch >expect &&\n> +\tgit ls-remote src refs/heads/branch >actual &&\n> +\ttest_cmp expect actual\n> +'\n> +\n>  test_done\n"},{"id":"292184","messageId":"20160726080309.pr46bbtzdvnr7fd3@john.keeping.me.uk","threadId":"42912","inReplyTo":"xmqqpoq12w93.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v2 2/3] push: add shorthand for --force-with-lease branch creation","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2016-07-26T08:03:09Z","receivedAt":"2016-07-26T08:03:26Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"On Mon, Jul 25, 2016 at 03:22:48PM -0700, Junio C Hamano wrote:\n> John Keeping <john@keeping.me.uk> writes:\n> \n> > Allow the empty string to stand in for the null SHA-1 when pushing a new\n> > branch, like we do when deleting branches.\n> >\n> > This means that the following command ensures that `new-branch` is\n> > created on the remote (that is, is must not already exist):\n> >\n> > \tgit push --force-with-lease=new-branch: origin new-branch\n> >\n> > Signed-off-by: John Keeping <john@keeping.me.uk>\n> > ---\n> > New in v2.\n> >\n> >  Documentation/git-push.txt |  3 ++-\n> >  remote.c                   |  2 ++\n> >  t/t5533-push-cas.sh        | 12 ++++++++++++\n> >  3 files changed, 16 insertions(+), 1 deletion(-)\n> >\n> > diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt\n> > index bf7c9a2..927a034 100644\n> > --- a/Documentation/git-push.txt\n> > +++ b/Documentation/git-push.txt\n> > @@ -201,7 +201,8 @@ if it is going to be updated, by requiring its current value to be\n> >  the same as the specified value `<expect>` (which is allowed to be\n> >  different from the remote-tracking branch we have for the refname,\n> >  or we do not even have to have such a remote-tracking branch when\n> > -this form is used).\n> > +this form is used).  If `<expect>` is the empty string, then the named ref\n> > +must not already exist.\n> >  +\n> >  Note that all forms other than `--force-with-lease=<refname>:<expect>`\n> >  that specifies the expected current value of the ref explicitly are\n> > diff --git a/remote.c b/remote.c\n> > index a326e4e..af94892 100644\n> > --- a/remote.c\n> > +++ b/remote.c\n> > @@ -2294,6 +2294,8 @@ int parse_push_cas_option(struct push_cas_option *cas, const char *arg, int unse\n> >  \tentry = add_cas_entry(cas, arg, colon - arg);\n> >  \tif (!*colon)\n> >  \t\tentry->use_tracking = 1;\n> > +\telse if (!colon[1])\n> > +\t\tmemset(entry->expect, 0, sizeof(entry->expect));\n> \n> hashclr()?\n\nYes (and in the following patch as well).  I hadn't realised that\nfunction exists.\n\n> >  \telse if (get_sha1(colon + 1, entry->expect))\n> >  \t\treturn error(\"cannot parse expected object name '%s'\", colon + 1);\n> >  \treturn 0;\n> > diff --git a/t/t5533-push-cas.sh b/t/t5533-push-cas.sh\n> > index c732012..5e7f6e9 100755\n> > --- a/t/t5533-push-cas.sh\n> > +++ b/t/t5533-push-cas.sh\n> > @@ -191,4 +191,16 @@ test_expect_success 'cover everything with default force-with-lease (allowed)' '\n> >  \ttest_cmp expect actual\n> >  '\n> >  \n> > +test_expect_success 'new branch covered by force-with-lease (explicit)' '\n> > +\tsetup_srcdst_basic &&\n> > +\t(\n> > +\t\tcd dst &&\n> > +\t\tgit branch branch master &&\n> > +\t\tgit push --force-with-lease=branch: origin branch\n> > +\t) &&\n> > +\tgit ls-remote dst refs/heads/branch >expect &&\n> > +\tgit ls-remote src refs/heads/branch >actual &&\n> > +\ttest_cmp expect actual\n> > +'\n> > +\n> >  test_done\n"},{"id":"292189","messageId":"57973BAD.2020607@gmail.com","threadId":"42912","inReplyTo":"4e07ff23715b53fcd29564be1c74a9f66dd74e1e.1469483499.git.john@keeping.me.uk","subject":"Re: [PATCH v2 2/3] push: add shorthand for --force-with-lease branch creation","fromName":"Jakub Narębski","fromEmail":"jnareb@gmail.com","sentAt":"2016-07-26T10:30:05Z","receivedAt":"2016-07-26T10:30:31Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"W dniu 2016-07-25 o 23:59, John Keeping pisze:\n\n> +test_expect_success 'new branch covered by force-with-lease (explicit)' '\n> +\tsetup_srcdst_basic &&\n> +\t(\n> +\t\tcd dst &&\n> +\t\tgit branch branch master &&\n> +\t\tgit push --force-with-lease=branch: origin branch\n> +\t) &&\n> +\tgit ls-remote dst refs/heads/branch >expect &&\n> +\tgit ls-remote src refs/heads/branch >actual &&\n> +\ttest_cmp expect actual\n> +'\n\nDo we need to test the negative, that is that if branch is not\nnew it prevents push (e.g. when <branch> is HEAD), or is it\ncovered by other tests?\n\n-- \nJakub Narębski\n\n"},{"id":"292191","messageId":"20160726111911.cehaitav4enas7dm@john.keeping.me.uk","threadId":"42912","inReplyTo":"57973BAD.2020607@gmail.com","subject":"Re: [PATCH v2 2/3] push: add shorthand for --force-with-lease branch creation","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2016-07-26T11:19:11Z","receivedAt":"2016-07-26T11:19:21Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"On Tue, Jul 26, 2016 at 12:30:05PM +0200, Jakub Narębski wrote:\n> W dniu 2016-07-25 o 23:59, John Keeping pisze:\n> \n> > +test_expect_success 'new branch covered by force-with-lease (explicit)' '\n> > +\tsetup_srcdst_basic &&\n> > +\t(\n> > +\t\tcd dst &&\n> > +\t\tgit branch branch master &&\n> > +\t\tgit push --force-with-lease=branch: origin branch\n> > +\t) &&\n> > +\tgit ls-remote dst refs/heads/branch >expect &&\n> > +\tgit ls-remote src refs/heads/branch >actual &&\n> > +\ttest_cmp expect actual\n> > +'\n> \n> Do we need to test the negative, that is that if branch is not\n> new it prevents push (e.g. when <branch> is HEAD), or is it\n> covered by other tests?\n\nIt's covered by a test in patch 3 (at least for the implicit case added\nthere), but I could pull that forwards.  In fact, converting that test\nto the explicit syntax will make it simpler since we won't need to set\nup a non-fast-forward push.\n"},{"id":"292253","messageId":"xmqqwpk8yxvb.fsf@gitster.mtv.corp.google.com","threadId":"42912","inReplyTo":"20160726080309.pr46bbtzdvnr7fd3@john.keeping.me.uk","subject":"Re: [PATCH v2 2/3] push: add shorthand for --force-with-lease branch creation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-26T19:59:04Z","receivedAt":"2016-07-26T19:59:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Keeping <john@keeping.me.uk> writes:\n\n>> > @@ -2294,6 +2294,8 @@ int parse_push_cas_option(struct push_cas_option *cas, const char *arg, int unse\n>> >  \tentry = add_cas_entry(cas, arg, colon - arg);\n>> >  \tif (!*colon)\n>> >  \t\tentry->use_tracking = 1;\n>> > +\telse if (!colon[1])\n>> > +\t\tmemset(entry->expect, 0, sizeof(entry->expect));\n>> \n>> hashclr()?\n>\n> Yes (and in the following patch as well).  I hadn't realised that\n> function exists.\n\nThanks; I've locally tweaked these two patches; the interdiff looks\nlike this.\n\n remote.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex e8b7bac..7eaf3c8 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -2304,7 +2304,7 @@ int parse_push_cas_option(struct push_cas_option *cas, const char *arg, int unse\n \tif (!*colon)\n \t\tentry->use_tracking = 1;\n \telse if (!colon[1])\n-\t\tmemset(entry->expect, 0, sizeof(entry->expect));\n+\t\thashclr(entry->expect);\n \telse if (get_sha1(colon + 1, entry->expect))\n \t\treturn error(\"cannot parse expected object name '%s'\", colon + 1);\n \treturn 0;\n@@ -2354,7 +2354,7 @@ static void apply_cas(struct push_cas_option *cas,\n \t\tif (!entry->use_tracking)\n \t\t\thashcpy(ref->old_oid_expect.hash, cas->entry[i].expect);\n \t\telse if (remote_tracking(remote, ref->name, &ref->old_oid_expect))\n-\t\t\tmemset(&ref->old_oid_expect, 0, sizeof(ref->old_oid_expect));\n+\t\t\thashclr(ref->old_oid_expect.hash);\n \t\treturn;\n \t}\n \n@@ -2364,7 +2364,7 @@ static void apply_cas(struct push_cas_option *cas,\n \n \tref->expect_old_sha1 = 1;\n \tif (remote_tracking(remote, ref->name, &ref->old_oid_expect))\n-\t\tmemset(&ref->old_oid_expect, 0, sizeof(ref->old_oid_expect));\n+\t\thashclr(ref->old_oid_expect.hash);\n }\n \n void apply_push_cas(struct push_cas_option *cas,\n"},{"id":"292261","messageId":"20160726204253.ciumvungwfwaw6el@john.keeping.me.uk","threadId":"42912","inReplyTo":"xmqqwpk8yxvb.fsf@gitster.mtv.corp.google.com","subject":"Re: [PATCH v2 2/3] push: add shorthand for --force-with-lease branch creation","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2016-07-26T20:42:53Z","receivedAt":"2016-07-26T20:43:07Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"On Tue, Jul 26, 2016 at 12:59:04PM -0700, Junio C Hamano wrote:\n> John Keeping <john@keeping.me.uk> writes:\n> \n> >> > @@ -2294,6 +2294,8 @@ int parse_push_cas_option(struct push_cas_option *cas, const char *arg, int unse\n> >> >  \tentry = add_cas_entry(cas, arg, colon - arg);\n> >> >  \tif (!*colon)\n> >> >  \t\tentry->use_tracking = 1;\n> >> > +\telse if (!colon[1])\n> >> > +\t\tmemset(entry->expect, 0, sizeof(entry->expect));\n> >> \n> >> hashclr()?\n> >\n> > Yes (and in the following patch as well).  I hadn't realised that\n> > function exists.\n> \n> Thanks; I've locally tweaked these two patches; the interdiff looks\n> like this.\n\nThanks.  I'm about to send v3 anyway to pull a test forward to address\nJakub's comment.  I also used oidclr() for the last two changes below.\n\n>  remote.c | 6 +++---\n>  1 file changed, 3 insertions(+), 3 deletions(-)\n> \n> diff --git a/remote.c b/remote.c\n> index e8b7bac..7eaf3c8 100644\n> --- a/remote.c\n> +++ b/remote.c\n> @@ -2304,7 +2304,7 @@ int parse_push_cas_option(struct push_cas_option *cas, const char *arg, int unse\n>  \tif (!*colon)\n>  \t\tentry->use_tracking = 1;\n>  \telse if (!colon[1])\n> -\t\tmemset(entry->expect, 0, sizeof(entry->expect));\n> +\t\thashclr(entry->expect);\n>  \telse if (get_sha1(colon + 1, entry->expect))\n>  \t\treturn error(\"cannot parse expected object name '%s'\", colon + 1);\n>  \treturn 0;\n> @@ -2354,7 +2354,7 @@ static void apply_cas(struct push_cas_option *cas,\n>  \t\tif (!entry->use_tracking)\n>  \t\t\thashcpy(ref->old_oid_expect.hash, cas->entry[i].expect);\n>  \t\telse if (remote_tracking(remote, ref->name, &ref->old_oid_expect))\n> -\t\t\tmemset(&ref->old_oid_expect, 0, sizeof(ref->old_oid_expect));\n> +\t\t\thashclr(ref->old_oid_expect.hash);\n>  \t\treturn;\n>  \t}\n>  \n> @@ -2364,7 +2364,7 @@ static void apply_cas(struct push_cas_option *cas,\n>  \n>  \tref->expect_old_sha1 = 1;\n>  \tif (remote_tracking(remote, ref->name, &ref->old_oid_expect))\n> -\t\tmemset(&ref->old_oid_expect, 0, sizeof(ref->old_oid_expect));\n> +\t\thashclr(ref->old_oid_expect.hash);\n>  }\n>  \n>  void apply_push_cas(struct push_cas_option *cas,\n"},{"id":"292264","messageId":"cover.1469565810.git.john@keeping.me.uk","threadId":"42912","inReplyTo":"cover.1469483499.git.john@keeping.me.uk","subject":"[PATCH v3 0/3] push: allow pushing new branches with --force-with-lease","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2016-07-26T20:44:42Z","receivedAt":"2016-07-26T20:45:19Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"Changes in v3:\n- Use hashclr() and oidclr() where appropriate instead of memset()\n- Pull a test forward from patch 3 to patch 2 \n\nJohn Keeping (3):\n  Documentation/git-push: fix placeholder formatting\n  push: add shorthand for --force-with-lease branch creation\n  push: allow pushing new branches with --force-with-lease\n\n Documentation/git-push.txt |  5 +++--\n remote.c                   |  9 +++++----\n remote.h                   |  1 -\n t/t5533-push-cas.sh        | 38 ++++++++++++++++++++++++++++++++++++++\n 4 files changed, 46 insertions(+), 7 deletions(-)\n\n-- \n2.9.2.639.g855ae9f\n"},{"id":"292265","messageId":"bb37a70b0a47a72d38e29d34b3dd66ef9f018655.1469565810.git.john@keeping.me.uk","threadId":"42912","inReplyTo":"cover.1469565810.git.john@keeping.me.uk","subject":"[PATCH v3 1/3] Documentation/git-push: fix placeholder formatting","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2016-07-26T20:44:43Z","receivedAt":"2016-07-26T20:45:22Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"Format the placeholder as monospace to match other occurrences in this\nfile and obey CodingGuidelines.\n\nSigned-off-by: John Keeping <john@keeping.me.uk>\n---\nNo changes in v3.\n\n Documentation/git-push.txt | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-push.txt b/Documentation/git-push.txt\nindex 93c3527..bf7c9a2 100644\n--- a/Documentation/git-push.txt\n+++ b/Documentation/git-push.txt\n@@ -198,7 +198,7 @@ branch we have for it.\n +\n `--force-with-lease=<refname>:<expect>` will protect the named ref (alone),\n if it is going to be updated, by requiring its current value to be\n-the same as the specified value <expect> (which is allowed to be\n+the same as the specified value `<expect>` (which is allowed to be\n different from the remote-tracking branch we have for the refname,\n or we do not even have to have such a remote-tracking branch when\n this form is used).\n-- \n2.9.2.639.g855ae9f\n\n"},{"id":"292266","messageId":"0db0f8551d59e91cf2ad9a9853cf0dfd2750b748.1469565810.git.john@keeping.me.uk","threadId":"42912","inReplyTo":"cover.1469565810.git.john@keeping.me.uk","subject":"[PATCH v3 2/3] push: add shorthand for --force-with-lease branch creation","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2016-07-26T20:44:44Z","receivedAt":"2016-07-26T20:45:27Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"Allow the empty string to stand in for the null SHA-1 when pushing a new\nbranch, like we do when deleting branches.\n\nThis means that the following command ensures that `new-branch` is\ncreated on the remote (that is, is must not already exist):\n\n\tgit push --force-with-lease=new-branch: origin new-branch\n\nSigned-off-by: John Keeping <john@keeping.me.uk>\n---\nChanges in v3:\n- use hashclr()\n- pull 'new branch already exists' test forward from patch 3 and use\n  explicit --force-with-lease syntax\n\n Documentation/git-push.txt |  3 ++-\n remote.c                   |  2 ++\n t/t5533-push-cas.sh        | 26 ++++++++++++++++++++++++++\n 3 files changed, 30 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-push.txt b/Documentation/git-push.txt\nindex bf7c9a2..927a034 100644\n--- a/Documentation/git-push.txt\n+++ b/Documentation/git-push.txt\n@@ -201,7 +201,8 @@ if it is going to be updated, by requiring its current value to be\n the same as the specified value `<expect>` (which is allowed to be\n different from the remote-tracking branch we have for the refname,\n or we do not even have to have such a remote-tracking branch when\n-this form is used).\n+this form is used).  If `<expect>` is the empty string, then the named ref\n+must not already exist.\n +\n Note that all forms other than `--force-with-lease=<refname>:<expect>`\n that specifies the expected current value of the ref explicitly are\ndiff --git a/remote.c b/remote.c\nindex a326e4e..42c4a34 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -2294,6 +2294,8 @@ int parse_push_cas_option(struct push_cas_option *cas, const char *arg, int unse\n \tentry = add_cas_entry(cas, arg, colon - arg);\n \tif (!*colon)\n \t\tentry->use_tracking = 1;\n+\telse if (!colon[1])\n+\t\thashclr(entry->expect);\n \telse if (get_sha1(colon + 1, entry->expect))\n \t\treturn error(\"cannot parse expected object name '%s'\", colon + 1);\n \treturn 0;\ndiff --git a/t/t5533-push-cas.sh b/t/t5533-push-cas.sh\nindex c732012..ed631c3 100755\n--- a/t/t5533-push-cas.sh\n+++ b/t/t5533-push-cas.sh\n@@ -191,4 +191,30 @@ test_expect_success 'cover everything with default force-with-lease (allowed)' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'new branch covered by force-with-lease (explicit)' '\n+\tsetup_srcdst_basic &&\n+\t(\n+\t\tcd dst &&\n+\t\tgit branch branch master &&\n+\t\tgit push --force-with-lease=branch: origin branch\n+\t) &&\n+\tgit ls-remote dst refs/heads/branch >expect &&\n+\tgit ls-remote src refs/heads/branch >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'new branch already exists' '\n+\tsetup_srcdst_basic &&\n+\t(\n+\t\tcd src &&\n+\t\tgit checkout -b branch master &&\n+\t\ttest_commit c\n+\t) &&\n+\t(\n+\t\tcd dst &&\n+\t\tgit branch branch master &&\n+\t\ttest_must_fail git push --force-with-lease=branch: origin branch\n+\t)\n+'\n+\n test_done\n-- \n2.9.2.639.g855ae9f\n\n"},{"id":"292267","messageId":"f2bf19fd44684202177ae09d034756e0a68e2482.1469565810.git.john@keeping.me.uk","threadId":"42912","inReplyTo":"cover.1469565810.git.john@keeping.me.uk","subject":"[PATCH v3 3/3] push: allow pushing new branches with --force-with-lease","fromName":"John Keeping","fromEmail":"john@keeping.me.uk","sentAt":"2016-07-26T20:44:45Z","receivedAt":"2016-07-26T20:47:08Z","isPatch":true,"sender":{"key":"john@keeping.me.uk","avatar":"https://avatars.githubusercontent.com/u/1702081?v=4"},"body":"If there is no upstream information for a branch, it is likely that it\nis newly created and can safely be pushed under the normal fast-forward\nrules.  Relax the --force-with-lease check so that we do not reject\nthese branches immediately but rather attempt to push them as new\nbranches, using the null SHA-1 as the expected value.\n\nIn fact, it is already possible to push new branches using the explicit\n--force-with-lease=<branch>:<expect> syntax, so all we do here is make\nthis behaviour the default if no explicit \"expect\" value is specified.\n\nSigned-off-by: John Keeping <john@keeping.me.uk>\n---\nChanges in v3:\n- use oidclr()\n- final test is now added in the previous patch and now uses the\n  explicit --force-with-lease syntax\n\n remote.c            |  7 +++----\n remote.h            |  1 -\n t/t5533-push-cas.sh | 12 ++++++++++++\n 3 files changed, 15 insertions(+), 5 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex 42c4a34..d29850a 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -1544,8 +1544,7 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,\n \t\t * branch.\n \t\t */\n \t\tif (ref->expect_old_sha1) {\n-\t\t\tif (ref->expect_old_no_trackback ||\n-\t\t\t    oidcmp(&ref->old_oid, &ref->old_oid_expect))\n+\t\t\tif (oidcmp(&ref->old_oid, &ref->old_oid_expect))\n \t\t\t\treject_reason = REF_STATUS_REJECT_STALE;\n \t\t\telse\n \t\t\t\t/* If the ref isn't stale then force the update. */\n@@ -2345,7 +2344,7 @@ static void apply_cas(struct push_cas_option *cas,\n \t\tif (!entry->use_tracking)\n \t\t\thashcpy(ref->old_oid_expect.hash, cas->entry[i].expect);\n \t\telse if (remote_tracking(remote, ref->name, &ref->old_oid_expect))\n-\t\t\tref->expect_old_no_trackback = 1;\n+\t\t\toidclr(&ref->old_oid_expect);\n \t\treturn;\n \t}\n \n@@ -2355,7 +2354,7 @@ static void apply_cas(struct push_cas_option *cas,\n \n \tref->expect_old_sha1 = 1;\n \tif (remote_tracking(remote, ref->name, &ref->old_oid_expect))\n-\t\tref->expect_old_no_trackback = 1;\n+\t\toidclr(&ref->old_oid_expect);\n }\n \n void apply_push_cas(struct push_cas_option *cas,\ndiff --git a/remote.h b/remote.h\nindex c21fd37..9248811 100644\n--- a/remote.h\n+++ b/remote.h\n@@ -89,7 +89,6 @@ struct ref {\n \t\tforce:1,\n \t\tforced_update:1,\n \t\texpect_old_sha1:1,\n-\t\texpect_old_no_trackback:1,\n \t\tdeletion:1,\n \t\tmatched:1;\n \ndiff --git a/t/t5533-push-cas.sh b/t/t5533-push-cas.sh\nindex ed631c3..09899af 100755\n--- a/t/t5533-push-cas.sh\n+++ b/t/t5533-push-cas.sh\n@@ -191,6 +191,18 @@ test_expect_success 'cover everything with default force-with-lease (allowed)' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'new branch covered by force-with-lease' '\n+\tsetup_srcdst_basic &&\n+\t(\n+\t\tcd dst &&\n+\t\tgit branch branch master &&\n+\t\tgit push --force-with-lease=branch origin branch\n+\t) &&\n+\tgit ls-remote dst refs/heads/branch >expect &&\n+\tgit ls-remote src refs/heads/branch >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'new branch covered by force-with-lease (explicit)' '\n \tsetup_srcdst_basic &&\n \t(\n-- \n2.9.2.639.g855ae9f\n\n"},{"id":"292283","messageId":"xmqqvazsxfk7.fsf@gitster.mtv.corp.google.com","threadId":"42912","inReplyTo":"20160726204253.ciumvungwfwaw6el@john.keeping.me.uk","subject":"Re: [PATCH v2 2/3] push: add shorthand for --force-with-lease branch creation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-07-26T21:19:52Z","receivedAt":"2016-07-26T21:21:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"John Keeping <john@keeping.me.uk> writes:\n\n> Thanks.  I'm about to send v3 anyway to pull a test forward to address\n> Jakub's comment.  I also used oidclr() for the last two changes below.\n\nWill replace with v3.\n\nI think v3 is ready to advance to 'next'.  Let's see if we get\nfurther comments from others for a few days.\n\nThanks.\n"}]}