<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ktlint Archives - Codersee blog- Kotlin on the backend</title>
	<atom:link href="https://blog.codersee.com/tag/ktlint/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>Kotlin &#38; Backend Tutorials - Learn Through Practice.</description>
	<lastBuildDate>Wed, 16 Apr 2025 04:49:37 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://blog.codersee.com/wp-content/uploads/2025/04/cropped-codersee_logo_circle_2-32x32.png</url>
	<title>ktlint Archives - Codersee blog- Kotlin on the backend</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Ktlint with pre-commit Hook: Git Hooks in Kotlin Made Easy</title>
		<link>https://blog.codersee.com/git-hooks-kotlin-automate-ktlint-pre-commit-hook/</link>
					<comments>https://blog.codersee.com/git-hooks-kotlin-automate-ktlint-pre-commit-hook/#respond</comments>
		
		<dc:creator><![CDATA[Piotr]]></dc:creator>
		<pubDate>Tue, 05 Dec 2023 05:30:00 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[code style]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[git hook]]></category>
		<category><![CDATA[ktlint]]></category>
		<guid isPermaLink="false">https://codersee.com/?p=9008405</guid>

					<description><![CDATA[<p>In this article, we will learn how easily we can automate our Kotlin project with git hooks on the example of Ktlint pre-commit check.</p>
<p>The post <a href="https://blog.codersee.com/git-hooks-kotlin-automate-ktlint-pre-commit-hook/">Ktlint with pre-commit Hook: Git Hooks in Kotlin Made Easy</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>In this article, we will learn how easily we can automate our Kotlin project with <strong>git hooks</strong> on the example of <strong>Ktlint pre-commit check</strong>. </p>



<p>At the end of this tutorial, you will know precisely: </p>



<ul class="wp-block-list">
<li>what are Git client-side Hooks, </li>



<li>what types of client-side hooks Git offers, </li>



<li>how to implement an automated code check before we commit our changes, </li>



<li>and how to combine that together with Kotlin and Gradle. </li>
</ul>



<p>And although this guide may seem a bit specific, you can trust me that after reading it you will be able to adjust this knowledge to many other cases in your real-life scenarios. </p>



<h2 class="wp-block-heading" id="h-video-tutorial">Video Tutorial</h2>



<p>If you prefer <strong>video content</strong>, then check out my video:</p>



<div style="text-align: center; width: 90%; margin-left: 5%;">
<a href="https://blog.codersee.com/git-hooks-kotlin-automate-ktlint-pre-commit-hook/"><img decoding="async" src="https://blog.codersee.com/wp-content/plugins/wp-youtube-lyte/lyteCache.php?origThumbUrl=%2F%2Fi.ytimg.com%2Fvi%2FD_oQwhcWr4M%2Fhqdefault.jpg" alt="YouTube Video"></a><br /><br /></p></div>



<p>If you find this content useful,<strong> please leave a subscription&nbsp;</strong> 😉</p>



<h2 class="wp-block-heading" id="h-git-hooks-and-client-side-types">Git Hooks And Client-Side Types </h2>



<p>Before we see how to do a Ktlint check as a pre-commit hook, let&#8217;s learn a bit about Git Hooks.</p>



<p>Git Hooks, in simple words, are a way to trigger custom scripts, whenever a particular action happens in our repository. An action can be a <em>rebase</em>, a <em>checkout</em>, a <em>merge</em>, etc.  </p>



<p>And <strong>in order to run our script</strong>, the only thing we must do is to put it inside the <strong>hooks</strong> directory, which we can find in the <strong>.git</strong> directory. </p>



<p>Moreover, when we navigate there, we will see that it <strong>already contains </strong>a bunch of useful examples: </p>



<figure class="wp-block-image aligncenter size-full"><img fetchpriority="high" decoding="async" width="570" height="453" src="http://blog.codersee.com/wp-content/uploads/2023/11/ktlint_pre-commit_default_git_hooks.png" alt="Image is a screenshot presenting a directory where Git Hooks are put and a list of sample, already predefined hooks. This is the directory where we will put our ktlint pre-commit hook." class="wp-image-9008406" srcset="https://blog.codersee.com/wp-content/uploads/2023/11/ktlint_pre-commit_default_git_hooks.png 570w, https://blog.codersee.com/wp-content/uploads/2023/11/ktlint_pre-commit_default_git_hooks-300x238.png 300w" sizes="(max-width: 570px) 100vw, 570px" /></figure>



<p>If we would like to try any of the predefined samples, then we must simply remove the <code>.sample</code> suffix from the filename. </p>



<p>And what client-side Git Hooks can we work with? Well: </p>



<ul class="wp-block-list">
<li><strong>pre-commit</strong> &#8211; run before creating a commit,</li>



<li><strong>prepare-commit-msg </strong>&#8211; run before the commit message editor is opened,</li>



<li><strong>commit-msg </strong>&#8211; triggered after the commit message is created but before the commit is finalized,</li>



<li><strong>post-commit </strong>&#8211; run after a commit is made,</li>



<li><strong>applypatch-msg</strong> &#8211; invoked during the git apply operation to edit patch messages, </li>



<li><strong>pre-applypatch / post-applypatch</strong> &#8211; run before/after applying changes from a patch, </li>



<li><strong>pre-rebase </strong>&#8211; run before starting a rebase operation,</li>



<li><strong>post-rewrite </strong>&#8211; triggered after commands that rewrite commit history,</li>



<li><strong>post-checkout </strong>&#8211; invoked after a successful git checkout operation,</li>



<li><strong>post-merge</strong> &#8211; run after a successful git merge operation,</li>



<li><strong>pre-push</strong> &#8211; run before a push to a remote repository.</li>
</ul>



<p>The <code>pre-receive</code>, <code>update</code>, <code>and</code> <code>post-receive</code> are server-side hooks, which we won&#8217;t cover here. </p>



<h2 class="wp-block-heading" id="h-import-ktlint">Import Ktlint</h2>



<p>Excellent! </p>



<p>At this point, we know what we&#8217;re dealing with today and we can start the practice part of the Ktlint pre-commit hook implementation.</p>



<p>As the first thing, let&#8217;s navigate to the <code>build.gradle.kts</code> and import the library: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">plugins {
    kotlin("jvm") version "1.9.10"
    application

    id("org.jlleitschuh.gradle.ktlint") version "11.6.1"
}</pre>



<p>At the moment of writing, the most recent version is <code>11.6.1</code> and you can always figure out what&#8217;s the current one <a href="https://github.com/JLLeitschuh/ktlint-gradle" target="_blank" rel="noreferrer noopener">here</a>.</p>



<p>Following, let&#8217;s sync the project. </p>



<p>When the synchronization process finishes, we should see plenty of new tasks added, among which, these we will use the most:</p>



<ul class="wp-block-list">
<li><strong>ktlintFormat</strong>&#8211; to format according to the code style all <code>SourceSets</code> Kotlin files and project Kotlin script files, </li>



<li><strong>ktlintCheck</strong>&#8211; to check all <code>SourceSets</code> and project Kotlin script files</li>
</ul>



<h2 class="wp-block-heading" id="h-add-script">Add Script</h2>



<p>With that done, let&#8217;s create the <code>scripts</code> directory and put the <code>pre-commit</code> file there: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="bash" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">#!/bin/bash

echo "Running git pre-commit hook"

./gradlew ktlintCheck

ktlintCheckStatus=$?

# return 1 if check fails
if [[ $ktlintCheckStatus -ne 0 ]]; then
     exit 1
else
     exit 0
fi</pre>



<p>But <strong>why don&#8217;t we put that directly to the <code>.git/hooks</code> directory?</strong> </p>



<p>Well, the problem is that by default, the <code>.git</code> directory <strong>is not tracked</strong>. It contains all the information about the repository, including the repository&#8217;s configuration, commit history, branches, and other metadata. And if the .git directory were tracked, it would create a kind of recursive loop, leading to potential issues and conflicts.</p>



<p>So, when working with Gradle and Kotlin, we will simply put our script in the <code>scripts</code> destination, and later configure Gradle to copy it to the desired folder. </p>



<p>And what is our script? </p>



<p>Well, it is a simple script, which will run the <em>ktlint check</em> command using the gradle wrapper. If it is successful, the command returns 0 and we return 0, too. In other case, we return 1 and the commit will simply fail. </p>



<p>Update build.gradle.kts</p>



<p>Following, let&#8217;s navigate to the <code>build.gradle.kts</code> file and add a new task- the <code>copyPreCommitHook</code>: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">tasks.register&lt;Copy>("copyPreCommitHook") {
    description = "Copy pre-commit git hook from the scripts to the .git/hooks folder."
    group = "git hooks"
    outputs.upToDateWhen { false }
    from("$rootDir/scripts/pre-commit")
    into("$rootDir/.git/hooks/")
}</pre>



