git: Add global git integration enable/disable setting (#43326)

Closes #13304

Release Notes:

- Add global `git status` and `git diff` on/off in one place instead of
control everywhere

We can first review to ensure this change meets both `Zed` and user
requirements, as well as code rules. Currently, we only support
user-level settings. We can wait for this PR:
https://github.com/zed-industries/zed/pull/43173 to be merged, then
modify it to support both user and project levels.
This commit is contained in:
Leo
2025-12-19 00:45:26 +08:00
committed by GitHub
parent 098adf3bdd
commit e10b9b70ef
8 changed files with 174 additions and 4 deletions

View File

@@ -1321,6 +1321,14 @@
"hidden_files": ["**/.*"],
// Git gutter behavior configuration.
"git": {
// Global switch to enable or disable all git integration features.
// If set to true, disables all git integration features.
// If set to false, individual git integration features below will be independently enabled or disabled.
"disable_git": false,
// Whether to enable git status tracking.
"enable_status": true,
// Whether to enable git diff display.
"enable_diff": true,
// Control whether the git gutter is shown. May take 2 values:
// 1. Show the gutter
// "git_gutter": "tracked_files"

View File

@@ -215,7 +215,8 @@ impl Settings for EditorSettings {
},
scrollbar: Scrollbar {
show: scrollbar.show.map(Into::into).unwrap(),
git_diff: scrollbar.git_diff.unwrap(),
git_diff: scrollbar.git_diff.unwrap()
&& content.git.unwrap().enabled.unwrap().is_git_diff_enabled(),
selected_text: scrollbar.selected_text.unwrap(),
selected_symbol: scrollbar.selected_symbol.unwrap(),
search_results: scrollbar.search_results.unwrap(),

View File

@@ -50,7 +50,13 @@ impl Settings for OutlinePanelSettings {
dock: panel.dock.unwrap(),
file_icons: panel.file_icons.unwrap(),
folder_icons: panel.folder_icons.unwrap(),
git_status: panel.git_status.unwrap(),
git_status: panel.git_status.unwrap()
&& content
.git
.unwrap()
.enabled
.unwrap()
.is_git_status_enabled(),
indent_size: panel.indent_size.unwrap(),
indent_guides: IndentGuidesSettings {
show: panel.indent_guides.unwrap().show.unwrap(),

View File

@@ -332,6 +332,10 @@ impl GoToDiagnosticSeverityFilter {
#[derive(Copy, Clone, Debug)]
pub struct GitSettings {
/// Whether or not git integration is enabled.
///
/// Default: true
pub enabled: GitEnabledSettings,
/// Whether or not to show the git gutter.
///
/// Default: tracked_files
@@ -361,6 +365,18 @@ pub struct GitSettings {
pub path_style: GitPathStyle,
}
#[derive(Clone, Copy, Debug)]
pub struct GitEnabledSettings {
/// Whether git integration is enabled for showing git status.
///
/// Default: true
pub status: bool,
/// Whether git integration is enabled for showing diffs.
///
/// Default: true
pub diff: bool,
}
#[derive(Clone, Copy, Debug, PartialEq, Default)]
pub enum GitPathStyle {
#[default]
@@ -502,7 +518,14 @@ impl Settings for ProjectSettings {
let inline_diagnostics = diagnostics.inline.as_ref().unwrap();
let git = content.git.as_ref().unwrap();
let git_enabled = {
GitEnabledSettings {
status: git.enabled.as_ref().unwrap().is_git_status_enabled(),
diff: git.enabled.as_ref().unwrap().is_git_diff_enabled(),
}
};
let git_settings = GitSettings {
enabled: git_enabled,
git_gutter: git.git_gutter.unwrap(),
gutter_debounce: git.gutter_debounce.unwrap_or_default(),
inline_blame: {

View File

@@ -92,7 +92,13 @@ impl Settings for ProjectPanelSettings {
entry_spacing: project_panel.entry_spacing.unwrap(),
file_icons: project_panel.file_icons.unwrap(),
folder_icons: project_panel.folder_icons.unwrap(),
git_status: project_panel.git_status.unwrap(),
git_status: project_panel.git_status.unwrap()
&& content
.git
.unwrap()
.enabled
.unwrap()
.is_git_status_enabled(),
indent_size: project_panel.indent_size.unwrap(),
indent_guides: IndentGuidesSettings {
show: project_panel.indent_guides.unwrap().show.unwrap(),

View File

@@ -288,6 +288,11 @@ impl std::fmt::Debug for ContextServerCommand {
#[with_fallible_options]
#[derive(Copy, Clone, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
pub struct GitSettings {
/// Whether or not to enable git integration.
///
/// Default: true
#[serde(flatten)]
pub enabled: Option<GitEnabledSettings>,
/// Whether or not to show the git gutter.
///
/// Default: tracked_files
@@ -317,6 +322,25 @@ pub struct GitSettings {
pub path_style: Option<GitPathStyle>,
}
#[with_fallible_options]
#[derive(Clone, Copy, Debug, PartialEq, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
#[serde(rename_all = "snake_case")]
pub struct GitEnabledSettings {
pub disable_git: Option<bool>,
pub enable_status: Option<bool>,
pub enable_diff: Option<bool>,
}
impl GitEnabledSettings {
pub fn is_git_status_enabled(&self) -> bool {
!self.disable_git.unwrap_or(false) && self.enable_status.unwrap_or(true)
}
pub fn is_git_diff_enabled(&self) -> bool {
!self.disable_git.unwrap_or(false) && self.enable_diff.unwrap_or(true)
}
}
#[derive(
Clone,
Copy,

View File

@@ -5519,6 +5519,102 @@ pub(crate) fn settings_data(cx: &App) -> Vec<SettingsPage> {
SettingsPage {
title: "Version Control",
items: vec![
SettingsPageItem::SectionHeader("Git Integration"),
SettingsPageItem::DynamicItem(DynamicItem {
discriminant: SettingItem {
files: USER,
title: "Disable Git Integration",
description: "Disable all Git integration features in Zed.",
field: Box::new(SettingField::<bool> {
json_path: Some("git.disable_git"),
pick: |settings_content| {
settings_content
.git
.as_ref()?
.enabled
.as_ref()?
.disable_git
.as_ref()
},
write: |settings_content, value| {
settings_content
.git
.get_or_insert_default()
.enabled
.get_or_insert_default()
.disable_git = value;
},
}),
metadata: None,
},
pick_discriminant: |settings_content| {
let disabled = settings_content
.git
.as_ref()?
.enabled
.as_ref()?
.disable_git
.unwrap_or(false);
Some(if disabled { 0 } else { 1 })
},
fields: vec![
vec![],
vec![
SettingItem {
files: USER,
title: "Enable Git Status",
description: "Show Git status information in the editor.",
field: Box::new(SettingField::<bool> {
json_path: Some("git.enable_status"),
pick: |settings_content| {
settings_content
.git
.as_ref()?
.enabled
.as_ref()?
.enable_status
.as_ref()
},
write: |settings_content, value| {
settings_content
.git
.get_or_insert_default()
.enabled
.get_or_insert_default()
.enable_status = value;
},
}),
metadata: None,
},
SettingItem {
files: USER,
title: "Enable Git Diff",
description: "Show Git diff information in the editor.",
field: Box::new(SettingField::<bool> {
json_path: Some("git.enable_diff"),
pick: |settings_content| {
settings_content
.git
.as_ref()?
.enabled
.as_ref()?
.enable_diff
.as_ref()
},
write: |settings_content, value| {
settings_content
.git
.get_or_insert_default()
.enabled
.get_or_insert_default()
.enable_diff = value;
},
}),
metadata: None,
},
],
],
}),
SettingsPageItem::SectionHeader("Git Gutter"),
SettingsPageItem::SettingItem(SettingItem {
title: "Visibility",

View File

@@ -76,7 +76,13 @@ impl Settings for ItemSettings {
fn from_settings(content: &settings::SettingsContent) -> Self {
let tabs = content.tabs.as_ref().unwrap();
Self {
git_status: tabs.git_status.unwrap(),
git_status: tabs.git_status.unwrap()
&& content
.git
.unwrap()
.enabled
.unwrap()
.is_git_status_enabled(),
close_position: tabs.close_position.unwrap(),
activate_on_close: tabs.activate_on_close.unwrap(),
file_icons: tabs.file_icons.unwrap(),