summaryrefslogtreecommitdiff
path: root/public/git-go-pre-commit.md
diff options
context:
space:
mode:
authorLuke Shumaker <LukeShu@sbcglobal.net>2013-10-12 13:47:42 -0400
committerLuke Shumaker <LukeShu@sbcglobal.net>2013-10-12 13:47:42 -0400
commit6a42c8de66e3b2dc7293ddeadaa3ee396db2624d (patch)
tree67a027b892d3122662526504dd6d11e8dea02ca1 /public/git-go-pre-commit.md
initial commit
Diffstat (limited to 'public/git-go-pre-commit.md')
-rw-r--r--public/git-go-pre-commit.md54
1 files changed, 54 insertions, 0 deletions
diff --git a/public/git-go-pre-commit.md b/public/git-go-pre-commit.md
new file mode 100644
index 0000000..74dca28
--- /dev/null
+++ b/public/git-go-pre-commit.md
@@ -0,0 +1,54 @@
+A git pre-commit hook for automatically formatting Go code
+==========================================================
+:copyright 2013 Luke Shumaker
+:license WTFPL-2
+
+One of the (many) wonderful things about the Go programming language
+is the `gofmt` tool, which formats your source in a canonical way. I
+thought it would be nice to integrate this in my `git` workflow by
+adding it in a pre-commit hook to automatically format my source code
+when I commited it.
+
+The Go distribution contains a git pre-commit hook that checks whether
+the source code is formatted, and aborts the commit if it isn't. I
+don't remember if I was aware of this at the time (or if it even
+existed at the time, or if it is new), but I wanted it to go ahead and
+format the code for me.
+
+I found a few solutions online, but they wre all missing
+something—support for partial commits. I frequently use `git add
+-p`/`git gui` to commit a subset of the changes I've made to a file,
+the existing solutions would end up adding the entire set of changes
+to my commit.
+
+I ended up writing a solution that only formats the version of the
+that is staged for commit; here's my `.git/hooks/pre-commit`:
+
+ #!/bin/bash
+
+ # This would only loop over files that are already staged for commit.
+ # git diff --cached --numstat |
+ # while read add del file; do
+ # ...
+ # done
+
+ shopt -s globstar
+ for file in **/*.go; do
+ tmp="$(mktemp "$file.bak.XXXXXXXXXX")"
+ mv "$file" "$tmp"
+ git checkout "$file"
+ gofmt -w "$file"
+ git add "$file"
+ mv "$tmp" "$file"
+ done
+
+It's still not perfect. It will try to operate on every `*.go`
+file—which might do weird things if you have a file that hasn't been
+checked in at all. This also has the effect of formatting files that
+were checked in without being formatted, but weren't modified in this
+commit.
+
+I don't remember why I did that—as you can see from the comment, I
+knew how to only select files that were staged for commit. I haven't
+worked on any projects in Go in a while—if I return to one of them,
+and remember why I did that, I will update this page.