summaryrefslogtreecommitdiff
path: root/public/git-go-pre-commit.html
diff options
context:
space:
mode:
Diffstat (limited to 'public/git-go-pre-commit.html')
-rw-r--r--public/git-go-pre-commit.html71
1 files changed, 71 insertions, 0 deletions
diff --git a/public/git-go-pre-commit.html b/public/git-go-pre-commit.html
new file mode 100644
index 0000000..7349e46
--- /dev/null
+++ b/public/git-go-pre-commit.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>A git pre-commit hook for automatically formatting Go code — Luke T. Shumaker</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <link rel="stylesheet" href="assets/style.css">
+ <link rel="alternate" type="application/atom+xml" href="./index.atom" name="web log entries"/>
+</head>
+<body>
+<header><a href="/">Luke T. Shumaker</a> » <a href=/blog>blog</a> » git-go-pre-commit</header>
+<article>
+<h1 id="a-git-pre-commit-hook-for-automatically-formatting-go-code">A
+git pre-commit hook for automatically formatting Go code</h1>
+<p>One of the (many) wonderful things about the Go programming language
+is the <code>gofmt</code> tool, which formats your source in a canonical
+way. I thought it would be nice to integrate this in my <code>git</code>
+workflow by adding it in a pre-commit hook to automatically format my
+source code when I committed it.</p>
+<p>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.</p>
+<p>I found a few solutions online, but they were all missing
+something—support for partial commits. I frequently use
+<code>git add -p</code>/<code>git gui</code> 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.</p>
+<p>I ended up writing a solution that only formats the version of the
+that is staged for commit; here’s my
+<code>.git/hooks/pre-commit</code>:</p>
+<pre><code>#!/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=&quot;$(mktemp &quot;$file.bak.XXXXXXXXXX&quot;)&quot;
+ mv &quot;$file&quot; &quot;$tmp&quot;
+ git checkout &quot;$file&quot;
+ gofmt -w &quot;$file&quot;
+ git add &quot;$file&quot;
+ mv &quot;$tmp&quot; &quot;$file&quot;
+done</code></pre>
+<p>It’s still not perfect. It will try to operate on every
+<code>*.go</code> 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.</p>
+<p>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.</p>
+
+</article>
+<footer>
+ <aside class="sponsor"><p>I'd love it if you <a class="em"
+ href="/sponsor/">sponsored me</a>. It will allow me to continue
+ <a class="em" href="/imworkingon/">my work</a> on the GNU/Linux
+ ecosystem. Thanks!</p></aside>
+
+<p>The content of this page is Copyright © 2013 <a href="mailto:lukeshu@lukeshu.com">Luke T. Shumaker</a>.</p>
+<p>This page is licensed under the <a href="http://www.wtfpl.net/txt/copying/">WTFPL-2</a> license.</p>
+</footer>
+</body>
+</html>