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.
This commit is contained in:
Umesh Yadav
2025-09-09 10:37:53 -06:00
committed by GitHub
parent 7f607a9b7d
commit 8527dcfc65
+88
View File
@@ -351,6 +351,7 @@ pub struct GitPanel {
pending: Vec<PendingOperation>,
pending_commit: Option<Task<()>>,
amend_pending: bool,
original_commit_message: Option<String>,
signoff_enabled: bool,
pending_serialization: Task<()>,
pub(crate) project: Entity<Project>,
@@ -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<Self>) {
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, "");
});
}
}