- Published on
Building a .NET-Powered Commit Message Generator: A Step-by-Step Guide
- Authors
- Name
- Filip Grilec
Building a .NET-Powered Commit Message Generator: A Step-by-Step Guide
In this guide, we'll learn how to:
- Set up a .NET console app and install required dependencies
- Integrate with the OpenAI API to generate commit messages
- Implement functions to retrieve git diffs and generate commit messages
- Run and test the commit message generator program
Why are commit messages important
If you ever tracked my commit messages they would ideally look something like this
Before automatic commit messages
Commit Message |
---|
Remove memoryCache |
Add retry |
But with the help of Commit message generator our commit messages will look like this:
After automatic commit messages
Commit Message | Details |
---|---|
Add images to commit message generator documentation | Include before and after screenshots to illustrate the usage of the commit message generator tool. |
Fix section numbering and improve method descriptions | Updated the commit message generator guide to include an overview of key learning objectives, such as effective prompt creation and API usage for generating messages. Also clarified variable names in the code example for better readability. |
The automatically generated commit messages are more detailed and informative, clearly conveying the purpose and changes of each commit. They follow best practices like using the imperative mood and referencing relevant issues. This results in a more organized and maintainable commit history that benefits the entire development team.
1. Set up a .NET console app
Create a new .NET console app:
dotnet new console -n CommitMessageGenerator cd CommitMessageGenerator
Install the required NuGet packages:
dotnet add package CliWrap dotnet add package OpenAI --prerelease
- CliWrap: For executing git commands from within the application.
- OpenAI: For integrating with the OpenAI API to generate commit messages.
Open the project in your preferred IDE or text editor:
code .
2. Set up the OpenAI API key
- Obtain an API key from OpenAI by signing up for their service and creating a new API key Where do I find my OpenAI API Key?.
- Set the API key as an environment variable named
OPENAI_API_KEY
. This will allow your application to securely access the OpenAI API.
# OPENAI_API_KEY begins with `sk-`
export OPENAI_API_KEY=<your-key-here>
3. Implement the CreateGitMessage function
static async Task<ChatCompletion> CreateGitMessage(string gitDiff)
{
string apiKeyCredential = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new ArgumentNullException("apiKeyCredential", "Missing OPENAI_API_KEY");
ChatClient client = new(model: "gpt-4o-mini", apiKeyCredential);
string createGitMessagePrompt = $"""
You are a Git commit message generator. Analyze the following git diff and
produce a concise, informative commit message following standard Git commit message
conventions. The commit message should have a brief subject line (50 characters
or less) and, if necessary, a more detailed body separated by a blank line. Use
the imperative mood and reference any relevant issue numbers. Respond only with
the commit message itself, without any additional text or explanation.
<git_diff>{gitDiff}</git_diff>
""";
ChatCompletion commitMessage = await client.CompleteChatAsync(
[
new UserChatMessage(createGitMessagePrompt),
]);
return commitMessage;
}
Full breakdown of the method
- Raw String Literals for Prompt:
string createGitMessagePrompt = $"""
You are a Git commit message generator. Analyze the following git diff and
produce a concise, informative commit message following standard Git commit message
conventions. The commit message should have a brief subject line (50 characters
or less) and, if necessary, a more detailed body separated by a blank line. Use
the imperative mood and reference any relevant issue numbers. Respond only with
the commit message itself, without any additional text or explanation. <git_diff>{gitDiff}</git_diff>
""";
- The method uses a raw string literal (denoted by
"""..."""
) to define the prompt. This approach offers several benefits:- Preserves formatting, including line breaks and indentation
- Eliminates the need for escape characters for quotes or special characters
- Allows easy embedding of variables (like
{gitDiff}
) without breaking the string - Improves readability, especially for multi-line prompts or those containing code snippets
- Choice of "gpt-4o-mini" Model:
ChatClient client = new(model: "gpt-4o-mini", apiKeyCredential);
- The
gpt-4o-mini
model is dirt cheap, costing$0.15
per million input tokens - for 75 commits the cost was about
$1
- It's quick, suitable for tasks like generating commit messages
- The benefit of
gpt4o-mini
being so quick is we don't need to implement streaming and can useCompleteChatAsync()
and simplify our code
ChatCompletion commitMessage = await client.CompleteChatAsync(
[
new UserChatMessage(createGitMessagePrompt),
]);
4. Implement the GetDiff function
async Task<string?> GetDiff(string? gitRepositoryPath = null)
{
gitRepositoryPath ??= Environment.CurrentDirectory;
try
{
BufferedCommandResult result = await Cli.Wrap("git")
.WithWorkingDirectory(gitRepositoryPath)
.WithArguments("diff --cached")
.ExecuteBufferedAsync();
return result.StandardOutput;
}
catch (Exception ex)
{
Console.Write($"An error occurred while executing `git diff --cached`: {ex.Message}");
return null;
}
}
5. Implement the main program flow
string? diffMessage = await GetDiff();
if (string.IsNullOrWhiteSpace(diffMessage))
{
Console.WriteLine("No changes to display.");
return;
}
ChatCompletion gitCommitMessage = await CreateGitMessage(diffMessage);
Console.WriteLine(gitCommitMessage);
You can find the full code here
6. Run and test the commit message generator
- Stage some changes in your git repository.
- Run the program from the command line or your IDE.
- Review the generated commit message to ensure it accurately summarizes the changes.
By following this step-by-step guide, you should now have a functional commit message generator powered by C# and .NET. Feel free to extend and customize the generator to fit your specific needs and workflow.
Happy coding!