diff --git a/crates/but-workspace/src/upstream_integration.rs b/crates/but-workspace/src/upstream_integration.rs index c34931cca9a..cc6bc27f77f 100644 --- a/crates/but-workspace/src/upstream_integration.rs +++ b/crates/but-workspace/src/upstream_integration.rs @@ -381,13 +381,37 @@ pub fn integrate_upstream_with_hints<'ws, 'meta, M: RefMetadata>( .context("BUG: Head should exist")?; let head_step = editor.lookup_step(*head)?; - let insert_side = match head_step { + let insert_side = match &head_step { Step::Pick(_) | Step::None => InsertSide::Above, Step::Reference { .. } => InsertSide::Below, }; + // Name the branch this is merged into. In a managed workspace the head is the lane's + // own reference. A direct checkout's head is the commit instead, and there the branch + // the user has checked out is the one to name: other branches can sit on the same + // commit, and `step_references()` promises no ordering, so asking it first would name + // whichever of them it happened to reach. + let merged_into = match &head_step { + Step::Reference { refname, .. } => Some(refname.clone()), + Step::Pick(_) | Step::None => direct_checkout_head_ref_name.clone().or_else(|| { + editor.step_references(*head).ok()?.into_iter().find_map( + |selector| match editor.lookup_step(selector) { + Ok(Step::Reference { refname, .. }) => Some(refname), + _ => None, + }, + ) + }), + }; + let mut merge_commit = editor.empty_commit()?; - merge_commit.message = format!("Merge {} into merge", target_ref.ref_name).into(); + merge_commit.message = match merged_into { + Some(refname) => { + format!("Merge {} into {}", target_ref.ref_name, refname.shorten()) + } + // Nothing names this head, so the message only states what was merged. + None => format!("Merge {}", target_ref.ref_name), + } + .into(); let merge_commit = editor.new_commit(merge_commit, DateMode::CommitterKeepAuthorKeep)?; let merge_commit = editor.insert( diff --git a/crates/but-workspace/tests/workspace/upstream_integration.rs b/crates/but-workspace/tests/workspace/upstream_integration.rs index 39c8340ceab..e502350e543 100644 --- a/crates/but-workspace/tests/workspace/upstream_integration.rs +++ b/crates/but-workspace/tests/workspace/upstream_integration.rs @@ -174,8 +174,8 @@ fn diamond_partially_historically_integrated_merge() -> Result<()> { snapbox::assert_data_eq!( visualize_commit_graph_all(&repo)?, snapbox::str![[r#" -* 292b0b3 (HEAD -> gitbutler/workspace) GitButler Workspace Commit -* ed5f276 (E) Merge refs/remotes/origin/master into merge +* 61cce4f (HEAD -> gitbutler/workspace) GitButler Workspace Commit +* b379f5e (E) Merge refs/remotes/origin/master into E |\ | * 7de2393 (origin/master, master) o4 | * 7d62953 (o3) o3 @@ -351,8 +351,8 @@ fn diamond_partially_content_integrated_merge() -> Result<()> { snapbox::assert_data_eq!( visualize_commit_graph_all(&repo)?, snapbox::str![[r#" -* ebd6fa2 (HEAD -> gitbutler/workspace) GitButler Workspace Commit -* 0a395ba (E) Merge refs/remotes/origin/master into merge +* 6a96563 (HEAD -> gitbutler/workspace) GitButler Workspace Commit +* 9073990 (E) Merge refs/remotes/origin/master into E |\ | * 162b064 (origin/master, master) o4 | * dd87d69 (o3) B @@ -592,7 +592,7 @@ fn integrated_bottom_branch_no_workspace_merge() -> Result<()> { snapbox::assert_data_eq!( visualize_commit_graph_all(&repo)?, snapbox::str![[r#" -* 7ce831c (HEAD -> A) Merge refs/remotes/origin/main into merge +* 874bd64 (HEAD -> A) Merge refs/remotes/origin/main into A |\ | * 8c8a843 (origin/main) add X1 * | e792f40 add A1 @@ -673,8 +673,8 @@ fn merge_upstream_with_conflicting_target_materializes_conflicted_merge_commit() snapbox::assert_data_eq!( visualize_commit_graph_all(&repo)?, snapbox::str![[r#" -* 379fa91 (HEAD -> gitbutler/workspace) GitButler Workspace Commit -* 9b4efdf (A) [conflict] Merge refs/remotes/origin/A into merge +* 93bd4fe (HEAD -> gitbutler/workspace) GitButler Workspace Commit +* 1ef8813 (A) [conflict] Merge refs/remotes/origin/A into A |\ | * f03fc2c (origin/A, new-origin) remote change in A 1 * | 61c4a24 local change in A 1 @@ -706,7 +706,7 @@ fn merge_upstream_with_conflicting_target_materializes_conflicted_merge_commit() snapbox::assert_data_eq!( branch_tip.message_raw()?.to_string(), snapbox::str![[r#" -[conflict] Merge refs/remotes/origin/A into merge +[conflict] Merge refs/remotes/origin/A into A GitButler-Conflict: This is a GitButler-managed conflicted commit. Files are auto-resolved using the "ours" side. The commit tree contains additional directories: