Metadata-Version: 2.4
Name: gitslip
Version: 0.1.0
Summary: Find files that slipped past .gitignore but are still tracked by git — and get the exact git rm --cached fix. Zero dependencies.
Author: yyfjj
License: MIT
Project-URL: Homepage, https://github.com/jjdoor/gitslip-py
Project-URL: Repository, https://github.com/jjdoor/gitslip-py
Project-URL: Issues, https://github.com/jjdoor/gitslip-py/issues
Keywords: git,gitignore,tracked,cli,lint,cleanup,repo-hygiene,pre-commit,devops
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Version Control :: Git
Classifier: Topic :: Utilities
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# gitslip

**Find files that slipped past `.gitignore` but are still tracked by git.** You
add `*.log` or `.env` to `.gitignore`, but the file that was committed *before*
the rule existed keeps getting tracked — git only ignores files it isn't
already following. `gitslip` finds those leftovers and hands you the exact fix.

```bash
pipx run gitslip
#  2 tracked files are ignored by your rules but still committed:
#
#    config/secrets.env
#        ↳ .gitignore:7  *.env
#    logs/app.log
#        ↳ .gitignore:2  *.log
#
#  Fix — stop tracking them (keeps your local copy):
#    git rm --cached -- config/secrets.env
#    git rm --cached -- logs/app.log
```

Zero dependencies, pure standard library. Also available for Node:
`npx gitslip` — byte-for-byte identical behaviour.

## Why

Adding a path to `.gitignore` does **nothing** to a file git already tracks.
That's by design — but it means secrets, build artifacts and logs routinely sit
in repos long after someone "gitignored" them. The usual `git rm --cached`
fix-up is only run once someone *notices*, and a raw `grep` over `.gitignore`
can't tell a still-tracked leftover from a file that's correctly excluded.

`gitslip` answers one question precisely: **which tracked files do my own ignore
rules say should be excluded?** It then prints the `git rm --cached` commands to
untrack them (your working copy stays put).

## How it works

It defers all the matching to git, so negation rules (`!keep.log`), directory
rules (`build/`), nested `.gitignore` files, `.git/info/exclude` and your global
`core.excludesFile` are all handled correctly:

1. **Detect** — `git ls-files -i -c --exclude-standard` lists files that are
   both *tracked* and *ignored*. That's the authoritative slipped set.
2. **Attribute** — for each one, `gitslip` names the rule that catches it
   (`.gitignore:7  *.env`) by asking `git check-ignore` against an empty index
   (tracked files are otherwise reported as "not ignored").

No file matching logic of our own = no subtle disagreements with git.

## Usage

```bash
gitslip                 # audit the whole repo (exit 1 if anything slipped)
gitslip src/ config/    # limit the audit to pathspecs
gitslip --json          # machine-readable, for CI
gitslip --apply         # run the git rm --cached for you (keeps files on disk)
```

`--apply` only un-tracks; it never deletes your files. Review the diff and
commit when you're happy:

```bash
gitslip --apply
git commit -m "stop tracking ignored files"
```

### In CI

```yaml
- run: pipx run gitslip   # fails the job if a tracked file is gitignored
```

Exit codes: `0` clean · `1` slipped files found · `2` error (not a repo, git
missing).

## Install

```bash
pip install gitslip   # or `pipx run gitslip`
npm i -g gitslip      # Node build, identical behaviour
```

Requires git on `PATH` and Python ≥ 3.8 (or Node ≥ 18).

## License

MIT
