Skip to content

Commit fdbdf15

Browse files
committed
3 modes: . - #
1 parent 52d953e commit fdbdf15

File tree

2 files changed

+48
-33
lines changed

2 files changed

+48
-33
lines changed

README.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,16 @@ This repository includes a custom Git commit message hook powered by OpenAI. The
66

77
## Features
88

9-
- **AI-generated commit messages:** Uses OpenAI to suggest commit messages based on your code changes or file list.
10-
- **Static file awareness:** Recognizes static file changes (CSS, HTML, images) and notes them accordingly.
11-
- **Two modes:**
12-
- `.` (one dot): Generates a commit message based on the full diff of staged changes.
13-
- `..` (two dots): Generates a commit message based only on the list of changed files.
9+
**Modes:**
10+
- `.` (dot): Full diff (includes static assets) -> richest context.
11+
- `-` (dash): File list only (old `..` behavior).
12+
- `#` (hash): Diff excluding static assets (old `.` behavior) with their names listed separately.
1413

1514
## Quick Install
1615

17-
```sh
18-
curl -fsSL instll.sh/inem/dot-commit | sh
19-
```
16+
- `.` — analyze full diff (includes static assets like css/html/images).
17+
- `-` — analyze only the file list (no diff body).
18+
- `#` — analyze diff excluding static/static-like files; list of all changed files appended.
2019

2120
or
2221

main.go

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -56,30 +56,32 @@ func main() {
5656
logDebug(logFile, fmt.Sprintf("commit message = '%s'", text))
5757
}
5858

59-
// Only process if message is "." or ".."
60-
if text != "." && text != ".." {
61-
logDebug(logFile, "message is not '.' or '..', exiting")
59+
// Modes:
60+
// "." -> full diff including static files (new default)
61+
// "-" -> file list only (replaces old "..")
62+
// "#" -> diff excluding static files (old "." behavior)
63+
if text != "." && text != "-" && text != "#" {
64+
logDebug(logFile, "message is not one of '.', '-', '#'; exiting")
6265
return
6366
}
6467

6568
logDebug(logFile, fmt.Sprintf("proceeding with AI generation for '%s'", text))
6669

6770
var body string
71+
var mode string
6872

69-
if text == ".." {
70-
// 1. For ".." - only file list mode
71-
logDebug(logFile, "using file list only mode")
72-
73+
switch text {
74+
case "-":
75+
mode = "file_list"
76+
logDebug(logFile, "using file list only mode (-)")
7377
cmd := exec.Command("git", "diff", "--cached", "--name-only")
7478
output, err := cmd.Output()
7579
if err != nil {
7680
logDebug(logFile, fmt.Sprintf("git command failed: %v", err))
7781
return
7882
}
79-
8083
files := strings.Split(strings.TrimSpace(string(output)), "\n")
8184
var staticFiles, nonStaticFiles []string
82-
8385
for _, file := range files {
8486
file = strings.TrimSpace(file)
8587
if file == "" {
@@ -91,42 +93,57 @@ func main() {
9193
nonStaticFiles = append(nonStaticFiles, file)
9294
}
9395
}
94-
9596
body = "FILES CHANGED:\n" + strings.Join(nonStaticFiles, "\n")
9697
if len(staticFiles) > 0 {
9798
body += "\nSTATIC FILES CHANGED:\n" + strings.Join(staticFiles, "\n")
9899
}
99-
} else {
100-
// 2. For "." - full diff mode
101-
logDebug(logFile, "using full diff mode")
102-
100+
case "#":
101+
mode = "diff_excluding_static"
102+
logDebug(logFile, "using diff excluding static files mode (#)")
103+
// old behavior: exclude static files from diff, append list at end
103104
excludeArgs := []string{"diff", "--cached", "--binary"}
104105
for _, ext := range staticExt {
105106
excludeArgs = append(excludeArgs, fmt.Sprintf(":(exclude)*.%s", ext))
106107
}
107-
108108
diffCmd := exec.Command("git", excludeArgs...)
109109
diffOutput, err := diffCmd.Output()
110110
if err != nil {
111111
logDebug(logFile, fmt.Sprintf("git diff command failed: %v", err))
112112
return
113113
}
114-
115114
staticCmd := exec.Command("git", "diff", "--cached", "--name-only")
116115
staticOutput, err := staticCmd.Output()
117116
if err != nil {
118117
logDebug(logFile, fmt.Sprintf("git name-only command failed: %v", err))
119118
return
120119
}
121-
122120
body = string(diffOutput) + "\nSTATIC FILES CHANGED:\n" + string(staticOutput)
123-
124-
if len(body) > 8000 { // Trim to 8KB
121+
if len(body) > 8000 {
122+
body = body[:8000]
123+
}
124+
case ".":
125+
mode = "full_diff"
126+
logDebug(logFile, "using full diff including static files mode (.)")
127+
diffCmd := exec.Command("git", "diff", "--cached", "--binary")
128+
diffOutput, err := diffCmd.Output()
129+
if err != nil {
130+
logDebug(logFile, fmt.Sprintf("git diff command failed: %v", err))
131+
return
132+
}
133+
// Also capture name-only list for potential static awareness (not excluding here)
134+
nameOnlyCmd := exec.Command("git", "diff", "--cached", "--name-only")
135+
nameOnlyOutput, err := nameOnlyCmd.Output()
136+
if err != nil {
137+
logDebug(logFile, fmt.Sprintf("git name-only command failed: %v", err))
138+
return
139+
}
140+
body = string(diffOutput) + "\nFILES CHANGED:\n" + string(nameOnlyOutput)
141+
if len(body) > 8000 {
125142
body = body[:8000]
126143
}
127144
}
128145

129-
// 2. Send to OpenAI
146+
// Send to OpenAI
130147
apiKey := os.Getenv("OPENAI_API_KEY")
131148
if apiKey == "" {
132149
logDebug(logFile, "OPENAI_API_KEY not set")
@@ -136,7 +153,7 @@ func main() {
136153
client := openai.NewClient(apiKey)
137154

138155
var prompt string
139-
if text == ".." {
156+
if mode == "file_list" {
140157
prompt = fmt.Sprintf(`You are a senior software engineer crafting high–quality, intention‑revealing Git commit titles.
141158
142159
TASK:
@@ -159,11 +176,11 @@ FILE CHANGES:
159176
%s
160177
161178
Commit message:`, body)
162-
} else {
179+
} else { // diff modes
163180
prompt = fmt.Sprintf(`You are a senior software engineer writing a single Git commit title.
164181
165182
TASK:
166-
Analyze the following staged diff (and a list of static files at the end) and produce ONE concise, intention‑revealing commit message line (<=70 chars) capturing the primary purpose (WHY) of the change set.
183+
Analyze the following staged diff (and file list at the end) and produce ONE concise, intention‑revealing commit message line (<=70 chars) capturing the primary purpose (WHY) of the change set.
167184
168185
DIFF & CONTEXT:
169186
%s
@@ -209,7 +226,6 @@ Commit message:`, body)
209226
}
210227

211228
newMsg := strings.TrimSpace(resp.Choices[0].Message.Content)
212-
// Safety: ensure single line & <= 70 chars
213229
if idx := strings.IndexAny(newMsg, "\r\n"); idx >= 0 {
214230
newMsg = strings.TrimSpace(newMsg[:idx])
215231
}
@@ -226,4 +242,4 @@ Commit message:`, body)
226242
}
227243
logDebug(logFile, "wrote new message to file")
228244
}
229-
}
245+
}

0 commit comments

Comments
 (0)