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
@ f
b2
b1
b4
b3
b4
b3
@ f
b2
b1
a

View file

@ -643,33 +643,39 @@ pub fn move_commits(
new_children
.iter()
.map(|child_commit| {
let mut new_child_parent_ids: IndexSet<_> = child_commit
.parent_ids()
.iter()
let mut new_child_parent_ids = IndexSet::new();
for old_child_parent_id in child_commit.parent_ids() {
// Replace target commits with their parents outside the target set.
.flat_map(|id| {
if let Some(parents) = target_commits_external_parents.get(id) {
parents.iter().cloned().collect_vec()
} else {
[id.clone()].to_vec()
}
})
// 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();
let old_child_parent_ids = if let Some(parents) =
target_commits_external_parents.get(old_child_parent_id)
{
parents.iter().collect_vec()
} else {
vec![old_child_parent_id]
};
// 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());
(
child_commit.id().clone(),
new_child_parent_ids.iter().cloned().collect_vec(),
new_child_parent_ids.into_iter().collect_vec(),
)
})
.collect()