Allow viewing past commits in Zed (#27636)

This PR adds functionality for loading the diff for an arbitrary git
commit, and displaying it in a tab. To retrieve the diff for the commit,
I'm using a single `git cat-file --batch` invocation to efficiently load
both the old and new versions of each file that was changed in the
commit.

Todo

* Features
* [x] Open the commit view when clicking the most recent commit message
in the commit panel
  * [x] Open the commit view when clicking a SHA in a git blame column
  * [x] Open the commit view when clicking a SHA in a commit tooltip
  * [x] Make it work over RPC
  * [x] Allow buffer search in commit view
* [x] Command palette action to open the commit for the current blame
line
* Styling
* [x] Add a header that shows the author, timestamp, and the full commit
message
  * [x] Remove stage/unstage buttons in commit view
  * [x] Truncate the commit message in the tab
* Bugs
  * [x] Dedup commit tabs within a pane
  * [x] Add a tooltip to the tab

Release Notes:

- Added the ability to show past commits in Zed. You can view the most
recent commit by clicking its message in the commit panel. And when
viewing a git blame, you can show any commit by clicking its sha.
This commit is contained in:
Max Brunsfeld 2025-03-31 16:26:47 -07:00 committed by GitHub
parent 33912011b7
commit 8546dc101d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 1742 additions and 603 deletions

View file

@ -483,7 +483,7 @@ impl TrackedBuffer {
buffer_without_edits
.update(cx, |buffer, cx| buffer.undo_operations(edits_to_undo, cx));
let primary_diff_update = self.diff.update(cx, |diff, cx| {
diff.set_base_text(
diff.set_base_text_buffer(
buffer_without_edits,
self.buffer.read(cx).text_snapshot(),
cx,
@ -500,7 +500,7 @@ impl TrackedBuffer {
buffer.undo_operations(unreviewed_edits_to_undo, cx)
});
let secondary_diff_update = self.secondary_diff.update(cx, |diff, cx| {
diff.set_base_text(
diff.set_base_text_buffer(
buffer_without_unreviewed_edits.clone(),
self.buffer.read(cx).text_snapshot(),
cx,
@ -559,13 +559,7 @@ impl TrackedBuffer {
if let Ok(primary_diff_snapshot) = primary_diff_snapshot {
primary_diff
.update(cx, |diff, cx| {
diff.set_snapshot(
&buffer_snapshot,
primary_diff_snapshot,
false,
None,
cx,
)
diff.set_snapshot(primary_diff_snapshot, &buffer_snapshot, None, cx)
})
.ok();
}
@ -574,9 +568,8 @@ impl TrackedBuffer {
secondary_diff
.update(cx, |diff, cx| {
diff.set_snapshot(
&buffer_snapshot,
secondary_diff_snapshot,
false,
&buffer_snapshot,
None,
cx,
)