rewrite::move_commits(): preserve order of parent commits

When rebasing a new child commit on top of the moved commit(s), the
order of the new child commit's parent commits is now correctly
preserved if the original parent commit is now a parent of the moved
commit(s).

Closes #3969.
This commit is contained in:
Benjamin Tan 2024-08-14 19:24:30 +08:00
parent 4a17b9fbe4
commit ab604b4ecd
2 changed files with 32 additions and 26 deletions

View file

@ -1470,11 +1470,11 @@ fn test_rebase_revisions_after() {
c c
@ f b4
b2 b3
b1 @ f
b4 b2
b3 b1
a a

View file

@ -643,33 +643,39 @@ pub fn move_commits(
new_children new_children
.iter() .iter()
.map(|child_commit| { .map(|child_commit| {
let mut new_child_parent_ids: IndexSet<_> = child_commit let mut new_child_parent_ids = IndexSet::new();
.parent_ids() for old_child_parent_id in child_commit.parent_ids() {
.iter()
// Replace target commits with their parents outside the target set. // Replace target commits with their parents outside the target set.
.flat_map(|id| { let old_child_parent_ids = if let Some(parents) =
if let Some(parents) = target_commits_external_parents.get(id) { target_commits_external_parents.get(old_child_parent_id)
parents.iter().cloned().collect_vec() {
} else { parents.iter().collect_vec()
[id.clone()].to_vec() } else {
} vec![old_child_parent_id]
}) };
// Exclude any of the new parents of the target commits, since we are
// "inserting" the target commits in between the new parents and the new
// children.
.filter(|id| {
!new_parent_ids
.iter()
.any(|new_parent_id| new_parent_id == id)
})
.collect();
// Add `target_heads` as parents of the new child commit. // If the original parents of the new children are the new parents of the
// `target_heads`, replace them with the target heads since we are "inserting"
// the target commits in between the new parents and the new children.
for id in old_child_parent_ids {
if new_parent_ids
.iter()
.any(|new_parent_id| *new_parent_id == *id)
{
new_child_parent_ids.extend(target_heads.clone());
} else {
new_child_parent_ids.insert(id.clone());
};
}
}
// If not already present, add `target_heads` as parents of the new child
// commit.
new_child_parent_ids.extend(target_heads.clone()); new_child_parent_ids.extend(target_heads.clone());
( (
child_commit.id().clone(), child_commit.id().clone(),
new_child_parent_ids.iter().cloned().collect_vec(), new_child_parent_ids.into_iter().collect_vec(),
) )
}) })
.collect() .collect()