Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing what is about to be committed in a pre-commit hook

When a pre-commit hook runs, the repository might not be clean. So if you naively run your tests, they will not be against what you're committing, but whatever happens to be in your working tree.

The obvious thing to do is to git stash --keep-index --include-untracked at the start of the pre-commit and git pop at the end. That way you are testing against the (pure) index, which is what we want.

Unfortunately, this generates merge conflict markers if you use git add --patch (especially if you edit hunks), since the contents of stash@{0} might not match up against the work tree after commit.

Another common solution is to clone the repository and run the tests in a new temporary one. There are two issues with that:

  1. we haven't committed yet, so we can't easily get a copy of the repository in the state we're about to commit; and
  2. my tests might be sensitive to the location of the current working directory, for example because of local environment configuration.

How can I restore my work-tree to whatever state it was in before the git stash --keep-index --include-untracked, without introducing merge conflict markers, and without modifying the post-commit HEAD?

like image 343
pwaller Avatar asked Sep 07 '12 14:09

pwaller


People also ask

What is a pre-commit hook?

The pre-commit hook is run first, before you even type in a commit message. It's used to inspect the snapshot that's about to be committed, to see if you've forgotten something, to make sure tests run, or to examine whatever you need to inspect in the code.

What is a pre-commit test?

Pre-commit checks your Git repo automatically before each commit to make sure specific tests pass.

Can you commit pre-commit hooks?

pre-commit hooks are a mechanism of the version control system git. They let you execute code right before the commit. Confusingly, there is also a Python package called pre-commit which allows you to create and use pre-commit hooks with a way simpler interface.


1 Answers

git write-tree is useful in pre-commit hooks. It writes a tree into the repo of the index (this tree will be reused if and when the commit is finalised.)

Once the tree is written to the repo, you can use git archive | tar -x to write the tree to a temporary directory.

E.g.:

#!/bin/bash

TMPDIR=$(mktemp -d)
TREE=$(git write-tree)
git archive $TREE | tar -x -C $TMPDIR

# Run tests in $TMPDIR

RESULT=$?
rm -rf "$TMPDIR"
exit $RESULT
like image 198
Gary van der Merwe Avatar answered Nov 07 '22 23:11

Gary van der Merwe