From d5139f34cec36864be90a7add024f1156af31c0f Mon Sep 17 00:00:00 2001 From: Chris Idema Date: Thu, 29 Jan 2026 11:09:04 +0000 Subject: git-gui: shift tabstops to account for the first column of patch text When reviewing a change before staging, it is desirable to see text after tabstops aligned the same way as in the text editor. However, since there is always an additional character in column one in patch text ('+', '-', or space), the alignment is broken if text before the first tab character is just long enough to push the stop to the next tab position. Commit a43c5f51a4b1 (git-gui: add configurable tab size to the diff view, 2012-02-12) added infrastructure that manipulates the tabstop positions of the Tk text widget. However, it does so only when a 3-way diff is shown and only so that it takes into account the one additional markup at the beginning of lines. This only achieved that alignment does not get worse for 3-way diffs compared to regular patch text, but left misaligned text in regular patch text unmodified. Use and modify this infrastructure to shift tabstops by one position for regular patch text and two positions for 3-way diffs. Existing code already resets the tabstops to an unshifted position when contents of untracked files are displayed. Signed-off-by: Chris Idema [j6t: extend commit message] Signed-off-by: Johannes Sixt --- lib/diff.tcl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/diff.tcl b/lib/diff.tcl index 442737ba4f..8be1a613fb 100644 --- a/lib/diff.tcl +++ b/lib/diff.tcl @@ -385,6 +385,8 @@ proc read_diff {fd conflict_size cont_info} { # if {[string match {@@@ *} $line]} { set is_3way_diff 1 + apply_tab_size 2 + } elseif {[string match {@@ *} $line]} { apply_tab_size 1 } -- cgit v1.3 From 31d235c4c72666dec71a104d3bcd37cc7bd71ec5 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 10 Feb 2026 13:45:17 +0100 Subject: git-gui: fix use of GIT_CEILING_DIRECTORIES The GIT-VERSION-GEN script sets up GIT_CEILING_DIRECTORIES so that we won't accidentally parse version information from an unrelated parent repository. The ceiling is derived from the source directory by simply appendign "/.." to it, which mean that we'll only consider the current directory for repository discovery. This works alright in the case where git-gui is built as a standalone project, but it breaks when git-gui is embedded into a _related_ parent project. This is for example how git-gui is distributed via Git. Interestingly enough, the version information is still derived properly when building git-gui via Git's Makefile. In that case we eventually end up specifying the ceiling directory as "./.." as we use relative paths there, and that seems to not restrict the repository discovery. But when building via Meson we specify the source directory as an absolute path, and if so the repository discovery _is_ stopped. The consequence is that we won't be able to derive the version in that case. Fix the issue by adding a new optional parameter to GIT-VERSION-GEN that allows the caller to override the parent project directory and wire up new build options for Meson and Make that allows users to specify it. Note that by default we won't set the parent project directory. This isn't required for Meson anyway as we already use absolute paths there, but for our Makefile it means that we still end up with "./.." as ceiling directory, which is ineffective. But using e.g. pwd(1) as the default value would break downstream's version generation, unless we updated git-gui and the Makefile at the same point in time. Signed-off-by: Patrick Steinhardt --- GIT-VERSION-GEN | 16 ++++++++++++---- Makefile | 2 +- meson.build | 1 + meson_options.txt | 2 ++ 4 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 meson_options.txt diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index c2767b4136..2f729de4bb 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -5,19 +5,27 @@ DEF_VER=0.21.GITGUI LF=' ' -if test "$#" -ne 2 +if test "$#" -lt 2 then - echo >&2 "usage: $0 " + echo >&2 "usage: $0 []" exit 1 fi SOURCE_DIR="$1" OUTPUT="$2" +PARENT_PROJECT_DIR="$3" # Protect us from reading Git version information outside of the Git directory # in case it is not a repository itself, but embedded in an unrelated -# repository. -GIT_CEILING_DIRECTORIES="$SOURCE_DIR/.." +# repository. The PARENT_PROJECT_DIR variable can be used to override this, for +# example when git-gui is included as a subproject. +if test -n "$PARENT_PROJECT_DIR" +then + GIT_CEILING_DIRECTORIES="$PARENT_PROJECT_DIR/.." +else + GIT_CEILING_DIRECTORIES="$SOURCE_DIR/.." +fi + export GIT_CEILING_DIRECTORIES tree_search () diff --git a/Makefile b/Makefile index 69b0b84435..5679af62bd 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ all:: # GIT-VERSION-FILE: FORCE - @$(SHELL_PATH) ./GIT-VERSION-GEN . $@ + @$(SHELL_PATH) ./GIT-VERSION-GEN . $@ "$(PARENT_PROJECT_DIR)" uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not') diff --git a/meson.build b/meson.build index 320ba09ecf..4a60465753 100644 --- a/meson.build +++ b/meson.build @@ -34,6 +34,7 @@ version_file = custom_target( '@INPUT@', meson.current_source_dir(), '@OUTPUT@', + get_option('parent_project_dir'), ], build_always_stale: true, ) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000000..7591a34218 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,2 @@ +option('parent_project_dir', type: 'string', value: '', + description: 'The directory of the parent project. This is used so that the version can be determined even in case git-gui is included as a subtree.') -- cgit v1.3 From 8334d5e459de0386cf7b5b87cec136d62c14c3ad Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 10 Feb 2026 13:45:33 +0100 Subject: git-gui: prefer shell at "/bin/sh" with Meson Meson detects the path of the target shell via `find_program("sh")`, which essentially does a lookup via `PATH`. We know that almost all systems have "/bin/sh" available though, which makes it the superior choice as a default value. Adapt `find_program()` to prefer "/bin/sh" over any other "sh" executable. Signed-off-by: Patrick Steinhardt --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 4a60465753..a2156f01e3 100644 --- a/meson.build +++ b/meson.build @@ -4,7 +4,7 @@ project('git-gui', fs = import('fs') -shell = find_program('sh') +shell = find_program('/bin/sh', 'sh') tclsh = find_program('tclsh') wish = find_program('wish') -- cgit v1.3 From d4fa9a6aef48ec9660de2be937418ec1d802aad4 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 10 Feb 2026 14:18:04 +0100 Subject: git-gui: massage "git-gui--askyesno" with "generate-script.sh" In e749c87 (git-gui: provide question helper for retry fallback on Windows, 2025-08-28) we have introudced a new "git-gui--askyesno" helper script. While the script is conceptually similar to our existing helper script "git-gui--askpass", we don't massage it via "generate-script.sh". This means that build options like the path to the wish shell are not propagated correctly. Fix this issue. Signed-off-by: Patrick Steinhardt --- .gitignore | 1 + Makefile | 7 ++++-- git-gui--askyesno | 63 ---------------------------------------------------- git-gui--askyesno.sh | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 65 deletions(-) delete mode 100755 git-gui--askyesno create mode 100755 git-gui--askyesno.sh diff --git a/.gitignore b/.gitignore index 5130b4f018..38a41ebc58 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ GIT-GUI-BUILD-OPTIONS GIT-VERSION-FILE git-gui git-gui--askpass +git-gui--askyesno lib/tclIndex diff --git a/Makefile b/Makefile index 5679af62bd..ca01068810 100644 --- a/Makefile +++ b/Makefile @@ -177,10 +177,13 @@ GIT-GUI-BUILD-OPTIONS: FORCE git-gui--askpass: git-gui--askpass.sh GIT-GUI-BUILD-OPTIONS generate-script.sh $(QUIET_GEN)$(SHELL_PATH) generate-script.sh $@ $< ./GIT-GUI-BUILD-OPTIONS +git-gui--askyesno: git-gui--askyesno.sh GIT-GUI-BUILD-OPTIONS generate-script.sh + $(QUIET_GEN)$(SHELL_PATH) generate-script.sh $@ $< ./GIT-GUI-BUILD-OPTIONS + ifdef GITGUI_WINDOWS_WRAPPER all:: git-gui endif -all:: $(GITGUI_MAIN) git-gui--askpass lib/tclIndex $(ALL_MSGFILES) +all:: $(GITGUI_MAIN) git-gui--askpass git-gui--askyesno lib/tclIndex $(ALL_MSGFILES) install: all $(QUIET)$(INSTALL_D0)'$(DESTDIR_SQ)$(gitexecdir_SQ)' $(INSTALL_D1) @@ -221,7 +224,7 @@ dist-version: GIT-VERSION-FILE @sed 's|^GITGUI_VERSION=||' $(TARDIR)/version clean:: - $(RM_RF) $(GITGUI_MAIN) git-gui--askpass lib/tclIndex po/*.msg $(PO_TEMPLATE) + $(RM_RF) $(GITGUI_MAIN) git-gui--askpass git-gui--askyesno lib/tclIndex po/*.msg $(PO_TEMPLATE) $(RM_RF) GIT-VERSION-FILE GIT-GUI-BUILD-OPTIONS ifdef GITGUI_WINDOWS_WRAPPER $(RM_RF) git-gui diff --git a/git-gui--askyesno b/git-gui--askyesno deleted file mode 100755 index 142d1bc3de..0000000000 --- a/git-gui--askyesno +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/sh -# Tcl ignores the next line -*- tcl -*- \ -exec wish "$0" -- "$@" - -# This is an implementation of a simple yes no dialog -# which is injected into the git commandline by git gui -# in case a yesno question needs to be answered. -# -# The window title, which defaults to "Question?", can be -# overridden via the optional `--title` command-line -# option. - -set NS {} -set use_ttk [package vsatisfies [package provide Tk] 8.5] -if {$use_ttk} { - set NS ttk -} - -set title "Question?" -if {$argc < 1} { - puts stderr "Usage: $argv0 " - exit 1 -} else { - if {$argc > 2 && [lindex $argv 0] == "--title"} { - set title [lindex $argv 1] - set argv [lreplace $argv 0 1] - } - set prompt [join $argv " "] -} - -${NS}::frame .t -${NS}::label .t.m -text $prompt -justify center -width 40 -.t.m configure -wraplength 400 -pack .t.m -side top -fill x -padx 20 -pady 20 -expand 1 -pack .t -side top -fill x -ipadx 20 -ipady 20 -expand 1 - -${NS}::frame .b -${NS}::frame .b.left -width 200 -${NS}::button .b.yes -text Yes -command {exit 0} -${NS}::button .b.no -text No -command {exit 1} - -pack .b.left -side left -expand 1 -fill x -pack .b.yes -side left -expand 1 -pack .b.no -side right -expand 1 -ipadx 5 -pack .b -side bottom -fill x -ipadx 20 -ipady 15 - -bind . {exit 0} -bind . {exit 1} - -if {$::tcl_platform(platform) eq {windows}} { - set icopath [file dirname [file normalize $argv0]] - if {[file tail $icopath] eq {git-core}} { - set icopath [file dirname $icopath] - } - set icopath [file dirname $icopath] - set icopath [file join $icopath share git git-for-windows.ico] - if {[file exists $icopath]} { - wm iconbitmap . -default $icopath - } -} - -wm title . $title -tk::PlaceWindow . diff --git a/git-gui--askyesno.sh b/git-gui--askyesno.sh new file mode 100755 index 0000000000..142d1bc3de --- /dev/null +++ b/git-gui--askyesno.sh @@ -0,0 +1,63 @@ +#!/bin/sh +# Tcl ignores the next line -*- tcl -*- \ +exec wish "$0" -- "$@" + +# This is an implementation of a simple yes no dialog +# which is injected into the git commandline by git gui +# in case a yesno question needs to be answered. +# +# The window title, which defaults to "Question?", can be +# overridden via the optional `--title` command-line +# option. + +set NS {} +set use_ttk [package vsatisfies [package provide Tk] 8.5] +if {$use_ttk} { + set NS ttk +} + +set title "Question?" +if {$argc < 1} { + puts stderr "Usage: $argv0 " + exit 1 +} else { + if {$argc > 2 && [lindex $argv 0] == "--title"} { + set title [lindex $argv 1] + set argv [lreplace $argv 0 1] + } + set prompt [join $argv " "] +} + +${NS}::frame .t +${NS}::label .t.m -text $prompt -justify center -width 40 +.t.m configure -wraplength 400 +pack .t.m -side top -fill x -padx 20 -pady 20 -expand 1 +pack .t -side top -fill x -ipadx 20 -ipady 20 -expand 1 + +${NS}::frame .b +${NS}::frame .b.left -width 200 +${NS}::button .b.yes -text Yes -command {exit 0} +${NS}::button .b.no -text No -command {exit 1} + +pack .b.left -side left -expand 1 -fill x +pack .b.yes -side left -expand 1 +pack .b.no -side right -expand 1 -ipadx 5 +pack .b -side bottom -fill x -ipadx 20 -ipady 15 + +bind . {exit 0} +bind . {exit 1} + +if {$::tcl_platform(platform) eq {windows}} { + set icopath [file dirname [file normalize $argv0]] + if {[file tail $icopath] eq {git-core}} { + set icopath [file dirname $icopath] + } + set icopath [file dirname $icopath] + set icopath [file join $icopath share git git-for-windows.ico] + if {[file exists $icopath]} { + wm iconbitmap . -default $icopath + } +} + +wm title . $title +tk::PlaceWindow . -- cgit v1.3 From 65d3a128842c4eedf4c91828061d948df1ae14f2 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 10 Feb 2026 14:19:28 +0100 Subject: git-gui: wire up "git-gui--askyesno" with Meson The new "git-gui--askyesno" helper script has only been wired up for our Makefile, not for Meson. Wire it up properly to bring both build systems on par with each other again. Signed-off-by: Patrick Steinhardt --- meson.build | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/meson.build b/meson.build index a2156f01e3..a8119aa29f 100644 --- a/meson.build +++ b/meson.build @@ -54,19 +54,21 @@ if target_machine.system() == 'windows' ) endif -custom_target( - output: 'git-gui--askpass', - input: 'git-gui--askpass.sh', - command: [ - shell, - meson.current_source_dir() / 'generate-script.sh', - '@OUTPUT@', - '@INPUT@', - meson.current_build_dir() / 'GIT-GUI-BUILD-OPTIONS', - ], - install: true, - install_dir: get_option('libexecdir') / 'git-core', -) +foreach script : [ 'git-gui--askpass', 'git-gui--askyesno' ] + custom_target( + output: script, + input: script + '.sh', + command: [ + shell, + meson.current_source_dir() / 'generate-script.sh', + '@OUTPUT@', + '@INPUT@', + meson.current_build_dir() / 'GIT-GUI-BUILD-OPTIONS', + ], + install: true, + install_dir: get_option('libexecdir') / 'git-core', + ) +endforeach custom_target( input: 'git-gui.sh', -- cgit v1.3 From bb52cdac6254c006e06bf0bb820268dcf024fc22 Mon Sep 17 00:00:00 2001 From: Wolfgang Faust Date: Tue, 3 Mar 2026 17:30:52 -0800 Subject: git-gui: grey out comment lines in commit message Comment lines are stripped by wash_commit_message, but there is no indication in the UI that they are special and will be removed. Grey these lines out to indicate that they will be removed. Signed-off-by: Wolfgang Faust Signed-off-by: Johannes Sixt --- git-gui.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/git-gui.sh b/git-gui.sh index d3d3aa14a9..23fe76e498 100755 --- a/git-gui.sh +++ b/git-gui.sh @@ -3900,6 +3900,24 @@ if {[winfo exists $ui_comm]} { backup_commit_buffer + # Grey out comment lines (which are stripped from the final commit message by + # wash_commit_message). + $ui_comm tag configure commit_comment -foreground gray + proc dim_commit_comment_lines {} { + global ui_comm comment_string + $ui_comm tag remove commit_comment 1.0 end + set text [$ui_comm get 1.0 end] + # See also cmt_rx in wash_commit_message + set cmt_rx [strcat {^} [regsub -all {\W} $comment_string {\\&}]] + set ranges [regexp -all -indices -inline -line -- $cmt_rx $text] + foreach pair $ranges { + set idx "1.0 + [lindex $pair 0] chars" + $ui_comm tag add commit_comment $idx "$idx lineend + 1 char" + } + } + dim_commit_comment_lines + bind $ui_comm <> { after idle dim_commit_comment_lines } + # -- If the user has aspell available we can drive it # in pipe mode to spellcheck the commit message. # -- cgit v1.3