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