Skip to content

Git Commit Message

The gcm script provides a guided flow to create commit with generated messages.

Configuration

First off, we define the script function, which sets up our GenAI script by providing a title and a description, and specifying the model we’ll be using:

script({
title: "git commit message",
description: "Generate a commit message for all staged changes",
model: "openai:gpt-4o",
})

Look for changes

Next up, we check for any staged changes in your Git repository using git diff --cached. If there’s nothing staged, GenAI kindly offers to stage all changes for you:

let diff = await host.exec("git diff --cached")
if (!diff.stdout) {
const stage = await host.confirm("No staged changes. Stage all changes?", {
default: true,
})
if (stage) {
await host.exec("git add .")
diff = await host.exec("git diff --cached -- . :!**/genaiscript.d.ts")
}
if (!diff.stdout) cancel("no staged changes")
}

We then log the diff to the console so you can review what changes are about to be committed:

console.log(diff.stdout)

Generate and refine commit message

Here comes the interesting part. We enter a loop where GenAI will generate a commit message for you based on the diff. If you’re not satisfied with the message, you can choose to edit it, accept it, or regenerate it:

let choice
let message
do {
const res = await runPrompt(
(_) => {
_.def("GIT_DIFF", diff, { maxTokens: 20000 })
_.$`GIT_DIFF is a diff of all staged changes, coming from the command:
\`\`\`
git diff --cached
\`\`\`
Please generate a concise, one-line commit message for these changes.
- do NOT add quotes
`
},
{ cache: false, temperature: 0.8 }
)
// ... handle response and user choices
} while (choice !== "commit")

Commit and push

If you choose to commit, GenAI runs the git commit command with your message, and if you’re feeling super confident, it can even push the changes to your repository right after:

if (choice === "commit" && message) {
console.log(
(await host.exec("git", ["commit", "-m", message, "-n"])).stdout
)
if (await host.confirm("Push changes?", { default: true }))
console.log((await host.exec("git push")).stdout)
}

Running the Script with GenAIScript CLI

Getting this script up and running is a cinch. If you’ve already installed the GenAIScript CLI, you can simply run it with:

Terminal window
genaiscript run gcm

Remember, you’ll need to have your changes staged in Git for the script to work its magic. 🧙

Full source (GitHub)

gcm.genai.mts
/**
* git commit flow with auto-generated commit message
*/
script({
title: "git commit message",
description: "Generate a commit message for all staged changes",
})
// Check for staged changes and stage all changes if none are staged
const diff = await git.diff({
staged: true,
excludedPaths: "**/genaiscript.d.ts",
askStageOnEmpty: true,
})
if (!diff) cancel("no staged changes")
// show diff in the console
console.log(diff)
let choice
let message
do {
// Generate commit message
const res = await runPrompt(
(_) => {
_.def("GIT_DIFF", diff, { maxTokens: 20000 })
_.$`GIT_DIFF is a diff of all staged changes, coming from the command:
\`\`\`
git diff --cached
\`\`\`
Please generate a concise, one-line commit message for these changes.
- do NOT add quotes
` // TODO: add a better prompt
},
{ cache: false, temperature: 0.8 }
)
if (res.error) throw res.error
message = res.text
if (!message) {
console.log("No message generated, did you configure the LLM model?")
break
}
// Prompt user for commit message
choice = await host.select(message, [
{
value: "commit",
description: "accept message and commit",
},
{
value: "edit",
description: "edit message and commit",
},
{
value: "regenerate",
description: "regenerate message",
},
])
// Handle user choice
if (choice === "edit") {
message = await host.input("Edit commit message", {
required: true,
})
choice = "commit"
}
// Regenerate message
if (choice === "commit" && message) {
console.log(await git.exec(["commit", "-m", message]))
if (await host.confirm("Push changes?", { default: true }))
console.log(await git.exec("push"))
break
}
} while (choice !== "commit")