This post discusses what you have to do to be able to use JGit / Egit together with git hooks when running Windows.

Git hooks currently supported by JGit / EGit

Git currently supports 13 client-side hooks. Not all of them are supported by JGit / EGit. The following (not always up-to-date) list outlines which client-side hooks have already been implemented in JGit:

  • pre-commit
  • prepare-commit-msg
  • commit-msg
  • post-commit
  • post-rewrite
  • applypatch-msg
  • pre-applypatch
  • post-applypatch
  • pre-rebase
  • pre-push
  • post-checkout
  • post-merge
  • pre-auto-gc

To get up-to-date information about what hooks are currently supported in the latest JGit version take a look at the source code of this factory class inside the JGit source code repo.

As of JGit v4.2.0 support for hooks is only enabled when the JGit file system layer detects a POSIX or a Win32 + Cygwin file system.

Necessary prerequisites to use Git hooks when running under Windows

In order for the Git hooks to be called by JGit when running under Windows you have to do two things:

  1. Install Cygwin (do not forget to install the Git package)
  2. Add the Cygwin bin folder (e.g. cygwin64\system\bin) to the Windows PATH environment variable.

The next section outlines how the JGit file system layer actually checks on which file system it is running on. So in case if you have any problems when using with JGit and Git hooks I recommend reading on.

Details about the JGit Filesystem layer

The JGit file system class hierachy is as follows:

            +----------------------+
            |abstract class        |
            |FS                    |
            +----------------------+
            |                      |
            |runHookIfPresent()    |
            |does not support hooks|
            +-----+------------+---+
                  ^            ^
                  |            |
                  |            |
                  |            |
+-----------------+----+    +--+---------------+
|class                 |    |class             |
|FS_Win32              |    |FS_POSIX          |
+----------------------+    +------------------+
|                      |    |                  |
|runHookIfPresent()    |    |runHookIfPresent()|
|does not support hooks|    |does support hooks|
+-----------------+----+    +------------------+
                  ^
                  |
                  +------+
                         |
               +---------+--------+
               |class             |
               |FS_Win32_Cygwin   |
               +------------------+
               |                  |
               |runHookIfPresent()|
               |does support hooks|
               +------------------+

The default implementation of runHookIfPresent(...) in FS does not support running hooks:

public ProcessResult runHookIfPresent(Repository repository,
        final String hookName,
        String[] args) throws JGitInternalException {
    return runHookIfPresent(repository, hookName, args, System.out, System.err,
            null);
}

And how does the FS layer decide if it’s running on a Win32 or FS_Win32 + Cygwin file system? The presence of a Cygwin installation is determined by the isCygwin() function in the FS_Win32_Cygwin class:

/**
 * @return true if cygwin is found
 */
public static boolean isCygwin() {
    final String path = AccessController
            .doPrivileged(new PrivilegedAction() {
                public String run() {
                    return System.getProperty("java.library.path"); //$NON-NLS-1$
                }
            });
    if (path == null)
        return false;
    File found = FS.searchPath(path, "cygpath.exe"); //$NON-NLS-1$
    if (found != null)
        cygpath = found.getPath();
    return cygpath != null;
}

It simply checks if the Windows PATH variable contains the file cygpath.exe. (Reminder: The java.library.path is pre-populated with the PATH entries when running under Windows.)

A note about Netcup

Netcup offers inexpensive, yet powerfull web hosting packages, KVM-based root servers or dedicated servers for example. Using a code generated by my Netcup coupon code generator you can even save more money (5$ on your first purchase, 30% off any KVM-based root server, ...).