git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jeff King <peff@peff.net>
To: "brian m. carlson" <sandals@crustytoothpaste.net>
Cc: Junio C Hamano <gitster@pobox.com>,
	Frank Schwidom <schwidom@gmx.net>,
	git@vger.kernel.org
Subject: partial commit of file-to-directory change, was Re: Bugreport
Date: Fri, 19 Jan 2024 19:46:28 -0500	[thread overview]
Message-ID: <20240120004628.GA117170@coredump.intra.peff.net> (raw)
In-Reply-To: <ZasCZ0YetzmlBFvw@tapette.crustytoothpaste.net>

On Fri, Jan 19, 2024 at 11:14:47PM +0000, brian m. carlson wrote:

> > $ git commit . -m +
> > error: 'd' does not have a commit checked out
> > fatal: updating files failed
> 
> I can confirm this behaviour[0], and it's definitely wrong that it
> thinks `d` is a submodule.  It does, however, work if you do `git commit
> -m +` (that is, without the .), which makes sense since the relevant
> change is already staged in the index.
> 
> I'm not going to get to a patch or more thorough investigation, but
> perhaps someone else will.

I peeked at this a bit earlier; I didn't come up with a solution, but
here are a few more details.

As you noted, the problem is only with giving a pathspec to "git
commit". The bug is in the custom code git-commit uses to set up the
index for a partial commit. It generates a list of entries for the
partial commit via list_path(), and then tries to add them to the index.
But of course "d", being a directory, does not make any sense as an
index entry itself (unless as a submodule).

I'd have thought that we should just be using the same code that "git
add" does here (which obviously works). But all of this comes from
2888605c64 (builtin-commit: fix partial-commit support, 2007-11-18),
which explicitly says "you can't just run add_files_to_cache()", which
is what git-add does under the hood.

I don't know if we could revisit those assumptions and reuse some of the
existing code, or if the custom partial-commit code could be fixed.  I
guess the root of the issue is that in the call to list_paths(), we call
overlay_tree_on_index(). And that's how we end up thinking that "d" is a
useful path to talk about, even though it has already been removed from
the index (we have "d/b.txt" instead).

So I'm not sure if we need a solution here-ish:

diff --git a/builtin/commit.c b/builtin/commit.c
index 65196a2827..25e65e986d 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -302,7 +302,9 @@ static void add_remove_files(struct string_list *list)
 			continue;
 
 		if (!lstat(p->string, &st)) {
-			if (add_to_index(&the_index, p->string, &st, 0))
+			if (S_ISDIR(st.st_mode))
+				warning("woah, %s is a dir", p->string);
+			else if (add_to_index(&the_index, p->string, &st, 0))
 				die(_("updating files failed"));
 		} else
 			remove_file_from_index(&the_index, p->string);

but I'm not quite sure what we should be doing instead of that
warning(). Should we updating and including everything in "d/"? What
about if there were a "d/c.txt" that was not a tracked file at all?

It might also be that the bug is earlier in list_paths(), where we
should notice that "d" is gone and now we have entries under "d/".

I dunno. I probably won't dig much further on this myself, but it's
possible Junio (cc'd) might have an idea right away.

-Peff

  reply	other threads:[~2024-01-20  0:46 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-19 13:25 Bugreport Frank Schwidom
2024-01-19 23:14 ` Bugreport brian m. carlson
2024-01-20  0:46   ` Jeff King [this message]
2024-01-20  0:55     ` partial commit of file-to-directory change, was Bugreport Junio C Hamano
2024-01-20  1:22     ` Junio C Hamano
2024-01-25 18:54     ` Junio C Hamano

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

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240120004628.GA117170@coredump.intra.peff.net \
    --to=peff@peff.net \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=sandals@crustytoothpaste.net \
    --cc=schwidom@gmx.net \
    /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.
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 NNTP newsgroup(s).