Tags: gitgitgadget/git
Tags
bisect: add --auto-reset to leave when done Add a --auto-reset option to git bisect that resets the bisect session when culprit is found. Changes in v2: * Add option --auto-reset[=<where>] with option to go to final commit as well as original. * Refactored tests. Harald Nordgren (3): bisect: read run output from the open descriptor bisect: let bisect_reset() optionally check out quietly bisect: add --auto-reset to leave when done Documentation/git-bisect.adoc | 14 +++- bisect.c | 2 + builtin/bisect.c | 132 +++++++++++++++++++++++++++++----- t/t6030-bisect-porcelain.sh | 107 +++++++++++++++++++++++++++ 4 files changed, 234 insertions(+), 21 deletions(-) base-commit: 44de152 Submitted-As: https://lore.kernel.org/git/pull.2335.v2.git.git.1784312854.gitgitgadget@gmail.com In-Reply-To: https://lore.kernel.org/git/pull.2335.git.git.1784180159.gitgitgadget@gmail.com
bisect: add --auto-reset to leave when done Add a --auto-reset option to git bisect start and git bisect run that returns to the commit checked out before git bisect start as soon as the first bad commit is reported, instead of leaving the session active until git bisect reset is run by hand. Harald Nordgren (3): bisect: read run output from the open descriptor bisect: let bisect_reset() optionally check out quietly bisect: add --auto-reset to leave when done Documentation/git-bisect.adoc | 12 +++++++-- bisect.c | 2 ++ builtin/bisect.c | 51 ++++++++++++++++++++++------------- t/t6030-bisect-porcelain.sh | 34 +++++++++++++++++++++++ 4 files changed, 78 insertions(+), 21 deletions(-) base-commit: f60db8d Submitted-As: https://lore.kernel.org/git/pull.2335.git.git.1784180159.gitgitgadget@gmail.com
Some wincred fixes These were rolled out as part of the security fix release Git for Windows v2.55.0(3). Johannes Schindelin (2): wincred: avoid memory corruption when erasing a credential wincred: prevent silent credential loss when storing OAuth tokens contrib/credential/wincred/git-credential-wincred.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) base-commit: 94f0577 Submitted-As: https://lore.kernel.org/git/pull.2182.git.1784212072.gitgitgadget@gmail.com
revision: fix --no-walk path filtering regression From: Kristofer Karlsson <krka@spotify.com> Since dd4bc01 (revision: use priority queue for non-limited streaming walks, 2026-05-27), "git rev-list --no-walk <commit> -- <path>" ignores the path arguments and outputs all commits regardless of whether they touch the given paths. That commit introduced a REV_WALK_NO_WALK enum value to separate --no-walk from the streaming walk in get_revision_1(). The new case skips process_parents(), which is correct for not enqueuing parents, but also skips try_to_simplify_commit() which process_parents() calls to evaluate whether each commit touches the given paths. Add a call to try_to_simplify_commit() for the REV_WALK_NO_WALK case, folding it into the existing REV_WALK_REFLOG case which already does the same. Add tests for --no-walk path filtering to t6017. The "single commit, match" test is defensive and passes without the fix, while the other two fail without it. Reported-by: Peter Colberg <pcolberg@redhat.com> Signed-off-by: Kristofer Karlsson <krka@spotify.com> Submitted-As: https://lore.kernel.org/git/pull.2181.git.1784198879711.gitgitgadget@gmail.com
stash: add 'rename' subcommand
From: =?UTF-8?q?Emin=20=C3=96zata?= <eminozata@proton.me>
There is no way to change the message of a stash entry after the
fact. The only option is dropping the entry and re-storing it by
hand, which moves it to the top of the stash list and gets fiddly
for deeper entries.
Add 'git stash rename <message> [<stash>]', defaulting to the
latest entry like the other subcommands do. It reads the object id
and reflog message of the target entry and of the entries above it,
drops them all like 'git stash drop' would, and stores them back in
the same order, with the new message going to the target. Position,
contents and the reflog chain stay as they were.
The command checks every entry it is about to rewrite and refuses
to start if one of them does not look like a stash commit, which
can only happen when refs/stash was written to by hand. Finding
that out halfway through the sequence would lose entries. Should a
write-back fail anyway, the entry's object id is reported so it can
be recovered with 'git stash store', and the command only reports
success when the reflog ended up in the requested state.
This was proposed before: in 2010, as a "git reflog update" command
that edited reflog entries in place [1]. When it came up again in
2013 [2], Junio rejected it on the grounds that reflogs are
append-only recovery logs, and that whoever really cares about a
stash message can pop and re-stash [3]. Michael Haggerty pointed
out in that thread that refs/stash does not fit the description:
its reflog is the primary data store for stash entries, and 'git
stash drop' rewrites it all the time [4]. So this patch stays away
from the reflog machinery entirely and does the suggested
pop-and-re-stash workaround mechanically, without the detour
through the working tree.
The sequence only works if entry positions hold still while it
runs, so the command takes index-based selectors (stash@{1}) and
rejects time-based ones. It also refreshes the reflog timestamps
of the rewritten entries, and renaming stash@{n} costs n+1 reflog
deletions and ref updates.
[1] https://lore.kernel.org/git/20100620093142.GF24805@occam.hewgill.net/
[2] https://lore.kernel.org/git/loom.20130104T192132-16@post.gmane.org/
[3] https://lore.kernel.org/git/7vbod4tynt.fsf@alter.siamese.dyndns.org/
[4] https://lore.kernel.org/git/50ED2C78.1030300@alum.mit.edu/
Signed-off-by: Emin Özata <eminozata@proton.me>
Submitted-As: https://lore.kernel.org/git/pull.2180.git.1784190706028.gitgitgadget@gmail.com
mv: report missing destination leading directory
From: Lucas Zamboni Orioli <lucaszam0@gmail.com>
When moving a file to a destination whose leading directory does not
exist, "git mv" fails at the rename(2) syscall with ENOENT. Because
the error is reported via die_errno() using only the source path:
fatal: renaming 'src' failed: No such file or directory
the message misleadingly blames the source, even though it is the
destination's parent directory that is missing. A user who runs
git mv a/file b/does-not-exist/file
is told the problem is with 'a/file', which exists, giving no hint
that 'b/does-not-exist/' needs to be created first.
The checking phase already rejects a missing destination directory
when the destination ends in a slash, but a destination that names a
file inside a non-existent directory is not caught and only fails
later at rename(2). As a result "git mv -n" also fails to detect the
problem, since the dry run never reaches the syscall and reports a
move that would not actually succeed.
Detect this during the checking phase instead: for entries that will
be renamed on disk, stat the destination's leading directory and, if
it is missing, fail with the existing "destination directory does not
exist" message. Guard the check with the same condition under which
rename(2) is invoked so that directory moves, whose child entries are
expanded to paths under a not-yet-created directory, and sparse or
out-of-cone destinations, which are not written to the worktree, are
not flagged incorrectly.
This gives a clear message and lets "git mv -n" report the failure.
Signed-off-by: Lucas Zamboni Orioli <lucaszam0@gmail.com>
Submitted-As: https://lore.kernel.org/git/pull.2356.git.git.1784125963694.gitgitgadget@gmail.com
history: add squash subcommand to fold a range Adds git history squash <revision-range> to fold a range of commits. Changes in v9: * Use the last amend! targeting the oldest folded commit as the default squashed message. Ignore amend! markers targeting later commits while selecting that replacement message. * Improve tests. Changes in v8: * --reedit-message now builds the same editor template as git rebase -i --autosquash: fixup!, squash! and amend! commits are grouped under the commit they target instead of shown in commit order, and an amend! replaces its target's message. * A fixup!, squash! or amend! is refused only when its target is outside the range, so several fixups for an in-range commit fold together. A range that is entirely markers for one below-range target is combined into a single commit, keeping the last amend! message. * Merges inside the range are folded when the range has a single base, with no dedicated opt-in flag, --ancestry-path ensures only commits descended from the base are folded, and a range reaching more than one base is rejected. * Rev-list options are accepted and sanitized the way git replay does, forcing the walk order back with a warning, which also fixes git history squash -- --reverse slipping past the previous option check. * Kept this as an explicit squash subcommand rather than making --reedit-message the default or renaming the command. Changes in v7: * --reedit-message now builds the same editor template git rebase -i shows for a squash (a combination of N commits banner with each folded message under its own header) and follows autosquash for markers: a fixup! message falls out (commented under a will be skipped header), while a squash! or amend! keeps its body with only the marker subject commented so its remark can be reworded in. Only the message text is affected, every commit's changes are always folded in. * Reuse git rebase -i's squash-message code: a preparatory sequencer: commit extracts the banner, header and marker-comment helpers so both rebase and git history squash build the identical template from one source. * Refuse a range whose oldest commit is a fixup!, squash! or amend!, since the marker's target cannot be inside the range. * Reorder the squash usage so dashed options come before <revision-range>, and spell out HEAD instead of @ in the documentation and examples. * Expand the squash commit message and documentation with this overview, and scope the merge limitation so it no longer contradicts squash folding a single-base interior merge. Changes in v6: * git history squash now accepts multiple revision arguments, read like the arguments to git-rev-list, so a compound range such as @~3.. ^topic works. * The base to reparent onto is now the oldest in-range commit's parent; a boundary other than that base means the range has more than one base and is rejected. This also fixes the earlier overly-restrictive handling of merges and side branches. * A single-commit range (e.g. @^!) is rejected with "nothing to squash" (this also covers the @^!-style example that previously succeeded silently). * Commit messages reworded: the squash commit now gives an overview of fixup!/squash!/amend! handling, rewording, merge-parent and ref behavior. Changes in v5: * The range walk now uses --ancestry-path, so only commits descended from the base are folded; a single revision such as HEAD or HEAD~1 is now rejected as "not a <base>..<tip> range" rather than treated as a squash down to the root. * This adopts the --ancestry-path suggestion; the multi-base rejection is unchanged, so a side branch that forked before the base and merged in is still refused. * Added tests covering more merge topologies: two interior merges, a nested merge, an octopus merge, an octopus arm forked before the base, a merge among the descendants replayed above the range, and a ref pointing at an interior merge commit. Changes in v4: * git history squash now detects when another ref points at a commit inside the range being folded and refuses, with an advice.historyUpdateRefs hint to use --update-refs=head. * A merge inside the range is folded fine as long as the range has a single base; a range with merge commit at the tip or base also folds correctly. Only a range with more than one base is rejected. Changes in v3: * Moved the feature out of git rebase and into a new git history squash <revision-range> subcommand, per the list discussion. git rebase --squash is dropped. * Takes an arbitrary range (git history squash @~3.., git history squash @~5..@~2), folding it into the oldest commit and replaying any descendants on top. * Implemented as a single tree operation rather than picking each commit, so there are no repeated conflict stops (addresses Phillip's efficiency point). * A merge inside the range is folded fine, only a range with more than one base is rejected. * --reedit-message seeds the editor with every folded-in message, not just the oldest. Harald Nordgren (5): history: extract helper for a commit's parent tree history: give commit_tree_ext a message template history: add squash subcommand to fold a range sequencer: share the squash message marker helpers and flags history: re-edit a squash with every message Documentation/config/advice.adoc | 4 + Documentation/git-history.adoc | 57 ++- advice.c | 1 + advice.h | 1 + builtin/history.c | 550 ++++++++++++++++++++-- sequencer.c | 70 +-- sequencer.h | 30 ++ t/meson.build | 1 + t/t3455-history-squash.sh | 766 +++++++++++++++++++++++++++++++ 9 files changed, 1408 insertions(+), 72 deletions(-) create mode 100755 t/t3455-history-squash.sh base-commit: 55526a1 Submitted-As: https://lore.kernel.org/git/pull.2337.v9.git.git.1784128573.gitgitgadget@gmail.com In-Reply-To: https://lore.kernel.org/git/pull.2337.git.git.1781465141.gitgitgadget@gmail.com In-Reply-To: https://lore.kernel.org/git/pull.2337.v2.git.git.1781512625.gitgitgadget@gmail.com In-Reply-To: https://lore.kernel.org/git/pull.2337.v3.git.git.1781810226.gitgitgadget@gmail.com In-Reply-To: https://lore.kernel.org/git/pull.2337.v4.git.git.1782021195.gitgitgadget@gmail.com In-Reply-To: https://lore.kernel.org/git/pull.2337.v5.git.git.1782338102.gitgitgadget@gmail.com In-Reply-To: https://lore.kernel.org/git/pull.2337.v6.git.git.1782635349.gitgitgadget@gmail.com In-Reply-To: https://lore.kernel.org/git/pull.2337.v7.git.git.1783327849.gitgitgadget@gmail.com In-Reply-To: https://lore.kernel.org/git/pull.2337.v8.git.git.1783674396.gitgitgadget@gmail.com
trace2: tolerate failed timestamp formatting From: Derrick Stolee <stolee@gmail.com> Some users reported issues of repeated messages: fatal: recursion detected in die handler This wasn't happening every time, but we eventually captured a GIT_TRACE2_PERF log file with this issue and revealed an interesting internal detail, failing with this message: unable to format message: %4d-%02d-%02dT%02d:%02d:%02d.%06ldZ This specific format string tracks to tr2_tbuf_utc_datetime_extended() in trace2/tr2_tbuf.c. This logic began as tr2_tbuf_utc_time() in ee4512e (trace2: create new combined trace facility, 2019-02-22) but was later split in bad229a (trace2: clarify UTC datetime formatting, 2019-04-15). This use of xsnprintf() is writing a very specific datetime format into a 32-character buffer. The format requires that the input data will not overflow the format digits or the buffer will not hold the result. Since we are using xsnprintf() here, those failures turn into die() events. This method and its siblings, tr2_tbuf_local_time() and tr2_tbuf_utc_datetime(), are used in the tracing library. The extended form is used only for the 'event' format, which these users were using via a config setting for use in client-side telemetry. The non-extended form is used to help generate the 'SID' that defines the process in the traces. Not only are these inappropriate times for a failure, but the extended method is called specifially during the 'atexit' event, which was triggering this problem in a loop as the 'atexit' event would be retriggered by the die(). I could not determine the exact cause of why these errors started occuring in a bunch. My best guess is that these users are dogfooding an early operating system version that is more likely to fail in the gettimeofday() function and thus leaves the structures uninitialized and potentially violating the expected values. However, for full defense-in-depth I made several modifications: 1. Both 'tv' and 'tm' structs are initialized with zero values, allowing an erroring gettimeofday() or gmtime_r() method to leave them zero-valued. A zero-valued date is better than a die() here. 2. Replace the use of xsnprintf() with snprintf() to avoid the possibility of calling die() here. Instead, check the response to see if there was a failure. On failure, put a blank value into the buffer instead of possibly allowing a value that would not format correctly for a trace2 consumer. This value should be seen as obviously wrong and therefore signals a problem. As the core issue in this code seems to require a system method returning an error, no test accompanies this change. This change removes all uses of xsnprintf() from the trace2/ directory. There are two uses of xstrdup() that could be considered for removal, but they only die() on out-of-memory errors instead of formatting issues. I chose to leave those in place for now. Signed-off-by: Derrick Stolee <stolee@gmail.com> Submitted-As: https://lore.kernel.org/git/pull.2178.git.1784131932489.gitgitgadget@gmail.com
revision: make get_commit_action() a pure predicate From: Michael Montalbo <mmontalbo@gmail.com> get_commit_action() reads as a predicate that decides whether a commit is shown or ignored, but for a line-level log without parent rewriting it also calls line_log_process_ranges_arbitrary_commit(), which mutates the tracked line ranges. That hidden side effect makes it unsafe to evaluate ahead of the walk, the way a lookahead would. get_commit_action() was split out of simplify_commit() in beb5af4 (graph API: fix bug in graph_is_interesting(), 2009-08-18) as the show/ignore decision minus the parent rewriting, so the graph renderer could reuse it; line-level log later routed its filtering through it as well, in 3cb9d2b (line-log: more responsive, incremental 'git log -L', 2020-05-11). Besides simplify_commit(), the walk driver, graph_is_interesting() is its only other caller, and it runs only under --graph, which sets rewrite_parents and therefore want_ancestry(); the "-L without ancestry" branch that holds the side effect never fires there, so it is dormant today. The line-level processing folds a commit's tracked ranges onto its parents, which must happen even for a commit that get_commit_action() filters from the output, or the ranges never reach the parents. Move it to simplify_commit() and run it before get_commit_action(), gated by get_commit_action()'s leading checks (already shown, uninteresting, and the like) so a commit ignored by those is not folded, as before; factor those checks out as commit_early_ignore(). get_commit_action() is then side-effect free. commit_early_ignore() runs twice on the -L path, once for that gate and once inside get_commit_action(), but it reads only object flags and pack membership, disjoint from the TREESAME flag the fold sets, so the repeat is harmless. Add a "line-log-peek" subcommand to the revision-walking test helper that evaluates get_commit_action() on a commit the walk has not reached yet, plus a t4211 check that the call leaves the commit's flags unchanged. The flags are compared rather than the commit list because add_line_range() merges ranges by union, which is idempotent, so the side effect never changed which commits a linear -L history shows. Suggested-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Michael Montalbo <mmontalbo@gmail.com> Submitted-As: https://lore.kernel.org/git/pull.2169.git.1784143793613.gitgitgadget@gmail.com
[RFC] diff: add diff.<driver>.process for external hunk providers
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 diff output with the program's own
output, so display features like word diff, function context, and color
cannot operate on it; and because the program is consulted only for that
patch output, blame, --stat, and git log -L fall back to Git's builtin line
matching and cannot benefit from the tool at all.
This series adds diff.<driver>.process, a long-running subprocess protocol
that lets an external tool control which lines Git considers changed while
Git handles all output formatting. The protocol follows
filter.<driver>.process: pkt-line over stdin/stdout, capability negotiation,
one process per Git invocation.
The tool receives both file versions and returns changed regions (line
ranges in the old and new file). Git validates and feeds them into the xdiff
pipeline in place of the builtin diff algorithm. When the tool returns no
hunks, Git treats the files as having no changes, which propagates through
patch output, the --stat summary, blame, and git log -L. The request also
carries the two blobs' object names (old-oid/new-oid) so a tool can cache
its analysis keyed on the pair.
* Patch 1: document how an external diff driver (diff.<driver>.command)
relates to the rest of Git's diff features, so the contrast with the new
process driver is clear.
* Patch 2: xdiff plumbing for externally supplied hunks.
* Patch 3: diff.<driver>.process config key.
* Patch 4: refactor subprocess API to separate process lifecycle from
hashmap management, since the diff process stores its subprocess on the
userdiff driver rather than in a hashmap.
* Patch 5: the main feature, including the old-oid/new-oid request metadata
for blob-pair caching.
* Patch 6: bypass knobs (--no-ext-diff, format-patch).
* Patch 7: blame integration so the tool can declare commits as having no
changes; introduces the shared xdi_diff_process() consult-then-diff
helper that blame and git log -L both use.
* Patch 8: --stat/--numstat/--shortstat consult the tool, so the summary
agrees with the patch output.
* Patch 9: git log -L range tracking consults the tool, so a reformat-only
commit is dropped from the log rather than shown with an empty diff.
A "Which features consult the diff process" section in gitattributes(5) lays
out, per feature, why each does or does not consult the process (patch
output, blame, summary formats, and the -L line-range view do; pickaxe -G,
patch-id, merge, range-diff, --check, and --raw do not, with reasons).
Combined diffs (--cc) remain on the builtin algorithm and are noted as
future work.
Changes since v4:
* New preparatory doc patch (patch 1): document how an external diff driver
(diff.<driver>.command) relates to the rest of Git's diff features, so
the contrast with the process driver added later in the series is
explicit.
* New: --stat/--numstat/--shortstat now consult the process (patch 8). A
file the tool reports as equivalent contributes no stat line, matching
the empty patch git diff produces for it. Summary formats do not apply
textconv, so the tool is fed raw content there, as the builtin --stat
already counts raw lines.
* New: git log -L range tracking now consults the process (patch 9).
Previously the tracking pass used the builtin diff while the displayed
diff used the tool, so a reformat-only commit could be selected by
tracking and then rendered with an empty diff. Tracking now agrees with
the display and the commit is dropped.
* New: the request carries the old and new blob object names
(old-oid/new-oid), so a tool can cache its line matching keyed on the
blob pair. A side's oid is sent only when the tool receives that raw
blob; it is omitted under textconv (which rewrites the bytes) and for a
working-tree side with no stored object. This is where the process
differs from diff.<name>.command, which never composes with textconv and
so always feeds the raw blob its oid names.
* Refactor: blame and git log -L now consult the process through a single
xdi_diff_process() helper instead of open-coding the consult-then-diff
dance; builtin_diff() keeps its own path so it can short-circuit
equivalent files before its funcname/word-diff setup. The whitespace
bypass keys off the effective diff parameters (xpp), which removes
blame's separate -w guard, and blame's diff_hunks() sheds an intermediate
variant it no longer needs.
* Correctness: external-hunk validation now checks per-gap alignment, not
just the total unchanged-line count. xdl_build_script() walks the two
files in lockstep over unchanged lines, so a hunk set whose totals
balance but whose per-gap line counts do not (e.g. hunk 1 1 3 1)
previously passed validation and produced a corrupt diff, --stat, and
blame attribution. Such responses are now rejected and Git falls back to
the builtin diff.
* Robustness: hunk accumulation is bounded by the two files' combined line
count, so a misbehaving tool that floods hunk lines cannot grow memory
without bound before validation.
* Forward-compat: the hunk-line parser now ignores unknown trailing fields
after the four counts, so a future protocol version can append a field
without older clients rejecting it.
* Feature interactions: the whitespace-ignoring options (-w,
--ignore-space-change, --ignore-blank-lines, ...), -I, and --anchored
bypass the process (the tool is never told about them and could not honor
them), and git blame -w does the same. A change that only adds or removes
the trailing newline cannot be expressed as line hunks, so it also falls
back to the builtin diff (preserving the "\ No newline at end of file"
marker).
* Documentation: added the per-feature "Which features consult the diff
process" section; documented that the process trusts the tool's notion of
"unchanged" (it is not byte-validated, so like git diff -w such a patch
may not apply against the old blob), that --exit-code/--quiet report
success for tool- equivalent files, and that diff.<name>.command takes
precedence when both it and .process are configured.
* Tests: t4080 grew coverage for the per-gap check, the hunk- flood cap,
the whitespace/-w bypasses, the trailing-newline and added/deleted-file
fallbacks, multi-hunk output through patch and --stat, --stat
--exit-code, a mode-only change, and a mixed equivalent/changed
multi-file diffstat.
Michael Montalbo (9):
gitattributes: document how external diff drivers relate to diff
features
xdiff: support external hunks via xpparam_t
userdiff: add diff.<driver>.process config
sub-process: separate process lifecycle from hashmap management
diff: add long-running diff process via diff.<driver>.process
diff: bypass diff process with --no-ext-diff and in format-patch
blame: consult diff process for no-hunk detection
diff: consult diff process for --stat counts
line-log: consult diff process for range tracking
Documentation/config/diff.adoc | 5 +
Documentation/diff-algorithm-option.adoc | 3 +
Documentation/diff-options.adoc | 4 +-
Documentation/gitattributes.adoc | 274 +++++++
Makefile | 2 +
blame.c | 24 +-
builtin/log.c | 7 +
diff-process.c | 529 +++++++++++++
diff-process.h | 75 ++
diff.c | 57 +-
diff.h | 6 +
line-log.c | 33 +-
meson.build | 1 +
sub-process.c | 28 +-
sub-process.h | 9 +-
t/helper/meson.build | 1 +
t/helper/test-diff-process-backend.c | 381 +++++++++
t/helper/test-tool.c | 1 +
t/helper/test-tool.h | 1 +
t/meson.build | 1 +
t/t4080-diff-process.sh | 950 +++++++++++++++++++++++
userdiff.c | 7 +
userdiff.h | 5 +
xdiff-interface.c | 7 +-
xdiff/xdiff.h | 16 +
xdiff/xdiffi.c | 84 +-
xdiff/xprepare.c | 10 +
xdiff/xprepare.h | 1 +
28 files changed, 2504 insertions(+), 18 deletions(-)
create mode 100644 diff-process.c
create mode 100644 diff-process.h
create mode 100644 t/helper/test-diff-process-backend.c
create mode 100755 t/t4080-diff-process.sh
base-commit: e9019fc
Submitted-As: https://lore.kernel.org/git/pull.2120.v5.git.1784149323.gitgitgadget@gmail.com
In-Reply-To: https://lore.kernel.org/git/pull.2120.git.1779415884.gitgitgadget@gmail.com
In-Reply-To: https://lore.kernel.org/git/pull.2120.v2.git.1779733799.gitgitgadget@gmail.com
In-Reply-To: https://lore.kernel.org/git/pull.2120.v3.git.1780087700.gitgitgadget@gmail.com
In-Reply-To: https://lore.kernel.org/git/pull.2120.v4.git.1781463564.gitgitgadget@gmail.com
PreviousNext