From 6a42c8de66e3b2dc7293ddeadaa3ee396db2624d Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sat, 12 Oct 2013 13:47:42 -0400 Subject: initial commit --- public/git-go-pre-commit.md | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 public/git-go-pre-commit.md (limited to 'public/git-go-pre-commit.md') 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. -- cgit v1.2.3