threads / bug / 59898

Bug: git add does not process gitignore properly

Subject: Bug: git add does not process gitignore properly

## tl;dr

4 messages between Jun 22, 2023 and Jun 24, 2023.

replies: 3people: 4as markdown or json

David C Black· Jun 22, 2023, 19:38 UTC · lore
Thank you for filling out a Git bug report!
Please answer the following questions to help us understand your issue.
 
What did you do before the bug happened?
 
Sitting at the rood of my working directory I attempted to add a file to the git repository with:
 
> git add extern/bin/build
 
The repository had the following .gitignore file contents:
 
> /extern/
> !/extern/bin/
> !/extern/ABOUT.md
 
What did you expect to happen? (Expected behavior)
 
I expected it to be added.
 
What happened instead? (Actual behavior)
 
I received an error message:
 
Show 5 quoted lines
> The following paths are ignored by one of your .gitignore files:
> extern
> hint: Use -f if you really want to add them.
> hint: Turn this message off by running
> hint: "git config advice.addIgnoredFile false"
 
What's different between what you expected and what actually happened?
 
By negating entries in the /extern/bin/ directory, I did not expect an error
message. Of course adding -f made it work, but I think it does not match the
described behavior for this tool.
 
Anything else you want to add:
 
Please review the rest of the bug report below.
You can delete any lines you don't wish to share.
 
[System Info]
git version:
git version 2.41.0
cpu: arm64
no commit associated with this build
sizeof-long: 8
sizeof-size_t: 8
shell-path: /bin/sh
feature: fsmonitor--daemon
uname: Darwin 22.5.0 Darwin Kernel Version 22.5.0: Mon Apr 24 20:52:24 PDT 2023; root:xnu-8796.121.2~5/RELEASE_ARM64_T6000 arm64
compiler info: clang: 14.0.3 (clang-1403.0.22.14.1)
libc info: no libc information available
$SHELL (typically, interactive shell): /bin/zsh
 
 
[Enabled Hooks]
 
-- 
David C. Black, Electronics/Programming Technology Instructor
Eric Sunshine· Jun 23, 2023, 22:07 UTC · re: David C Black · lore

Re: Bug: git add does not process gitignore properly

On Thu, Jun 22, 2023 at 3:56 PM David C Black <david.black@doulos.com> wrote:
Show 16 quoted lines
> Sitting at the rood of my working directory I attempted to add a file to the git repository with:
> > git add extern/bin/build
>
> The repository had the following .gitignore file contents:
> > /extern/
> > !/extern/bin/
> > !/extern/ABOUT.md
>
> I received an error message:
> > The following paths are ignored by one of your .gitignore files:
> > extern
> > hint: Use -f if you really want to add them.
>
> By negating entries in the /extern/bin/ directory, I did not expect an error
> message. Of course adding -f made it work, but I think it does not match the
> described behavior for this tool.
This appears to be working as documented. From the gitginore(5) man page:
    An optional prefix "!" which negates the pattern; any matching
    file excluded by a previous pattern will become included again. It
    is not possible to re-include a file if a parent directory of that
    file is excluded.

In your .gitignore file, /extern/ is ignored, which means that the subsequent "!/extern/.../" lines are ineffectual. So, as far as Git is concerned, /extern/bin/build is indeed ignored, thus its refusal without --force.

Phillip Wood· Jun 24, 2023, 10:13 UTC · re: Eric Sunshine · lore

Re: Bug: git add does not process gitignore properly

On 23/06/2023 23:07, Eric Sunshine wrote:
Show 29 quoted lines
> On Thu, Jun 22, 2023 at 3:56 PM David C Black <david.black@doulos.com> wrote:
>> Sitting at the rood of my working directory I attempted to add a file to the git repository with:
>>> git add extern/bin/build
>>
>> The repository had the following .gitignore file contents:
>>> /extern/
>>> !/extern/bin/
>>> !/extern/ABOUT.md
>>
>> I received an error message:
>>> The following paths are ignored by one of your .gitignore files:
>>> extern
>>> hint: Use -f if you really want to add them.
>>
>> By negating entries in the /extern/bin/ directory, I did not expect an error
>> message. Of course adding -f made it work, but I think it does not match the
>> described behavior for this tool.
> 
> This appears to be working as documented. From the gitginore(5) man page:
> 
>      An optional prefix "!" which negates the pattern; any matching
>      file excluded by a previous pattern will become included again. It
>      is not possible to re-include a file if a parent directory of that
>      file is excluded.
> 
> In your .gitignore file, /extern/ is ignored, which means that the
> subsequent "!/extern/.../" lines are ineffectual. So, as far as Git is
> concerned, /extern/bin/build is indeed ignored, thus its refusal
> without --force.
I think the usual way around this is to use patterns like
	/extern/*
	!/extern/bin/
	!/extern/ABOUT.md
see the example on the gitignore man page.
Best Wishes
Phillip
Junio C Hamano· Jun 24, 2023, 22:19 UTC · re: Phillip Wood · lore

Re: Bug: git add does not process gitignore properly

Phillip Wood <phillip.wood123@gmail.com> writes:
Show 7 quoted lines
> I think the usual way around this is to use patterns like
>
> 	/extern/*
> 	!/extern/bin/
> 	!/extern/ABOUT.md
>
> see the example on the gitignore man page.
Thanks for a very good suggestion.

The behaviour may be somewhat counter-intuitive, especially when you have "/extern/" followed by "!/extern/blah" in the same file. The original rationale for this was because the behaviour becomes consistent between the cases where

 (1) these two patterns appear in the same top-level .gitignore
     file, and
 (2) "/extern/" is in the top-level .gitignore file and "!/bin/" is
     in ".gitignore" file in the "extern/" directory
which ought to be the moral equivalents.

There have been at least two attempts to change this, but without much success.

 - 57534ee7 (dir.c: don't exclude whole dir prematurely if neg
   pattern may match, 2015-09-21) tried but it caused breakages
   reported on the list [*1*, *2*] and got reverted at 8c722360
   (Revert "dir.c: don't exclude whole dir prematurely if neg
   pattern may match", 2016-01-08).
 - 5e57f9c3 (Merge branch 'nd/exclusion-regression-fix', 2016-02-24)
   was a merge of another attempt, which again had to be reverted at
   5cee3493 (Revert "Merge branch 'nd/exclusion-regression-fix'",
   2016-03-18).

It is dubious if it is worth making another attempt to change it. "Fixing" this and still keeping consistency between the two ways to spell the same pair of rules would mean that even "/extern/" in the ".gitignore" file in a higher level tells us not to bother with the "extern" directory, we would have to look for "extern/.gitignore" just in case it unignores something, which would probably make it unacceptably costly. It would be quite a backward incompatible change, too.

[References] *1* Git 2.7.0 gitignore behaviour regression: https://lore.kernel.org/git/20160107234455.GB265296@vauxhall.crustytoothpaste.net/

*2* Behavior change in 2.7.0: With core.sparseCheckout some files have
    the skip-worktree bit set after a checkout.:
https://lore.kernel.org/git/trinity-5caa2985-5cf1-453b-9a9e-bcce057f8615-1452249323061@3capp-gmx-bs51/

← back to recent threads