Add warning when git commit title is longer than 72 chars (#54653)

Adds a warning to the git commit panel when the message title (i.e.
first line) is longer than 72 (configurable) chars.

<img width="406" height="227" alt="image"
src="https://github.com/user-attachments/assets/08b900d0-3865-4530-8495-e301d5b8c452"
/>

<img width="754" height="482" alt="image"
src="https://github.com/user-attachments/assets/574ebaa5-d6b7-48cd-9ca4-6ee01172ccb4"
/>


Release Notes:

- Added: Display a warning when git commit message title exceeds a
configurable limit

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
This commit is contained in:
Cameron Mcloughlin 2026-04-23 18:02:36 +01:00 committed by GitHub
parent 6f84d9be2c
commit cf8eb424b0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 123 additions and 14 deletions

View file

@ -975,6 +975,11 @@
//
// Default: true
"diff_stats": true,
// Maximum length of the commit message title before a warning is shown.
// Set to 0 to disable.
//
// Default: 72
"commit_title_max_length": 72,
},
"message_editor": {
// Whether to automatically replace emoji shortcodes with emoji characters.

View file

@ -1,5 +1,6 @@
use crate::branch_picker::{self, BranchList};
use crate::git_panel::{GitPanel, commit_message_editor, panel_editor_style};
use crate::git_panel_settings::GitPanelSettings;
use git::repository::CommitOptions;
use git::{Amend, Commit, GenerateCommitMessage, Signoff};
use panel::panel_button;
@ -539,6 +540,18 @@ impl Render for CommitModal {
let border_radius = properties.modal_border_radius;
let editor_focus_handle = self.commit_editor.focus_handle(cx);
let max_title_length = GitPanelSettings::get_global(cx).commit_title_max_length;
let title_exceeds_limit = if max_title_length > 0 {
self.commit_editor
.read(cx)
.text(cx)
.lines()
.next()
.is_some_and(|title| title.len() > max_title_length)
} else {
false
};
v_flex()
.id("commit-modal")
.key_context("GitCommit")
@ -567,6 +580,9 @@ impl Render for CommitModal {
this.toggle_branch_selector(window, cx);
}),
)
.w(width)
.h_112()
.p(container_padding)
.elevation_3(cx)
.overflow_hidden()
.flex_none()
@ -575,30 +591,50 @@ impl Render for CommitModal {
.rounded(px(border_radius))
.border_1()
.border_color(cx.theme().colors().border)
.w(width)
.p(container_padding)
.child(
v_flex()
.id("editor-container")
.justify_between()
.cursor_text()
.p_2()
.size_full()
.gap_2()
.justify_between()
.rounded(properties.editor_border_radius())
.overflow_hidden()
.cursor_text()
.bg(cx.theme().colors().editor_background)
.border_1()
.border_color(cx.theme().colors().border_variant)
.border_color(if title_exceeds_limit {
cx.theme().status().warning_border
} else {
cx.theme().colors().border_variant
})
.on_click(cx.listener(move |_, _: &ClickEvent, window, cx| {
window.focus(&editor_focus_handle, cx);
}))
.child(
div()
.flex_1()
.size_full()
.child(self.render_commit_editor(window, cx)),
)
.child(self.render_commit_editor(window, cx))
.when(title_exceeds_limit, |this| {
this.child(
h_flex()
.absolute()
.bottom_12()
.w_full()
.py_1()
.px_2()
.gap_1()
.justify_center()
.child(
Icon::new(IconName::Warning)
.size(IconSize::XSmall)
.color(Color::Warning),
)
.child(
Label::new(format!(
"Commit message title exceeds {max_title_length}-character limit."
))
.size(LabelSize::Small),
),
)
})
.child(self.render_footer(window, cx)),
)
}

View file

@ -4343,6 +4343,18 @@ impl GitPanel {
editor.max_point(cx).row().0 >= MAX_PANEL_EDITOR_LINES as u32
});
let max_title_length = GitPanelSettings::get_global(cx).commit_title_max_length;
let title_exceeds_limit = if max_title_length > 0 {
self.commit_editor
.read(cx)
.text(cx)
.lines()
.next()
.is_some_and(|title| title.len() > max_title_length)
} else {
false
};
let footer = v_flex()
.child(PanelRepoFooter::new(
display_name,
@ -4350,15 +4362,41 @@ impl GitPanel {
head_commit,
Some(git_panel),
))
.when(title_exceeds_limit, |this| {
this.child(
h_flex()
.px_2()
.py_1()
.gap_1()
.border_t_1()
.border_color(cx.theme().status().warning_border)
.bg(cx.theme().status().warning_background.opacity(0.5))
.child(
Icon::new(IconName::Warning)
.size(IconSize::XSmall)
.color(Color::Warning),
)
.child(
Label::new(format!(
"Commit message title exceeds {max_title_length}-character limit."
))
.size(LabelSize::Small),
),
)
})
.child(
panel_editor_container(window, cx)
.id("commit-editor-container")
.cursor_text()
.relative()
.w_full()
.h(max_height + footer_size)
.border_t_1()
.border_color(cx.theme().colors().border)
.cursor_text()
.border_color(if title_exceeds_limit {
cx.theme().status().warning_border
} else {
cx.theme().colors().border
})
.on_click(cx.listener(move |this, _: &ClickEvent, window, cx| {
window.focus(&this.commit_editor.focus_handle(cx), cx);
}))

View file

@ -30,6 +30,7 @@ pub struct GitPanelSettings {
pub diff_stats: bool,
pub show_count_badge: bool,
pub starts_open: bool,
pub commit_title_max_length: usize,
}
#[derive(Default)]
@ -76,6 +77,7 @@ impl Settings for GitPanelSettings {
diff_stats: git_panel.diff_stats.unwrap(),
show_count_badge: git_panel.show_count_badge.unwrap(),
starts_open: git_panel.starts_open.unwrap(),
commit_title_max_length: git_panel.commit_title_max_length.unwrap(),
}
}
}

View file

@ -647,6 +647,12 @@ pub struct GitPanelSettingsContent {
///
/// Default: false
pub starts_open: Option<bool>,
/// Maximum length of the commit message title before a warning is shown.
/// Set to 0 to disable.
///
/// Default: 72
pub commit_title_max_length: Option<usize>,
}
#[derive(

View file

@ -5424,7 +5424,7 @@ fn panels_page() -> SettingsPage {
]
}
fn git_panel_section() -> [SettingsPageItem; 14] {
fn git_panel_section() -> [SettingsPageItem; 15] {
[
SettingsPageItem::SectionHeader("Git Panel"),
SettingsPageItem::SettingItem(SettingItem {
@ -5642,6 +5642,28 @@ fn panels_page() -> SettingsPage {
metadata: None,
files: USER,
}),
SettingsPageItem::SettingItem(SettingItem {
title: "Commit Title Max Length",
description: "Maximum length of the commit message title before a warning is shown. Set to 0 to disable.",
field: Box::new(SettingField {
json_path: Some("git_panel.commit_title_max_length"),
pick: |settings_content| {
settings_content
.git_panel
.as_ref()?
.commit_title_max_length
.as_ref()
},
write: |settings_content, value, _app: &App| {
settings_content
.git_panel
.get_or_insert_default()
.commit_title_max_length = value;
},
}),
metadata: None,
files: USER,
}),
SettingsPageItem::SettingItem(SettingItem {
title: "Scroll Bar",
description: "How and when the scrollbar should be displayed.",