Skip to content

.gitignore is too powerful and cannot be stopped #16920

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
kingmesal opened this issue Mar 3, 2025 · 7 comments · Fixed by #17255
Closed

.gitignore is too powerful and cannot be stopped #16920

kingmesal opened this issue Mar 3, 2025 · 7 comments · Fixed by #17255

Comments

@kingmesal
Copy link

What version of Tailwind CSS are you using?

v4.0.9

What build tool (or framework if it abstracts the build tool) are you using?

postcss: 8.5.3

What version of Node.js are you using?

Node: v22.11.0
Bun: 1.2.5

What browser are you using?

N/A

What operating system are you using?

Linux

Describe your issue

I have a mulitple wildcard patterns like special-*.hbs in my .gitignore and I cannot find a way to tell tailwind v4 to ignore my gitignore or to be able to specify an @source "../src/special-*.hbs"

Let me explain my process. My toolset copies a bunch of templates into my users site. They match special-*.hbs. These are in the .gitignore because they are not intended to be checked into their repository.

I have tried @import "tailwindcss" source(none); then specify @source "../src"; but the .gitignore is still in effect, which I thought would get turned off using the source(none).

What can I do here?

@kerams
Copy link

kerams commented Mar 7, 2025

Same here. During builds I am generating files which are gitignored, so I'd really love the ability to use source(none) in combination with file globbing like in v3, something like @source "../*.generated.js", or some strict whitelisting with everything else excluded.

@rvanbaalen
Copy link

rvanbaalen commented Mar 20, 2025

Omg, @kerams I was running into exactly the same problem. Generating some templated files in my build process and somehow, Tailwind was not having it when it comes to parsing the correct styles.

After wasting two days in this I finally discovered the problem was the .gitignore file.

These are two completely separate concerns! What I want ignored by .gitignore is for, you guessed it, git to ignore. It has nothing to do with Tailwind and the fact that this is not clearly documented in big fat red letters is unfortunate.

If tailwind wants to do magic automated guessing; perhaps support some sort of .twignore file standard instead.
Even when explicitly mentioning specific folders with @source() won't overwrite the .gitignore.

Sorry for the rant, I was just disappointed that this cost me two full days to discover. I love tailwind as much as the next person but this was just annoying and more important, unexpected.

@KennethHoff
Copy link

I think using .gitignore is a good default. Most people don't need or want Tailwind to scan generated files, and having to define everything twice is annoying.

I'm not opposed to a .twignore ( or similar) concept, but it should default to following .gitignore without such a file.

@rvanbaalen
Copy link

@KennethHoff you're right. My previous comment was written slightly in the heat of the moment (can you tell? 🤣 )

.gitignore is an acceptable default. The current situation/problem is just a two fold:

  • The fact that .gitignore is used as a default is not documented/clearly stated
  • Its hard (impossible?) to overwrite the .gitignore-ignores.

@kingmesal
Copy link
Author

I think this is a multi-step problem:

  • Step 1 - How can a user override/ ignore .gitignore
  • Step 2 - How can a user specify what they actually want TW to ignore

@philipp-spiess
Copy link
Member

philipp-spiess commented Mar 21, 2025

Hey folks! You'll be happy with this PR I think: #17255

This makes some changes that will also make it so that @source rules can now overwrite your .gitignore presets so the examples I saw in this thread (@source "../src/special-*.hbs" and @source "../*.generated.js") will now be included regardless of your .gitignore settings.

RobinMalfait added a commit that referenced this issue Mar 25, 2025
This PR adds a new source detection feature: `@source not "…"`. It can
be used to exclude files specifically from your source configuration
without having to think about creating a rule that matches all but the
requested file:

```css
@import "tailwindcss";
@source not "../src/my-tailwind-js-plugin.js";
```

While working on this feature, we noticed that there are multiple places
with different heuristics we used to scan the file system. These are:

- Auto source detection (so the default configuration or an `@source
"./my-dir"`)
- Custom sources ( e.g. `@source "./**/*.bin"` — these contain file
extensions)
- The code to detect updates on the file system

Because of the different heuristics, we were able to construct failing
cases (e.g. when you create a new file into `my-dir` that would be
thrown out by auto-source detection, it'd would actually be scanned). We
were also leaving a lot of performance on the table as the file system
is traversed multiple times for certain problems.

To resolve these issues, we're now unifying all of these systems into
one `ignore` crate walker setup. We also implemented features like
auto-source-detection and the `not` flag as additional _gitignore_ rules
only, avoid the need for a lot of custom code needed to make decisions.

High level, this is what happens after the now:

- We collect all non-negative `@source` rules into a list of _roots_
(that is the source directory for this rule) and optional _globs_ (that
is the actual rules for files in this file). For custom sources (i.e
with a custom `glob`), we add an allowlist rule to the gitignore setup,
so that we can be sure these files are always included.
- For every negative `@source` rule, we create respective ignore rules.
- Furthermore we have a custom filter that ensures files are only read
if they have been changed since the last time they were read.

So, consider the following setup:

```css
/* packages/web/src/index.css */
@import "tailwindcss";
@source "../../lib/ui/**/*.bin";
@source not "../../lib/ui/expensive.bin";
```

This creates a git ignore file that (simplified) looks like this:

```gitignore
# Auto-source rules
*.{exe,node,bin,…}
*.{css,scss,sass,…}
{node_modules,git}/

# Custom sources can overwrite auto-source rules
!lib/ui/**/*.bin

# Negative rules
lib/ui/expensive.bin
```

We then use this information _on top of your existing `.gitignore`
setup_ to resolve files (i.e so if your `.gitignore` contains rules e.g.
`dist/` this line is going to be added _before_ any of the rules lined
out in the example above. This allows negative rules to allow-list your
`.gitignore` rules.

To implement this, we're rely on the `ignore` crate but we had to make
various changes, very specific, to it so we decided to fork the crate.
All changes are prefixed with a `// CHANGED:` block but here are the
most-important ones:

- We added a way to add custom ignore rules that _extend_ (rather than
overwrite) your existing `.gitignore` rules
- We updated the order in which files are resolved and made it so that
more-specific files can allow-list more generic ignore rules.
- We resolved various issues related to adding more than one base path
to the traversal and ensured it works consistent for Linux, macOS, and
Windows.

## Behavioral changes

1. Any custom glob defined via `@source` now wins over your `.gitignore`
file and the auto-content rules.
   - Resolves #16920
3. The `node_modules` and `.git` folders as well as the `.gitignore`
file are now ignored by default (but can be overridden by an explicit
`@source` rule).
   - Resolves #17318
   - Resolves #15882
4. Source paths into ignored-by-default folders (like `node_modules`)
now also win over your `.gitignore` configuration and auto-content
rules.
    -  Resolves #16669
5. Introduced `@source not "…"` to negate any previous rules.
   - Resolves #17058
6. Negative `content` rules in your legacy JavaScript configuration
(e.g. `content: ['!./src']`) now work with v4.
   - Resolves #15943 
7. The order of `@source` definitions matter now, because you can
technically include or negate previous rules. This is similar to your
`.gitingore` file.
9. Rebuilds in watch mode now take the `@source` configuration into
account
   - Resolves #15684

## Combining with other features

Note that the `not` flag is also already compatible with [`@source
inline(…)`](#17147)
added in an earlier commit:

```css
@import "tailwindcss";
@source not inline("container");
```

## Test plan

- We added a bunch of oxide unit tests to ensure that the right files
are scanned
- We updated the existing integration tests with new `@source not "…"`
specific examples and updated the existing tests to match the subtle
behavior changes
- We also added a new special tag `[ci-all]` that, when added to the
description of a PR, causes the PR to run unit and integration tests on
all operating systems.

[ci-all]

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
@RobinMalfait
Copy link
Member

Hey! Small update, we merged the PR (#17255) that fixes this, and it will be available in the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants