summaryrefslogtreecommitdiff
AgeCommit message (Collapse)AuthorFilesLines
2026-06-05docs: fix typosTuomas Ahola5-5/+5
Fix some typos and grammar errors in comments and documentation files. Signed-off-by: Tuomas Ahola <taahol@utu.fi> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05Merge branch 'ps/odb-source-loose' into ps/odb-source-packedJunio C Hamano15-870/+973
* ps/odb-source-loose: odb/source-loose: drop pointer to the "files" source odb/source-loose: stub out remaining callbacks odb/source-loose: wire up `write_object_stream()` callback object-file: refactor writing objects to use loose source odb/source-loose: wire up `write_object()` callback loose: refactor object map to operate on `struct odb_source_loose` odb/source-loose: wire up `freshen_object()` callback odb/source-loose: drop `odb_source_loose_has_object()` odb/source-loose: wire up `count_objects()` callback odb/source-loose: wire up `find_abbrev_len()` callback odb/source-loose: wire up `for_each_object()` callback odb/source-loose: wire up `read_object_stream()` callback odb/source-loose: wire up `read_object_info()` callback odb/source-loose: wire up `close()` callback odb/source-loose: wire up `reprepare()` callback odb/source-loose: start converting to a proper `struct odb_source` odb/source-loose: store pointer to "files" instead of generic source odb/source-loose: move loose source into "odb/" subsystem
2026-06-05setup: construct object database in `apply_repository_format()`Patrick Steinhardt3-27/+32
With the preceding changes we now always construct the repository's object database before applying the repository format. Remove this duplication by constructing it in `apply_repository_format()` instead. Note that we create the object database _after_ having set up the repository's hash algorithm, but _before_ setting the compat hash algorithm. This is intentional: - Constructing the object database may require knowledge of its intended object format. - Setting up the compatibility hash requires the object database to be initialized already, because we immediately read the loose object map. The first point is sensible, the second maybe a little less so. Ideally, it should be the responsibility of the object database itself to initialize any data structures required for the compatibility hash. But this would require further changes, so this is kept as-is for now. Further note that this requires us to move handling of the environment variables GIT_OBJECT_DIRECTORY and GIT_ALTERNATE_OBJECT_DIRECTORIES into the repository format, as well. This allows the caller more flexibility around whether or not those environment variables are being honored, as we want to respect them in "setup.c", but not in "repository.c". Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05repository: stop reading loose object map twice on repo initPatrick Steinhardt1-3/+0
When initializing a repository via `repo_init()` we end up reading the loose object map twice: - `apply_repository_format()` calls `repo_set_compat_hash_algo()`, which in turn calls `repo_read_loose_object_map()` if we have a compatibility hash configured. - `repo_init()` calls `repo_read_loose_object_map()` directly a second time. Drop the second read of the loose object map in `repo_init()`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05setup: stop initializing object database without repositoryPatrick Steinhardt2-6/+5
The function `setup_git_directory_gently()` is responsible for discovering and setting up a Git repository based on various environment variables and the current working directory. The result is thus a fully usable Git repository. One oddity of this function is that we may set up the object database even in the case where we don't have a repository, namely in the case where the `GIT_DIR_EXPLICIT` environment variable is set but points to a non-existent repository. If so, we call `setup_git_env_internal()` with the value of the environment variable so that the repository's Git directory is configured, even if it points to a non-existent directory. Historically though, this function didn't only configure the repository, but also initialized the object database. We retained this behaviour from a preceding commit, even though it really doesn't make much sense in the first place -- there is no repository, so we don't have an object database either. There seemingly isn't much of a reason to construct the object database, as we typically won't try to read objects when we don't have an object database. There's one exception though: git-index-pack(1) may run outside of a repository, which can be used to perform consistency checks for a packfile. The code path is _almost_ working: we already know to call `parse_object_buffer()`, which can read objects without an object database being available. And that works for all object types except for commits, because `parse_commit_buffer()` calls `parse_commit_graph()`, and that function doesn't handle the case where we don't have an object database. Fix this instance to check for the object database instead of checking for the Git directory having been initialized. With this fixed, we can now stop constructing an object database completely. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05setup: stop creating the object database in `setup_git_env()`Patrick Steinhardt1-11/+26
In the preceding commit we have stopped creating the object database in `repo_set_gitdir()`. But the logic is still somewhat confusing as we still end up creating it conditionally in `setup_git_dir()`, which is called multiple times. Drop the conditional logic and instead create the object database in all places where we have discovered and configured a repository. This leads to even more duplication than we already had in the preceding commit, but an alert reader may notice that we now (almost) always call `odb_new()` directly before having called `apply_repository_format()`. The only exception to this is `setup_git_directory_gently()`, where we also call the function when _not_ applying the repository format. This will be fixed in the next commit, and once that's done we can then unify creation of the object database into `apply_repository_format()`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05repository: stop initializing the object database in `repo_set_gitdir()`Patrick Steinhardt3-12/+6
The function `repo_set_gitdir()` obviously sets the Git directory for a given repository. Less obviously though, the function also configures a couple of auxiliary settings. One such thing is that we create the object database in this function. This logic only happens conditionally though, as `set_git_dir()` may be called multiple times during repository setup, and we don't want to create the object database multiple times. This is somewhat tangled and hard to follow. Remove the logic from `repo_set_gitdir()` and instead initialize the object database outside of it. This leads to some duplication right now, but that duplication will be removed in a subsequent step where we will start initializing the object database as part of applying the repo's format. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05setup: deduplicate logic to apply repository formatPatrick Steinhardt3-63/+71
After having discovered the repository format we then apply it to the repository so that it knows to use the proper repository extensions. The logic to apply the format is duplicated across three callsites, which makes it rather painfull to add new extensions. Introduce a new function `apply_repository_format()` that takes a repo and applies a given format to it and adapt all callsites to use it. This function is also the new caller of `verify_repository_format()` so that we can ensure that we never apply an invalid repository format. The verification we have in `read_and_verify_repository_format()` is thus redundant now and dropped. Rename `read_and_verify_repository_format()` accordingly. While at it, also rename `check_repository_format()` to clarify that it doesn't only _check_ the format, but that it also applies it. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05setup: drop `setup_git_env()`Patrick Steinhardt3-14/+4
The `setup_git_env()` function is a trivial wrapper around `setup_git_env_internal()` and has a single call site only. Drop the function. While at it, drop stale documentation in "environment.h" that points to this function, even though it hasn't been exposed to callers outside of "setup.c" since 43ad1047a9 (setup: stop using `the_repository` in `setup_git_env()`, 2026-03-27) anymore. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05t0001: plug test gaps for git-init(1) with GIT_OBJECT_DIRECTORYPatrick Steinhardt1-0/+10
In subsequent commits we'll rework how we set up the repository. This is a somewhat intricate and thus fragile sequence; there's many things that can go subtly wrong, and there are lots of interesting interactions that one can discover. One such discovered edge case was the interaction between git-init(1) and the "GIT_OBJECT_DIRECTORY" environment variable. When set, the behaviour is that the object directory should be created at the path that the variable points to. This behaviour is documented as such in its man page: If the object storage directory is specified via the GIT_OBJECT_DIRECTORY environment variable then the sha1 directories are created underneath; otherwise, the default $GIT_DIR/objects directory is used. Curiously enough though we don't seem to have any tests that exercise this directly, and thus a subsequent commit inadvertently would have broken this expectation. Plug this test gap. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05t: let prove fail when parsing invalid TAP outputPatrick Steinhardt1-0/+6
To make the result of our tests accessible we use the TAP protocol. This protocol is parsed by either prove or by Meson. Unfortunately, these two tools differ when it comes to their strictness when parsing the protocol: - Prove by default happily accepts lines not specified by the protocol. - Meson will also accept such lines, but prints a big and ugly warning message. We have fixed our test suite in the past to not print invalid TAP lines anymore via b1dc2e796e (Merge branch 'ps/meson-tap-parse', 2025-06-17). But as none of our tools perform a strict check it's still possible for broken tests to sneak back in, like for example in 362f69547f (Merge branch 'ps/t1006-tap-fix', 2025-07-16). This doesn't hurt at all when using prove, but it's quite annoying when using Meson due to the generated warnings. Unfortunately, there doesn't seem to be a portable way to make all tools complain about violations of the TAP format. The TAP 14 specification has added pragmas to the protocol that would allow us to say `pragma +strict`, and the effect of that would be to treat invalid TAP lines as a test failure. But the release of TAP 14 is still rather recent, and Test-Harness for example only gained support for it in version 3.48, which was released in 2023. In fact though, this pragma was already introduced as an inofficial extension of the TAP protocol with Test-Harness 3.10, released in 2008. So while not all tools understand the pragma, at least prove does for a long time. Unconditionally enable the pragma when using prove so that we'll detect tests that emit broken TAP output right away. This would have detected the issues fixed in preceding commits: $ prove t7527-builtin-fsmonitor.sh t7527-builtin-fsmonitor.sh .. All 69 subtests passed (less 6 skipped subtests: 63 okay) Test Summary Report ------------------- t7527-builtin-fsmonitor.sh (Wstat: 0 Tests: 69 Failed: 0) Parse errors: Unknown TAP token: "Initialized empty Git repository in /tmp/git/test_fsmonitor_smoke/.git/" Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05t/lib-git-p4: silence output when killing p4d and its watchdogPatrick Steinhardt1-2/+2
When stopping the p4d watchdog process via "kill -9", the shell may print a job-control notification like: ./test-lib.sh: line 1269: 57960 Killed: 9 while true; do if test $nr_tries_left -eq 0; then kill -9 $p4d_pid; exit 1; fi; sleep 1; nr_tries_left=$(($nr_tries_left - 1)); done 2> /dev/null 4>&2 (wd: ~) This message is printed asynchronously by the shell when it reaps the process. While harmless right now, this will cause breakage once we enable strict parsing of the TAP protocol in a subsequent commit. Fix this by using `wait` so that we can synchronously reap the watchdog process and swallow the diagnostic. While at it, deduplicate the logic we have in `stop_p4d_and_watchdog ()` and `stop_and_cleanup_p4d ()`. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05t/test-lib: silence EBUSY errors on Windows during test cleanupPatrick Steinhardt1-2/+2
When tests have finished we clean up the trash directory via `rm -rf`. On Windows this can fail with EBUSY in cases where a process still holds some of the files open, for example when we have spawned a daemonized process that wasn't properly terminated. We thus retry several times, but every failure will result in error messages being printed, and that in turn breaks the TAP output format. One such case where this is causing issues is in t921x, which contains tests related to Scalar. Some tests spawn the fsmonitor daemon, and we never properly terminate it. The obvious fix would be to ensure that we never leak any processes, but that gets ugly fast. Instead, let's work around the issue by silencing error messages printed by the `rm -rf` calls. We already know to print an error when the retry loop fails, so we don't loose much. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05t7810: turn MB_REGEX check into a lazy prereqPatrick Steinhardt1-2/+3
In t7810 we verify whether the system has proper multibyte locale support by executing `test-tool regex` with a unicode character. When this check fails though we'll output an error that breaks the TAP format. Fix this issue by turning the logic into a lazy prerequisite. Reported-by: Jeff King <peff@peff.net> Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05t7527: fix broken TAP outputPatrick Steinhardt1-3/+4
Before running the tests in t7527 we first verify whether the fsmonitor even works, which seems to depend on the actual filesystem that is in use. The verification executes outside of any prerequisite or test body, so its stdout/stderr is not being redirected. The consequence of this is that any command that prints to stdout/stderr may break the TAP specification by printing invalid lines. And in fact we already do that, as git-init(1) prints the path to the created Git repository by default. Fix this issue by moving the logic into a lazy prerequisite. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05ci: unify Linux images across GitLab and GitHubPatrick Steinhardt2-2/+2
The image for the "linux-breaking-changes" job has drifted apart across GitHub and GitLab. Adapt it to use "ubuntu:rolling" on both systems. With this change there's only one difference remaining: GitHub uses "ubuntu:focal" for the "linux32" job while GitLab uses "ubuntu:20.04". These are different names for the same image, so there is no actual difference here. Adjust GitHub to use the "20.04" tag -- this matches all the other jobs which use version numbers, and you don't have to learn Ubuntu's release names by heart. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05gitlab-ci: add missing Linux jobsPatrick Steinhardt2-1/+7
The GitLab CI definitions are missing jobs for AlmaLinux and Debian, both of which exist in GitHub Workflows. Plug this gap. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-05gitlab-ci: rearrange Linux jobs to match GitHub's orderPatrick Steinhardt1-7/+8
Rearrange the order of Linux jobs that we have defined in GitLab CI so that it matches the order on GitHub's side. This makes it easier to compare whether the list of jobs actually matches on both sides. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-03config: improve diagnostic for "set" with missing valueHarald Nordgren2-1/+87
"git config set pull.rebase=false" currently fails with "wrong number of arguments", and the implicit form "git config pull.rebase=false" fails with "invalid key". Neither points at the real problem: the value is missing. Report that directly, and when the argument has the shape "<valid-key>=<value>", also suggest the split form: $ git config set pull.rebase=false error: missing value to set to the variable 'pull.rebase=false' hint: did you mean "git config set pull.rebase false"? When the prefix before "=" is not a valid key, drop the hint: $ git config set foo=bar error: missing value to set to a variable with an invalid name 'foo=bar' Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-03config: add git_config_key_is_valid() for quiet validationHarald Nordgren2-9/+31
Move the body of git_config_parse_key() into a static helper do_parse_config_key() that takes a "quiet" flag and treats store_key as optional. git_config_parse_key() becomes a thin wrapper. Add git_config_key_is_valid() for callers that only need to know whether a key is well-formed. Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-03revision.c: implement --max-count-oldestMirko Faina4-4/+154
"--max-count" is a commit limiting option and sets a maximum amount of commits to be shown. If a user wants to see only the first N commits of the history (the oldest commits) they'd have to do something like git log $(git rev-list HEAD | tail -n N | head -n 1) This is not very user-friendly. Teach get_revision() the --max-count-oldest option. Signed-off-by: Mirko Faina <mroik@delayed.space> [jc: fixed up t4202 <xmqq7boy4o05.fsf@gitster.g>] Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-03environment: move "warn_on_object_refname_ambiguity" into `struct ↵Olamide Caleb Bello7-15/+20
repo_config_values` The `core.warnAmbiguousRefs` configuration was previously stored in a global `int` variable, making it shared across repository instances and risking cross‑repository state leakage. Store it instead in `repo_config_values`, where eagerly‑parsed repository configuration lives. This option is parsed eagerly because ambiguity warnings influence how users interpret object references in many commands; a lazy parse could cause these warnings to behave inconsistently or to appear for the wrong repository, confusing users and hindering libification. This preserves the existing behavior while tying the value to the repository from which it was read, avoiding cross‑repository state leakage and continuing the effort to reduce reliance on global configuration state. Update all references to use `repo_config_values()`. Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com> Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-03environment: move "sparse_expect_files_outside_of_patterns" into `struct ↵Olamide Caleb Bello3-5/+8
repo_config_values` The `core.sparseCheckoutExpectFilesOutsideOfPatterns` configuration was previously stored in a global `int` variable, making it shared across repository instances and risking cross‑repository state leakage. Store it instead in `repo_config_values`, where eagerly‑parsed repository configuration lives. This option is parsed eagerly because it controls how sparse‑checkout paths are interpreted – a fundamental behavior that many commands rely on; a lazy parse could cause inconsistent sparse‑checkout handling and complicate libification. This preserves the existing behavior while tying the value to the repository from which it was read, avoiding cross‑repository state leakage and continuing the effort to reduce reliance on global configuration state. Update all references to use `repo_config_values()`. Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com> Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-03environment: move "core_sparse_checkout_cone" into `struct repo_config_values`Olamide Caleb Bello6-21/+29
The `core.sparseCheckoutCone` configuration was previously stored in an uninitialized global `int` variable, risking cross‑repository state leakage. Move it into `repo_config_values`, where eagerly‑parsed repository configuration lives. `core.sparseCheckoutCone` is parsed eagerly because it determines the fundamental sparse‑checkout mode and is consulted very early during repository setup; a lazy parse could leave the sparse‑checkout state undefined and complicate libification. This preserves the existing behavior while tying the value to the repository from which it was read, avoiding cross‑ repository state leakage and continuing the effort to reduce reliance on global configuration state. Update all references to use `repo_config_values()`. Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com> Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-03environment: move "precomposed_unicode" into `struct repo_config_values`Olamide Caleb Bello4-11/+18
The `core.precomposeunicode` configuration is currently stored in the global variable `precomposed_unicode`, which makes it shared across repository instances within a single process. Store it instead in `repo_config_values`, where eagerly‑parsed repository configuration lives. `core.precomposeunicode` is parsed eagerly because it controls Unicode path normalization on macOS, a fundamental filesystem‑level behavior that many operations depend on; a lazy parse could lead to inconsistent results and hamper libification. This preserves the existing behavior while tying the value to the repository from which it was read, avoiding cross‑ repository state leakage and continuing the effort to reduce reliance on global configuration state. Update all references to use `repo_config_values()`. Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com> Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-03environment: move "pack_compression_level" into `struct repo_config_values`Olamide Caleb Bello5-15/+23
The `pack_compression_level` configuration is currently stored in the global variable `pack_compression_level`, which makes it shared across repository instances within a single process. Store it instead in `repo_config_values`, where eagerly‑parsed repository configuration lives. `pack_compression_level` is parsed eagerly because it influences packfile compression, a core operation where a lazy parse could cause inconsistent behavior and hamper libification. This preserves the existing eager‑parsing behavior while tying the value to the repository from which it was read, avoiding cross‑repository state leakage and continuing the effort to reduce reliance on global configuration state. Update all references to use `repo_config_values()`. Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com> Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-03environment: move `zlib_compression_level` into `struct repo_config_values`Olamide Caleb Bello6-8/+12
The `zlib_compression_level` configuration is currently stored in the global variable `zlib_compression_level`, which makes it shared across repository instances within a single process. Store it instead in `repo_config_values`, where eagerly‑parsed repository configuration lives. `zlib_compression_level` is parsed eagerly because it determines compression behaviour for objects and packs – core operations where a lazy parse could lead to unpredictable results and hinder libification. This preserves the existing eager‑parsing behavior while tying the value to the repository it was read from, avoiding cross‑repository state leakage and continuing the effort to reduce reliance on global configuration state. Update all references to use `repo_config_values()`. Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com> Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-03environment: move "check_stat" into `struct repo_config_values`Olamide Caleb Bello4-10/+11
The `core.checkstat` configuration is currently stored in the global variable `check_stat`, which makes it shared across repository instances within a single process. Store it instead in `repo_config_values`, where eagerly‑parsed repository configuration lives. `core.checkstat` is parsed eagerly because it controls how `match_stat_data()` and related functions decide file freshness; a lazy parse could lead to unexpected behavior or complicate libification. This preserves the existing eager‑parsing behavior while tying the value to the repository it was read from, avoiding cross‑repository state leakage, and continuing the effort to reduce reliance on global configuration state. Update all references to use `repo_config_values()`. Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: Usman Akinyemi <usmanakinyemi202@gmail.com> Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-03environment: move "trust_ctime" into `struct repo_config_values`Olamide Caleb Bello3-5/+7
The `core.trustctime` configuration is currently stored in the global variable `trust_ctime`, which makes it shared across repository instances in a single process. Store it instead in `repo_config_values`, where eagerly‑parsed repository configuration lives. `core.trustctime` is parsed eagerly because it is used in low‑level stat‑matching functions (`match_stat_data()`), where a lazy parse could cause unexpected fatal errors, result in a performance regression and complicate libification efforts. This preserves that behavior while tying the value to the repository from which it was read, avoiding cross‑repository state leakage and continuing the effort to reduce reliance on global configuration state. Update all references to use repo_config_values(). Mentored-by: Christian Couder <christian.couder@gmail.com> Signed-off-by: Olamide Caleb Bello <belkid98@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-02git-gui: add gui and pick as explicit subcommandsMark Levedahl1-4/+21
git-gui accepts subcommands blame | browser | citool, and assumes the subcommand is 'gui' if none is actually given, But, git-gui also has a repository picker (choose_repository::pick) that can create a new repository + worktree, or choose an existing one, switch to that, and the run the gui. The user has no direct control over invoking the picker, instead the picker is triggered by failure in the repository / worktree discovery process: this includes being started in a directory not controlled by git, which is probably the intended use case. The picker can appear when the user has no intention of creating a new worktree, and the user cannot use the picker to create a new worktree inside another. So, add two explicit subcommands: gui - Run the gui if repository/worktree discovery succeeds, or die with an error message, but never run the picker. pick - First run the picker, regardless, then start the gui in the chosen worktree. Nothing in this changes the prior behavior, the alternates above must be explicitly selected to see any change. Signed-off-by: Mark Levedahl <mlevedahl@gmail.com> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
2026-06-02git-gui: check browser/blame arguments carefullyMark Levedahl1-59/+63
git gui offers two related commands, browser and blame, that provide graphical interfaces driven by git ls-tree and git blame. As such, the arguments to git-gui need to satisfy those two git commands. But, git-gui does not assure this leading to confusing or incorrect results. For instance 'git browser <non-existent path>' shows a blank browser window rather than error message. Also, commit 3e45ee1ef2 ("git-gui: Smarter command line parsing for browser, blame", 2007-05-08) implemented code to allow giving path before rev on the command line, and unconditionally uses the worktree to disambiguate. As a result, the following command run in a current git-gui checkout of the master branch shows the master branch version of blame.tcl, when none should be shown as that file does not exist in gitgui-0.6.0. git gui blame lib/blame.tcl gitgui-0.6.0 This 'file before rev' feature in git-gui mirrors ideas considered when git's user interface was very young, but no such feature is documented for any git command. Rather than try to fix an idea git itself rejected, let's just remove this broken and hopefully unused feature. git-gui browser|blame both accept 'rev' and 'path' as command line arguments. rev defaults to 'HEAD' if not given, while path must be given. path names a directory tree to ls-tree or a file to blame. path must exist in rev for ls-tree and for blame. In addition git blame will include uncommitted changes from the worktree file at 'path' if rev is not given (thus defaulting to HEAD), but still requires that the file exists in HEAD. So, let's clean up the parser to check that the arguments are usable. - give a full synopsis, including '--' that may be used to separate rev and path. (as path is the required final arg, -- gives no extra info) - explicitly check the number of arguments - use rev-parse to assure a user supplied rev is valid - use ls-tree to assure that path exists in rev - for blame only, with no rev given and a worktree existing, also assure that path points to a file in the worktree With these changes, error messages are thrown by the parser if the path or rev are not known: no blank or erroneous displays are created. Also, this avoids accessing the worktree except in the specific use case supported by blame / git-blame, meaning browser|blame now also work without a worktree. Signed-off-by: Mark Levedahl <mlevedahl@gmail.com> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
2026-06-02git-gui: allow specifying path '.' to the browserMark Levedahl1-1/+5
Invoking "git-gui browser rev ." should show the file browser for the commitish rev, starting at the current directory. When the current directory is the working tree root, this errors out in normalize_relpath because the '.' is removed, yielding an empty list as argument to [file join ...]. git ls-tree (underlying the browser) accepts '.', so use that as the value when in the root. Signed-off-by: Mark Levedahl <mlevedahl@gmail.com> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
2026-06-02git-gui: try harder to find worktree from gitdirMark Levedahl1-0/+38
git-gui, since 87cd09f43e ("git-gui: work from the .git dir", 2010-01-23), has had the intent to allow starting from inside a repository, then switching to the parent directory if that is a valid worktree. This certainly hasn't worked since 2d92ab32fd ("rev-parse: make --show-toplevel without a worktree an error", 2019-11-19) in git, but breaking this git-gui feature was unintentional. There are (at least) 3 cases where the gitdir can tell us where the worktree is, and we would like all to work: - core.worktree is set, and points to a valid worktree. This is already handled by git rev-parse --show-toplevel, even when not in the worktree. There is nothing more to do in this case. - the gitdir is embedded in a worktree as subdirectory .git. The parent is (or at least should be) a valid worktree. This worked long ago. - the gitdir is a worktree specific directory (under <mainrepo>/worktrees/worktree_name), within which there is a file "gitdir" pointing to .git in the worktree. git gui never learned to handle this case. Let's handle the latter two cases. Always check that the discovered worktree is valid and points to the already discovered gitdir according to git rev-parse. This avoids issues that may arise because we are discovering from the gitdir up, rather than the worktree down, and file system non-posix behavior or misconfiguration of git might cause confusion. For instance, a manually moved worktree might not be where the gitdir points, or the gitdir might be configured with core.bare=true. Signed-off-by: Mark Levedahl <mlevedahl@gmail.com> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
2026-06-02git-gui: simplify [is_bare] to report if a worktree is knownMark Levedahl1-24/+1
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> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
2026-06-02git-gui: use git rev-parse for worktree discoveryMark Levedahl1-34/+27
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> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
2026-06-02git-gui: use rev-parse exclusively to find a repositoryMark Levedahl1-15/+34
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> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
2026-06-02git-gui: use --absolute-git-dirMark Levedahl1-11/+3
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> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
2026-06-02git-gui: do not change global vars in choose_repository::pickMark Levedahl2-14/+14
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> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
2026-06-02git-gui: guard set/unset of GIT_DIR and GIT_WORK_TREEMark Levedahl1-16/+20
git-gui unconditionally exports _gitdir as GIT_DIR, and _gitworktree as GIT_WORK_TREE, to the environment, and unconditionally unsets these environment variables before invoking gitk or git-gui when a submodule is involved. This export happens even if _gitworktree is empty, which happens when running from a bare repository. However, exporting GIT_WORK_TREE as empty is never valid, and causes errors in git. GIT_DIR must be exported if the repository is not discoverable from the worktree (or current directory if there is no worktree). The user might have configured this. If there is a worktree, git-gui makes this the current directory. However, if the repository sets core.worktree, this value can only be overridden by GIT_WORK_TREE so the latter must be exported. As we cannot eliminate conditions where either variable is needed, let's implement a pair of functions to set / unset these variables without error, and without ever exporting an empty GIT_WORK_TREE. Signed-off-by: Mark Levedahl <mlevedahl@gmail.com> Signed-off-by: Johannes Sixt <j6t@kdbg.org>
2026-06-02SubmittingPatches: describe cover letterJunio C Hamano1-0/+24
We talk about how a commit log message should look like, but do not give advice on writing the cover letter to sell a series to the widest possible audience. Helped-by: Patrick Steinhardt <ps@pks.im> Helped-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-02SubmittingPatches: separate typofixes sectionJunio C Hamano1-0/+1
The existing text said something about tests (with [[tests]] to make it easier to refer to it from elsewhere) and then flowed into a different topic of typofixes, but it was unclear where the latter started. Add a similar [[typofixes]] marker to the document. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-02doc: document and test `@` prefix for raw timestampsLuna Schwalbe2-0/+16
The Git internal date format `<unix-timestamp> <time-zone-offset>` fails to parse when the timestamp is less than 100,000,000 (fewer than 9 digits). This happens to avoid potential ambiguity with other date formats such as `YYYYMMDD`, especially when used with approxidate. To force the parser to interpret the value as a raw timestamp, it must be prefixed with `@` (e.g., `@0 +0000`). This behavior was introduced in 2c733fb24c10a9d7aacc51f956bf9b7881980870 (parse_date(): '@' prefix forces git-timestamp, 2012-02-02) but was never documented. Document the `@` prefix in `Documentation/date-formats.adoc` to make this behavior explicit. Also add test cases to `t/t0006-date.sh` to verify and demonstrate the difference between prefixed and unprefixed small timestamps (e.g., `@2000` vs `2000`). Signed-off-by: Luna Schwalbe <dev@luna.gl> Co-authored-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-02config.mak.uname: avoid macOS linker warning on Xcode 16.3+Harald Nordgren1-0/+6
Building on macOS with Xcode 16.3 or newer emits: ld: warning: reducing alignment of section __DATA,__common from 0x8000 to 0x4000 because it exceeds segment maximum alignment Pass -fno-common when "ld -v" reports ld-1167 or newer, so tentative definitions of large arrays go into BSS instead of __DATA,__common. Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-02The 11th batchJunio C Hamano1-0/+11
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-02Merge branch 'kh/doc-hook'Junio C Hamano3-11/+21
Doc updates. * kh/doc-hook: doc: hook: don’t self-link via config include doc: config: include existing git-hook(1) section doc: hook: consistently capitalize Git doc: hook: remove stray backtick
2026-06-02Merge branch 'ds/path-walk-filters'Junio C Hamano12-78/+1124
The "git pack-objects --path-walk" traversal has been integrated with several object filters, including blobless and sparse filters. * ds/path-walk-filters: path-walk: support `combine` filter path-walk: support `object:type` filter path-walk: support `tree:0` filter t6601: tag otherwise-unreachable trees pack-objects: support sparse:oid filter with path-walk path-walk: add pl_sparse_trees to control tree pruning path-walk: support blob size limit filter backfill: die on incompatible filter options path-walk: support blobless filter path-walk: always emit directly-requested objects t/perf: add pack-objects filter and path-walk benchmark pack-objects: pass --objects with --path-walk t5620: make test work with path-walk var
2026-06-02Merge branch 'ta/approxidate-noon-fix'Junio C Hamano3-12/+81
"Friday noon" asked in the morning on Sunday was parsed to be one day before the specified time, which has been corrected. * ta/approxidate-noon-fix: approxidate: use deferred mday adjustments for "specials" approxidate: make "specials" respect fixed day-of-month t0006: add support for approxidate test date adjustment approxidate: make "today" wrap to midnight
2026-06-02Merge branch 'jk/connect-service-enum'Junio C Hamano9-28/+58
The "name" argument in git_connect() and related functions has been converted to a "service" enum to improve type safety and clarify its purpose. * jk/connect-service-enum: transport-helper: fix typo in BUG() message connect: use "service" enum for "name" argument
2026-06-02describe: fix --exclude, --match with --contains and --allJacob Keller2-3/+37
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> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-06-02index-pack: retain child bases in delta cacheArijit Banerjee1-1/+0
When resolving a delta whose result has children of its own, index-pack adds the result to work_head, accounts its data in base_cache_used, and calls prune_base_data(). It then immediately frees that same data. This bypasses the existing delta base cache policy and can force later descendants to reconstruct the queued base again. Let the existing delta_base_cache_limit pruning policy decide whether to keep or evict the data instead. This does not add a new cache or increase the cache limit. The object data is already accounted in base_cache_used before prune_base_data() runs, and the existing pruning and base cleanup paths still release it. On a quiet Ubuntu 24.04 VM with 16 vCPUs, 32 GiB RAM, and local SSD, direct index-pack timings on single-pack Linux fixtures improved as follows: linux blobless: 69.17s -> 57.98s (16.2% faster), RSS flat linux full: 280.72s -> 236.32s (15.8% faster), RSS +1.9% Five-repeat medians on public repositories also improved: git.git: 12.31s -> 10.70s (13.1% faster) libgit2: 3.35s -> 2.88s (14.0% faster) redis: 6.52s -> 5.64s (13.5% faster) cpython: 33.02s -> 31.44s (4.8% faster) The standard p5302 perf test on a smaller git.git fixture was neutral: 5302.9 index-pack default threads: 11.21(38.07+1.33) -> 11.16(37.90+1.31), -0.4% t/t5302-pack-index.sh passed, and GitGitGadget's linux-leaks CI also exercised that test under SANITIZE=leak. Signed-off-by: Arijit Banerjee <arijit@effectiveailabs.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>