* [PATCH v3 08/12] git-gui: simplify [is_bare] to report if a worktree is known
From: Mark Levedahl @ 2026-05-31 23:02 UTC (permalink / raw)
To: git; +Cc: j6t, egg_mushroomcow, bootaina702, Mark Levedahl
In-Reply-To: <20260531230225.126817-1-mlevedahl@gmail.com>
git-gui includes proc is_bare, used in several places to make decisions
on whether a worktree exists, but also in discovery to tell if a
worktree can be supported.
But, is_bare is out of date with regard to multiple worktrees, safe
repository guards, and possibly other relevant features known to git
rev-parse. Also, is_bare caches its result on the first call, so is not
useful if a later step in the discovery process finds a worktree.
So, simplify is_bare to report whether git-gui has a worktree or is
working only from a repository.
Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
---
git-gui.sh | 25 +------------------------
1 file changed, 1 insertion(+), 24 deletions(-)
diff --git a/git-gui.sh b/git-gui.sh
index 53b6859345..abee222903 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -372,7 +372,6 @@ if {[tk windowingsystem] eq "aqua"} {
set _appname {Git Gui}
set _gitdir {}
set _gitworktree {}
-set _isbare {}
set _githtmldir {}
set _prefix {}
set _reponame {}
@@ -524,29 +523,7 @@ proc get_config {name} {
}
proc is_bare {} {
- global _isbare
- global _gitdir
- global _gitworktree
-
- if {$_isbare eq {}} {
- if {[catch {
- set _bare [git rev-parse --is-bare-repository]
- switch -- $_bare {
- true { set _isbare 1 }
- false { set _isbare 0}
- default { throw }
- }
- }]} {
- if {[is_config_true core.bare]
- || ($_gitworktree eq {}
- && [lindex [file split $_gitdir] end] ne {.git})} {
- set _isbare 1
- } else {
- set _isbare 0
- }
- }
- }
- return $_isbare
+ return [expr {$::_gitworktree eq {}}]
}
######################################################################
--
2.54.0.99.14
^ permalink raw reply related
* [PATCH v3 07/12] git-gui: use git rev-parse for worktree discovery
From: Mark Levedahl @ 2026-05-31 23:02 UTC (permalink / raw)
To: git; +Cc: j6t, egg_mushroomcow, bootaina702, Mark Levedahl
In-Reply-To: <20260531230225.126817-1-mlevedahl@gmail.com>
git gui uses a combination of tcl code and git invocations to determine
the worktree and the location with respect to the worktree root
(_prefix). But, git rev-parse provides all of this information directly,
and assures full error and configuration checking are done by git
itself. The entirety of discovery in normal configurations involves
git rev-parse --show-toplevel (gets worktree root)
git rev-parse --show-prefix (shows location wrt the root)
An error thrown on either of these lines means the worktree discovered
by git is unusable, or git did not discover a worktree because the
current directory is inside the repository. If the user has defined
GIT_DIR or GIT_WORK_TREE, this is a user configuration error and git-gui
should stop.
Otherwise, the blame or browser subcommands can be used without a
worktree.
A separate error might occur when changing to the root of the discovered
worktree. The cause would be file system related and completely outside
of git's control, so trap that independently.
Discovery of the repository and the worktree must be guarded to trap
errors: the intent is that any configuration problems are caught during
discovery, and later processing need not include error trapping and
recovery. So, move all worktree discovery code to be immediately after
repository discovery.
This does move configuration loading to occur after worktree discovery
rather than before. None of the code executed in worktree discovery has
any option controlled by a git-gui configuration variable, so no impact
is expected. git itself will always read the repository configuration,
including worktree specific configuration data if that exists, so this
is unaffected by when git-gui loads its own config data. Also, we cannot
be sure the worktree dependent configuration can be loaded before
full discovery is complete.
Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
---
git-gui.sh | 61 ++++++++++++++++++++++++------------------------------
1 file changed, 27 insertions(+), 34 deletions(-)
diff --git a/git-gui.sh b/git-gui.sh
index aed3bc7200..53b6859345 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -1187,6 +1187,33 @@ if {$_gitdir eq {}} {
set picked 1
}
+# find worktree, continue without if not required
+if {[catch {
+ set _gitworktree [git rev-parse --show-toplevel]
+ set _prefix [git rev-parse --show-prefix]
+ } err]} {
+ if {[is_gitvars_error $err]} {
+ exit 1
+ }
+ set _gitworktree {}
+ set _prefix {}
+}
+
+if {![is_bare]} {
+ if {[catch {cd $_gitworktree} err]} {
+ catch {wm withdraw .}
+ error_popup [strcat [mc "No working directory"] " $_gitworktree:\n\n$err"]
+ exit 1
+ }
+} elseif {![is_enabled bare]} {
+ catch {wm withdraw .}
+ error_popup [strcat [mc "Cannot use bare repository:"] "\n\n$_gitdir"]
+ exit 1
+}
+
+# repository and worktree config are complete, export them
+set_gitdir_vars
+
# Use object format as hash algorithm (either "sha1" or "sha256")
set hashalgorithm [git rev-parse --show-object-format]
if {$hashalgorithm eq "sha1"} {
@@ -1202,37 +1229,6 @@ if {$hashalgorithm eq "sha1"} {
load_config 0
apply_config
-set _gitworktree [git rev-parse --show-toplevel]
-
-if {$_prefix ne {}} {
- if {$_gitworktree eq {}} {
- regsub -all {[^/]+/} $_prefix ../ cdup
- } else {
- set cdup $_gitworktree
- }
- if {[catch {cd $cdup} err]} {
- catch {wm withdraw .}
- error_popup [strcat [mc "Cannot move to top of working directory:"] "\n\n$err"]
- exit 1
- }
- set _gitworktree [pwd]
- unset cdup
-} elseif {![is_enabled bare]} {
- if {[is_bare]} {
- catch {wm withdraw .}
- error_popup [strcat [mc "Cannot use bare repository:"] "\n\n$_gitdir"]
- exit 1
- }
- if {$_gitworktree eq {}} {
- set _gitworktree [file dirname $_gitdir]
- }
- if {[catch {cd $_gitworktree} err]} {
- catch {wm withdraw .}
- error_popup [strcat [mc "No working directory"] " $_gitworktree:\n\n$err"]
- exit 1
- }
- set _gitworktree [pwd]
-}
set _reponame [file split [file normalize $_gitdir]]
if {[lindex $_reponame end] eq {.git}} {
set _reponame [lindex $_reponame end-1]
@@ -1240,9 +1236,6 @@ if {[lindex $_reponame end] eq {.git}} {
set _reponame [lindex $_reponame end]
}
-# Export the final paths
-set_gitdir_vars
-
######################################################################
##
## global init
--
2.54.0.99.14
^ permalink raw reply related
* [PATCH v3 06/12] git-gui: use rev-parse exclusively to find a repository
From: Mark Levedahl @ 2026-05-31 23:02 UTC (permalink / raw)
To: git; +Cc: j6t, egg_mushroomcow, bootaina702, Mark Levedahl
In-Reply-To: <20260531230225.126817-1-mlevedahl@gmail.com>
git-gui attempts to use env(GIT_DIR) directly as the git repository,
accepting GIT_DIR if it is a directory. Only if that fails is git
rev-parse used to discover the repository. But, this avoids all of
git-core's validity checking on a repository, thus possibly deferring an
error to a later step, possibly unexpected. Repository validation should
be part of initial setup so that later processing does not need error
trapping for configuration errors.
Let's just invoke rev-parse so all error checking is done.
While here, let's cleanup the error handling.
Stop if an error occurs and the user set GIT_DIR or GIT_WORK_TREE.
Use of either or both of those variables is supported by git, but their
use also means the user has taken responsibility that they are correct,
so a failure is something the user must address.
Otherwise on error, continue the existing behavior and show the
repository picker. But, let's move the possible invocation of
repository_chooser::pick to a separate code block. This permits adding
separate conditions on using pick independent of repository discovery, and
will be exploited later in the series. Note that the picker always
returns with the current directory in the root of a worktree with the
git repository is in the .git subdirectory. The variable "picked" is
used by git-gui to automatically execute the "Explore Working Copy" menu
item after the repository picker is run. This is controlled by config
variable gui.autoexplore, and happens after all discovery is complete.
Remove a later check on whether _gitdir is a directory: that code
cannot be reached without rev-parse already validating the repository.
_prefix is set as part of worktree discovery, but must be {} if not
running with a worktree. Initialze this as {} along with other global
variables, this is the correct value is no worktree is found.
Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
---
git-gui.sh | 49 ++++++++++++++++++++++++++++++++++---------------
1 file changed, 34 insertions(+), 15 deletions(-)
diff --git a/git-gui.sh b/git-gui.sh
index 8a5f0bd938..aed3bc7200 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -374,6 +374,7 @@ set _gitdir {}
set _gitworktree {}
set _isbare {}
set _githtmldir {}
+set _prefix {}
set _reponame {}
set _shellpath {@@SHELL_PATH@@}
@@ -1125,6 +1126,24 @@ unset argv0dir
##
## repository setup
+proc is_gitvars_error {err} {
+ set havevars 0
+ set GIT_DIR {}
+ set GIT_WORK_TREE {}
+ catch {set GIT_DIR $::env(GIT_DIR); set havevars 1}
+ catch {set GIT_WORK_TREE $::env(GIT_WORK_TREE); set havevars 1}
+
+ if {$havevars} {
+ catch {wm withdraw .}
+ error_popup [strcat [mc "Invalid configuration:"] \
+ "\n" "GIT_DIR: " $GIT_DIR \
+ "\n" "GIT_WORK_TREE: " $GIT_WORK_TREE \
+ "\n\n$err"]
+ return 1
+ }
+ return 0
+}
+
proc set_gitdir_vars {} {
global _gitdir _gitworktree env
set env(GIT_DIR) $_gitdir
@@ -1139,16 +1158,22 @@ proc unset_gitdir_vars {} {
catch {unset env(GIT_WORK_TREE)}
}
+# find repository
+set _gitdir {}
+if {$_gitdir eq {}} {
+ if {[catch {
+ set _gitdir [git rev-parse --absolute-git-dir]
+ } err]} {
+ if {[is_gitvars_error $err]} {
+ exit 1
+ }
+ set _gitdir {}
+ }
+}
+
set picked 0
-if {[catch {
- set _gitdir $env(GIT_DIR)
- set _prefix {}
- }]
- && [catch {
- # beware that from the .git dir this sets _prefix to the empty string
- set _gitdir [git rev-parse --absolute-git-dir]
- set _prefix [git rev-parse --show-prefix]
- } err]} {
+if {$_gitdir eq {}} {
+ unset_gitdir_vars
load_config 1
apply_config
choose_repository::pick
@@ -1159,7 +1184,6 @@ if {[catch {
error_popup [strcat [mc "Unusable repo/worktree:"] " [pwd] \n\n$err"]
exit 1
}
- set _prefix {}
set picked 1
}
@@ -1174,11 +1198,6 @@ if {$hashalgorithm eq "sha1"} {
exit 1
}
-if {![file isdirectory $_gitdir]} {
- catch {wm withdraw .}
- error_popup [strcat [mc "Git directory not found:"] "\n\n$_gitdir"]
- exit 1
-}
# _gitdir exists, so try loading the config
load_config 0
apply_config
--
2.54.0.99.14
^ permalink raw reply related
* [PATCH v3 05/12] git-gui: use --absolute-git-dir
From: Mark Levedahl @ 2026-05-31 23:02 UTC (permalink / raw)
To: git; +Cc: j6t, egg_mushroomcow, bootaina702, Mark Levedahl
In-Reply-To: <20260531230225.126817-1-mlevedahl@gmail.com>
git-gui uses git rev-parse --git-dir to get the pathname of the
discovered git repository. The returned value can be relative, and is
'.' if the current directory is the top of the repository directory
itself. git-gui has code to change '.' to [pwd] in this case so that
subsequent logic runs.
But, git rev-parse supports --absolute-git-dir from fac60b8925
("rev-parse: add option for absolute or relative path formatting",
2020-12-13), and included in git 2.31. git-gui requires git >= 2.36, so
this more useful form is always available. Use --absolute-git-dir to
always get an absolute path, avoiding the need for other checks, and
delete the now unneeded code to fix a relative _gitdir.
Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
---
git-gui.sh | 14 +++-----------
1 file changed, 3 insertions(+), 11 deletions(-)
diff --git a/git-gui.sh b/git-gui.sh
index 44914bddcf..8a5f0bd938 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -1145,16 +1145,15 @@ if {[catch {
set _prefix {}
}]
&& [catch {
- # beware that from the .git dir this sets _gitdir to .
- # and _prefix to the empty string
- set _gitdir [git rev-parse --git-dir]
+ # beware that from the .git dir this sets _prefix to the empty string
+ set _gitdir [git rev-parse --absolute-git-dir]
set _prefix [git rev-parse --show-prefix]
} err]} {
load_config 1
apply_config
choose_repository::pick
if {[catch {
- set _gitdir [git rev-parse --git-dir]
+ set _gitdir [git rev-parse --absolute-git-dir]
} err]} {
catch {wm withdraw .}
error_popup [strcat [mc "Unusable repo/worktree:"] " [pwd] \n\n$err"]
@@ -1175,13 +1174,6 @@ if {$hashalgorithm eq "sha1"} {
exit 1
}
-# we expand the _gitdir when it's just a single dot (i.e. when we're being
-# run from the .git dir itself) lest the routines to find the worktree
-# get confused
-if {$_gitdir eq "."} {
- set _gitdir [pwd]
-}
-
if {![file isdirectory $_gitdir]} {
catch {wm withdraw .}
error_popup [strcat [mc "Git directory not found:"] "\n\n$_gitdir"]
--
2.54.0.99.14
^ permalink raw reply related
* [PATCH v3 04/12] git-gui: do not change global vars in choose_repository::pick
From: Mark Levedahl @ 2026-05-31 23:02 UTC (permalink / raw)
To: git; +Cc: j6t, egg_mushroomcow, bootaina702, Mark Levedahl
In-Reply-To: <20260531230225.126817-1-mlevedahl@gmail.com>
The repository picker (choose_repository::pick, AKA pick) on success
always returns with the current directory at the root of the selected
worktree, with the global variable _gitdir holding the name of the
git repository, possibly as a relative path, and _prefix {}. The
worktree root (_gitworktree) is not filled out, and if the selection was
from the "recent" list, no validation has occurred beyond testing that
the worktree root exists. So, repository and worktree validation are
still needed to be sure the new repo + worktree is usable.
pick only supports worktrees with a .git entry in the worktree root, so
git repository and worktree discovery will work starting in the current
directory on return. In cases of error, or user abort, pick exits the
process rather than returning.
So, let's change pick to not alter any global values, with success
indicated by the process returning to the caller. In this case, the
current directory is the worktree root, with a .git entry. The caller
then proceeds with normal discovery to find and validate both repository
and worktree.
With this, pick now returns 1 in the success case, but additional work
would be necessary to return from conditions where 0 should be returned.
Checking this return value would be superfluous.
Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
---
git-gui.sh | 7 ++++++-
lib/choose_repository.tcl | 21 ++++++++-------------
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/git-gui.sh b/git-gui.sh
index 2cf14d0dd5..44914bddcf 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -1153,9 +1153,14 @@ if {[catch {
load_config 1
apply_config
choose_repository::pick
- if {![file isdirectory $_gitdir]} {
+ if {[catch {
+ set _gitdir [git rev-parse --git-dir]
+ } err]} {
+ catch {wm withdraw .}
+ error_popup [strcat [mc "Unusable repo/worktree:"] " [pwd] \n\n$err"]
exit 1
}
+ set _prefix {}
set picked 1
}
diff --git a/lib/choose_repository.tcl b/lib/choose_repository.tcl
index 7e1462a20c..4b06afee93 100644
--- a/lib/choose_repository.tcl
+++ b/lib/choose_repository.tcl
@@ -15,7 +15,7 @@ field w_recentlist ; # Listbox containing recent repositories
field w_localpath ; # Entry widget bound to local_path
field done 0 ; # Finished picking the repository?
-field clone_ok false ; # clone succeeeded
+field pick_ok 0 ; # true if repo pick/clone succeeded
field local_path {} ; # Where this repository is locally
field origin_url {} ; # Where we are cloning from
field origin_name origin ; # What we shall call 'origin'
@@ -220,6 +220,8 @@ constructor pick {} {
if {$top eq {.}} {
eval destroy [winfo children $top]
}
+
+ return $pick_ok
}
method _center {} {
@@ -327,8 +329,7 @@ method _git_init {} {
}
_append_recentrepos [pwd]
- set ::_gitdir .git
- set ::_prefix {}
+ set pick_ok 1
return 1
}
@@ -409,6 +410,7 @@ method _do_new2 {} {
if {![_git_init $this]} {
return
}
+ set pick_ok 1
set done 1
}
@@ -621,7 +623,7 @@ method _do_clone2 {} {
}
tkwait variable @done
- if {!$clone_ok} {
+ if {!$pick_ok} {
error_popup [mc "Clone failed."]
return
}
@@ -632,18 +634,12 @@ method _do_clone2_done {ok} {
if {$ok} {
if {[catch {
cd $local_path
- set ::_gitdir .git
- set ::_prefix {}
_append_recentrepos [pwd]
} err]} {
set ok 0
}
}
- if {!$ok} {
- set ::_gitdir {}
- set ::_prefix {}
- }
- set clone_ok $ok
+ set pick_ok $ok
set done 1
}
@@ -721,8 +717,7 @@ method _do_open2 {} {
}
_append_recentrepos [pwd]
- set ::_gitdir $actualgit
- set ::_prefix {}
+ set pick_ok 1
set done 1
}
--
2.54.0.99.14
^ permalink raw reply related
* [PATCH v3 03/12] git-gui: guard set/unset of GIT_DIR and GIT_WORK_TREE
From: Mark Levedahl @ 2026-05-31 23:02 UTC (permalink / raw)
To: git; +Cc: j6t, egg_mushroomcow, bootaina702, Mark Levedahl
In-Reply-To: <20260531230225.126817-1-mlevedahl@gmail.com>
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>
---
git-gui.sh | 37 +++++++++++++++++++++----------------
1 file changed, 21 insertions(+), 16 deletions(-)
diff --git a/git-gui.sh b/git-gui.sh
index 52897fbd09..2cf14d0dd5 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -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,7 @@ 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
+ global _gitworktree
# -- Always start gitk through whatever we were loaded with. This
# lets us bypass using shell process on Windows systems.
@@ -2020,8 +2034,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 +2061,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 +2088,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 \
--
2.54.0.99.14
^ permalink raw reply related
* [PATCH v3 02/12] git-gui: remove unnecessary 'cd $_gitworktree' from do_gitk
From: Mark Levedahl @ 2026-05-31 23:02 UTC (permalink / raw)
To: git; +Cc: j6t, egg_mushroomcow, bootaina702, Mark Levedahl
In-Reply-To: <20260531230225.126817-1-mlevedahl@gmail.com>
From: Johannes Sixt <j6t@kdbg.org>
In the procedure that invokes Gitk, we have a 'cd $_gitworktree'. Such
a change of the current directory is not necessary, because
- if we have a working tree, then the startup routine has already
changed the current directory to the root of the working tree, which
*is* $_gitworktree; or
- if we are in a bare repository, then there is no point in changing
the current directory anywhere. (And $_gitworktree is empty.)
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
---
git-gui.sh | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/git-gui.sh b/git-gui.sh
index f70a54a61b..52897fbd09 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -2024,11 +2024,7 @@ proc do_gitk {revs {is_submodule false}} {
set pwd [pwd]
- if {!$is_submodule} {
- if {![is_bare]} {
- cd $_gitworktree
- }
- } else {
+ if {$is_submodule} {
cd $current_diff_path
if {$revs eq {--}} {
set s $file_states($current_diff_path)
--
2.54.0.99.14
^ permalink raw reply related
* [PATCH v3 01/12] git-gui: use HEAD as current branch when detached
From: Mark Levedahl @ 2026-05-31 23:02 UTC (permalink / raw)
To: git; +Cc: j6t, egg_mushroomcow, bootaina702, Mark Levedahl
In-Reply-To: <20260531230225.126817-1-mlevedahl@gmail.com>
commit f87a36b697 ("git-gui: use git-branch --show-current", 2024-02-12)
changed git-gui to use git-branch to access refs, rather than directly
reading files as doing the latter is not compatible with the reftable
backend. git branch --show-current reports an empty branch name when the
head is detached, and in this case load_current_branch needs to report
HEAD using special case logic as it did prior to the above commit. Make
it do so.
This addresses an issue with git-gui browser failing with a detached
head.
Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
---
git-gui.sh | 3 +++
1 file changed, 3 insertions(+)
diff --git a/git-gui.sh b/git-gui.sh
index 23fe76e498..f70a54a61b 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -670,6 +670,9 @@ proc load_current_branch {} {
set current_branch [git branch --show-current]
set is_detached [expr [string length $current_branch] == 0]
+ if {$is_detached} {
+ set current_branch {HEAD}
+ }
}
auto_load tk_optionMenu
--
2.54.0.99.14
^ permalink raw reply related
* [PATCH v3 00/12] Improve git gui operation without a worktree
From: Mark Levedahl @ 2026-05-31 23:02 UTC (permalink / raw)
To: git; +Cc: j6t, egg_mushroomcow, bootaina702, Mark Levedahl
In-Reply-To: <20260520202411.108764-1-mlevedahl@gmail.com>
git gui has a number of inter-related problems that result in problems
during startup from anything but a checked out worktree pointing at a
valid git repository. Some of the symptoms are:
- blame / browser subcommands, and launching gitk, are intended to be
useful without a worktree, but fail to work.
- unlike git, git-gui is supposed to use the parent directory as a
worktree if started from the .git subdirectory in the very common
single worktree + embedded git repository format. This does not
work.
- git-gui includes a repository picker allowing a user to select a
worktree from a list and/or start a new repo+worktree: this dialog can
appear at unexpected times, masking useful error feedback on
configuration problems.
This patch series addresses the above issues, substantially rewriting
the initial repository/worktree process to rely upon git rev-parse so
that git's knowledge of access rules, repository configuration, and use
of GIT_DIR / GIT_WORK_TREE (or git --gitdir / --work-tree) is used
throughout, replacing code largely based upon what git did in 2008. This
also means that git gui will naturally gain any new rules implmented in
git-core.
With this, git-gui only exports GIT_WORK_TREE when non-empty.
GIT_WORK_TREE is needed, and must be exported, if the user is overriding
core.worktree in the git repository. But, GIT_WORK_TREE cannot be used
to specify the lack of a worktree, so exporting an empty GIT_WORK_TREE
is one of the problems fixed by this series.
v3 of this series addresses j6t's review of v2, with some reordering of
patches (1 from j6t added, patch #8 moved to #1), adds another rewrite
of the browser / blame parser that eliminates the notion of path before
rev on the command line, blame works correctly with a user modified file
in the worktree. Clarification is added on the need for GTI_WORK_TREE,
and the logic in finding a worktree from the gitdir is simplified.
Johannes Sixt (1):
git-gui: remove unnecessary 'cd $_gitworktree' from do_gitk
Mark Levedahl (11):
git-gui: use HEAD as current branch when detached
git-gui: guard set/unset of GIT_DIR and GIT_WORK_TREE
git-gui: do not change global vars in choose_repository::pick
git-gui: use --absolute-git-dir
git-gui: use rev-parse exclusively to find a repository
git-gui: use git rev-parse for worktree discovery
git-gui: simplify [is_bare] to report if a worktree is known
git-gui: try harder to find worktree from gitdir
git-gui: allow specifying path '.' to the browser
git-gui: check browser/blame arguments carefully
git-gui: add gui and pick as explicit subcommands
git-gui.sh | 377 ++++++++++++++++++++++----------------
lib/choose_repository.tcl | 21 +--
2 files changed, 223 insertions(+), 175 deletions(-)
Interdiff against v2:
diff --git a/git-gui.sh b/git-gui.sh
index 299c1a0292..933e72c9b2 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -1114,33 +1114,29 @@ unset argv0dir
## repository setup
proc find_worktree_from_gitdir {} {
- # Directory 'parent' of a repository named 'parent/.git' might be the worktree.
- # Assure parent is a worktree and using the git repository already discovered.
- # Also, handle case of being in a worktree's gitdir, where file "gitdir" points to
- # gitlink file .git in the real worktree.
+ # this is invoked only if the current directory is inside the repository
set worktree {}
if {[file tail $::_gitdir] eq {.git}} {
+ # the dir containing .git is a worktree if repo allows it
+ # Check that git reports parent as a worktree (gitdir might not allow a worktree)
if {[catch {
- set gitdir_parent [file dirname $::_gitdir]
- set worktree [git -C $gitdir_parent rev-parse --show-toplevel]
- set parent_gitdir [git -C $worktree rev-parse --absolute-git-dir]
- if {$::_gitdir ne $parent_gitdir} {
- set worktree {}
- }
- }]} {
+ set parent [file dirname $::_gitdir]
+ set worktree [git -C $parent rev-parse --show-toplevel]
+ }]} {
set worktree {}
}
} elseif [file exists {gitdir}] {
+ # a worktree gitdir has .gitdir naming worktree/.git
+ # assure git run there reports this dir as the gitdir (links might be broken)
if {[catch {
- set fd_gitdir [open {gitdir} {r}]
- set gitlink_parent [file dirname [read $fd_gitdir]]
- catch {close $fd_gitdir}
- set worktree [git -C $gitlink_parent rev-parse --show-toplevel]
- set parent_gitdir [git -C $worktree rev-parse --absolute-git-dir]
- if {$::_gitdir ne $parent_gitdir} {
- set worktree {}
- }
- }]} {
+ set fd_gitdir [open {gitdir} {r}]
+ set worktree [file dirname [read $fd_gitdir]]
+ catch {close $fd_gitdir}
+ set worktree_gitdir [git -C $worktree rev-parse --absolute-git-dir]
+ if {$::_gitdir ne $worktree_gitdir} {
+ set worktree {}
+ }
+ }]} {
catch {close $fd_gitdir}
set worktree {}
}
@@ -1153,7 +1149,7 @@ proc is_gitvars_error {err} {
set GIT_DIR {}
set GIT_WORK_TREE {}
catch {set GIT_DIR $::env(GIT_DIR); set havevars 1}
- catch {set GIT_WORK_TREE $::env(GIT_WORK_TREE) ; set havevars 1}
+ catch {set GIT_WORK_TREE $::env(GIT_WORK_TREE); set havevars 1}
if {$havevars} {
catch {wm withdraw .}
@@ -1168,9 +1164,7 @@ proc is_gitvars_error {err} {
proc set_gitdir_vars {} {
global _gitdir _gitworktree env
- if {$_gitdir ne {}} {
- set env(GIT_DIR) $_gitdir
- }
+ set env(GIT_DIR) $_gitdir
if {$_gitworktree ne {}} {
set env(GIT_WORK_TREE) $_gitworktree
}
@@ -1182,12 +1176,12 @@ proc unset_gitdir_vars {} {
catch {unset env(GIT_WORK_TREE)}
}
-# find repository.
+# find repository
set _gitdir {}
if {[is_enabled gitdir_discovery]} {
if {[catch {
- set _gitdir [git rev-parse --absolute-git-dir]
- } err]} {
+ set _gitdir [git rev-parse --absolute-git-dir]
+ } err]} {
if {[is_gitvars_error $err]} {
exit 1
}
@@ -1200,14 +1194,13 @@ if {$_gitdir eq {} && [is_enabled picker]} {
unset_gitdir_vars
load_config 1
apply_config
- if {![choose_repository::pick]} {
- exit 1
- }
+ choose_repository::pick
if {[catch {
- set _gitdir [git rev-parse --absolute-git-dir]
- } err]} {
+ set _gitdir [git rev-parse --absolute-git-dir]
+ } err]} {
catch {wm withdraw .}
- error_popup [strcat [mc "Unusable repo/worktree:"] " [pwd] "\n\n$err"]
+ error_popup [strcat [mc "Unusable repo/worktree:"] " [pwd] \n\n$err"]
+ exit 1
}
set picked 1
}
@@ -1220,9 +1213,9 @@ if {$_gitdir eq {}} {
# find worktree, continue without if not required
if {[catch {
- set _gitworktree [git rev-parse --show-toplevel]
- set _prefix [git rev-parse --show-prefix]
-} err]} {
+ set _gitworktree [git rev-parse --show-toplevel]
+ set _prefix [git rev-parse --show-prefix]
+ } err]} {
if {[is_gitvars_error $err]} {
exit 1
}
@@ -1238,17 +1231,14 @@ if {[is_bare]} {
}
if {![is_bare]} {
- if {[catch {
- cd $_gitworktree
- } err]} {
+ if {[catch {cd $_gitworktree} err]} {
catch {wm withdraw .}
- error_popup [strcat [mc "Cannot change to discovered worktree: "] \
- "$_gitworktree" "\n\n$err"]
- exit 1;
+ error_popup [strcat [mc "No working directory"] " $_gitworktree:\n\n$err"]
+ exit 1
}
} elseif {![is_enabled bare]} {
catch {wm withdraw .}
- error_popup [strcat [mc "Cannot use bare repository:"] "\n\n" $_gitdir]
+ error_popup [strcat [mc "Cannot use bare repository:"] "\n\n$_gitdir"]
exit 1
}
@@ -2086,11 +2076,7 @@ proc do_gitk {revs {is_submodule false}} {
} else {
set pwd [pwd]
- if {!$is_submodule} {
- if {![is_bare]} {
- cd $_gitworktree
- }
- } else {
+ if {$is_submodule} {
cd $current_diff_path
if {$revs eq {--}} {
set s $file_states($current_diff_path)
@@ -3026,26 +3012,18 @@ proc normalize_relpath {path} {
if {$elements ne {}} {
return [eval file join $elements]
} else {
- return {./}
+ return {.}
}
}
-proc find_path_type {head path} {
- if {$path eq {./}} {
- # the root-tree exists in every rev, ls-tree gives data on the contents,
- # not the type of tree itself. So, if the rev exists, return {tree}
- if {[catch {set objtype [git ls-tree $head]}]} {
- set objtype {}
- } else {
- set objtype {tree}
- }
+proc show_parse_err {err} {
+ if {[tk windowingsystem] eq "win32"} {
+ catch {wm withdraw .}
+ error_popup $err
} else {
- # test that the path exists in head, ls-tree gives info on the path only
- if {[catch {set objtype [git ls-tree {--format=%(objecttype)} $head $path]}]} {
- set objtype {}
- }
+ puts stderr $err
}
- return $objtype
+ exit 1
}
# -- Not a normal commit type invocation? Do that instead!
@@ -3054,91 +3032,80 @@ switch -- $subcommand {
browser -
blame {
if {$subcommand eq "blame"} {
- set subcommand_args {[--line=<num>] <[rev] [--] filename | [--] filename rev>}
- set required_objtype blob
+ set subcommand_args {[--line=<num>] [rev] [--] <filename>}
+ set required_pathtype blob
} else {
- set subcommand_args {<[rev] [--] directory | [--] directory rev>}
- set required_objtype tree
+ set subcommand_args {[rev] [--] <dirname>}
+ set required_pathtype tree
}
set maxargs [llength $subcommand_args]
set nargs [llength $argv]
if {$nargs < 1 || $nargs > $maxargs} usage
set head {}
- set althead {}
set path {}
- set altpath {}
- set canswap 1
set jump_spec {}
- # assume: [--line=num] [head] [--] path as the possible arguments, in order.
- # head and path may need a swap later.
- for {set iarg 0} {$iarg < $nargs} {incr iarg} {
- set arg [lindex $argv $iarg]
- if {$arg eq {--}} {
- # next arg is the path, prevent or FORCE swap?
- if {$iarg == $nargs - 2} {
- set canswap 0
- } elseif {$iarg == $nargs - 3} {
- set canswap 2
- } else {
+ set iarg 0
+ foreach a $argv {
+ incr iarg
+ if {$iarg == $nargs} {
+ # final argument is path
+ set path [normalize_relpath [file join $_prefix $a]]
+ } elseif {$a eq {--}} {
+ # allow before required final arg that must be path
+ if {$iarg != $nargs - 1} {
usage
}
- } elseif {[regexp {^--line=(\d+)$} $arg arg lnum]} {
+ } elseif {[regexp {^--line=(\d+)$} $a a lnum]} {
# --line can only be the first arg
- if {$iarg != 0 || $maxargs < 4} usage
+ if {$iarg != 1 || $subcommand ne {blame}} usage
set jump_spec [list $lnum]
- } elseif {$iarg == $nargs - 1} {
- # assume final argument is path
- set path [normalize_relpath [file join $_prefix $arg]]
- set althead $arg
} elseif {$head eq {}} {
- # assume the other argument is head
- set head $arg
- set altpath [normalize_relpath [file join $_prefix $arg]]
+ set head $a
} else {
usage
}
}
- # no swapping allowed if head not given, use current branch (HEAD)
+ # If head not given, use current branch (HEAD),
+ # and blame will use worktree if there is one.
+ set use_worktree 0
if {$head eq {}} {
load_current_branch
set head $current_branch
- set canswap 0
- }
-
- # -- before "rev" arg means we got -- path head
- if {$canswap == 2} {
- set head $althead
- set path $altpath
- set canswap 0
- }
-
- set objtype [find_path_type $head $path]
- if {$objtype eq {} && $canswap} {
- set objtype [find_path_type $althead $altpath]
- if {$objtype ne {}} {
- set head $althead
- set path $altpath
+ if {$subcommand eq {blame} && ![is_bare]} {
+ if {![file isfile $path]} {
+ show_parse_err [mc "fatal: no such file '%s' in worktree" $path]
+ }
+ set use_worktree 1
}
- }
- set current_branch $head
-
- # check that path exists in head, and objtype matches need
- if {$objtype ne $required_objtype} {
- switch -- $required_objtype {
- tree {set err [strcat \
- [mc "'%s' is not a directory in rev '%s'" $path $head]]}
- blob {set err [strcat \
- [mc "'%s' is not a filename in rev '%s'" $path $head]]}
- }
- if {[tk windowingsystem] eq "win32"} {
- catch {wm withdraw .}
- error_popup $err
+ } else {
+ if {[catch {
+ set commitid \
+ [git rev-parse --verify --end-of-options \
+ [strcat $head "^{commit}"]]
+ }]} {
+ show_parse_err [mc "fatal: '%s' is not a valid rev'" $head]
} else {
- puts stderr $err
+ set current_branch $head
+ }
+ }
+
+ # check path is known in head, and is file / directory as required
+ set pathtype {}
+ catch {set pathtype [git ls-tree {--format=%(objecttype)} $head $path]}
+ if {$pathtype ne {} && $path eq {.}} {
+ # ls-tree gives contents of root-dir, we need root-dir itself
+ set pathtype {tree}
+ }
+
+ if {$pathtype ne $required_pathtype} {
+ switch -- $required_pathtype {
+ tree {show_parse_err \
+ [mc "'%s' is not a directory in rev '%s'" $path $head]}
+ blob {show_parse_err \
+ [mc "'%s' is not a filename in rev '%s'" $path $head]}
}
- exit 1
}
wm deiconify .
@@ -3146,8 +3113,8 @@ blame {
browser {
browser::new $head $path
}
- blame {
- blame::new $head $path $jump_spec
+ blame {
+ blame::new [expr {$use_worktree ? {} : $head}] $path $jump_spec
}
}
return
--
2.54.0.99.14
^ permalink raw reply related
* [PATCH v2] doc: fix typos via codespell
From: Andrew Kreimer @ 2026-05-31 18:43 UTC (permalink / raw)
To: git; +Cc: Andrew Kreimer
In-Reply-To: <20260506101631.18127-1-algonell@gmail.com>
There are some typos in the documentation, comments, etc.
Fix them via codespell.
Signed-off-by: Andrew Kreimer <algonell@gmail.com>
---
v2:
- Drop typos under po/ and git-gui/ (different projects).
Documentation/SubmittingPatches | 2 +-
Documentation/git-sparse-checkout.adoc | 2 +-
Documentation/technical/build-systems.adoc | 6 +++---
builtin/pack-objects.c | 2 +-
commit-graph.h | 2 +-
compat/precompose_utf8.c | 2 +-
hook.h | 2 +-
meson_options.txt | 2 +-
midx-write.c | 2 +-
odb/source.h | 2 +-
packfile.h | 2 +-
path.h | 2 +-
reftable/system.h | 2 +-
t/README | 2 +-
t/chainlint.pl | 2 +-
t/chainlint/chain-break-false.expect | 2 +-
t/chainlint/chain-break-false.test | 2 +-
t/t1700-split-index.sh | 2 +-
t/t3909-stash-pathspec-file.sh | 6 +++---
t/t4052-stat-output.sh | 2 +-
t/t4067-diff-partial-clone.sh | 2 +-
t/t9150/svk-merge.dump | 10 +++++-----
t/t9151/svn-mergeinfo.dump | 18 +++++++++---------
t/unit-tests/clar/README.md | 2 +-
24 files changed, 40 insertions(+), 40 deletions(-)
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index d570184ec8..35b4952c8a 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -92,7 +92,7 @@ input and avoids unnecessary churn from many rapid iterations.
topic are appropriate, so such an incremental updates are limited to
small corrections and polishing. After a topic cooks for some time
(like 7 calendar days) in 'next' without needing further tweaks on
- top, it gets merged to the 'master' branch and wait to become part
+ top, it gets merged to the 'master' branch and waits to become part
of the next major release.
In the following sections, many techniques and conventions are listed
diff --git a/Documentation/git-sparse-checkout.adoc b/Documentation/git-sparse-checkout.adoc
index 0d1618f161..e286584c67 100644
--- a/Documentation/git-sparse-checkout.adoc
+++ b/Documentation/git-sparse-checkout.adoc
@@ -134,7 +134,7 @@ the `clean.requireForce` config option is set to `false`.
+
The `--dry-run` option will list the directories that would be removed
without deleting them. Running in this mode can be helpful to predict the
-behavior of the clean comand or to determine which kinds of files are left
+behavior of the clean command or to determine which kinds of files are left
in the sparse directories.
+
The `--verbose` option will list every file within the directories that
diff --git a/Documentation/technical/build-systems.adoc b/Documentation/technical/build-systems.adoc
index 3c5237b9fd..ca5b5d96f1 100644
--- a/Documentation/technical/build-systems.adoc
+++ b/Documentation/technical/build-systems.adoc
@@ -47,7 +47,7 @@ Auto-detection of the following items is considered to be important:
- Check for the existence of headers.
- Check for the existence of libraries.
- - Check for the existence of exectuables.
+ - Check for the existence of executables.
- Check for the runtime behavior of specific functions.
- Check for specific link order requirements when multiple libraries are
involved.
@@ -106,7 +106,7 @@ by the build system:
- C: the primary compiled language used by Git, must be supported. Relevant
toolchains are GCC, Clang and MSVC.
- - Rust: candidate as a second compiled lanugage, should be supported. Relevant
+ - Rust: candidate as a second compiled language, should be supported. Relevant
toolchains is the LLVM-based rustc.
Built-in support for the respective languages is preferred over support that
@@ -142,7 +142,7 @@ The following list of build systems are considered:
=== GNU Make
-- Platform support: ubitquitous on all platforms, but not well-integrated into Windows.
+- Platform support: ubiquitous on all platforms, but not well-integrated into Windows.
- Auto-detection: no built-in support for auto-detection of features.
- Ease of use: easy to use, but discovering available options is hard. Makefile
rules can quickly get out of hand once reaching a certain scope.
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 480cc0bd8c..558cf821fe 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -1349,7 +1349,7 @@ static void write_pack_file(void)
* length of them as buffer length.
*
* Note that we need to subtract one though to
- * accomodate for the sideband byte.
+ * accommodate for the sideband byte.
*/
struct hashfd_options opts = {
.progress = progress_state,
diff --git a/commit-graph.h b/commit-graph.h
index f6a5433641..13ca4ff010 100644
--- a/commit-graph.h
+++ b/commit-graph.h
@@ -18,7 +18,7 @@
* This method is only used to enhance coverage of the commit-graph
* feature in the test suite with the GIT_TEST_COMMIT_GRAPH and
* GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS environment variables. Do not
- * call this method oustide of a builtin, and only if you know what
+ * call this method outside of a builtin, and only if you know what
* you are doing!
*/
void git_test_write_commit_graph_or_die(struct odb_source *source);
diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c
index 43b3be0114..6e709bd138 100644
--- a/compat/precompose_utf8.c
+++ b/compat/precompose_utf8.c
@@ -85,7 +85,7 @@ const char *precompose_string_if_needed(const char *in)
out = reencode_string_iconv(in, inlen, ic_prec, 0, &outlen);
if (out) {
if (outlen == inlen && !memcmp(in, out, outlen))
- free(out); /* no need to return indentical */
+ free(out); /* no need to return identical */
else
in = out;
}
diff --git a/hook.h b/hook.h
index b4372b636f..27bb1aeb2e 100644
--- a/hook.h
+++ b/hook.h
@@ -128,7 +128,7 @@ struct run_hooks_opt {
* While the callback allows piecemeal writing, it can also be
* used for smaller inputs, where it gets called only once.
*
- * Add hook callback initalization context to `feed_pipe_ctx`.
+ * Add hook callback initialization context to `feed_pipe_ctx`.
* Add hook callback internal state to `feed_pipe_cb_data`.
*
*/
diff --git a/meson_options.txt b/meson_options.txt
index 80a8025f20..d936ada098 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -106,7 +106,7 @@ option('highlight_bin', type: 'string', value: 'highlight')
# Documentation.
option('docs', type: 'array', choices: ['man', 'html'], value: [],
- description: 'Which documenattion formats to build and install.')
+ description: 'Which documentation formats to build and install.')
option('default_help_format', type: 'combo', choices: ['man', 'html', 'platform'], value: 'platform',
description: 'Default format used when executing git-help(1).')
option('docs_backend', type: 'combo', choices: ['asciidoc', 'asciidoctor', 'auto'], value: 'auto',
diff --git a/midx-write.c b/midx-write.c
index 561e9eedc0..19e1cd10b7 100644
--- a/midx-write.c
+++ b/midx-write.c
@@ -1461,7 +1461,7 @@ static int write_midx_internal(struct write_midx_opts *opts)
/*
* Attempt opening the pack index to populate num_objects.
- * Ignore failiures as they can be expected and are not
+ * Ignore failures as they can be expected and are not
* fatal during this selection time.
*/
open_pack_index(oldest);
diff --git a/odb/source.h b/odb/source.h
index 0a440884e4..2f51fcb9ff 100644
--- a/odb/source.h
+++ b/odb/source.h
@@ -341,7 +341,7 @@ static inline int odb_source_read_object_stream(struct odb_read_stream **out,
* are only iterated over once.
*
* The optional `request` structure serves as a template for retrieving the
- * object info for each indvidual iterated object and will be populated as if
+ * object info for each individual iterated object and will be populated as if
* `odb_source_read_object_info()` was called on the object. It will not be
* modified, the callback will instead be invoked with a separate `struct
* object_info` for every object. Object info will not be read when passing a
diff --git a/packfile.h b/packfile.h
index 49d6bdecf6..5729a37018 100644
--- a/packfile.h
+++ b/packfile.h
@@ -124,7 +124,7 @@ struct packfile_store {
* that packs that contain a lot of accessed objects will be located
* towards the front.
*
- * This is usually desireable, but there are exceptions. One exception
+ * This is usually desirable, but there are exceptions. One exception
* is when the looking up multiple objects in a loop for each packfile.
* In that case, we may easily end up with an infinite loop as the
* packfiles get reordered to the front repeatedly.
diff --git a/path.h b/path.h
index 0434ba5e07..4c2958a903 100644
--- a/path.h
+++ b/path.h
@@ -217,7 +217,7 @@ void safe_create_dir(struct repository *repo, const char *dir, int share);
*
* - It always adjusts shared permissions.
*
- * Returns a negative erorr code on error, 0 on success.
+ * Returns a negative error code on error, 0 on success.
*/
int safe_create_dir_in_gitdir(struct repository *repo, const char *path);
diff --git a/reftable/system.h b/reftable/system.h
index c0e2cbe0ff..628232a46f 100644
--- a/reftable/system.h
+++ b/reftable/system.h
@@ -84,7 +84,7 @@ struct reftable_flock {
* to acquire the lock. If `timeout_ms` is 0 we don't wait, if it is negative
* we block indefinitely.
*
- * Retrun 0 on success, a reftable error code on error. Specifically,
+ * Return 0 on success, a reftable error code on error. Specifically,
* `REFTABLE_LOCK_ERROR` should be returned in case the target path is already
* locked.
*/
diff --git a/t/README b/t/README
index adbbd9acf4..085921be4b 100644
--- a/t/README
+++ b/t/README
@@ -972,7 +972,7 @@ see test-lib-functions.sh for the full list and their options.
- test_lazy_prereq <prereq> <script>
Declare the way to determine if a test prerequisite <prereq> is
- satisified or not, but delay the actual determination until the
+ satisfied or not, but delay the actual determination until the
prerequisite is actually used by "test_have_prereq" or the
three-arg form of the test_expect_* functions. For example, this
is how the SYMLINKS prerequisite is declared to see if the platform
diff --git a/t/chainlint.pl b/t/chainlint.pl
index f0598e3934..2d07a99700 100755
--- a/t/chainlint.pl
+++ b/t/chainlint.pl
@@ -35,7 +35,7 @@
#
# In other languages, `1+2` would typically be scanned as three tokens
# (`1`, `+`, and `2`), but in shell it is a single token. However, the similar
-# `1 + 2`, which embeds whitepace, is scanned as three token in shell, as well.
+# `1 + 2`, which embeds whitespace, is scanned as three token in shell, as well.
# In shell, several characters with special meaning lose that meaning when not
# surrounded by whitespace. For instance, the negation operator `!` is special
# when standing alone surrounded by whitespace; whereas in `foo!uucp` it is
diff --git a/t/chainlint/chain-break-false.expect b/t/chainlint/chain-break-false.expect
index f6a0a301e9..db6f8b12a4 100644
--- a/t/chainlint/chain-break-false.expect
+++ b/t/chainlint/chain-break-false.expect
@@ -1,4 +1,4 @@
-2 if condition not satisified
+2 if condition not satisfied
3 then
4 echo it did not work...
5 echo failed!
diff --git a/t/chainlint/chain-break-false.test b/t/chainlint/chain-break-false.test
index f78ad911fc..924c9627c0 100644
--- a/t/chainlint/chain-break-false.test
+++ b/t/chainlint/chain-break-false.test
@@ -1,6 +1,6 @@
test_expect_success 'chain-break-false' '
# LINT: broken &&-chain okay if explicit "false" signals failure
-if condition not satisified
+if condition not satisfied
then
echo it did not work...
echo failed!
diff --git a/t/t1700-split-index.sh b/t/t1700-split-index.sh
index ac4a5b2734..869fb4a14e 100755
--- a/t/t1700-split-index.sh
+++ b/t/t1700-split-index.sh
@@ -502,7 +502,7 @@ test_expect_success 'do not refresh null base index' '
git checkout main &&
git update-index --split-index &&
test_commit more &&
- # must not write a new shareindex, or we wont catch the problem
+ # must not write a new shareindex, or we won't catch the problem
git -c splitIndex.maxPercentChange=100 merge --no-edit side-branch 2>err &&
# i.e. do not expect warnings like
# could not freshen shared index .../shareindex.00000...
diff --git a/t/t3909-stash-pathspec-file.sh b/t/t3909-stash-pathspec-file.sh
index 73f2dbdeb0..3afa6bff3d 100755
--- a/t/t3909-stash-pathspec-file.sh
+++ b/t/t3909-stash-pathspec-file.sh
@@ -29,7 +29,7 @@ verify_expect () {
test_expect_success 'simplest' '
restore_checkpoint &&
- # More files are written to make sure that git didnt ignore
+ # More files are written to make sure that git didn't ignore
# --pathspec-from-file, stashing everything
echo A >fileA.t &&
echo B >fileB.t &&
@@ -47,7 +47,7 @@ test_expect_success 'simplest' '
test_expect_success '--pathspec-file-nul' '
restore_checkpoint &&
- # More files are written to make sure that git didnt ignore
+ # More files are written to make sure that git didn't ignore
# --pathspec-from-file, stashing everything
echo A >fileA.t &&
echo B >fileB.t &&
@@ -66,7 +66,7 @@ test_expect_success '--pathspec-file-nul' '
test_expect_success 'only touches what was listed' '
restore_checkpoint &&
- # More files are written to make sure that git didnt ignore
+ # More files are written to make sure that git didn't ignore
# --pathspec-from-file, stashing everything
echo A >fileA.t &&
echo B >fileB.t &&
diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh
index e009585925..62d3d2604c 100755
--- a/t/t4052-stat-output.sh
+++ b/t/t4052-stat-output.sh
@@ -420,7 +420,7 @@ test_expect_success 'merge --stat respects COLUMNS with long name' '
# enough terminal display width, will contain the following line:
# "<RED>|<RESET> ${FILENAME} | 0"
# where "<RED>" and "<RESET>" are ANSI escape codes to color the text.
-# To calculate the minimium terminal display width MIN_TERM_WIDTH so that the
+# To calculate the minimum terminal display width MIN_TERM_WIDTH so that the
# FILENAME in the diffstat will not be shortened, we take the FILENAME length
# and add 9 to it.
# To check if the diffstat width, when the line_prefix (the "<RED>|<RESET>" of
diff --git a/t/t4067-diff-partial-clone.sh b/t/t4067-diff-partial-clone.sh
index 30813109ac..a9dec84c30 100755
--- a/t/t4067-diff-partial-clone.sh
+++ b/t/t4067-diff-partial-clone.sh
@@ -159,7 +159,7 @@ test_expect_success 'diff succeeds even if prefetch triggered by break-rewrites'
# We need baz to trigger break-rewrites detection.
git -C client reset --hard HEAD &&
- # break-rewrites detction in reset.
+ # break-rewrites detection in reset.
git -C client reset HEAD~1
'
diff --git a/t/t9150/svk-merge.dump b/t/t9150/svk-merge.dump
index 42f70dbec7..6a8ac81b11 100644
--- a/t/t9150/svk-merge.dump
+++ b/t/t9150/svk-merge.dump
@@ -77,7 +77,7 @@ Content-length: 2411
PROPS-END
# -DCOLLISION_CHECK if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
-# enough guarantees about no collisions between objects ever hapenning.
+# enough guarantees about no collisions between objects ever happening.
#
# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
# Note that you need some new glibc (at least >2.2.4) for this, and it will
@@ -206,7 +206,7 @@ Content-length: 2465
# -DCOLLISION_CHECK if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
-# enough guarantees about no collisions between objects ever hapenning.
+# enough guarantees about no collisions between objects ever happening.
#
# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
# Note that you need some new glibc (at least >2.2.4) for this, and it will
@@ -310,7 +310,7 @@ Content-length: 2521
# -DCOLLISION_CHECK if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
-# enough guarantees about no collisions between objects ever hapenning.
+# enough guarantees about no collisions between objects ever happening.
#
# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
# Note that you need some new glibc (at least >2.2.4) for this, and it will
@@ -417,7 +417,7 @@ Content-length: 2593
# -DCOLLISION_CHECK if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
-# enough guarantees about no collisions between objects ever hapenning.
+# enough guarantees about no collisions between objects ever happening.
#
# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
# Note that you need some new glibc (at least >2.2.4) for this, and it will
@@ -534,7 +534,7 @@ Content-length: 2713
# -DCOLLISION_CHECK if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
-# enough guarantees about no collisions between objects ever hapenning.
+# enough guarantees about no collisions between objects ever happening.
#
# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
# Note that you need some new glibc (at least >2.2.4) for this, and it will
diff --git a/t/t9151/svn-mergeinfo.dump b/t/t9151/svn-mergeinfo.dump
index 47cafcf528..d5e1695637 100644
--- a/t/t9151/svn-mergeinfo.dump
+++ b/t/t9151/svn-mergeinfo.dump
@@ -87,7 +87,7 @@ Content-length: 2411
PROPS-END
# -DCOLLISION_CHECK if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
-# enough guarantees about no collisions between objects ever hapenning.
+# enough guarantees about no collisions between objects ever happening.
#
# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
# Note that you need some new glibc (at least >2.2.4) for this, and it will
@@ -260,7 +260,7 @@ Content-length: 2465
# -DCOLLISION_CHECK if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
-# enough guarantees about no collisions between objects ever hapenning.
+# enough guarantees about no collisions between objects ever happening.
#
# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
# Note that you need some new glibc (at least >2.2.4) for this, and it will
@@ -365,7 +365,7 @@ Content-length: 2521
# -DCOLLISION_CHECK if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
-# enough guarantees about no collisions between objects ever hapenning.
+# enough guarantees about no collisions between objects ever happening.
#
# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
# Note that you need some new glibc (at least >2.2.4) for this, and it will
@@ -473,7 +473,7 @@ Content-length: 2529
# -DCOLLISION_CHECK if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
-# enough guarantees about no collisions between objects ever hapenning.
+# enough guarantees about no collisions between objects ever happening.
#
# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
# Note that you need some new glibc (at least >2.2.4) for this, and it will
@@ -578,7 +578,7 @@ Content-length: 2593
# -DCOLLISION_CHECK if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
-# enough guarantees about no collisions between objects ever hapenning.
+# enough guarantees about no collisions between objects ever happening.
#
# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
# Note that you need some new glibc (at least >2.2.4) for this, and it will
@@ -767,7 +767,7 @@ Content-length: 2593
# -DCOLLISION_CHECK if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
-# enough guarantees about no collisions between objects ever hapenning.
+# enough guarantees about no collisions between objects ever happening.
#
# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
# Note that you need some new glibc (at least >2.2.4) for this, and it will
@@ -948,7 +948,7 @@ Content-length: 2713
# -DCOLLISION_CHECK if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
-# enough guarantees about no collisions between objects ever hapenning.
+# enough guarantees about no collisions between objects ever happening.
#
# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
# Note that you need some new glibc (at least >2.2.4) for this, and it will
@@ -1172,7 +1172,7 @@ Content-length: 2713
# -DCOLLISION_CHECK if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
-# enough guarantees about no collisions between objects ever hapenning.
+# enough guarantees about no collisions between objects ever happening.
#
# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
# Note that you need some new glibc (at least >2.2.4) for this, and it will
@@ -1414,7 +1414,7 @@ Content-length: 2713
# -DCOLLISION_CHECK if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
-# enough guarantees about no collisions between objects ever hapenning.
+# enough guarantees about no collisions between objects ever happening.
#
# -DNSEC if you want git to care about sub-second file mtimes and ctimes.
# Note that you need some new glibc (at least >2.2.4) for this, and it will
diff --git a/t/unit-tests/clar/README.md b/t/unit-tests/clar/README.md
index 41595989ca..a45b9c8e5d 100644
--- a/t/unit-tests/clar/README.md
+++ b/t/unit-tests/clar/README.md
@@ -138,7 +138,7 @@ raise errors during test execution.
__Caution:__ If you use assertions inside of `test_suitename__initialize`,
make sure that you do not rely on `__initialize` being completely run
inside your `test_suitename__cleanup` function. Otherwise you might
-encounter ressource cleanup twice.
+encounter resource cleanup twice.
## How does Clar work?
Interdiff against v1:
diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
index 40e95bccb4..23fe76e498 100755
--- a/git-gui/git-gui.sh
+++ b/git-gui/git-gui.sh
@@ -109,7 +109,7 @@ foreach p [split $env(PATH) $_path_sep] {
if {[file pathtype $p] ne {absolute}} {
continue
}
- # Keep only the first occurrence of any duplicates.
+ # Keep only the first occurence of any duplicates.
set norm_p [file normalize $p]
dict set _path_seen $norm_p 1
}
diff --git a/git-gui/lib/choose_repository.tcl b/git-gui/lib/choose_repository.tcl
index a4703af028..7e1462a20c 100644
--- a/git-gui/lib/choose_repository.tcl
+++ b/git-gui/lib/choose_repository.tcl
@@ -15,7 +15,7 @@ field w_recentlist ; # Listbox containing recent repositories
field w_localpath ; # Entry widget bound to local_path
field done 0 ; # Finished picking the repository?
-field clone_ok false ; # clone succeeded
+field clone_ok false ; # clone succeeeded
field local_path {} ; # Where this repository is locally
field origin_url {} ; # Where we are cloning from
field origin_name origin ; # What we shall call 'origin'
diff --git a/git-gui/lib/themed.tcl b/git-gui/lib/themed.tcl
index f4cffeac66..c18e201d85 100644
--- a/git-gui/lib/themed.tcl
+++ b/git-gui/lib/themed.tcl
@@ -4,7 +4,7 @@
namespace eval color {
# Variable colors
- # Preferred way to set widget colors is using add_option.
+ # Preffered way to set widget colors is using add_option.
# In some cases, like with tags in_diff/in_sel, we use these colors.
variable select_bg lightgray
variable select_fg black
diff --git a/po/el.po b/po/el.po
index c45560c996..703f46d0c7 100644
--- a/po/el.po
+++ b/po/el.po
@@ -2748,7 +2748,7 @@ msgid "Low-level Commands / Interrogators"
msgstr "Εντολές Χαμηλού Επιπέδου / Ερωτημάτων"
#: help.c:37
-msgid "Low-level Commands / Syncing Repositories"
+msgid "Low-level Commands / Synching Repositories"
msgstr "Εντολές Χαμηλού Επιπέδου / Συγχρονισμού Αποθετηρίων"
#: help.c:38
diff --git a/po/ko.po b/po/ko.po
index 6bc20a43e3..7a6847f023 100644
--- a/po/ko.po
+++ b/po/ko.po
@@ -2062,7 +2062,7 @@ msgid "Low-level Commands / Interrogators"
msgstr "보조 명령 / 정보 획득 기능"
#: help.c:37
-msgid "Low-level Commands / Syncing Repositories"
+msgid "Low-level Commands / Synching Repositories"
msgstr "보조 명령 / 저장소 동기화 기능"
#: help.c:38
Range-diff against v1:
1: 381e2c1fc3 ! 1: 674edefc99 doc: fix typos via codespell
@@ compat/precompose_utf8.c: const char *precompose_string_if_needed(const char *in
in = out;
}
- ## git-gui/git-gui.sh ##
-@@ git-gui/git-gui.sh: foreach p [split $env(PATH) $_path_sep] {
- if {[file pathtype $p] ne {absolute}} {
- continue
- }
-- # Keep only the first occurence of any duplicates.
-+ # Keep only the first occurrence of any duplicates.
- set norm_p [file normalize $p]
- dict set _path_seen $norm_p 1
- }
-
- ## git-gui/lib/choose_repository.tcl ##
-@@ git-gui/lib/choose_repository.tcl: field w_recentlist ; # Listbox containing recent repositories
- field w_localpath ; # Entry widget bound to local_path
-
- field done 0 ; # Finished picking the repository?
--field clone_ok false ; # clone succeeeded
-+field clone_ok false ; # clone succeeded
- field local_path {} ; # Where this repository is locally
- field origin_url {} ; # Where we are cloning from
- field origin_name origin ; # What we shall call 'origin'
-
- ## git-gui/lib/themed.tcl ##
-@@
-
- namespace eval color {
- # Variable colors
-- # Preffered way to set widget colors is using add_option.
-+ # Preferred way to set widget colors is using add_option.
- # In some cases, like with tags in_diff/in_sel, we use these colors.
- variable select_bg lightgray
- variable select_fg black
-
## hook.h ##
@@ hook.h: struct run_hooks_opt {
* While the callback allows piecemeal writing, it can also be
@@ path.h: void safe_create_dir(struct repository *repo, const char *dir, int share
int safe_create_dir_in_gitdir(struct repository *repo, const char *path);
- ## po/el.po ##
-@@ po/el.po: msgid "Low-level Commands / Interrogators"
- msgstr "Εντολές Χαμηλού Επιπέδου / Ερωτημάτων"
-
- #: help.c:37
--msgid "Low-level Commands / Synching Repositories"
-+msgid "Low-level Commands / Syncing Repositories"
- msgstr "Εντολές Χαμηλού Επιπέδου / Συγχρονισμού Αποθετηρίων"
-
- #: help.c:38
-
- ## po/ko.po ##
-@@ po/ko.po: msgid "Low-level Commands / Interrogators"
- msgstr "보조 명령 / 정보 획득 기능"
-
- #: help.c:37
--msgid "Low-level Commands / Synching Repositories"
-+msgid "Low-level Commands / Syncing Repositories"
- msgstr "보조 명령 / 저장소 동기화 기능"
-
- #: help.c:38
-
## reftable/system.h ##
@@ reftable/system.h: struct reftable_flock {
* to acquire the lock. If `timeout_ms` is 0 we don't wait, if it is negative
--
2.54.0
^ permalink raw reply related
* [PATCH] prio-queue: use cascade-down sift for faster extract-min
From: Kristofer Karlsson via GitGitGadget @ 2026-05-31 17:57 UTC (permalink / raw)
To: git; +Cc: Kristofer Karlsson, Kristofer Karlsson
From: Kristofer Karlsson <krka@spotify.com>
Replace the standard sift-down in prio_queue_get() with a
cascade-down approach.
The standard approach places the last array element at the root,
then sifts it down. At each level this requires two comparisons
(left vs right child, then element vs winner) and, when the
element is larger, a swap (three 16-byte copies).
The cascade approach instead promotes the smaller child into the
vacant root slot at each level — one comparison and one copy.
The vacancy sinks to a leaf, where the last array element is
placed and sifted up if needed — typically zero levels since the
last array element tends to be large.
In the common case, work per extract drops from 2d comparisons
+ 3d copies to d comparisons + d copies: roughly half the
comparisons and a third of the data movement. The sift-up phase
can add work when the last element is smaller than ancestors of
the leaf vacancy, but this is rare in practice.
Simplify prio_queue_replace() to a plain get+put sequence. This
is semantically equivalent: the old implementation wrote to slot 0
and sifted down, which has the same observable effect as removing
the root and inserting a new element. No caller observes queue
state between the two operations. The previous implementation
shared sift_down_root() with get, but the cascade approach no
longer accommodates that cleanly since sift_down_root() now
expects the element to reinsert at queue->array[queue->nr], left
there by prio_queue_get() after decrementing nr. This is fine in
practice: replace is only called from pop_most_recent_commit()
(fetch-pack, object-name, walker) and show-branch — none of
which appear in any hot path.
A synthetic benchmark (10 rounds of 10M put+get cycles, ascending
integer keys, CPU-pinned, median of 3 runs, same compiler and
Makefile flags) shows consistent improvement across all queue
sizes, with no regressions:
queue width baseline cascade speedup
------------------------------------------------
10 4.32s 3.97s 1.09x
100 7.95s 6.49s 1.23x
1,000 11.30s 9.66s 1.17x
10,000 16.34s 14.15s 1.16x
100,000 21.43s 18.66s 1.15x
With descending keys (worst case — the last element always sinks
to a leaf in both approaches) the cascade still wins slightly
(1-4%) by replacing swaps with copies, and never regresses.
In end-to-end git commands the improvement is modest because
sift_down_root is only ~8% of total runtime. Profiling
rev-list --count on a 2.5M-commit monorepo shows sift_down_root
dropping from 8.2% to 0.4% of total runtime. The improvement
scales with DAG width: wider DAGs produce larger priority queues,
amplifying the per-level savings. In small or narrow repos the
queues stay shallow and the effect is negligible.
Signed-off-by: Kristofer Karlsson <krka@spotify.com>
---
prio-queue: use cascade-down sift for faster extract-min
Hi, I am not sure this is just noise or not but I thought it at least
was interesting.
I looked into the internals of prio_queue and found it was technically
doing too much work and could be simplified/optimized. I found I could
optimize it by ~20% for the common case (adding commits that would
typically end up far back in the queue) but only ~1% for the reverse
case (adding things to the front of the prio queue). The average speedup
is somewhere in between I suppose. That said, this is not really the
bottleneck so the overall boost seems to be around ~3-4% improvement for
repos with wide DAGs.
I would normally classify this as not urgent or important, but I think
the advantage is that the change is very small and simple and it already
has good unit tests (t/unit-tests/u-prio-queue.c).
With that said, here are the details:
The prio_queue_get impl is based on removing the root entry, then moving
the very last element into the root slot, then sifting it down into the
right place. This uses both comparisons between sibling elements in the
heap as well as comparisons between the element to add and one of the
siblings. Then it uses swap operations to move things correctly.
This patch instead promotes the smaller child upward at each level,
leaving a vacancy that sinks to a leaf, then places the removed element
there with a short sift-up to keep the heap balanced.
We can analytically compare this - for a sift-distance of d we can
reason about the number of operations to execute.
Before: 2d comparisons + 3d copies
After: d comparisons + d copies
After changing sift_down in this way, the replace operation can't simply
depend on it anymore, so I reimplemented it as a sequence of get + put.
This is technically correct but maybe not as efficient. However, I am
not sure that it matters, since I couldn't see any usage of the replace
operation in any hot path.
Performance: Profiling git rev-list --count on a 2.5M-commit monorepo
shows sift_down_root dropping from 8.2% to 0.4% of total runtime,
effectively eliminated as significant overhead.
Synthetic benchmark 10 rounds of 10M put+get cycles, CPU-pinned, median
of 3 runs, same compiler and Makefile flags.
Ascending keys (git's typical pattern -- parents have lower priority
than children):
queue width baseline patched speedup
10 4.32s 3.97s 1.09x
100 7.95s 6.49s 1.23x
1,000 11.30s 9.66s 1.17x
10,000 16.34s 14.15s 1.16x
100,000 21.43s 18.66s 1.15x
Descending keys (worst case — last element always sinks to leaf in both
approaches):
queue width baseline patched speedup
10 4.84s 4.78s 1.01x
100 9.43s 9.20s 1.03x
1,000 15.28s 14.71s 1.04x
10,000 23.61s 23.49s 1.01x
100,000 29.16s 28.22s 1.03x
No regressions in any scenario.
End-to-end benchmarks
All benchmarks use a benchmark setup of 1 warmup run followed by 10
timed runs. Each configuration is built from the same source tree and
tested on the same repo in alternating order.
linux kernel (1.4M commits) — range v5.0..v6.0 (311K commits):
Command baseline patched speedup
rev-list --count v5.0..v6.0 455ms 440ms 1.04x
I also ran it on git.git but did not see any performance diff at all,
due to the size and narrow DAG.
The improvement scales with DAG width: wider DAGs produce larger
priority queues, amplifying the per-level savings. In small or narrow
repositories the priority queues stay shallow and the sift-down cost is
already negligible, so the change is not noticeable.
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2132%2Fspkrka%2Fcascade-sift-down-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2132/spkrka/cascade-sift-down-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/2132
prio-queue.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/prio-queue.c b/prio-queue.c
index 9748528ce6..18005c43c4 100644
--- a/prio-queue.c
+++ b/prio-queue.c
@@ -62,17 +62,21 @@ static void sift_down_root(struct prio_queue *queue)
{
size_t ix, child;
- /* Push down the one at the root */
- for (ix = 0; ix * 2 + 1 < queue->nr; ix = child) {
- child = ix * 2 + 1; /* left */
+ for (ix = 0; (child = ix * 2 + 1) < queue->nr; ix = child) {
if (child + 1 < queue->nr &&
compare(queue, child, child + 1) >= 0)
child++; /* use right child */
+ queue->array[ix] = queue->array[child];
+ }
- if (compare(queue, ix, child) <= 0)
+ /* Place queue->array[queue->nr] (left by caller) and sift up. */
+ queue->array[ix] = queue->array[queue->nr];
+ while (ix) {
+ size_t parent = (ix - 1) / 2;
+ if (compare(queue, parent, ix) <= 0)
break;
-
- swap(queue, child, ix);
+ swap(queue, parent, ix);
+ ix = parent;
}
}
@@ -89,7 +93,6 @@ void *prio_queue_get(struct prio_queue *queue)
if (!--queue->nr)
return result;
- queue->array[0] = queue->array[queue->nr];
sift_down_root(queue);
return result;
}
@@ -111,8 +114,7 @@ void prio_queue_replace(struct prio_queue *queue, void *thing)
queue->array[queue->nr - 1].ctr = queue->insertion_ctr++;
queue->array[queue->nr - 1].data = thing;
} else {
- queue->array[0].ctr = queue->insertion_ctr++;
- queue->array[0].data = thing;
- sift_down_root(queue);
+ prio_queue_get(queue);
+ prio_queue_put(queue, thing);
}
}
base-commit: c69baaf57ba26cf117c2b6793802877f19738b0d
--
gitgitgadget
^ permalink raw reply related
* Draft of Git Rev News edition 135
From: Christian Couder @ 2026-05-31 11:01 UTC (permalink / raw)
To: git
Cc: Junio C Hamano, Jakub Narebski, Markus Jansen, Kaartic Sivaraam,
Štěpán Němec, Taylor Blau,
Johannes Schindelin, Derrick Stolee, Elijah Newren, Jeff King,
Matthias A.
Hi everyone,
A draft of a new Git Rev News edition is available here:
https://github.com/git/git.github.io/blob/master/rev_news/drafts/edition-135.md
Everyone is welcome to contribute in any section either by editing the
above page on GitHub and sending a pull request, or by commenting on
this GitHub issue:
https://github.com/git/git.github.io/issues/844
You can also reply to this email.
In general all kinds of contributions, for example proofreading,
suggestions for articles or links, help on the issues in GitHub,
volunteering for being interviewed and so on, are very much
appreciated.
I tried to Cc everyone who appears in this edition, but maybe I missed
some people, sorry about that.
Jakub, Markus, Kaartic and I plan to publish this edition on Tuesday
June 2nd, 2026.
Thanks,
Christian.
^ permalink raw reply
* Re: [PATCH v3 0/6] [RFC] diff: add diff.<driver>.process for external hunk providers
From: Junio C Hamano @ 2026-05-31 10:44 UTC (permalink / raw)
To: Michael Montalbo via GitGitGadget; +Cc: git, Michael Montalbo
In-Reply-To: <pull.2120.v3.git.1780087700.gitgitgadget@gmail.com>
"Michael Montalbo via GitGitGadget" <gitgitgadget@gmail.com> writes:
> Language-aware diff tools (e.g., Difftastic) and format-specific analyzers
> can produce better line matching than Git's builtin diff algorithm, but
> diff.<driver>.command replaces Git's output entirely, losing downstream
> features like word diff, function context, color, and blame.
This seems to break CI on Windows; take a look at
https://github.com/git/git/actions/runs/26709491830/job/78717295153
for an example.
Thanks.
^ permalink raw reply
* Re: doc: document '@' prefix for raw timestamps
From: Luna Schwalbe @ 2026-05-31 8:29 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Kristoffer Haugsbakk, git
In-Reply-To: <xmqqpl2de41m.fsf@gitster.g>
>> This was introduced in 116eb3ab (parse_date(): allow ancient
>> git-timestamp, 2012-02-02) and 2c733fb2 (parse_date(): '@' prefix
>> forces git-timestamp, 2012-02-02) to allow specifying "ancient"
>> timestamps (like 0 +0000) without conflicting with YYYYMMDD date
>> formats. I do not think neither commit added documentation for this
>> '@' prefix, and Documentation/date-formats would be an excellent
>> place to do so.
>>
>> Care to whip up a patch?
> It might look something like this.
Thanks! And sure, I'll try to submit something later; this will be my
first time using the send-mail workflow, I hope I don't mess anything up.
^ permalink raw reply
* Re: [PATCH] doc: add missing --message long option to merge docs
From: Brandon @ 2026-05-31 6:37 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Brandon Dong via GitGitGadget, git
In-Reply-To: <xmqqo6hyiz9g.fsf@gitster.g>
Junio C Hamano <gitster@pobox.com> writes:
> Hmph. This is still not consistent with "git merge -h" output has,
> which seems to accept --[no-]message as well.
>
> It is not exactly your fault, but there are a few options other than
> this one that support optional [no-] and they are not documented as
> such, even though they appear in "git merge -h". "git merge -m foo
> --no-message other" behaves as if "GIT_EDITOR=: git merge other" was
> run, it seems.
Looking at the code, I believe this might be intentional or maybe a
stylistic choice to document this way?
The overwhelming majority of long name flags have a [no-] variant as
it comes for free when defining a new option and otherwise requires
an explicit opt out (via PARSE_OPT_NONEG).
The -h output auto-generates the inclusion of [no-] but for the
handwritten docs, most examples I see where it's included are for
cases where the [no-] variant has some behavior nuance that needs to
be explained or it's for a bool-like flag. Most string-valued options
do not include mention of the [no-] variant and they share the
default behavior where passing the [no-] variant unsets the option.
For -m/--message in particular, none of the
git-commit/git-notes/git-svn/git-tag docs mention the --no variant
either and I think merge should be consistent with them.
^ permalink raw reply
* Re: [PATCH v2 2/2] status: improve rebase todo list parsing
From: Junio C Hamano @ 2026-05-31 0:46 UTC (permalink / raw)
To: Phillip Wood; +Cc: git, Elijah Newren, Patrick Steinhardt
In-Reply-To: <b80bc1e0a298e2773a2fdab3e73651d59b8d39b7.1777648598.git.phillip.wood@dunelm.org.uk>
Phillip Wood <phillip.wood123@gmail.com> writes:
> +static void abbrev_oid_in_line(struct repository *r,
> + struct strbuf *line, char **pp)
> +{
> ...
> + have_oid = !repo_get_oid(r, p, &oid);
> + *end_of_object_name = saved;
> + if (!have_oid)
> + goto out; /* object name was a label */
Can there be a label "deadbeef123" that is unrelated to an object whose
object name happens to abbreviate to "deadbeef123"?
> + case TODO_MERGE:
> + skip_dash_c(&p);
> + while (true) {
> + p += strspn(p, " \t");
> + if (!p[0] || (p[0] == '#' && (!p[1] || isspace(p[1]))))
> + break;
> + abbrev_oid_in_line(r, line, &p);
> + }
> + break;
What does this loop do? A "merge" command may look like "merge
[[-C|-c] <commit>] <label>", and we give each whitespace-separated
token to abbrev_oid_in_line()? Would "<label>" that is ambiguous
cause an issue? You may want to limit the scope of what the loop
does a bit, e.g., massage only the token after -C/-c, or something?
> + case TODO_FIXUP:
> + skip_dash_c(&p);
> + /* fallthrough */
> + case TODO_DROP:
> + case TODO_EDIT:
> + case TODO_PICK:
> + case TODO_RESET:
Doesn't RESET also take a <label>? And if it happens to be the same
as an abbreviated object name, e.g., "deadbeef123", of an unrelated
object, would wt-status say "reset deadbeef1", causing a mismatch?
If this is indeed an issue, would moving this to the "no-op" section
below, next to TODO_LABEL, solve it?
> + case TODO_REVERT:
> + case TODO_REWORD:
> + case TODO_SQUASH:
> + abbrev_oid_in_line(r, line, &p);
> + break;
> +
> + /*
> + * Avoid "default" and instead list all the other commands so
> + * that -Wswitch (which is included in -Wall) warns if a new
> + * command is added without handling it in this function.
> + */
> + case TODO_BREAK:
> + case TODO_EXEC:
> + case TODO_LABEL:
> + case TODO_NOOP:
> + case TODO_UPDATE_REF:
> + break;
> }
> - string_list_clear(&split, 0);
> +
> + return true;
> }
^ permalink raw reply
* Re: [PATCH] describe: fix --exclude, --match with --contains and --all
From: Junio C Hamano @ 2026-05-30 23:47 UTC (permalink / raw)
To: Jacob Keller; +Cc: git, Jacob Keller, Tuomas Ahola
In-Reply-To: <20260528232950.187002-2-jacob.e.keller@intel.com>
Jacob Keller <jacob.e.keller@intel.com> writes:
> From: Jacob Keller <jacob.keller@gmail.com>
>
> git describe --contains acts as a wrapper around git name-rev. When
> operating with --contains and --all, the --match and --exclude patterns
> are not properly forwarded to name-rev as --exclude and --refs options.
>
> This results in the command silently discarding match and exclude
> requests from the user when operating in --all mode.
>
> We could check and die() if the user provides --contains, --all, and
> --match/--exclude. However, its also straight forward to just pass the
> filters down to git name-rev.
>
> Notice that the documentation for --match and --exclude mention the
> --all mode. It explains that they operate on refs with the prefix
> refs/tags, and additionally refs/heads and refs/remotes when using
> --all.
>
> Fix the describe logic to pass the patterns down with the appropriate
> prefixes when --all is provided. This fixes the support to match the
> documented behavior.
>
> Add tests to check that this works as expected.
>
> Reported-by: Tuomas Ahola <taahol@utu.fi>
> Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
> ---
>
> I was looking into reviving the patch that just added a simple die() and
> realized that its actually pretty straight forward to just fix the support
> instead. I'm open to either route, if we think this support isn't
> necessary... I'm not sure if there are any gotchas or other issues with how
> I implemented this.
It is curious that this fails in some but not all CI jobs, and even
more curious that these failures look the same.
e.g., https://github.com/git/git/actions/runs/26671595367/job/78615760984#step:4:1984
+++ diff -u expect actual
--- expect 2026-05-30 02:21:23
+++ actual 2026-05-30 02:21:23
@@ -1 +1 @@
-branch_A
+remotes/origin/remote_branch_A
error: last command exited with $?=1
not ok 70 - describe --contains --all --exclude
#
# echo "branch_A" >expect &&
# tagged_commit=$(git rev-parse "refs/tags/A^0") &&
# git describe --contains --all --exclude="A" --exclude="c" --exclude="test*" $tagged_commit >actual &&
# test_cmp expect actual
Rings any bell?
^ permalink raw reply
* Re: [PATCH v1 3/4] environment: move 'trust_executable_bit' into repo_config_values
From: Junio C Hamano @ 2026-05-30 23:17 UTC (permalink / raw)
To: Tian Yuchen
Cc: git, christian.couder, ps, Ayush Chandekar, Olamide Caleb Bello
In-Reply-To: <20260530160520.77859-4-cat@malon.dev>
Tian Yuchen <cat@malon.dev> writes:
> diff --git a/apply.c b/apply.c
> index 249248d4f2..73ca9907f8 100644
> --- a/apply.c
> +++ b/apply.c
> @@ -3890,10 +3890,12 @@ static int check_preimage(struct apply_state *state,
> }
>
> if (!state->cached && !previous) {
> + struct repo_config_values *cfg = repo_config_values(the_repository);
> +
> if (*ce && !(*ce)->ce_mode)
> BUG("ce_mode == 0 for path '%s'", old_name);
>
> - if (trust_executable_bit || !S_ISREG(st->st_mode))
> + if (cfg->trust_executable_bit || !S_ISREG(st->st_mode))
> st_mode = ce_mode_from_stat(*ce, st->st_mode);
> else if (*ce)
> st_mode = (*ce)->ce_mode;
> diff --git a/read-cache.c b/read-cache.c
> index 54150fe756..18af533649 100644
> --- a/read-cache.c
> +++ b/read-cache.c
> @@ -204,10 +204,12 @@ void fill_stat_cache_info(struct index_state *istate, struct cache_entry *ce, st
>
> unsigned int ce_mode_from_stat(const struct cache_entry *ce, unsigned int mode)
> {
> + struct repo_config_values *cfg = repo_config_values(the_repository);
> +
> if (!has_symlinks && S_ISREG(mode) &&
> ce && S_ISLNK(ce->ce_mode))
> return ce->ce_mode;
> - if (!trust_executable_bit && S_ISREG(mode)) {
> + if (!cfg->trust_executable_bit && S_ISREG(mode)) {
> if (ce && S_ISREG(ce->ce_mode))
> return ce->ce_mode;
> return create_ce_mode(0666);
How hot are the code paths that call into this helper function? In
the original under some condition, it was possible to return without
even consulting the trust_executable_bit variable, but in the
updated code, the helper unconditionally makes a call to the
repo_config_values() helper function even before it knows it needs
to know the value of trust_executable_bit.
> @@ -217,11 +219,13 @@ unsigned int ce_mode_from_stat(const struct cache_entry *ce, unsigned int mode)
>
> static unsigned int st_mode_from_ce(const struct cache_entry *ce)
> {
> + struct repo_config_values *cfg = repo_config_values(the_repository);
> +
> switch (ce->ce_mode & S_IFMT) {
> case S_IFLNK:
> return has_symlinks ? S_IFLNK : (S_IFREG | 0644);
> case S_IFREG:
> - return (ce->ce_mode & (trust_executable_bit ? 0755 : 0644)) | S_IFREG;
> + return (ce->ce_mode & (cfg->trust_executable_bit ? 0755 : 0644)) | S_IFREG;
> case S_IFGITLINK:
> return S_IFDIR | 0755;
> case S_IFDIR:
Ditto.
> @@ -321,6 +325,7 @@ static int ce_modified_check_fs(struct index_state *istate,
> static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)
> {
> unsigned int changed = 0;
> + struct repo_config_values *cfg = repo_config_values(the_repository);
>
> if (ce->ce_flags & CE_REMOVE)
> return MODE_CHANGED | DATA_CHANGED | TYPE_CHANGED;
> @@ -331,7 +336,7 @@ static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)
> /* We consider only the owner x bit to be relevant for
> * "mode changes"
> */
> - if (trust_executable_bit &&
> + if (cfg->trust_executable_bit &&
> (0100 & (ce->ce_mode ^ st->st_mode)))
> changed |= MODE_CHANGED;
> break;
Ditto.
> @@ -732,6 +737,8 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
> (intent_only ? ADD_CACHE_NEW_ONLY : 0));
> unsigned hash_flags = pretend ? 0 : INDEX_WRITE_OBJECT;
>
> + struct repo_config_values *cfg = repo_config_values(the_repository);
> +
Lose the excess blank line before the new declaration.
> if (flags & ADD_CACHE_RENORMALIZE)
> hash_flags |= INDEX_RENORMALIZE;
>
> @@ -752,7 +759,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
> ce->ce_flags |= CE_INTENT_TO_ADD;
>
>
> - if (trust_executable_bit && has_symlinks) {
> + if (cfg->trust_executable_bit && has_symlinks) {
> ce->ce_mode = create_ce_mode(st_mode);
> } else {
> /* If there is an existing entry, pick the mode bits and type
Almost all of these places that care about trust_executable_bit also
cares about has_symlinks. I wonder if they should be converted to
repo-local settings in the same series.
^ permalink raw reply
* Re: [PATCH 4/4] doc: replay: move “default” to the right-hand-side
From: Junio C Hamano @ 2026-05-30 22:37 UTC (permalink / raw)
To: kristofferhaugsbakk; +Cc: git, Kristoffer Haugsbakk, Siddharth Asthana
In-Reply-To: <default_RHS.70d@msgid.xyz>
kristofferhaugsbakk@fastmail.com writes:
> -`update` (default);; Update refs directly using an atomic transaction.
> +`update`;; (default) Update refs directly using an atomic transaction.
This looks sensible. Nice.
> All refs are updated or none are (all-or-nothing behavior).
> `print`;; Output update-ref commands for pipeline use. This is the
> traditional behavior where output can be piped to `git update-ref --stdin`.
^ permalink raw reply
* Re: [PATCH 3/4] doc: replay: use a nested definition list
From: Junio C Hamano @ 2026-05-30 22:37 UTC (permalink / raw)
To: kristofferhaugsbakk; +Cc: git, Kristoffer Haugsbakk, Siddharth Asthana
In-Reply-To: <--ref-action_definition_list.70c@msgid.xyz>
kristofferhaugsbakk@fastmail.com writes:
> From: Kristoffer Haugsbakk <code@khaugsbakk.name>
>
> This bullet list for `--ref-action` introduces a term with a colon.
> This is exactly what a definition list is, structurally. Let’s be
> sylistically consistent and use the definition list markup construct.
Makes sense.
> --
> - * `update` (default): Update refs directly using an atomic transaction.
> - All refs are updated or none are (all-or-nothing behavior).
> - * `print`: Output update-ref commands for pipeline use. This is the
> - traditional behavior where output can be piped to `git update-ref --stdin`.
> +`update` (default);; Update refs directly using an atomic transaction.
> + All refs are updated or none are (all-or-nothing behavior).
> +`print`;; Output update-ref commands for pipeline use. This is the
> + traditional behavior where output can be piped to `git update-ref --stdin`.
> --
> +
The transition from a bulleted list to a nested definition list
(`;;`) for the `--ref-action` modes indeed makes the document
structure much cleaner.
> The default mode can be configured via the `replay.refAction` configuration variable.
^ permalink raw reply
* Re: [PATCH 2/4] doc: replay: simplify replay.refAction description
From: Junio C Hamano @ 2026-05-30 22:37 UTC (permalink / raw)
To: kristofferhaugsbakk; +Cc: git, Kristoffer Haugsbakk, Siddharth Asthana
In-Reply-To: <simplify_replay.refAction.70b@msgid.xyz>
kristofferhaugsbakk@fastmail.com writes:
> replay.refAction::
> - Specifies the default mode for handling reference updates in
> - `git replay`. The value can be:
> -+
> ---
> - * `update`: Update refs directly using an atomic transaction (default behavior).
> - * `print`: Output update-ref commands for pipeline use.
> ---
> -+
> -This setting can be overridden with the `--ref-action` command-line option.
> -When not configured, `git replay` defaults to `update` mode.
> + Specifies the default mode for handling reference updates. Either `update` or `print`.
> +ifdef::git-replay[]
> +See `--ref-action`.
> +endif::git-replay[]
> +ifndef::git-replay[]
> +See `--ref-action` for linkgit:git-replay[1] for details.
> +endif::git-replay[]
This makes it a bit roundabout for "git config --help" readers who
wanted to figure out what value to set to the configuration
variable, because the valid choices are no longer listed here.
Finding `--ref-action=<mode>` and its description in the other page
is straight-forward, so it may not be too bad, though.
> diff --git a/Documentation/git-replay.adoc b/Documentation/git-replay.adoc
> index f9ca2db2833..4de85088d6c 100644
> --- a/Documentation/git-replay.adoc
> +++ b/Documentation/git-replay.adoc
> @@ -211,6 +211,7 @@ to use bare commit IDs instead of branch names.
>
> CONFIGURATION
> -------------
> +:git-replay: 1
> include::config/replay.adoc[]
The use of conditional attributes (`ifdef::git-replay[]`) is a neat
and standard way to tailor the description depending on whether it
is read as part of `git-config(1)` or `git-replay(1)`. It correctly
points the reader to `--ref-action` in the latter case, and provides
a full `linkgit` reference in the former. Clean and correct.
^ permalink raw reply
* Re: [PATCH 2/4] doc: replay: simplify replay.refAction description
From: Junio C Hamano @ 2026-05-30 22:29 UTC (permalink / raw)
To: kristofferhaugsbakk; +Cc: git, Kristoffer Haugsbakk, Siddharth Asthana
In-Reply-To: <simplify_replay.refAction.70b@msgid.xyz>
kristofferhaugsbakk@fastmail.com writes:
> replay.refAction::
> - Specifies the default mode for handling reference updates in
> - `git replay`. The value can be:
> -+
> ---
> - * `update`: Update refs directly using an atomic transaction (default behavior).
> - * `print`: Output update-ref commands for pipeline use.
> ---
> -+
> -This setting can be overridden with the `--ref-action` command-line option.
> -When not configured, `git replay` defaults to `update` mode.
> + Specifies the default mode for handling reference updates. Either `update` or `print`.
> +ifdef::git-replay[]
> +See `--ref-action`.
> +endif::git-replay[]
> +ifndef::git-replay[]
> +See `--ref-action` for linkgit:git-replay[1] for details.
> +endif::git-replay[]
This makes it a bit roundabout for "git config --help" readers who
wanted to figure out what value to set to the configuration
variable, because the valid choices are no longer listed here.
Finding `--ref-action=<mode>` and its description in the other page
is straight-forward, so it may not be too bad, though.
> diff --git a/Documentation/git-replay.adoc b/Documentation/git-replay.adoc
> index f9ca2db2833..4de85088d6c 100644
> --- a/Documentation/git-replay.adoc
> +++ b/Documentation/git-replay.adoc
> @@ -211,6 +211,7 @@ to use bare commit IDs instead of branch names.
>
> CONFIGURATION
> -------------
> +:git-replay: 1
> include::config/replay.adoc[]
The use of conditional attributes (`ifdef::git-replay[]`) is a neat
and standard way to tailor the description depending on whether it
is read as part of `git-config(1)` or `git-replay(1)`. It correctly
points the reader to `--ref-action` in the latter case, and provides
a full `linkgit` reference in the former. Clean and correct.
^ permalink raw reply
* Re: [PATCH 1/4] doc: link to config for git-replay(1)
From: Junio C Hamano @ 2026-05-30 22:18 UTC (permalink / raw)
To: kristofferhaugsbakk; +Cc: git, Kristoffer Haugsbakk, Siddharth Asthana
In-Reply-To: <doc_replay_link_config.70a@msgid.xyz>
kristofferhaugsbakk@fastmail.com writes:
> From: Kristoffer Haugsbakk <code@khaugsbakk.name>
>
> This config doc was added in 336ac90c (replay: add replay.refAction
> config option, 2025-11-06) but never included anywhere. Include it in
> git-replay(1) and git-config(1).
>
> Signed-off-by: Kristoffer Haugsbakk <code@khaugsbakk.name>
> ---
> Documentation/config.adoc | 2 ++
> Documentation/git-replay.adoc | 4 ++++
> 2 files changed, 6 insertions(+)
It is always nice to see documentation gaps filled.
The `replay.refAction` configuration variable was indeed left
dangling without a proper link from the main command documentation,
which is embarrassing. I wonder if we can add simple "doc-lint"
rule or two to prevent similar mistakes from happening again?
> diff --git a/Documentation/config.adoc b/Documentation/config.adoc
> index 62eebe7c545..51fabecb9b0 100644
> --- a/Documentation/config.adoc
> +++ b/Documentation/config.adoc
> @@ -511,6 +511,8 @@ include::config/remotes.adoc[]
>
> include::config/repack.adoc[]
>
> +include::config/replay.adoc[]
> +
> include::config/rerere.adoc[]
>
> include::config/revert.adoc[]
Placing `include::config/replay.adoc[]` in `config.adoc`
alphabetically between `repack` and `rerere` is correct, as the list
is alphabetical.
> diff --git a/Documentation/git-replay.adoc b/Documentation/git-replay.adoc
> index a32f72aead3..f9ca2db2833 100644
> --- a/Documentation/git-replay.adoc
> +++ b/Documentation/git-replay.adoc
> @@ -209,6 +209,10 @@ This replays the range `aabbcc..ddeeff` onto commit `112233` and updates
> `refs/heads/mybranch` to point at the result. This can be useful when you want
> to use bare commit IDs instead of branch names.
>
> +CONFIGURATION
> +-------------
> +include::config/replay.adoc[]
> +
Adding the `CONFIGURATION` section near the end of `git-replay.adoc`
is also the standard way we expose configuration variables to the
command's manual page.
Looking good.
> GIT
> ---
> Part of the linkgit:git[1] suite
^ permalink raw reply
* Re: [PATCH 0/4] doc: replay: fix config link
From: Junio C Hamano @ 2026-05-30 22:18 UTC (permalink / raw)
To: kristofferhaugsbakk; +Cc: git, Kristoffer Haugsbakk, Siddharth Asthana
In-Reply-To: <CV_doc_replay_config.709@msgid.xyz>
kristofferhaugsbakk@fastmail.com writes:
> From: Kristoffer Haugsbakk <code@khaugsbakk.name>
>
> [1/4] doc: link to config for git-replay(1)
> [2/4] doc: replay: simplify replay.refAction description
> [3/4] doc: replay: use a nested definition list
> [4/4] doc: replay: move “default” to the right-hand-side
It is always nice to see documentation gaps filled.
^ permalink raw reply
* Re: [PATCH v1 4/4] read-cache: pass 'istate' to stat/mode helper functions
From: Christian Couder @ 2026-05-30 18:14 UTC (permalink / raw)
To: Tian Yuchen; +Cc: git, ps, Ayush Chandekar, Olamide Caleb Bello
In-Reply-To: <20260530160520.77859-5-cat@malon.dev>
On Sat, May 30, 2026 at 6:05 PM Tian Yuchen <cat@malon.dev> wrote:
>
> In the previous commit, the gloabl 'trust_executable_bit' was
s/gloabl/global/
> migrated into 'repo_config_values', but low-level helpers in
> read-cache.c still relied on 'the_repository' to access it.
>
> Refactor the signatures of ce_mode_from_stat(), st_mode_from_ce(),
> fake_lstat(), and check_removed() to accept a 'struct
> index_state *istate'. This allows these functions to retrieve the
> repository context via 'istate->repo'.
The cover letter contains:
"In other words, this series of patches is laying the groundwork for
the eventual elimination of 'the_repository'."
but I think it would be also interesting to have something similar
here, as this is especially relevant to this commit.
For example maybe add something like "which will help with removing
'the_repository' in the future" to the last sentence?
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox