Subject: Re: [PATCH] precious-files.txt: new document proposing new precious file type

From: Junio C Hamano <[email-masked]>
Date: Thu, 18 Jan 2024 11:14:56 -0800

Sebastian Thiel <[email-masked]> writes:

> #(keep)
> .config
>
> As a side-effect of the syntax, it's obvious this is an 'upgrade', with
> perfect backwards compatibility as old git does the same as always.

Yes but ...

The point Elijah makes is worth considering.  To existing versions
of git, having this entry for ".config" means that it is ignored
(i.e. "git add ." will not include it), but expendable (i.e. "git
clean" considers ".config" as a candidate for removal; "git checkout
other", if the "other" branch has it as a tracked path, will clobber
it).  Compared to the case where ".config" is not mentioned in
".gitignore", where it may be added by use of "git add .", it won't
be clobbered by "git clean".

So this syntax having "perfect backward compatibility" is not quite
true.  It does have downsides when used by existing versions of Git.

If we use Elijah's syntax to say

	$.config

then the entry to existing versions of git is a no-op wrt a file
named ".config".  It simply does not match the pattern, so an
accidental "git add ." *will* add ".config" to the index, while "git
clean" may not touch it, simply because it is treated as "untracked
and precious".  In other words, its downside is the same as not
marking the path ".config" in any way in ".gitignore", as far as
existing versions of Git are concerned.

We of course discount the possibility that people keep a file whose
name literally is dollar-dot followed by "config" and older versions
of Git would start treating them as ignored-and-expendable.  While
it *is* an additional downside compared to Phillip's "#(keep)"
approach, I do not think that particular downside is worth worrying
about.  Yet another downside compared to Phillip's is that it is
less extensible.  Over the years, however, the ignored-but-precious
is the only one we heard from users that lack of which is hurting
them, so lack of extensibility may not be too huge a deal.

For projects that are currently listing these files in ".gitignore"
as "ignored-and-expendable" already and want to categorize them as
"ignored-and-precious" by changing ".config" to "$.config" (or
adding "#(keep)" comment before the existing entry), the
pros-and-cons equation may differ.  Their current participants are
protected from accidentally adding them with "git add ." but risking
to lose them with "git clean -f".  They may even be trained to be
careful to see "git clean -n" output before actually running the
command with "-f".  Now, if their project ships a new version of
".gitignore" that marks these paths as "ignored-and-precious", both
approaches will have intended effect to participants who upgraded to
the version of Git.

To participants using the current version of Git:

 * Phillip's approach to add "#(keep)" will not change anything.
   They will be protected from accidental "git add ." as before, and
   they will still have to be careful about "git clean -f".

 * Elijah's approach to rewrite existing'.config' to '$.config',
   however, will stop protecting them from "git add .", even though
   it will start protecting them from "git clean -f".

The devil you already know may be the lessor of two evils in such a
situation.

So, all it boils down to is these two questions.

 * Which one between "'git add .' adds '.config' that users did not
   want to add" and "'git clean -f' removes '.config' together with
   other files" a larger problem to the users, who participate in a
   project that already decided to use the new .gitignore feature to
   mark ".config" as "precious", of older versions of Git that
   predate "precious"?

 * What are projects doing to paths that they want to make
   "precious" with the current system?  Do they leave them out of
   ".gitignore" and have them subject to accidental "git add ." to
   protect them from "git clean -f"?  Or do they list them in
   ".gitignore" to prevent "git add ." from touching, but leave them
   susceptible to accidental removal by "git clean -f"?

Thanks.