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.

+3


source to share


2 answers


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.

+4


source


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
)

      

0


source







All Articles