Git Commit Messages and Hooks

Maintaining integrity in your code is hard. Git hooks are an easy way to manage your workflow so you never commit code that doesn’t meet your standards.

How do you know if the changes you made introduced bugs? Testing of course. Do you know if your code follows best practices? To figure that out, you’d use a linter. In PowerShell the community uses Pester for testing and PSScriptAnalyzer for making sure you follow community standards. Git hooks let you validate your code before it is committed in Git.

Another useful feature that Git provides is the ability to pre-populate your commit message. Maybe your commit messages would benefit from template or maybe a reminder to describe your changes.

Pre-Commit Hooks

With the pre-commit hook the key is to make sure your hook exits correctly. Every initialized repository comes with a sample git hooks.

Get-ChildItem .git\hooks\ -Recurse

Directory: Git:\project\.git\hooks

Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 11/20/2017 8:25 PM 478 applypatch-msg.sample
-a---- 11/20/2017 8:25 PM 896 commit-msg.sample
-a---- 11/20/2017 8:25 PM 189 post-update.sample
-a---- 11/20/2017 8:25 PM 424 pre-applypatch.sample
-a---- 11/20/2017 8:25 PM 1642 pre-commit
-a---- 11/20/2017 8:25 PM 1642 pre-commit.sample
-a---- 11/20/2017 8:25 PM 1348 pre-push.sample
-a---- 11/20/2017 8:25 PM 4898 pre-rebase.sample
-a---- 11/20/2017 8:25 PM 544 pre-receive.sample
-a---- 11/20/2017 8:25 PM 1239 prepare-commit-msg.sample
-a---- 11/20/2017 8:25 PM 3610 update.sample

To start, create a pre-commit file in the .git\hooks\ directory located in your repository. Since this is a PowerShell blog we’re going to use a bash script to invoke PowerShell.

>#!/bin/sh
c:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -ExecutionPolicy Bypass -NoProfile -File '.git\hooks\pre-commit.ps1'

In the pre-commit.ps1 file you can write standard PowerShell code. Write-Host can be used to write errors to the screen.

What governs whether a commit message is saved or not is the exit code PowerShell.exe throws. If you’d like to keep someone from being able to commit, add the following:

Write-Host "Aborting Commit" -ForegroundColor Red
exit 1

PSScriptAnalyzer

Consider a file named alias.ps1 needs to be added to your repository but was copy and pasted from the PowerShell console. Now I don’t know about you, but I try to save as many characters as I can when so I use lots of aliases.

When I go to commit the quick script I get an error. Notice your prompt, I still have one file sitting in the staging area. The script I attempted to put into source control didn’t meet the standards from PSScriptAnalyzer.

$Results = Invoke-ScriptAnalyzer -Severity Error, Warning .\ -Recurse

if ( $Results.count -gt 0 ) {
    "Found {0} issues" -f $Results.Count
    $Results
    exit 1
}

Pester

If you’ve been writing Pester tests with your work you can also leverage your work to make sure you always commit clean code. Consider the the following tests:

Describe "Addition" {
    It "Can't Add" {
        5 | should be 4
    }
}

It is designed to fail to illustrate the ability to keep git from finalizing your commit. Our pre-commit.ps1 file will look similar to our previous one. It will abort the commit on any failing Pester tests.

$Results = Invoke-Pester -Show Failed, describe -PassThru

if ( $Results.FailedCount -gt 0 ) {
    exit 1
}

Other Uses

You can also use pre-commit hooks to sign your PowerShell files to make sure they comply with security practices on your network. Another use could be to put your .ps1 files through a code formater that makes sure you’re following company code styles.

Commit Messages

Commit messages have a nasty habit of devolving.

XKCD

To combat this tendency git has a configuration where you can add information and instructions to your commit message so you are reminded to leave the useful comments.

First, create a text file with your template commit message. Here is a simple example of a commit message that keeps you on track. Remember, anything that begins with a ‘#’ character is ignored in a commit message.

## Subject 


## Body


## Files Changed


## Link to Issue in tracker
To associate the template with your local repository use the following.
git config --global commit.template .\commit_template.txt