lazygit
lazygit copied to clipboard
Add autocommit commit messages
-
PR Description
-
Please check if the PR fulfills these requirements
- [ ] Cheatsheets are up-to-date (run
go generate ./...) - [ ] Code has been formatted (see here)
- [ ] Tests have been added/updated (see here for the integration test guide)
- [ ] Text is internationalised (see here)
- [ ] If a new UserConfig entry was added, make sure it can be hot-reloaded (see here)
- [ ] Docs have been updated if necessary
- [ ] You've read through your own file changes for silly mistakes etc
This PR adds the ability to generate commit messages using AI, primarily through GitHub Copilot integration, with potential support for OpenAI-compatible APIs.
Background
This aims to implement #3763, adding AI-assisted commit message generation similar to VS Code's Copilot feature.
While the GitHub Copilot API is not officially public, the implementation doesn't appear to violate the terms of service. However, I understand introducing AI features like this may be a significant direction change for the project, so I'm open to discussion about whether this aligns with lazygit's goals.
This initial scope focuses solely on commit message generation to keep the implementation focused and manageable. Future possibilities like generating release notes, improving squash commit messages, or crafting PR descriptions could be considered later once this core functionality is proven.
The implementation is based on the flow from Zed and Copilot.lua .
I would appreciate some feedback on both the implementation approach and whether this feature could be added to the project.
Current Implementation Status
This is very much a work in progress. Just a proof of concept at the moment
- [x] GitHub Copilot authentication via device codes
- [x] Chat completion
- [ ] Support for generic OpenAI-compatible APIs
- [ ] Support for other providers (Antropic, Geminni, Ollama)
- [ ] Diff extraction and processing
- [ ] Commit message style consistency
- [ ] Large diff handling (according to the model size)
- [ ] Model selection configuration (UserConfig?)
Proposed configuration
git:
commitSuggestions:
enabled: true
provider: "github-copilot" # or "openai-compatible"
modelName: "gpt-4o" # for openai-compatible
maxDiffSize: 4096 # tokens
endpoint: "http://localhost:8080" # for self or openai compatible
Note: Tests and documentation will be added as the implementation progresses.
I was just looking at a way to do that using custom commands, but there is no good way to use the current prompts to do that ...
I have contributed an improved version of this implementation to mods (a way of using LLMs in the CLI). I'll port back to this PR.
- https://github.com/charmbracelet/mods/pull/406
- https://github.com/charmbracelet/mods/pull/408
But there are some interesting considerations like tokenization, we might need to discuss. I'm working in a POC.
In the meantime, I hacked together a custom command integration it with LazyGit and mods that already addresses all these issues. If someone else finds it useful, here is my workflow:
Important considerations
- This script will only consider staged changes
- Your diff WILL BE SENT to an LLM.
If work for a company that does not allow that, you can configure a local model, as long as it is OpenAI compatible (Ollama works as well, refer to mods example config for all options)
How to use
Flow
- Generate commit message
- Update if necessary
- Use the message (ctrl + g; commit)
Shortcuts
Ctrl + g: Generate a commit message
Ctrl + n: Modify the commit message (you can type whatever you want and the message will be updated)
Requirements
- Have
modsinstalled (https://github.com/charmbracelet/mods) - Configure an LLM for mods
If you have github copilot, you can put this into your mods config
~/.config/mods/mods.yml
apis:
copilot:
base-url: https://api.githubcopilot.com
models:
gpt-4o-2024-05-13:
aliases: ["4o-2024", "4o", "gpt-4o"]
max-input-chars: 392000
gpt-4:
aliases: ["4"]
max-input-chars: 24500
gpt-3.5-turbo:
aliases: ["35t"]
max-input-chars: 12250
o1-preview-2024-09-12:
aliases: ["o1-preview", "o1p"]
max-input-chars: 128000
o1-mini-2024-09-12:
aliases: ["o1-mini", "o1m"]
max-input-chars: 128000
claude-3.5-sonnet:
aliases: ["claude3.5-sonnet", "sonnet-3.5", "claude-3-5-sonnet"]
max-input-chars: 680000
Custom commands
To be placed in your lazygit config file
~/.config/lazygit/config.yml
customCommands:
- key: '<c-g>'
context: 'global'
description: 'AI Commit Message'
loadingText: 'Generating commit message'
prompts:
- type: 'menu'
title: 'AI Commit Options'
key: 'action'
options:
- name: 'Generate'
description: 'Generate new commit message'
value: 'generate'
- name: 'Commit'
description: 'Use current message'
value: 'commit'
- name: 'View'
description: 'View current message'
value: 'view'
- name: 'Clear'
description: 'Remove current message'
value: 'clear'
command: |
{{if eq .Form.action "generate"}}
gen-commit-lazygit | tee /tmp/lazygit-commit-msg
{{else if eq .Form.action "view"}}
test -f /tmp/lazygit-commit-msg && cat /tmp/lazygit-commit-msg || echo "No commit message generated yet"
{{else if eq .Form.action "clear"}}
test -f /tmp/lazygit-commit-msg && rm /tmp/lazygit-commit-msg || echo "No commit message file exists"
{{else}}
git commit -m "$(cat /tmp/lazygit-commit-msg)" && rm /tmp/lazygit-commit-msg
{{end}}
showOutput: true
- key: '<c-N>'
context: 'global'
description: 'Refine commit message'
prompts:
- type: 'input'
title: 'Enter feedback for refinement'
key: 'feedback'
command: "cat /tmp/lazygit-commit-msg | mods -q -C \"feedback: {{.Form.feedback}}\""
showOutput: true
Message generator
You can put this wherever you what, you just need to make sure it's executable and in your $PATH
A suggestion is to save it in
~/.local/bin/gen-commit-lazygit
#!/bin/bash
base_prompt="Create a conventional commit message for these changes. If there are multiple features or changes, list them with bullet points ('-') on separate lines. For scope, as prefix: use 'backend' for Go or other backend files, 'frontend' for Svelte or other frontend specific files, and if both are changed use the general feature scope instead. Eg: 'feat(backend/git): add new API endpoint'. If previous commits don't follow conventional format, maintain their style instead. Use the same idiom for the commit message as the previous commits"
if [ "$1" = "wip" ]; then
prompt="$base_prompt Prefix with wip() to indicate work in progress."
else
prompt="$base_prompt"
fi
context=$(
echo -e "=== Last commits ===\n"
git log -5 | sed 's/[^[:print:]]//g'
echo -e "\n=== Staged Changes ===\n"
changed_files=$(git diff --staged --name-only | sed 's/[^[:print:]]//g')
staged_changes=""
# Ignore some changes to avoid noise
# lock files, binary, in those cases, just send their names
# Define array of ignored file patterns
ignore_patterns=(".lock" ".bin" ".exe" ".dll" ".so" ".jpg" ".jpeg" ".png" ".gif" ".bmp" ".ico" ".svg" ".webp" ".mp4" ".mov" ".avi")
# Loop through each changed file
while IFS= read -r file; do
# Check if file matches any ignore pattern
should_ignore=false
for pattern in "${ignore_patterns[@]}"; do
if [[ "$file" == *"$pattern"* ]]; then
should_ignore=true
break
fi
done
if [ "$should_ignore" = true ]; then
# Just append filename for ignored files
staged_changes+="$(echo "$file" | sed 's/[^[:print:]]//g')\n"
else
# Append full diff for non-ignored files
diff=$(git diff --cached "$file" | sed 's/[^[:print:]]//g')
staged_changes+="$diff\n"
fi
done <<< "$changed_files"
# Translit to utf-8
staged_changes=$(echo "$staged_changes" | iconv -c -f utf-8 -t utf-8 | sed 's/[^[:print:]]//g')
echo -e "$staged_changes"
)
full_prompt=\
''"$prompt Just the commit message, multiple
lines if necessary . Just the commit message NOTHING ELSE. If no data is shown
or if you only see file paths with no diff content making it difficult to
understand the changes, just write the '\'\'\'' (empty string) character: '\'\'\''
<gencommit_prompt_context>
$context
</gencommit_prompt_context>
"''
message=$(echo $full_prompt | mods -q)
echo -e "$message"
I'll try this next week, looks like this could work.
Is there anything blocking this PR? Maybe I can help
Hi, @Demianeen!
I'll be backporting the changes I've made to this PR very soon, definitely this week.
Initially, it will be only GitHub Copilot and OpenAI-compatible providers, but many more still to be implemented.
If you're willing to test it out and provide some feedback, that would be greatly appreciated! Can I ping you back here for that?
Feel free to contribute to the development as well if you're interested.
@nathabonfim59 sure ping me to test
Hi, any updates on this pr?