Imported from shipshitdev/skills (
skills/git-safety/SKILL.md). Install upstream withnpx skills add shipshitdev/skills --skill git-safety. Copyright stays with the author.
Git Safety
Two guards, one repository you already work in every day:
- Staged guard — nothing sensitive enters the next commit.
- Operation guard — no destructive git command runs unconfirmed and unbacked.
Both are recurring. They run at commit time and at push time, on every branch, forever. A one-time audit of a whole repository before it goes public is a different moment — see Related.
Authorized Scope
Apply this engine only within the user's requested task and existing explicit authorization. Loading or delegating to it grants no additional authority. Preserve report-only restrictions and the caller's target, host, provider, and cost limits. Existing approval satisfies a gate only for the same actions and scope; obtain approval before expanding them. Forward these limits to delegates.
Contract
Inputs:
- Repository root
- Mode:
scan,guard,prevent,clean, orfull - For
clean: the leaked path or secret string, and the refs it touches
Outputs:
- Staged findings with a block/allow verdict per file
- Destructive-operation risk assessment and backup command
- Rotation checklist for anything already pushed
Creates/Modifies:
scanandguard: no file changesprevent:.gitignore,.env.example, and hook filesclean: rewritten git history, only after explicit confirmation
External Side Effects:
- May force-push rewritten history in
cleanmode - Requires credential rotation on systems outside the repository
Confirmation Required:
- Before rewriting history
- Before force-pushing or any push that discards remote commits
- Before
reset --hard,clean -fdx, or branch/tag deletion - Before changing hooks or ignore rules in a shared repository
Delegates To:
open-source-checkerbefore publishing a private repositorysecurity-auditfor broader application-security review
Default a delegated safety check to scan or guard. Hook installation,
credential rotation, and history rewriting require their own authorized action;
finding a secret does not authorize those mutations automatically.
Rotate first
Removing a secret from git history does not make it safe. Once pushed:
- Bots scrape new pushes within seconds
- Archive and mirror services may hold snapshots
- Forks keep the original history
- CI/CD logs may hold the value
Rotate the credential at its source before touching history. History rewriting is cleanup, never containment. The bound: the old value is rejected by the issuing system.
Modes
| Mode | Moment | Ends when |
|---|---|---|
scan |
Before committing | Every staged file and added line is cleared or flagged |
guard |
Before a destructive command | Blast radius stated, backup made, operator confirmed |
prevent |
Once per repo, then on drift | Ignore rules and hook block a known-bad test commit |
clean |
After a confirmed leak, post-rotation | Secret absent from every ref, collaborators notified |
full |
New repo onboarding | scan → prevent complete |
scan — staged guard
Scope is the working tree and the staged diff, not history.
# Files about to be committed
git diff --cached --name-only
# Sensitive filenames among them
git diff --cached --name-only | grep -iE '(^|/)\.env($|\.)|\.(pem|key|p12|pfx|secret)$|credentials|service-account|id_rsa|id_ed25519|\.npmrc$|kubeconfig'
# Secret-shaped values in added lines only
git diff --cached -U0 | grep -E '^\+' | grep -iE '(api[_-]?key|secret[_-]?key|client[_-]?secret|access[_-]?token|auth[_-]?token|password)[^a-z]{0,4}[=:][^=:]{8,}'
# Untracked files sitting in the tree that must never be added
git status --porcelain --untracked-files=all | grep -E '^\?\?' | grep -iE '\.env|\.pem$|\.key$|credentials|secrets\.'
Verdict per finding: block (real credential), allow (placeholder, fixture, or example), or ask when the value cannot be classified from the diff alone. Report the file and line for each block. Ends when every staged path carries a verdict.
guard — destructive operation gate
Any of these rewrites or discards work that git cannot recover for a collaborator:
| Command | Discards |
|---|---|
git push --force / --force-with-lease |
Remote commits others may hold |
git filter-repo, bfg |
Every commit hash in the repository |
git reset --hard |
Uncommitted work in the tree and index |
git clean -fdx |
Untracked files, including local .env |
git checkout -- <path> |
Uncommitted edits to that path |
git branch -D, git push origin --delete |
Unmerged commits on that ref |
git rebase on a pushed branch |
Published commits under collaborators |
Before running one:
- State the blast radius — which refs change, whose clones break, what is unrecoverable.
- Back up —
git clone --mirror . ../repo-backup-$(date +%Y%m%d)for any history rewrite;git stash -ubefore areset --hardorclean -fdx. - Prefer the reversible form —
--force-with-leaseover--force,git revertoverreset --hardon a pushed branch,git stashovercheckout --. - Confirm with the operator, quoting the exact command.
Ends when the operator confirms against a stated blast radius, or the reversible alternative is used instead.
prevent — make the guard automatic
Add the ignore rules, write the pre-commit hook, and create .env.example.
Patterns, the full hook script, and git secrets setup are in
references/full-guide.md.
Ends when a deliberate test commit of a dummy .env is rejected by the hook.
clean — rewrite history after a leak
Runs only after rotation is confirmed, and only inside the guard gate above.
git clone --mirror . ../repo-backup-$(date +%Y%m%d)
git filter-repo --path .env --invert-paths
git push origin --force --all && git push origin --force --tags
Verify:
git log --all --full-history -- .env # empty
git log -p --all -S '<rotated-value>' # empty
Ends when both verifications return empty and every collaborator has re-cloned.
Emergency response
A credential is in a pushed commit:
- Rotate the credential. Nothing else counts until this is done.
- Check the provider's access logs for use of the old value.
- Run
cleanto strip it from history. - Force-push through the
guardgate. - Tell collaborators to re-clone; forks and open PRs keep the old history.
- Run
preventso the same file cannot be staged again. - Write down what leaked, when, and what was rotated.
Related
open-source-checker— the one-time audit before a private repository is published: license and attribution, secrets across the entire history, internal hostnames and employee references. Run it once, at the publish decision; rungit-safetyat every commit thereafter.security-audit— application-level vulnerability review, not git state.
Full sensitive-file patterns, the complete pre-commit hook script, .gitignore
template, git secrets setup, BFG alternative, and platform notes:
references/full-guide.md