Skip to content

Instantly share code, notes, and snippets.

@radlinskii
Last active October 5, 2022 15:56
Show Gist options
  • Star 30 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save radlinskii/0ba6ec694b1e590d8457c98a358f335f to your computer and use it in GitHub Desktop.
Save radlinskii/0ba6ec694b1e590d8457c98a358f335f to your computer and use it in GitHub Desktop.
pre-commit git hook file for working in Go. Be sure to save this file in your repository as `.git/hooks/pre-commit` and give it right to execute e.g. with command `chmod +x .git/hooks/pre-commit`
#!/bin/sh
STAGED_GO_FILES=$(git diff --cached --name-only | grep ".go$")
if [[ "$STAGED_GO_FILES" = "" ]]; then
exit 0
fi
GOLINT=$GOPATH/bin/golint
GOIMPORTS=$GOPATH/bin/goimports
# Check for golint
if [[ ! -x "$GOLINT" ]]; then
printf "\t\033[41mPlease install golint\033[0m (go get -u golang.org/x/lint/golint)"
exit 1
fi
# Check for goimports
if [[ ! -x "$GOIMPORTS" ]]; then
printf "\t\033[41mPlease install goimports\033[0m (go get golang.org/x/tools/cmd/goimports)"
exit 1
fi
PASS=true
for FILE in $STAGED_GO_FILES
do
# Run goimports on the staged file
$GOIMPORTS -w $FILE
# Run golint on the staged file and check the exit status
$GOLINT "-set_exit_status" $FILE
if [[ $? == 1 ]]; then
printf "\t\033[31mgolint $FILE\033[0m \033[0;30m\033[41mFAILURE!\033[0m\n"
PASS=false
else
printf "\t\033[32mgolint $FILE\033[0m \033[0;30m\033[42mpass\033[0m\n"
fi
# Run govet on the staged file and check the exit status
go vet $FILE
if [[ $? != 0 ]]; then
printf "\t\033[31mgo vet $FILE\033[0m \033[0;30m\033[41mFAILURE!\033[0m\n"
PASS=false
else
printf "\t\033[32mgo vet $FILE\033[0m \033[0;30m\033[42mpass\033[0m\n"
fi
done
if ! $PASS; then
printf "\033[0;30m\033[41mCOMMIT FAILED\033[0m\n"
exit 1
else
printf "\033[0;30m\033[42mCOMMIT SUCCEEDED\033[0m\n"
fi
exit 0
@leucos
Copy link

leucos commented Aug 11, 2019

Nice !
A few hiccups though:

  • for the [[ construct to work, the shebang line should be #!/bin/bash
  • go vet will fail when testing a single file when a package has several files and a struct defined in one of them is used in another on (the one being staged)

@akfaew
Copy link

akfaew commented Aug 29, 2019

Better to grep "\.go$", not grep ".go$"

@fonini
Copy link

fonini commented Mar 3, 2020

When you delete a file, the go vet will fail. I'm filtering the staged files to exclude the deleted ones.

STAGED_GO_FILES=$(git diff --cached --name-status --diff-filter d -- '*.go' | awk '{ print $2 }')

It's also necessary to add the following block to the for loop to fix the file renames.

if [ ! -f "$FILE" ]; then
  git add $FILE
  continue
fi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment