Skip to content

Instantly share code, notes, and snippets.

@chadmaughan
Last active November 25, 2022 00:38
Show Gist options
  • Star 48 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save chadmaughan/5889802 to your computer and use it in GitHub Desktop.
Save chadmaughan/5889802 to your computer and use it in GitHub Desktop.
A git pre commit hook that runs the test task with the gradle wrapper
#!/bin/sh
# this hook is in SCM so that it can be shared
# to install it, create a symbolic link in the projects .git/hooks folder
#
# i.e. - from the .git/hooks directory, run
# $ ln -s ../../git-hooks/pre-commit.sh pre-commit
#
# to skip the tests, run with the --no-verify argument
# i.e. - $ 'git commit --no-verify'
# stash any unstaged changes
git stash -q --keep-index
# run the tests with the gradle wrapper
./gradlew test
# store the last exit code in a variable
RESULT=$?
# unstash the unstashed changes
git stash pop -q
# return the './gradlew test' exit code
exit $RESULT
@KenVanHoeylandt
Copy link

Thanks, this is very useful!
For people using Gradle, I made a self-installing commit hook.

@gideonaina
Copy link

Is there a reason for stashing unstaged changes (line 12) before running the gradle task?

@t-buss
Copy link

t-buss commented Jul 16, 2019

@gideonaina The working directory may be different from the staging area. Say you staged a version of a file which fails the test and fixed the file in the working directory. If you just run ./gradlew test, then the test would run against the working directory and pass, while staging are still contains the failing file. The hook would pass and the staged failing file would be commited.

@jknair0
Copy link

jknair0 commented May 15, 2022

what if you have nothing to stash now but you have the non-empty stash. It would pop the unneeded.

@hellosagar
Copy link

the staged failing

I don't get it exactly

@t-buss
Copy link

t-buss commented Jun 7, 2022

@hellosagar let me rephrase: "The hook would pass and the staged file (which makes the tests fail) would be committed without the fix for this error in the working directory."

@hellosagar
Copy link

hellosagar commented Jun 7, 2022

@t-buss sorry if I'm asking a noob question, I'm learning about the pre-commit, what I don't get is that

  • is this script working only on the code which is already in a commit?
  • what do you mean exactly by working directory and staging area? I know when we are doing git add ... it will add that to the staging area, what do we mean by working directory tho? which is not added to the staging area? or it is already in commit

@t-buss
Copy link

t-buss commented Jun 7, 2022

This script is working on the changes you have staged, right after you hit enter on "git commit" and right before the commit is created. It runs ./gradlew test on the code from the latest commit + these staged changes.
The working directory is what's in your project directory, independent from git. You could say that the working directory is "the green (staged) stuff, the red (unstaged) stuff and all unchanged files".

Now, when you have some staged change that makes the tests fail and you fix it, but do not add the change to the staging area, then running /.gradlew test would still work because Gradle runs against the working directory. But both changes have to be committed together. That's why this pre-commit hook stashes "the red stuff" first, so: working directory == unchanged files + staged files aka "the green stuff"

@hellosagar
Copy link

hellosagar commented Jun 7, 2022

ohh, Thanks @t-buss 🙇‍♂️🙇‍♂️🙇‍♂️ for the clear explanation

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