# Gitignore ## Precedence and Negation ### How Git evaluates ignore rules **Precedence (high to low):** 1. Command-line excludes 2. `.gitignore` files from repository root down to file's directory (closer directories override higher ones) 3. `.git/info/exclude` 4. Global ignore file **Within the same precedence level:** Last matching pattern wins. ### Negation with `!` A pattern starting with `!` negates a previous ignore match (re-includes the path). **Example:** ```gitignore .env* # Ignore all .env* files !.env.example # But keep .env.example !*.gpg # But keep all .gpg files ``` **Question:** Will `.env.gpg` be ignored? **Answer:** No - `.env.gpg` will **not** be ignored. **Why:** - `.env*` matches `.env.gpg` and ignores it - `!*.gpg` (later line) re-includes any `*.gpg` file, including `.env.gpg` - **Last matching pattern wins**, so final state is **not ignored** ### Important caveats 1. **Cannot re-include from ignored parent directory** - If `.env.gpg` is inside an ignored directory (e.g., `secrets/`), a `!` rule cannot re-include it - Git doesn't descend into ignored directories 2. **Already tracked files** - `.gitignore` only affects untracked files - If `.env.gpg` is already tracked, it stays tracked until `git rm --cached .env.gpg` ### Force ignore a negated file If you want `.env.gpg` to be ignored despite `!*.gpg`: **Option 1: Add more specific ignore after the negation** ```gitignore .env* !*.gpg .env.gpg # Last match wins; ignores just this one ``` **Option 2: Swap order (if appropriate)** ```gitignore !*.gpg .env* # Last match wins; .env.gpg will be ignored ``` ### Check which rule applies ```bash git check-ignore -v .env.gpg ``` Prints the rule and file that decides the outcome. ## Are multiple `.gitignore`s frowned on? [source](https://stackoverflow.com/questions/3305869/are-multiple-gitignores-frowned-on) > I can think of at least two situations where you would want to have multiple `.gitignore` files in different (sub)directories. > > - Different directories have different types of file to ignore. For example the `.gitignore` in the top directory of your project ignores generated programs, while `Documentation/.gitignore` ignores generated documentation. > > - Ignore given files only in given (sub)directory (you can use `/sub/foo` in `.gitignore`, though). > > > Please remember that patterns in [`.gitignore`](http://git-scm.com/docs/gitignore "gitignore(5) Manual Page - Specifies intentionally untracked files to ignore") file apply recursively to the (sub)directory the file is in and all its subdirectories, unless pattern contains '/' (so e.g. pattern `name` applies to any file named `name` in given directory and all its subdirectories, while `/name` applies to file with this name only in given directory).