Re: [PATCH 3/3] checkout: allow -b/-B to work on a merge base
- From
Junio C Hamano <gitster@pobox.com>
- Date
- Apr 26, 2019, 04:59 UTC
- Message-ID
- <xmqqh8aluzsu.fsf@gitster-ct.c.googlers.com>
- In-Reply-To
- <xmqqmukdv57q.fsf@gitster-ct.c.googlers.com>
Junio C Hamano <gitster@pobox.com> writes:
Show 13 quoted lines
> Denton Liu <liu.denton@gmail.com> writes: > >> - new_branch_info->name = arg; >> + new_branch_info->name = strstr(arg, "...") ? >> + xstrdup(oid_to_hex(rev)) : >> + arg; > > Can we do better? > > I am not sure why we want to hardcode the knowledge of "..." syntax > like this here. "git checkout A...B" introduced in 2009 needed only > a single-liner change from get_sha1() to get_sha1_mb() without making > the ugly implementation detail seep into this layer.
I _think_ what you are trying to work around is that a syntax that is not understood as a reference to a single revision by get_oid() but is understood as such by get_oid_mb() can be in the .name field, and that eventually gets passed to branch.c::create_branch() as "start_name" in the codepath. The function ought to know that start_name wants to name a single revision and never a revision range, but fails to use get_oid_mb() but just a plain get_oid(), and fails.
If that is the case, wouldn't a better fix be more like the attached? This hasn't even been compile tested, but I suspect that without taking this approach, you would introduce a new "bug", namely, that
$ git checkout -b newbranch master...
ought to behave exactly like
$ git branch newbranch master... $ git checkout newbranch
But the first step would hit the same branch.c::create_branch() and would not work, no?
The reason I care about hiding syntax details like "..." from users of get_*_mb() is because I anticipate that we'll want to extend it to things other than just "merge base between two" with syntax different from "..." (while probably renaming _mb suffix to something else).
The codebase is not ready to replace get_oid() with get_oid_mb() blindly and wholesale, I think, as the former is used as an implementation detail of parsing range syntax like A..B but places that are end user facing *and* expect to take only a single revision (e.g. "rebase --onto <commit>", "checkout <commit>", etc.) and never a range that currently use get_oid() should be able to get replaced with get_oid_mb() to learn "A...B means their merge base, not a symmetric range" semantics for free.
branch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/branch.c b/branch.c index 28b81a7e02..a84c8aaca2 100644 --- a/branch.c +++ b/branch.c @@ -268,7 +268,7 @@ void create_branch(struct repository *r, } real_ref = NULL; - if (get_oid(start_name, &oid)) { + if (get_oid_mb(start_name, &oid)) { if (explicit_tracking) { if (advice_set_upstream_failure) { error(_(upstream_missing), start_name);