From 76c466fe06bb6325f637160ae8854e60d70cecba Mon Sep 17 00:00:00 2001 From: zhangkun Date: Sun, 28 Sep 2025 18:36:46 +0800 Subject: [PATCH 1/2] feat: add --amend option for commit command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Added --amend flag to modify the last commit instead of creating a new one 2. Implemented logic to fetch diff from last commit when in amend mode 3. Added display of original commit message for reference during amend 4. Modified git command execution to include --amend flag when appropriate 5. Added proper error handling for amend mode when no commit history exists 6. Updated help documentation to include the new --amend option 7. Skip AI code review for amend operations since it's modifying existing commit Log: Added --amend option to modify last commit with new commit message Influence: 1. Test normal commit functionality to ensure no regression 2. Test --amend option with staged changes to modify last commit 3. Test --amend option with other flags like --only-chinese 4. Verify error handling when no commit history exists for amend 5. Test amend with different commit types and messages 6. Verify that original commit message is displayed correctly 7. Ensure AI code review is skipped for amend operations feat: 为 commit 命令添加 --amend 选项 1. 添加 --amend 标志用于修改上一次提交而不是创建新提交 2. 实现在 amend 模式下从上次提交获取差异内容的逻辑 3. 添加在 amend 时显示原提交信息供参考的功能 4. 修改 git 命令执行以在适当时包含 --amend 标志 5. 为 amend 模式添加适当的错误处理,当没有提交历史时 6. 更新帮助文档以包含新的 --amend 选项 7. 为 amend 操作跳过 AI 代码审查,因为是修改现有提交 Log: 新增 --amend 选项用于使用新提交信息修改上次提交 Influence: 1. 测试正常提交功能以确保没有回归 2. 测试 --amend 选项与暂存更改一起使用来修改上次提交 3. 测试 --amend 选项与其他标志如 --only-chinese 的组合使用 4. 验证当没有提交历史时 amend 的错误处理 5. 测试使用不同提交类型和消息的 amend 操作 6. 验证原提交信息是否正确显示 7. 确保 AI 代码审查在 amend 操作中被跳过 --- README.md | 6 +++- src/commit.rs | 82 ++++++++++++++++++++++++++++++++++++++++----------- src/git.rs | 34 +++++++++++++++++++-- src/main.rs | 7 +++-- 4 files changed, 107 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 1c98240..529ff42 100644 --- a/README.md +++ b/README.md @@ -197,7 +197,7 @@ git-commit-helper translate /path/to/existing/file # 文件路径 | ai list | 列出所有服务 | `git-commit-helper ai list` | | ai test | 测试指定服务 | `git-commit-helper ai test [-t "测试文本"]` | | translate | 翻译内容 | `git-commit-helper translate [-f 文件] [-t 文本]` | -| commit | 生成提交信息 | `git-commit-helper commit [-t 类型] [-m 描述] [-a] [--no-review/--no-influence/--no-log/--only-chinese/--only-english] [--issues ISSUE...]` | +| commit | 生成提交信息 | `git-commit-helper commit [-t 类型] [-m 描述] [-a] [--amend] [--no-review/--no-influence/--no-log/--only-chinese/--only-english] [--issues ISSUE...]` | | ai-review | 管理 AI 代码审查 | `git-commit-helper ai-review [--enable/--disable/--status]` | ### 提交类型 @@ -304,6 +304,10 @@ git-commit-helper commit --issues "https://pms.uniontech.com/story-view-38949.ht # 混合关联 git-commit-helper commit --issues "123" "https://pms.uniontech.com/bug-view-320461.html" git-commit-helper commit --issues "https://github.com/owner/repo/issues/123" "https://pms.uniontech.com/task-view-374223.html" + +# 修补上次提交 +git-commit-helper commit --amend +git-commit-helper commit --amend --only-chinese ``` ### AI 代码审查功能 diff --git a/src/commit.rs b/src/commit.rs index feeb3d7..3ba3adc 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -686,6 +686,7 @@ pub async fn generate_commit_message( commit_type: Option, message: Option, auto_add: bool, + amend: bool, no_review: bool, no_translate: bool, mut only_chinese: bool, @@ -726,15 +727,26 @@ pub async fn generate_commit_message( std::env::set_var("GIT_COMMIT_HELPER_NO_TRANSLATE", "1"); } - let diff = get_staged_diff()?; + // 根据是否是 amend 模式选择不同的 diff + let diff = if amend { + println!("正在分析上一次提交的更改内容..."); + git::get_last_commit_diff()? + } else { + get_staged_diff()? + }; + if diff.is_empty() { - return Err(anyhow::anyhow!("没有已暂存的改动,请先使用 git add 添加改动")); + if amend { + return Err(anyhow::anyhow!("无法获取上一次提交的差异内容,可能没有足够的提交历史")); + } else { + return Err(anyhow::anyhow!("没有已暂存的改动,请先使用 git add 添加改动")); + } } let config = config::Config::load()?; - // 在确认有暂存的改动后执行代码审查 - if !no_review && config.ai_review { + // 在确认有差异内容后执行代码审查(对于 amend 模式,我们跳过审查,因为是对已有提交的修改) + if !amend && !no_review && config.ai_review { info!("正在进行代码审查..."); if let Some(review) = review::review_changes(&config, no_review).await? { println!("\n{}\n", review); @@ -756,7 +768,19 @@ pub async fn generate_commit_message( let service = config.get_default_service()?; let translator = ai_service::create_translator_for_service(service).await?; - println!("\n正在生成提交信息建议..."); + if amend { + println!("\n正在基于上一次提交的更改生成新的提交信息..."); + // 显示原提交信息供参考 + if let Ok(original_msg) = git::get_last_commit_message() { + println!("原提交信息:"); + println!("----------------------------------------"); + println!("{}", original_msg.trim()); + println!("----------------------------------------\n"); + } + } else { + println!("\n正在生成提交信息建议..."); + } + let mut message = translator.chat(&prompt, &diff).await? .trim_start_matches("[NO_TRANSLATE]") .trim_start_matches("、、、plaintext") @@ -795,38 +819,62 @@ pub async fn generate_commit_message( } // 预览生成的提交信息 - println!("\n生成的提交信息预览:"); + if amend { + println!("\n生成的修改后提交信息预览:"); + } else { + println!("\n生成的提交信息预览:"); + } println!("----------------------------------------"); println!("{}", content); println!("----------------------------------------"); - // 移除翻译相关的询问,直接询问用户是否确认提交 + // 询问用户是否确认提交 + let prompt_text = if amend { + "是否使用此提交信息修改上一次提交?" + } else { + "是否使用此提交信息?" + }; + if !Confirm::with_theme(&dialoguer::theme::ColorfulTheme::default()) - .with_prompt("是否使用此提交信息?") + .with_prompt(prompt_text) .default(true) .interact()? { - println!("已取消提交"); + if amend { + println!("已取消修改上一次提交"); + } else { + println!("已取消提交"); + } return Ok(()); } // 执行git commit - let status = Command::new("git") - .current_dir(std::env::current_dir()?) - .arg("commit") - .arg("-m") - .arg(content) - .status()?; + let mut cmd = Command::new("git"); + cmd.current_dir(std::env::current_dir()?); + cmd.arg("commit"); + + if amend { + cmd.arg("--amend"); + } + + cmd.arg("-m").arg(content); + + let status = cmd.status()?; // 清理环境变量(无论命令是否执行成功) std::env::remove_var("GIT_COMMIT_HELPER_SKIP_REVIEW"); std::env::remove_var("GIT_COMMIT_HELPER_NO_TRANSLATE"); if !status.success() { - return Err(anyhow::anyhow!("git commit 命令执行失败")); + let action = if amend { "修改提交" } else { "提交" }; + return Err(anyhow::anyhow!("git commit 命令执行失败,{} 失败", action)); } - println!("提交成功!"); + if amend { + println!("修改提交成功!"); + } else { + println!("提交成功!"); + } Ok(()) } diff --git a/src/git.rs b/src/git.rs index 9fea451..8d81d47 100644 --- a/src/git.rs +++ b/src/git.rs @@ -102,6 +102,36 @@ fn contains_chinese(text: &str) -> bool { text.chars().any(|c| c as u32 >= 0x4E00 && c as u32 <= 0x9FFF) } -pub fn wrap_text(text: &str, max_length: usize) -> String { - fill(text, max_length) +pub fn wrap_text(text: &str, width: usize) -> String { + fill(text, width) +} + +/// 获取上一次提交的差异内容,用于 amend 模式 +pub fn get_last_commit_diff() -> anyhow::Result { + use std::process::Command; + + let output = Command::new("git") + .args(["diff", "HEAD~1..HEAD", "--no-prefix"]) + .output()?; + + if !output.status.success() { + return Err(anyhow::anyhow!("执行 git diff HEAD~1..HEAD 命令失败,可能没有足够的提交历史")); + } + + Ok(String::from_utf8(output.stdout)?) +} + +/// 获取上一次提交的信息 +pub fn get_last_commit_message() -> anyhow::Result { + use std::process::Command; + + let output = Command::new("git") + .args(["log", "-1", "--pretty=format:%s%n%n%b"]) + .output()?; + + if !output.status.success() { + return Err(anyhow::anyhow!("执行 git log 命令失败")); + } + + Ok(String::from_utf8(output.stdout)?) } diff --git a/src/main.rs b/src/main.rs index 7ea8b1a..2d8c751 100644 --- a/src/main.rs +++ b/src/main.rs @@ -83,6 +83,9 @@ enum Commands { /// 自动添加所有已修改但未暂存的文件 #[arg(short, long)] all: bool, + /// 修改上一次提交信息 + #[arg(long)] + amend: bool, /// 不翻译提交信息 #[arg(long)] no_translate: bool, @@ -413,13 +416,13 @@ async fn main() -> Result<()> { Err(e) => Err(e) } } - Some(Commands::Commit { r#type, message, all, no_translate, only_chinese, only_english, no_influence, no_log, issues }) => { + Some(Commands::Commit { r#type, message, all, amend, no_translate, only_chinese, only_english, no_influence, no_log, issues }) => { let issues_str = if issues.is_empty() { None } else { Some(issues.join(" ")) }; - commit::generate_commit_message(r#type, message, all, cli.no_review, no_translate, only_chinese, only_english, no_influence, no_log, issues_str).await + commit::generate_commit_message(r#type, message, all, amend, cli.no_review, no_translate, only_chinese, only_english, no_influence, no_log, issues_str).await } Some(Commands::AIReview { enable, disable, status }) => { let mut config = config::Config::load()?; From 53b0087065952d05ce9135d0d17e56800e64890c Mon Sep 17 00:00:00 2001 From: zccrs Date: Sat, 11 Oct 2025 16:44:07 +0800 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/git.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/git.rs b/src/git.rs index 8d81d47..75be2f6 100644 --- a/src/git.rs +++ b/src/git.rs @@ -115,7 +115,7 @@ pub fn get_last_commit_diff() -> anyhow::Result { .output()?; if !output.status.success() { - return Err(anyhow::anyhow!("执行 git diff HEAD~1..HEAD 命令失败,可能没有足够的提交历史")); + return Err(anyhow::anyhow!("执行 git diff HEAD~1..HEAD --no-prefix 命令失败,可能没有足够的提交历史")); } Ok(String::from_utf8(output.stdout)?)