<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Harshit Rai</title>
    <description>The latest articles on DEV Community by Harshit Rai (@harshit_rai_14102005).</description>
    <link>https://dev.to/harshit_rai_14102005</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4187226%2F52c85fb7-9633-4a61-bd90-d7c5c6583e95.png</url>
      <title>DEV Community: Harshit Rai</title>
      <link>https://dev.to/harshit_rai_14102005</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/harshit_rai_14102005"/>
    <language>en</language>
    <item>
      <title>GAI: Let AI Generate Your Git Commit Messages Locally</title>
      <dc:creator>Harshit Rai</dc:creator>
      <pubDate>Wed, 21 Oct 2026 20:57:31 +0000</pubDate>
      <link>https://dev.to/harshit_rai_14102005/gai-let-ai-generate-your-git-commit-messages-locally-4gb7</link>
      <guid>https://dev.to/harshit_rai_14102005/gai-let-ai-generate-your-git-commit-messages-locally-4gb7</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Writing commit messages is one of those small tasks developers do constantly but rarely enjoy. After debugging an issue or implementing a feature, describing the changes clearly can feel like unnecessary friction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GAI&lt;/strong&gt; is my attempt to automate that part of the development workflow without relying on external LLM APIs.&lt;/p&gt;

&lt;p&gt;GAI analyzes staged Git changes, retrieves similar commits from historical commit data, and uses a locally running language model to generate a commit message that follows the repository's existing tagging conventions.&lt;/p&gt;

&lt;p&gt;Instead of simply sending an entire Git diff to a model, GAI combines two approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Retrieval-augmented generation (RAG):&lt;/strong&gt; Finds historically similar changes using embeddings and FAISS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Change-focused diff parsing:&lt;/strong&gt; Extracts file paths, hunks, additions, deletions, and relevant context to make the changes easier for the generation model to understand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I use GAI in my own development workflow to reduce the friction of writing commit messages.&lt;/p&gt;

&lt;p&gt;The generated message is not committed automatically. I can accept it, edit it, regenerate it, or cancel the operation. Before committing, GAI also checks that the staged changes have not changed since the message was generated.&lt;/p&gt;

&lt;p&gt;The idea is simple: spend less time writing commit messages and more time writing code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Workflow
&lt;/h3&gt;



&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    A([Run gai]) --&amp;gt; AZ[Invokes src/cli.py]
    AZ --&amp;gt; B[Validate Git repository]
    B --&amp;gt; C[Read staged Git diff]
    C --&amp;gt; D{Staged changes exist?}

    D -- No --&amp;gt; E[Display error and exit]
    D -- Yes --&amp;gt; F[Preserve raw diff snapshot]

    F --&amp;gt; G[Parse diff by file and hunk]
    G --&amp;gt; H["Extract added lines, &amp;lt;br&amp;gt;removed lines and context"]
    H --&amp;gt; I["Format structured diff &amp;lt;br&amp;gt;for generation"]

    F --&amp;gt; J[Generate embedding &amp;lt;br&amp;gt;from raw diff]
    J --&amp;gt; K[Search FAISS index]
    K --&amp;gt; L["Retrieve top-k &amp;lt;br&amp;gt;historical commits"]

    I --&amp;gt; M[Build generation prompt]
    L --&amp;gt; M

    M --&amp;gt; N["Call local Gemma model &amp;lt;br&amp;gt;through Ollama"]
    N --&amp;gt; O[Parse generated commit message]
    O --&amp;gt; P{Message valid?}

    P -- No --&amp;gt; Q["Handle invalid output &amp;lt;br&amp;gt;or generation error"]
    P -- Yes --&amp;gt; R["Display suggested &amp;lt;br&amp;gt;commit message"]

    R --&amp;gt; S{User choice}
    S -- Edit --&amp;gt; T[Enter replacement message]
    T --&amp;gt; U{Edited message valid?}
    U -- Yes --&amp;gt; R
    U -- No --&amp;gt; R

    S -- Regenerate --&amp;gt; M
    S -- Cancel --&amp;gt; V([Exit without committing])

    S -- Accept --&amp;gt; W[Read current staged diff again]
    W --&amp;gt; X{Raw diff unchanged?}

    X -- No --&amp;gt; Y[Abort commit and request rerun]
    X -- Yes --&amp;gt; Z[Execute git commit]
    Z --&amp;gt; AA{Commit successful?}
    AA -- Yes --&amp;gt; AB([Done])
    AA -- No --&amp;gt; AC[Display Git error]&lt;/code&gt;&lt;/pre&gt;



&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;GAI is a local command-line tool, so it runs directly in a developer's environment.&lt;br&gt;
Here's how I use GAI on my own code changes.&lt;br&gt;
&lt;strong&gt;1. Stage the changes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add README.md
git diff &lt;span class="nt"&gt;--cached&lt;/span&gt; &lt;span class="nt"&gt;--stat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgcagrrks4bxp8g5y7pj4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgcagrrks4bxp8g5y7pj4.png" alt="Staged git diff from VS code UI" width="799" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Generate a commit message&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq15u2c5w4jd3jr98g7xj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq15u2c5w4jd3jr98g7xj.png" alt="gai terminal execution -- formatted-diff" width="800" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flt0eie861vz5c5olu1ht.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flt0eie861vz5c5olu1ht.png" alt="gai terminal execution -- generating the commit using gemma" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GAI retrieves similar historical commits, generates a message, and lets me review it before committing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Verify the commit (optional)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="nt"&gt;--oneline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh2qoel16bl1hchvgfsa8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh2qoel16bl1hchvgfsa8.png" alt="Git log output showing the commit created using GAI's generated message" width="798" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GitHub repository:&lt;/strong&gt; &lt;a href="https://github.com/kira14102005/gai" rel="noopener noreferrer"&gt;https://github.com/kira14102005/gai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GAI is implemented in Python and can also be invoked through its Python CLI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; src.cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can control the number of historical examples retrieved:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; src.cli &lt;span class="nt"&gt;--top-k&lt;/span&gt; 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The repository README contains the setup instructions, FAISS index preparation steps, and details of the current workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;The current implementation uses &lt;strong&gt;Ollama, FAISS, EmbeddingGemma, and Gemma4:e2b&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I started with historical commit data containing tags, messages, and diffs. The indexing pipeline generates embeddings for usable historical diffs using EmbeddingGemma and stores them in a FAISS &lt;code&gt;IndexFlatL2&lt;/code&gt; index. The corresponding commit metadata is stored separately so retrieved vectors can be mapped back to their original messages and tags.&lt;/p&gt;

&lt;p&gt;When I run GAI, it reads the staged Git diff. The raw diff is used for retrieval, while a parsed and formatted representation gives the generation model a clearer view of the actual changes.&lt;/p&gt;

&lt;p&gt;FAISS retrieves the most relevant historical commits, and their messages and tags are included alongside the formatted diff in the generation prompt. Gemma then generates a candidate message through Ollama.&lt;/p&gt;

&lt;p&gt;The CLI handles the final review. I remain in control of whether a commit is created, and GAI verifies that the staged diff is unchanged before committing.&lt;/p&gt;

&lt;p&gt;One challenge I'm interested in solving is how smaller local models handle large diffs. Simply increasing the context window isn't always the best solution; giving the model better-structured information may be more useful.&lt;/p&gt;

&lt;p&gt;My planned next step is a parallel LangGraph workflow with two generation paths:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A retrieval-based chain that uses historical commits, as the current implementation does.&lt;/li&gt;
&lt;li&gt;A diff-understanding chain that summarizes large changes by file and hunk before generating another candidate.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An evaluator would assess both candidates for correctness, relevance, specificity, and tag validity. A reducer would then select the stronger candidate or synthesize a better one when necessary.&lt;/p&gt;

&lt;p&gt;These LangGraph chains, evaluator, and reducer are future improvements; they are not yet part of the current implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Open Innovation Matters
&lt;/h2&gt;

&lt;p&gt;I wanted GAI to generate commit messages that reflect how I actually write commits, rather than producing generic descriptions of code changes.&lt;/p&gt;

&lt;p&gt;That's why I combined &lt;strong&gt;local inference with retrieval from historical commits&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learning from existing conventions:&lt;/strong&gt; FAISS retrieves similar historical diffs and their commit messages, giving Gemma concrete examples of the repository's tagging conventions and writing style.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keeping code local:&lt;/strong&gt; Git diffs can contain proprietary implementation details. Running both embedding and generation models through Ollama lets GAI process these changes locally without depending on an external LLM API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Experimenting without being locked in:&lt;/strong&gt; I can change the generation model, refine prompts, or experiment with retrieval strategies without redesigning the application around a particular hosted AI provider.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interesting part isn't simply running an LLM locally. It's combining open models with a repository's own history to build a commit-message generator tailored to the way its developers work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lazy Payoff
&lt;/h2&gt;

&lt;p&gt;The goal is to remove a repetitive task from the development loop.&lt;/p&gt;

&lt;p&gt;Instead of switching from coding to thinking about the wording of a commit message, I can stage my changes, run &lt;code&gt;gai&lt;/code&gt;, review the suggestion, and continue.&lt;/p&gt;

&lt;p&gt;The human review step is intentional. Automating the boring part shouldn't mean giving up control over the final commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;I'm planning to experiment with parallel generation chains, hierarchical diff summarization, and an evaluator/reducer workflow to improve the quality of generated messages.&lt;/p&gt;

&lt;p&gt;I'd love to hear how others approach commit-message generation, especially when working with smaller local models. What would you improve in this pipeline?&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma&lt;/strong&gt; — GAI uses &lt;em&gt;gemma4:e2b&lt;/em&gt; through Ollama to generate commit messages locally, combining open-weight AI with retrieval from historical Git commits.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
