From 671c3e723eeb42a6303d61cacd7070c3303533f2 Mon Sep 17 00:00:00 2001
From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
Date: Mon, 16 Feb 2026 18:51:35 -0300
Subject: [PATCH] git_ui: Add button for the `branch diff` action (#49298)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This PR adds a button in the Git Panel to open the `git: branch diff`
view. The button only shows if the staging area is clean/no changes and
if the branch is not main/master. I've been using this action so much
these days and we should expose it on the UI so it's more discoverable.
Release Notes:
- N/A
---
crates/git_ui/src/git_panel.rs | 99 ++++++++++++++++++++++------------
1 file changed, 66 insertions(+), 33 deletions(-)
diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs
index d50f9088211425518f5f97366aa3a1419821581f..9e4b125c3766af11894ec952808ffa48078d2362 100644
--- a/crates/git_ui/src/git_panel.rs
+++ b/crates/git_ui/src/git_panel.rs
@@ -2,7 +2,7 @@ use crate::askpass_modal::AskPassModal;
use crate::commit_modal::CommitModal;
use crate::commit_tooltip::CommitTooltip;
use crate::commit_view::CommitView;
-use crate::project_diff::{self, Diff, ProjectDiff};
+use crate::project_diff::{self, BranchDiff, Diff, ProjectDiff};
use crate::remote_output::{self, RemoteAction, SuccessMessage};
use crate::{branch_picker, picker_prompt, render_remote_button};
use crate::{
@@ -4566,38 +4566,71 @@ impl GitPanel {
}
fn render_empty_state(&self, cx: &mut Context) -> impl IntoElement {
- h_flex().h_full().flex_grow().justify_center().child(
- v_flex()
- .gap_2()
- .child(h_flex().w_full().justify_around().child(
- if self.active_repository.is_some() {
- "No changes to commit"
- } else {
- "No Git repositories"
- },
- ))
- .children({
- let worktree_count = self.project.read(cx).visible_worktrees(cx).count();
- (worktree_count > 0 && self.active_repository.is_none()).then(|| {
- h_flex().w_full().justify_around().child(
- panel_filled_button("Initialize Repository")
- .tooltip(Tooltip::for_action_title_in(
- "git init",
- &git::Init,
- &self.focus_handle,
- ))
- .on_click(move |_, _, cx| {
- cx.defer(move |cx| {
- cx.dispatch_action(&git::Init);
- })
- }),
- )
- })
- })
- .text_ui_sm(cx)
- .mx_auto()
- .text_color(Color::Placeholder.color(cx)),
- )
+ let has_repo = self.active_repository.is_some();
+ let has_no_repo = self.active_repository.is_none();
+ let worktree_count = self.project.read(cx).visible_worktrees(cx).count();
+
+ let should_show_branch_diff =
+ has_repo && self.changes_count == 0 && !self.is_on_main_branch(cx);
+
+ let label = if has_repo {
+ "No changes to commit"
+ } else {
+ "No Git repositories"
+ };
+
+ v_flex()
+ .gap_1p5()
+ .flex_1()
+ .items_center()
+ .justify_center()
+ .child(Label::new(label).size(LabelSize::Small).color(Color::Muted))
+ .when(has_no_repo && worktree_count > 0, |this| {
+ this.child(
+ panel_filled_button("Initialize Repository")
+ .tooltip(Tooltip::for_action_title_in(
+ "git init",
+ &git::Init,
+ &self.focus_handle,
+ ))
+ .on_click(move |_, _, cx| {
+ cx.defer(move |cx| {
+ cx.dispatch_action(&git::Init);
+ })
+ }),
+ )
+ })
+ .when(should_show_branch_diff, |this| {
+ this.child(
+ panel_filled_button("View Branch Diff")
+ .tooltip(move |_, cx| {
+ Tooltip::with_meta(
+ "Branch Diff",
+ Some(&BranchDiff),
+ "Show diff between working directory and default branch",
+ cx,
+ )
+ })
+ .on_click(move |_, _, cx| {
+ cx.defer(move |cx| {
+ cx.dispatch_action(&BranchDiff);
+ })
+ }),
+ )
+ })
+ }
+
+ fn is_on_main_branch(&self, cx: &Context) -> bool {
+ let Some(repo) = self.active_repository.as_ref() else {
+ return false;
+ };
+
+ let Some(branch) = repo.read(cx).branch.as_ref() else {
+ return false;
+ };
+
+ let branch_name = branch.name();
+ matches!(branch_name, "main" | "master")
}
fn render_buffer_header_controls(