Protection patterns for git operations including force push, reset, clean, and branch deletion
shellfirm provides two groups of git checks: git (standard) for clearly dangerous operations and git-strict for broader coverage of history-modifying commands.
Standard git checks (git)
Force push
| |
|---|
| ID | git:force_push |
| Severity | High |
| Filter | NotContains --force-with-lease |
| Alternative | git push --force-with-lease -- checks that your local ref is up-to-date before force pushing |
| Blast radius | Counts commits ahead of remote |
# Triggers
git push --force origin main
git push -f origin feature
# Does NOT trigger (safe variant)
git push --force-with-lease origin main
Reset
| |
|---|
| ID | git:reset |
| Severity | High |
| Filter | NotContains --soft |
| Alternative | git stash -- saves changes so you can recover them later |
| Blast radius | Counts modified files (staged + unstaged) |
# Triggers
git reset --hard
git reset HEAD~5
git reset --mixed
# Does NOT trigger
git reset --soft HEAD~1
Clean (force)
| |
|---|
| ID | git:clean_force |
| Severity | High |
| Filters | NotContains --dry-run, NotContains -n |
| Alternative | git clean -fdn -- dry-run shows what would be deleted |
| Blast radius | Counts untracked files/directories |
# Triggers
git clean -fd
git clean -fdx
# Does NOT trigger
git clean -fdn
git clean -fd --dry-run
Force delete branch
| |
|---|
| ID | git:force_delete_branch |
| Severity | High |
| Alternative | git branch -d <branch> -- safe delete refuses if branch has unmerged changes |
| Blast radius | Names the branch being deleted |
# Triggers
git branch -D feature-old
git branch -D experiment
Force checkout
| |
|---|
| ID | git:force_checkout |
| Severity | High |
| Alternative | git stash && git checkout <branch> -- stash changes first |
| Blast radius | Counts files with uncommitted changes |
# Triggers
git checkout -f main
git checkout -f feature
Checkout discard all
| |
|---|
| ID | git:checkout_discard_all |
| Severity | High |
| Alternative | git stash -- saves changes so you can recover them later |
# Triggers
git checkout -- .
git checkout -- ./
git checkout -- *
# Does NOT trigger (specific file is fine)
git checkout -- file.txt
git checkout -- src/main.rs
git checkout -- .gitignore
Restore discard all
| |
|---|
| ID | git:restore_discard_all |
| Severity | High |
| Alternative | git stash -- saves changes so you can recover them later |
# Triggers
git restore .
git restore ./
git restore *
git restore --staged .
git restore --source=HEAD .
# Does NOT trigger (specific file is fine)
git restore file.txt
git restore --staged file.txt
git restore src/main.rs
git restore .gitignore
Stash clear
| |
|---|
| ID | git:stash_clear |
| Severity | High |
| Alternative | git stash list -- review your stashes before clearing. Use git stash drop stash@{N} to remove individual entries |
# Triggers
git stash clear
# Does NOT trigger
git stash list
git stash drop stash@{0}
Delete all tracked files
| |
|---|
| ID | git:delete_all |
| Severity | High |
| Blast radius | Counts all tracked files in the repository |
# Triggers
git rm *
git rm .
Interactive rebase
| |
|---|
| ID | git:interactive_rebase |
| Severity | Medium |
# Triggers
git rebase -i HEAD~5
git rebase -i main
Filter-branch
| |
|---|
| ID | git:filter_branch |
| Severity | High |
| Alternative | git-filter-repo -- faster, safer, and officially recommended |
| Blast radius | Counts total commits in history |
# Triggers
git filter-branch --tree-filter 'rm -rf secrets' HEAD
Push mirror
| |
|---|
| ID | git:push_mirror |
| Severity | Critical |
Mirror push overwrites the ENTIRE remote -- all branches, tags, and refs.
# Triggers
git push --mirror
git push --mirror origin
git push origin --mirror
Push delete branch
| |
|---|
| ID | git:push_delete_branch |
| Severity | High |
# Triggers
git push origin --delete feature-branch
git push --delete origin feature
git push origin :feature-branch
Reflog expire
| |
|---|
| ID | git:reflog_expire |
| Severity | Critical |
Expiring all reflog entries destroys the last recovery mechanism for lost commits.
# Triggers
git reflog expire --expire=now --all
git reflog expire --all --expire=now
# Does NOT trigger
git reflog show
git reflog expire --expire=90.days
Other standard checks
| ID | Description | Severity |
|---|
git:gc_prune | git gc --prune=now -- permanently deletes unreachable objects | High |
git:delete_ref | git update-ref -d -- deletes a Git reference | High |
git:merge_no_ff | git merge --no-ff or git merge --abort | Medium |
git:cherry_pick | git cherry-pick -- applies changes from existing commits | Medium |
git:bisect | git bisect -- starts binary search for bugs | Medium |
git:worktree_management | git worktree add or git worktree remove | Medium |
Strict git checks (git-strict)
These checks cover broader operations. Useful for teams that want visibility into staging and committing.
| ID | Description | Severity |
|---|
git-strict:add_all | git add ., git add --all, git add -A -- stages all changes | Low |
git-strict:commit_all | git commit --all or git commit -a -- commits all changed files | Low |
git-strict:rebase | git rebase -- rewrites commit history | Medium |
git-strict:stash_pop_drop | git stash pop or git stash drop -- applies or removes stashed changes | Low |
git-strict:submodule_update | git submodule update or git submodule deinit | Low |
git-strict:create_tag | git tag -a -- creates an annotated tag | Low |
The strict checks have blast radius support for git-strict:add_all and git-strict:commit_all, showing how many files would be staged or committed.