1GIT-RANGE-DIFF(1)                 Git Manual                 GIT-RANGE-DIFF(1)
2
3
4

NAME

6       git-range-diff - Compare two commit ranges (e.g. two versions of a
7       branch)
8

SYNOPSIS

10       git range-diff [--color=[<when>]] [--no-color] [<diff-options>]
11               [--no-dual-color] [--creation-factor=<factor>]
12               ( <range1> <range2> | <rev1>...<rev2> | <base> <rev1> <rev2> )
13
14

DESCRIPTION

16       This command shows the differences between two versions of a patch
17       series, or more generally, two commit ranges (ignoring merge commits).
18
19       To that end, it first finds pairs of commits from both commit ranges
20       that correspond with each other. Two commits are said to correspond
21       when the diff between their patches (i.e. the author information, the
22       commit message and the commit diff) is reasonably small compared to the
23       patches' size. See ``Algorithm`` below for details.
24
25       Finally, the list of matching commits is shown in the order of the
26       second commit range, with unmatched commits being inserted just after
27       all of their ancestors have been shown.
28

OPTIONS

30       --no-dual-color
31           When the commit diffs differ, ‘git range-diff` recreates the
32           original diffs’ coloring, and adds outer -/+ diff markers with the
33           background being red/green to make it easier to see e.g. when there
34           was a change in what exact lines were added.
35
36           Additionally, the commit diff lines that are only present in the
37           first commit range are shown "dimmed" (this can be overridden using
38           the color.diff.<slot> config setting where <slot> is one of
39           contextDimmed, oldDimmed and newDimmed), and the commit diff lines
40           that are only present in the second commit range are shown in bold
41           (which can be overridden using the config settings
42           color.diff.<slot> with <slot> being one of contextBold, oldBold or
43           newBold).
44
45           This is known to range-diff as "dual coloring". Use --no-dual-color
46           to revert to color all lines according to the outer diff markers
47           (and completely ignore the inner diff when it comes to color).
48
49       --creation-factor=<percent>
50           Set the creation/deletion cost fudge factor to <percent>. Defaults
51           to 60. Try a larger value if git range-diff erroneously considers a
52           large change a total rewrite (deletion of one commit and addition
53           of another), and a smaller one in the reverse case. See the
54           ``Algorithm`` section below for an explanation why this is needed.
55
56       <range1> <range2>
57           Compare the commits specified by the two ranges, where <range1> is
58           considered an older version of <range2>.
59
60       <rev1>...<rev2>
61           Equivalent to passing <rev2>..<rev1> and <rev1>..<rev2>.
62
63       <base> <rev1> <rev2>
64           Equivalent to passing <base>..<rev1> and <base>..<rev2>. Note that
65           <base> does not need to be the exact branch point of the branches.
66           Example: after rebasing a branch my-topic, git range-diff
67           my-topic@{u} my-topic@{1} my-topic would show the differences
68           introduced by the rebase.
69
70       git range-diff also accepts the regular diff options (see git-diff(1)),
71       most notably the --color=[<when>] and --no-color options. These options
72       are used when generating the "diff between patches", i.e. to compare
73       the author, commit message and diff of corresponding old/new commits.
74       There is currently no means to tweak the diff options passed to git log
75       when generating those patches.
76

OUTPUT STABILITY

78       The output of the range-diff command is subject to change. It is
79       intended to be human-readable porcelain output, not something that can
80       be used across versions of Git to get a textually stable range-diff (as
81       opposed to something like the --stable option to git-patch-id(1)).
82       There’s also no equivalent of git-apply(1) for range-diff, the output
83       is not intended to be machine-readable.
84
85       This is particularly true when passing in diff options. Currently some
86       options like --stat can, as an emergent effect, produce output that’s
87       quite useless in the context of range-diff. Future versions of
88       range-diff may learn to interpret such options in a manner specific to
89       range-diff (e.g. for --stat producing human-readable output which
90       summarizes how the diffstat changed).
91

CONFIGURATION

93       This command uses the diff.color.* and pager.range-diff settings (the
94       latter is on by default). See git-config(1).
95

EXAMPLES

97       When a rebase required merge conflicts to be resolved, compare the
98       changes introduced by the rebase directly afterwards using:
99
100           $ git range-diff @{u} @{1} @
101
102
103       A typical output of git range-diff would look like this:
104
105           -:  ------- > 1:  0ddba11 Prepare for the inevitable!
106           1:  c0debee = 2:  cab005e Add a helpful message at the start
107           2:  f00dbal ! 3:  decafe1 Describe a bug
108               @@ -1,3 +1,3 @@
109                Author: A U Thor <author@example.com>
110
111               -TODO: Describe a bug
112               +Describe a bug
113               @@ -324,5 +324,6
114                 This is expected.
115
116               -+What is unexpected is that it will also crash.
117               ++Unexpectedly, it also crashes. This is a bug, and the jury is
118               ++still out there how to fix it best. See ticket #314 for details.
119
120                 Contact
121           3:  bedead < -:  ------- TO-UNDO
122
123
124       In this example, there are 3 old and 3 new commits, where the developer
125       removed the 3rd, added a new one before the first two, and modified the
126       commit message of the 2nd commit as well its diff.
127
128       When the output goes to a terminal, it is color-coded by default, just
129       like regular git diff's output. In addition, the first line (adding a
130       commit) is green, the last line (deleting a commit) is red, the second
131       line (with a perfect match) is yellow like the commit header of git
132       show's output, and the third line colors the old commit red, the new
133       one green and the rest like git show's commit header.
134
135       A naive color-coded diff of diffs is actually a bit hard to read,
136       though, as it colors the entire lines red or green. The line that added
137       "What is unexpected" in the old commit, for example, is completely red,
138       even if the intent of the old commit was to add something.
139
140       To help with that, range uses the --dual-color mode by default. In this
141       mode, the diff of diffs will retain the original diff colors, and
142       prefix the lines with -/+ markers that have their background red or
143       green, to make it more obvious that they describe how the diff itself
144       changed.
145

ALGORITHM

147       The general idea is this: we generate a cost matrix between the commits
148       in both commit ranges, then solve the least-cost assignment.
149
150       The cost matrix is populated thusly: for each pair of commits, both
151       diffs are generated and the "diff of diffs" is generated, with 3
152       context lines, then the number of lines in that diff is used as cost.
153
154       To avoid false positives (e.g. when a patch has been removed, and an
155       unrelated patch has been added between two iterations of the same patch
156       series), the cost matrix is extended to allow for that, by adding
157       fixed-cost entries for wholesale deletes/adds.
158
159       Example: Let commits 1--2 be the first iteration of a patch series and
160       A--C the second iteration. Let’s assume that A is a cherry-pick of 2,
161       and C is a cherry-pick of 1 but with a small modification (say, a fixed
162       typo). Visualize the commits as a bipartite graph:
163
164               1            A
165
166               2            B
167
168                            C
169
170
171       We are looking for a "best" explanation of the new series in terms of
172       the old one. We can represent an "explanation" as an edge in the graph:
173
174               1            A
175                          /
176               2 --------'  B
177
178                            C
179
180
181       This explanation comes for "free" because there was no change.
182       Similarly C could be explained using 1, but that comes at some cost c>0
183       because of the modification:
184
185               1 ----.      A
186                     |    /
187               2 ----+---'  B
188                     |
189                     `----- C
190                     c>0
191
192
193       In mathematical terms, what we are looking for is some sort of a
194       minimum cost bipartite matching; ‘1` is matched to C at some cost, etc.
195       The underlying graph is in fact a complete bipartite graph; the cost we
196       associate with every edge is the size of the diff between the two
197       commits’ patches. To explain also new commits, we introduce dummy nodes
198       on both sides:
199
200               1 ----.      A
201                     |    /
202               2 ----+---'  B
203                     |
204               o     `----- C
205                     c>0
206               o            o
207
208               o            o
209
210
211       The cost of an edge o--C is the size of C's diff, modified by a fudge
212       factor that should be smaller than 100%. The cost of an edge o--o is
213       free. The fudge factor is necessary because even if 1 and C have
214       nothing in common, they may still share a few empty lines and such,
215       possibly making the assignment 1--C, o--o slightly cheaper than 1--o,
216       o--C even if 1 and C have nothing in common. With the fudge factor we
217       require a much larger common part to consider patches as corresponding.
218
219       The overall time needed to compute this algorithm is the time needed to
220       compute n+m commit diffs and then n*m diffs of patches, plus the time
221       needed to compute the least-cost assigment between n and m diffs. Git
222       uses an implementation of the Jonker-Volgenant algorithm to solve the
223       assignment problem, which has cubic runtime complexity. The matching
224       found in this case will look like this:
225
226               1 ----.      A
227                     |    /
228               2 ----+---'  B
229                  .--+-----'
230               o -'  `----- C
231                     c>0
232               o ---------- o
233
234               o ---------- o
235
236

SEE ALSO

238       git-log(1)
239

GIT

241       Part of the git(1) suite
242
243
244
245Git 2.24.1                        12/10/2019                 GIT-RANGE-DIFF(1)
Impressum