From 8527dcfc652776d3c5d7ade5151c0fdd96801679 Mon Sep 17 00:00:00 2001 From: Umesh Yadav <23421535+imumesh18@users.noreply.github.com> Date: Tue, 9 Sep 2025 22:07:53 +0530 Subject: [PATCH] git_ui: Better handle commit message amend (#35268) Follow up to this: #35114 * Previously we were still showing the commit message even after cancelling amend which was the old commit message. * This PR fixes that by restoring the commit message to the old state before the amend begin so that in case user typed a commit message it's shown if not then it's not. Before: https://github.com/user-attachments/assets/e0edcfff-863d-4367-a7c4-8a2998e702ca After: https://github.com/user-attachments/assets/9daf9be0-8a3d-4914-91a4-567693711b6b Release Notes: - Resolved an issue where cancelling an amend commit would incorrectly leave the old commit message in the input field. The commit message box now properly reverts to its pre-amend state. --- crates/git_ui/src/git_panel.rs | 88 ++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs index 02a60d8fe33a9da24ddfd50b873b363b3bbcd9c9..87a573a7a8b3dd4d3619bd284c1627ab0cfcbbff 100644 --- a/crates/git_ui/src/git_panel.rs +++ b/crates/git_ui/src/git_panel.rs @@ -351,6 +351,7 @@ pub struct GitPanel { pending: Vec, pending_commit: Option>, amend_pending: bool, + original_commit_message: Option, signoff_enabled: bool, pending_serialization: Task<()>, pub(crate) project: Entity, @@ -532,6 +533,7 @@ impl GitPanel { pending: Vec::new(), pending_commit: None, amend_pending: false, + original_commit_message: None, signoff_enabled: false, pending_serialization: Task::ready(()), single_staged_entry: None, @@ -1713,6 +1715,7 @@ impl GitPanel { Ok(()) => { this.commit_editor .update(cx, |editor, cx| editor.clear(window, cx)); + this.original_commit_message = None; } Err(e) => this.show_error_toast("commit", e, cx), } @@ -4345,6 +4348,22 @@ impl GitPanel { } pub fn set_amend_pending(&mut self, value: bool, cx: &mut Context) { + if value && !self.amend_pending { + let current_message = self.commit_message_buffer(cx).read(cx).text(); + self.original_commit_message = if current_message.trim().is_empty() { + None + } else { + Some(current_message) + }; + } else if !value && self.amend_pending { + let message = self.original_commit_message.take().unwrap_or_default(); + self.commit_message_buffer(cx).update(cx, |buffer, cx| { + let start = buffer.anchor_before(0); + let end = buffer.anchor_after(buffer.len()); + buffer.edit([(start..end, message)], None, cx); + }); + } + self.amend_pending = value; self.serialize(cx); cx.notify(); @@ -5490,4 +5509,73 @@ mod tests { ], ); } + + #[gpui::test] + async fn test_amend_commit_message_handling(cx: &mut TestAppContext) { + init_test(cx); + let fs = FakeFs::new(cx.background_executor.clone()); + fs.insert_tree( + "/root", + json!({ + "project": { + ".git": {}, + "src": { + "main.rs": "fn main() {}" + } + } + }), + ) + .await; + + fs.set_status_for_repo( + Path::new(path!("/root/project/.git")), + &[(Path::new("src/main.rs"), StatusCode::Modified.worktree())], + ); + + let project = Project::test(fs.clone(), [Path::new(path!("/root/project"))], cx).await; + let workspace = + cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx)); + let cx = &mut VisualTestContext::from_window(*workspace, cx); + + let panel = workspace.update(cx, GitPanel::new).unwrap(); + + // Test: User has commit message, enables amend (saves message), then disables (restores message) + panel.update(cx, |panel, cx| { + panel.commit_message_buffer(cx).update(cx, |buffer, cx| { + let start = buffer.anchor_before(0); + let end = buffer.anchor_after(buffer.len()); + buffer.edit([(start..end, "Initial commit message")], None, cx); + }); + + panel.set_amend_pending(true, cx); + assert!(panel.original_commit_message.is_some()); + + panel.set_amend_pending(false, cx); + let current_message = panel.commit_message_buffer(cx).read(cx).text(); + assert_eq!(current_message, "Initial commit message"); + assert!(panel.original_commit_message.is_none()); + }); + + // Test: User has empty commit message, enables amend, then disables (clears message) + panel.update(cx, |panel, cx| { + panel.commit_message_buffer(cx).update(cx, |buffer, cx| { + let start = buffer.anchor_before(0); + let end = buffer.anchor_after(buffer.len()); + buffer.edit([(start..end, "")], None, cx); + }); + + panel.set_amend_pending(true, cx); + assert!(panel.original_commit_message.is_none()); + + panel.commit_message_buffer(cx).update(cx, |buffer, cx| { + let start = buffer.anchor_before(0); + let end = buffer.anchor_after(buffer.len()); + buffer.edit([(start..end, "Previous commit message")], None, cx); + }); + + panel.set_amend_pending(false, cx); + let current_message = panel.commit_message_buffer(cx).read(cx).text(); + assert_eq!(current_message, ""); + }); + } }