I need to write a Git pre commit hook in Java, which would check if the code commited by the developer is formatted according to a specific eclipse code formatter before actually commiting it, otherwise reject it from commiting. Is it possible to write the pre commit hook in Java?
4 Answers
The idea is to call a script which in turns call your java program (checking the format).
You can see here an example written in python, which calls java.
try:
# call checkstyle and print output
print call(['java', '-jar', checkstyle, '-c', checkstyle_config, '-r', tempdir])
except subprocess.CalledProcessError, ex:
print ex.output # print checkstyle messages
exit(1)
finally:
# remove temporary directory
shutil.rmtree(tempdir)
This other example calls directly ant
, in order to execute an ant script (which in turns call a Java JUnit test suite)
#!/bin/sh
# Run the test suite.
# It will exit with 0 if it everything compiled and tested fine.
ant test
if [ $? -eq 0 ]; then
exit 0
else
echo "Building your project or running the tests failed."
echo "Aborting the commit. Run with --no-verify to ignore."
exit 1
fi
As of Java 11, you can now run un-compiled main class files using the java command.
$ java Hook.java
If you are using a Unix based operating system (MacOS or Linux for example), you can strip off the .java
and add a shebang to the top line like so:
#!/your/path/to/bin/java --source 11
public class Hook {
public static void main(String[] args) {
System.out.println("No committing please.");
System.exit(1);
}
}
then you can simply execute it the same way you would with any other script file.
$ ./Hook
If you rename the file pre-commit
, and then move it into your .git/hooks
directory, you now have a working Java Git Hook.
Note: You may be able to get this to work on Windows using Cygwin or Git Bash or similar terminal emulators. However, shebangs do not handle spaces well. I tested that this works by moving a copy of java into a directory without spaces and it works fine.
-
I have updated the answer because it appears there has been some confusion. Shebangs are a Unix feature. Commented May 8, 2022 at 10:36
You can write the hook in any language that can be understood by the shell, with the properly configured interpreter (bash, python, perl) etc.
But, why not write your java code formatter in java, and invoke it from the pre-commit hook.
Yes, you can write a git hook in java.
Attempted solution
I attempted Rudi's solution for my commit-msg hook:
commit-msg file
#!C:/Progra~1/Java/jdk-17.0.1/bin/java.exe --source 17
#Using Progra~1 to represent "Program Files" as escaping the space
#or surrounding the path in double quotes didn't work for me.
public class Hook {
public static void main(String[] args) {
System.out.println("No committing please.");
System.exit(1);
}
}
But I received this error message and had difficulty troubleshooting
$ git commit -m "Message"
Error: Could not find or load main class .git.hooks.commit-msg
Caused by: java.lang.ClassNotFoundException: /git/hooks/commit-msg
Solution that worked for me
Then I found a source that outlines another way.
The commit-msg hook looks like this
#!bin/sh
DIR=$(dirname "$0")
exec java $DIR/commit-msg.java "$@"
This saves the current directory (.git/hooks) of the git commit command to a variable to help build the path to the java file. Then the shell executes the java command with the path to the java file and an argument holding the path to the COMMIT_EDITMSG file.
Then you can move the Hook class defined above into its own java file (in this case commit-msg.java) and put it in the .git/hooks directory.
Now you can run git commit -m "Message" and the commit-msg hook will block the commit
-
exec
would prevent further commands (if for examplegit add
is needed to commit some changes) Commented May 5, 2022 at 4:50