@@ -821,6 +821,145 @@ NOTE: If `diff.<name>.command` is defined for path with the
821821(see above), and adding `diff.<name>.algorithm` has no effect, as the
822822algorithm is not passed to the external diff driver.
823823
824+ Using an external diff process
825+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
826+
827+ If `diff.<name>.process` is defined, Git sends the old and new file
828+ content to an external tool and receives back a list of changed
829+ regions (pairs of line ranges in the old and new file). Git uses
830+ these instead of its builtin diff algorithm, but still controls
831+ all output formatting, so features like word diff, function context,
832+ color, and blame work normally. This is achieved by using the
833+ long-running process protocol (described in
834+ Documentation/technical/long-running-process-protocol.adoc).
835+ Unlike `diff.<name>.command`, which replaces Git's output entirely,
836+ the diff process feeds results back into the standard pipeline.
837+
838+ First, in `.gitattributes`, assign the `diff` attribute for paths.
839+
840+ ------------------------
841+ *.c diff=cdiff
842+ ------------------------
843+
844+ Then, define a "diff.<name>.process" configuration to specify
845+ the diff process command.
846+
847+ ----------------------------------------------------------------
848+ [diff "cdiff"]
849+ process = /path/to/diff-process-tool
850+ ----------------------------------------------------------------
851+
852+ When Git encounters the first file that needs to be diffed, it starts
853+ the process and performs the handshake. In the handshake, the welcome
854+ message sent by Git is "git-diff-client", only version 1 is supported,
855+ and the supported capability is "hunks" (the changed regions
856+ described below).
857+
858+ For each file, Git sends a list of "key=value" pairs terminated with
859+ a flush packet, followed by the old and new file content as packetized
860+ data, each terminated with a flush packet. The pathname is relative
861+ to the repository root. When `diff.<name>.textconv` is also set,
862+ the tool receives the textconv-transformed content rather than the
863+ raw blob. Git does not send binary files to the diff process.
864+
865+ -----------------------
866+ packet: git> command=hunks
867+ packet: git> pathname=path/file.c
868+ packet: git> 0000
869+ packet: git> OLD_CONTENT
870+ packet: git> 0000
871+ packet: git> NEW_CONTENT
872+ packet: git> 0000
873+ -----------------------
874+
875+ The tool is expected to respond with zero or more hunk lines,
876+ a flush packet, and a status packet terminated with a flush packet.
877+ Each hunk line has the form:
878+
879+ `hunk <old_start> <old_count> <new_start> <new_count>`
880+
881+ where `<old_start>` and `<old_count>` identify a range of lines in
882+ the old file, and `<new_start>` and `<new_count>` identify the
883+ replacement range in the new file. Start values are 1-based and
884+ counts are non-negative. Ranges must not extend beyond the end of
885+ the file. For example, `hunk 3 2 3 4` means that 2 lines starting
886+ at line 3 in the old file were replaced by 4 lines starting at
887+ line 3 in the new file. An `<old_count>` of 0 means no lines were
888+ removed (pure insertion); a `<new_count>` of 0 means no lines were
889+ added (pure deletion).
890+
891+ Lines are delimited by newlines. A file `"foo\nbar\n"` and a
892+ file `"foo\nbar"` both have 2 lines.
893+
894+ Hunks must be listed in order and must not overlap. Any line
895+ not covered by a hunk is treated as unchanged, so the total
896+ number of unchanged lines must be the same on both sides.
897+ For example, if the old file has 10 lines and the hunks cover
898+ 4 of them (`old_count` values summing to 4), then 6 old lines
899+ are unchanged. The new file must also have exactly 6 lines
900+ not covered by hunks, so the `new_count` values must sum to
901+ `new_file_lines - 6`.
902+
903+ -----------------------
904+ packet: git< hunk 1 3 1 5
905+ packet: git< hunk 10 2 12 2
906+ packet: git< 0000
907+ packet: git< status=success
908+ packet: git< 0000
909+ -----------------------
910+
911+ If the tool responds with hunks and "success", Git marks those lines
912+ as changed and feeds them into the standard diff pipeline. Patch
913+ output features (word diff, function context, color) work normally.
914+ Note that `--stat` and other summary formats use their own diff path
915+ and are not affected by the diff process.
916+
917+ If no hunk lines precede the flush, followed by "success", Git
918+ treats the files as having no changes: `git diff` produces no output
919+ and `git blame` skips the commit, attributing lines to earlier commits.
920+
921+ -----------------------
922+ packet: git< 0000
923+ packet: git< status=success
924+ packet: git< 0000
925+ -----------------------
926+
927+ If the tool returns invalid hunks (out of bounds, overlapping), Git
928+ silently falls back to the builtin diff algorithm.
929+
930+ In case the tool cannot or does not want to process the content,
931+ it is expected to respond with an "error" status. Git warns and
932+ falls back to the builtin diff algorithm for this file. The tool
933+ remains available for subsequent files.
934+
935+ -----------------------
936+ packet: git< 0000
937+ packet: git< status=error
938+ packet: git< 0000
939+ -----------------------
940+
941+ In case the tool cannot or does not want to process the content as
942+ well as any future content for the lifetime of the Git process, it
943+ is expected to respond with an "abort" status. Git silently falls
944+ back to the builtin diff algorithm for this file and does not send
945+ further requests to the tool.
946+
947+ -----------------------
948+ packet: git< 0000
949+ packet: git< status=abort
950+ packet: git< 0000
951+ -----------------------
952+
953+ If the tool dies during the communication or does not adhere to the
954+ protocol then Git will stop the process and fall back to the builtin
955+ diff algorithm. Git warns once and does not restart the process for
956+ subsequent files.
957+
958+ Tools should ignore unknown keys in the per-file request to remain
959+ forward-compatible. Future versions of Git may send additional
960+ `command=` values; tools that receive an unrecognized command should
961+ respond with `status=error` rather than terminating.
962+
824963Defining a custom hunk-header
825964^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
826965
0 commit comments