@@ -33,23 +33,91 @@ function Git.is_repository()
3333 return vim .v .shell_error == 0 and vim .trim (result ) == " true"
3434end
3535
36- --- Get git diff for staged changes
37- --- @return string | nil diff The staged changes diff , nil if no changes or error
38- function Git .get_staged_diff ()
36+ --- Check if currently in git commit --amend state
37+ --- @return boolean
38+ function Git .is_amending ()
3939 if not Git .is_repository () then
40- return nil
40+ return false
4141 end
4242
43- local diff = vim .fn .system (" git diff --no-ext-diff --staged" )
43+ -- Check if COMMIT_EDITMSG exists and we're in a rebase/merge state
44+ local git_dir = vim .fn .system (" git rev-parse --git-dir" ):gsub (" \n " , " " )
4445 if vim .v .shell_error ~= 0 then
45- return nil
46+ return false
47+ end
48+
49+ -- Check for COMMIT_EDITMSG file which indicates we're editing a commit
50+ local commit_editmsg = git_dir .. " /COMMIT_EDITMSG"
51+ local stat = vim .uv .fs_stat (commit_editmsg )
52+ if not stat then
53+ return false
4654 end
4755
48- if vim .trim (diff ) == " " then
56+ -- Additional check: see if we have HEAD commit (not initial commit)
57+ local head_check = vim .fn .system (" git rev-parse --verify HEAD" )
58+ return vim .v .shell_error == 0
59+ end
60+
61+ --- Get git diff for staged changes or last commit (for amend)
62+ --- @return string | nil diff The changes diff , nil if no changes or error
63+ function Git .get_staged_diff ()
64+ if not Git .is_repository () then
4965 return nil
5066 end
5167
52- return diff
68+ -- First try to get staged changes
69+ local staged_diff = vim .fn .system (" git diff --no-ext-diff --staged" )
70+ if vim .v .shell_error == 0 and vim .trim (staged_diff ) ~= " " then
71+ return staged_diff
72+ end
73+
74+ -- If no staged changes and we're in amend mode, get the last commit's changes
75+ if Git .is_amending () then
76+ local last_commit_diff = vim .fn .system (" git diff --no-ext-diff HEAD~1" )
77+ if vim .v .shell_error == 0 and vim .trim (last_commit_diff ) ~= " " then
78+ return last_commit_diff
79+ end
80+
81+ -- Fallback: if HEAD~1 doesn't exist (initial commit), show all files
82+ local show_diff = vim .fn .system (" git show --no-ext-diff --format= HEAD" )
83+ if vim .v .shell_error == 0 and vim .trim (show_diff ) ~= " " then
84+ return show_diff
85+ end
86+ end
87+
88+ return nil
89+ end
90+
91+ --- Get contextual diff based on current git state
92+ --- @return string | nil diff The relevant diff , nil if no changes
93+ --- @return string context The context of what diff represents
94+ function Git .get_contextual_diff ()
95+ if not Git .is_repository () then
96+ return nil , " not_in_repo"
97+ end
98+
99+ -- Check for staged changes first
100+ local staged_diff = vim .fn .system (" git diff --no-ext-diff --staged" )
101+ if vim .v .shell_error == 0 and vim .trim (staged_diff ) ~= " " then
102+ return staged_diff , " staged"
103+ end
104+
105+ -- Check if we're amending
106+ if Git .is_amending () then
107+ -- Try to get the last commit's diff
108+ local last_commit_diff = vim .fn .system (" git diff --no-ext-diff HEAD~1" )
109+ if vim .v .shell_error == 0 and vim .trim (last_commit_diff ) ~= " " then
110+ return last_commit_diff , " amend_with_parent"
111+ end
112+
113+ -- Fallback for initial commit amend
114+ local show_diff = vim .fn .system (" git show --no-ext-diff --format= HEAD" )
115+ if vim .v .shell_error == 0 and vim .trim (show_diff ) ~= " " then
116+ return show_diff , " amend_initial"
117+ end
118+ end
119+
120+ return nil , " no_changes"
53121end
54122
55123--- Commit changes with the provided message
@@ -61,10 +129,16 @@ function Git.commit_changes(message)
61129 return false
62130 end
63131
64- -- Check if there are staged changes
65- local diff = Git .get_staged_diff ()
132+ -- Check if there are changes to commit
133+ local diff , context = Git .get_contextual_diff ()
66134 if not diff then
67- vim .notify (" No staged changes found. Please stage your changes first." , vim .log .levels .ERROR )
135+ if context == " no_changes" then
136+ if Git .is_amending () then
137+ vim .notify (" No changes to amend. The commit already exists." , vim .log .levels .WARN )
138+ else
139+ vim .notify (" No staged changes found. Please stage your changes first." , vim .log .levels .ERROR )
140+ end
141+ end
68142 return false
69143 end
70144
@@ -79,16 +153,23 @@ function Git.commit_changes(message)
79153 file :write (message )
80154 file :close ()
81155
82- -- Execute git commit
83- local cmd = string.format (" git commit -F %s" , vim .fn .shellescape (temp_file ))
156+ -- Execute appropriate git commit command
157+ local cmd
158+ if Git .is_amending () then
159+ cmd = string.format (" git commit --amend -F %s" , vim .fn .shellescape (temp_file ))
160+ else
161+ cmd = string.format (" git commit -F %s" , vim .fn .shellescape (temp_file ))
162+ end
163+
84164 local result = vim .fn .system (cmd )
85165 local exit_code = vim .v .shell_error
86166
87167 -- Clean up temporary file
88168 os.remove (temp_file )
89169
90170 if exit_code == 0 then
91- vim .notify (" Successfully committed changes!" , vim .log .levels .INFO )
171+ local action = Git .is_amending () and " amended" or " committed"
172+ vim .notify (string.format (" Successfully %s changes!" , action ), vim .log .levels .INFO )
92173 return true
93174 else
94175 local error_msg = vim .trim (result )
0 commit comments