blob: 200b0e047d5b4b7c9cb2da646f2c0f4e805c4c6c [file] [log] [blame]
Junio C Hamano2bd8a742009-12-01 21:16:591<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
2 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
4<head>
Junio C Hamano9d971152012-12-19 00:43:115<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
Junio C Hamanoc14e6ad2014-10-31 20:25:536<meta name="generator" content="AsciiDoc 8.6.9" />
Junio C Hamano103b5722011-01-31 05:03:457<title>Fighting regressions with git bisect</title>
Junio C Hamano2bd8a742009-12-01 21:16:598<style type="text/css">
Junio C Hamano9d971152012-12-19 00:43:119/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
10
11/* Default font. */
12body {
13 font-family: Georgia,serif;
14}
15
16/* Title font. */
17h1, h2, h3, h4, h5, h6,
18div.title, caption.title,
19thead, p.table.header,
20#toctitle,
21#author, #revnumber, #revdate, #revremark,
22#footer {
23 font-family: Arial,Helvetica,sans-serif;
Junio C Hamano2bd8a742009-12-01 21:16:5924}
25
26body {
27 margin: 1em 5% 1em 5%;
28}
29
30a {
31 color: blue;
32 text-decoration: underline;
33}
34a:visited {
35 color: fuchsia;
36}
37
38em {
39 font-style: italic;
Junio C Hamano103b5722011-01-31 05:03:4540 color: navy;
Junio C Hamano2bd8a742009-12-01 21:16:5941}
42
43strong {
44 font-weight: bold;
Junio C Hamano103b5722011-01-31 05:03:4545 color: #083194;
Junio C Hamano2bd8a742009-12-01 21:16:5946}
47
Junio C Hamano2bd8a742009-12-01 21:16:5948h1, h2, h3, h4, h5, h6 {
49 color: #527bbd;
Junio C Hamano2bd8a742009-12-01 21:16:5950 margin-top: 1.2em;
51 margin-bottom: 0.5em;
52 line-height: 1.3;
53}
54
55h1, h2, h3 {
56 border-bottom: 2px solid silver;
57}
58h2 {
59 padding-top: 0.5em;
60}
61h3 {
62 float: left;
63}
64h3 + * {
65 clear: left;
66}
Junio C Hamano9d971152012-12-19 00:43:1167h5 {
68 font-size: 1.0em;
69}
Junio C Hamano2bd8a742009-12-01 21:16:5970
71div.sectionbody {
Junio C Hamano2bd8a742009-12-01 21:16:5972 margin-left: 0;
73}
74
75hr {
76 border: 1px solid silver;
77}
78
79p {
80 margin-top: 0.5em;
81 margin-bottom: 0.5em;
82}
83
Junio C Hamano103b5722011-01-31 05:03:4584ul, ol, li > p {
85 margin-top: 0;
86}
Junio C Hamano9d971152012-12-19 00:43:1187ul > li { color: #aaa; }
88ul > li > * { color: black; }
Junio C Hamano103b5722011-01-31 05:03:4589
Junio C Hamanoc14e6ad2014-10-31 20:25:5390.monospaced, code, pre {
91 font-family: "Courier New", Courier, monospace;
92 font-size: inherit;
93 color: navy;
Junio C Hamano2bd8a742009-12-01 21:16:5994 padding: 0;
95 margin: 0;
96}
Junio C Hamanoc14e6ad2014-10-31 20:25:5397pre {
98 white-space: pre-wrap;
99}
Junio C Hamano2bd8a742009-12-01 21:16:59100
Junio C Hamano9d971152012-12-19 00:43:11101#author {
Junio C Hamano2bd8a742009-12-01 21:16:59102 color: #527bbd;
Junio C Hamano2bd8a742009-12-01 21:16:59103 font-weight: bold;
104 font-size: 1.1em;
105}
Junio C Hamano9d971152012-12-19 00:43:11106#email {
Junio C Hamano2bd8a742009-12-01 21:16:59107}
Junio C Hamano9d971152012-12-19 00:43:11108#revnumber, #revdate, #revremark {
Junio C Hamano2bd8a742009-12-01 21:16:59109}
110
Junio C Hamano9d971152012-12-19 00:43:11111#footer {
Junio C Hamano2bd8a742009-12-01 21:16:59112 font-size: small;
113 border-top: 2px solid silver;
114 padding-top: 0.5em;
115 margin-top: 4.0em;
116}
Junio C Hamano9d971152012-12-19 00:43:11117#footer-text {
Junio C Hamano2bd8a742009-12-01 21:16:59118 float: left;
119 padding-bottom: 0.5em;
120}
Junio C Hamano9d971152012-12-19 00:43:11121#footer-badges {
Junio C Hamano2bd8a742009-12-01 21:16:59122 float: right;
123 padding-bottom: 0.5em;
124}
125
Junio C Hamano9d971152012-12-19 00:43:11126#preamble {
Junio C Hamano103b5722011-01-31 05:03:45127 margin-top: 1.5em;
128 margin-bottom: 1.5em;
129}
Junio C Hamano9d971152012-12-19 00:43:11130div.imageblock, div.exampleblock, div.verseblock,
Junio C Hamano2bd8a742009-12-01 21:16:59131div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
132div.admonitionblock {
Junio C Hamano7bd050f2011-09-22 06:32:22133 margin-top: 1.0em;
Junio C Hamano2bd8a742009-12-01 21:16:59134 margin-bottom: 1.5em;
135}
136div.admonitionblock {
Junio C Hamano7bd050f2011-09-22 06:32:22137 margin-top: 2.0em;
138 margin-bottom: 2.0em;
139 margin-right: 10%;
140 color: #606060;
Junio C Hamano2bd8a742009-12-01 21:16:59141}
142
143div.content { /* Block element content. */
144 padding: 0;
145}
146
147/* Block element titles. */
148div.title, caption.title {
Junio C Hamano103b5722011-01-31 05:03:45149 color: #527bbd;
Junio C Hamano2bd8a742009-12-01 21:16:59150 font-weight: bold;
151 text-align: left;
152 margin-top: 1.0em;
153 margin-bottom: 0.5em;
154}
155div.title + * {
156 margin-top: 0;
157}
158
159td div.title:first-child {
160 margin-top: 0.0em;
161}
162div.content div.title:first-child {
163 margin-top: 0.0em;
164}
165div.content + div.title {
166 margin-top: 0.0em;
167}
168
169div.sidebarblock > div.content {
170 background: #ffffee;
Junio C Hamano9d971152012-12-19 00:43:11171 border: 1px solid #dddddd;
172 border-left: 4px solid #f0f0f0;
Junio C Hamano2bd8a742009-12-01 21:16:59173 padding: 0.5em;
174}
175
Junio C Hamano2bd8a742009-12-01 21:16:59176div.listingblock > div.content {
Junio C Hamano9d971152012-12-19 00:43:11177 border: 1px solid #dddddd;
178 border-left: 5px solid #f0f0f0;
179 background: #f8f8f8;
Junio C Hamano2bd8a742009-12-01 21:16:59180 padding: 0.5em;
181}
182
Junio C Hamano7bd050f2011-09-22 06:32:22183div.quoteblock, div.verseblock {
184 padding-left: 1.0em;
185 margin-left: 1.0em;
Junio C Hamano103b5722011-01-31 05:03:45186 margin-right: 10%;
Junio C Hamano9d971152012-12-19 00:43:11187 border-left: 5px solid #f0f0f0;
188 color: #888;
Junio C Hamano2bd8a742009-12-01 21:16:59189}
Junio C Hamano7bd050f2011-09-22 06:32:22190
Junio C Hamano103b5722011-01-31 05:03:45191div.quoteblock > div.attribution {
192 padding-top: 0.5em;
Junio C Hamano2bd8a742009-12-01 21:16:59193 text-align: right;
194}
Junio C Hamano103b5722011-01-31 05:03:45195
Junio C Hamano9d971152012-12-19 00:43:11196div.verseblock > pre.content {
197 font-family: inherit;
198 font-size: inherit;
Junio C Hamano103b5722011-01-31 05:03:45199}
200div.verseblock > div.attribution {
201 padding-top: 0.75em;
202 text-align: left;
203}
204/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
Junio C Hamano2bd8a742009-12-01 21:16:59205div.verseblock + div.attribution {
206 text-align: left;
207}
208
209div.admonitionblock .icon {
210 vertical-align: top;
211 font-size: 1.1em;
212 font-weight: bold;
213 text-decoration: underline;
214 color: #527bbd;
215 padding-right: 0.5em;
216}
217div.admonitionblock td.content {
218 padding-left: 0.5em;
Junio C Hamano7bd050f2011-09-22 06:32:22219 border-left: 3px solid #dddddd;
Junio C Hamano2bd8a742009-12-01 21:16:59220}
221
222div.exampleblock > div.content {
Junio C Hamano7bd050f2011-09-22 06:32:22223 border-left: 3px solid #dddddd;
224 padding-left: 0.5em;
Junio C Hamano2bd8a742009-12-01 21:16:59225}
226
Junio C Hamano2bd8a742009-12-01 21:16:59227div.imageblock div.content { padding-left: 0; }
Junio C Hamanoc14e6ad2014-10-31 20:25:53228span.image img { border-style: none; vertical-align: text-bottom; }
Junio C Hamano103b5722011-01-31 05:03:45229a.image:visited { color: white; }
Junio C Hamano2bd8a742009-12-01 21:16:59230
231dl {
232 margin-top: 0.8em;
233 margin-bottom: 0.8em;
234}
235dt {
236 margin-top: 0.5em;
237 margin-bottom: 0;
Junio C Hamano103b5722011-01-31 05:03:45238 font-style: normal;
239 color: navy;
Junio C Hamano2bd8a742009-12-01 21:16:59240}
241dd > *:first-child {
Junio C Hamano103b5722011-01-31 05:03:45242 margin-top: 0.1em;
Junio C Hamano2bd8a742009-12-01 21:16:59243}
244
245ul, ol {
246 list-style-position: outside;
247}
Junio C Hamano103b5722011-01-31 05:03:45248ol.arabic {
249 list-style-type: decimal;
250}
251ol.loweralpha {
Junio C Hamano2bd8a742009-12-01 21:16:59252 list-style-type: lower-alpha;
253}
Junio C Hamano103b5722011-01-31 05:03:45254ol.upperalpha {
255 list-style-type: upper-alpha;
256}
257ol.lowerroman {
258 list-style-type: lower-roman;
259}
260ol.upperroman {
261 list-style-type: upper-roman;
262}
263
264div.compact ul, div.compact ol,
265div.compact p, div.compact p,
266div.compact div, div.compact div {
267 margin-top: 0.1em;
268 margin-bottom: 0.1em;
269}
Junio C Hamano2bd8a742009-12-01 21:16:59270
Junio C Hamano2bd8a742009-12-01 21:16:59271tfoot {
272 font-weight: bold;
273}
Junio C Hamano103b5722011-01-31 05:03:45274td > div.verse {
275 white-space: pre;
276}
Junio C Hamano103b5722011-01-31 05:03:45277
278div.hdlist {
Junio C Hamano2bd8a742009-12-01 21:16:59279 margin-top: 0.8em;
280 margin-bottom: 0.8em;
281}
Junio C Hamano103b5722011-01-31 05:03:45282div.hdlist tr {
283 padding-bottom: 15px;
Junio C Hamano2bd8a742009-12-01 21:16:59284}
Junio C Hamano103b5722011-01-31 05:03:45285dt.hdlist1.strong, td.hdlist1.strong {
286 font-weight: bold;
287}
288td.hdlist1 {
Junio C Hamano2bd8a742009-12-01 21:16:59289 vertical-align: top;
Junio C Hamano103b5722011-01-31 05:03:45290 font-style: normal;
Junio C Hamano2bd8a742009-12-01 21:16:59291 padding-right: 0.8em;
Junio C Hamano103b5722011-01-31 05:03:45292 color: navy;
Junio C Hamano2bd8a742009-12-01 21:16:59293}
Junio C Hamano103b5722011-01-31 05:03:45294td.hdlist2 {
Junio C Hamano2bd8a742009-12-01 21:16:59295 vertical-align: top;
296}
Junio C Hamano103b5722011-01-31 05:03:45297div.hdlist.compact tr {
298 margin: 0;
299 padding-bottom: 0;
300}
301
302.comment {
303 background: yellow;
304}
Junio C Hamano2bd8a742009-12-01 21:16:59305
Junio C Hamano7bd050f2011-09-22 06:32:22306.footnote, .footnoteref {
307 font-size: 0.8em;
308}
309
310span.footnote, span.footnoteref {
311 vertical-align: super;
312}
313
314#footnotes {
315 margin: 20px 0 20px 0;
316 padding: 7px 0 0 0;
317}
318
319#footnotes div.footnote {
320 margin: 0 0 5px 0;
321}
322
323#footnotes hr {
324 border: none;
325 border-top: 1px solid silver;
326 height: 1px;
327 text-align: left;
328 margin-left: 0;
329 width: 20%;
330 min-width: 100px;
331}
332
Junio C Hamano9d971152012-12-19 00:43:11333div.colist td {
334 padding-right: 0.5em;
335 padding-bottom: 0.3em;
336 vertical-align: top;
337}
338div.colist td img {
339 margin-top: 0.3em;
Junio C Hamano2bd8a742009-12-01 21:16:59340}
341
Junio C Hamano9d971152012-12-19 00:43:11342@media print {
343 #footer-badges { display: none; }
344}
345
346#toc {
Junio C Hamano7bd050f2011-09-22 06:32:22347 margin-bottom: 2.5em;
348}
349
Junio C Hamano9d971152012-12-19 00:43:11350#toctitle {
Junio C Hamano2bd8a742009-12-01 21:16:59351 color: #527bbd;
Junio C Hamano2bd8a742009-12-01 21:16:59352 font-size: 1.1em;
353 font-weight: bold;
354 margin-top: 1.0em;
355 margin-bottom: 0.1em;
356}
357
Junio C Hamanoc14e6ad2014-10-31 20:25:53358div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
Junio C Hamano2bd8a742009-12-01 21:16:59359 margin-top: 0;
360 margin-bottom: 0;
361}
362div.toclevel2 {
363 margin-left: 2em;
364 font-size: 0.9em;
365}
366div.toclevel3 {
367 margin-left: 4em;
368 font-size: 0.9em;
369}
370div.toclevel4 {
371 margin-left: 6em;
372 font-size: 0.9em;
373}
Junio C Hamano2bd8a742009-12-01 21:16:59374
Junio C Hamano9d971152012-12-19 00:43:11375span.aqua { color: aqua; }
376span.black { color: black; }
377span.blue { color: blue; }
378span.fuchsia { color: fuchsia; }
379span.gray { color: gray; }
380span.green { color: green; }
381span.lime { color: lime; }
382span.maroon { color: maroon; }
383span.navy { color: navy; }
384span.olive { color: olive; }
385span.purple { color: purple; }
386span.red { color: red; }
387span.silver { color: silver; }
388span.teal { color: teal; }
389span.white { color: white; }
390span.yellow { color: yellow; }
391
392span.aqua-background { background: aqua; }
393span.black-background { background: black; }
394span.blue-background { background: blue; }
395span.fuchsia-background { background: fuchsia; }
396span.gray-background { background: gray; }
397span.green-background { background: green; }
398span.lime-background { background: lime; }
399span.maroon-background { background: maroon; }
400span.navy-background { background: navy; }
401span.olive-background { background: olive; }
402span.purple-background { background: purple; }
403span.red-background { background: red; }
404span.silver-background { background: silver; }
405span.teal-background { background: teal; }
406span.white-background { background: white; }
407span.yellow-background { background: yellow; }
408
409span.big { font-size: 2em; }
410span.small { font-size: 0.6em; }
411
412span.underline { text-decoration: underline; }
413span.overline { text-decoration: overline; }
414span.line-through { text-decoration: line-through; }
415
Junio C Hamanoc14e6ad2014-10-31 20:25:53416div.unbreakable { page-break-inside: avoid; }
417
Junio C Hamano9d971152012-12-19 00:43:11418
419/*
420 * xhtml11 specific
421 *
422 * */
423
424div.tableblock {
425 margin-top: 1.0em;
426 margin-bottom: 1.5em;
Junio C Hamano2bd8a742009-12-01 21:16:59427}
Junio C Hamano9d971152012-12-19 00:43:11428div.tableblock > table {
429 border: 3px solid #527bbd;
430}
431thead, p.table.header {
Junio C Hamano2bd8a742009-12-01 21:16:59432 font-weight: bold;
Junio C Hamano9d971152012-12-19 00:43:11433 color: #527bbd;
434}
435p.table {
436 margin-top: 0;
437}
438/* Because the table frame attribute is overriden by CSS in most browsers. */
439div.tableblock > table[frame="void"] {
440 border-style: none;
441}
442div.tableblock > table[frame="hsides"] {
443 border-left-style: none;
444 border-right-style: none;
445}
446div.tableblock > table[frame="vsides"] {
447 border-top-style: none;
448 border-bottom-style: none;
Junio C Hamano2bd8a742009-12-01 21:16:59449}
450
Junio C Hamano9d971152012-12-19 00:43:11451
452/*
453 * html5 specific
454 *
455 * */
456
457table.tableblock {
458 margin-top: 1.0em;
459 margin-bottom: 1.5em;
460}
461thead, p.tableblock.header {
462 font-weight: bold;
463 color: #527bbd;
464}
465p.tableblock {
466 margin-top: 0;
467}
468table.tableblock {
469 border-width: 3px;
470 border-spacing: 0px;
471 border-style: solid;
472 border-color: #527bbd;
473 border-collapse: collapse;
474}
475th.tableblock, td.tableblock {
476 border-width: 1px;
477 padding: 4px;
478 border-style: solid;
479 border-color: #527bbd;
Junio C Hamano2bd8a742009-12-01 21:16:59480}
481
Junio C Hamano9d971152012-12-19 00:43:11482table.tableblock.frame-topbot {
483 border-left-style: hidden;
484 border-right-style: hidden;
485}
486table.tableblock.frame-sides {
487 border-top-style: hidden;
488 border-bottom-style: hidden;
489}
490table.tableblock.frame-none {
491 border-style: hidden;
492}
493
494th.tableblock.halign-left, td.tableblock.halign-left {
495 text-align: left;
496}
497th.tableblock.halign-center, td.tableblock.halign-center {
498 text-align: center;
499}
500th.tableblock.halign-right, td.tableblock.halign-right {
Junio C Hamano103b5722011-01-31 05:03:45501 text-align: right;
502}
503
Junio C Hamano9d971152012-12-19 00:43:11504th.tableblock.valign-top, td.tableblock.valign-top {
505 vertical-align: top;
Junio C Hamano103b5722011-01-31 05:03:45506}
Junio C Hamano9d971152012-12-19 00:43:11507th.tableblock.valign-middle, td.tableblock.valign-middle {
508 vertical-align: middle;
509}
510th.tableblock.valign-bottom, td.tableblock.valign-bottom {
511 vertical-align: bottom;
Junio C Hamano2bd8a742009-12-01 21:16:59512}
513
Junio C Hamano9d971152012-12-19 00:43:11514
515/*
516 * manpage specific
517 *
518 * */
519
520body.manpage h1 {
521 padding-top: 0.5em;
522 padding-bottom: 0.5em;
523 border-top: 2px solid silver;
524 border-bottom: 2px solid silver;
525}
526body.manpage h2 {
527 border-style: none;
528}
529body.manpage div.sectionbody {
530 margin-left: 3em;
Junio C Hamano2bd8a742009-12-01 21:16:59531}
532
Junio C Hamano9d971152012-12-19 00:43:11533@media print {
534 body.manpage div#toc { display: none; }
535}
Junio C Hamanoc14e6ad2014-10-31 20:25:53536
537
Junio C Hamano2bd8a742009-12-01 21:16:59538</style>
Junio C Hamano7bd050f2011-09-22 06:32:22539<script type="text/javascript">
540/*<![CDATA[*/
Junio C Hamano7bd050f2011-09-22 06:32:22541var asciidoc = { // Namespace.
542
543/////////////////////////////////////////////////////////////////////
544// Table Of Contents generator
545/////////////////////////////////////////////////////////////////////
546
547/* Author: Mihai Bazon, September 2002
548 * http://students.infoiasi.ro/~mishoo
549 *
550 * Table Of Content generator
551 * Version: 0.4
552 *
553 * Feel free to use this script under the terms of the GNU General Public
554 * License, as long as you do not remove or alter this notice.
555 */
556
557 /* modified by Troy D. Hanson, September 2006. License: GPL */
558 /* modified by Stuart Rackham, 2006, 2009. License: GPL */
559
560// toclevels = 1..4.
561toc: function (toclevels) {
562
563 function getText(el) {
564 var text = "";
565 for (var i = el.firstChild; i != null; i = i.nextSibling) {
566 if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
567 text += i.data;
568 else if (i.firstChild != null)
569 text += getText(i);
570 }
571 return text;
572 }
573
574 function TocEntry(el, text, toclevel) {
575 this.element = el;
576 this.text = text;
577 this.toclevel = toclevel;
578 }
579
580 function tocEntries(el, toclevels) {
581 var result = new Array;
Junio C Hamanoc14e6ad2014-10-31 20:25:53582 var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
Junio C Hamano7bd050f2011-09-22 06:32:22583 // Function that scans the DOM tree for header elements (the DOM2
584 // nodeIterator API would be a better technique but not supported by all
585 // browsers).
586 var iterate = function (el) {
587 for (var i = el.firstChild; i != null; i = i.nextSibling) {
588 if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
589 var mo = re.exec(i.tagName);
590 if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
591 result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
592 }
593 iterate(i);
594 }
595 }
596 }
597 iterate(el);
598 return result;
599 }
600
601 var toc = document.getElementById("toc");
Junio C Hamano9d971152012-12-19 00:43:11602 if (!toc) {
603 return;
604 }
605
606 // Delete existing TOC entries in case we're reloading the TOC.
607 var tocEntriesToRemove = [];
608 var i;
609 for (i = 0; i < toc.childNodes.length; i++) {
610 var entry = toc.childNodes[i];
Junio C Hamanoc14e6ad2014-10-31 20:25:53611 if (entry.nodeName.toLowerCase() == 'div'
Junio C Hamano9d971152012-12-19 00:43:11612 && entry.getAttribute("class")
613 && entry.getAttribute("class").match(/^toclevel/))
614 tocEntriesToRemove.push(entry);
615 }
616 for (i = 0; i < tocEntriesToRemove.length; i++) {
617 toc.removeChild(tocEntriesToRemove[i]);
618 }
619
620 // Rebuild TOC entries.
Junio C Hamano7bd050f2011-09-22 06:32:22621 var entries = tocEntries(document.getElementById("content"), toclevels);
622 for (var i = 0; i < entries.length; ++i) {
623 var entry = entries[i];
624 if (entry.element.id == "")
625 entry.element.id = "_toc_" + i;
626 var a = document.createElement("a");
627 a.href = "#" + entry.element.id;
628 a.appendChild(document.createTextNode(entry.text));
629 var div = document.createElement("div");
630 div.appendChild(a);
631 div.className = "toclevel" + entry.toclevel;
632 toc.appendChild(div);
633 }
634 if (entries.length == 0)
635 toc.parentNode.removeChild(toc);
636},
637
638
639/////////////////////////////////////////////////////////////////////
640// Footnotes generator
641/////////////////////////////////////////////////////////////////////
642
643/* Based on footnote generation code from:
644 * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
645 */
646
647footnotes: function () {
Junio C Hamano9d971152012-12-19 00:43:11648 // Delete existing footnote entries in case we're reloading the footnodes.
649 var i;
Junio C Hamano7bd050f2011-09-22 06:32:22650 var noteholder = document.getElementById("footnotes");
Junio C Hamano9d971152012-12-19 00:43:11651 if (!noteholder) {
652 return;
653 }
654 var entriesToRemove = [];
655 for (i = 0; i < noteholder.childNodes.length; i++) {
656 var entry = noteholder.childNodes[i];
Junio C Hamanoc14e6ad2014-10-31 20:25:53657 if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
Junio C Hamano9d971152012-12-19 00:43:11658 entriesToRemove.push(entry);
659 }
660 for (i = 0; i < entriesToRemove.length; i++) {
661 noteholder.removeChild(entriesToRemove[i]);
662 }
663
664 // Rebuild footnote entries.
665 var cont = document.getElementById("content");
Junio C Hamano7bd050f2011-09-22 06:32:22666 var spans = cont.getElementsByTagName("span");
667 var refs = {};
668 var n = 0;
669 for (i=0; i<spans.length; i++) {
670 if (spans[i].className == "footnote") {
671 n++;
Junio C Hamano9d971152012-12-19 00:43:11672 var note = spans[i].getAttribute("data-note");
673 if (!note) {
674 // Use [\s\S] in place of . so multi-line matches work.
675 // Because JavaScript has no s (dotall) regex flag.
676 note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
677 spans[i].innerHTML =
678 "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
679 "' title='View footnote' class='footnote'>" + n + "</a>]";
680 spans[i].setAttribute("data-note", note);
681 }
Junio C Hamano7bd050f2011-09-22 06:32:22682 noteholder.innerHTML +=
683 "<div class='footnote' id='_footnote_" + n + "'>" +
684 "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
685 n + "</a>. " + note + "</div>";
Junio C Hamano7bd050f2011-09-22 06:32:22686 var id =spans[i].getAttribute("id");
687 if (id != null) refs["#"+id] = n;
688 }
689 }
690 if (n == 0)
691 noteholder.parentNode.removeChild(noteholder);
692 else {
693 // Process footnoterefs.
694 for (i=0; i<spans.length; i++) {
695 if (spans[i].className == "footnoteref") {
696 var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
697 href = href.match(/#.*/)[0]; // Because IE return full URL.
698 n = refs[href];
699 spans[i].innerHTML =
700 "[<a href='#_footnote_" + n +
701 "' title='View footnote' class='footnote'>" + n + "</a>]";
702 }
703 }
704 }
Junio C Hamano9d971152012-12-19 00:43:11705},
706
707install: function(toclevels) {
708 var timerId;
709
710 function reinstall() {
711 asciidoc.footnotes();
712 if (toclevels) {
713 asciidoc.toc(toclevels);
714 }
715 }
716
717 function reinstallAndRemoveTimer() {
718 clearInterval(timerId);
719 reinstall();
720 }
721
722 timerId = setInterval(reinstall, 500);
723 if (document.addEventListener)
724 document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
725 else
726 window.onload = reinstallAndRemoveTimer;
Junio C Hamano7bd050f2011-09-22 06:32:22727}
728
729}
Junio C Hamano9d971152012-12-19 00:43:11730asciidoc.install();
Junio C Hamano7bd050f2011-09-22 06:32:22731/*]]>*/
732</script>
Junio C Hamano2bd8a742009-12-01 21:16:59733</head>
Junio C Hamano9d971152012-12-19 00:43:11734<body class="article">
Junio C Hamano2bd8a742009-12-01 21:16:59735<div id="header">
736<h1>Fighting regressions with git bisect</h1>
737<span id="author">Christian Couder</span><br />
Junio C Hamanoc14e6ad2014-10-31 20:25:53738<span id="email"><code>&lt;<a href="mailto:chriscool@tuxfamily.org">chriscool@tuxfamily.org</a>&gt;</code></span><br />
Junio C Hamano103b5722011-01-31 05:03:45739<span id="revdate">2009/11/08</span>
Junio C Hamano2bd8a742009-12-01 21:16:59740</div>
Junio C Hamano7bd050f2011-09-22 06:32:22741<div id="content">
Junio C Hamano9d971152012-12-19 00:43:11742<div class="sect1">
Junio C Hamano2bd8a742009-12-01 21:16:59743<h2 id="_abstract">Abstract</h2>
744<div class="sectionbody">
Junio C Hamano103b5722011-01-31 05:03:45745<div class="paragraph"><p>"git bisect" enables software users and developers to easily find the
Junio C Hamano2bd8a742009-12-01 21:16:59746commit that introduced a regression. We show why it is important to
747have good tools to fight regressions. We describe how "git bisect"
748works from the outside and the algorithms it uses inside. Then we
749explain how to take advantage of "git bisect" to improve current
750practices. And we discuss how "git bisect" could improve in the
751future.</p></div>
752</div>
Junio C Hamano9d971152012-12-19 00:43:11753</div>
754<div class="sect1">
Junio C Hamano2bd8a742009-12-01 21:16:59755<h2 id="_introduction_to_git_bisect">Introduction to "git bisect"</h2>
756<div class="sectionbody">
Junio C Hamano103b5722011-01-31 05:03:45757<div class="paragraph"><p>Git is a Distributed Version Control system (DVCS) created by Linus
Junio C Hamano2bd8a742009-12-01 21:16:59758Torvalds and maintained by Junio Hamano.</p></div>
Junio C Hamano103b5722011-01-31 05:03:45759<div class="paragraph"><p>In Git like in many other Version Control Systems (VCS), the different
Junio C Hamano2bd8a742009-12-01 21:16:59760states of the data that is managed by the system are called
761commits. And, as VCS are mostly used to manage software source code,
762sometimes "interesting" changes of behavior in the software are
763introduced in some commits.</p></div>
Junio C Hamano103b5722011-01-31 05:03:45764<div class="paragraph"><p>In fact people are specially interested in commits that introduce a
Junio C Hamano2bd8a742009-12-01 21:16:59765"bad" behavior, called a bug or a regression. They are interested in
766these commits because a commit (hopefully) contains a very small set
Junio C Hamano103b5722011-01-31 05:03:45767of source code changes. And it&#8217;s much easier to understand and
Junio C Hamano2bd8a742009-12-01 21:16:59768properly fix a problem when you only need to check a very small set of
Junio C Hamano103b5722011-01-31 05:03:45769changes, than when you don&#8217;t know where look in the first place.</p></div>
770<div class="paragraph"><p>So to help people find commits that introduce a "bad" behavior, the
Junio C Hamano2bd8a742009-12-01 21:16:59771"git bisect" set of commands was invented. And it follows of course
772that in "git bisect" parlance, commits where the "interesting
773behavior" is present are called "bad" commits, while other commits are
774called "good" commits. And a commit that introduce the behavior we are
775interested in is called a "first bad commit". Note that there could be
776more than one "first bad commit" in the commit space we are searching.</p></div>
Junio C Hamano103b5722011-01-31 05:03:45777<div class="paragraph"><p>So "git bisect" is designed to help find a "first bad commit". And to
Junio C Hamano2bd8a742009-12-01 21:16:59778be as efficient as possible, it tries to perform a binary search.</p></div>
779</div>
Junio C Hamano9d971152012-12-19 00:43:11780</div>
781<div class="sect1">
Junio C Hamano2bd8a742009-12-01 21:16:59782<h2 id="_fighting_regressions_overview">Fighting regressions overview</h2>
783<div class="sectionbody">
Junio C Hamano9d971152012-12-19 00:43:11784<div class="sect2">
785<h3 id="_regressions_a_big_problem">Regressions: a big problem</h3>
Junio C Hamano103b5722011-01-31 05:03:45786<div class="paragraph"><p>Regressions are a big problem in the software industry. But it&#8217;s
Junio C Hamano2bd8a742009-12-01 21:16:59787difficult to put some real numbers behind that claim.</p></div>
Junio C Hamano103b5722011-01-31 05:03:45788<div class="paragraph"><p>There are some numbers about bugs in general, like a NIST study in
Junio C Hamano2bd8a742009-12-01 21:16:597892002 <a href="#1">[1]</a> that said:</p></div>
790<div class="quoteblock">
Junio C Hamano9d971152012-12-19 00:43:11791<div class="content">
Junio C Hamano103b5722011-01-31 05:03:45792<div class="paragraph"><p>Software bugs, or errors, are so prevalent and so detrimental that
Junio C Hamano2bd8a742009-12-01 21:16:59793they cost the U.S. economy an estimated $59.5 billion annually, or
794about 0.6 percent of the gross domestic product, according to a newly
Junio C Hamano103b5722011-01-31 05:03:45795released study commissioned by the Department of Commerce&#8217;s National
Junio C Hamano2bd8a742009-12-01 21:16:59796Institute of Standards and Technology (NIST). At the national level,
797over half of the costs are borne by software users and the remainder
798by software developers/vendors. The study also found that, although
799all errors cannot be removed, more than a third of these costs, or an
800estimated $22.2 billion, could be eliminated by an improved testing
801infrastructure that enables earlier and more effective identification
802and removal of software defects. These are the savings associated with
803finding an increased percentage (but not 100 percent) of errors closer
804to the development stages in which they are introduced. Currently,
805over half of all errors are not found until "downstream" in the
806development process or during post-sale software use.</p></div>
Junio C Hamano103b5722011-01-31 05:03:45807</div>
Junio C Hamano9d971152012-12-19 00:43:11808<div class="attribution">
Junio C Hamano103b5722011-01-31 05:03:45809</div></div>
810<div class="paragraph"><p>And then:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:59811<div class="quoteblock">
Junio C Hamano9d971152012-12-19 00:43:11812<div class="content">
Junio C Hamano103b5722011-01-31 05:03:45813<div class="paragraph"><p>Software developers already spend approximately 80 percent of
Junio C Hamano2bd8a742009-12-01 21:16:59814development costs on identifying and correcting defects, and yet few
815products of any type other than software are shipped with such high
816levels of errors.</p></div>
Junio C Hamano103b5722011-01-31 05:03:45817</div>
Junio C Hamano9d971152012-12-19 00:43:11818<div class="attribution">
Junio C Hamano103b5722011-01-31 05:03:45819</div></div>
820<div class="paragraph"><p>Eventually the conclusion started with:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:59821<div class="quoteblock">
Junio C Hamano9d971152012-12-19 00:43:11822<div class="content">
Junio C Hamano103b5722011-01-31 05:03:45823<div class="paragraph"><p>The path to higher software quality is significantly improved software
Junio C Hamano2bd8a742009-12-01 21:16:59824testing.</p></div>
Junio C Hamano103b5722011-01-31 05:03:45825</div>
Junio C Hamano9d971152012-12-19 00:43:11826<div class="attribution">
Junio C Hamano103b5722011-01-31 05:03:45827</div></div>
828<div class="paragraph"><p>There are other estimates saying that 80% of the cost related to
Junio C Hamano2bd8a742009-12-01 21:16:59829software is about maintenance <a href="#2">[2]</a>.</p></div>
Junio C Hamano103b5722011-01-31 05:03:45830<div class="paragraph"><p>Though, according to Wikipedia <a href="#3">[3]</a>:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:59831<div class="quoteblock">
Junio C Hamano9d971152012-12-19 00:43:11832<div class="content">
Junio C Hamano103b5722011-01-31 05:03:45833<div class="paragraph"><p>A common perception of maintenance is that it is merely fixing
Junio C Hamano2bd8a742009-12-01 21:16:59834bugs. However, studies and surveys over the years have indicated that
835the majority, over 80%, of the maintenance effort is used for
836non-corrective actions (Pigosky 1997). This perception is perpetuated
837by users submitting problem reports that in reality are functionality
838enhancements to the system.</p></div>
Junio C Hamano103b5722011-01-31 05:03:45839</div>
Junio C Hamano9d971152012-12-19 00:43:11840<div class="attribution">
Junio C Hamano103b5722011-01-31 05:03:45841</div></div>
842<div class="paragraph"><p>But we can guess that improving on existing software is very costly
Junio C Hamano2bd8a742009-12-01 21:16:59843because you have to watch out for regressions. At least this would
844make the above studies consistent among themselves.</p></div>
Junio C Hamano103b5722011-01-31 05:03:45845<div class="paragraph"><p>Of course some kind of software is developed, then used during some
Junio C Hamano2bd8a742009-12-01 21:16:59846time without being improved on much, and then finally thrown away. In
847this case, of course, regressions may not be a big problem. But on the
848other hand, there is a lot of big software that is continually
849developed and maintained during years or even tens of years by a lot
850of people. And as there are often many people who depend (sometimes
851critically) on such software, regressions are a really big problem.</p></div>
Junio C Hamanofb5ffde2014-11-04 22:38:56852<div class="paragraph"><p>One such software is the Linux kernel. And if we look at the Linux
Junio C Hamano2bd8a742009-12-01 21:16:59853kernel, we can see that a lot of time and effort is spent to fight
854regressions. The release cycle start with a 2 weeks long merge
855window. Then the first release candidate (rc) version is tagged. And
856after that about 7 or 8 more rc versions will appear with around one
857week between each of them, before the final release.</p></div>
Junio C Hamano103b5722011-01-31 05:03:45858<div class="paragraph"><p>The time between the first rc release and the final release is
Junio C Hamano2bd8a742009-12-01 21:16:59859supposed to be used to test rc versions and fight bugs and especially
860regressions. And this time is more than 80% of the release cycle
861time. But this is not the end of the fight yet, as of course it
862continues after the release.</p></div>
Junio C Hamanofb5ffde2014-11-04 22:38:56863<div class="paragraph"><p>And then this is what Ingo Molnar (a well known Linux kernel
Junio C Hamano2bd8a742009-12-01 21:16:59864developer) says about his use of git bisect:</p></div>
865<div class="quoteblock">
Junio C Hamano9d971152012-12-19 00:43:11866<div class="content">
Junio C Hamano103b5722011-01-31 05:03:45867<div class="paragraph"><p>I most actively use it during the merge window (when a lot of trees
Junio C Hamano2bd8a742009-12-01 21:16:59868get merged upstream and when the influx of bugs is the highest) - and
869yes, there have been cases that i used it multiple times a day. My
870average is roughly once a day.</p></div>
Junio C Hamano103b5722011-01-31 05:03:45871</div>
Junio C Hamano9d971152012-12-19 00:43:11872<div class="attribution">
Junio C Hamano103b5722011-01-31 05:03:45873</div></div>
874<div class="paragraph"><p>So regressions are fought all the time by developers, and indeed it is
Junio C Hamano2bd8a742009-12-01 21:16:59875well known that bugs should be fixed as soon as possible, so as soon
Junio C Hamano103b5722011-01-31 05:03:45876as they are found. That&#8217;s why it is interesting to have good tools for
Junio C Hamano2bd8a742009-12-01 21:16:59877this purpose.</p></div>
Junio C Hamano9d971152012-12-19 00:43:11878</div>
879<div class="sect2">
880<h3 id="_other_tools_to_fight_regressions">Other tools to fight regressions</h3>
Junio C Hamano103b5722011-01-31 05:03:45881<div class="paragraph"><p>So what are the tools used to fight regressions? They are nearly the
Junio C Hamano2bd8a742009-12-01 21:16:59882same as those used to fight regular bugs. The only specific tools are
883test suites and tools similar as "git bisect".</p></div>
Junio C Hamano103b5722011-01-31 05:03:45884<div class="paragraph"><p>Test suites are very nice. But when they are used alone, they are
Junio C Hamano2bd8a742009-12-01 21:16:59885supposed to be used so that all the tests are checked after each
886commit. This means that they are not very efficient, because many
887tests are run for no interesting result, and they suffer from
888combinational explosion.</p></div>
Junio C Hamano103b5722011-01-31 05:03:45889<div class="paragraph"><p>In fact the problem is that big software often has many different
Junio C Hamano2bd8a742009-12-01 21:16:59890configuration options and that each test case should pass for each
891configuration after each commit. So if you have for each release: N
892configurations, M commits and T test cases, you should perform:</p></div>
893<div class="listingblock">
894<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:53895<pre><code>N * M * T tests</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:59896</div></div>
Junio C Hamano103b5722011-01-31 05:03:45897<div class="paragraph"><p>where N, M and T are all growing with the size your software.</p></div>
898<div class="paragraph"><p>So very soon it will not be possible to completely test everything.</p></div>
899<div class="paragraph"><p>And if some bugs slip through your test suite, then you can add a test
Junio C Hamano2bd8a742009-12-01 21:16:59900to your test suite. But if you want to use your new improved test
901suite to find where the bug slipped in, then you will either have to
902emulate a bisection process or you will perhaps bluntly test each
903commit backward starting from the "bad" commit you have which may be
904very wasteful.</p></div>
905</div>
Junio C Hamano9d971152012-12-19 00:43:11906</div>
907</div>
908<div class="sect1">
Junio C Hamano2bd8a742009-12-01 21:16:59909<h2 id="_git_bisect_overview">"git bisect" overview</h2>
910<div class="sectionbody">
Junio C Hamano9d971152012-12-19 00:43:11911<div class="sect2">
912<h3 id="_starting_a_bisection">Starting a bisection</h3>
Junio C Hamano103b5722011-01-31 05:03:45913<div class="paragraph"><p>The first "git bisect" subcommand to use is "git bisect start" to
Junio C Hamano2bd8a742009-12-01 21:16:59914start the search. Then bounds must be set to limit the commit
915space. This is done usually by giving one "bad" and at least one
916"good" commit. They can be passed in the initial call to "git bisect
917start" like this:</p></div>
918<div class="listingblock">
919<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:53920<pre><code>$ git bisect start [BAD [GOOD...]]</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:59921</div></div>
Junio C Hamano103b5722011-01-31 05:03:45922<div class="paragraph"><p>or they can be set using:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:59923<div class="listingblock">
924<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:53925<pre><code>$ git bisect bad [COMMIT]</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:59926</div></div>
Junio C Hamano103b5722011-01-31 05:03:45927<div class="paragraph"><p>and:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:59928<div class="listingblock">
929<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:53930<pre><code>$ git bisect good [COMMIT...]</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:59931</div></div>
Junio C Hamano103b5722011-01-31 05:03:45932<div class="paragraph"><p>where BAD, GOOD and COMMIT are all names that can be resolved to a
Junio C Hamano2bd8a742009-12-01 21:16:59933commit.</p></div>
Junio C Hamano103b5722011-01-31 05:03:45934<div class="paragraph"><p>Then "git bisect" will checkout a commit of its choosing and ask the
Junio C Hamano2bd8a742009-12-01 21:16:59935user to test it, like this:</p></div>
936<div class="listingblock">
937<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:53938<pre><code>$ git bisect start v2.6.27 v2.6.25
Junio C Hamano2bd8a742009-12-01 21:16:59939Bisecting: 10928 revisions left to test after this (roughly 14 steps)
Junio C Hamanoc14e6ad2014-10-31 20:25:53940[2ec65f8b89ea003c27ff7723525a2ee335a2b393] x86: clean up using max_low_pfn on 32-bit</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:59941</div></div>
Junio C Hamano103b5722011-01-31 05:03:45942<div class="paragraph"><p>Note that the example that we will use is really a toy example, we
Junio C Hamano2bd8a742009-12-01 21:16:59943will be looking for the first commit that has a version like
944"2.6.26-something", that is the commit that has a "SUBLEVEL = 26" line
945in the top level Makefile. This is a toy example because there are
Junio C Hamano076ffcc2013-02-06 05:13:21946better ways to find this commit with Git than using "git bisect" (for
Junio C Hamano2bd8a742009-12-01 21:16:59947example "git blame" or "git log -S&lt;string&gt;").</p></div>
Junio C Hamano9d971152012-12-19 00:43:11948</div>
949<div class="sect2">
950<h3 id="_driving_a_bisection_manually">Driving a bisection manually</h3>
Junio C Hamano103b5722011-01-31 05:03:45951<div class="paragraph"><p>At this point there are basically 2 ways to drive the search. It can
Junio C Hamano2bd8a742009-12-01 21:16:59952be driven manually by the user or it can be driven automatically by a
953script or a command.</p></div>
Junio C Hamano103b5722011-01-31 05:03:45954<div class="paragraph"><p>If the user is driving it, then at each step of the search, the user
Junio C Hamano2bd8a742009-12-01 21:16:59955will have to test the current commit and say if it is "good" or "bad"
956using the "git bisect good" or "git bisect bad" commands respectively
957that have been described above. For example:</p></div>
958<div class="listingblock">
959<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:53960<pre><code>$ git bisect bad
Junio C Hamano2bd8a742009-12-01 21:16:59961Bisecting: 5480 revisions left to test after this (roughly 13 steps)
Junio C Hamanoc14e6ad2014-10-31 20:25:53962[66c0b394f08fd89236515c1c84485ea712a157be] KVM: kill file-&gt;f_count abuse in kvm</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:59963</div></div>
Junio C Hamano103b5722011-01-31 05:03:45964<div class="paragraph"><p>And after a few more steps like that, "git bisect" will eventually
Junio C Hamano2bd8a742009-12-01 21:16:59965find a first bad commit:</p></div>
966<div class="listingblock">
967<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:53968<pre><code>$ git bisect bad
Junio C Hamano2bd8a742009-12-01 21:16:599692ddcca36c8bcfa251724fe342c8327451988be0d is the first bad commit
970commit 2ddcca36c8bcfa251724fe342c8327451988be0d
971Author: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
972Date: Sat May 3 11:59:44 2008 -0700
973
974 Linux 2.6.26-rc1
975
Junio C Hamanoc14e6ad2014-10-31 20:25:53976:100644 100644 5cf82581... 4492984e... M Makefile</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:59977</div></div>
Junio C Hamano103b5722011-01-31 05:03:45978<div class="paragraph"><p>At this point we can see what the commit does, check it out (if it&#8217;s
Junio C Hamano2bd8a742009-12-01 21:16:59979not already checked out) or tinker with it, for example:</p></div>
980<div class="listingblock">
981<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:53982<pre><code>$ git show HEAD
Junio C Hamano2bd8a742009-12-01 21:16:59983commit 2ddcca36c8bcfa251724fe342c8327451988be0d
984Author: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
985Date: Sat May 3 11:59:44 2008 -0700
986
987 Linux 2.6.26-rc1
988
989diff --git a/Makefile b/Makefile
990index 5cf8258..4492984 100644
991--- a/Makefile
992+++ b/Makefile
993@@ -1,7 +1,7 @@
994 VERSION = 2
995 PATCHLEVEL = 6
996-SUBLEVEL = 25
997-EXTRAVERSION =
998+SUBLEVEL = 26
999+EXTRAVERSION = -rc1
1000 NAME = Funky Weasel is Jiggy wit it
1001
Junio C Hamanoc14e6ad2014-10-31 20:25:531002 # *DOCUMENTATION*</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591003</div></div>
Junio C Hamano103b5722011-01-31 05:03:451004<div class="paragraph"><p>And when we are finished we can use "git bisect reset" to go back to
Junio C Hamano2bd8a742009-12-01 21:16:591005the branch we were in before we started bisecting:</p></div>
1006<div class="listingblock">
1007<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531008<pre><code>$ git bisect reset
Junio C Hamano2bd8a742009-12-01 21:16:591009Checking out files: 100% (21549/21549), done.
1010Previous HEAD position was 2ddcca3... Linux 2.6.26-rc1
Junio C Hamanoc14e6ad2014-10-31 20:25:531011Switched to branch 'master'</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591012</div></div>
Junio C Hamano9d971152012-12-19 00:43:111013</div>
1014<div class="sect2">
1015<h3 id="_driving_a_bisection_automatically">Driving a bisection automatically</h3>
Junio C Hamano103b5722011-01-31 05:03:451016<div class="paragraph"><p>The other way to drive the bisection process is to tell "git bisect"
Junio C Hamano2bd8a742009-12-01 21:16:591017to launch a script or command at each bisection step to know if the
1018current commit is "good" or "bad". To do that, we use the "git bisect
1019run" command. For example:</p></div>
1020<div class="listingblock">
1021<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531022<pre><code>$ git bisect start v2.6.27 v2.6.25
Junio C Hamano2bd8a742009-12-01 21:16:591023Bisecting: 10928 revisions left to test after this (roughly 14 steps)
1024[2ec65f8b89ea003c27ff7723525a2ee335a2b393] x86: clean up using max_low_pfn on 32-bit
1025$
1026$ git bisect run grep '^SUBLEVEL = 25' Makefile
1027running grep ^SUBLEVEL = 25 Makefile
1028Bisecting: 5480 revisions left to test after this (roughly 13 steps)
1029[66c0b394f08fd89236515c1c84485ea712a157be] KVM: kill file-&gt;f_count abuse in kvm
1030running grep ^SUBLEVEL = 25 Makefile
1031SUBLEVEL = 25
1032Bisecting: 2740 revisions left to test after this (roughly 12 steps)
1033[671294719628f1671faefd4882764886f8ad08cb] V4L/DVB(7879): Adding cx18 Support for mxl5005s
1034...
1035...
1036running grep ^SUBLEVEL = 25 Makefile
1037Bisecting: 0 revisions left to test after this (roughly 0 steps)
1038[2ddcca36c8bcfa251724fe342c8327451988be0d] Linux 2.6.26-rc1
1039running grep ^SUBLEVEL = 25 Makefile
10402ddcca36c8bcfa251724fe342c8327451988be0d is the first bad commit
1041commit 2ddcca36c8bcfa251724fe342c8327451988be0d
1042Author: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
1043Date: Sat May 3 11:59:44 2008 -0700
1044
1045 Linux 2.6.26-rc1
1046
Junio C Hamanof2b74942012-11-20 21:06:261047:100644 100644 5cf82581... 4492984e... M Makefile
Junio C Hamanoc14e6ad2014-10-31 20:25:531048bisect run success</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591049</div></div>
Junio C Hamano103b5722011-01-31 05:03:451050<div class="paragraph"><p>In this example, we passed "grep <em>^SUBLEVEL = 25</em> Makefile" as
Junio C Hamano2bd8a742009-12-01 21:16:591051parameter to "git bisect run". This means that at each step, the grep
1052command we passed will be launched. And if it exits with code 0 (that
1053means success) then git bisect will mark the current state as
1054"good". If it exits with code 1 (or any code between 1 and 127
1055included, except the special code 125), then the current state will be
1056marked as "bad".</p></div>
Junio C Hamano103b5722011-01-31 05:03:451057<div class="paragraph"><p>Exit code between 128 and 255 are special to "git bisect run". They
Junio C Hamano2bd8a742009-12-01 21:16:591058make it stop immediately the bisection process. This is useful for
1059example if the command passed takes too long to complete, because you
1060can kill it with a signal and it will stop the bisection process.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451061<div class="paragraph"><p>It can also be useful in scripts passed to "git bisect run" to "exit
Junio C Hamano2bd8a742009-12-01 21:16:591062255" if some very abnormal situation is detected.</p></div>
Junio C Hamano9d971152012-12-19 00:43:111063</div>
1064<div class="sect2">
1065<h3 id="_avoiding_untestable_commits">Avoiding untestable commits</h3>
Junio C Hamano103b5722011-01-31 05:03:451066<div class="paragraph"><p>Sometimes it happens that the current state cannot be tested, for
Junio C Hamano2bd8a742009-12-01 21:16:591067example if it does not compile because there was a bug preventing it
1068at that time. This is what the special exit code 125 is for. It tells
1069"git bisect run" that the current commit should be marked as
1070untestable and that another one should be chosen and checked out.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451071<div class="paragraph"><p>If the bisection process is driven manually, you can use "git bisect
Junio C Hamano2bd8a742009-12-01 21:16:591072skip" to do the same thing. (In fact the special exit code 125 makes
1073"git bisect run" use "git bisect skip" in the background.)</p></div>
Junio C Hamano103b5722011-01-31 05:03:451074<div class="paragraph"><p>Or if you want more control, you can inspect the current state using
Junio C Hamano2bd8a742009-12-01 21:16:591075for example "git bisect visualize". It will launch gitk (or "git log"
Junio C Hamano042f2142016-06-27 18:05:051076if the <code>DISPLAY</code> environment variable is not set) to help you find a
Junio C Hamano2bd8a742009-12-01 21:16:591077better bisection point.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451078<div class="paragraph"><p>Either way, if you have a string of untestable commits, it might
Junio C Hamano2bd8a742009-12-01 21:16:591079happen that the regression you are looking for has been introduced by
Junio C Hamano103b5722011-01-31 05:03:451080one of these untestable commits. In this case it&#8217;s not possible to
Junio C Hamano2bd8a742009-12-01 21:16:591081tell for sure which commit introduced the regression.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451082<div class="paragraph"><p>So if you used "git bisect skip" (or the run script exited with
Junio C Hamano2bd8a742009-12-01 21:16:591083special code 125) you could get a result like this:</p></div>
1084<div class="listingblock">
1085<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531086<pre><code>There are only 'skip'ped commits left to test.
Junio C Hamano2bd8a742009-12-01 21:16:591087The first bad commit could be any of:
108815722f2fa328eaba97022898a305ffc8172db6b1
108978e86cf3e850bd755bb71831f42e200626fbd1e0
1090e15b73ad3db9b48d7d1ade32f8cd23a751fe0ace
1091070eab2303024706f2924822bfec8b9847e4ac1b
Junio C Hamanoc14e6ad2014-10-31 20:25:531092We cannot bisect more!</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591093</div></div>
Junio C Hamano9d971152012-12-19 00:43:111094</div>
1095<div class="sect2">
1096<h3 id="_saving_a_log_and_replaying_it">Saving a log and replaying it</h3>
Junio C Hamano103b5722011-01-31 05:03:451097<div class="paragraph"><p>If you want to show other people your bisection process, you can get a
Junio C Hamano2bd8a742009-12-01 21:16:591098log using for example:</p></div>
1099<div class="listingblock">
1100<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531101<pre><code>$ git bisect log &gt; bisect_log.txt</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591102</div></div>
Junio C Hamano103b5722011-01-31 05:03:451103<div class="paragraph"><p>And it is possible to replay it using:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591104<div class="listingblock">
1105<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531106<pre><code>$ git bisect replay bisect_log.txt</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591107</div></div>
1108</div>
Junio C Hamano9d971152012-12-19 00:43:111109</div>
1110</div>
1111<div class="sect1">
Junio C Hamano2bd8a742009-12-01 21:16:591112<h2 id="_git_bisect_details">"git bisect" details</h2>
1113<div class="sectionbody">
Junio C Hamano9d971152012-12-19 00:43:111114<div class="sect2">
1115<h3 id="_bisection_algorithm">Bisection algorithm</h3>
Junio C Hamano103b5722011-01-31 05:03:451116<div class="paragraph"><p>As the Git commits form a directed acyclic graph (DAG), finding the
Junio C Hamano2bd8a742009-12-01 21:16:591117best bisection commit to test at each step is not so simple. Anyway
1118Linus found and implemented a "truly stupid" algorithm, later improved
1119by Junio Hamano, that works quite well.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451120<div class="paragraph"><p>So the algorithm used by "git bisect" to find the best bisection
Junio C Hamano2bd8a742009-12-01 21:16:591121commit when there are no skipped commits is the following:</p></div>
Junio C Hamano103b5722011-01-31 05:03:451122<div class="paragraph"><p>1) keep only the commits that:</p></div>
1123<div class="paragraph"><p>a) are ancestor of the "bad" commit (including the "bad" commit itself),
Junio C Hamano2bd8a742009-12-01 21:16:591124b) are not ancestor of a "good" commit (excluding the "good" commits).</p></div>
Junio C Hamano103b5722011-01-31 05:03:451125<div class="paragraph"><p>This means that we get rid of the uninteresting commits in the DAG.</p></div>
1126<div class="paragraph"><p>For example if we start with a graph like this:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591127<div class="listingblock">
1128<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531129<pre><code>G-Y-G-W-W-W-X-X-X-X
Junio C Hamano2bd8a742009-12-01 21:16:591130 \ /
1131 W-W-B
1132 /
1133Y---G-W---W
1134 \ / \
1135Y-Y X-X-X-X
1136
Junio C Hamanoc14e6ad2014-10-31 20:25:531137-&gt; time goes this way -&gt;</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591138</div></div>
Junio C Hamano103b5722011-01-31 05:03:451139<div class="paragraph"><p>where B is the "bad" commit, "G" are "good" commits and W, X, and Y
Junio C Hamano2bd8a742009-12-01 21:16:591140are other commits, we will get the following graph after this first
1141step:</p></div>
1142<div class="listingblock">
1143<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531144<pre><code>W-W-W
Junio C Hamano2bd8a742009-12-01 21:16:591145 \
1146 W-W-B
1147 /
Junio C Hamanoc14e6ad2014-10-31 20:25:531148W---W</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591149</div></div>
Junio C Hamano103b5722011-01-31 05:03:451150<div class="paragraph"><p>So only the W and B commits will be kept. Because commits X and Y will
Junio C Hamano2bd8a742009-12-01 21:16:591151have been removed by rules a) and b) respectively, and because commits
1152G are removed by rule b) too.</p></div>
Junio C Hamano076ffcc2013-02-06 05:13:211153<div class="paragraph"><p>Note for Git users, that it is equivalent as keeping only the commit
Junio C Hamano2bd8a742009-12-01 21:16:591154given by:</p></div>
1155<div class="listingblock">
1156<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531157<pre><code>git rev-list BAD --not GOOD1 GOOD2...</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591158</div></div>
Junio C Hamano103b5722011-01-31 05:03:451159<div class="paragraph"><p>Also note that we don&#8217;t require the commits that are kept to be
Junio C Hamano2bd8a742009-12-01 21:16:591160descendants of a "good" commit. So in the following example, commits W
1161and Z will be kept:</p></div>
1162<div class="listingblock">
1163<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531164<pre><code>G-W-W-W-B
Junio C Hamano2bd8a742009-12-01 21:16:591165 /
Junio C Hamanoc14e6ad2014-10-31 20:25:531166Z-Z</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591167</div></div>
Junio C Hamano103b5722011-01-31 05:03:451168<div class="paragraph"><p>2) starting from the "good" ends of the graph, associate to each
Junio C Hamano2bd8a742009-12-01 21:16:591169commit the number of ancestors it has plus one</p></div>
Junio C Hamano103b5722011-01-31 05:03:451170<div class="paragraph"><p>For example with the following graph where H is the "bad" commit and A
Junio C Hamano2bd8a742009-12-01 21:16:591171and D are some parents of some "good" commits:</p></div>
1172<div class="listingblock">
1173<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531174<pre><code>A-B-C
Junio C Hamano2bd8a742009-12-01 21:16:591175 \
1176 F-G-H
1177 /
Junio C Hamanoc14e6ad2014-10-31 20:25:531178D---E</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591179</div></div>
Junio C Hamano103b5722011-01-31 05:03:451180<div class="paragraph"><p>this will give:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591181<div class="listingblock">
1182<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531183<pre><code>1 2 3
Junio C Hamano2bd8a742009-12-01 21:16:591184A-B-C
1185 \6 7 8
1186 F-G-H
11871 2/
Junio C Hamanoc14e6ad2014-10-31 20:25:531188D---E</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591189</div></div>
Junio C Hamano103b5722011-01-31 05:03:451190<div class="paragraph"><p>3) associate to each commit: min(X, N - X)</p></div>
1191<div class="paragraph"><p>where X is the value associated to the commit in step 2) and N is the
Junio C Hamano2bd8a742009-12-01 21:16:591192total number of commits in the graph.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451193<div class="paragraph"><p>In the above example we have N = 8, so this will give:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591194<div class="listingblock">
1195<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531196<pre><code>1 2 3
Junio C Hamano2bd8a742009-12-01 21:16:591197A-B-C
1198 \2 1 0
1199 F-G-H
12001 2/
Junio C Hamanoc14e6ad2014-10-31 20:25:531201D---E</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591202</div></div>
Junio C Hamano103b5722011-01-31 05:03:451203<div class="paragraph"><p>4) the best bisection point is the commit with the highest associated
Junio C Hamano2bd8a742009-12-01 21:16:591204number</p></div>
Junio C Hamano103b5722011-01-31 05:03:451205<div class="paragraph"><p>So in the above example the best bisection point is commit C.</p></div>
1206<div class="paragraph"><p>5) note that some shortcuts are implemented to speed up the algorithm</p></div>
1207<div class="paragraph"><p>As we know N from the beginning, we know that min(X, N - X) can&#8217;t be
Junio C Hamano2bd8a742009-12-01 21:16:591208greater than N/2. So during steps 2) and 3), if we would associate N/2
1209to a commit, then we know this is the best bisection point. So in this
1210case we can just stop processing any other commit and return the
1211current commit.</p></div>
Junio C Hamano9d971152012-12-19 00:43:111212</div>
1213<div class="sect2">
1214<h3 id="_bisection_algorithm_debugging">Bisection algorithm debugging</h3>
Junio C Hamano103b5722011-01-31 05:03:451215<div class="paragraph"><p>For any commit graph, you can see the number associated with each
1216commit using "git rev-list --bisect-all".</p></div>
1217<div class="paragraph"><p>For example, for the above graph, a command like:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591218<div class="listingblock">
1219<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531220<pre><code>$ git rev-list --bisect-all BAD --not GOOD1 GOOD2</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591221</div></div>
Junio C Hamano103b5722011-01-31 05:03:451222<div class="paragraph"><p>would output something like:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591223<div class="listingblock">
1224<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531225<pre><code>e15b73ad3db9b48d7d1ade32f8cd23a751fe0ace (dist=3)
Junio C Hamano2bd8a742009-12-01 21:16:59122615722f2fa328eaba97022898a305ffc8172db6b1 (dist=2)
122778e86cf3e850bd755bb71831f42e200626fbd1e0 (dist=2)
1228a1939d9a142de972094af4dde9a544e577ddef0e (dist=2)
1229070eab2303024706f2924822bfec8b9847e4ac1b (dist=1)
1230a3864d4f32a3bf5ed177ddef598490a08760b70d (dist=1)
1231a41baa717dd74f1180abf55e9341bc7a0bb9d556 (dist=1)
Junio C Hamanoc14e6ad2014-10-31 20:25:5312329e622a6dad403b71c40979743bb9d5be17b16bd6 (dist=0)</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591233</div></div>
Junio C Hamano9d971152012-12-19 00:43:111234</div>
1235<div class="sect2">
1236<h3 id="_bisection_algorithm_discussed">Bisection algorithm discussed</h3>
Junio C Hamano103b5722011-01-31 05:03:451237<div class="paragraph"><p>First let&#8217;s define "best bisection point". We will say that a commit X
Junio C Hamano2bd8a742009-12-01 21:16:591238is a best bisection point or a best bisection commit if knowing its
1239state ("good" or "bad") gives as much information as possible whether
1240the state of the commit happens to be "good" or "bad".</p></div>
Junio C Hamano103b5722011-01-31 05:03:451241<div class="paragraph"><p>This means that the best bisection commits are the commits where the
Junio C Hamano2bd8a742009-12-01 21:16:591242following function is maximum:</p></div>
1243<div class="listingblock">
1244<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531245<pre><code>f(X) = min(information_if_good(X), information_if_bad(X))</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591246</div></div>
Junio C Hamano103b5722011-01-31 05:03:451247<div class="paragraph"><p>where information_if_good(X) is the information we get if X is good
Junio C Hamano2bd8a742009-12-01 21:16:591248and information_if_bad(X) is the information we get if X is bad.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451249<div class="paragraph"><p>Now we will suppose that there is only one "first bad commit". This
Junio C Hamano2bd8a742009-12-01 21:16:591250means that all its descendants are "bad" and all the other commits are
1251"good". And we will suppose that all commits have an equal probability
1252of being good or bad, or of being the first bad commit, so knowing the
1253state of c commits gives always the same amount of information
1254wherever these c commits are on the graph and whatever c is. (So we
1255suppose that these commits being for example on a branch or near a
1256good or a bad commit does not give more or less information).</p></div>
Junio C Hamano103b5722011-01-31 05:03:451257<div class="paragraph"><p>Let&#8217;s also suppose that we have a cleaned up graph like one after step
Junio C Hamano2bd8a742009-12-01 21:16:5912581) in the bisection algorithm above. This means that we can measure
1259the information we get in terms of number of commit we can remove from
1260the graph..</p></div>
Junio C Hamano103b5722011-01-31 05:03:451261<div class="paragraph"><p>And let&#8217;s take a commit X in the graph.</p></div>
1262<div class="paragraph"><p>If X is found to be "good", then we know that its ancestors are all
Junio C Hamano2bd8a742009-12-01 21:16:591263"good", so we want to say that:</p></div>
1264<div class="listingblock">
1265<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531266<pre><code>information_if_good(X) = number_of_ancestors(X) (TRUE)</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591267</div></div>
Junio C Hamano103b5722011-01-31 05:03:451268<div class="paragraph"><p>And this is true because at step 1) b) we remove the ancestors of the
Junio C Hamano2bd8a742009-12-01 21:16:591269"good" commits.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451270<div class="paragraph"><p>If X is found to be "bad", then we know that its descendants are all
Junio C Hamano2bd8a742009-12-01 21:16:591271"bad", so we want to say that:</p></div>
1272<div class="listingblock">
1273<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531274<pre><code>information_if_bad(X) = number_of_descendants(X) (WRONG)</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591275</div></div>
Junio C Hamano103b5722011-01-31 05:03:451276<div class="paragraph"><p>But this is wrong because at step 1) a) we keep only the ancestors of
Junio C Hamano2bd8a742009-12-01 21:16:591277the bad commit. So we get more information when a commit is marked as
1278"bad", because we also know that the ancestors of the previous "bad"
1279commit that are not ancestors of the new "bad" commit are not the
Junio C Hamano103b5722011-01-31 05:03:451280first bad commit. We don&#8217;t know if they are good or bad, but we know
Junio C Hamano2bd8a742009-12-01 21:16:591281that they are not the first bad commit because they are not ancestor
1282of the new "bad" commit.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451283<div class="paragraph"><p>So when a commit is marked as "bad" we know we can remove all the
Junio C Hamano2bd8a742009-12-01 21:16:591284commits in the graph except those that are ancestors of the new "bad"
1285commit. This means that:</p></div>
1286<div class="listingblock">
1287<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531288<pre><code>information_if_bad(X) = N - number_of_ancestors(X) (TRUE)</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591289</div></div>
Junio C Hamano103b5722011-01-31 05:03:451290<div class="paragraph"><p>where N is the number of commits in the (cleaned up) graph.</p></div>
1291<div class="paragraph"><p>So in the end this means that to find the best bisection commits we
Junio C Hamano2bd8a742009-12-01 21:16:591292should maximize the function:</p></div>
1293<div class="listingblock">
1294<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531295<pre><code>f(X) = min(number_of_ancestors(X), N - number_of_ancestors(X))</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591296</div></div>
Junio C Hamano103b5722011-01-31 05:03:451297<div class="paragraph"><p>And this is nice because at step 2) we compute number_of_ancestors(X)
Junio C Hamano2bd8a742009-12-01 21:16:591298and so at step 3) we compute f(X).</p></div>
Junio C Hamano103b5722011-01-31 05:03:451299<div class="paragraph"><p>Let&#8217;s take the following graph as an example:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591300<div class="listingblock">
1301<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531302<pre><code> G-H-I-J
Junio C Hamano2bd8a742009-12-01 21:16:591303 / \
1304A-B-C-D-E-F O
1305 \ /
Junio C Hamanoc14e6ad2014-10-31 20:25:531306 K-L-M-N</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591307</div></div>
Junio C Hamano103b5722011-01-31 05:03:451308<div class="paragraph"><p>If we compute the following non optimal function on it:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591309<div class="listingblock">
1310<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531311<pre><code>g(X) = min(number_of_ancestors(X), number_of_descendants(X))</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591312</div></div>
Junio C Hamano103b5722011-01-31 05:03:451313<div class="paragraph"><p>we get:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591314<div class="listingblock">
1315<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531316<pre><code> 4 3 2 1
Junio C Hamano2bd8a742009-12-01 21:16:591317 G-H-I-J
13181 2 3 4 5 6/ \0
1319A-B-C-D-E-F O
1320 \ /
1321 K-L-M-N
Junio C Hamanoc14e6ad2014-10-31 20:25:531322 4 3 2 1</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591323</div></div>
Junio C Hamano103b5722011-01-31 05:03:451324<div class="paragraph"><p>but with the algorithm used by git bisect we get:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591325<div class="listingblock">
1326<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531327<pre><code> 7 7 6 5
Junio C Hamano2bd8a742009-12-01 21:16:591328 G-H-I-J
13291 2 3 4 5 6/ \0
1330A-B-C-D-E-F O
1331 \ /
1332 K-L-M-N
Junio C Hamanoc14e6ad2014-10-31 20:25:531333 7 7 6 5</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591334</div></div>
Junio C Hamano103b5722011-01-31 05:03:451335<div class="paragraph"><p>So we chose G, H, K or L as the best bisection point, which is better
Junio C Hamano2bd8a742009-12-01 21:16:591336than F. Because if for example L is bad, then we will know not only
1337that L, M and N are bad but also that G, H, I and J are not the first
1338bad commit (since we suppose that there is only one first bad commit
1339and it must be an ancestor of L).</p></div>
Junio C Hamano103b5722011-01-31 05:03:451340<div class="paragraph"><p>So the current algorithm seems to be the best possible given what we
Junio C Hamano2bd8a742009-12-01 21:16:591341initially supposed.</p></div>
Junio C Hamano9d971152012-12-19 00:43:111342</div>
1343<div class="sect2">
1344<h3 id="_skip_algorithm">Skip algorithm</h3>
Junio C Hamano103b5722011-01-31 05:03:451345<div class="paragraph"><p>When some commits have been skipped (using "git bisect skip"), then
Junio C Hamano2bd8a742009-12-01 21:16:591346the bisection algorithm is the same for step 1) to 3). But then we use
1347roughly the following steps:</p></div>
Junio C Hamano103b5722011-01-31 05:03:451348<div class="paragraph"><p>6) sort the commit by decreasing associated value</p></div>
1349<div class="paragraph"><p>7) if the first commit has not been skipped, we can return it and stop
Junio C Hamano2bd8a742009-12-01 21:16:591350here</p></div>
Junio C Hamano103b5722011-01-31 05:03:451351<div class="paragraph"><p>8) otherwise filter out all the skipped commits in the sorted list</p></div>
1352<div class="paragraph"><p>9) use a pseudo random number generator (PRNG) to generate a random
Junio C Hamano2bd8a742009-12-01 21:16:591353number between 0 and 1</p></div>
Junio C Hamano103b5722011-01-31 05:03:451354<div class="paragraph"><p>10) multiply this random number with its square root to bias it toward
Junio C Hamano2bd8a742009-12-01 21:16:5913550</p></div>
Junio C Hamano103b5722011-01-31 05:03:451356<div class="paragraph"><p>11) multiply the result by the number of commits in the filtered list
Junio C Hamano2bd8a742009-12-01 21:16:591357to get an index into this list</p></div>
Junio C Hamano103b5722011-01-31 05:03:451358<div class="paragraph"><p>12) return the commit at the computed index</p></div>
Junio C Hamano9d971152012-12-19 00:43:111359</div>
1360<div class="sect2">
1361<h3 id="_skip_algorithm_discussed">Skip algorithm discussed</h3>
Junio C Hamano103b5722011-01-31 05:03:451362<div class="paragraph"><p>After step 7) (in the skip algorithm), we could check if the second
Junio C Hamano2bd8a742009-12-01 21:16:591363commit has been skipped and return it if it is not the case. And in
1364fact that was the algorithm we used from when "git bisect skip" was
Junio C Hamano076ffcc2013-02-06 05:13:211365developed in Git version 1.5.4 (released on February 1st 2008) until
1366Git version 1.6.4 (released July 29th 2009).</p></div>
Junio C Hamano103b5722011-01-31 05:03:451367<div class="paragraph"><p>But Ingo Molnar and H. Peter Anvin (another well known linux kernel
Junio C Hamano2bd8a742009-12-01 21:16:591368developer) both complained that sometimes the best bisection points
1369all happened to be in an area where all the commits are
1370untestable. And in this case the user was asked to test many
1371untestable commits, which could be very inefficient.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451372<div class="paragraph"><p>Indeed untestable commits are often untestable because a breakage was
Junio C Hamano2bd8a742009-12-01 21:16:591373introduced at one time, and that breakage was fixed only after many
1374other commits were introduced.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451375<div class="paragraph"><p>This breakage is of course most of the time unrelated to the breakage
Junio C Hamano2bd8a742009-12-01 21:16:591376we are trying to locate in the commit graph. But it prevents us to
1377know if the interesting "bad behavior" is present or not.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451378<div class="paragraph"><p>So it is a fact that commits near an untestable commit have a high
Junio C Hamano2bd8a742009-12-01 21:16:591379probability of being untestable themselves. And the best bisection
1380commits are often found together too (due to the bisection algorithm).</p></div>
Junio C Hamano103b5722011-01-31 05:03:451381<div class="paragraph"><p>This is why it is a bad idea to just chose the next best unskipped
Junio C Hamano2bd8a742009-12-01 21:16:591382bisection commit when the first one has been skipped.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451383<div class="paragraph"><p>We found that most commits on the graph may give quite a lot of
Junio C Hamano2bd8a742009-12-01 21:16:591384information when they are tested. And the commits that will not on
1385average give a lot of information are the one near the good and bad
1386commits.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451387<div class="paragraph"><p>So using a PRNG with a bias to favor commits away from the good and
Junio C Hamano2bd8a742009-12-01 21:16:591388bad commits looked like a good choice.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451389<div class="paragraph"><p>One obvious improvement to this algorithm would be to look for a
Junio C Hamano2bd8a742009-12-01 21:16:591390commit that has an associated value near the one of the best bisection
1391commit, and that is on another branch, before using the PRNG. Because
1392if such a commit exists, then it is not very likely to be untestable
1393too, so it will probably give more information than a nearly randomly
1394chosen one.</p></div>
Junio C Hamano9d971152012-12-19 00:43:111395</div>
1396<div class="sect2">
1397<h3 id="_checking_merge_bases">Checking merge bases</h3>
Junio C Hamano103b5722011-01-31 05:03:451398<div class="paragraph"><p>There is another tweak in the bisection algorithm that has not been
Junio C Hamano2bd8a742009-12-01 21:16:591399described in the "bisection algorithm" above.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451400<div class="paragraph"><p>We supposed in the previous examples that the "good" commits were
Junio C Hamano2bd8a742009-12-01 21:16:591401ancestors of the "bad" commit. But this is not a requirement of "git
1402bisect".</p></div>
Junio C Hamano103b5722011-01-31 05:03:451403<div class="paragraph"><p>Of course the "bad" commit cannot be an ancestor of a "good" commit,
Junio C Hamano2bd8a742009-12-01 21:16:591404because the ancestors of the good commits are supposed to be
1405"good". And all the "good" commits must be related to the bad commit.
1406They cannot be on a branch that has no link with the branch of the
1407"bad" commit. But it is possible for a good commit to be related to a
1408bad commit and yet not be neither one of its ancestor nor one of its
1409descendants.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451410<div class="paragraph"><p>For example, there can be a "main" branch, and a "dev" branch that was
Junio C Hamano2bd8a742009-12-01 21:16:591411forked of the main branch at a commit named "D" like this:</p></div>
1412<div class="listingblock">
1413<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531414<pre><code>A-B-C-D-E-F-G &lt;--main
Junio C Hamano2bd8a742009-12-01 21:16:591415 \
Junio C Hamanoc14e6ad2014-10-31 20:25:531416 H-I-J &lt;--dev</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591417</div></div>
Junio C Hamano103b5722011-01-31 05:03:451418<div class="paragraph"><p>The commit "D" is called a "merge base" for branch "main" and "dev"
1419because it&#8217;s the best common ancestor for these branches for a merge.</p></div>
1420<div class="paragraph"><p>Now let&#8217;s suppose that commit J is bad and commit G is good and that
Junio C Hamano2bd8a742009-12-01 21:16:591421we apply the bisection algorithm like it has been previously
1422described.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451423<div class="paragraph"><p>As described in step 1) b) of the bisection algorithm, we remove all
Junio C Hamano2bd8a742009-12-01 21:16:591424the ancestors of the good commits because they are supposed to be good
1425too.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451426<div class="paragraph"><p>So we would be left with only:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591427<div class="listingblock">
1428<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531429<pre><code>H-I-J</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591430</div></div>
Junio C Hamano103b5722011-01-31 05:03:451431<div class="paragraph"><p>But what happens if the first bad commit is "B" and if it has been
Junio C Hamano2bd8a742009-12-01 21:16:591432fixed in the "main" branch by commit "F"?</p></div>
Junio C Hamano103b5722011-01-31 05:03:451433<div class="paragraph"><p>The result of such a bisection would be that we would find that H is
1434the first bad commit, when in fact it&#8217;s B. So that would be wrong!</p></div>
1435<div class="paragraph"><p>And yes it can happen in practice that people working on one branch
Junio C Hamano2bd8a742009-12-01 21:16:591436are not aware that people working on another branch fixed a bug! It
1437could also happen that F fixed more than one bug or that it is a
1438revert of some big development effort that was not ready to be
1439released.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451440<div class="paragraph"><p>In fact development teams often maintain both a development branch and
Junio C Hamano2bd8a742009-12-01 21:16:591441a maintenance branch, and it would be quite easy for them if "git
1442bisect" just worked when they want to bisect a regression on the
1443development branch that is not on the maintenance branch. They should
1444be able to start bisecting using:</p></div>
1445<div class="listingblock">
1446<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531447<pre><code>$ git bisect start dev main</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591448</div></div>
Junio C Hamano103b5722011-01-31 05:03:451449<div class="paragraph"><p>To enable that additional nice feature, when a bisection is started
Junio C Hamano2bd8a742009-12-01 21:16:591450and when some good commits are not ancestors of the bad commit, we
1451first compute the merge bases between the bad and the good commits and
1452we chose these merge bases as the first commits that will be checked
1453out and tested.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451454<div class="paragraph"><p>If it happens that one merge base is bad, then the bisection process
Junio C Hamano2bd8a742009-12-01 21:16:591455is stopped with a message like:</p></div>
1456<div class="listingblock">
1457<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531458<pre><code>The merge base BBBBBB is bad.
1459This means the bug has been fixed between BBBBBB and [GGGGGG,...].</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591460</div></div>
Junio C Hamano103b5722011-01-31 05:03:451461<div class="paragraph"><p>where BBBBBB is the sha1 hash of the bad merge base and [GGGGGG,&#8230;]
Junio C Hamano2bd8a742009-12-01 21:16:591462is a comma separated list of the sha1 of the good commits.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451463<div class="paragraph"><p>If some of the merge bases are skipped, then the bisection process
Junio C Hamano2bd8a742009-12-01 21:16:591464continues, but the following message is printed for each skipped merge
1465base:</p></div>
1466<div class="listingblock">
1467<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531468<pre><code>Warning: the merge base between BBBBBB and [GGGGGG,...] must be skipped.
Junio C Hamano2bd8a742009-12-01 21:16:591469So we cannot be sure the first bad commit is between MMMMMM and BBBBBB.
Junio C Hamanoc14e6ad2014-10-31 20:25:531470We continue anyway.</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591471</div></div>
Junio C Hamano103b5722011-01-31 05:03:451472<div class="paragraph"><p>where BBBBBB is the sha1 hash of the bad commit, MMMMMM is the sha1
Junio C Hamano2bd8a742009-12-01 21:16:591473hash of the merge base that is skipped and [GGGGGG,&#8230;] is a comma
1474separated list of the sha1 of the good commits.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451475<div class="paragraph"><p>So if there is no bad merge base, the bisection process continues as
Junio C Hamano2bd8a742009-12-01 21:16:591476usual after this step.</p></div>
1477</div>
Junio C Hamano9d971152012-12-19 00:43:111478</div>
1479</div>
1480<div class="sect1">
Junio C Hamano2bd8a742009-12-01 21:16:591481<h2 id="_best_bisecting_practices">Best bisecting practices</h2>
1482<div class="sectionbody">
Junio C Hamano9d971152012-12-19 00:43:111483<div class="sect2">
1484<h3 id="_using_test_suites_and_git_bisect_together">Using test suites and git bisect together</h3>
Junio C Hamano103b5722011-01-31 05:03:451485<div class="paragraph"><p>If you both have a test suite and use git bisect, then it becomes less
Junio C Hamano2bd8a742009-12-01 21:16:591486important to check that all tests pass after each commit. Though of
1487course it is probably a good idea to have some checks to avoid
1488breaking too many things because it could make bisecting other bugs
1489more difficult.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451490<div class="paragraph"><p>You can focus your efforts to check at a few points (for example rc
Junio C Hamano2bd8a742009-12-01 21:16:591491and beta releases) that all the T test cases pass for all the N
Junio C Hamano103b5722011-01-31 05:03:451492configurations. And when some tests don&#8217;t pass you can use "git
Junio C Hamano2bd8a742009-12-01 21:16:591493bisect" (or better "git bisect run"). So you should perform roughly:</p></div>
1494<div class="listingblock">
1495<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531496<pre><code>c * N * T + b * M * log2(M) tests</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591497</div></div>
Junio C Hamano103b5722011-01-31 05:03:451498<div class="paragraph"><p>where c is the number of rounds of test (so a small constant) and b is
Junio C Hamano2bd8a742009-12-01 21:16:591499the ratio of bug per commit (hopefully a small constant too).</p></div>
Junio C Hamano103b5722011-01-31 05:03:451500<div class="paragraph"><p>So of course it&#8217;s much better as it&#8217;s O(N * T) vs O(N * T * M) if
Junio C Hamano2bd8a742009-12-01 21:16:591501you would test everything after each commit.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451502<div class="paragraph"><p>This means that test suites are good to prevent some bugs from being
Junio C Hamano2bd8a742009-12-01 21:16:591503committed and they are also quite good to tell you that you have some
1504bugs. But they are not so good to tell you where some bugs have been
1505introduced. To tell you that efficiently, git bisect is needed.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451506<div class="paragraph"><p>The other nice thing with test suites, is that when you have one, you
Junio C Hamano2bd8a742009-12-01 21:16:591507already know how to test for bad behavior. So you can use this
1508knowledge to create a new test case for "git bisect" when it appears
1509that there is a regression. So it will be easier to bisect the bug and
1510fix it. And then you can add the test case you just created to your
1511test suite.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451512<div class="paragraph"><p>So if you know how to create test cases and how to bisect, you will be
Junio C Hamano2bd8a742009-12-01 21:16:591513subject to a virtuous circle:</p></div>
Junio C Hamano103b5722011-01-31 05:03:451514<div class="paragraph"><p>more tests &#8658; easier to create tests &#8658; easier to bisect &#8658; more tests</p></div>
1515<div class="paragraph"><p>So test suites and "git bisect" are complementary tools that are very
Junio C Hamano2bd8a742009-12-01 21:16:591516powerful and efficient when used together.</p></div>
Junio C Hamano9d971152012-12-19 00:43:111517</div>
1518<div class="sect2">
1519<h3 id="_bisecting_build_failures">Bisecting build failures</h3>
Junio C Hamano103b5722011-01-31 05:03:451520<div class="paragraph"><p>You can very easily automatically bisect broken builds using something
Junio C Hamano2bd8a742009-12-01 21:16:591521like:</p></div>
1522<div class="listingblock">
1523<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531524<pre><code>$ git bisect start BAD GOOD
1525$ git bisect run make</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591526</div></div>
Junio C Hamano9d971152012-12-19 00:43:111527</div>
1528<div class="sect2">
1529<h3 id="_passing_sh_c_some_commands_to_git_bisect_run">Passing sh -c "some commands" to "git bisect run"</h3>
Junio C Hamano103b5722011-01-31 05:03:451530<div class="paragraph"><p>For example:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591531<div class="listingblock">
1532<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531533<pre><code>$ git bisect run sh -c "make || exit 125; ./my_app | grep 'good output'"</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591534</div></div>
Junio C Hamano103b5722011-01-31 05:03:451535<div class="paragraph"><p>On the other hand if you do this often, then it can be worth having
Junio C Hamano2bd8a742009-12-01 21:16:591536scripts to avoid too much typing.</p></div>
Junio C Hamano9d971152012-12-19 00:43:111537</div>
1538<div class="sect2">
1539<h3 id="_finding_performance_regressions">Finding performance regressions</h3>
Junio C Hamano103b5722011-01-31 05:03:451540<div class="paragraph"><p>Here is an example script that comes slightly modified from a real
Junio C Hamano2bd8a742009-12-01 21:16:591541world script used by Junio Hamano <a href="#4">[4]</a>.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451542<div class="paragraph"><p>This script can be passed to "git bisect run" to find the commit that
Junio C Hamano2bd8a742009-12-01 21:16:591543introduced a performance regression:</p></div>
1544<div class="listingblock">
1545<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531546<pre><code>#!/bin/sh
Junio C Hamano2bd8a742009-12-01 21:16:591547
1548# Build errors are not what I am interested in.
1549make my_app || exit 255
1550
1551# We are checking if it stops in a reasonable amount of time, so
1552# let it run in the background...
1553
1554./my_app &gt;log 2&gt;&amp;1 &amp;
1555
1556# ... and grab its process ID.
1557pid=$!
1558
1559# ... and then wait for sufficiently long.
1560sleep $NORMAL_TIME
1561
1562# ... and then see if the process is still there.
1563if kill -0 $pid
1564then
1565 # It is still running -- that is bad.
1566 kill $pid; sleep 1; kill $pid;
1567 exit 1
1568else
1569 # It has already finished (the $pid process was no more),
1570 # and we are happy.
1571 exit 0
Junio C Hamanoc14e6ad2014-10-31 20:25:531572fi</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591573</div></div>
Junio C Hamano9d971152012-12-19 00:43:111574</div>
1575<div class="sect2">
1576<h3 id="_following_general_best_practices">Following general best practices</h3>
Junio C Hamano103b5722011-01-31 05:03:451577<div class="paragraph"><p>It is obviously a good idea not to have commits with changes that
Junio C Hamano2bd8a742009-12-01 21:16:591578knowingly break things, even if some other commits later fix the
1579breakage.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451580<div class="paragraph"><p>It is also a good idea when using any VCS to have only one small
Junio C Hamano2bd8a742009-12-01 21:16:591581logical change in each commit.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451582<div class="paragraph"><p>The smaller the changes in your commit, the most effective "git
Junio C Hamano2bd8a742009-12-01 21:16:591583bisect" will be. And you will probably need "git bisect" less in the
1584first place, as small changes are easier to review even if they are
Junio C Hamano619596a2010-08-18 22:15:351585only reviewed by the committer.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451586<div class="paragraph"><p>Another good idea is to have good commit messages. They can be very
Junio C Hamano2bd8a742009-12-01 21:16:591587helpful to understand why some changes were made.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451588<div class="paragraph"><p>These general best practices are very helpful if you bisect often.</p></div>
Junio C Hamano9d971152012-12-19 00:43:111589</div>
1590<div class="sect2">
1591<h3 id="_avoiding_bug_prone_merges">Avoiding bug prone merges</h3>
Junio C Hamano103b5722011-01-31 05:03:451592<div class="paragraph"><p>First merges by themselves can introduce some regressions even when
Junio C Hamano2bd8a742009-12-01 21:16:591593the merge needs no source code conflict resolution. This is because a
1594semantic change can happen in one branch while the other branch is not
1595aware of it.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451596<div class="paragraph"><p>For example one branch can change the semantic of a function while the
Junio C Hamano2bd8a742009-12-01 21:16:591597other branch add more calls to the same function.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451598<div class="paragraph"><p>This is made much worse if many files have to be fixed to resolve
1599conflicts. That&#8217;s why such merges are called "evil merges". They can
Junio C Hamano2bd8a742009-12-01 21:16:591600make regressions very difficult to track down. It can even be
1601misleading to know the first bad commit if it happens to be such a
1602merge, because people might think that the bug comes from bad conflict
1603resolution when it comes from a semantic change in one branch.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451604<div class="paragraph"><p>Anyway "git rebase" can be used to linearize history. This can be used
Junio C Hamano2bd8a742009-12-01 21:16:591605either to avoid merging in the first place. Or it can be used to
1606bisect on a linear history instead of the non linear one, as this
1607should give more information in case of a semantic change in one
1608branch.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451609<div class="paragraph"><p>Merges can be also made simpler by using smaller branches or by using
Junio C Hamano2bd8a742009-12-01 21:16:591610many topic branches instead of only long version related branches.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451611<div class="paragraph"><p>And testing can be done more often in special integration branches
Junio C Hamano2bd8a742009-12-01 21:16:591612like linux-next for the linux kernel.</p></div>
Junio C Hamano9d971152012-12-19 00:43:111613</div>
1614<div class="sect2">
1615<h3 id="_adapting_your_work_flow">Adapting your work-flow</h3>
Junio C Hamano103b5722011-01-31 05:03:451616<div class="paragraph"><p>A special work-flow to process regressions can give great results.</p></div>
1617<div class="paragraph"><p>Here is an example of a work-flow used by Andreas Ericsson:</p></div>
1618<div class="ulist"><ul>
Junio C Hamano2bd8a742009-12-01 21:16:591619<li>
1620<p>
1621write, in the test suite, a test script that exposes the regression
1622</p>
1623</li>
1624<li>
1625<p>
1626use "git bisect run" to find the commit that introduced it
1627</p>
1628</li>
1629<li>
1630<p>
1631fix the bug that is often made obvious by the previous step
1632</p>
1633</li>
1634<li>
1635<p>
1636commit both the fix and the test script (and if needed more tests)
1637</p>
1638</li>
1639</ul></div>
Junio C Hamano103b5722011-01-31 05:03:451640<div class="paragraph"><p>And here is what Andreas said about this work-flow <a href="#5">[5]</a>:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591641<div class="quoteblock">
Junio C Hamano9d971152012-12-19 00:43:111642<div class="content">
Junio C Hamano103b5722011-01-31 05:03:451643<div class="paragraph"><p>To give some hard figures, we used to have an average report-to-fix
Junio C Hamano2bd8a742009-12-01 21:16:591644cycle of 142.6 hours (according to our somewhat weird bug-tracker
Junio C Hamano076ffcc2013-02-06 05:13:211645which just measures wall-clock time). Since we moved to Git, we&#8217;ve
Junio C Hamano2bd8a742009-12-01 21:16:591646lowered that to 16.2 hours. Primarily because we can stay on top of
Junio C Hamano103b5722011-01-31 05:03:451647the bug fixing now, and because everyone&#8217;s jockeying to get to fix
Junio C Hamano076ffcc2013-02-06 05:13:211648bugs (we&#8217;re quite proud of how lazy we are to let Git find the bugs
Junio C Hamano2bd8a742009-12-01 21:16:591649for us). Each new release results in ~40% fewer bugs (almost certainly
1650due to how we now feel about writing tests).</p></div>
Junio C Hamano103b5722011-01-31 05:03:451651</div>
Junio C Hamano9d971152012-12-19 00:43:111652<div class="attribution">
Junio C Hamano103b5722011-01-31 05:03:451653</div></div>
1654<div class="paragraph"><p>Clearly this work-flow uses the virtuous circle between test suites
Junio C Hamano2bd8a742009-12-01 21:16:591655and "git bisect". In fact it makes it the standard procedure to deal
1656with regression.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451657<div class="paragraph"><p>In other messages Andreas says that they also use the "best practices"
Junio C Hamano2bd8a742009-12-01 21:16:591658described above: small logical commits, topic branches, no evil
1659merge,&#8230; These practices all improve the bisectability of the commit
1660graph, by making it easier and more useful to bisect.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451661<div class="paragraph"><p>So a good work-flow should be designed around the above points. That
Junio C Hamano2bd8a742009-12-01 21:16:591662is making bisecting easier, more useful and standard.</p></div>
Junio C Hamano9d971152012-12-19 00:43:111663</div>
1664<div class="sect2">
1665<h3 id="_involving_qa_people_and_if_possible_end_users">Involving QA people and if possible end users</h3>
Junio C Hamano103b5722011-01-31 05:03:451666<div class="paragraph"><p>One nice about "git bisect" is that it is not only a developer
Junio C Hamano2bd8a742009-12-01 21:16:591667tool. It can effectively be used by QA people or even end users (if
1668they have access to the source code or if they can get access to all
1669the builds).</p></div>
Junio C Hamano103b5722011-01-31 05:03:451670<div class="paragraph"><p>There was a discussion at one point on the linux kernel mailing list
Junio C Hamano2bd8a742009-12-01 21:16:591671of whether it was ok to always ask end user to bisect, and very good
1672points were made to support the point of view that it is ok.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451673<div class="paragraph"><p>For example David Miller wrote <a href="#6">[6]</a>:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591674<div class="quoteblock">
Junio C Hamano9d971152012-12-19 00:43:111675<div class="content">
Junio C Hamano103b5722011-01-31 05:03:451676<div class="paragraph"><p>What people don&#8217;t get is that this is a situation where the "end node
Junio C Hamano2bd8a742009-12-01 21:16:591677principle" applies. When you have limited resources (here: developers)
Junio C Hamano103b5722011-01-31 05:03:451678you don&#8217;t push the bulk of the burden upon them. Instead you push
Junio C Hamano2bd8a742009-12-01 21:16:591679things out to the resource you have a lot of, the end nodes (here:
1680users), so that the situation actually scales.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451681</div>
Junio C Hamano9d971152012-12-19 00:43:111682<div class="attribution">
Junio C Hamano103b5722011-01-31 05:03:451683</div></div>
1684<div class="paragraph"><p>This means that it is often "cheaper" if QA people or end users can do
Junio C Hamano2bd8a742009-12-01 21:16:591685it.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451686<div class="paragraph"><p>What is interesting too is that end users that are reporting bugs (or
Junio C Hamano2bd8a742009-12-01 21:16:591687QA people that reproduced a bug) have access to the environment where
1688the bug happens. So they can often more easily reproduce a
1689regression. And if they can bisect, then more information will be
1690extracted from the environment where the bug happens, which means that
1691it will be easier to understand and then fix the bug.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451692<div class="paragraph"><p>For open source projects it can be a good way to get more useful
Junio C Hamano2bd8a742009-12-01 21:16:591693contributions from end users, and to introduce them to QA and
1694development activities.</p></div>
Junio C Hamano9d971152012-12-19 00:43:111695</div>
1696<div class="sect2">
1697<h3 id="_using_complex_scripts">Using complex scripts</h3>
Junio C Hamano103b5722011-01-31 05:03:451698<div class="paragraph"><p>In some cases like for kernel development it can be worth developing
Junio C Hamano2bd8a742009-12-01 21:16:591699complex scripts to be able to fully automate bisecting.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451700<div class="paragraph"><p>Here is what Ingo Molnar says about that <a href="#7">[7]</a>:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591701<div class="quoteblock">
Junio C Hamano9d971152012-12-19 00:43:111702<div class="content">
Junio C Hamano103b5722011-01-31 05:03:451703<div class="paragraph"><p>i have a fully automated bootup-hang bisection script. It is based on
Junio C Hamano2bd8a742009-12-01 21:16:591704"git-bisect run". I run the script, it builds and boots kernels fully
1705automatically, and when the bootup fails (the script notices that via
1706the serial log, which it continuously watches - or via a timeout, if
Junio C Hamano103b5722011-01-31 05:03:451707the system does not come up within 10 minutes it&#8217;s a "bad" kernel),
Junio C Hamano2bd8a742009-12-01 21:16:591708the script raises my attention via a beep and i power cycle the test
1709box. (yeah, i should make use of a managed power outlet to 100%
1710automate it)</p></div>
Junio C Hamano103b5722011-01-31 05:03:451711</div>
Junio C Hamano9d971152012-12-19 00:43:111712<div class="attribution">
Junio C Hamano103b5722011-01-31 05:03:451713</div></div>
Junio C Hamano9d971152012-12-19 00:43:111714</div>
1715<div class="sect2">
1716<h3 id="_combining_test_suites_git_bisect_and_other_systems_together">Combining test suites, git bisect and other systems together</h3>
Junio C Hamano103b5722011-01-31 05:03:451717<div class="paragraph"><p>We have seen that test suites an git bisect are very powerful when
Junio C Hamano2bd8a742009-12-01 21:16:591718used together. It can be even more powerful if you can combine them
1719with other systems.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451720<div class="paragraph"><p>For example some test suites could be run automatically at night with
Junio C Hamano2bd8a742009-12-01 21:16:591721some unusual (or even random) configurations. And if a regression is
1722found by a test suite, then "git bisect" can be automatically
1723launched, and its result can be emailed to the author of the first bad
1724commit found by "git bisect", and perhaps other people too. And a new
1725entry in the bug tracking system could be automatically created too.</p></div>
1726</div>
Junio C Hamano9d971152012-12-19 00:43:111727</div>
1728</div>
1729<div class="sect1">
Junio C Hamano2bd8a742009-12-01 21:16:591730<h2 id="_the_future_of_bisecting">The future of bisecting</h2>
1731<div class="sectionbody">
Junio C Hamano9d971152012-12-19 00:43:111732<div class="sect2">
1733<h3 id="_git_replace">"git replace"</h3>
Junio C Hamano103b5722011-01-31 05:03:451734<div class="paragraph"><p>We saw earlier that "git bisect skip" is now using a PRNG to try to
Junio C Hamano2bd8a742009-12-01 21:16:591735avoid areas in the commit graph where commits are untestable. The
1736problem is that sometimes the first bad commit will be in an
1737untestable area.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451738<div class="paragraph"><p>To simplify the discussion we will suppose that the untestable area is
Junio C Hamano2bd8a742009-12-01 21:16:591739a simple string of commits and that it was created by a breakage
Junio C Hamano103b5722011-01-31 05:03:451740introduced by one commit (let&#8217;s call it BBC for bisect breaking
1741commit) and later fixed by another one (let&#8217;s call it BFC for bisect
Junio C Hamano2bd8a742009-12-01 21:16:591742fixing commit).</p></div>
Junio C Hamano103b5722011-01-31 05:03:451743<div class="paragraph"><p>For example:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591744<div class="listingblock">
1745<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531746<pre><code>...-Y-BBC-X1-X2-X3-X4-X5-X6-BFC-Z-...</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591747</div></div>
Junio C Hamano103b5722011-01-31 05:03:451748<div class="paragraph"><p>where we know that Y is good and BFC is bad, and where BBC and X1 to
Junio C Hamano2bd8a742009-12-01 21:16:591749X6 are untestable.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451750<div class="paragraph"><p>In this case if you are bisecting manually, what you can do is create
Junio C Hamano2bd8a742009-12-01 21:16:591751a special branch that starts just before the BBC. The first commit in
1752this branch should be the BBC with the BFC squashed into it. And the
1753other commits in the branch should be the commits between BBC and BFC
1754rebased on the first commit of the branch and then the commit after
1755BFC also rebased on.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451756<div class="paragraph"><p>For example:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591757<div class="listingblock">
1758<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531759<pre><code> (BBC+BFC)-X1'-X2'-X3'-X4'-X5'-X6'-Z'
Junio C Hamano2bd8a742009-12-01 21:16:591760 /
Junio C Hamanoc14e6ad2014-10-31 20:25:531761...-Y-BBC-X1-X2-X3-X4-X5-X6-BFC-Z-...</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591762</div></div>
Junio C Hamano103b5722011-01-31 05:03:451763<div class="paragraph"><p>where commits quoted with ' have been rebased.</p></div>
1764<div class="paragraph"><p>You can easily create such a branch with Git using interactive rebase.</p></div>
1765<div class="paragraph"><p>For example using:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591766<div class="listingblock">
1767<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531768<pre><code>$ git rebase -i Y Z</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591769</div></div>
Junio C Hamano103b5722011-01-31 05:03:451770<div class="paragraph"><p>and then moving BFC after BBC and squashing it.</p></div>
1771<div class="paragraph"><p>After that you can start bisecting as usual in the new branch and you
Junio C Hamano2bd8a742009-12-01 21:16:591772should eventually find the first bad commit.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451773<div class="paragraph"><p>For example:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591774<div class="listingblock">
1775<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531776<pre><code>$ git bisect start Z' Y</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591777</div></div>
Junio C Hamano103b5722011-01-31 05:03:451778<div class="paragraph"><p>If you are using "git bisect run", you can use the same manual fix up
Junio C Hamano2bd8a742009-12-01 21:16:591779as above, and then start another "git bisect run" in the special
1780branch. Or as the "git bisect" man page says, the script passed to
1781"git bisect run" can apply a patch before it compiles and test the
1782software <a href="#8">[8]</a>. The patch should turn a current untestable commits
1783into a testable one. So the testing will result in "good" or "bad" and
1784"git bisect" will be able to find the first bad commit. And the script
1785should not forget to remove the patch once the testing is done before
1786exiting from the script.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451787<div class="paragraph"><p>(Note that instead of a patch you can use "git cherry-pick BFC" to
1788apply the fix, and in this case you should use "git reset --hard
Junio C Hamano2bd8a742009-12-01 21:16:591789HEAD^" to revert the cherry-pick after testing and before returning
1790from the script.)</p></div>
Junio C Hamano103b5722011-01-31 05:03:451791<div class="paragraph"><p>But the above ways to work around untestable areas are a little bit
Junio C Hamano2bd8a742009-12-01 21:16:591792clunky. Using special branches is nice because these branches can be
1793shared by developers like usual branches, but the risk is that people
1794will get many such branches. And it disrupts the normal "git bisect"
1795work-flow. So, if you want to use "git bisect run" completely
1796automatically, you have to add special code in your script to restart
1797bisection in the special branches.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451798<div class="paragraph"><p>Anyway one can notice in the above special branch example that the Z'
Junio C Hamano2bd8a742009-12-01 21:16:591799and Z commits should point to the same source code state (the same
Junio C Hamano103b5722011-01-31 05:03:451800"tree" in git parlance). That&#8217;s because Z' result from applying the
Junio C Hamano2bd8a742009-12-01 21:16:591801same changes as Z just in a slightly different order.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451802<div class="paragraph"><p>So if we could just "replace" Z by Z' when we bisect, then we would
Junio C Hamano2bd8a742009-12-01 21:16:591803not need to add anything to a script. It would just work for anyone in
1804the project sharing the special branches and the replacements.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451805<div class="paragraph"><p>With the example above that would give:</p></div>
Junio C Hamano2bd8a742009-12-01 21:16:591806<div class="listingblock">
1807<div class="content">
Junio C Hamanoc14e6ad2014-10-31 20:25:531808<pre><code> (BBC+BFC)-X1'-X2'-X3'-X4'-X5'-X6'-Z'-...
Junio C Hamano2bd8a742009-12-01 21:16:591809 /
Junio C Hamanoc14e6ad2014-10-31 20:25:531810...-Y-BBC-X1-X2-X3-X4-X5-X6-BFC-Z</code></pre>
Junio C Hamano2bd8a742009-12-01 21:16:591811</div></div>
Junio C Hamano103b5722011-01-31 05:03:451812<div class="paragraph"><p>That&#8217;s why the "git replace" command was created. Technically it
Junio C Hamano2bd8a742009-12-01 21:16:591813stores replacements "refs" in the "refs/replace/" hierarchy. These
1814"refs" are like branches (that are stored in "refs/heads/") or tags
1815(that are stored in "refs/tags"), and that means that they can
1816automatically be shared like branches or tags among developers.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451817<div class="paragraph"><p>"git replace" is a very powerful mechanism. It can be used to fix
Junio C Hamano2bd8a742009-12-01 21:16:591818commits in already released history, for example to change the commit
1819message or the author. And it can also be used instead of git "grafts"
1820to link a repository with another old repository.</p></div>
Junio C Hamano076ffcc2013-02-06 05:13:211821<div class="paragraph"><p>In fact it&#8217;s this last feature that "sold" it to the Git community, so
1822it is now in the "master" branch of Git&#8217;s Git repository and it should
1823be released in Git 1.6.5 in October or November 2009.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451824<div class="paragraph"><p>One problem with "git replace" is that currently it stores all the
Junio C Hamano2bd8a742009-12-01 21:16:591825replacements refs in "refs/replace/", but it would be perhaps better
1826if the replacement refs that are useful only for bisecting would be in
1827"refs/replace/bisect/". This way the replacement refs could be used
1828only for bisecting, while other refs directly in "refs/replace/" would
1829be used nearly all the time.</p></div>
Junio C Hamano9d971152012-12-19 00:43:111830</div>
1831<div class="sect2">
1832<h3 id="_bisecting_sporadic_bugs">Bisecting sporadic bugs</h3>
Junio C Hamano103b5722011-01-31 05:03:451833<div class="paragraph"><p>Another possible improvement to "git bisect" would be to optionally
Junio C Hamano2bd8a742009-12-01 21:16:591834add some redundancy to the tests performed so that it would be more
1835reliable when tracking sporadic bugs.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451836<div class="paragraph"><p>This has been requested by some kernel developers because some bugs
Junio C Hamano2bd8a742009-12-01 21:16:591837called sporadic bugs do not appear in all the kernel builds because
1838they are very dependent on the compiler output.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451839<div class="paragraph"><p>The idea is that every 3 test for example, "git bisect" could ask the
Junio C Hamano2bd8a742009-12-01 21:16:591840user to test a commit that has already been found to be "good" or
1841"bad" (because one of its descendants or one of its ancestors has been
1842found to be "good" or "bad" respectively). If it happens that a commit
1843has been previously incorrectly classified then the bisection can be
1844aborted early, hopefully before too many mistakes have been made. Then
1845the user will have to look at what happened and then restart the
1846bisection using a fixed bisect log.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451847<div class="paragraph"><p>There is already a project called BBChop created by Ealdwulf Wuffinga
Junio C Hamano2bd8a742009-12-01 21:16:591848on Github that does something like that using Bayesian Search Theory
1849<a href="#9">[9]</a>:</p></div>
1850<div class="quoteblock">
Junio C Hamano9d971152012-12-19 00:43:111851<div class="content">
Junio C Hamano103b5722011-01-31 05:03:451852<div class="paragraph"><p>BBChop is like <em>git bisect</em> (or equivalent), but works when your bug
Junio C Hamano2bd8a742009-12-01 21:16:591853is intermittent. That is, it works in the presence of false negatives
1854(when a version happens to work this time even though it contains the
1855bug). It assumes that there are no false positives (in principle, the
1856same approach would work, but adding it may be non-trivial).</p></div>
Junio C Hamano103b5722011-01-31 05:03:451857</div>
Junio C Hamano9d971152012-12-19 00:43:111858<div class="attribution">
Junio C Hamano103b5722011-01-31 05:03:451859</div></div>
1860<div class="paragraph"><p>But BBChop is independent of any VCS and it would be easier for Git
Junio C Hamano2bd8a742009-12-01 21:16:591861users to have something integrated in Git.</p></div>
1862</div>
Junio C Hamano9d971152012-12-19 00:43:111863</div>
1864</div>
1865<div class="sect1">
Junio C Hamano2bd8a742009-12-01 21:16:591866<h2 id="_conclusion">Conclusion</h2>
1867<div class="sectionbody">
Junio C Hamano103b5722011-01-31 05:03:451868<div class="paragraph"><p>We have seen that regressions are an important problem, and that "git
Junio C Hamano2bd8a742009-12-01 21:16:591869bisect" has nice features that complement very well practices and
1870other tools, especially test suites, that are generally used to fight
1871regressions. But it might be needed to change some work-flows and
1872(bad) habits to get the most out of it.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451873<div class="paragraph"><p>Some improvements to the algorithms inside "git bisect" are possible
Junio C Hamano2bd8a742009-12-01 21:16:591874and some new features could help in some cases, but overall "git
1875bisect" works already very well, is used a lot, and is already very
Junio C Hamano103b5722011-01-31 05:03:451876useful. To back up that last claim, let&#8217;s give the final word to Ingo
Junio C Hamano2bd8a742009-12-01 21:16:591877Molnar when he was asked by the author how much time does he think
1878"git bisect" saves him when he uses it:</p></div>
1879<div class="quoteblock">
Junio C Hamano9d971152012-12-19 00:43:111880<div class="content">
Junio C Hamano103b5722011-01-31 05:03:451881<div class="paragraph"><p>a <em>lot</em>.</p></div>
1882<div class="paragraph"><p>About ten years ago did i do my first <em>bisection</em> of a Linux patch
Junio C Hamano2bd8a742009-12-01 21:16:591883queue. That was prior the Git (and even prior the BitKeeper) days. I
1884literally days spent sorting out patches, creating what in essence
1885were standalone commits that i guessed to be related to that bug.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451886<div class="paragraph"><p>It was a tool of absolute last resort. I&#8217;d rather spend days looking
Junio C Hamano2bd8a742009-12-01 21:16:591887at printk output than do a manual <em>patch bisection</em>.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451888<div class="paragraph"><p>With Git bisect it&#8217;s a breeze: in the best case i can get a ~15 step
Junio C Hamano2bd8a742009-12-01 21:16:591889kernel bisection done in 20-30 minutes, in an automated way. Even with
Junio C Hamano103b5722011-01-31 05:03:451890manual help or when bisecting multiple, overlapping bugs, it&#8217;s rarely
Junio C Hamano2bd8a742009-12-01 21:16:591891more than an hour.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451892<div class="paragraph"><p>In fact it&#8217;s invaluable because there are bugs i would never even
1893<em>try</em> to debug if it wasn&#8217;t for git bisect. In the past there were bug
Junio C Hamano2bd8a742009-12-01 21:16:591894patterns that were immediately hopeless for me to debug - at best i
1895could send the crash/bug signature to lkml and hope that someone else
1896can think of something.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451897<div class="paragraph"><p>And even if a bisection fails today it tells us something valuable
1898about the bug: that it&#8217;s non-deterministic - timing or kernel image
Junio C Hamano2bd8a742009-12-01 21:16:591899layout dependent.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451900<div class="paragraph"><p>So git bisect is unconditional goodness - and feel free to quote that
Junio C Hamano2bd8a742009-12-01 21:16:591901;-)</p></div>
Junio C Hamano103b5722011-01-31 05:03:451902</div>
Junio C Hamano9d971152012-12-19 00:43:111903<div class="attribution">
Junio C Hamano103b5722011-01-31 05:03:451904</div></div>
Junio C Hamano2bd8a742009-12-01 21:16:591905</div>
Junio C Hamano9d971152012-12-19 00:43:111906</div>
1907<div class="sect1">
Junio C Hamanod7fccbf2013-07-25 03:24:571908<h2 id="_acknowledgments">Acknowledgments</h2>
Junio C Hamano2bd8a742009-12-01 21:16:591909<div class="sectionbody">
Junio C Hamano103b5722011-01-31 05:03:451910<div class="paragraph"><p>Many thanks to Junio Hamano for his help in reviewing this paper, for
Junio C Hamano076ffcc2013-02-06 05:13:211911reviewing the patches I sent to the Git mailing list, for discussing
Junio C Hamano2bd8a742009-12-01 21:16:591912some ideas and helping me improve them, for improving "git bisect" a
1913lot and for his awesome work in maintaining and developing Git.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451914<div class="paragraph"><p>Many thanks to Ingo Molnar for giving me very useful information that
Junio C Hamano2bd8a742009-12-01 21:16:591915appears in this paper, for commenting on this paper, for his
1916suggestions to improve "git bisect" and for evangelizing "git bisect"
1917on the linux kernel mailing lists.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451918<div class="paragraph"><p>Many thanks to Linus Torvalds for inventing, developing and
Junio C Hamano2bd8a742009-12-01 21:16:591919evangelizing "git bisect", Git and Linux.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451920<div class="paragraph"><p>Many thanks to the many other great people who helped one way or
Junio C Hamano076ffcc2013-02-06 05:13:211921another when I worked on Git, especially to Andreas Ericsson, Johannes
Junio C Hamano2bd8a742009-12-01 21:16:591922Schindelin, H. Peter Anvin, Daniel Barkalow, Bill Lear, John Hawley,
1923Shawn O. Pierce, Jeff King, Sam Vilain, Jon Seymour.</p></div>
Junio C Hamano103b5722011-01-31 05:03:451924<div class="paragraph"><p>Many thanks to the Linux-Kongress program committee for choosing the
Junio C Hamano2bd8a742009-12-01 21:16:591925author to given a talk and for publishing this paper.</p></div>
1926</div>
Junio C Hamano9d971152012-12-19 00:43:111927</div>
1928<div class="sect1">
Junio C Hamano2bd8a742009-12-01 21:16:591929<h2 id="_references">References</h2>
1930<div class="sectionbody">
Junio C Hamano103b5722011-01-31 05:03:451931<div class="ulist"><ul>
Junio C Hamano2bd8a742009-12-01 21:16:591932<li>
1933<p>
Junio C Hamanobeca3402017-04-27 02:21:511934<a id="1"></a>[1] <a href="https://www.nist.gov/sites/default/files/documents/director/planning/report02-3.pdf"><em>The Economic Impacts of Inadequate Infratructure for Software Testing</em>. Nist Planning Report 02-3</a>, see Executive Summary and Chapter 8.
Junio C Hamano2bd8a742009-12-01 21:16:591935</p>
1936</li>
1937<li>
1938<p>
Junio C Hamanobeca3402017-04-27 02:21:511939<a id="2"></a>[2] <a href="http://www.oracle.com/technetwork/java/codeconvtoc-136057.html"><em>Code Conventions for the Java Programming Language</em>. Sun Microsystems.</a>
Junio C Hamano2bd8a742009-12-01 21:16:591940</p>
1941</li>
1942<li>
1943<p>
Junio C Hamanobeca3402017-04-27 02:21:511944<a id="3"></a>[3] <a href="https://en.wikipedia.org/wiki/Software_maintenance"><em>Software maintenance</em>. Wikipedia.</a>
Junio C Hamano2bd8a742009-12-01 21:16:591945</p>
1946</li>
1947<li>
1948<p>
Junio C Hamanod3ab1ad2017-05-23 06:52:181949<a id="4"></a>[4] <a href="https://public-inbox.org/git/7vps5xsbwp.fsf_-_@assigned-by-dhcp.cox.net/">Junio C Hamano. <em>Automated bisect success story</em>.</a>
Junio C Hamano2bd8a742009-12-01 21:16:591950</p>
1951</li>
1952<li>
1953<p>
Junio C Hamanobeca3402017-04-27 02:21:511954<a id="5"></a>[5] <a href="https://lwn.net/Articles/317154/">Christian Couder. <em>Fully automated bisecting with "git bisect run"</em>. LWN.net.</a>
Junio C Hamano2bd8a742009-12-01 21:16:591955</p>
1956</li>
1957<li>
1958<p>
Junio C Hamanobeca3402017-04-27 02:21:511959<a id="6"></a>[6] <a href="https://lwn.net/Articles/277872/">Jonathan Corbet. <em>Bisection divides users and developers</em>. LWN.net.</a>
Junio C Hamano2bd8a742009-12-01 21:16:591960</p>
1961</li>
1962<li>
1963<p>
Junio C Hamanod3ab1ad2017-05-23 06:52:181964<a id="7"></a>[7] <a href="http://marc.info/?l=linux-kernel&amp;m=119702753411680&amp;w=2">Ingo Molnar. <em>Re: BUG 2.6.23-rc3 can&#8217;t see sd partitions on Alpha</em>. Linux-kernel mailing list.</a>
Junio C Hamano2bd8a742009-12-01 21:16:591965</p>
1966</li>
1967<li>
1968<p>
Junio C Hamanobeca3402017-04-27 02:21:511969<a id="8"></a>[8] <a href="https://www.kernel.org/pub/software/scm/git/docs/git-bisect.html">Junio C Hamano and the git-list. <em>git-bisect(1) Manual Page</em>. Linux Kernel Archives.</a>
Junio C Hamano2bd8a742009-12-01 21:16:591970</p>
1971</li>
1972<li>
1973<p>
Junio C Hamanobeca3402017-04-27 02:21:511974<a id="9"></a>[9] <a href="https://github.com/Ealdwulf/bbchop">Ealdwulf. <em>bbchop</em>. GitHub.</a>
Junio C Hamano2bd8a742009-12-01 21:16:591975</p>
1976</li>
1977</ul></div>
1978</div>
Junio C Hamano7bd050f2011-09-22 06:32:221979</div>
Junio C Hamano9d971152012-12-19 00:43:111980</div>
Junio C Hamano7bd050f2011-09-22 06:32:221981<div id="footnotes"><hr /></div>
Junio C Hamano2bd8a742009-12-01 21:16:591982<div id="footer">
1983<div id="footer-text">
Junio C Hamano2ef0ba32018-01-26 23:13:531984Last updated
1985 2018-01-26 15:11:04 PST
Junio C Hamano2bd8a742009-12-01 21:16:591986</div>
1987</div>
1988</body>
1989</html>