/magit-gptcommit

Magit commit with help of gpt

Primary LanguageEmacs LispGNU General Public License v3.0GPL-3.0

Intro

Generate git commit messages on Magit using LLM providers, for example: OpenAI ChatGPT, Google Gemini, and more.

melpa

magit-gptcommit.intro.mp4

Dependencies

Setup

Note

If you are using gptel as a backend, please check out this branch: gptel

magit-gptcommit depends on llm. Please read the documentation of llm for more details on how to set up providers. Debug logging for llm can be enabled by setting llm-log to t.

For example, to set up the OpenAI provider, first create an OpenAI API key. Once obtained, configure the llm OpenAI provider with the API key (replace "OPENAI-KEY" with your key):

(setq magit-gptcommit-llm-provider (make-llm-openai :key "OPENAI-KEY"))

Recommended: See below how to use Emacs auth-source to protect API keys for llm providers.

Activate magit-gptcommit-mode and open a Magit status buffer, the commit message will be automatically generated when changes are staged. You can run magit-gptcommit-generate when visiting a Magit status buffer to generate a commit message manually.

Setup example using use-package and straight:

(use-package magit-gptcommit
  :straight t
  :demand t
  :after magit
  :bind (:map git-commit-mode-map
              ("C-c C-g" . magit-gptcommit-commit-accept))
  :custom
  (magit-gptcommit-llm-provider (make-llm-openai :key "OPENAI-KEY"))

  :config
  ;; Enable magit-gptcommit-mode to watch staged changes and generate commit message automatically in magit status buffer
  ;; This mode is optional, you can also use `magit-gptcommit-generate' to generate commit message manually
  ;; `magit-gptcommit-generate' should only execute on magit status buffer currently
  ;; (magit-gptcommit-mode 1)

  ;; Add gptcommit transient commands to `magit-commit'
  ;; Eval (transient-remove-suffix 'magit-commit '(1 -1)) to remove gptcommit transient commands
  (magit-gptcommit-status-buffer-setup))

Usage

Command Description
magit-gptcommit-generate Generate gptcommit message and insert it into magit buffer.
magit-gptcommit-commit-create Execute `magit-commit-create' and bring gptcommit message to editor.
magit-gptcommit-commit-quick Accept gptcommit message and make a commit with current staged.
magit-gptcommit-commit-accept Call on COMMIT_EDITMSG buffer, Accept gptcommit message after saving current message.
magit-gptcommit-abort Abort the query process of current Repository.
magit-gptcommit-remove-section Remove the gptcommit section from the current magit buffer.
Variable Description
magit-gptcommit-prompt Prompt.
magit-gptcommit-max-token Default 4096, magit-gptcommit will truncate excessive characters based on 1 token = 4 chars
magit-gptcommit-determine-max-token Whether to use the llm provider max tokens, used only if magit-gptcommit-max-token is nil.
magit-gptcommit-cache-limit Cache size, default is 30
magit-gptcommit--cache Cache of last generated commit message.
magit-gptcommit-llm-provider llm provider or a function that returns an llm provider.
magit-gptcommit-llm-provider-temperature llm provider temperature. (float)
magit-gptcommit-llm-provider-max-tokens llm provider max generated tokens. (integer)

Using auth-source for API keys

Setup an llm provider for Google Gemini using use-package, straight, and Emacs auth-source, given that there is an auth-source secret stored with the host "generativelanguage.googleapis.com" and the user "apikey".

(use-package magit-gptcommit
  :straight t
  :demand t
  :after magit
  :bind (:map git-commit-mode-map
              ("C-c C-g" . magit-gptcommit-commit-accept))
  :init
  (defun my/magit-gptcommit-gemini-llm-provider ()
    (let (provider)
      (lambda ()
        (or provider
            (progn
              (require 'llm-gemini)
              (setq provider (make-llm-gemini
                              :key
                              (auth-info-password
                               (car (auth-source-search
                                     :host "generativelanguage.googleapis.com"
                                     :user "apikey"))))))))))
  :custom
  (magit-gptcommit-llm-provider (my/magit-gptcommit-gemini-llm-provider))

  :config
  ;; Enable magit-gptcommit-mode to watch staged changes and generate commit message automatically in magit status buffer
  ;; This mode is optional, you can also use `magit-gptcommit-generate' to generate commit message manually
  ;; `magit-gptcommit-generate' should only execute on magit status buffer currently
  ;; (magit-gptcommit-mode 1)

  ;; Add gptcommit transient commands to `magit-commit'
  ;; Eval (transient-remove-suffix 'magit-commit '(1 -1)) to remove gptcommit transient commands
  (magit-gptcommit-status-buffer-setup))

Todo

  • Prompt optimization
    • There is still a lot of room for optimization. One problem is the context limitation, for example, GPT3.5 has a 4k context limit, so making a slightly larger edit will exceed the limit. Currently, the code roughly truncates the edit based on proportions to avoid this problem.
    • Alternatively, we could use a method similar to gptcommit. This method summarizes the diff of each file and then merges all the summaries to generate the commit message. However, this approach requires n + 2 requests to generate a single message.
  • LRU Cache or Disk Cache
  • NO Stream
  • Other LLM Support

Credit

  • llm Great project.
  • gptcommit Very helpful, Prompt modified from this project.
  • magit-todos This project has been of great help to me in learning magit development.
  • GPT-Commit: Another Emacs pacakge for a similar purpose.