How can I get git push to prompt for confirmation or do some checks?
I would like to set up my Git prompt to remind me or perform checks for me before I push to the remote repo.
For example, when I run
git push
Git should ask the user
Did you run unit tests locally?
or something like that so that I don't accidentally hit code that hasn't been tested.
source to share
Set up a pre-launch to prevent clicking if the file does not exist .testspassed
. Example:
cat > .git/hooks/pre-push <<EOF
#!/bin/sh -e
if ! [ -f .testspassed ]; then
echo 1>&2 "push aborted because tests were not run or did not all pass"
exit 1
fi
exit 0
EOF
chmod +x .git/hooks/pre-push
Configure your hook-commit-msg to remove .testspassed
if it exists:
cat > .git/hooks/prepare-commit-msg <<EOF
#!/bin/sh -e
rm -f .testspassed
exit 0
EOF
I use prepare-commit-msg
instead pre-commit
, because it prepare-commit-msg
works with merges too. Every time you commit or merge, git deletes the file .testspassed
, preventing you from pushing.
Tell git to ignore the file .testspassed
so it doesn't end up in your repo:
echo .testspassed >> .gitignore
git commit -m 'add .testspassed to .gitignore' .gitignore
Finally, modify your test process to "touch" .testspassed
if all of your tests pass. How you do this depends on how you run your tests.
source to share
First: It won't work (not in a technical sense, but in a human habit). See Idea by Rob Mayoff.
However, to demonstrate the implementation, you can put the following in yours ~/.bashrc
:
git() {
if [[ $1 = push ]]; then
printf %s "Did you run unit tests locally?"
read response
case $response in
y|Y|yes|YES) command git "$@" ;;
*) echo "Aborting" ;;
esac
else
command git "$@"
fi
}
Better to implement Rob's idea:
git() {
local -a options=( )
while (( $# )) && [[ $1 = -* ]]; do
case $1 in
-C|-c) options+=( "$1" "$2" ); shift; shift ;;
*) options+=( "$1" ); shift ;;
esac
done
local base_dir=$(git rev-parse --show-toplevel)
case $1 in
commit|merge|rebase)
touch "$base_dir/.untested"
command git "${options[@]}" "$@"
;;
push)
if [[ -e "$base_dir/.untested" ]]; then
echo "Untested commits exist; you must run tests"
else
command git "${options[@]}" "$@"
fi
;;
*) command git "${options[@]}" "$@" ;;
esac
}
unittest() (
cd "$(git rev-parse --show-toplevel)"
make test && rm .untested
)
source to share