Skip to content

Commit 1bfaea9

Browse files
Copilotzccrs
andauthored
fix: preserve all commit marks (Fixes/PMS/Log/etc.) when using --amend (#19)
* Initial plan * fix: preserve Fixes:/PMS: issue references in --amend mode When using `git-commit-helper commit --amend`, issue references (Fixes: and PMS:) from the original commit were being lost because the AI-generated message didn't always include them. Now, when --amend is used without explicitly providing new --issues, the tool extracts Fixes: and PMS: marks from the original commit message and appends any missing ones to the new commit message. The Change-Id preservation logic already existed and is unchanged. Co-authored-by: zccrs <13449038+zccrs@users.noreply.github.com> * fix: preserve all marks (Fixes/PMS/Log/etc) in --amend mode, not just issue refs Expand the amend mark preservation from only Fixes:/PMS: to all marks from the original commit (excluding Change-Id which is already handled by append_change_id). This ensures Log:, Fixes:, PMS:, and any other single-line marks are retained when amending a commit. Co-authored-by: zccrs <13449038+zccrs@users.noreply.github.com> * refactor: move amend mark preservation into a dedicated if amend block Separate the mark preservation logic from the --issues parameter check. Instead of nesting in `else if amend`, use a standalone `if amend { ... }` block that handles all amend-specific mark preservation (including Change-Id) in one place, after the --issues handling. Co-authored-by: zccrs <13449038+zccrs@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: zccrs <13449038+zccrs@users.noreply.github.com>
1 parent 5b28e51 commit 1bfaea9

File tree

1 file changed

+91
-2
lines changed

1 file changed

+91
-2
lines changed

src/commit.rs

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -878,9 +878,30 @@ pub async fn generate_commit_message(
878878
}
879879
}
880880
}
881-
882-
// 在 amend 模式下,如果原提交有 Change-Id,保留它
881+
882+
// 在 amend 模式下,保留原提交中所有未被新内容覆盖的标记字段
883+
// (Change-Id 须保持在最后,由 append_change_id 单独处理)
883884
if amend {
885+
if let Some(ref orig_msg) = original_message {
886+
let orig_commit = CommitMessage::parse(orig_msg);
887+
let marks_to_add: Vec<String> = orig_commit.marks.iter()
888+
.filter(|mark| {
889+
let mark_key = mark.split(':').next().unwrap_or("").trim().to_lowercase();
890+
mark_key != "change-id" && !content.lines().any(|line| {
891+
line.trim().split(':').next()
892+
.map_or(false, |k| k.trim().to_lowercase() == mark_key)
893+
})
894+
})
895+
.cloned()
896+
.collect();
897+
if !marks_to_add.is_empty() {
898+
if !content.ends_with('\n') {
899+
content.push('\n');
900+
}
901+
content.push('\n');
902+
content.push_str(&marks_to_add.join("\n"));
903+
}
904+
}
884905
if let Some(change_id) = original_change_id {
885906
content = append_change_id(&content, &change_id);
886907
}
@@ -1154,4 +1175,72 @@ mod tests {
11541175
// Change-Id 应该在最后
11551176
assert!(result.ends_with("Change-Id: I1234567890abcdef1234567890abcdef12345678"));
11561177
}
1178+
1179+
// 测试从原提交消息中提取所有需保留的标记(排除 Change-Id)
1180+
#[test]
1181+
fn test_extract_issue_marks_from_original_commit() {
1182+
let original = "fix: some bug\n\nDescription here\n\nFixes: #123\nPMS: BUG-456\nLog: Fix critical bug\nChange-Id: Iabc123\n";
1183+
let orig_commit = CommitMessage::parse(original);
1184+
let marks_to_preserve: Vec<String> = orig_commit.marks.iter()
1185+
.filter(|mark| {
1186+
let mark_key = mark.split(':').next().unwrap_or("").trim().to_lowercase();
1187+
mark_key != "change-id"
1188+
})
1189+
.cloned()
1190+
.collect();
1191+
assert_eq!(marks_to_preserve.len(), 3);
1192+
assert!(marks_to_preserve.contains(&"Fixes: #123".to_string()));
1193+
assert!(marks_to_preserve.contains(&"PMS: BUG-456".to_string()));
1194+
assert!(marks_to_preserve.contains(&"Log: Fix critical bug".to_string()));
1195+
// Change-Id 不应被保留(由 append_change_id 单独处理)
1196+
assert!(!marks_to_preserve.iter().any(|m| m.to_lowercase().starts_with("change-id:")));
1197+
}
1198+
1199+
// 测试 amend 时新内容已包含标记时不重复添加
1200+
#[test]
1201+
fn test_amend_no_duplicate_issue_marks() {
1202+
let original = "fix: some bug\n\nFixes: #123\nLog: Fix bug\n";
1203+
let orig_commit = CommitMessage::parse(original);
1204+
1205+
// 新内容已包含 Fixes: 和 Log:
1206+
let new_content = "fix: improved bug fix\n\nBetter description\n\nFixes: #123\nLog: Fix bug";
1207+
let marks_to_add: Vec<String> = orig_commit.marks.iter()
1208+
.filter(|mark| {
1209+
let mark_key = mark.split(':').next().unwrap_or("").trim().to_lowercase();
1210+
mark_key != "change-id" && !new_content.lines().any(|line| {
1211+
line.trim().split(':').next()
1212+
.map_or(false, |k| k.trim().to_lowercase() == mark_key)
1213+
})
1214+
})
1215+
.cloned()
1216+
.collect();
1217+
// 不应重复添加
1218+
assert!(marks_to_add.is_empty());
1219+
}
1220+
1221+
// 测试 amend 时新内容不含标记时正确添加所有标记
1222+
#[test]
1223+
fn test_amend_preserves_issue_marks_when_missing() {
1224+
let original = "fix: some bug\n\nFixes: #123\nPMS: BUG-456\nLog: Fix critical bug\nChange-Id: Iabc123\n";
1225+
let orig_commit = CommitMessage::parse(original);
1226+
1227+
// 新内容不含任何标记
1228+
let new_content = "fix: improved bug fix\n\nBetter description";
1229+
let marks_to_add: Vec<String> = orig_commit.marks.iter()
1230+
.filter(|mark| {
1231+
let mark_key = mark.split(':').next().unwrap_or("").trim().to_lowercase();
1232+
mark_key != "change-id" && !new_content.lines().any(|line| {
1233+
line.trim().split(':').next()
1234+
.map_or(false, |k| k.trim().to_lowercase() == mark_key)
1235+
})
1236+
})
1237+
.cloned()
1238+
.collect();
1239+
assert_eq!(marks_to_add.len(), 3);
1240+
assert!(marks_to_add.contains(&"Fixes: #123".to_string()));
1241+
assert!(marks_to_add.contains(&"PMS: BUG-456".to_string()));
1242+
assert!(marks_to_add.contains(&"Log: Fix critical bug".to_string()));
1243+
// Change-Id 不应被包含(由 append_change_id 处理)
1244+
assert!(!marks_to_add.iter().any(|m| m.to_lowercase().starts_with("change-id:")));
1245+
}
11571246
}

0 commit comments

Comments
 (0)