| 1 | git-diff-hunks(1) |
| 2 | ================= |
| 3 | |
| 4 | NAME |
| 5 | ---- |
| 6 | git-diff-hunks - Inspect and manage the diff-hunks store |
| 7 | |
| 8 | SYNOPSIS |
| 9 | -------- |
| 10 | [synopsis] |
| 11 | git diff-hunks verify |
| 12 | git diff-hunks clear |
| 13 | |
| 14 | DESCRIPTION |
| 15 | ----------- |
| 16 | |
| 17 | The diff-hunks store is a cache of diff hunk coordinates, the line |
| 18 | ranges that changed between two blobs, so that commands |
| 19 | which need them, such as linkgit:git-blame[1] and `git log` and `git diff` |
| 20 | with the `--stat`, `--numstat`, and `--shortstat` formats, can skip |
| 21 | running the diff algorithm, and blame can skip loading the blob |
| 22 | content. (The summary formats still test each pair for binariness, |
| 23 | which can load the blobs.) |
| 24 | |
| 25 | The store is a single file, `$GIT_DIR/objects/info/diff-hunks`. Reading is |
| 26 | enabled by default; writing is off by default. A `git diff`, `git log`, |
| 27 | `git show`, or `git diff-tree` that produces one of the stat formats |
| 28 | fills the store as a side effect, but only when writing is enabled for |
| 29 | that run (see "WARMING THE STORE" below), so ordinary reads never |
| 30 | modify the repository. When the store does not have the pair, holds a |
| 31 | different object hash, the file is unreadable, or an object replacement |
| 32 | redirects one of the blobs, the consumer falls back to computing the |
| 33 | diff. A store only speeds up these commands; it never changes their |
| 34 | output. |
| 35 | |
| 36 | `git diff-hunks` itself only inspects and manages the file. See |
| 37 | linkgit:gitformat-diff-hunks[5] for the file format. |
| 38 | |
| 39 | WARMING THE STORE |
| 40 | ----------------- |
| 41 | |
| 42 | The store is filled by running ordinary commands with writing enabled. |
| 43 | Turn writing on for a single invocation with the `GIT_DIFF_HUNKS_WRITE` |
| 44 | environment variable, or persistently with the `diffHunks.write` |
| 45 | configuration; the environment variable takes precedence. A repository |
| 46 | owner warms the store by running the diff-producing commands they care |
| 47 | about with writing on, for example: |
| 48 | |
| 49 | GIT_DIFF_HUNKS_WRITE=1 git log --all --stat >/dev/null |
| 50 | |
| 51 | A `--stat` walk records one entry per blob pair; |
| 52 | linkgit:git-blame[1] replays the coordinates and the summary formats |
| 53 | sum the counts, so a single warming walk serves both. |
| 54 | A warming run seeds from the existing store and rewrites the file |
| 55 | with the newly computed pairs merged in, so a later run adds to what |
| 56 | earlier runs recorded rather than discarding it. |
| 57 | |
| 58 | A walk records only the pairs it diffs. `git log --all --stat` diffs |
| 59 | each commit against its first parent, so a blame that follows a |
| 60 | merge's second parent computes those pairs itself: blame coverage is |
| 61 | partial on history with merges. Warming with a walk that also diffs |
| 62 | the other parents, for example `git log --all -m --stat`, raises |
| 63 | blame coverage at the cost of a larger store and a longer warming |
| 64 | run. |
| 65 | |
| 66 | COMMANDS |
| 67 | -------- |
| 68 | |
| 69 | `verify`:: |
| 70 | Check the integrity of the store: the trailing hash checksum, the |
| 71 | chunk table of contents, the sort order of the index, and the |
| 72 | bounds of every entry. Exits with non-zero status if the store is |
| 73 | corrupt. An absent store is valid. |
| 74 | |
| 75 | `clear`:: |
| 76 | Remove the store file. |
| 77 | |
| 78 | CORRECTNESS |
| 79 | ----------- |
| 80 | |
| 81 | A stored result is interchangeable with a freshly computed one because an |
| 82 | entry is keyed by the inputs that determine the diff: |
| 83 | |
| 84 | * the object IDs of the old and new blob, so a result is used only for |
| 85 | the exact contents it was computed from; and |
| 86 | * the diff algorithm and ignore flags (`xdl_opts`) the hunks were |
| 87 | computed under. A lookup whose `xdl_opts` differ from a stored entry |
| 88 | misses. This is why, for example, `blame -w` and |
| 89 | `--diff-algorithm=<algorithm>` (including a per-path |
| 90 | `diff.<driver>.algorithm`) do not reuse entries recorded under the |
| 91 | default settings: they change `xdl_opts`. |
| 92 | |
| 93 | The context length is not part of the key because only trim-stable |
| 94 | pairs are recorded: pairs whose zero-context trimmed diff and untrimmed |
| 95 | diff are identical, so one entry answers blame (zero context) and the |
| 96 | summary formats (any context) alike. The rare pair where |
| 97 | the zero-context trimming optimization picks a different but |
| 98 | equally valid set of hunks is |
| 99 | never recorded and is always computed. |
| 100 | |
| 101 | Some options shape the hunks in ways the key does not express, so a |
| 102 | diff that uses them is excluded from the store in both directions: |
| 103 | break detection (`-B`), `--ignore-matching-lines` (`-I`), and |
| 104 | `--anchored`. `--ignore-blank-lines` is different: it is an ignore |
| 105 | flag and therefore part of the key, but the summary formats exclude |
| 106 | it anyway, because it coalesces hunks differently between the code |
| 107 | path that emits text and the one that replays coordinates, so a |
| 108 | served answer would not match a store-less run. |
| 109 | linkgit:git-blame[1] additionally does not |
| 110 | consult the store for reverse blame, ignored revisions, or paths with a |
| 111 | textconv driver. |
| 112 | |
| 113 | The store carries a trailing hash checksum, but readers do not |
| 114 | re-checksum it on every load. As with the commit-graph and |
| 115 | multi-pack-index, the writer fsyncs the file (honoring `core.fsync`) and |
| 116 | commits it atomically, so a committed store is intact; every offset and |
| 117 | count is still bounds-checked as it is read. The checksum is verified by |
| 118 | `git diff-hunks verify`, not on the read path, so structural corruption |
| 119 | that fails a bounds check is read as an absent entry, while a record |
| 120 | that stays within bounds but whose bytes were altered is served until |
| 121 | `verify` detects the mismatch. |
| 122 | |
| 123 | CONFIGURATION |
| 124 | ------------- |
| 125 | |
| 126 | `core.diffHunks`:: |
| 127 | Whether commands read the store. Defaults to true. See |
| 128 | linkgit:git-config[1]. |
| 129 | |
| 130 | `diffHunks.write`:: |
| 131 | Whether diff-producing commands write to the store. Defaults to |
| 132 | false. The `GIT_DIFF_HUNKS_WRITE` environment variable overrides it |
| 133 | for a single invocation. See linkgit:git-config[1]. |
| 134 | |
| 135 | Writing the store honors the `core.fsync` configuration through the |
| 136 | `diff-hunks` component; see linkgit:git-config[1]. |
| 137 | |
| 138 | SEE ALSO |
| 139 | -------- |
| 140 | linkgit:git-blame[1], |
| 141 | linkgit:git-log[1], |
| 142 | linkgit:gitformat-diff-hunks[5] |
| 143 | |
| 144 | GIT |
| 145 | --- |
| 146 | Part of the linkgit:git[1] suite |