Development

Automate your Git flow


About debugging and something else

As Ruby on Rails developers, we use some commands that help us debugging applications like Rails.logger.debug, binding.pry or things such as a simple puts command. The lists gets bigger if we consider console.log or alert for Javascript.

The problem appears when we finish debugging and we forget to remove those lines. We include them in a commit or ever worse: we push them to our remote repo.

I don't really remember how many times I've pushed code with one or more lines of debugging information, so I decided to look up for a way of avoiding making the same mistake again.

Put scripts to work for you

Fortunately, Git has a very powerful native tool called hooks that can help running scripts before, or after, some specific moments during the Git workflow.

What is a Git hook?

A Git hook allows you to execute an script before performing some common actions in the Git workflow, such as doing a commit, pushing to a remote server or rebasing a branch.

In Git 1.8.2, the available hooks are:

  • applypatch-msg
  • commit-msg
  • post-update
  • pre-applypatch
  • pre-commit
  • prepare-commit-msg
  • pre-push
  • pre-rebase
  • update

We can find some sample scripts in all of our Git repos if we take a look at .git/hooks

image alt

Git adds the .sample extension so they are not enabled by default

One of the hooks I've been using during the last week gets executed every time I do a git commit to verify using grep if any of the files I'm about to commit contains one of the 'banned' words from the $LIST variable: if found, the script will exit with a status of 1, aborting the commit.

# Based on the git hook created by Mark Story
# http://mark-story.com/posts/view/using-git-commit-hooks-to-prevent-stupid-mistakes

# !/bin/sh
LIST="puts\|debugger\|biding.pry\|logger"

if git rev-parse --verify HEAD >/dev/null 2>&1; then
    against=HEAD
else
    against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

for FILE in `git diff-index --name-status --cached $against -- | cut -c3-` ; do
    # Check if the file contains one of the words in LIST
    if grep -w $LIST $FILE; then
      echo $FILE." has one of the word you don't want to commit. Please remove it"
      exit 1
    fi
      done
exit 

As you can see, we can create our own Git hooks and make them as complex as we need: we can run our test automatically and abort a push if the suite doesn't pass by using the pre-push hook and the following script:

# !/bin/sh
SUCESS_OUTPUT="\, 0 failures"

echo "This script will run 'rake' command to make sure your test suite passes before pushing"
echo "You can skip this script by adding '--no-verify' to your regular 'git push [repository] [branch]' command"
echo 'This can take a while...'
exec 5>&1
OUTPUT=$( rake |tee /dev/fd/5)
if  echo "$OUTPUT" | grep -q "$SUCESS_OUTPUT"; then
        echo 'Test passed! proceeding with the push'
        exit
else
        echo "Some test did not pass! Failed test are shown above. Push aborted!"
        exit 1
fi

Once you put your script into your .git/hooks directory, don't forget to make it executable:

chmod +x hook-name

What if…

As we said before, the script will run every time we perform the action related to the hook but, what if we don't want to run the hook once in a while?

Well, Git also allows us to skip the execution of hooks by adding the –no-verify option at the end of the action:

git commit -m "I don't want to use the hook' --no-verify

git push origin master --no-verify # Don't run test suite

Show me the code

The scripts shown above can be found in my Gist account so, feel free to comment or fork either the pre-push or the pre-commit scripts.

More information

If you want to dig deeper into Git hooks, I really encourage you to read Git Pro by Scott Chacon.

Thanks for reading.

Best Practices
De Código, Café y Cervezas – Clean Code
Beginner
ReactJS: Loops in JSX
Development
What is VTEX platform and why should you migrate your ecommerce to it?