Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ A lightweight CLI tool that analyzes your staged changes and generates professio

## Features

- **Hybrid Intelligence** - Merges deterministic heuristic algorithms with deep semantic understanding via Local LLMs
- **Local AI Integration (Ollama)** - Seamlessly integrates with Ollama to generate context-rich commit messages offline
- **Intelligent Analysis** - Analyzes git status and diff to understand your changes using advanced pattern detection
- **Conventional Commits** - Follows the Conventional Commits specification for standardized messages
- **Configuration Hierarchy** - Local (`.gitmit.json`) → Global (`~/.gitmit.json`) → Default (Embedded) config support
Expand All @@ -30,10 +32,46 @@ A lightweight CLI tool that analyzes your staged changes and generates professio
- **Pattern Detection** - Detects error handling, tests, API changes, database operations, and more
- **Multiple Commit Types** - Supports feat, fix, refactor, chore, test, docs, style, perf, ci, build, security, and more
- **Zero Configuration** - Works out of the box with sensible defaults
- **Offline First** - Complete offline operation, no AI or external dependencies required
- **Hybrid Offline Approach** - Operates completely locally; chooses between heuristic rules or local AI
- **History Tracking** - Learns from your commit history to avoid repetitive suggestions


## Hybrid Intelligence: Local AI via Ollama

Gitmit evolves from a rule-based utility into a **Hybrid Intelligence** tool by integrating with **Ollama**. This allows you to use powerful local LLMs (like Qwen2.5-Coder) to generate highly descriptive and contextually accurate commit messages without sacrificing privacy or performance.

### Prerequisites

1. **Install Ollama**: Download from [ollama.com](https://ollama.com)
2. **Pull the Model**:
```bash
ollama pull qwen2.5-coder:3b
```

### Enabling the AI Engine

To switch from the default heuristic engine to the AI engine, update your `.gitmit.json`:

```json
{
"engine": "ollama",
"ollama": {
"model": "qwen2.5-coder:3b",
"url": "http://localhost:11434",
"temperature": 0.2
}
}
```

### How the Hybrid Pipeline Works

Gitmit uses a tiered approach to ensure you always get a high-quality suggestion:

1. **Refined Context Engineering**: Instead of piping raw diffs, Gitmit extracts structured metadata (modified files, symbols, change ratios, project type) and feeds it into a strict system prompt.
2. **Local LLM Processing**: Ollama processes the context using your specified model to generate a precise Conventional Commit message.
3. **Deterministic Fallback**: If the Ollama daemon is unreachable, the model is missing, or the output is malformatted, Gitmit **instantly falls back** to the Phase 1 Heuristic engine. Your workflow remains uninterrupted.


## Installation

### From Releases
Expand Down Expand Up @@ -110,15 +148,18 @@ Actions:
n - Reject and exit
e - Edit message manually
r - Regenerate different suggestion
a - Upgrade suggestion with Local AI (Ollama)

Choice [y/n/e/r]:
Choice [y/n/e/r/a]:
```

**Interactive Options:**
- **`y`** (or press Enter) - Accept the suggestion and commit
- **`n`** - Reject and exit without committing
- **`e`** - Edit the message manually with your own text
- **`r`** - Regenerate a completely different suggestion using intelligent variation algorithms
- **`a`** - **Upgrade to Local AI**: If you are using the heuristic engine, this attempts to connect to Ollama for a more semantic suggestion
- **`h`** - **Fallback to Heuristic**: If you are in AI mode, this switches back to the classic rule-based engine

### Command-Line Options

Expand Down Expand Up @@ -237,6 +278,12 @@ Gitmit uses intelligent offline algorithms to analyze your changes:
- Special case detection
- Diversity algorithms for variations

11. **Local AI Generation (Optional)** - When enabled:
- Serializes extracted context into a structured LLM prompt
- Dispatches generation requests to local Ollama daemon
- Validates AI output against Conventional Commit standards
- Provides deterministic fallback to heuristic engine on error

## Commit Types

Gitmit supports the following commit types (automatically detected):
Expand Down
45 changes: 45 additions & 0 deletions assets/assets.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package assets

import (
"bytes"
"embed"
"text/template"
)

//go:embed prompts/* messages/*

Check failure on line 9 in assets/assets.go

View workflow job for this annotation

GitHub Actions / Build and Test

comment on exported var Files should be of the form "Files ..."
var Files embed.FS

// GetPrompt returns the system prompt template
func GetPrompt() (string, error) {
b, err := Files.ReadFile("prompts/system_prompt.txt")
return string(b), err
}

// GetOllamaWarning returns the Ollama warning message
func GetOllamaWarning() (string, error) {
b, err := Files.ReadFile("messages/ollama_warning.txt")
return string(b), err
}

// GetInitSuccess returns the initialization success message
func GetInitSuccess() (string, error) {
b, err := Files.ReadFile("messages/init_success.txt")
return string(b), err
}

// RenderOllamaWarning renders the Ollama warning message with the provided context
func RenderOllamaWarning(url, model string) (string, error) {
warningTmpl, err := GetOllamaWarning()
if err != nil {
return "", err
}
tmpl, err := template.New("warning").Parse(warningTmpl)
if err != nil {
return "", err
}
var buf bytes.Buffer
if err := tmpl.Execute(&buf, struct{ URL, Model string }{URL: url, Model: model}); err != nil {
return "", err
}
return buf.String(), nil
}
7 changes: 7 additions & 0 deletions assets/messages/init_success.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

You can now customize the configuration to fit your project's needs.

Configuration hierarchy:
1. Local (.gitmit.json) - project-specific settings
2. Global (~/.gitmit.json) - user-wide settings
3. Default (embedded) - built-in defaults
7 changes: 7 additions & 0 deletions assets/messages/ollama_warning.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
⚠️ Ollama connection not detected on {{.URL}}
To enable Local AI generation, please ensure:
1. Ollama is running locally (`ollama serve`)
2. The required model is pulled (`ollama pull {{.Model}}`)
3. Your .gitmit.json sets "engine": "ollama"

Falling back to interactive options...
18 changes: 18 additions & 0 deletions assets/prompts/system_prompt.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
You are an expert developer assistant. Analyze the provided structured git diff metadata and generate a single-line commit message following the Conventional Commits specification.

Guidelines:
1. Format MUST be: <type>(<scope>): <short description in present tense>
2. Allowed types: feat, fix, refactor, chore, test, docs, style, perf, ci, build, security
3. Do NOT include any markdown, backticks, quotes, or introductory text like "Here is your commit message:".
4. Output ONLY the raw string of the commit message.

Metadata Context:
- Project Type: {{.ProjectType}}
- Active Branch Name: {{.CurrentBranch}}
- Detected Intent/Type Bonus: {{.RecommendedType}}
- Modified Files: {{range .Files}}{{.}}, {{end}}
- Key Code Symbols Altered: {{range .CodeSymbols}}{{.}}, {{end}}
- Dependency Changes: {{.DependencyAlert}}
- Added/Deleted Line Ratio: {{printf "%.2f" .DiffSummary.Ratio}}

Output:
9 changes: 4 additions & 5 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/fatih/color"
"github.com/spf13/cobra"

"gitmit/assets"
"gitmit/internal/config"
)

Expand Down Expand Up @@ -152,11 +153,9 @@ func runInit(cmd *cobra.Command, args []string) error {

color.Green("✅ Created config file: %s", configPath)
color.Blue("\n📝 Detected project type: %s", projectType)
fmt.Println("\nYou can now customize the configuration to fit your project's needs.")
fmt.Println("\nConfiguration hierarchy:")
fmt.Println(" 1. Local (.gitmit.json) - project-specific settings")
fmt.Println(" 2. Global (~/.gitmit.json) - user-wide settings")
fmt.Println(" 3. Default (embedded) - built-in defaults")

msg, _ := assets.GetInitSuccess()
fmt.Println(msg)

return nil
}
Loading
Loading