Skip to content

Tags: gitgitgadget/git

Tags

pr-git-2335/HaraldNordgren/bisect-auto-reset-v2

Toggle pr-git-2335/HaraldNordgren/bisect-auto-reset-v2's commit message
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

pr-git-2335/HaraldNordgren/bisect-auto-reset-v1

Toggle pr-git-2335/HaraldNordgren/bisect-auto-reset-v1's commit message
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

pr-2182/dscho/wincred-fixes-v1

Toggle pr-2182/dscho/wincred-fixes-v1's commit message
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

pr-2181/spkrka/kk/no-walk-pathspec-fix-v1

Toggle pr-2181/spkrka/kk/no-walk-pathspec-fix-v1's commit message
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

pr-2180/ozemin/stash-rename-v1

Toggle pr-2180/ozemin/stash-rename-v1's commit message
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

pr-git-2356/ZamboniL/mv-detect-non-existing-target-folder-v1

Toggle pr-git-2356/ZamboniL/mv-detect-non-existing-target-folder-v1's commit message
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

pr-git-2337/HaraldNordgren/rebase-fixup-fold-v9

Toggle pr-git-2337/HaraldNordgren/rebase-fixup-fold-v9's commit message
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

pr-2178/derrickstolee/trace2-dont-die-v1

Toggle pr-2178/derrickstolee/trace2-dont-die-v1's commit message
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

pr-2169/mmontalbo/mm/line-log-tidy-proto-v1

Toggle pr-2169/mmontalbo/mm/line-log-tidy-proto-v1's commit message
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

pr-2120/mmontalbo/mm/structural-diff-backend-clean-v5

Toggle pr-2120/mmontalbo/mm/structural-diff-backend-clean-v5's commit message
[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