]> git.ipfire.org Git - thirdparty/git.git/blame - Documentation/git-range-diff.txt
builtin/show-index: provide options to determine hash algo
[thirdparty/git.git] / Documentation / git-range-diff.txt
CommitLineData
348ae56c
JS
1git-range-diff(1)
2=================
3
4NAME
5----
6git-range-diff - Compare two commit ranges (e.g. two versions of a branch)
7
ba931edd
JS
8SYNOPSIS
9--------
10[verse]
11'git range-diff' [--color=[<when>]] [--no-color] [<diff-options>]
27526793 12 [--no-dual-color] [--creation-factor=<factor>]
ba931edd
JS
13 ( <range1> <range2> | <rev1>...<rev2> | <base> <rev1> <rev2> )
14
15DESCRIPTION
16-----------
17
18This command shows the differences between two versions of a patch
19series, or more generally, two commit ranges (ignoring merge commits).
20
21To that end, it first finds pairs of commits from both commit ranges
22that correspond with each other. Two commits are said to correspond when
23the diff between their patches (i.e. the author information, the commit
24message and the commit diff) is reasonably small compared to the
25patches' size. See ``Algorithm`` below for details.
26
27Finally, the list of matching commits is shown in the order of the
28second commit range, with unmatched commits being inserted just after
29all of their ancestors have been shown.
30
31
32OPTIONS
33-------
27526793
JS
34--no-dual-color::
35 When the commit diffs differ, `git range-diff` recreates the
36 original diffs' coloring, and adds outer -/+ diff markers with
37 the *background* being red/green to make it easier to see e.g.
a7be92ac
JS
38 when there was a change in what exact lines were added.
39+
40Additionally, the commit diff lines that are only present in the first commit
41range are shown "dimmed" (this can be overridden using the `color.diff.<slot>`
42config setting where `<slot>` is one of `contextDimmed`, `oldDimmed` and
43`newDimmed`), and the commit diff lines that are only present in the second
44commit range are shown in bold (which can be overridden using the config
45settings `color.diff.<slot>` with `<slot>` being one of `contextBold`,
46`oldBold` or `newBold`).
47+
48This is known to `range-diff` as "dual coloring". Use `--no-dual-color`
49to revert to color all lines according to the outer diff markers
50(and completely ignore the inner diff when it comes to color).
ba931edd
JS
51
52--creation-factor=<percent>::
53 Set the creation/deletion cost fudge factor to `<percent>`.
54 Defaults to 60. Try a larger value if `git range-diff` erroneously
55 considers a large change a total rewrite (deletion of one commit
56 and addition of another), and a smaller one in the reverse case.
57 See the ``Algorithm`` section below for an explanation why this is
58 needed.
59
bd361918
DL
60--[no-]notes[=<ref>]::
61 This flag is passed to the `git log` program
62 (see linkgit:git-log[1]) that generates the patches.
63
ba931edd
JS
64<range1> <range2>::
65 Compare the commits specified by the two ranges, where
66 `<range1>` is considered an older version of `<range2>`.
67
68<rev1>...<rev2>::
69 Equivalent to passing `<rev2>..<rev1>` and `<rev1>..<rev2>`.
70
71<base> <rev1> <rev2>::
72 Equivalent to passing `<base>..<rev1>` and `<base>..<rev2>`.
73 Note that `<base>` does not need to be the exact branch point
74 of the branches. Example: after rebasing a branch `my-topic`,
75 `git range-diff my-topic@{u} my-topic@{1} my-topic` would
76 show the differences introduced by the rebase.
77
78`git range-diff` also accepts the regular diff options (see
79linkgit:git-diff[1]), most notably the `--color=[<when>]` and
80`--no-color` options. These options are used when generating the "diff
81between patches", i.e. to compare the author, commit message and diff of
bd361918 82corresponding old/new commits. There is currently no means to tweak most of the
ba931edd
JS
83diff options passed to `git log` when generating those patches.
84
df569c3f
ÆAB
85OUTPUT STABILITY
86----------------
87
88The output of the `range-diff` command is subject to change. It is
89intended to be human-readable porcelain output, not something that can
90be used across versions of Git to get a textually stable `range-diff`
91(as opposed to something like the `--stable` option to
92linkgit:git-patch-id[1]). There's also no equivalent of
93linkgit:git-apply[1] for `range-diff`, the output is not intended to
94be machine-readable.
95
96This is particularly true when passing in diff options. Currently some
97options like `--stat` can, as an emergent effect, produce output
98that's quite useless in the context of `range-diff`. Future versions
99of `range-diff` may learn to interpret such options in a manner
100specific to `range-diff` (e.g. for `--stat` producing human-readable
101output which summarizes how the diffstat changed).
ba931edd
JS
102
103CONFIGURATION
104-------------
105This command uses the `diff.color.*` and `pager.range-diff` settings
106(the latter is on by default).
107See linkgit:git-config[1].
108
109
110EXAMPLES
111--------
112
113When a rebase required merge conflicts to be resolved, compare the changes
114introduced by the rebase directly afterwards using:
115
116------------
117$ git range-diff @{u} @{1} @
118------------
119
120
121A typical output of `git range-diff` would look like this:
122
123------------
124-: ------- > 1: 0ddba11 Prepare for the inevitable!
1251: c0debee = 2: cab005e Add a helpful message at the start
1262: f00dbal ! 3: decafe1 Describe a bug
127 @@ -1,3 +1,3 @@
128 Author: A U Thor <author@example.com>
129
130 -TODO: Describe a bug
131 +Describe a bug
132 @@ -324,5 +324,6
133 This is expected.
134
135 -+What is unexpected is that it will also crash.
136 ++Unexpectedly, it also crashes. This is a bug, and the jury is
137 ++still out there how to fix it best. See ticket #314 for details.
138
139 Contact
1403: bedead < -: ------- TO-UNDO
141------------
142
143In this example, there are 3 old and 3 new commits, where the developer
144removed the 3rd, added a new one before the first two, and modified the
145commit message of the 2nd commit as well its diff.
146
147When the output goes to a terminal, it is color-coded by default, just
148like regular `git diff`'s output. In addition, the first line (adding a
149commit) is green, the last line (deleting a commit) is red, the second
150line (with a perfect match) is yellow like the commit header of `git
151show`'s output, and the third line colors the old commit red, the new
152one green and the rest like `git show`'s commit header.
153
27526793
JS
154A naive color-coded diff of diffs is actually a bit hard to read,
155though, as it colors the entire lines red or green. The line that added
156"What is unexpected" in the old commit, for example, is completely red,
157even if the intent of the old commit was to add something.
ba931edd 158
27526793
JS
159To help with that, `range` uses the `--dual-color` mode by default. In
160this mode, the diff of diffs will retain the original diff colors, and
161prefix the lines with -/+ markers that have their *background* red or
162green, to make it more obvious that they describe how the diff itself
163changed.
ba931edd
JS
164
165
166Algorithm
167---------
168
169The general idea is this: we generate a cost matrix between the commits
170in both commit ranges, then solve the least-cost assignment.
171
172The cost matrix is populated thusly: for each pair of commits, both
173diffs are generated and the "diff of diffs" is generated, with 3 context
174lines, then the number of lines in that diff is used as cost.
175
176To avoid false positives (e.g. when a patch has been removed, and an
177unrelated patch has been added between two iterations of the same patch
178series), the cost matrix is extended to allow for that, by adding
179fixed-cost entries for wholesale deletes/adds.
180
181Example: Let commits `1--2` be the first iteration of a patch series and
182`A--C` the second iteration. Let's assume that `A` is a cherry-pick of
183`2,` and `C` is a cherry-pick of `1` but with a small modification (say,
184a fixed typo). Visualize the commits as a bipartite graph:
185
186------------
187 1 A
188
189 2 B
190
191 C
192------------
193
194We are looking for a "best" explanation of the new series in terms of
195the old one. We can represent an "explanation" as an edge in the graph:
196
197
198------------
199 1 A
200 /
201 2 --------' B
202
203 C
204------------
205
206This explanation comes for "free" because there was no change. Similarly
207`C` could be explained using `1`, but that comes at some cost c>0
208because of the modification:
209
210------------
211 1 ----. A
212 | /
213 2 ----+---' B
214 |
215 `----- C
216 c>0
217------------
218
219In mathematical terms, what we are looking for is some sort of a minimum
220cost bipartite matching; `1` is matched to `C` at some cost, etc. The
221underlying graph is in fact a complete bipartite graph; the cost we
222associate with every edge is the size of the diff between the two
223commits' patches. To explain also new commits, we introduce dummy nodes
224on both sides:
225
226------------
227 1 ----. A
228 | /
229 2 ----+---' B
230 |
231 o `----- C
232 c>0
233 o o
234
235 o o
236------------
237
238The cost of an edge `o--C` is the size of `C`'s diff, modified by a
239fudge factor that should be smaller than 100%. The cost of an edge
240`o--o` is free. The fudge factor is necessary because even if `1` and
241`C` have nothing in common, they may still share a few empty lines and
242such, possibly making the assignment `1--C`, `o--o` slightly cheaper
243than `1--o`, `o--C` even if `1` and `C` have nothing in common. With the
244fudge factor we require a much larger common part to consider patches as
245corresponding.
246
247The overall time needed to compute this algorithm is the time needed to
248compute n+m commit diffs and then n*m diffs of patches, plus the time
031fd4b9 249needed to compute the least-cost assignment between n and m diffs. Git
ba931edd
JS
250uses an implementation of the Jonker-Volgenant algorithm to solve the
251assignment problem, which has cubic runtime complexity. The matching
252found in this case will look like this:
253
254------------
255 1 ----. A
256 | /
257 2 ----+---' B
258 .--+-----'
259 o -' `----- C
260 c>0
261 o ---------- o
262
263 o ---------- o
264------------
265
266
267SEE ALSO
268--------
269linkgit:git-log[1]
270
348ae56c
JS
271GIT
272---
273Part of the linkgit:git[1] suite