git-gui: add gui and pick as explicit subcommands

git-gui accepts subcommands blame | browser | citool, and assumes the subcommand is 'gui' if none is actually given, But, git-gui also has a repository picker (choose_repository::pick) that can create a new repository + worktree, or choose an existing one, switch to that, and the run the gui. The user has no direct control over invoking the picker, instead the picker is triggered by failure in the repository / worktree discovery process: this includes being started in a directory not controlled by git, which is probably the intended use case. The picker can appear when the user has no intention of creating a new worktree, and the user cannot use the picker to create a new worktree inside another. So, add two explicit subcommands: gui - Run the gui if repository/worktree discovery succeeds, or die with an error message, but never run the picker. pick - First run the picker, regardless, then start the gui in the chosen worktree. Nothing in this changes the prior behavior, the alternates above must be explicitly selected to see any change. Signed-off-by: Mark Levedahl <mlevedahl@gmail.com> Signed-off-by: Johannes Sixt <j6t@kdbg.org>

Mark Levedahl committed May 31, 2026 at 19:02 UTC e61190e2faf7ee677424c622881899a10e41612c
1 file changed +21 -4
git-gui.sh
+21 -4
@@ -1024,6 +1024,8 @@ proc load_config {include_global} {
1024 ##
1025 ## feature option selection
1026
1027 +enable_option picker
1028 +enable_option gitdir_discovery
1029 if {[regexp {^git-(.+)$} [file tail $argv0] _junk subcommand]} {
1030 unset _junk
1031 } else {
@@ -1035,6 +1037,9 @@ if {$subcommand eq {gui.sh}} {
1037 if {$subcommand eq {gui} && [llength $argv] > 0} {
1038 set subcommand [lindex $argv 0]
1039 set argv [lrange $argv 1 end]
1040 + if {$subcommand eq {gui}} {
1041 + disable_option picker
1042 + }
1043 }
1044
1045 enable_option multicommit
@@ -1050,6 +1055,7 @@ blame {
1055 disable_option multicommit
1056 disable_option branch
1057 disable_option transport
1058 + disable_option picker
1059 }
1060 citool {
1061 enable_option singlecommit
@@ -1058,6 +1064,7 @@ citool {
1064 disable_option multicommit
1065 disable_option branch
1066 disable_option transport
1067 + disable_option picker
1068
1069 while {[llength $argv] > 0} {
1070 set a [lindex $argv 0]
@@ -1080,6 +1087,9 @@ citool {
1087 set argv [lrange $argv 1 end]
1088 }
1089 }
1090 +pick {
1091 + disable_option gitdir_discovery
1092 +}
1093 }
1094
1095 ######################################################################
@@ -1168,7 +1178,7 @@ proc unset_gitdir_vars {} {
1178
1179 # find repository
1180 set _gitdir {}
1171 -if {$_gitdir eq {}} {
1181 +if {[is_enabled gitdir_discovery]} {
1182 if {[catch {
1183 set _gitdir [git rev-parse --absolute-git-dir]
1184 } err]} {
@@ -1180,7 +1190,7 @@ if {$_gitdir eq {}} {
1190 }
1191
1192 set picked 0
1183 -if {$_gitdir eq {}} {
1193 +if {$_gitdir eq {} && [is_enabled picker]} {
1194 unset_gitdir_vars
1195 load_config 1
1196 apply_config
@@ -1195,6 +1205,12 @@ if {$_gitdir eq {}} {
1205 set picked 1
1206 }
1207
1208 +if {$_gitdir eq {}} {
1209 + catch {wm withdraw .}
1210 + error_popup [strcat [mc "Git directory not found:"] "\n\n$err"]
1211 + exit 1
1212 +}
1213 +
1214 # find worktree, continue without if not required
1215 if {[catch {
1216 set _gitworktree [git rev-parse --show-toplevel]
@@ -3103,14 +3119,15 @@ blame {
3119 return
3120 }
3121 citool -
3106 -gui {
3122 +gui -
3123 +pick {
3124 if {[llength $argv] != 0} {
3125 usage
3126 }
3127 # fall through to setup UI for commits
3128 }
3129 default {
3113 - set err "[mc usage:] $argv0 \[{blame|browser|citool}\]"
3130 + set err "[mc usage:] $argv0 \[{blame|browser|citool|gui|pick}\]"
3131 if {[tk windowingsystem] eq "win32"} {
3132 wm withdraw .
3133 tk_messageBox -icon error -message $err \