]> git.ipfire.org Git - thirdparty/git.git/commitdiff
git-gui: guard set/unset of GIT_DIR and GIT_WORK_TREE
authorMark Levedahl <mlevedahl@gmail.com>
Sun, 31 May 2026 23:02:16 +0000 (19:02 -0400)
committerJohannes Sixt <j6t@kdbg.org>
Tue, 2 Jun 2026 17:13:13 +0000 (19:13 +0200)
git-gui unconditionally exports _gitdir as GIT_DIR, and _gitworktree as
GIT_WORK_TREE, to the environment, and unconditionally
unsets these environment variables before invoking gitk or git-gui when
a submodule is involved. This export happens even if _gitworktree is
empty, which happens when running from a bare repository. However,
exporting GIT_WORK_TREE as empty is never valid, and causes errors in
git.

GIT_DIR must be exported if the repository is not discoverable from the
worktree (or current directory if there is no worktree). The user might
have configured this.

If there is a worktree, git-gui makes this the current directory.
However, if the repository sets core.worktree, this value can only be
overridden by GIT_WORK_TREE so the latter must be exported.

As we cannot eliminate conditions where either variable is needed, let's
implement a pair of functions to set / unset these variables without
error, and without ever exporting an empty GIT_WORK_TREE.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
git-gui.sh

index 52897fbd0998184a1578ccf3c854c504fb7b6984..e7a87fc9962edaf7867d34587af4d1f1a5d21e77 100755 (executable)
@@ -1125,6 +1125,20 @@ unset argv0dir
 ##
 ## repository setup
 
+proc set_gitdir_vars {} {
+       global _gitdir _gitworktree env
+       set env(GIT_DIR) $_gitdir
+       if {$_gitworktree ne {}} {
+               set env(GIT_WORK_TREE) $_gitworktree
+       }
+}
+
+proc unset_gitdir_vars {} {
+       global env
+       catch {unset env(GIT_DIR)}
+       catch {unset env(GIT_WORK_TREE)}
+}
+
 set picked 0
 if {[catch {
                set _gitdir $env(GIT_DIR)
@@ -1210,8 +1224,8 @@ if {[lindex $_reponame end] eq {.git}} {
        set _reponame [lindex $_reponame end]
 }
 
-set env(GIT_DIR) $_gitdir
-set env(GIT_WORK_TREE) $_gitworktree
+# Export the final paths
+set_gitdir_vars
 
 ######################################################################
 ##
@@ -2010,7 +2024,6 @@ proc incr_font_size {font {amt 1}} {
 
 proc do_gitk {revs {is_submodule false}} {
        global current_diff_path file_states current_diff_side ui_index
-       global _gitdir _gitworktree
 
        # -- Always start gitk through whatever we were loaded with.  This
        #    lets us bypass using shell process on Windows systems.
@@ -2020,8 +2033,6 @@ proc do_gitk {revs {is_submodule false}} {
        if {$exe eq {}} {
                error_popup [mc "Couldn't find gitk in PATH"]
        } else {
-               global env
-
                set pwd [pwd]
 
                if {$is_submodule} {
@@ -2049,13 +2060,11 @@ proc do_gitk {revs {is_submodule false}} {
                        # TODO we could make life easier (start up faster?) for gitk
                        # by setting these to the appropriate values to allow gitk
                        # to skip the heuristics to find their proper value
-                       unset env(GIT_DIR)
-                       unset env(GIT_WORK_TREE)
+                       unset_gitdir_vars
                }
                safe_exec_bg [concat $cmd $revs "--" "--"]
 
-               set env(GIT_DIR) $_gitdir
-               set env(GIT_WORK_TREE) $_gitworktree
+               set_gitdir_vars
                cd $pwd
 
                if {[info exists main_status]} {
@@ -2078,21 +2087,16 @@ proc do_git_gui {} {
        if {$exe eq {}} {
                error_popup [mc "Couldn't find git gui in PATH"]
        } else {
-               global env
-               global _gitdir _gitworktree
-
                # see note in do_gitk about unsetting these vars when
                # running tools in a submodule
-               unset env(GIT_DIR)
-               unset env(GIT_WORK_TREE)
+               unset_gitdir_vars
 
                set pwd [pwd]
                cd $current_diff_path
 
                safe_exec_bg [concat $exe gui]
 
-               set env(GIT_DIR) $_gitdir
-               set env(GIT_WORK_TREE) $_gitworktree
+               set_gitdir_vars
                cd $pwd
 
                set status_operation [$::main_status \