42

I currently have a single repo with two projects, each in their own subfolder: one in C# and one in Javascript. I want to have a pre-commit hook that will run jshint but only if any of the staged files are in the Javascript folder If the staged files are only from the C# folder, then the pre-commit hook won't run.

Is it that possible at all? Or is my only solution to split the two projects into their own repos?

somecoolguy
  • 431
  • 1
  • 4
  • 3
  • How the repository is divided ? a branch for each projects ? – ôkio Oct 15 '14 at 07:36
  • Same problem here. We have an independent project per directory all in the same git repo and if I'm commiting a directory, I want to run only that directory's tests – nurettin Oct 22 '14 at 09:33
  • I wrote a little tool https://pypi.org/project/hooks4git/ to help to handle git hooks. Although it is not directly supported, you can call a custom script on its configuration file which solves your question. But this tool can easily be upgraded to support that. I liked the idea and created a issue there: https://github.com/lovato/hooks4git/issues/23 – Lovato Aug 06 '18 at 19:36

5 Answers5

30

If you use pre-commit, specify files to include (or exclude to exclude) specific directories, e.g. run hooks only in my_dir:

files: ^my_dir/
repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    hooks:
        ...

or run everywhere but inside my_dir:

exclude: ^my_dir/
repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    hooks:
        ...

If you have a long list of exclusions, use verbose regex:

exclude: >
  (?x)^(
      path/to/file1.py|
      path/to/file2.py|
      path/to/file3.py
  )$

you can also apply these to specific hooks only, just do:

-   id: my-hook
    exclude: ^my_dir/
Igor
  • 349
  • 1
  • 6
Tomasz Bartkowiak
  • 12,154
  • 4
  • 57
  • 62
4

Here are good native solutions.

I use something like this

if git diff --cached --quiet -- "frontend/"
then
  echo "Unchanged"
  exit 0
else
  echo "Changed"
fi
Igor
  • 349
  • 1
  • 6
2

If you are using pre-commit newer than v1.1.0, then you can add a exclude field to your .pre-commit-config.yaml which is located in the root folder of your repo.

Just like below:

exclude: '^(?!javascript/)'

Check the document here

zoron
  • 21
  • 4
1

You can use git log to find out if the latest commit in a subdir matches the latest commit at your repository root:

#!/bin/env bash

function get_commit {
    git log --oneline -- $1 | head -n 1 | cut -d " " -f1
}

ROOT_COMMIT=$(get_commit)
SUBDIR_COMMIT=$(get_commit my/subdir/path)

if [ "$SUBDIR_COMMIT" == "$ROOT_COMMIT" ]; then
    # do pre-commit hook stuff here
fi
marcusljx
  • 959
  • 7
  • 9
-1

Git hooks are scripts that Git runs before or after it does specific things.

If you write a script and save it as <repository_name>/.git/hooks/pre-commit then git will run it before committing. So write a simple script for the operating system you are using that runs jshint against that subfolder and save it to that path.

Git doesn't run your pre-commit hook with any arguments. You can use git commands to figure out the state of your repository (the changes added as part of the commit are still just staged and accessible through --cached). If you make any changes and want them to become part of the commit, you'll need to add them before the script exits.

You are working with C# so you should be aware that git hooks on windows are a bit quirky: Executing Git hooks on Windows

Community
  • 1
  • 1
Sam
  • 9