dmazin / git-lazy-commit

git-lazy-commit generates commit messages for staged changes in a git repository using OpenAI's OpenGPT.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

git-lazy-commit

git-lazy-commit generates commit messages for staged changes in a git repository using OpenAI's OpenGPT.

This tool is great at describing what you did, but not why you did it. I'd advise you to use it as a starting point, but then add the why. Use AI to augment yourself, not replace yourself.

For more backstory and discussion, please see my blog post about this.

Installation

You can install the ChatGPT Commit Assistant using pip: pip install git-lazy-commit

You can upgrade it using pip install --upgrade git-lazy-commit.

Usage

After staging some changes (git add <glob>), call git-lazy-commit. It will generate a commit message for the staged changes. By "staged changes", I mean the changes that you have run git add on, but not yet committed, i.e. the ones returned by git diff --staged.

You need to be an OpenAI user to use git-lazy-commit, and you need to specify where to find your API key. Here is the precedence for where I look for the API key.

  1. --api-key-path <path>
  2. OPENAI_API_KEY environment variable
  3. ~/.openai-api-key

You can create keys at https://platform.openai.com/account/api-keys.

For example:

$ cd my-git-repo
$ git add .
$ git-lazy-commit
Generated commit message: Update version to 0.12 and remove print statement
Do you approve this commit message? ((y)es/(n)o/(e)ditor):

If you press y/yes, it will commit your change with the proposed message. If you press n/no, it will try coming up with another message. If you press e/editor, it will open up $EDITOR and let you modify the message before comitting.

If you want to exit the script, press Ctrl+C.

You can pass the model you want to use using -m/--model, e.g. -m gpt-4. The default is gpt-3-turbo. Note that gpt-4 is quite a bit slower and more expensive. gpt-3-turbo, on the other hand, is extremely cheap (it's costing me less than 10 cents a day to use this).

You can also pass --verbose to see some extra info, like the token usage.

Acknowledgement

It should not be surprising that this tool was itself mostly generated by ChatGPT (the GPT-4 version), except for chatbot.py, which was written by Simon Willison and discussed in this blog post.

Examples

Here's a diff from my dotfiles repo where I added the direnv plugin to oh-my-zsh.

diff --git a/.zshrc.base.inc b/.zshrc.base.inc
index 7926b0e..34b54e0 100644
--- a/.zshrc.base.inc
+++ b/.zshrc.base.inc
@@ -11,6 +11,7 @@ plugins=(
   asdf
   # git clone https://github.com/davidparsson/zsh-pyenv-lazy.git ~/.oh-my-zsh/custom/plugins/pyenv-lazy
   pyenv-lazy
+  direnv
 )

what I'd have written if I wasn't lazy: add direnv plugin to oh-my-zsh

git-lazy-commit: feat: add direnv plugin to zshrc base configuration file

Note that it prepended a silly little "feat:". It's not perfect! For this reason, git-lazy-commit lets you edit the proposed commit message using the $EDITOR of your choice.

Another example. Here's a diff from the git-lazy-commit repo, where I gave up trying to generate the diff with GitPython (I couldn't figure out how to make its output match git diff --staged) and just used subprocess to run git diff --staged directly.

diff --git a/assistant/core.py b/assistant/core.py
index bea132e..7524ed4 100755
--- a/assistant/core.py
+++ b/assistant/core.py
@@ -1,6 +1,7 @@
 import os
-import git
 import argparse
+import subprocess
+import git
 from .chatbot import ChatBot


@@ -11,8 +12,9 @@ class Assistant:
             model=model,
         )

-    def get_uncommitted_changes(self, repo):
-        uncommitted_changes = repo.git.diff().split("\n")
+    def get_uncommitted_changes(self):
+        staged_changes = subprocess.run(["git", "diff", "--staged"], capture_output=True, text=True)
+        uncommitted_changes = staged_changes.stdout.split('\n')
         return uncommitted_changes

     def generate_commit_message(self, changes_summary):
@@ -47,7 +49,7 @@ def main(args=None):
     assistant = Assistant(args.model)

     repo = git.Repo(os.getcwd())
-    uncommitted_changes = assistant.get_uncommitted_changes(repo)
+    uncommitted_changes = assistant.get_uncommitted_changes()
     changes_summary = "\n".join(uncommitted_changes)
     generated_commit_message = assistant.generate_commit_message(changes_summary)

what I'd have written if I wasn't lazy: Use subprocess to call git diff --staged instead of trying to get gitpython to print what I want

git-lazy-commit: Refactored uncommitted changes retrieval to use subprocess instead of git module

Here, I wanted update the interactivity of git-lazy-commit to allow a user to enter "y" instead of "yes" (etc).

diff --git a/d1c2fee b/2c59fd1
index d1c2fee..2c59fd1 100644
--- a/assistant/core.py
+++ b/assistant/core.py
@@ -39,11 +39,11 @@ class Assistant:
             input("Do you approve this commit message? ((y)es/(n)o/(e)ditor): ").strip().lower()
         )

-        if user_input == "yes":
+        if user_input in ["yes", "y"]:
             return True, commit_msg
-        elif user_input == "no":
+        elif user_input in ["no", "n"]:
             return False, commit_msg
-        elif user_input == "e":
+        elif user_input in ["editor", "e"]:
             return self.edit_commit_message(commit_msg)
         else:
             print("Invalid input. Please enter 'yes (or y)', 'no (or n)', or 'editor (or e)'.")
diff --git a/setup.py b/setup.py
index fccccad..50e03a7 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages

 setup(
     name="git-lazy-commit",
-    version="0.9",
+    version="0.10",
     packages=find_packages(),
     entry_points={"console_scripts": ["git-lazy-commit = assistant:main"]},
     install_requires=["openai", "GitPython"],

what I'd have written if I wasn't lazy: allow user to enter "y" instead of "yes" (etc); bump version

git-lazy-commit: Update version number in setup.py and add support for 'y' and 'n' input in Assistant class.

License

Apache 2.0

About

git-lazy-commit generates commit messages for staged changes in a git repository using OpenAI's OpenGPT.

License:Other


Languages

Language:Python 97.3%Language:Makefile 2.7%