diff --git a/docs/checks/git.md b/docs/checks/git.md index f41d31c..9bf42bd 100644 --- a/docs/checks/git.md +++ b/docs/checks/git.md @@ -7,6 +7,8 @@ - `git push -f` - This command will force push and overwrite remote history and prompts for confirmation. - `git branch -D {BRANCH}` - This command will force delete a branch and prompts for confirmation. - `git checkout -f` - This command will force checkout and discard local changes and prompts for confirmation. +- `git checkout -- .` - This command will discard all local changes in the working directory. Specific files like `git checkout -- file.txt` are allowed. +- `git restore .` - This command will discard all local changes in the working directory. Specific files like `git restore file.txt` are allowed. - `git rebase -i` - This command will start an interactive rebase which can modify commit history and prompts for confirmation. - `git filter-branch` - This command will rewrite Git history and can be dangerous if used incorrectly, prompting for confirmation. - `git gc --prune=now` - This command will permanently delete unreachable objects and prompts for confirmation. diff --git a/shellfirm/checks/git.yaml b/shellfirm/checks/git.yaml index aefb838..6c17086 100644 --- a/shellfirm/checks/git.yaml +++ b/shellfirm/checks/git.yaml @@ -49,6 +49,20 @@ severity: High alternative: "git stash && git checkout " alternative_info: "Stash your changes first so they can be recovered later." +- from: git + test: git\s{1,}checkout\s{1,}--\s{1,}(\.\/?|\*)(\s|$) + description: "This command will discard all local changes in the working directory." + id: git:checkout_discard_all + severity: High + alternative: "git stash" + alternative_info: "Saves your changes to the stash so you can recover them later with 'git stash pop'." +- from: git + test: git\s{1,}restore\s{1,}(.*\s)?(\.\/?|\*)(\s|$) + description: "This command will discard all local changes in the working directory." + id: git:restore_discard_all + severity: High + alternative: "git stash" + alternative_info: "Saves your changes to the stash so you can recover them later with 'git stash pop'." - from: git test: git\s{1,}rebase\s{1,}-i description: "This command will start an interactive rebase which can modify commit history." diff --git a/shellfirm/tests/checks/git.yaml b/shellfirm/tests/checks/git.yaml index 89869e6..855b895 100644 --- a/shellfirm/tests/checks/git.yaml +++ b/shellfirm/tests/checks/git.yaml @@ -308,6 +308,73 @@ description: "force checkout with -- separator" expect_ids: ["git:force_checkout"] +# -- git:checkout_discard_all -- +- test: "git checkout -- ." + description: "match checkout discard all changes" + expect_ids: ["git:checkout_discard_all"] +- test: "git checkout -- ./" + description: "match checkout discard all with trailing slash" + expect_ids: ["git:checkout_discard_all"] +- test: "git checkout -- *" + description: "match checkout discard with glob" + expect_ids: ["git:checkout_discard_all"] +- test: "git checkout -- ." + description: "match checkout discard all with extra spaces" + expect_ids: ["git:checkout_discard_all"] +- test: "git checkout -- file.txt" + description: "negative: checkout specific file should not match" + expect_ids: [] +- test: "git checkout -- src/main.rs" + description: "negative: checkout specific file path should not match" + expect_ids: [] +- test: "git checkout -- .gitignore" + description: "negative: checkout dotfile should not match" + expect_ids: [] +- test: "git checkout -- .env" + description: "negative: checkout .env file should not match" + expect_ids: [] + +# -- git:restore_discard_all -- +- test: "git restore ." + description: "match restore discard all changes" + expect_ids: ["git:restore_discard_all"] +- test: "git restore ./" + description: "match restore discard all with trailing slash" + expect_ids: ["git:restore_discard_all"] +- test: "git restore *" + description: "match restore discard with glob" + expect_ids: ["git:restore_discard_all"] +- test: "git restore --staged ." + description: "match restore staged discard all" + expect_ids: ["git:restore_discard_all"] +- test: "git restore --staged ./" + description: "match restore staged with trailing slash" + expect_ids: ["git:restore_discard_all"] +- test: "git restore --source=HEAD ." + description: "match restore with source flag" + expect_ids: ["git:restore_discard_all"] +- test: "git restore --staged --worktree ." + description: "match restore with multiple flags" + expect_ids: ["git:restore_discard_all"] +- test: "git restore ." + description: "match restore discard all with extra spaces" + expect_ids: ["git:restore_discard_all"] +- test: "git restore file.txt" + description: "negative: restore specific file should not match" + expect_ids: [] +- test: "git restore --staged file.txt" + description: "negative: restore staged specific file should not match" + expect_ids: [] +- test: "git restore src/main.rs" + description: "negative: restore specific file path should not match" + expect_ids: [] +- test: "git restore .gitignore" + description: "negative: restore dotfile should not match" + expect_ids: [] +- test: "git restore .env" + description: "negative: restore .env file should not match" + expect_ids: [] + # -- git:reset — more variants -- - test: "git reset --hard" description: "hard reset, most dangerous variant"