Skip to content

Commit ca86a4a

Browse files
baldawarishiclaude
andauthored
feat: deduplicate trailers by email address (#9)
Checks existing commit message trailers by extracted email address instead of the full "Name <email>" string. Prevents adding a duplicate Co-authored-by when the agent already wrote one with a different display name (e.g. "Claude Opus 4.6" vs "Claude Code" both using noreply@anthropic.com). --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ada80d8 commit ca86a4a

File tree

2 files changed

+30
-8
lines changed

2 files changed

+30
-8
lines changed

src/git.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ pub fn find_git_root(start_path: &Path) -> Option<PathBuf> {
2222
pub fn append_trailers(commit_msg_file: &PathBuf, agent: &Agent, debug: bool) -> std::io::Result<()> {
2323
let content = fs::read_to_string(commit_msg_file)?;
2424

25-
if content.contains("Co-authored-by:") && content.contains(agent.email) {
25+
let addr = Agent::extract_email_addr(agent.email);
26+
if content.contains("Co-authored-by:") && content.contains(addr) {
2627
if debug {
2728
eprintln!("\n=== Git Command ===");
2829
eprintln!("Trailers already present, skipping git interpret-trailers");

src/main.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -242,15 +242,36 @@ fn main() {
242242
#[cfg(test)]
243243
mod tests {
244244
use super::*;
245-
use agent::KNOWN_AGENTS;
246245
use std::fs;
247246
use std::io::Write;
248247
use tempfile::NamedTempFile;
249248

249+
#[test]
250+
fn test_append_trailers_skips_existing_email_different_name() {
251+
// Simulate Claude Code already having added a trailer with a different display name
252+
// but the same email address (e.g. "Claude Opus 4.6 <noreply@anthropic.com>")
253+
let mut file = NamedTempFile::new().unwrap();
254+
writeln!(file, "Initial commit").unwrap();
255+
writeln!(file).unwrap();
256+
writeln!(file, "Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>").unwrap();
257+
258+
let agent = Agent::find_by_name("claude").unwrap();
259+
append_trailers(&file.path().to_path_buf(), agent, false).unwrap();
260+
261+
let content = fs::read_to_string(file.path()).unwrap();
262+
// Should NOT have added a second Co-authored-by for noreply@anthropic.com
263+
let co_author_count = content.matches("noreply@anthropic.com").count();
264+
assert_eq!(
265+
co_author_count, 1,
266+
"Should not add duplicate trailer for same email address, found {} occurrences",
267+
co_author_count
268+
);
269+
}
270+
250271
#[test]
251272
fn test_dedup_agents_removes_duplicates() {
252-
let claude = &KNOWN_AGENTS[0]; // Claude Code
253-
let amp = &KNOWN_AGENTS[8]; // Amp
273+
let claude = Agent::find_by_name("claude").unwrap();
274+
let amp = Agent::find_by_name("amp").unwrap();
254275
let agents = vec![claude, amp, claude];
255276
let deduped = dedup_agents(agents);
256277
assert_eq!(deduped.len(), 2);
@@ -316,7 +337,7 @@ mod tests {
316337
let mut file = NamedTempFile::new().unwrap();
317338
writeln!(file, "Initial commit").unwrap();
318339

319-
let agent = &KNOWN_AGENTS[0];
340+
let agent = Agent::find_by_name("claude").unwrap();
320341
append_trailers(&file.path().to_path_buf(), agent, false).unwrap();
321342

322343
let content = fs::read_to_string(file.path()).unwrap();
@@ -329,7 +350,7 @@ mod tests {
329350
let mut file = NamedTempFile::new().unwrap();
330351
writeln!(file, "Initial commit").unwrap();
331352

332-
let agent = &KNOWN_AGENTS[0];
353+
let agent = Agent::find_by_name("claude").unwrap();
333354
append_trailers(&file.path().to_path_buf(), agent, false).unwrap();
334355
let content1 = fs::read_to_string(file.path()).unwrap();
335356

@@ -363,8 +384,8 @@ mod tests {
363384
let mut file = NamedTempFile::new().unwrap();
364385
writeln!(file, "Initial commit").unwrap();
365386

366-
let agent1 = &KNOWN_AGENTS[0]; // Claude
367-
let agent2 = &KNOWN_AGENTS[8]; // Amp
387+
let agent1 = Agent::find_by_name("claude").unwrap();
388+
let agent2 = Agent::find_by_name("amp").unwrap();
368389

369390
append_trailers(&file.path().to_path_buf(), agent1, false).unwrap();
370391
append_trailers(&file.path().to_path_buf(), agent2, false).unwrap();

0 commit comments

Comments
 (0)