Format Your .NET Code with Git Hooks

ollowing the correct code convention is directly help to the quality of code. Badly formatted code can make it really hard to spot bugs or even to work on a program.

You can define and manage a consistent code style in your codebase with the use of an EditorConfig file. EditorConfig includes numerous core formatting properties, such as indent_style and indent_size.

In Visual Studio, .NET coding conventions settings can also be configured by using an EditorConfig file. You can enable or disable individual .NET coding conventions and configure the degree to which you want each rule enforced, via a severity level.

When you define coding conventions in an EditorConfig file, you’re configuring how you want the code style analyzers that are built into Visual Studio to analyze your code. The EditorConfig file is the configuration file for these analyzers.

This article describes how to format a .NET Core project using dotnet-format ,.editorconfig file and git hooks. What we are going to do here is, defining C# Formatting Rules such as Newline preferences, Indentation preferences and Space preferences in the .editorconfig file and enable the dotnet-format command during commit. This solution helps developers to avoid mistakes of formatting with less effort. All the defined formattings will happen when commit.

Dotnet-format

dotnet-format is a code formatter for dotnet that applies style preferences to a project or solution. Preferences will be read from an .editorconfig file, if present, otherwise a default set of preferences will be used.

Step 01
First of all let’s add the .editorconfig file into our solution. I am using Visual Studio for this demo.

Right click on your solution ⟶ Add ⟶ Add New Item

Then Select editorconfig File (.NET)

There are three supported .NET coding convention categories:
⭐Language conventions
⭐ Formatting conventions
⭐ Naming conventions

You can edit the given default conventions according to your desire.

Step 02
Now we need to install dotnet-format package globally.

The dotnet-format nuget package is published to nuget.org. You can install the tool using the following command in Package Manager Console.

dotnet tool install -g dotnet-format

Step 03
It is time to write our git hook. But before that, we have to consider the behavior of git hooks. Usually, git hooks are placed in .git\hooks folder. As .git folder does not version control we should use a separate way to store and version control out git hook. To do this I use the following hack.

  1. Create a folder called Script inside the root. and create a subfolder called git_hooks

2. Copy the content inside .git/hooks folder into Scripts/git_hooks

3. Rename the pre-commit.sample into pre-commit

4. Now we can write the script for invoking dotnet-format command

#!/bin/sh
LC_ALL=C
# Select files to format
FILES=$(git diff --cached --name-only --diff-filter=ACM "*.cs" | sed 's| |\\ |g')
[ -z "$FILES" ] && exit 0
# Format all selected files
echo "$FILES" | cat | xargs | sed -e 's/ /,/g' | xargs dotnet-format --files
# Add back the modified files to staging
echo "$FILES" | xargs git add
exit 0

But still, there should be a way to copy the content inside Scripts/git_hooks into .git/hooks to do that, we can write a simple javascript file to copy the content inside folder one to folder two. Create a file called init.js inside Scripts folder.

And add the code to copy the content of Scripts/git_hooks folder into .git/hooks

var fs   = require('fs');
var path = require('path');
var exec = require('child_process').exec;
var hiddenHooksFolderPath = path.join(__dirname, '../.git/hooks');
var hooksFolderPath = path.join(__dirname, 'git_hooks');
var hooks = fs.readdirSync(hooksFolderPath);
function copyFile (source, target, cb) {
var cbCalled = false;
var rd = fs.createReadStream(source);
var wr = fs.createWriteStream(target);
function done(err) {
if (!cbCalled) {
cb(err);
cbCalled = true;
}
}
rd.on("error", done);
wr.on("error", done);
wr.on("close", done);
rd.pipe(wr);
}
hooks.forEach(function (hook) {
var hookSource = path.join(hooksFolderPath, hook);
var hookTarget = path.join(hiddenHooksFolderPath, hook);
copyFile(hookSource, hookTarget, function (err) {
if (!err) {
console.log(hook + ' added to your .git/hooks folder')
exec(
'chmod +x ' + hookTarget,
function (error) {
if (!error) {
console.log(hookTarget + ' made executable');
}
}
);
}
})
});

To automate the execution of this init.js file, we can use a build event. Go back to your project folder and right-click.

Right Click ⟶ Properties ⟶ Build Events

Inside Pre-build event command line space, write the following command to execute the init.js file to copy the git_hooks.

if $(ConfigurationName) == Debug node ../Scripts/init.js

Now we are almost done.

We can simply build our code and the content inside the Scripts/git_hooks folder will copy into .git/hooks and your pre-commit hook is ready!!

Let’s format 😎

Build the code ⟶ commit the code

It will format all changed files.

Summary

These are the main steps:

Step 01: Add .editorconfig
Step 02 : Install dotnet-format nuget package globally
Step 03 : Setting up pre-commit hook to execute dotnet-format command
Step 03 : Test your code

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store