Skip to content
This repository was archived by the owner on Jan 14, 2026. It is now read-only.

Commit 06f1272

Browse files
committed
feat(gitcommit): add commit history context for message generation
- introduce `use_commit_history` and `commit_history_count` options to include recent commit messages as context - update generator to pass commit history to LLM prompt for improved style consistency - implement `Git.get_commit_history` to retrieve recent commit messages from git log - update configuration, types, and example config to support and document the new feature - ensure commit history context is used across buffer, init, and generator modules
1 parent 4d0682e commit 06f1272

7 files changed

Lines changed: 163 additions & 25 deletions

File tree

config_example_with_history.lua

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
-- Example configuration showing how to use the new commit history feature
2+
3+
require("codecompanion").setup({
4+
adapters = {
5+
openai = function()
6+
return require("codecompanion.adapters").use("openai", {
7+
env = {
8+
api_key = "your_api_key_here"
9+
},
10+
})
11+
end,
12+
},
13+
extensions = {
14+
-- GitCommit extension with history context enabled
15+
require("codecompanion._extensions.gitcommit").setup({
16+
-- Core configuration
17+
adapter = "openai",
18+
model = "gpt-4-turbo-preview",
19+
languages = { "English", "Chinese" },
20+
21+
-- NEW: History commit context configuration
22+
use_commit_history = true, -- Enable using commit history as context
23+
commit_history_count = 15, -- Use 15 recent commits for context (default: 10)
24+
25+
-- Existing configuration options
26+
buffer = {
27+
enabled = true,
28+
keymap = "<leader>gc",
29+
auto_generate = true,
30+
auto_generate_delay = 200,
31+
skip_auto_generate_on_amend = true,
32+
},
33+
34+
exclude_files = {
35+
"*.pb.go",
36+
"*.min.js",
37+
"package-lock.json",
38+
"yarn.lock",
39+
"*.log",
40+
"dist/*",
41+
"build/*",
42+
"node_modules/*",
43+
},
44+
45+
add_git_tool = true,
46+
enable_git_read = true,
47+
enable_git_edit = true,
48+
enable_git_bot = true,
49+
git_tool_auto_submit_success = true,
50+
})
51+
},
52+
})
53+
54+
-- Alternative configuration with history disabled
55+
-- require("codecompanion._extensions.gitcommit").setup({
56+
-- use_commit_history = false, -- Disable history context
57+
-- -- ... other options
58+
-- })

lua/codecompanion/_extensions/gitcommit/buffer.lua

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,16 @@ function Buffer._generate_and_insert_commit_message(bufnr)
114114

