Question

I followed this guide on creating git pre-commit hooks, and so far I really like the benefit it's given me.

However, I have a problem when I use it:

  1. I write some code, perhaps something that doesn't pass a rubocop inspection.
  2. I stage it, then attempt to commit it. The pre-commit hook works as intended.
  3. I go and fix the issues that rubocop reported.
  4. I save the changes, but forget to add it to the index.

When I commit, my script just takes the list of files changed that are in git diff --cached --name-only --diff-filter=AM, runs rubocop on each of them, and quits if there's any issues.

Here's my script:

#!/bin/sh

# Set the ruby environment from local/rvm, depending on your machine.
# http://stackoverflow.com/questions/17515769
if [ -d "$HOME/.rvm/bin" ]; then
  PATH="$HOME/.rvm/bin:$PATH"
  [[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"

  if [ -f ".ruby-version" ]; then
    rvm use "$(cat .ruby-version)"
  fi

  if [ -f ".ruby-gemset" ]; then
    rvm gemset use "$(cat .ruby-gemset)"
  fi
fi

# http://codeinthehole.com/writing/tips-for-using-a-git-pre-commit-hook/
FILES_PATTERN='\.rb(\..+)?$'
FORBIDDEN='debug'

# Quit if no ruby files are being checked in.
RB_FILES=$(git df --cached --name-only --diff-filter=AM | grep -Ec $FILES_PATTERN)
if [ "$RB_FILES" = "0" ]; then
    exit 0
fi

git diff --cached --name-only --diff-filter=AM | \
    grep -E $FILES_PATTERN | \
    GREP_COLOR='37;41' xargs grep --color --with-filename -n $FORBIDDEN && \
    echo 'Please remove debugging statements before commiting.' && exit 1

# Pull in altered files, check with rubocop.
git diff --cached --name-only --diff-filter=AM | \
    grep -E $FILES_PATTERN | xargs rubocop -f simple | \
    grep 'no offences detected' && exit 0
# If it didn't exit 0 above, warn of issues, output results.
echo 'Rubocop has detected issues with your commit.' && \
    git diff --cached --name-only --diff-filter=AM | \
    grep -E $FILES_PATTERN | xargs rubocop -f simple && exit 1

I don't want to use sed to parse through the results of git diff. Is there an easier way to ensure that I'm checking the index, opposed to the file as it appears on disk?

My instinct tells me that there may be a way to check if there are any files that are both in git diff --name-only --cached --diff-filter=M and git diff --name-only --diff-filter=M, and just quit if that's the case.

Other suggestions are welcome.

Was it helpful?

Solution

If I understood your problem correctly, you need to have files as they are in index at hand.

To do so, you can do git stash -k (keeping index) before running your utility and git stash pop afterwards assuming it won't change anything so that no conflicts would appear.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top