Skip to content

Commit ad90677

Browse files
committed
fix: add backup before git reset --hard in rebase_continue and rebase_skip
rebase_continue() and rebase_skip() performed git reset --hard during squash-merge Reset handling without creating a backup branch first, unlike rebase() which always creates a backup. This was a data loss risk. Add create_backup_branch() helper and call it before destructive resets in both functions. Also add 10 new integration tests covering squash-merge handling in continue/skip, second conflicts, abort with multiple modified branches, step mode with conflict, dirty working directory, cleanup backups after continue, and status with mixed statuses.
1 parent 9971291 commit ad90677

2 files changed

Lines changed: 1556 additions & 4 deletions

File tree

src/git_chain/operations.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,11 @@ impl GitChain {
601601
parent_name.bold()
602602
);
603603

604+
// Create backup before destructive reset
605+
self.create_backup_branch(&state.chain_name, &branch_name)?;
606+
let backup_name = format!("backup-{}/{}", state.chain_name, &branch_name);
607+
println!("📦 Created backup branch: {}", backup_name.bold());
608+
604609
let command = format!("git reset --hard {}", parent_name);
605610
let output = Command::new("git")
606611
.arg("reset")
@@ -910,6 +915,11 @@ impl GitChain {
910915
parent_name.bold()
911916
);
912917

918+
// Create backup before destructive reset
919+
self.create_backup_branch(&state.chain_name, &branch_name)?;
920+
let backup_name = format!("backup-{}/{}", state.chain_name, &branch_name);
921+
println!("📦 Created backup branch: {}", backup_name.bold());
922+
913923
let command = format!("git reset --hard {}", parent_name);
914924
let output = Command::new("git")
915925
.arg("reset")
@@ -1122,6 +1132,15 @@ impl GitChain {
11221132
}
11231133
}
11241134

1135+
/// Create a backup branch for a named branch in a chain.
1136+
fn create_backup_branch(&self, chain_name: &str, branch_name: &str) -> Result<(), Error> {
1137+
let (object, _reference) = self.repo.revparse_ext(branch_name)?;
1138+
let commit = self.repo.find_commit(object.id())?;
1139+
let backup_branch = format!("backup-{}/{}", chain_name, branch_name);
1140+
self.repo.branch(&backup_branch, &commit, true)?;
1141+
Ok(())
1142+
}
1143+
11251144
/// Delete backup branches for a chain after successful rebase.
11261145
fn cleanup_backup_branches(&self, chain_name: &str, branches: &[BranchState]) {
11271146
let mut cleaned = 0;

0 commit comments

Comments
 (0)