Skip to content

Instantly share code, notes, and snippets.

@knyazer
Last active September 28, 2024 19:27
Show Gist options
  • Save knyazer/675e6eb945ae5ec64af2f9be4826b07e to your computer and use it in GitHub Desktop.
Save knyazer/675e6eb945ae5ec64af2f9be4826b07e to your computer and use it in GitHub Desktop.
Bringing AI to Git commit.
function gcm
# Check if llm is installed, if not, install it
if not type -q llm
echo "'llm' is not installed. Attempting to install it using pip..."
if pip install llm
echo "'llm' installed successfully."
else
echo "Failed to install 'llm'. Please install it manually and try again."
return 1
end
end
# Check if an API key is set up for llm
set llm_keys (llm keys)
if test "$llm_keys" = "No keys found"
echo "No API key found for 'llm'. You need to set it up."
llm keys set openai
if test $status -ne 0
echo "Failed to set up the OpenAI key. Please try again manually."
return 1
else
echo "OpenAI key set successfully."
end
end
# Function to generate commit message
function generate_commit_message
set -l prompt_text "Here are some examples of good commit messages:
- tests: correct TPU large array indexing tests
- feat: add overloads to eqx.combine
- docs: improve training loop documentation
- refactor: remove deprecated calls to jax.DeviceArray
- docs: explain why we do direct dtype conversion in precompute_freqs
- perf: donate tensors to increase memory utilization
- ci: switch from unittest to pytest
- tests: add double precision test for Adam
- build: allow cargo multithreading
- style: shorter conditions for key handling
- feat: partial weight decay only for weights
- refactor: improve control flow in some_model_function
- wip: debugging the flash attention with float16
- style: fix the type annotations
- tests: add parametrized testing for the collision logic
Below is a diff of all changes coming from ```git diff HEAD```. Do NOT use quotes in your answer. Generate a concise, one-line, single sentence, at most 7 words long, summary commit message for these changes. End it with a new line, not a period. Feel free to provide a few-sentence explanation after a new line, so that it will be included as a commit description, but be as concise as possible! If it is taking more than 20 words, you are doing something wrong.
Prepend your answer with either of feat, fix, refactor, style, ci, docs, build, tests, perf, or wip, following the commitizen convention. The most important part to get right is the type of the commit, so make try as hard as possible to get it right!
Be specific, and make sure to mention only meaningful changes. Do not use generic terms, talk only about things that happened in the code.
\n\n"
# Check if --retry argument is present and get the index
set retry_index (contains --index -- '--retry' $argv)
if set -q $retry_index
set -l last_message $argv[$retry_index + 1]
echo "Previous message: $last_message" # For debugging purposes
set -l prompt_text "$prompt_text
The previous commit message generated was:
\`\`\`
$last_message
\`\`\`
It was not satisfactory. Below is the diff again. Please generate a better commit message.
Your answer must adhere to the commitizen convention."
end
git diff HEAD | llm $prompt_text
end
# Function to read user input
function read_input
set -l prompt $argv[1]
read -P $prompt reply
echo $reply
end
# Main script
if contains -- -a $argv
set files (git diff HEAD --name-only)
else
set files (git diff --cached --name-only)
echo "Generating AI-powered commit message for staged files:"
end
echo $files
set commit_message (generate_commit_message $argv --retry "")
while true
echo -e "Proposed commit message:\n"
echo $commit_message
echo -e ""
set choice (read_input "Do you want to (a)ccept or (r)egenerate? ")
set short_message (string split -m 1 "\n" $commit_message)[1]
set description (string split -m 1 "\n" $commit_message)[2]
if test -z "$description"
set description ""
end
switch $choice
case 'a' 'A' ''
if git commit $argv -m "$short_message" -m "$description"
echo "Changes committed successfully!"
return 0
else
echo "Commit failed. Please check your changes and try again."
return 1
end
case 'r' 'R'
echo "Regenerating commit message..."
set commit_message (generate_commit_message $argv --retry $commit_message)
case 'c' 'C' 'q' 'Q'
echo "Commit cancelled."
return 1
case '*'
echo "Invalid choice. Please try again."
end
end
end
@daanzu
Copy link

daanzu commented Sep 18, 2024

Thanks for posting this!

@knyazer
Copy link
Author

knyazer commented Sep 18, 2024

@daanzu btw, I iterated on it quite a bunch, and the new version is a lot better; just updated it

Thanks for pinging, I completely forgot that I posted it here :)

@knyazer
Copy link
Author

knyazer commented Sep 18, 2024

Generally, just fixed some bugs, added more examples, allowed to write git commit description, and now it takes any arguments git commit takes, which is nice; e.g. my workflow is

gcm -a && git push

and if I am too lazy I just press enter twice, so that it triggers automatic accept 😉

you can see some example commits I made with it at https://github.com/knyazer/nano_jax_gpt

@daanzu
Copy link

daanzu commented Sep 20, 2024

@knyazer Neat changes; I'll try them out! FWIW, I had already made the following change, which is similar to yours but a different approach:

    function generate_commit_message
        set -l prompt_text "
Below is:
1. A list of recent git commit messages (just first lines), coming from the command:
\`\`\`
git log --oneline -n 20
\`\`\`
2. A diff of all staged changes, coming from the command:
\`\`\`
git diff --cached
\`\`\`
Please generate a concise, one-line commit message for these changes, using a similar format and styling as the existing commit messages. But really be concise! I mean it!"

        if contains -- -a $argv
            # git diff HEAD | llm $prompt_text
            begin; echo "### GIT LOG ###"; git log --oneline -n 20; echo "### GIT DIFF ###"; git diff HEAD; end | llm $prompt_text
        else
            # git diff --cached | llm $prompt_text
            begin; echo "### GIT LOG ###"; git log --oneline -n 20; echo "### GIT DIFF ###"; git diff --cached; end | llm $prompt_text
        end
    end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment