blog post image
Andrew Lock avatar

Andrew Lock

~4 min read

Git integration improvements in Visual Studio 2017 - git-hooks

Visual Studio 2017 includes a whole host of improvements to its Git integration. Among other things, SSH support is built it, you can push --force-with-lease, and easily diff commits.

Some of these improvements are due to a switch in the way the Git integration works - instead of relying on libgit, VS2017 has switched to using Git.exe for all your Git interactions. That might seem like a minor change, but it actually solves a number of the issues I had in using git in my daily VS2015 work.

Git integration in Visual Studio

For those that don't know, Visual Studio has come with built in support for Git repositories for some time. You can do a lot from within VS, including staging and commiting obviously, but also merging, rebasing, managing branches (both local and remote), viewing the commit history and a whole host of other options.

Image of git history in VS 2015

I know the concept of a git UI is an abomination for some people, but for some things I really like it. Don't get me wrong, I'm very comfortable at the command line, but the built in diff view in VS works really well for me, and sometimes it's just handy to stay in your IDE.

One of the windows I use the most is the Changes window within Team Explorer. This shows you all the files you have waiting to be committed - it's essentially a visual git status. Having that there while I'm working is great, and easily lets me flick back to a file I was editing. I find it sometimes easier to work with than ctrl + Tabing through the sea of tabs I inevitably have open:

View of changes windows

Git integration limitations in VS 2015

Generally speaking, the changes window has served me well, but there were a couple of niggles. One of the problems I often ran into was when you have files in your repo that are not part of the Visual Studio solution. Normally, hitting Commit All should be equivalent to running git commit -Am "My commit message" i.e. it should commit all unstaged files. However, occasionally I find that it leaves out some files that are part of the repository but not part of the solution. I've seen it do it with word files in particular.

By calling out to the underlying git.exe executable, you can be sure that the details shown in the Changes window match those you'd get from git status; a much smoother experience.

Another feature that works from the command line, but not from the Changes window in VS 2015 was client-side git-hooks.

Using git hooks in Visual Studio 2017

I dabbled with using git-hooks on the client side a while back. These run in your checked-out repository, rather than on the git-server. You can use them for a whole variety of things, but a common reason is to validate and enforce the format of commit messages before the commit is actually made. These hooks aren't full-proof, and they aren't installed by default when you clone a repository, but they can be handy none the less.

An occasional requirement for commit messages is that they should always start with an issue number. For example, if your issue tracker, such as JIRA, produces issues prefixed with EV-, e.g. EV-123 or EV-345, you might require that all commit messages start with such an EV- issue label to ensure commits are tracked correctly.

If you create a commit-msg file inside the .git/hooks directory of your repository, then you can create a file that validates the format of your commit message before the commit is made. For example, I used this simple script to run a regex on the commit message to check it starts with an issue number:

#!C:/Program\ Files/Git/usr/bin/sh.exe

COMMIT_MESSAGE_FILE=$1
COMMIT_MESSAGE_LINE1=$(head -n 1 $COMMIT_MESSAGE_FILE)
ERR_MSG='Aborting commit. Your commit message is missing a JIRA Issue (''EV-1111'')'

MATCH_RESULT=$(echo $COMMIT_MESSAGE_LINE1 | grep -E '^EV-[[:digit:]]+.*')

if [[ ! -n "$MATCH_RESULT" ]]; then 
	echo "ERR_MSG" >&2
	exit 1
fi

exit 0

You can also use powershell and other scripting languages if you like and have them available. The commit-msg file above is specific to my windows machine and location of Git.

With this file in place, when you try and make a commit, it will be rejected with the message:

Aborting commit. Your commit message is missing a JIRA Issue (''EV-1111'')

Commit being rejected

Good, if I forget to add an issue, the message will let me know.

This might seem like a handy feature, but the big problem I had was VS 2015's use of libgit. Unfortunately, this doesn't support git hooks, which means that all our good work was for nought. VS 2015 would just ignore the hook and commit the files anyway. doh.

Enter VS 2017. With no other changes, when I click 'Commit All' from the Changes dialog, I get the warning message, and the commit is aborted!

Warning when committing from VS 2017

Once I've fixed my commit message, I can happily commit without leaving my IDE

Successful commit

This is just one of a whole plethora of updates to VS 2017, but as someone who uses the git integration a fair amount, it's definitely a welcome one.

Andrew Lock | .Net Escapades
Want an email when
there's new posts?