Skip to content

post-checkout hook prevents pre-commit hooks from working with unstaged files #1418

@domodwyer

Description

@domodwyer

Hi there!

Most important thing first: pre-commit is great, it makes managing git hooks trivial and when combined with static analysis hooks, helps our team immeasurably - thanks for all the hard work.

We have pre-commit hooks that run a bunch of checks, and thanks to #1339, a post-checkout hook that does some workspace analysis and prints a few warnings if needed.

Unfortunately this seems to have broken the "stash unstaged changes" behaviour when committing - the stash runs a git checkout to clear the working directory before running the hooks, and that fails because of the post-checkout hook. I'd expect that the working directory to be cleared as normal, commit OK and then the working directory to be restored as it does without the post-checkout hook, as the actual mechanism behind removing the unstaged changes and restoring them is hidden from the user.

Below is a quick test to reproduce it:

#!/usr/bin/env bash

mkdir test
cd test || exit
git init

# Configure a pre-commit and post-checkout hook
cat << EOF > .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: pre-commit-ok
        name: Pre-commit hook that always passes
        stages: [commit]
        language: system
        entry: sh -c 'exit 0'
        always_run: true

  - repo: local
    hooks:
      - id: post-checkout-fail
        name: Post-checkout hook that fails
        stages: [post-checkout]
        language: system
        entry: sh -c 'exit 1'
        always_run: true

EOF

echo "bananas" > great-things.txt
git add .
git commit -m "init"

# Install the hooks
pre-commit install -t pre-commit
pre-commit install -t post-checkout

# Do a checkout - this is expected to print an error from the lint
git checkout -b test

# Change the original file
echo "platanos" >> great-things.txt

# Add another file and stage it
echo "42" > answer.txt
git add answer.txt

# Attempt to commit the new, staged file.
#
# Without the post-checkout hook, this causes the unstaged changes to be
# stashed and the commit works as normal.
echo ""
echo ""
echo "    Attempting to commit with unstaged changes"
echo "    This will fail when attempting to checkout as part of the commit hook:"
echo ""
echo ""
git commit -m "more info"

Unfortunately there seems to be no easy way to skip the post-checkout hook when clearing the unstaged files with git checkout.

Happy to open a PR to help fix this, just unsure what to do - I could swap the git checkout for a git stash save --keep-index --include-untracked but I assume it is using checkout for reason.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions