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
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "git-intelligence-message"
version = "2.1.0"
version = "2.1.1"
edition = "2024"
description = "An advanced Git commit message generation utility with AI assistance"
authors = ["Sheldon.Wei<sheldon.sh.hb@gmail.com>"]
Expand Down
2 changes: 1 addition & 1 deletion dist-workspace.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ tap = "davelet/homebrew-gim"
# A GitHub repo to push Scoop manifests to
scoop-bucket = "davelet/scoop-gim"
# Target platforms to build apps for (Rust target-triple syntax)
targets = ["aarch64-apple-darwin", "aarch64-unknown-linux-gnu", "aarch64-pc-windows-msvc", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu", "x86_64-unknown-linux-musl", "x86_64-pc-windows-msvc"]
targets = ["aarch64-apple-darwin", "aarch64-unknown-linux-gnu", "aarch64-pc-windows-msvc", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu", "x86_64-pc-windows-msvc"]
# Path that installers should place binaries in
install-path = "CARGO_HOME"
# Publish jobs to run in CI
Expand Down
12 changes: 11 additions & 1 deletion docs/content/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## [2.1.1] - 2025-03-17

- **Smart File Limiting**: Added `--max-files` / `-n` option to limit the number of changed files sent to AI
- Configurable via `gim config --max-files <N>` (default: 10)
- Intelligent file selection: prioritizes files with most changes
- Auto-filters to code files only when code changes exceed 50% of total
- Supports file type classification (Code, Config, Doc, Other)
- Priority order: CLI argument > config file > default value


## [2.1.0] - 2026-02-12

- **M Chip Support for Mac**: Release build for M chip Macs.
Expand Down Expand Up @@ -62,4 +72,4 @@
- View both diff and subject prompt templates
- Edit prompt files with `--edit` flag
- Support for custom editors with `--editor` option
- Short aliases for prompt types (d/diff/diff_prompt, s/subject/subject_prompt)
- Short aliases for prompt types (d/diff/diff_prompt, s/subject/subject_prompt)
40 changes: 39 additions & 1 deletion docs/content/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ gim -ap
- `-t, --title <STRING>`: Specify the commit message title
- `-a, --auto-add`: Automatically stage all modifications
- `-p, --update`: Amend the most recent commit
- `-n, --max-files <N>`: Maximum number of changed files to send to AI (overrides config, default: 10)
- `-v, --verbose`: Show detailed information (will be suppressed in quiet mode)
- `-q, --quiet`: Suppress normal output (quiet mode)
- `--diff-prompt <STRING>`: Custom diff prompt to override the default AI prompt for analyzing changes
Expand Down Expand Up @@ -86,4 +87,41 @@ The prompts are used in the following priority order:
3. **Config directory** - Global prompt files
4. **Built-in defaults** - Fallback prompts

This allows you to have project-specific prompts in a `.gim` directory, but override them temporarily with command line arguments when needed.
This allows you to have project-specific prompts in a `.gim` directory, but override them temporarily with command line arguments when needed.

## Limiting Files Sent to AI (`--max-files` / `-n`)

When you have many changed files, sending all of them to AI can be overwhelming and costly. The `--max-files` option limits how many files are included in the diff sent to AI.

**Usage examples:**

```bash
# Limit to 5 most significant files
gim -n 5

# Combine with other options
gim -a -n 3

# Override config setting temporarily
gim --max-files 20
```

**Smart File Selection:**

When the number of changed files exceeds the limit, GIM uses intelligent selection:

1. Files are ranked by the number of lines changed (additions + deletions)
2. If code file changes exceed 50% of total changes, only code files are kept (config and doc files are filtered out)
3. The top N most significant files are selected

**Supported file types:**

- **Code**: `.rs`, `.go`, `.py`, `.js`, `.ts`, `.java`, `.c`, `.cpp`, and many more
- **Config**: `.xml`, `.toml`, `.yaml`, `.json`, `.ini`, `.env`, etc.
- **Doc**: `.md`, `.txt`, `.rst`, `.adoc`, etc.

**Priority Order:**

1. **Command line argument** (`-n` / `--max-files`) - Highest priority
2. **Config file** (`gim config --max-files <N>`)
3. **Default value** (10 files)
34 changes: 33 additions & 1 deletion docs/content/user_config.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,44 @@
This feature was introduced in version `1.4.0`. Currently, only one parameter is configurable.
This feature was introduced in version `1.4.0`.

# lines-limit

`lines-limit` is an integer that limits the maximum number of lines per commit. If this limit is exceeded, the application will not execute. The default value is `1000`.

You can configure this parameter using `gim config --lines-limit <LINES_LIMIT>`.

# max-files

`max-files` is an integer that limits the maximum number of changed files to send to AI. When the number of changed files exceeds this limit, GIM will intelligently select the most significant files based on:

1. **Lines changed**: Files with more changes are prioritized
2. **File type filtering**: If code changes exceed 50% of total changes, only code files are included (filtering out config, docs, etc.)

The default value is `10`.

You can configure this parameter using:

```bash
gim config --max-files <MAX_FILES>
```

You can also override this value temporarily using the `-n` or `--max-files` CLI option:

```bash
# Limit to 5 files for this commit
gim -n 5

# Or use the long form
gim --max-files 5
```

**Supported file type classifications:**

- **Code**: `.rs`, `.go`, `.py`, `.js`, `.ts`, `.java`, `.c`, `.cpp`, etc.
- **Config**: `.xml`, `.toml`, `.yaml`, `.json`, `.ini`, `.env`, etc.
- **Doc**: `.md`, `.txt`, `.rst`, `.adoc`, etc.

# show-location

Since version `1.7.0`, you can use `--show-location` flag to show config file location.
And it opens the default file manager to the config file location.

Expand Down
8 changes: 8 additions & 0 deletions src/cli/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ pub struct GimCli {
/// Custom subject prompt to override the default
#[arg(long)]
pub subject_prompt: Option<String>,

/// Maximum number of changed files to send to AI (overrides config)
#[arg(short = 'n', long)]
pub max_files: Option<usize>,
}

/// Enum representing all supported subcommands for the gim CLI.
Expand Down Expand Up @@ -102,6 +106,10 @@ pub enum GimCommands {
#[arg(long)]
lines_limit: Option<usize>,

/// Maximum number of changed files to send to AI
#[arg(long)]
max_files: Option<usize>,

/// Print config file's location
#[arg(long, default_value_t = false)]
show_location: bool,
Expand Down
7 changes: 5 additions & 2 deletions src/commands/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ pub async fn generate_commit_message(
pub fn execute_commit(subject: &str, message: &str, overwrite: bool) {
if crate::core::git::git_commit(subject, message, overwrite) {
output::print_normal(
"✅ Successfully committed changes! If you were discontent with the commit message and want to polish or revise it, run 'gim -p' or 'git commit --amend'"
"✅ Successfully committed changes! If you were discontent with the commit message and want to polish or revise it, run 'gim -p' or 'git commit --amend'",
);
} else {
eprintln!("Error: Failed to commit changes");
Expand All @@ -121,7 +121,10 @@ pub fn execute_commit(subject: &str, message: &str, overwrite: bool) {
/// # Returns
///
/// * `Ok(())` if within limit, exits with error if exceeds.
pub fn check_diff_limit(diff_content: &str, diff_limit: usize) -> Result<(), Box<dyn std::error::Error>> {
pub fn check_diff_limit(
diff_content: &str,
diff_limit: usize,
) -> Result<(), Box<dyn std::error::Error>> {
if diff_content.lines().count() > diff_limit {
eprintdoc!(
r"
Expand Down
58 changes: 55 additions & 3 deletions src/commands/config.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::io::{ErrorKind, Result};
use toml::{Value, map::Map};

use crate::config::constants::{CUSTOM_SECTION_NAME, DIFF_SIZE_LIMIT};
use crate::config::constants::{CUSTOM_SECTION_NAME, DIFF_SIZE_LIMIT, MAX_DIFF_FILES};
use crate::utils::output;

static NAME: &str = "lines_limit";
static MAX_FILES_NAME: &str = "max_diff_files";

pub fn get_lines_limit() -> usize {
let lines_limit = gim_config::config::get_config_value(CUSTOM_SECTION_NAME, NAME);
Expand Down Expand Up @@ -47,13 +48,64 @@ pub fn set_lines_limit(lines_limit: usize) -> Result<()> {
}
return Err(e);
}
output::print_normal(
&format!("set custom config '{}' done, value: {:?}",
output::print_normal(&format!(
"set custom config '{}' done, value: {:?}",
NAME, lines_limit
));
Ok(())
}

pub fn get_max_diff_files() -> usize {
let max_files = gim_config::config::get_config_value(CUSTOM_SECTION_NAME, MAX_FILES_NAME);
if let Err(e) = max_files {
output::print_verbose(&format!(
"get custom config '{}' error: {:?}, return default: {}",
MAX_FILES_NAME, e, MAX_DIFF_FILES
));
return MAX_DIFF_FILES;
}
let max_files = max_files.ok();
if let Some(limit) = max_files {
output::print_verbose(&format!(
"get custom config '{}' value: {:?}",
MAX_FILES_NAME, limit
));
return limit.as_integer().unwrap_or(MAX_DIFF_FILES as i64) as usize;
}
MAX_DIFF_FILES
}

pub fn set_max_diff_files(max_files: usize) -> Result<()> {
let set = gim_config::config::update_config_value(
CUSTOM_SECTION_NAME,
MAX_FILES_NAME,
Value::Integer(max_files as i64),
);
if let Err(e) = set {
output::print_verbose(&format!(
"set custom config '{}' error: {:?}",
MAX_FILES_NAME, e
));
if e.kind() == ErrorKind::NotFound {
if e.to_string() == format!("Section '{}' not found", CUSTOM_SECTION_NAME) {
let mut config = gim_config::config::get_config().unwrap();
let map = config.as_table_mut().unwrap();

let mut update_table = Map::new();
update_table.insert(MAX_FILES_NAME.to_string(), Value::Integer(max_files as i64));
map.insert(CUSTOM_SECTION_NAME.to_string(), Value::Table(update_table));
return gim_config::config::save_config(&mut config);
}
}
return Err(e);
}
output::print_normal(&format!(
"set custom config '{}' done, value: {:?}",
MAX_FILES_NAME, max_files
));
Ok(())
}

/// Gets and prints the config file location.
///
/// # Returns
Expand Down
6 changes: 3 additions & 3 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub mod update;
pub mod prompt;
pub mod ai;
pub mod config;
pub mod commit;
pub mod config;
pub mod prompt;
pub mod update;
5 changes: 4 additions & 1 deletion src/commands/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ fn get_latest_version_by_homebrew() -> Result<Version, Box<dyn std::error::Error
let output = Command::new("brew")
.args(["info", "--json=v2", REPOSITORY])
.output()?;
output::print_verbose(&format!("[background] run 'brew info --json=v2 {}'", REPOSITORY));
output::print_verbose(&format!(
"[background] run 'brew info --json=v2 {}'",
REPOSITORY
));

if !output.status.success() {
return Err("Failed to fetch version information from Homebrew".into());
Expand Down
1 change: 1 addition & 0 deletions src/config/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ pub const SUBJECT_PROMPT_FILE: &str = "subject_prompt.txt";

pub const CUSTOM_SECTION_NAME: &str = "user";
pub const DIFF_SIZE_LIMIT: usize = 1000;
pub const MAX_DIFF_FILES: usize = 10;
2 changes: 1 addition & 1 deletion src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pub mod urls;
pub mod constants;
pub mod urls;
Loading
Loading