Skip to content

Commit 0212e9a

Browse files
feat(move): Add --fixup to squash moved commits into the destination
1 parent bda1877 commit 0212e9a

File tree

5 files changed

+940
-3
lines changed

5 files changed

+940
-3
lines changed

git-branchless-lib/src/core/rewrite/execute.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,10 @@ mod in_memory {
612612
"Applying patch for commit: {}",
613613
fixup_commit_description
614614
));
615+
// TODO it's possible that we could skip much of this
616+
// loop if, instead of creating a commit and then
617+
// immediately (repeatedly) amending and re-creating it,
618+
// we just amended the tree and then commited it once
615619
let commit_tree = repo.amend_fast(
616620
&rebased_commit,
617621
&AmendFastOptions::FromCommit {

git-branchless/src/commands/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ fn do_main_and_drop_locals() -> eyre::Result<i32> {
221221
dest,
222222
base,
223223
exact,
224+
fixup,
224225
insert,
225226
move_options,
226227
} => r#move::r#move(
@@ -230,6 +231,7 @@ fn do_main_and_drop_locals() -> eyre::Result<i32> {
230231
dest,
231232
base,
232233
exact,
234+
fixup,
233235
insert,
234236
&move_options,
235237
)?,

git-branchless/src/commands/move.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ pub fn r#move(
6464
dest: Option<Revset>,
6565
bases: Vec<Revset>,
6666
exacts: Vec<Revset>,
67+
fixup: bool,
6768
insert: bool,
6869
move_options: &MoveOptions,
6970
) -> eyre::Result<ExitCode> {
@@ -255,7 +256,7 @@ pub fn r#move(
255256
let commits_to_move = commits_to_move.union(&union_all(
256257
&exact_components.values().cloned().collect::<Vec<_>>(),
257258
));
258-
let commits_to_move = if insert {
259+
let commits_to_move = if insert || fixup {
259260
commits_to_move.union(&dag.query().children(CommitSet::from(dest_oid))?)
260261
} else {
261262
commits_to_move
@@ -274,7 +275,18 @@ pub fn r#move(
274275

275276
let source_roots = dag.query().roots(source_oids.clone())?;
276277
for source_root in commit_set_to_vec(&source_roots)? {
277-
builder.move_subtree(source_root, vec![dest_oid])?;
278+
if fixup {
279+
let commits = dag
280+
.query()
281+
.descendants(CommitSet::from(source_root))?
282+
.difference(&dag.obsolete_commits);
283+
let commits = commit_set_to_vec(&commits)?;
284+
for commit in commits.iter() {
285+
builder.fixup_commit(*commit, dest_oid)?;
286+
}
287+
} else {
288+
builder.move_subtree(source_root, vec![dest_oid])?;
289+
}
278290
}
279291

280292
let component_roots: CommitSet = exact_components.keys().cloned().collect();
@@ -383,7 +395,14 @@ pub fn r#move(
383395
}
384396
}
385397

386-
builder.move_subtree(component_root, vec![component_dest_oid])?;
398+
if fixup {
399+
let commits = commit_set_to_vec(component)?;
400+
for commit in commits.iter() {
401+
builder.fixup_commit(*commit, dest_oid)?;
402+
}
403+
} else {
404+
builder.move_subtree(component_root, vec![component_dest_oid])?;
405+
}
387406
}
388407

389408
if insert {

git-branchless/src/opts.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,10 @@ pub enum Command {
311311
#[clap(value_parser, short = 'd', long = "dest")]
312312
dest: Option<Revset>,
313313

314+
/// Combine the moved commits and squash into the destination commit.
315+
#[clap(action, short = 'F', long = "fixup", conflicts_with = "insert")]
316+
fixup: bool,
317+
314318
/// Insert the subtree between the destination and it's children, if any.
315319
/// Only supported if the moved subtree has a single head.
316320
#[clap(action, short = 'I', long = "insert")]

0 commit comments

Comments
 (0)