fix: prevent pre-commit hook from staging unstaged changes #150

Merged
noe.trevino merged 1 commit from fix/precommit-hook-partial-staging into main 2026-05-30 15:13:18 -05:00
Owner

The gofmt pre-commit hook ran 'gofmt -w' on the working-tree copy and then 'git add ', which re-staged the entire file. Any unstaged hunks (e.g. from 'git add -p') were silently swept into the commit.

Rewrite the hook to format only the staged content:

  • capture unstaged hunks as a patch and reset staged files to index content, so gofmt only ever sees what's being committed
  • re-stage only the files gofmt actually rewrote
  • re-apply the unstaged patch to the working tree (never the index): strict apply, then a tolerant -C1 fallback, then save a recovery patch if the edits genuinely overlap the reformatted lines (no data loss)
  • abort instead of creating an empty commit when staged changes were purely formatting differences
  • handle NUL-delimited paths, temp-index/pathspec commits, and ensure gofmt is on PATH

Checklist

  • Read CONTRIBUTING.md
  • Ran tests (go test ./... -race) locally
  • Formatted and linted with gofmt -w . and golangci-lint run ./... respectively
  • Added tests if necessary (significant changes/complex logic)
  • Updated documentation if applicable
  • Updated README.md if applicable

Summary

closes #148

The gofmt pre-commit hook ran 'gofmt -w' on the working-tree copy and then 'git add <file>', which re-staged the entire file. Any unstaged hunks (e.g. from 'git add -p') were silently swept into the commit. Rewrite the hook to format only the staged content: - capture unstaged hunks as a patch and reset staged files to index content, so gofmt only ever sees what's being committed - re-stage only the files gofmt actually rewrote - re-apply the unstaged patch to the working tree (never the index): strict apply, then a tolerant -C1 fallback, then save a recovery patch if the edits genuinely overlap the reformatted lines (no data loss) - abort instead of creating an empty commit when staged changes were purely formatting differences - handle NUL-delimited paths, temp-index/pathspec commits, and ensure gofmt is on PATH ## Checklist - [x] Read `CONTRIBUTING.md` - [x] Ran tests (`go test ./... -race`) locally - [x] Formatted and linted with `gofmt -w .` and `golangci-lint run ./...` respectively - [x] Added tests if necessary (significant changes/complex logic) - [x] Updated documentation if applicable - [x] Updated `README.md` if applicable ## Summary <!-- What does this PR change and/or fix? Examples: Closes: 54 Fixes: 67 --> closes #148
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
noe.trevino/paso!150
No description provided.