Re: [PATCH v4 1/3] push: add reflog check for "--force-if-includes"
- From
Srinidhi Kaushik <shrinidhi.kaushik@gmail.com>
- Date
- Sep 21, 2020, 08:42 UTC
- Message-ID
- <20200921084231.GA64896@mail.clickyotomy.dev>
- In-Reply-To
- <xmqqft7djzz0.fsf@gitster.c.googlers.com>
Hi Junio,
On 09/19/2020 13:03, Junio C Hamano wrote:
Show 6 quoted lines
> Srinidhi Kaushik <shrinidhi.kaushik@gmail.com> writes: > > > Adds a check to verify if the remote-tracking ref of the local branch > > is reachable from one of its "reflog" entries. > > s/Adds/Add/
Gotcha, I will reword the commit messages for all three commits. in the patch series.
> > When "--force-with-includes" is used along with "--force-with-lease", > > A misspelt name for the new option is found here.
*Facepalm.* Thanks, will update.
Show 24 quoted lines
> > [...] > Makes me wonder, if in_merge_bases() is so expensive that it makes > sense to split the "were we exactly at the tip?" and "is one of the > commits we were at a descendant of the tip?" into separate phases, > if this part should be calling in_merge_bases() one by one. > > Would it make more sense to iterate over reflog entries from newer > to older, collect them in an array of pointers to "struct commit" in > a batch of say 8 commits or less, and then ask in_merge_bases_many() > if the remote_commit is an ancestor of one of these local commits? > > The traversal cost to start from one "local commit" to see if > remote_commit is an ancestor of it using in_merge_bases() and > in_merge_bases_many() should be the same and an additional traversal > cost to start from more local commits should be negligible compared > to the traversal itself, so making a call to in_merge_bases() for > each local_commit smells somewhat suboptimal. > > If we were talking about older parts of the history, optional > generation numbers could change the equation somewhat, but the > common case for the workflow this series is trying to help is that > these local commits ane the remote tip are relatively new and it is > not unlikely that the generation numbers have not been computed for > them, which is why I suspect that in_merges_many may be a win.
Nice! We can definitely try batching commits from the reflog and pass it along to "in_merge_bases_many()". As for being faster than calling "in_merge_bases()" for each commit entry in the reflog -- I am not familiar with how the former works. Do we still keep the "reflog_entry_exists()" part? It might still be faster to go through the entries once to check with "oideq()" in the first run.
Also, I was wondering if it is worth considering this:
- check if the reflog of the HEAD has the remote ref
- check if the reflog of the local branch has the remote ref
- check if the remote ref is reachable from any of the local ref's
"reflog" entries using "in_merge_bases_many()" in batches as
suggested here.The first two (we can even skip the second one) runs are relatively fast, and the third one might be faster than checking "in_merge_bases()" for each reflog entry. I suppose adding these three steps would make the process slower overall, though. For context, I was referring to your message [1] on the other thread regarding checking the HEAD's reflog.
Show 10 quoted lines
> > [...] > > + /* > > + * If "compare-and-swap" is in "use_tracking[_for_rest]" > > + * mode, and if "--foce-if-includes" was specified, run > > + * the check. > > + */ > > + if (ref->if_includes) > > + check_if_includes_upstream(ref); > > s/foce/force/;
Yes, sorry about that; will update.
Show 36 quoted lines
> I can see that the code is checking "and if force-if-includes was
> specified" part, but it is not immediately clear where the code
> checks if "--force-with-lease" is used with "tracking" and not with
> "the other side must be exactly this commit" mode here.
>
> ... goes and looks ...
>
> Ah, ok, I found out.
>
> The field name "if_includes", and the comment for the field in
> remote.h, are both misleading. It gives an impression that the
> field being true means "--force-if-included is in use", but in
> reality the field means a lot more. When it is true, it signals
> that "--force-if-included" is in use *and* for this ref we were told
> to use the "--force-with-lease" without an exact object name. And
> that logic is not here, but has already happened in apply_cas().
>
> Which makes the above comment correct. We however need a better
> name for this field and/or an explanation for the field in the
> header file, or both, to avoid misleading readers.
>
> > diff --git a/remote.h b/remote.h
> > index 5e3ea5a26d..38ab8539e2 100644
> > --- a/remote.h
> > +++ b/remote.h
> > @@ -104,7 +104,9 @@ struct ref {
> > forced_update:1,
> > expect_old_sha1:1,
> > exact_oid:1,
> > - deletion:1;
> > + deletion:1,
> > + if_includes:1, /* If "--force-with-includes" was specified. */
>
> The description needs to be tightened.
>
> > + unreachable:1; /* For "if_includes"; unreachable in reflog. */OK, you're right. Perhaps, we could rename it to something like "if_includes_for_tracking" and update the comment description with saying something along the lines of:
+ /* + * Set when "--force-if-includes" is enabled, and + * if "compare-and-swap" is not provided with the + * exact commit to be expected on the remote (in + * "use_tracking" or use_tracking_for_rest" mode). + */
[1]: https://public-inbox.org/git/xmqqsgbdk69b.fsf@gitster.c.googlers.com
Thanks again, for taking the time to review this.
-- Srinidhi Kaushik