<p>As we can see, this task is responsible for copying the <em>pre-commit</em> file from the <code>scripts/pre-commit</code> to the <code>.git/hooks/</code>. </p>



<p>Moreover, we make a small workaround- <code>outputs.upToDateWhen { false }</code> &#8211; so that our task will never be cached. </p>



<p>When we sync our Gradle project, we should see that our task is available from now on inside the <code>git hooks</code> group: </p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="632" height="641" src="http://blog.codersee.com/wp-content/uploads/2023/11/ktlint_pre-commit_gradle_view.png" alt="Image is a screenshot and presents the Gradle tool window in IntelliJ and our copyPreCommitHook task, which will copy the pre-commit script with ktlint check from the scripts tirectory to the desired directory- .git/hooks" class="wp-image-9008409" srcset="https://blog.codersee.com/wp-content/uploads/2023/11/ktlint_pre-commit_gradle_view.png 632w, https://blog.codersee.com/wp-content/uploads/2023/11/ktlint_pre-commit_gradle_view-296x300.png 296w" sizes="(max-width: 632px) 100vw, 632px" /></figure>



<p>At this point, we can run the task and verify that the script was <strong>moved successfully</strong>. </p>



<p>But is that all? </p>



<p>Well, we could stop right here, but if we automate things, it would be good to avoid manual run of the <code>copyPreCommitHook</code> task, right? And we can easily achieve that this way: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="kotlin" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">tasks.build {
    dependsOn("copyPreCommitHook")
}</pre>



<p>With this setting, we simply instruct Gradle to run <code>copyPreCommitHook</code> before the <code>build</code> task. </p>



<h2 class="wp-block-heading" id="h-verification">Verification</h2>



<p>With all of that done, we can finally verify if our ktlint check will be run as a pre-commit hook. </p>



<p>To do so, let&#8217;s make some changes that will fail <code>ktlintCheck</code> and try to commit. In IntelliJ, we should see the following: </p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="558" height="177" src="http://blog.codersee.com/wp-content/uploads/2023/11/ktlint_pre-commit_failed_commit.png" alt="" class="wp-image-9008410" srcset="https://blog.codersee.com/wp-content/uploads/2023/11/ktlint_pre-commit_failed_commit.png 558w, https://blog.codersee.com/wp-content/uploads/2023/11/ktlint_pre-commit_failed_commit-300x95.png 300w" sizes="(max-width: 558px) 100vw, 558px" /></figure>



<p>And when we check the details, we will see a meaningful message: </p>



<pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Running git pre-commit hook
Starting a Gradle Daemon, 1 incompatible and 1 stopped Daemons could not be reused, use --status for details
> Task :loadKtlintReporters UP-TO-DATE
> Task :runKtlintCheckOverKotlinScripts UP-TO-DATE
> Task :runKtlintCheckOverTestSourceSet NO-SOURCE
> Task :ktlintTestSourceSetCheck SKIPPED
> Task :ktlintKotlinScriptCheck
> Task :runKtlintCheckOverMainSourceSet
> Task :ktlintMainSourceSetCheck FAILED
C:\Users\Piotr\src\main\kotlin\Main.kt:2:1 Unexpected indentation (10) (should be 4)
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':ktlintMainSourceSetCheck'.
> A failure occurred while executing org.jlleitschuh.gradle.ktlint.worker.ConsoleReportWorkAction
   > KtLint found code style violations. Please see the following reports:
     - C:\Users\Piotr\build\reports\ktlint\ktlintMainSourceSetCheck\ktlintMainSourceSetCheck.txt
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 7s
5 actionable tasks: 3 executed, 2 up-to-date
</pre>



<p>And this snippet proves that our <code>pre-commit</code> hook was triggered and works as expected.</p>



<p>Moreover, when we correct our code, we will see that we can commit without any message! </p>



<h2 class="wp-block-heading" id="h-summary">Summary</h2>



<p>And that&#8217;s all for this article about implementing ktlint check as a pre-commit Git Hook. </p>



<p>I hope you enjoyed this tutorial and that this will be a great start for adding more automation to your project. If you would like to get a ready-to-go project, then please navigate to <a href="https://github.com/codersee-blog/kotlin-ktlint-git-pre-commit-hook" target="_blank" rel="noreferrer noopener">my GitHub repo here</a>.</p>



<p>Lastly, I would like to invite you to my <a href="https://codersee.com/newsletter/">free newsletter</a>, so that you will never miss any important updates from both my blog and Kotlin world!  </p>
<p>The post <a href="https://blog.codersee.com/git-hooks-kotlin-automate-ktlint-pre-commit-hook/">Ktlint with pre-commit Hook: Git Hooks in Kotlin Made Easy</a> appeared first on <a href="https://blog.codersee.com">Codersee blog- Kotlin on the backend</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.codersee.com/git-hooks-kotlin-automate-ktlint-pre-commit-hook/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 

Served from: blog.codersee.com @ 2026-02-25 18:23:16 by W3 Total Cache
-->