Thursday, October 23, 2014

Prevent incorrectly-formatted Go code from being committed to Git

Problem

Even though Go is beautifully straightforward and blatantly obvious as to what is going on, there is still room for coding style differences.

And what happens when you're working in a multi-developer project not every developer uses the same coding styles?

Examples

  • Use TAB character rather than spaces
  • Use 2 spaces per TAB (v. 3 or 4 spaces)
  • Open brace on new line (v. at end of line)
  • etc...
...You get to experience needless merging and git diffs, that look like every line changed.

Enough of that nonsense... Just use the following pre-commit script to force each developer to run the standard gofmt against each source file before they git committed to git.

misc/git/pre-commit script

Simply create a file named pre-commit in your /.git/hooks/ directory with the following contents:

pre-commit


#!/bin/sh
# Copyright 2012 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

# git gofmt pre-commit hook
#
# To use, store as .git/hooks/pre-commit inside your repository and make sure
# it has execute permissions.
#
# This script does not handle file names that contain spaces.

gofiles=$(git diff --cached --name-only --diff-filter=ACM | grep '.go$')
[ -z "$gofiles" ] && exit 0

unformatted=$(gofmt -l $gofiles)
[ -z "$unformatted" ] && exit 0

# Some files are not gofmt'd. Print message and fail.

echo >&2 "Go files must be formatted with gofmt. Please run:"
for fn in $unformatted; do
 echo >&2 "  gofmt -w $PWD/$fn"
done

exit 1

Make it executable


$ chmod +x .git/hooks/pre-commit

See the pre-commit hook work

Add and extra TAB.

$ git diff
diff --git a/errors.go b/errors.go
index fc62d4c..dc3addf 100644
--- a/errors.go
+++ b/errors.go
@@ -15,8 +15,8 @@ 
     defaultErrMsg := "Oops! We had an issue with your request."
-    for _, errMsg := range optionalDefaultErrMsg {
-        defaultErrMsg = errMsg
+    if len(optionalDefaultErrMsg) > 0 {
+            defaultErrMsg = errMsg
     }

$ git add-commit 'Add extra TAB to break formatting'
Go files must be formatted with gofmt. Please run:
  gofmt -w /<PROJECT_DIRECTORY_HERE>/errors.go

See the pre-commit hook work

Run gofmt -w /<PROJECT_DIRECTORY_HERE>/errors.go and try again.

This time, your commit should work and your properly formatted file will be saved to your local git repo.

Notes

Since the file pre-commit file is in your .git/hooks directory, by default it will not get checked into your repo.

So, it's safe to use. No worries about an extra commit because you created the new pre-commit file.

Others on your team could rely only on their IDE to provide gofmt functionality (and choose not use this pre-commit hook).

But you can rest assured that all of your code will always be properly formatted before any push into the team git repo.

References

http://blog.golang.org/go-fmt-your-code
https://golang.org/doc/effective_go.html

This work is licensed under the Creative Commons Attribution 3.0 Unported License.

1 comment:

  1. It is really a great idea for developers team. I used similar way when I worked on my project because my teammate did not work in Git. I also read about information about mobile app development company which uses a variety of schemes of work in development styles - http://www.intellectsoft.co.uk/

    ReplyDelete