Format Your .NET Code with Git Hooks
Following 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.
- Create a folder called
Script
inside the root. and create a subfolder calledgit_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 addexit 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