From: Jeff King <peff@peff.net>
To: Elijah Newren <newren@gmail.com>
Cc: Git Mailing List <git@vger.kernel.org>
Subject: Re: Bug report: git branch behaves as if --no-replace-objects is passed
Date: Tue, 30 Mar 2021 03:02:28 -0400 [thread overview]
Message-ID: <YGLNBFJv8NKmrbvz@coredump.intra.peff.net> (raw)
In-Reply-To: <CABPp-BEAbN05+hCtK=xhGg5uZFqbUvH9hMcCNMcBWp5JWLqzPw@mail.gmail.com>
On Mon, Mar 29, 2021 at 11:05:05PM -0700, Elijah Newren wrote:
> it all works well. BUT, if I try to use it with branch it doesn't work:
>
> $ git branch --contains deadbeefdeadbeefdeadbeefdeadbeefdeadbeef
> $
I'm not surprised here. The replace mechanism is usually "if you are
trying to access object X, then access the contents of Y instead". But I
don't think we generally rewrite references from other objects. So in
that sense, no ref "contains" deadbeef, because nobody points to it as
an ancestor.
I guess "branch --contains" could convert the mention of the replaced
object on the command-line, something like this:
diff --git a/parse-options-cb.c b/parse-options-cb.c
index 4542d4d3f9..200be4e3d2 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -6,6 +6,7 @@
#include "string-list.h"
#include "strvec.h"
#include "oid-array.h"
+#include "replace-object.h"
/*----- some often used options -----*/
@@ -84,6 +85,7 @@ int parse_opt_verbosity_cb(const struct option *opt, const char *arg,
int parse_opt_commits(const struct option *opt, const char *arg, int unset)
{
struct object_id oid;
+ const struct object_id *replace;
struct commit *commit;
BUG_ON_OPT_NEG(unset);
@@ -92,7 +94,9 @@ int parse_opt_commits(const struct option *opt, const char *arg, int unset)
return -1;
if (get_oid(arg, &oid))
return error("malformed object name %s", arg);
- commit = lookup_commit_reference(the_repository, &oid);
+
+ replace = lookup_replace_object(the_repository, &oid);
+ commit = lookup_commit_reference(the_repository, replace);
if (!commit)
return error("no such commit %s", arg);
commit_list_insert(commit, opt->value);
though if we go that route, I suspect we ought to be adding both the
original _and_ the replacement.
I'm not entirely sure this is a good direction, though.
> and possibly worse, if I create a new branch based on it and use it:
>
> $ git branch foobar deadbeefdeadbeefdeadbeefdeadbeefdeadbeef
> $ git checkout foobar
> $ echo stuff >empty
> $ git add empty
> $ git commit -m more
>
> then it's clear that branch created foobar pointing to the replaced
> object rather than the replacement object -- despite the fact that the
> replaced object doesn't even exist within this repo:
>
> $ git cat-file -p HEAD
> tree 18108bae26dc91af2055bc66cc9fea278012dbd3
> parent deadbeefdeadbeefdeadbeefdeadbeefdeadbeef
> author Elijah Newren <newren@gmail.com> 1617083739 -0700
> committer Elijah Newren <newren@gmail.com> 1617083739 -0700
>
> more
Yeah, that's pretty horrible. I do think you're using replace objects in
a way they weren't really intended for, in two ways:
- usually you'd actually have deadbeef, and you just want to rewrite
it to something else
- you wouldn't usually work directly with the replace object on the
command line like this. Usually the intent is to patch some old
section of history to get a different view.
None of which is an excuse exactly. But just to say that I'm not too
surprised that the "replace" mechanism is a bit half-baked, and there
are probably a lot of weird implications nobody has thought through.
Patches welcome, of course, though I suspect it may be a rabbit hole
that isn't worth your time. :)
> I poked around in the code a little but it is not at all clear to me
> why some parts of the code (log, diff) translate replace refs
> correctly, while others (branch) don't. It is clear from the output
> that log is aware that the refs are replaced, which makes me wonder if
> every caller needs to be aware of replace refs for them to work
> correctly everywhere, because I couldn't find a missing environment
> setup for "branch".
Right. To work as you expect above, basically everything that is going
to look at an oid would need to consider whether to use a replace ref.
Shoving the lookup into get_oid() would "fix" that, but I suspect would
confuse some other callers. Right now the rule is "when you access the
object contents, pretend as if it had X instead of Y", so we can enforce
that at the layer of accessing the object database.
-Peff
next prev parent reply other threads:[~2021-03-30 7:03 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-30 6:05 Bug report: git branch behaves as if --no-replace-objects is passed Elijah Newren
2021-03-30 7:02 ` Jeff King [this message]
2021-03-30 18:58 ` Junio C Hamano
2021-03-30 21:19 ` Elijah Newren
2021-03-30 21:30 ` Elijah Newren
2021-03-30 21:59 ` Junio C Hamano
2021-03-30 21:53 ` Junio C Hamano
2021-03-30 22:43 ` Elijah Newren
2021-03-30 23:04 ` Junio C Hamano
2021-03-31 0:32 ` Elijah Newren
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=YGLNBFJv8NKmrbvz@coredump.intra.peff.net \
--to=peff@peff.net \
--cc=git@vger.kernel.org \
--cc=newren@gmail.com \
/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).