From: Srinidhi Kaushik <shrinidhi.kaushik@gmail.com>
To: git@vger.kernel.org
Cc: Johannes Schindelin <Johannes.Schindelin@gmx.de>,
Srinidhi Kaushik <shrinidhi.kaushik@gmail.com>
Subject: [PATCH] push: make `--force-with-lease[=<ref>]` safer
Date: Sat, 5 Sep 2020 00:21:47 +0530 [thread overview]
Message-ID: <20200904185147.77439-1-shrinidhi.kaushik@gmail.com> (raw)
The `--force-with-lease` option in `git-push`, makes sure that
refs on remote aren't clobbered by unexpected changes when the
"<expect>" ref value is explicitly specified.
For other cases (i.e., `--force-with-lease[=<ref>]`) where the tip
of the remote tracking branch is populated as the "<expect>" value,
there is a possibility of allowing unwanted overwrites on the remote
side when some tools that implicitly fetch remote-tracking refs in
the background are used with the repository. If a remote-tracking ref
was updated when a rewrite is happening locally and if those changes
are pushed by omitting the "<expect>" value in `--force-with-lease`,
any new changes from the updated tip will be lost locally and will
be overwritten on the remote.
This problem can be addressed by checking the `reflog` of the branch
that is being pushed and verify if there in a entry with the remote
tracking ref. By running this check, we can ensure that refs being
are fetched in the background while a "lease" is being held are not
overlooked before a push, and any new changes can be acknowledged
and (if necessary) integrated locally.
The new check will cause `git-push` to fail if it detects the presence
of any updated refs that we do not have locally and reject the push
stating `implicit fetch` as the reason.
An experimental configuration setting: `push.rejectImplicitFetch`
which defaults to `true` (when `features.experimental` is enabled)
has been added, to allow `git-push` to reject a push if the check
fails.
Signed-off-by: Srinidhi Kaushik <shrinidhi.kaushik@gmail.com>
---
Hello,
I picked this up from #leftoverbits over at GitHub [1] from the open
issues list. This idea [2], for a safer `--force-with-lease` was
originally proposed by Johannes on the mailing list.
[1]: https://github.com/gitgitgadget/git/issues/640
[2]: https://lore.kernel.org/git/nycvar.QRO.7.76.6.1808272306271.73@tvgsbejvaqbjf.bet/
Thanks.
Documentation/config/feature.txt | 3 +
Documentation/config/push.txt | 14 +++++
Documentation/git-push.txt | 6 ++
builtin/send-pack.c | 5 ++
remote.c | 96 +++++++++++++++++++++++++++++---
remote.h | 4 +-
send-pack.c | 1 +
t/t5533-push-cas.sh | 86 ++++++++++++++++++++++++++++
transport-helper.c | 5 ++
transport.c | 5 ++
10 files changed, 217 insertions(+), 8 deletions(-)
diff --git a/Documentation/config/feature.txt b/Documentation/config/feature.txt
index c0cbf2bb1c..f93e9fd898 100644
--- a/Documentation/config/feature.txt
+++ b/Documentation/config/feature.txt
@@ -18,6 +18,9 @@ skipping more commits at a time, reducing the number of round trips.
* `protocol.version=2` speeds up fetches from repositories with many refs by
allowing the client to specify which refs to list before the server lists
them.
++
+* `push.rejectImplicitFetch=true` runs additional checks for linkgit:git-push[1]
+`--force-with-lease` to mitigate implicit updates of remote-tracking refs.
feature.manyFiles::
Enable config options that optimize for repos with many files in the
diff --git a/Documentation/config/push.txt b/Documentation/config/push.txt
index f5e5b38c68..1a7184034d 100644
--- a/Documentation/config/push.txt
+++ b/Documentation/config/push.txt
@@ -114,3 +114,17 @@ 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.rejectImplicitFetch::
+ If set to `true`, runs additional checks for the `--force-with-lease`
+ option when used with linkgit:git-push[1] if the expected value for
+ the remote ref is unspecified (`--force-with-lease[=<ref>]`), and
+ instead asked depend on the current value of the remote-tracking ref.
+ The check ensures that the commit at the tip of the remote-tracking
+ branch -- which may have been implicitly updated by tools that fetch
+ remote refs by running linkgit:git-fetch[1] in the background -- has
+ been integrated locally, when holding the "lease". If the new changes
+ from such remote-tracking refs have not been updated locally before
+ pushing, linkgit:git-push[1] will fail indicating the reject reason
+ as `implicit fetch`. Enabling `feature.experimental` makes this option
+ default to `true`.
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 3b8053447e..2176a743f3 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -320,6 +320,12 @@ 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, setting the (experimental) `push.rejectImplicitFetch` option
+to `true` will ensure changes from remote-tracking refs that are updated in the
+background using linkgit:git-fetch[1] are accounted for (either by integrating
+them locally, or explicitly specifying an overwrite), by rejecting to update
+such refs.
-f::
--force::
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 2b9610f121..6500a8267a 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -69,6 +69,11 @@ static void print_helper_status(struct ref *ref)
msg = "stale info";
break;
+ case REF_STATUS_REJECT_IMPLICIT_FETCH:
+ res = "error";
+ msg = "implicit fetch";
+ break;
+
case REF_STATUS_REJECT_ALREADY_EXISTS:
res = "error";
msg = "already exists";
diff --git a/remote.c b/remote.c
index c5ed74f91c..ee2dedd15b 100644
--- a/remote.c
+++ b/remote.c
@@ -49,6 +49,8 @@ static const char *pushremote_name;
static struct rewrites rewrites;
static struct rewrites rewrites_push;
+static struct object_id cas_reflog_check_oid;
+
static int valid_remote(const struct remote *remote)
{
return (!!remote->url) || (!!remote->foreign_vcs);
@@ -1446,6 +1448,22 @@ int match_push_refs(struct ref *src, struct ref **dst,
return 0;
}
+/*
+ * Consider `push.rejectImplicitFetch` to be set to true if experimental
+ * features are enabled; use user-defined value if set explicitly.
+ */
+int reject_implicit_fetch()
+{
+ int conf = 0;
+ if (!git_config_get_bool("push.rejectImplicitFetch", &conf))
+ return conf;
+
+ if (!git_config_get_bool("feature.experimental", &conf))
+ return conf;
+
+ return conf;
+}
+
void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
int force_update)
{
@@ -1471,16 +1489,21 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
* If the remote ref has moved and is now different
* from what we expect, reject any push.
*
- * It also is an error if the user told us to check
- * with the remote-tracking branch to find the value
- * to expect, but we did not have such a tracking
- * branch.
+ * It also is an error if the user told us to check with the
+ * remote-tracking branch to find the value to expect, but we
+ * did not have such a tracking branch, or we have one that
+ * has new changes.
*/
if (ref->expect_old_sha1) {
if (!oideq(&ref->old_oid, &ref->old_oid_expect))
reject_reason = REF_STATUS_REJECT_STALE;
+ else if (reject_implicit_fetch() && ref->implicit_fetch)
+ reject_reason = REF_STATUS_REJECT_IMPLICIT_FETCH;
else
- /* If the ref isn't stale then force the update. */
+ /*
+ * If the ref isn't stale, or there was no
+ * implicit fetch, force the update.
+ */
force_ref_update = 1;
}
@@ -2272,23 +2295,67 @@ static int remote_tracking(struct remote *remote, const char *refname,
return 0;
}
+static int oid_in_reflog_ent(struct object_id *ooid, struct object_id *noid,
+ const char *ident, timestamp_t timestamp, int tz,
+ const char *message, void *cb_data)
+{
+ return oideq(noid, &cas_reflog_check_oid);
+}
+
+/*
+ * Iterate through the reflog of a local branch and check if the tip of the
+ * remote-tracking branch is reachable from one of the entries.
+ */
+static int remote_ref_in_reflog(const struct object_id *r_oid,
+ const struct object_id *l_oid,
+ const char *local_ref_name)
+{
+ int ret = 0;
+ cas_reflog_check_oid = *r_oid;
+
+ struct commit *r_commit, *l_commit;
+ l_commit = lookup_commit_reference(the_repository, l_oid);
+ r_commit = lookup_commit_reference(the_repository, r_oid);
+
+ /*
+ * If the remote-tracking ref is an ancestor of the local ref (a merge,
+ * for instance) there is no need to iterate through the reflog entries
+ * to ensure reachability; it can be skipped to return early instead.
+ */
+ ret = (r_commit && l_commit) ? in_merge_bases(r_commit, l_commit) : 0;
+ if (ret)
+ goto skip;
+
+ ret = for_each_reflog_ent_reverse(local_ref_name,
+ oid_in_reflog_ent,
+ NULL);
+skip:
+ return ret;
+}
+
static void apply_cas(struct push_cas_option *cas,
struct remote *remote,
struct ref *ref)
{
- int i;
+ int i, do_reflog_check = 0;
+ struct object_id oid;
+ struct ref *local_ref = get_local_ref(ref->name);
/* Find an explicit --<option>=<name>[:<value>] entry */
for (i = 0; i < cas->nr; i++) {
struct push_cas *entry = &cas->entry[i];
if (!refname_match(entry->refname, ref->name))
continue;
+
ref->expect_old_sha1 = 1;
if (!entry->use_tracking)
oidcpy(&ref->old_oid_expect, &entry->expect);
else if (remote_tracking(remote, ref->name, &ref->old_oid_expect))
oidclr(&ref->old_oid_expect);
- return;
+ else
+ do_reflog_check = 1;
+
+ goto reflog_check;
}
/* Are we using "--<option>" to cover all? */
@@ -2298,6 +2365,21 @@ static void apply_cas(struct push_cas_option *cas,
ref->expect_old_sha1 = 1;
if (remote_tracking(remote, ref->name, &ref->old_oid_expect))
oidclr(&ref->old_oid_expect);
+ else
+ do_reflog_check = 1;
+
+reflog_check:
+ /*
+ * For cases where "--force-with-lease[=<refname>]" i.e., when the
+ * "<expect>" value is unspecified, run additional checks to verify
+ * if the tip of the remote-tracking branch (if implicitly updated
+ * when a "lease" is being held) is reachable from at least one entry
+ * in the reflog of the local branch that is being pushed, ensuring
+ * new changes (if any) have been integrated locally.
+ */
+ if (do_reflog_check && local_ref && !read_ref(local_ref->name, &oid))
+ ref->implicit_fetch = !remote_ref_in_reflog(&ref->old_oid, &oid,
+ local_ref->name);
}
void apply_push_cas(struct push_cas_option *cas,
diff --git a/remote.h b/remote.h
index 5e3ea5a26d..f859fa5fed 100644
--- a/remote.h
+++ b/remote.h
@@ -104,7 +104,8 @@ struct ref {
forced_update:1,
expect_old_sha1:1,
exact_oid:1,
- deletion:1;
+ deletion:1,
+ implicit_fetch:1;
enum {
REF_NOT_MATCHED = 0, /* initial value */
@@ -133,6 +134,7 @@ struct ref {
REF_STATUS_REJECT_FETCH_FIRST,
REF_STATUS_REJECT_NEEDS_FORCE,
REF_STATUS_REJECT_STALE,
+ REF_STATUS_REJECT_IMPLICIT_FETCH,
REF_STATUS_REJECT_SHALLOW,
REF_STATUS_UPTODATE,
REF_STATUS_REMOTE_REJECT,
diff --git a/send-pack.c b/send-pack.c
index 632f1580ca..fe7f14add4 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -240,6 +240,7 @@ static int check_to_send_update(const struct ref *ref, const struct send_pack_ar
case REF_STATUS_REJECT_FETCH_FIRST:
case REF_STATUS_REJECT_NEEDS_FORCE:
case REF_STATUS_REJECT_STALE:
+ case REF_STATUS_REJECT_IMPLICIT_FETCH:
case REF_STATUS_REJECT_NODELETE:
return CHECK_REF_STATUS_REJECTED;
case REF_STATUS_UPTODATE:
diff --git a/t/t5533-push-cas.sh b/t/t5533-push-cas.sh
index 0b0eb1d025..840b2a95f9 100755
--- a/t/t5533-push-cas.sh
+++ b/t/t5533-push-cas.sh
@@ -13,6 +13,41 @@ setup_srcdst_basic () {
)
}
+setup_implicit_fetch () {
+ 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 &&
+ git push
+ ) &&
+ (
+ cd dup &&
+ git fetch &&
+ git merge origin/master &&
+ test_commit B &&
+ git switch -c branch master~1 &&
+ test_commit C &&
+ test_commit D &&
+ git push --all
+ ) &&
+ (
+ cd src &&
+ git switch master &&
+ git fetch --all &&
+ git branch branch --track origin/branch &&
+ git merge origin/master
+ ) &&
+ (
+ cd dup &&
+ git switch master &&
+ test_commit E &&
+ git push origin master:master
+ )
+}
+
test_expect_success setup '
# create template repository
test_commit A &&
@@ -256,4 +291,55 @@ test_expect_success 'background updates of REMOTE can be mitigated with a non-up
)
'
+test_expect_success 'implicit updates to remote-tracking refs with `push.rejectImplicitFetch` set (protected, all refs)' '
+ setup_implicit_fetch &&
+ test_when_finished "rm -fr dst src dup" &&
+ git ls-remote dst refs/heads/master >expect.master &&
+ git ls-remote dst refs/heads/master >expect.branch &&
+ (
+ cd src &&
+ git switch master &&
+ test_commit G &&
+ git switch branch &&
+ test_commit H &&
+ git fetch --all &&
+ git config --local feature.experimental true &&
+ test_must_fail git push --force-with-lease --all 2>err &&
+ grep "implicit fetch" err
+ ) &&
+ git ls-remote dst refs/heads/master >actual.master &&
+ git ls-remote dst refs/heads/master >actual.branch &&
+ test_cmp expect.master actual.master &&
+ test_cmp expect.branch actual.branch &&
+ (
+ cd src &&
+ git config --local feature.experimental false &&
+ git push --force-with-lease --all 2>err &&
+ grep "forced update" err
+ )
+'
+
+test_expect_success 'implicit updates to remote-tracking refs with `push.rejectImplicitFetch` set (protected, specific ref)' '
+ setup_implicit_fetch &&
+ git ls-remote dst refs/heads/master >actual &&
+ (
+ cd src &&
+ git switch branch &&
+ test_commit F &&
+ git switch master &&
+ test_commit G &&
+ git fetch &&
+ git config --local push.rejectImplicitFetch true &&
+ test_must_fail git push --force-with-lease=master --all 2>err &&
+ grep "implicit fetch" err
+ ) &&
+ git ls-remote dst refs/heads/master >expect &&
+ test_cmp expect actual &&
+ (
+ cd src &&
+ git push --force --force-with-lease --all 2>err &&
+ grep "forced update" err
+ )
+'
+
test_done
diff --git a/transport-helper.c b/transport-helper.c
index c52c99d829..75b4c1b758 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -779,6 +779,10 @@ static int push_update_ref_status(struct strbuf *buf,
status = REF_STATUS_REJECT_STALE;
FREE_AND_NULL(msg);
}
+ else if (!strcmp(msg, "ignored fetch")) {
+ status = REF_STATUS_REJECT_IMPLICIT_FETCH;
+ FREE_AND_NULL(msg);
+ }
else if (!strcmp(msg, "forced update")) {
forced = 1;
FREE_AND_NULL(msg);
@@ -896,6 +900,7 @@ static int push_refs_with_push(struct transport *transport,
switch (ref->status) {
case REF_STATUS_REJECT_NONFASTFORWARD:
case REF_STATUS_REJECT_STALE:
+ case REF_STATUS_REJECT_IMPLICIT_FETCH:
case REF_STATUS_REJECT_ALREADY_EXISTS:
if (atomic) {
reject_atomic_push(remote_refs, mirror);
diff --git a/transport.c b/transport.c
index 43e24bf1e5..588575498f 100644
--- a/transport.c
+++ b/transport.c
@@ -567,6 +567,10 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count,
print_ref_status('!', "[rejected]", ref, ref->peer_ref,
"stale info", porcelain, summary_width);
break;
+ case REF_STATUS_REJECT_IMPLICIT_FETCH:
+ print_ref_status('!', "[rejected]", ref, ref->peer_ref,
+ "implicit fetch", porcelain, summary_width);
+ break;
case REF_STATUS_REJECT_SHALLOW:
print_ref_status('!', "[rejected]", ref, ref->peer_ref,
"new shallow roots not allowed",
@@ -1101,6 +1105,7 @@ static int run_pre_push_hook(struct transport *transport,
if (!r->peer_ref) continue;
if (r->status == REF_STATUS_REJECT_NONFASTFORWARD) continue;
if (r->status == REF_STATUS_REJECT_STALE) continue;
+ if (r->status == REF_STATUS_REJECT_IMPLICIT_FETCH) continue;
if (r->status == REF_STATUS_UPTODATE) continue;
strbuf_reset(&buf);
--
2.28.0
next reply other threads:[~2020-09-04 18:53 UTC|newest]
Thread overview: 120+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-04 18:51 Srinidhi Kaushik [this message]
2020-09-07 15:23 ` [PATCH] push: make `--force-with-lease[=<ref>]` safer Phillip Wood
2020-09-08 15:48 ` Srinidhi Kaushik
2020-09-07 16:14 ` Junio C Hamano
2020-09-08 16:00 ` Srinidhi Kaushik
2020-09-08 21:00 ` Junio C Hamano
2020-09-07 19:45 ` Johannes Schindelin
2020-09-08 15:58 ` Junio C Hamano
2020-09-09 3:40 ` Johannes Schindelin
2020-09-08 16:59 ` Srinidhi Kaushik
2020-09-16 11:55 ` Johannes Schindelin
2020-09-08 19:34 ` Junio C Hamano
2020-09-09 3:44 ` Johannes Schindelin
2020-09-10 10:22 ` Johannes Schindelin
2020-09-10 14:44 ` Srinidhi Kaushik
2020-09-11 22:16 ` Johannes Schindelin
2020-09-14 11:06 ` Srinidhi Kaushik
2020-09-14 20:08 ` Junio C Hamano
2020-09-16 5:31 ` Srinidhi Kaushik
2020-09-16 10:20 ` Johannes Schindelin
2020-09-19 17:48 ` Junio C Hamano
2020-09-10 14:46 ` Junio C Hamano
2020-09-11 22:17 ` Johannes Schindelin
2020-09-14 20:07 ` Junio C Hamano
2020-09-12 15:04 ` [PATCH v2 0/2] push: make "--force-with-lease" safer Srinidhi Kaushik
2020-09-12 15:04 ` [PATCH v2 1/2] push: add "--[no-]force-if-includes" Srinidhi Kaushik
2020-09-12 18:20 ` Junio C Hamano
2020-09-12 21:25 ` Srinidhi Kaushik
2020-09-12 15:04 ` [PATCH v2 2/2] push: enable "forceIfIncludesWithLease" by default Srinidhi Kaushik
2020-09-12 18:22 ` Junio C Hamano
2020-09-12 18:15 ` [PATCH v2 0/2] push: make "--force-with-lease" safer Junio C Hamano
2020-09-12 21:03 ` Srinidhi Kaushik
2020-09-13 14:54 ` [PATCH v3 0/7] push: add "--[no-]force-if-includes" Srinidhi Kaushik
2020-09-13 14:54 ` [PATCH v3 1/7] remote: add reflog check for "force-if-includes" Srinidhi Kaushik
2020-09-14 20:17 ` Junio C Hamano
2020-09-16 10:51 ` Srinidhi Kaushik
2020-09-14 20:31 ` Junio C Hamano
2020-09-14 21:13 ` Junio C Hamano
2020-09-16 12:35 ` Johannes Schindelin
2020-09-19 17:01 ` Srinidhi Kaushik
2020-09-13 14:54 ` [PATCH v3 2/7] transport: add flag for "--[no-]force-if-includes" Srinidhi Kaushik
2020-09-13 14:54 ` [PATCH v3 3/7] send-pack: check ref status for "force-if-includes" Srinidhi Kaushik
2020-09-13 14:54 ` [PATCH v3 4/7] transport-helper: update " Srinidhi Kaushik
2020-09-13 14:54 ` [PATCH v3 5/7] builtin/push: add option "--[no-]force-if-includes" Srinidhi Kaushik
2020-09-16 12:36 ` Johannes Schindelin
2020-09-13 14:54 ` [PATCH v3 6/7] doc: add reference for "--[no-]force-if-includes" Srinidhi Kaushik
2020-09-14 21:01 ` Junio C Hamano
2020-09-16 5:35 ` Srinidhi Kaushik
2020-09-13 14:54 ` [PATCH v3 7/7] t: add tests for "force-if-includes" Srinidhi Kaushik
2020-09-16 12:47 ` [PATCH v3 0/7] push: add "--[no-]force-if-includes" Johannes Schindelin
2020-09-19 17:03 ` [PATCH v4 0/3] " Srinidhi Kaushik
2020-09-19 17:03 ` [PATCH v4 1/3] push: add reflog check for "--force-if-includes" Srinidhi Kaushik
2020-09-19 20:03 ` Junio C Hamano
2020-09-21 8:42 ` Srinidhi Kaushik
2020-09-21 18:48 ` Junio C Hamano
2020-09-23 10:22 ` Srinidhi Kaushik
2020-09-23 16:47 ` Junio C Hamano
2020-09-21 13:19 ` Phillip Wood
2020-09-21 16:12 ` Junio C Hamano
2020-09-21 18:11 ` Junio C Hamano
2020-09-23 10:27 ` Srinidhi Kaushik
2020-09-19 17:03 ` [PATCH v4 2/3] push: parse and set flag " Srinidhi Kaushik
2020-09-19 20:26 ` Junio C Hamano
2020-09-19 17:03 ` [PATCH v4 3/3] t, doc: update tests, reference " Srinidhi Kaushik
2020-09-19 20:42 ` Junio C Hamano
2020-09-23 7:30 ` [PATCH v5 0/3] push: add "--[no-]force-if-includes" Srinidhi Kaushik
2020-09-23 7:30 ` [PATCH v5 1/3] push: add reflog check for "--force-if-includes" Srinidhi Kaushik
2020-09-23 10:18 ` Phillip Wood
2020-09-23 11:26 ` Srinidhi Kaushik
2020-09-23 16:24 ` Junio C Hamano
2020-09-23 16:29 ` Junio C Hamano
2020-09-23 7:30 ` [PATCH v5 2/3] push: parse and set flag " Srinidhi Kaushik
2020-09-23 7:30 ` [PATCH v5 3/3] t, doc: update tests, reference " Srinidhi Kaushik
2020-09-23 10:24 ` Phillip Wood
2020-09-26 10:13 ` [PATCH v6 0/3] push: add "--[no-]force-if-includes" Srinidhi Kaushik
2020-09-26 10:13 ` [PATCH v6 1/3] push: add reflog check for "--force-if-includes" Srinidhi Kaushik
2020-09-26 10:13 ` [PATCH v6 2/3] push: parse and set flag " Srinidhi Kaushik
2020-09-26 10:13 ` [PATCH v6 3/3] t, doc: update tests, reference " Srinidhi Kaushik
2020-09-26 10:21 ` [PATCH v6 0/3] push: add "--[no-]force-if-includes" Srinidhi Kaushik
2020-09-26 11:46 ` [PATCH v7 " Srinidhi Kaushik
2020-09-26 11:46 ` [PATCH v7 1/3] push: add reflog check for "--force-if-includes" Srinidhi Kaushik
2020-09-26 23:42 ` Junio C Hamano
2020-09-27 12:27 ` Srinidhi Kaushik
2020-09-26 11:46 ` [PATCH v7 2/3] push: parse and set flag " Srinidhi Kaushik
2020-09-26 11:46 ` [PATCH v7 3/3] t, doc: update tests, reference " Srinidhi Kaushik
2020-09-27 14:17 ` [PATCH v8 0/3] push: add "--[no-]force-if-includes" Srinidhi Kaushik
2020-09-27 14:17 ` [PATCH v8 1/3] push: add reflog check for "--force-if-includes" Srinidhi Kaushik
2020-09-27 14:17 ` [PATCH v8 2/3] push: parse and set flag " Srinidhi Kaushik
2020-09-27 14:17 ` [PATCH v8 3/3] t, doc: update tests, reference " Srinidhi Kaushik
2020-09-30 12:54 ` Philip Oakley
2020-09-30 14:27 ` Srinidhi Kaushik
2020-09-28 17:31 ` [PATCH v8 0/3] push: add "--[no-]force-if-includes" Junio C Hamano
2020-09-28 17:46 ` SZEDER Gábor
2020-09-28 19:34 ` Srinidhi Kaushik
2020-09-28 19:51 ` Junio C Hamano
2020-09-28 20:00 ` Junio C Hamano
2020-10-01 8:21 ` [PATCH v9 " Srinidhi Kaushik
2020-10-01 8:21 ` [PATCH v9 1/3] push: add reflog check for "--force-if-includes" Srinidhi Kaushik
2020-10-02 13:52 ` Johannes Schindelin
2020-10-02 14:50 ` Johannes Schindelin
2020-10-02 16:22 ` Junio C Hamano
2020-10-02 15:07 ` Srinidhi Kaushik
2020-10-02 16:41 ` Junio C Hamano
2020-10-02 19:39 ` Srinidhi Kaushik
2020-10-02 20:14 ` Junio C Hamano
2020-10-02 20:58 ` Srinidhi Kaushik
2020-10-02 21:36 ` Junio C Hamano
2020-10-02 16:26 ` Junio C Hamano
2020-10-01 8:21 ` [PATCH v9 2/3] push: parse and set flag " Srinidhi Kaushik
2020-10-01 8:21 ` [PATCH v9 3/3] t, doc: update tests, reference " Srinidhi Kaushik
2020-10-01 15:46 ` [PATCH v9 0/3] push: add "--[no-]force-if-includes" Junio C Hamano
2020-10-01 17:12 ` Junio C Hamano
2020-10-01 17:54 ` Srinidhi Kaushik
2020-10-01 18:32 ` Junio C Hamano
2020-10-02 16:50 ` Junio C Hamano
2020-10-02 19:42 ` Srinidhi Kaushik
2020-10-03 12:10 ` [PATCH v10 " Srinidhi Kaushik
2020-10-03 12:10 ` [PATCH v10 1/3] push: add reflog check for "--force-if-includes" Srinidhi Kaushik
2020-10-03 12:10 ` [PATCH v10 2/3] push: parse and set flag " Srinidhi Kaushik
2020-10-03 12:10 ` [PATCH v10 3/3] t, doc: update tests, reference " Srinidhi Kaushik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200904185147.77439-1-shrinidhi.kaushik@gmail.com \
--to=shrinidhi.kaushik@gmail.com \
--cc=Johannes.Schindelin@gmx.de \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).