https://github.com/voidd0/gitwhen
gitwhen — pinpoint when a string, line, or file changed in git history. Zero deps wrapper around git log -S / git blame / git log --diff-filter.
https://github.com/voidd0/gitwhen
cli code-history devtools git git-archaeology git-blame git-history git-log nodejs voiddo
Last synced: 16 days ago
JSON representation
gitwhen — pinpoint when a string, line, or file changed in git history. Zero deps wrapper around git log -S / git blame / git log --diff-filter.
- Host: GitHub
- URL: https://github.com/voidd0/gitwhen
- Owner: voidd0
- License: mit
- Created: 2026-04-28T16:58:20.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-04-29T06:14:24.000Z (2 months ago)
- Last Synced: 2026-04-29T07:20:40.567Z (2 months ago)
- Topics: cli, code-history, devtools, git, git-archaeology, git-blame, git-history, git-log, nodejs, voiddo
- Language: JavaScript
- Homepage: https://tools.voiddo.com/gitwhen/
- Size: 13.7 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# gitwhen
[](https://www.npmjs.com/package/@v0idd0/gitwhen)
[](https://www.npmjs.com/package/@v0idd0/gitwhen)
[](LICENSE)
[](package.json)
**[Homepage](https://tools.voiddo.com/gitwhen/?ref=gitwhen-readme)** · **[Compare with tig](https://tools.voiddo.com/gitwhen/compare/tig/?ref=gitwhen-readme)** · **[GitHub](https://github.com/voidd0/gitwhen)** · **[npm](https://www.npmjs.com/package/@v0idd0/gitwhen)** · **[All tools](https://tools.voiddo.com/?ref=gitwhen-catalog-readme)** · **[Contact](mailto:support@voiddo.com)**
---
Pinpoint *when* a string, line, or file changed in git history. Wraps `git log -S`, `git blame`, and `git log --diff-filter=A` with sensible defaults so you don't have to memorize flag combinations. Zero deps. Free forever from vøiddo.
If you are choosing between a focused CLI and an interactive TUI, start with the live compare page: [gitwhen vs tig](https://tools.voiddo.com/gitwhen/compare/tig/?ref=gitwhen-readme).
```
$ gitwhen "TODO: deprecated"
gitwhen "TODO: deprecated"
● a3c4b18 2026-03-14 alice — drop legacy queue path
● 7f1e602 2025-11-08 bob — TODO before refactor
2 commit(s) touched the diff.
```
## Why gitwhen
Git already knows the answer. The problem is the question takes three different commands depending on whether you want to find when a *string* entered the codebase, when a *line* was last set, or when a *file* was first added or last deleted. You only run any of them once a quarter, so by the time you need it you've forgotten the flag soup. `git log -S "" -- path/`, `git blame -L 42,42 file`, `git log --diff-filter=A --reverse -- path` — three different mental models. gitwhen is the mnemonic that wraps all three.
## Install
```bash
npm install -g @v0idd0/gitwhen
```
## Usage
```bash
# When did this string get added/removed?
gitwhen "TODO: deprecated"
# What commit last set this exact line?
gitwhen src/server/index.ts:42
# When was a file first added / deleted / re-added?
gitwhen --file backend/legacy.py
# Regex variant
gitwhen --regex "console\.log\(.*pii.*\)"
# Restrict string search to a path
gitwhen "API_KEY" --path backend/
# JSON for scripts
gitwhen "feature_flag" --json | jq '.commits[0].author'
```
## What it does
| Mode | Wraps | Output |
|---|---|---|
| `gitwhen ""` | `git log --all -S ""` | Every commit that introduced or removed this exact string, oldest first |
| `gitwhen :` | `git blame --porcelain` | Hash, author, date, subject, line content |
| `gitwhen --file ` | `git log --diff-filter=A/D` | First-added commit, every delete, re-adds, last-touched |
| `gitwhen --regex ""` | `git log --all -G ` | Same as string mode but regex matching on the diff |
Add `--json` to any for structured output ready for `jq`.
## Compared to alternatives
| tool | string-pickaxe | line-blame | file-lifespan | regex on diff | install |
|---|---|---|---|---|---|
| gitwhen | yes | yes | yes | yes | one npm install |
| `git log -S` | yes | no | no | no | bundled |
| `git blame` | no | yes | no | no | bundled |
| `git log --diff-filter` | no | no | yes | no | bundled |
| GitLens (VS Code) | yes | yes | yes | partial | editor extension |
If you live in VS Code, GitLens does this and more. For a terminal-resident workflow (server triage, code review on a remote box), gitwhen is the consolidating CLI.
## FAQ
**Why search across all branches by default?** Because regressions tend to live in *some* branch you forgot about. `git log -S` defaulting to current branch means "I know what reverted me" misses the obvious answer.
**Performance on a 100K-commit repo?** First search is bound by `git log -S` itself (a few seconds in pathological cases). gitwhen adds <100ms of parsing on top.
**Does it find renames?** For `--file` mode yes (we pass `--follow`). For string-pickaxe mode renames don't matter — the content is what's tracked.
**What about `git log --all -L `?** That's the "evolution of this exact line" view. It's powerful but slow on large files; gitwhen's blame mode is the snapshot ("who set this *now*"). Different question, different tool.
## Exit codes
- `0` — found at least one match
- `1` — no commits matched (empty timeline)
- `2` — invalid arguments or not a git repo
Wire it into a pre-commit / CI guardrail:
```bash
gitwhen --json "OLD_DEPRECATED_API" | jq -e '.count > 0' > /dev/null && {
echo "OLD_DEPRECATED_API is back in your tree."
exit 1
}
```
## Programmatic API
```javascript
const { searchString, blameLine, fileLifespan } = require('@v0idd0/gitwhen');
const r = searchString('feature_flag', { cwd: '/path/to/repo' });
console.log(r.commits[0]);
// { hash, short, author, email, date, subject }
```
## More from the studio
This is one tool out of many — see [`from-the-studio.md`](from-the-studio.md) for the full lineup of vøiddo products (other CLI tools, browser extensions, the studio's flagship products and games).
## From the same studio
- **[@v0idd0/jsonyo](https://www.npmjs.com/package/@v0idd0/jsonyo)** — JSON swiss army knife, 18 commands, zero limits
- **[@v0idd0/envguard](https://www.npmjs.com/package/@v0idd0/envguard)** — stop shipping `.env` drift to staging
- **[@v0idd0/depcheck](https://www.npmjs.com/package/@v0idd0/depcheck)** — find unused dependencies in one command
- **[@v0idd0/gitstats](https://www.npmjs.com/package/@v0idd0/gitstats)** — git repo analytics, one command
- **[View all tools →](https://voiddo.com/tools/)**
## License
MIT — part of the [vøiddo](https://voiddo.com/?ref=gitwhen-studio-readme) tools collection.
---
Built by [vøiddo](https://voiddo.com/) — a small studio shipping AI-flavoured products, free dev tools, Chrome extensions and weird browser games.