git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Bug: `git check-ignore -v` changes the exit code.

From
Michael G Schwern <schwern@pobox.com>
Date
Mar 26, 2024, 22:07 UTC
Message-ID
<ddeef5fe-d208-49e1-bbf1-5563df3dcf51@pobox.com>

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? (Steps to reproduce your issue)

$ tree . ├── dir_b │ ├── sub │ │ └── test │ └── test └── top

$ cat .gitignore *

!/dir_b/ !/dir_b/**

$ git status --ignored On branch main

No commits yet
Untracked files:
   (use "git add <file>..." to include in what will be committed)
	dir_b/
Ignored files:
   (use "git add -f <file>..." to include in what will be committed)
	.gitignore
	top
nothing added to commit but untracked files present (use "git add" to track)
What did you expect to happen? (Expected behavior)

$ git check-ignore dir_b/sub/test $ echo $? 1

$ git check-ignore -v dir_b/sub/test $ echo $? 1

What happened instead? (Actual behavior)

$ git check-ignore dir_b/sub/test $ echo $? 1

$ git check-ignore -v dir_b/sub/test .gitignore:4:!/dir_b/** dir_b/sub/test $ echo $? 0

What's different between what you expected and what actually happened?

First, `git check-ignore -v` should have exited with 1 because that is defined as "None of the provided paths are ignored". Exiting with 0, "One or more of the provided paths is ignored", is clearly incorrect.

Second, it's confusing that `git check-ignore -v` shows matches to negation patterns. The documentation says "Instead of printing the paths that are excluded, for each path that matches an exclude pattern, print the exclude pattern together with the path." which seems pretty clear, but then there's this parenthetical... "(Matching an exclude pattern usually means the path is excluded, but if the pattern begins with "!" then it is a negated pattern and matching it means the path is NOT excluded.)" which *implies* -v is also going to show unignored files, but it's unclear.

An additional problem is the use of "excluded" to mean "ignored" and "exclude pattern" which includes negated patterns which include. Oy.

The existence of --non-matching makes this extra confusing. The casual reader can think "non-matching" means "paths which are not ignored" rather than "paths which match no pattern". Again, the misunderstanding hinges on realizing "exclude pattern" includes negated patterns which include.

Anything else you want to add:

`git check-ignore`, `git check-ignore -v`, and `git status --ignored` should all agree at least on what is ignored.

Verbose flags should not change the behavior of a command, they should only add to its output. `git check-ignore` shows only ignored paths while `git check-ignore -v` also shows unignored paths. One could argue only the exit status is the true behavior, but people look at the output. See https://stackoverflow.com/questions/78216866/file-in-the-same-path-one-can-be-git-trace-but-others-cannot#comment137908188_78216923 for a real example of this causing confusion.

I think the issue is that `git check-ignore` is for checking which files are ignored. Users expect --verbose to also show them why their file was ignored, but --verbose also shows unignored files. This is unexpected. The change in the exit status exacerbates the problem.

It would help to talk about "ignored files" rather than "excluded files". It's called "check-ignore" and users edit their ".gitignore" fie and read the "gitignore" docs (.git/exclude being rarely used).

I would also simply say "pattern". This avoids the confusion that "exclude patterns" sometimes unexclude. gitignore only says "pattern" and never says "exclude pattern". This also avoids the confusing "negated exclude pattern", that is just a "negated pattern".

Ideally, I'd make --verbose just show the path + the last matched pattern. Separate flag(s) change what is shown.

-v, --verbose Print the matching pattern and the path.

-a, --all-matching Show paths which match any pattern. If the path matches a negated pattern (the pattern begins with "!") it will be shown despite not being ignored.

The current behavior would be `git check-ignore -v -a <path>...`.
If -v has to remain backwards compatible, I would suggest...

-v, --verbose Print the matching pattern and the path. If the match is a negated pattern (the pattern begins with "!") the path is not ignored.

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.43.2 cpu: x86_64 no commit associated with this build sizeof-long: 8 sizeof-size_t: 8 shell-path: /bin/sh feature: fsmonitor--daemon uname: Darwin 23.3.0 Darwin Kernel Version 23.3.0: Wed Dec 20 21:28:58 PST 2023; root:xnu-10002.81.5~7/RELEASE_X86_64 x86_64 compiler info: clang: 15.0.0 (clang-1500.1.0.2.5) libc info: no libc information available $SHELL (typically, interactive shell): /bin/bash

[Enabled Hooks]
Message 1 of 1 in “Bug: `git check-ignore -v` changes the exit code.”
  1. Michael G SchwernMar 26, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.