Message Git Commit
Le script gcm
propose un flux guidé pour créer des commits avec des messages générés.
Il commence par générer un message de commit basé sur les changements mis en scène dans votre dépôt Git
en utilisant un prompt en ligne,
puis demande à l’utilisateur de valider le commit ou de régénérer le message.
compute diffloop generate commit message ask user to commit, edit message or regenerate if user says commit git commit and push
Configuration
Section intitulée « Configuration »Tout d’abord, nous définissons la fonction script
, qui configure notre script GenAI en fournissant un titre et une description, et en spécifiant le modèle que nous allons utiliser :
script({ title: "git commit message", description: "Generate a commit message for all staged changes", model: "openai:gpt-4o",})
Recherche de modifications
Section intitulée « Recherche de modifications »Ensuite, nous vérifions la présence de modifications mises en scène dans votre dépôt Git à l’aide de git diff
.
S’il n’y a rien de mis en scène, GenAI propose gentiment de tout mettre en scène pour vous :
// Check for staged changes and stage all changes if none are stagedconst diff = await git.diff({ staged: true, askStageOnEmpty: true,})if (!diff) cancel("no staged changes")
Nous affichons ensuite la différence dans la console pour que vous puissiez vérifier les modifications qui vont être validées :
console.log(diff.stdout)
Générer et affiner le message de commit
Section intitulée « Générer et affiner le message de commit »Voici la partie intéressante. Nous entrons dans une boucle où GenAI génère un message de commit pour vous sur la base du diff. Si le message ne vous satisfait pas, vous pouvez choisir de le modifier, de l’accepter ou de le régénérer :
let choicelet messagedo { // generate a conventional commit message (https://www.conventionalcommits.org/en/v1.0.0/) const res = await runPrompt((_) => { _.def("GIT_DIFF", diff, { maxTokens: 20000, language: "diff" }) _.$`Generate a git conventional commit message for the changes in GIT_DIFF. - do NOT add quotes - maximum 50 characters - use gitmojis` }) // ... handle response and user choices} while (choice !== "commit")
Valider et pousser
Section intitulée « Valider et pousser »Si vous choisissez de valider, GenAI exécute la commande git commit
avec votre message, et si vous êtes très confiant, il peut même pousser les modifications vers votre dépôt juste après :
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)}
Exécution du script avec GenAIScript CLI
Section intitulée « Exécution du script avec GenAIScript CLI »Utilisez le cli pour exécuter le script :
npx genaiscript run gcm
Full source (GitHub)
Section intitulée « Full source (GitHub) »/** * Script to automate the git commit process with AI-generated commit messages. * It checks for staged changes, generates a commit message, and prompts the user to review or edit the message before committing. */
script({ title: "git commit message", description: "Generate a commit message for all staged changes", unlisted: true, parameters: { chunkSize: { type: "number", default: 10000, description: "Maximum number of tokens per chunk", }, maxChunks: { type: "number", default: 4, description: "Safeguard against huge commits. Asks confirmation to the user before running more than maxChunks chunks", }, gitmoji: { type: "boolean", default: true, description: "Use gitmoji in the commit message", }, },});const { chunkSize, maxChunks, gitmoji } = env.vars;
// Check for staged changes and stage all changes if none are stagedconst diff = await git.diff({ staged: true, askStageOnEmpty: true, ignoreSpaceChange: true,});
// If no staged changes are found, cancel the script with a messageif (!diff) cancel("no staged changes");
// Display the diff of staged changes in the consoleconsole.debug(diff);
await git.pull();
// chunk if case of massive diffconst chunks = await tokenizers.chunk(diff, { chunkSize });if (chunks.length > 1) { console.log(`staged changes chunked into ${chunks.length} parts`); if (chunks.length > maxChunks) { const res = await host.confirm( `This is a big diff with ${chunks.length} chunks, do you want to proceed?`, ); if (!res) cancel("user cancelled"); }}
const gitPush = async () => { if (await host.confirm("Push changes?", { default: true })) console.log(await git.exec("push"));};
const addInstructions = (ctx) => { ctx.$`
<type>: <description><body>
${gitmoji ? `- <type> is a gitmoji` : `- <type> can be one of the following: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert`}- <description> is a short, imperative present-tense description of the change- <body> is a short description of the changes- Pretend you're writing an important newsworthy article. Give the headline in <description> that will sum up what happened and what is important. Then, provide further details in the <body> in an organized fashion.- the diff is generated by "git diff"- do NOT use markdown syntax- do NOT add quotes, single quote or code blocks- keep <description> short, 1 LINE ONLY, maximum 50 characters- keep <body> short, 1 LINE ONLY, maximum 72 characters- follow the conventional commit spec at https://www.conventionalcommits.org/en/v1.0.0/#specification- do NOT confuse delete lines starting with '-' and add lines starting with '+'`;};
let choice;let message;do { // Generate a conventional commit message based on the staged changes diff message = ""; for (const chunk of chunks) { const res = await runPrompt( (_) => { _.def("GIT_DIFF", chunk, { maxTokens: 10000, language: "diff", detectPromptInjection: "available", }); _.$`Generate a git conventional commit message that summarizes the changes in GIT_DIFF.`; addInstructions(_); }, { model: "large", // Specifies the LLM model to use for message generation label: "generate commit message", // Label for the prompt task system: ["system.assistant"], systemSafety: true, responseType: "text", }, ); if (res.error) throw res.error; message += (res.fences?.[0]?.content || res.text) + "\n"; }
// since we've concatenated the chunks, let's compress it back into a single sentence again if (chunks.length > 1) { const res = await runPrompt( (_) => { _.$`Generate a git conventional commit message that summarizes the <COMMIT_MESSAGES>.`; addInstructions(_); _.def("COMMIT_MESSAGES", message); }, { model: "large", label: "summarize chunk commit messages", system: ["system.assistant"], systemSafety: true, responseType: "text", }, ); if (res.error) throw res.error; message = res.text; }
message = message?.trim(); if (!message) { console.log("No commit message generated, did you configure the LLM model?"); break; }
// Prompt user to accept, edit, or regenerate the commit message choice = await host.select(message, [ { value: "commit", description: "accept message and commit", }, { value: "edit", description: "edit message in git editor", }, { value: "regenerate", description: "run LLM generation again", }, { value: "cancel", description: "cancel commit", }, ]);
// Handle user's choice for commit message if (choice === "edit") { // @ts-ignore const { spawnSync } = await import("child_process"); // 1) Launch git commit in an interactive editor const spawnResult = spawnSync("git", ["commit", "-m", message, "--edit"], { stdio: "inherit", });
// 2) After the editor closes, forcibly exit the entire script console.debug("git editor closed with exit code ", spawnResult.status); if (spawnResult.status === 0) await gitPush(); break; } // If user chooses to commit, execute the git commit and optionally push changes if (choice === "commit" && message) { console.log(await git.exec(["commit", "-m", message])); await gitPush(); break; }
if (choice === "cancel") { cancel("User cancelled commit"); break; }} while (choice !== "commit");
Sécurité du contenu
Section intitulée « Sécurité du contenu »Les mesures suivantes sont prises pour garantir la sécurité du contenu généré.
- Ce script inclut des invites système pour empêcher les injections de prompt et la génération de contenu nuisible.
- Le message de commit est examiné et approuvé par l’utilisateur avant de valider les modifications.
Des mesures supplémentaires pour renforcer la sécurité incluent l’exécution d’un modèle avec un filtre de sécurité ou la validation du message via un service de sécurité de contenu.
Consultez la Note de transparence pour plus d’informations sur la sécurité du contenu.