115115
Langs.select_lang(function(lang)
116116
vim.notify("Generating commit message...", vim.log.levels.INFO)
117+
118+
-- Get commit history if enabled
119+
local commit_history = nil
120+
local git_config = Git.get_config and Git.get_config() or {}
121+
if git_config.use_commit_history then
122+
commit_history = Git.get_commit_history(git_config.commit_history_count)
123+
end
124+
117125
-- Generate commit message using LLM
118-
Generator.generate_commit_message(diff, lang, function(result, error)
126+
Generator.generate_commit_message(diff, lang, commit_history, function(result, error)
119127
if error then
120128
vim.notify("Failed to generate commit message: " .. error, vim.log.levels.ERROR)
121129
return

lua/codecompanion/_extensions/gitcommit/config.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ M.default_opts = {
3434
git_tool_auto_submit_errors = false,
3535
git_tool_auto_submit_success = true,
3636
gitcommit_select_count = 100,
37+
-- History commit context configuration
38+
use_commit_history = true, -- Enable using commit history as context
39+
commit_history_count = 10, -- Number of recent commits to include as context
3740
}
3841

3942
return M

lua/codecompanion/_extensions/gitcommit/generator.lua

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,8 @@ function Generator.setup(adapter, model)
2727
error("Invalid adapter specified: " .. tostring(_adapter))
2828
end
2929
end
30-
31-
---Generate commit message using LLM
32-
---
33-
---@param diff string The git diff to analyze
34-
---@param lang? string The language to generate the commit message in (optional)
35-
---@param callback fun(result: string|nil, error: string|nil) Callback function
36-
function Generator.generate_commit_message(diff, lang, callback)
30+
---@param commit_history? string[] Array of recent commit messages for context (optional)
31+
function Generator.generate_commit_message(diff, lang, commit_history, callback)
3732
-- Setup adapter
3833
local adapter = codecompanion_adapter.resolve(_adapter)
3934
if not adapter then
@@ -49,7 +44,7 @@ function Generator.generate_commit_message(diff, lang, callback)
4944
})
5045

5146
-- Create prompt for LLM
52-
local prompt = Generator._create_prompt(diff, lang)
47+
local prompt = Generator._create_prompt(diff, lang, commit_history)
5348

5449
local payload = {
5550
messages = adapter:map_roles({
@@ -69,11 +64,20 @@ end
6964

7065
---Create prompt for commit message generation
7166
---@param diff string The git diff to include in prompt
72-
---@param lang? string The generate language (optional, not used in this implementation)
73-
---@return string prompt The formatted prompt
74-
function Generator._create_prompt(diff, lang)
67+
---@param commit_history? string[] Array of recent commit messages for context (optional)
68+
function Generator._create_prompt(diff, lang, commit_history)
69+
-- Build the history context section
70+
local history_context = ""
71+
if commit_history and #commit_history > 0 then
72+
history_context = "\nRECENT COMMIT HISTORY (for style reference):\n"
73+
for i, commit_msg in ipairs(commit_history) do
74+
history_context = history_context .. string.format("%d. %s\n", i, commit_msg)
75+
end
76+
history_context = history_context .. "\nAnalyze the above commit history to understand the project's commit style, tone, and format patterns. Use this as guidance to maintain consistency.\n"
77+
end
78+
7579
return string.format(
76-
[[You are a commit message generator. Generate exactly ONE complete Conventional Commit message for the provided git diff.
80+
[[You are a commit message generator. Generate exactly ONE complete Conventional Commit message for the provided git diff.%s
7781
7882
CRITICAL FORMAT REQUIREMENTS:
7983
1. MUST generate exactly ONE commit message, never multiple messages
@@ -95,8 +99,7 @@ RULES:
9599
- Title: Use imperative mood ("add" not "added"), keep under 50 characters
96100
- Body: At least ONE bullet point describing the changes
97101
- For large diffs: Focus on the most significant changes, group related changes
98-
- Choose the primary type that best represents the overall change
99-
- Even with extensive changes, generate only ONE unified commit message
102+
- If commit history is provided, follow the established patterns and style from recent commits
100103
101104
REQUIRED EXAMPLES:
102105
feat(auth): add OAuth2 integration
@@ -116,6 +119,7 @@ Generate ONE complete commit message for this diff:
116119
```
117120
118121
Return ONLY the commit message in the exact format shown above.]],
122+
history_context,
119123
lang or "English",
120124
diff
121125
)

lua/codecompanion/_extensions/gitcommit/git.lua

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ local Git = {}
44
-- Store configuration
55
local config = {}
66

7-
---Setup Git module with configuration
8-
---@param opts? table Configuration options
97
function Git.setup(opts)
108
config = vim.tbl_deep_extend("force", {
119
exclude_files = {},
10+
use_commit_history = true,
11+
commit_history_count = 10,
1212
}, opts or {})
1313
end
1414

@@ -342,4 +342,52 @@ function Git.commit_changes(message)
342342
return success
343343
end
344344

345+
---Get recent commit messages for context
346+
---@param count? number Number of recent commits to retrieve (default: 10)
347+
---@return string[]|nil commit_messages Array of commit messages or nil on error
348+
function Git.get_commit_history(count)
349+
count = count or 10
350+
351+
-- Use pcall to safely execute git operations
352+
local ok, result = pcall(function()
353+
if not Git.is_repository() then
354+
return nil
355+
end
356+
357+
-- Get recent commit messages using git log
358+
-- Use --pretty=format to get just the commit message
359+
local cmd = string.format("git log --pretty=format:%%s --no-merges -%d", count)
360+
local output = vim.fn.system(cmd)
361+
362+
if vim.v.shell_error ~= 0 then
363+
return nil
364+
end
365+
366+
-- Split output into lines and filter out empty lines
367+
local lines = vim.split(output, "\n")
368+
local commit_messages = {}
369+
370+
for _, line in ipairs(lines) do
371+
local trimmed = trim(line)
372+
if trimmed ~= "" then
373+
table.insert(commit_messages, trimmed)
374+
end
375+
end
376+
377+
return commit_messages
378+
end)
379+
380+
if not ok then
381+
return nil
382+
end
383+
384+
return result
385+
end
386+
387+
---Get current configuration
388+
---@return table config Current configuration
389+
function Git.get_config()
390+
return vim.deepcopy(config)
391+
end
392+
345393
return Git

lua/codecompanion/_extensions/gitcommit/init.lua

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,16 @@ function M.generate_commit_message()
3232

3333
Langs.select_lang(function(lang)
3434
vim.notify("Generating commit message...", vim.log.levels.INFO)
35+
36+
-- Get commit history if enabled
37+
local commit_history = nil
38+
local git_config = Git.get_config and Git.get_config() or {}
39+
if git_config.use_commit_history then
40+
commit_history = Git.get_commit_history(git_config.commit_history_count)
41+
end
42+
3543
-- Generate commit message using LLM
36-
Generator.generate_commit_message(diff, lang, function(result, error)
44+
Generator.generate_commit_message(diff, lang, commit_history, function(result, error)
3745
if error then
3846
vim.notify("Failed to generate commit message: " .. error, vim.log.levels.ERROR)
3947
return
@@ -268,7 +276,11 @@ return {
268276
setup = function(opts)
269277
opts = vim.tbl_deep_extend("force", Config.default_opts, opts or {})
270278

271-
Git.setup({ exclude_files = opts.exclude_files })
279+
Git.setup({
280+
exclude_files = opts.exclude_files,
281+
use_commit_history = opts.use_commit_history,
282+
commit_history_count = opts.commit_history_count,
283+
})
272284
Generator.setup(opts.adapter, opts.model)
273285
Buffer.setup(opts.buffer)
274286
Langs.setup(opts.languages)
@@ -294,8 +306,15 @@ return {
294306
return callback(nil, "No staged changes found. Please stage your changes first.")
295307
end
296308

309+
-- Get commit history if enabled
310+
local commit_history = nil
311+
local git_config = Git.get_config and Git.get_config() or {}
312+
if git_config.use_commit_history then
313+
commit_history = Git.get_commit_history(git_config.commit_history_count)
314+
end
315+
297316
-- Generate commit message
298-
Generator.generate_commit_message(diff, lang, callback)
317+
Generator.generate_commit_message(diff, lang, commit_history, callback)
299318
end,
300319

301320
---Check if current directory is in a git repository

lua/codecompanion/_extensions/gitcommit/types.lua

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
---@meta
1+
---@field use_commit_history? boolean Enable using commit history as context (default: true)
2+
---@field commit_history_count? number Number of recent commits to include as context (default: 10)
23

3-
---@class CodeCompanion.GitCommit.Extension
4-
---@field setup fun(opts: CodeCompanion.GitCommit.ExtensionOpts): nil
54
---@field exports CodeCompanion.GitCommit.Exports
65

76
---@class CodeCompanion.GitCommit.ExtensionOpts.Buffer
@@ -54,8 +53,7 @@
5453
---@field get_staged_diff fun(): string|nil -- Get git diff for staged changes
5554
---@field commit_changes fun(message: string): boolean -- Commit changes with the provided message
5655

57-
---@class CodeCompanion.GitCommit.Generator
58-
---@field generate_commit_message fun(diff: string,lang: string?, callback: fun(result: string|nil, error: string|nil)): nil -- Generate commit message using LLM
56+
---@field generate_commit_message fun(diff: string,lang: string?, commit_history: string[]?, callback: fun(result: string|nil, error: string|nil)): nil -- Generate commit message using LLM
5957

6058
---@class CodeCompanion.GitCommit.UI
6159
---@field show_commit_message fun(message: string, on_commit: fun(message: string): boolean): nil -- Show commit message in a floating window with interactive options

0 commit comments

Comments
 (0)