From fb59b387d3f235ba22d4446a79b9366740647b6e Mon Sep 17 00:00:00 2001 From: Amey Pawar Date: Wed, 5 Aug 2026 17:57:13 +0530 Subject: [PATCH] Name the branch a merge is made into Updating the workspace with the merge strategy wrote "Merge into merge", with the word merge taken literally rather than the branch. The name was already at hand: a managed workspace's head is the lane's own reference, and a direct checkout has the checked-out branch. Only a head that nothing names now falls back to stating what was merged. Reported as landing in 0.14.3 and returning with the current integration path. --- .../but-workspace/src/upstream_integration.rs | 28 +++++++++++++++++-- .../tests/workspace/upstream_integration.rs | 16 +++++------ 2 files changed, 34 insertions(+), 10 deletions(-) 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: