1645 lines
48 KiB
HTML
1645 lines
48 KiB
HTML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
|
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
|
|
<meta name="generator" content="AsciiDoc 10.2.0" />
|
|
<title>How to maintain Git</title>
|
|
<style type="text/css">
|
|
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
|
|
|
|
/* Default font. */
|
|
body {
|
|
font-family: Georgia,serif;
|
|
}
|
|
|
|
/* Title font. */
|
|
h1, h2, h3, h4, h5, h6,
|
|
div.title, caption.title,
|
|
thead, p.table.header,
|
|
#toctitle,
|
|
#author, #revnumber, #revdate, #revremark,
|
|
#footer {
|
|
font-family: Arial,Helvetica,sans-serif;
|
|
}
|
|
|
|
body {
|
|
margin: 1em 5% 1em 5%;
|
|
}
|
|
|
|
a {
|
|
color: blue;
|
|
text-decoration: underline;
|
|
}
|
|
a:visited {
|
|
color: fuchsia;
|
|
}
|
|
|
|
em {
|
|
font-style: italic;
|
|
color: navy;
|
|
}
|
|
|
|
strong {
|
|
font-weight: bold;
|
|
color: #083194;
|
|
}
|
|
|
|
h1, h2, h3, h4, h5, h6 {
|
|
color: #527bbd;
|
|
margin-top: 1.2em;
|
|
margin-bottom: 0.5em;
|
|
line-height: 1.3;
|
|
}
|
|
|
|
h1, h2, h3 {
|
|
border-bottom: 2px solid silver;
|
|
}
|
|
h2 {
|
|
padding-top: 0.5em;
|
|
}
|
|
h3 {
|
|
float: left;
|
|
}
|
|
h3 + * {
|
|
clear: left;
|
|
}
|
|
h5 {
|
|
font-size: 1.0em;
|
|
}
|
|
|
|
div.sectionbody {
|
|
margin-left: 0;
|
|
}
|
|
|
|
hr {
|
|
border: 1px solid silver;
|
|
}
|
|
|
|
p {
|
|
margin-top: 0.5em;
|
|
margin-bottom: 0.5em;
|
|
}
|
|
|
|
ul, ol, li > p {
|
|
margin-top: 0;
|
|
}
|
|
ul > li { color: #aaa; }
|
|
ul > li > * { color: black; }
|
|
|
|
.monospaced, code, pre {
|
|
font-family: "Courier New", Courier, monospace;
|
|
font-size: inherit;
|
|
color: navy;
|
|
padding: 0;
|
|
margin: 0;
|
|
}
|
|
pre {
|
|
white-space: pre-wrap;
|
|
}
|
|
|
|
#author {
|
|
color: #527bbd;
|
|
font-weight: bold;
|
|
font-size: 1.1em;
|
|
}
|
|
#email {
|
|
}
|
|
#revnumber, #revdate, #revremark {
|
|
}
|
|
|
|
#footer {
|
|
font-size: small;
|
|
border-top: 2px solid silver;
|
|
padding-top: 0.5em;
|
|
margin-top: 4.0em;
|
|
}
|
|
#footer-text {
|
|
float: left;
|
|
padding-bottom: 0.5em;
|
|
}
|
|
#footer-badges {
|
|
float: right;
|
|
padding-bottom: 0.5em;
|
|
}
|
|
|
|
#preamble {
|
|
margin-top: 1.5em;
|
|
margin-bottom: 1.5em;
|
|
}
|
|
div.imageblock, div.exampleblock, div.verseblock,
|
|
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
|
|
div.admonitionblock {
|
|
margin-top: 1.0em;
|
|
margin-bottom: 1.5em;
|
|
}
|
|
div.admonitionblock {
|
|
margin-top: 2.0em;
|
|
margin-bottom: 2.0em;
|
|
margin-right: 10%;
|
|
color: #606060;
|
|
}
|
|
|
|
div.content { /* Block element content. */
|
|
padding: 0;
|
|
}
|
|
|
|
/* Block element titles. */
|
|
div.title, caption.title {
|
|
color: #527bbd;
|
|
font-weight: bold;
|
|
text-align: left;
|
|
margin-top: 1.0em;
|
|
margin-bottom: 0.5em;
|
|
}
|
|
div.title + * {
|
|
margin-top: 0;
|
|
}
|
|
|
|
td div.title:first-child {
|
|
margin-top: 0.0em;
|
|
}
|
|
div.content div.title:first-child {
|
|
margin-top: 0.0em;
|
|
}
|
|
div.content + div.title {
|
|
margin-top: 0.0em;
|
|
}
|
|
|
|
div.sidebarblock > div.content {
|
|
background: #ffffee;
|
|
border: 1px solid #dddddd;
|
|
border-left: 4px solid #f0f0f0;
|
|
padding: 0.5em;
|
|
}
|
|
|
|
div.listingblock > div.content {
|
|
border: 1px solid #dddddd;
|
|
border-left: 5px solid #f0f0f0;
|
|
background: #f8f8f8;
|
|
padding: 0.5em;
|
|
}
|
|
|
|
div.quoteblock, div.verseblock {
|
|
padding-left: 1.0em;
|
|
margin-left: 1.0em;
|
|
margin-right: 10%;
|
|
border-left: 5px solid #f0f0f0;
|
|
color: #888;
|
|
}
|
|
|
|
div.quoteblock > div.attribution {
|
|
padding-top: 0.5em;
|
|
text-align: right;
|
|
}
|
|
|
|
div.verseblock > pre.content {
|
|
font-family: inherit;
|
|
font-size: inherit;
|
|
}
|
|
div.verseblock > div.attribution {
|
|
padding-top: 0.75em;
|
|
text-align: left;
|
|
}
|
|
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
|
|
div.verseblock + div.attribution {
|
|
text-align: left;
|
|
}
|
|
|
|
div.admonitionblock .icon {
|
|
vertical-align: top;
|
|
font-size: 1.1em;
|
|
font-weight: bold;
|
|
text-decoration: underline;
|
|
color: #527bbd;
|
|
padding-right: 0.5em;
|
|
}
|
|
div.admonitionblock td.content {
|
|
padding-left: 0.5em;
|
|
border-left: 3px solid #dddddd;
|
|
}
|
|
|
|
div.exampleblock > div.content {
|
|
border-left: 3px solid #dddddd;
|
|
padding-left: 0.5em;
|
|
}
|
|
|
|
div.imageblock div.content { padding-left: 0; }
|
|
span.image img { border-style: none; vertical-align: text-bottom; }
|
|
a.image:visited { color: white; }
|
|
|
|
dl {
|
|
margin-top: 0.8em;
|
|
margin-bottom: 0.8em;
|
|
}
|
|
dt {
|
|
margin-top: 0.5em;
|
|
margin-bottom: 0;
|
|
font-style: normal;
|
|
color: navy;
|
|
}
|
|
dd > *:first-child {
|
|
margin-top: 0.1em;
|
|
}
|
|
|
|
ul, ol {
|
|
list-style-position: outside;
|
|
}
|
|
ol.arabic {
|
|
list-style-type: decimal;
|
|
}
|
|
ol.loweralpha {
|
|
list-style-type: lower-alpha;
|
|
}
|
|
ol.upperalpha {
|
|
list-style-type: upper-alpha;
|
|
}
|
|
ol.lowerroman {
|
|
list-style-type: lower-roman;
|
|
}
|
|
ol.upperroman {
|
|
list-style-type: upper-roman;
|
|
}
|
|
|
|
div.compact ul, div.compact ol,
|
|
div.compact p, div.compact p,
|
|
div.compact div, div.compact div {
|
|
margin-top: 0.1em;
|
|
margin-bottom: 0.1em;
|
|
}
|
|
|
|
tfoot {
|
|
font-weight: bold;
|
|
}
|
|
td > div.verse {
|
|
white-space: pre;
|
|
}
|
|
|
|
div.hdlist {
|
|
margin-top: 0.8em;
|
|
margin-bottom: 0.8em;
|
|
}
|
|
div.hdlist tr {
|
|
padding-bottom: 15px;
|
|
}
|
|
dt.hdlist1.strong, td.hdlist1.strong {
|
|
font-weight: bold;
|
|
}
|
|
td.hdlist1 {
|
|
vertical-align: top;
|
|
font-style: normal;
|
|
padding-right: 0.8em;
|
|
color: navy;
|
|
}
|
|
td.hdlist2 {
|
|
vertical-align: top;
|
|
}
|
|
div.hdlist.compact tr {
|
|
margin: 0;
|
|
padding-bottom: 0;
|
|
}
|
|
|
|
.comment {
|
|
background: yellow;
|
|
}
|
|
|
|
.footnote, .footnoteref {
|
|
font-size: 0.8em;
|
|
}
|
|
|
|
span.footnote, span.footnoteref {
|
|
vertical-align: super;
|
|
}
|
|
|
|
#footnotes {
|
|
margin: 20px 0 20px 0;
|
|
padding: 7px 0 0 0;
|
|
}
|
|
|
|
#footnotes div.footnote {
|
|
margin: 0 0 5px 0;
|
|
}
|
|
|
|
#footnotes hr {
|
|
border: none;
|
|
border-top: 1px solid silver;
|
|
height: 1px;
|
|
text-align: left;
|
|
margin-left: 0;
|
|
width: 20%;
|
|
min-width: 100px;
|
|
}
|
|
|
|
div.colist td {
|
|
padding-right: 0.5em;
|
|
padding-bottom: 0.3em;
|
|
vertical-align: top;
|
|
}
|
|
div.colist td img {
|
|
margin-top: 0.3em;
|
|
}
|
|
|
|
@media print {
|
|
#footer-badges { display: none; }
|
|
}
|
|
|
|
#toc {
|
|
margin-bottom: 2.5em;
|
|
}
|
|
|
|
#toctitle {
|
|
color: #527bbd;
|
|
font-size: 1.1em;
|
|
font-weight: bold;
|
|
margin-top: 1.0em;
|
|
margin-bottom: 0.1em;
|
|
}
|
|
|
|
div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
|
|
margin-top: 0;
|
|
margin-bottom: 0;
|
|
}
|
|
div.toclevel2 {
|
|
margin-left: 2em;
|
|
font-size: 0.9em;
|
|
}
|
|
div.toclevel3 {
|
|
margin-left: 4em;
|
|
font-size: 0.9em;
|
|
}
|
|
div.toclevel4 {
|
|
margin-left: 6em;
|
|
font-size: 0.9em;
|
|
}
|
|
|
|
span.aqua { color: aqua; }
|
|
span.black { color: black; }
|
|
span.blue { color: blue; }
|
|
span.fuchsia { color: fuchsia; }
|
|
span.gray { color: gray; }
|
|
span.green { color: green; }
|
|
span.lime { color: lime; }
|
|
span.maroon { color: maroon; }
|
|
span.navy { color: navy; }
|
|
span.olive { color: olive; }
|
|
span.purple { color: purple; }
|
|
span.red { color: red; }
|
|
span.silver { color: silver; }
|
|
span.teal { color: teal; }
|
|
span.white { color: white; }
|
|
span.yellow { color: yellow; }
|
|
|
|
span.aqua-background { background: aqua; }
|
|
span.black-background { background: black; }
|
|
span.blue-background { background: blue; }
|
|
span.fuchsia-background { background: fuchsia; }
|
|
span.gray-background { background: gray; }
|
|
span.green-background { background: green; }
|
|
span.lime-background { background: lime; }
|
|
span.maroon-background { background: maroon; }
|
|
span.navy-background { background: navy; }
|
|
span.olive-background { background: olive; }
|
|
span.purple-background { background: purple; }
|
|
span.red-background { background: red; }
|
|
span.silver-background { background: silver; }
|
|
span.teal-background { background: teal; }
|
|
span.white-background { background: white; }
|
|
span.yellow-background { background: yellow; }
|
|
|
|
span.big { font-size: 2em; }
|
|
span.small { font-size: 0.6em; }
|
|
|
|
span.underline { text-decoration: underline; }
|
|
span.overline { text-decoration: overline; }
|
|
span.line-through { text-decoration: line-through; }
|
|
|
|
div.unbreakable { page-break-inside: avoid; }
|
|
|
|
|
|
/*
|
|
* xhtml11 specific
|
|
*
|
|
* */
|
|
|
|
div.tableblock {
|
|
margin-top: 1.0em;
|
|
margin-bottom: 1.5em;
|
|
}
|
|
div.tableblock > table {
|
|
border: 3px solid #527bbd;
|
|
}
|
|
thead, p.table.header {
|
|
font-weight: bold;
|
|
color: #527bbd;
|
|
}
|
|
p.table {
|
|
margin-top: 0;
|
|
}
|
|
/* Because the table frame attribute is overridden by CSS in most browsers. */
|
|
div.tableblock > table[frame="void"] {
|
|
border-style: none;
|
|
}
|
|
div.tableblock > table[frame="hsides"] {
|
|
border-left-style: none;
|
|
border-right-style: none;
|
|
}
|
|
div.tableblock > table[frame="vsides"] {
|
|
border-top-style: none;
|
|
border-bottom-style: none;
|
|
}
|
|
|
|
|
|
/*
|
|
* html5 specific
|
|
*
|
|
* */
|
|
|
|
table.tableblock {
|
|
margin-top: 1.0em;
|
|
margin-bottom: 1.5em;
|
|
}
|
|
thead, p.tableblock.header {
|
|
font-weight: bold;
|
|
color: #527bbd;
|
|
}
|
|
p.tableblock {
|
|
margin-top: 0;
|
|
}
|
|
table.tableblock {
|
|
border-width: 3px;
|
|
border-spacing: 0px;
|
|
border-style: solid;
|
|
border-color: #527bbd;
|
|
border-collapse: collapse;
|
|
}
|
|
th.tableblock, td.tableblock {
|
|
border-width: 1px;
|
|
padding: 4px;
|
|
border-style: solid;
|
|
border-color: #527bbd;
|
|
}
|
|
|
|
table.tableblock.frame-topbot {
|
|
border-left-style: hidden;
|
|
border-right-style: hidden;
|
|
}
|
|
table.tableblock.frame-sides {
|
|
border-top-style: hidden;
|
|
border-bottom-style: hidden;
|
|
}
|
|
table.tableblock.frame-none {
|
|
border-style: hidden;
|
|
}
|
|
|
|
th.tableblock.halign-left, td.tableblock.halign-left {
|
|
text-align: left;
|
|
}
|
|
th.tableblock.halign-center, td.tableblock.halign-center {
|
|
text-align: center;
|
|
}
|
|
th.tableblock.halign-right, td.tableblock.halign-right {
|
|
text-align: right;
|
|
}
|
|
|
|
th.tableblock.valign-top, td.tableblock.valign-top {
|
|
vertical-align: top;
|
|
}
|
|
th.tableblock.valign-middle, td.tableblock.valign-middle {
|
|
vertical-align: middle;
|
|
}
|
|
th.tableblock.valign-bottom, td.tableblock.valign-bottom {
|
|
vertical-align: bottom;
|
|
}
|
|
|
|
|
|
/*
|
|
* manpage specific
|
|
*
|
|
* */
|
|
|
|
body.manpage h1 {
|
|
padding-top: 0.5em;
|
|
padding-bottom: 0.5em;
|
|
border-top: 2px solid silver;
|
|
border-bottom: 2px solid silver;
|
|
}
|
|
body.manpage h2 {
|
|
border-style: none;
|
|
}
|
|
body.manpage div.sectionbody {
|
|
margin-left: 3em;
|
|
}
|
|
|
|
@media print {
|
|
body.manpage div#toc { display: none; }
|
|
}
|
|
|
|
|
|
</style>
|
|
<script type="text/javascript">
|
|
/*<+'])');
|
|
// Function that scans the DOM tree for header elements (the DOM2
|
|
// nodeIterator API would be a better technique but not supported by all
|
|
// browsers).
|
|
var iterate = function (el) {
|
|
for (var i = el.firstChild; i != null; i = i.nextSibling) {
|
|
if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
|
|
var mo = re.exec(i.tagName);
|
|
if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
|
|
result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
|
|
}
|
|
iterate(i);
|
|
}
|
|
}
|
|
}
|
|
iterate(el);
|
|
return result;
|
|
}
|
|
|
|
var toc = document.getElementById("toc");
|
|
if (!toc) {
|
|
return;
|
|
}
|
|
|
|
// Delete existing TOC entries in case we're reloading the TOC.
|
|
var tocEntriesToRemove = [];
|
|
var i;
|
|
for (i = 0; i < toc.childNodes.length; i++) {
|
|
var entry = toc.childNodes[i];
|
|
if (entry.nodeName.toLowerCase() == 'div'
|
|
&& entry.getAttribute("class")
|
|
&& entry.getAttribute("class").match(/^toclevel/))
|
|
tocEntriesToRemove.push(entry);
|
|
}
|
|
for (i = 0; i < tocEntriesToRemove.length; i++) {
|
|
toc.removeChild(tocEntriesToRemove[i]);
|
|
}
|
|
|
|
// Rebuild TOC entries.
|
|
var entries = tocEntries(document.getElementById("content"), toclevels);
|
|
for (var i = 0; i < entries.length; ++i) {
|
|
var entry = entries[i];
|
|
if (entry.element.id == "")
|
|
entry.element.id = "_toc_" + i;
|
|
var a = document.createElement("a");
|
|
a.href = "#" + entry.element.id;
|
|
a.appendChild(document.createTextNode(entry.text));
|
|
var div = document.createElement("div");
|
|
div.appendChild(a);
|
|
div.className = "toclevel" + entry.toclevel;
|
|
toc.appendChild(div);
|
|
}
|
|
if (entries.length == 0)
|
|
toc.parentNode.removeChild(toc);
|
|
},
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Footnotes generator
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
/* Based on footnote generation code from:
|
|
* http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
|
|
*/
|
|
|
|
footnotes: function () {
|
|
// Delete existing footnote entries in case we're reloading the footnodes.
|
|
var i;
|
|
var noteholder = document.getElementById("footnotes");
|
|
if (!noteholder) {
|
|
return;
|
|
}
|
|
var entriesToRemove = [];
|
|
for (i = 0; i < noteholder.childNodes.length; i++) {
|
|
var entry = noteholder.childNodes[i];
|
|
if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
|
|
entriesToRemove.push(entry);
|
|
}
|
|
for (i = 0; i < entriesToRemove.length; i++) {
|
|
noteholder.removeChild(entriesToRemove[i]);
|
|
}
|
|
|
|
// Rebuild footnote entries.
|
|
var cont = document.getElementById("content");
|
|
var spans = cont.getElementsByTagName("span");
|
|
var refs = {};
|
|
var n = 0;
|
|
for (i=0; i<spans.length; i++) {
|
|
if (spans[i].className == "footnote") {
|
|
n++;
|
|
var note = spans[i].getAttribute("data-note");
|
|
if (!note) {
|
|
// Use [\s\S] in place of . so multi-line matches work.
|
|
// Because JavaScript has no s (dotall) regex flag.
|
|
note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
|
|
spans[i].innerHTML =
|
|
"[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
|
|
"' title='View footnote' class='footnote'>" + n + "</a>]";
|
|
spans[i].setAttribute("data-note", note);
|
|
}
|
|
noteholder.innerHTML +=
|
|
"<div class='footnote' id='_footnote_" + n + "'>" +
|
|
"<a href='#_footnoteref_" + n + "' title='Return to text'>" +
|
|
n + "</a>. " + note + "</div>";
|
|
var id =spans[i].getAttribute("id");
|
|
if (id != null) refs["#"+id] = n;
|
|
}
|
|
}
|
|
if (n == 0)
|
|
noteholder.parentNode.removeChild(noteholder);
|
|
else {
|
|
// Process footnoterefs.
|
|
for (i=0; i<spans.length; i++) {
|
|
if (spans[i].className == "footnoteref") {
|
|
var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
|
|
href = href.match(/#.*/)[0]; // Because IE return full URL.
|
|
n = refs[href];
|
|
spans[i].innerHTML =
|
|
"[<a href='#_footnote_" + n +
|
|
"' title='View footnote' class='footnote'>" + n + "</a>]";
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
install: function(toclevels) {
|
|
var timerId;
|
|
|
|
function reinstall() {
|
|
asciidoc.footnotes();
|
|
if (toclevels) {
|
|
asciidoc.toc(toclevels);
|
|
}
|
|
}
|
|
|
|
function reinstallAndRemoveTimer() {
|
|
clearInterval(timerId);
|
|
reinstall();
|
|
}
|
|
|
|
timerId = setInterval(reinstall, 500);
|
|
if (document.addEventListener)
|
|
document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
|
|
else
|
|
window.onload = reinstallAndRemoveTimer;
|
|
}
|
|
|
|
}
|
|
asciidoc.install();
|
|
/*]]>*/
|
|
</script>
|
|
</head>
|
|
<body class="article">
|
|
<div id="header">
|
|
<h1>How to maintain Git</h1>
|
|
<span id="revdate"></span>
|
|
</div>
|
|
<div id="content">
|
|
<div class="sect1">
|
|
<h2 id="_activities">Activities</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph"><p>The maintainer’s Git time is spent on three activities.</p></div>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
Communication (45%)
|
|
</p>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>Mailing list discussions on general design, fielding user
|
|
questions, diagnosing bug reports; reviewing, commenting on,
|
|
suggesting alternatives to, and rejecting patches.</code></pre>
|
|
</div></div>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Integration (50%)
|
|
</p>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>Applying new patches from the contributors while spotting and
|
|
correcting minor mistakes, shuffling the integration and
|
|
testing branches, pushing the results out, cutting the
|
|
releases, and making announcements.</code></pre>
|
|
</div></div>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Own development (5%)
|
|
</p>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>Scratching my own itch and sending proposed patch series out.</code></pre>
|
|
</div></div>
|
|
</li>
|
|
</ul></div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_the_policy">The Policy</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph"><p>The policy on Integration is informally mentioned in "A Note
|
|
from the maintainer" message, which is periodically posted to
|
|
the mailing list after each feature release is made:</p></div>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
Feature releases are numbered as vX.Y.0 and are meant to
|
|
contain bugfixes and enhancements in any area, including
|
|
functionality, performance and usability, without regression.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Maintenance releases are numbered as vX.Y.Z (0 < Z) and are meant
|
|
to contain only bugfixes for the corresponding vX.Y.0 feature
|
|
release and earlier maintenance releases vX.Y.W (W < Z).
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
The <em>master</em> branch is used to prepare for the next feature
|
|
release. In other words, at some point, the tip of <em>master</em>
|
|
branch is tagged as vX.(Y+1).0, when vX.Y.0 is the latest
|
|
feature release.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
<em>maint</em> branch is used to prepare for the next maintenance
|
|
release. After the feature release vX.Y.0 is made, the tip
|
|
of <em>maint</em> branch is set to that release, and bugfixes will
|
|
accumulate on the branch, and at some point, the tip of the
|
|
branch is tagged with vX.Y.1, vX.Y.2, and so on.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
<em>next</em> branch is used to publish changes (both enhancements
|
|
and fixes) that (1) have worthwhile goal, (2) are in a fairly
|
|
good shape suitable for everyday use, (3) but have not yet
|
|
demonstrated to be regression free. Reviews from contributors on
|
|
the mailing list help to make the determination. After a topic
|
|
is merged to <em>next</em>, it is tested for at least 7 calendar days
|
|
before getting merged to <em>master</em>.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
<em>seen</em> branch is used to publish other proposed changes that do
|
|
not yet pass the criteria set for <em>next</em> (see above), but there
|
|
is no promise that <em>seen</em> will contain everything. A topic that
|
|
had no reviewer reaction may not be picked up.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
A new topic will first get merged to <em>seen</em>, unless it is
|
|
trivially correct and clearly urgent, in which case it may be
|
|
directly merged to <em>next</em> or even to <em>master</em>.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
If a topic that was picked up to <em>seen</em> becomes and stays
|
|
inactive for 3 calendar weeks without having seen a clear
|
|
consensus that it is good enough to be moved to <em>next</em>, the
|
|
topic may be discarded from <em>seen</em>. Interested parties are
|
|
still free to revive the topic. For the purpose of this
|
|
guideline, the definition of being "inactive" is that nobody
|
|
has discussed the topic, no new iteration of the topic was
|
|
posted, and no responses to the review comments were given.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
The tips of <em>master</em> and <em>maint</em> branches will not be rewound to
|
|
allow people to build their own customization on top of them.
|
|
Early in a new development cycle, <em>next</em> is rewound to the tip of
|
|
<em>master</em> once, but otherwise it will not be rewound until the end
|
|
of the cycle.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Usually <em>master</em> contains all of <em>maint</em> and <em>next</em> contains all
|
|
of <em>master</em>. <em>seen</em> contains all the topics merged to <em>next</em>, but
|
|
is rebuilt directly on <em>master</em>.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
The tip of <em>master</em> is meant to be more stable than any
|
|
tagged releases, and the users are encouraged to follow it.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
The <em>next</em> branch is where new action takes place, and the
|
|
users are encouraged to test it so that regressions and bugs
|
|
are found before new topics are merged to <em>master</em>.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
When a problem is found in a topic in <em>next</em>, the topic is marked
|
|
not to be merged to <em>master</em>. Follow-up patches are discussed on
|
|
the mailing list and applied to the topic after being reviewed and
|
|
then the topic is merged (again) to <em>next</em>. After going through
|
|
the usual testing in <em>next</em>, the entire (fixed) topic is merged
|
|
to <em>master</em>.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
One release cycle for a feature release is expected to last for
|
|
eight to ten weeks. A few "release candidate" releases are
|
|
expected to be tagged about a week apart before the final
|
|
release, and a "preview" release is tagged about a week before
|
|
the first release candidate gets tagged.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
After the preview release is tagged, topics that were well
|
|
reviewed may be merged to <em>master</em> before spending the usual 7
|
|
calendar days in <em>next</em>, with the expectation that any bugs in
|
|
them can be caught and fixed in the release candidates before
|
|
the final release.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
After the first release candidate is tagged, the contributors are
|
|
strongly encouraged to focus on finding and fixing new regressions
|
|
introduced during the cycle, over addressing old bugs and any new
|
|
features. Topics stop getting merged down from <em>next</em> to <em>master</em>,
|
|
and new topics stop getting merged to <em>next</em>. Unless they are fixes
|
|
to new regressions in the cycle, that is.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Soon after a feature release is made, the tip of <em>maint</em> gets
|
|
fast-forwarded to point at the release. Topics that have been
|
|
kept in <em>next</em> are merged down to <em>master</em> and a new development
|
|
cycle starts.
|
|
</p>
|
|
</li>
|
|
</ul></div>
|
|
<div class="paragraph"><p>Note that before v1.9.0 release, the version numbers used to be
|
|
structured slightly differently. vX.Y.Z were feature releases while
|
|
vX.Y.Z.W were maintenance releases for vX.Y.Z.</p></div>
|
|
<div class="paragraph"><p>Because most of the lines of code in Git are written by individual
|
|
contributors, and contributions come in the form of e-mailed patches
|
|
published on the mailing list, the project maintains a mapping from
|
|
individual commits to the Message-Id of the e-mail that resulted in
|
|
the commit, to help tracking the origin of the changes. The notes
|
|
in "refs/notes/amlog" are used for this purpose, and are published
|
|
along with the broken-out branches to the maintainer’s repository.</p></div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_a_typical_git_day">A Typical Git Day</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph"><p>A typical Git day for the maintainer implements the above policy
|
|
by doing the following:</p></div>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
Scan mailing list. Respond with review comments, suggestions
|
|
etc. Kibitz. Collect potentially usable patches from the
|
|
mailing list. Patches about a single topic go to one mailbox (I
|
|
read my mail in Gnus, and type \C-o to save/append messages in
|
|
files in mbox format).
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Write his own patches to address issues raised on the list but
|
|
nobody has stepped up to solve. Send it out just like other
|
|
contributors do, and pick them up just like patches from other
|
|
contributors (see above).
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Review the patches in the saved mailboxes. Edit proposed log
|
|
message for typofixes and clarifications, and add Acks
|
|
collected from the list. Edit patch to incorporate "Oops,
|
|
that should have been like this" fixes from the discussion.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Classify the collected patches and handle <em>master</em> and
|
|
<em>maint</em> updates:
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Obviously correct fixes that pertain to the tip of <em>maint</em>
|
|
are directly applied to <em>maint</em>.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Obviously correct fixes that pertain to the tip of <em>master</em>
|
|
are directly applied to <em>master</em>.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Other topics are not handled in this step.
|
|
</p>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>This step is done with "git am".</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git checkout master ;# or "git checkout maint"
|
|
$ git am -sc3 mailbox
|
|
$ make test</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>In practice, almost no patch directly goes to 'master' or
|
|
'maint'.</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>Applying the e-mailed patches using "git am" automatically records
|
|
the mappings from 'Message-Id' to the applied commit in the "amlog"
|
|
notes. Periodically check that this is working with "git show -s
|
|
--notes=amlog $commit".</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>This mapping is maintained with the aid of the "post-applypatch"
|
|
hook found in the 'todo' branch. That hook should be installed
|
|
before applying patches. It is also helpful to carry forward any
|
|
relevant amlog entries when rebasing, so the following config may
|
|
be useful:</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>[notes]
|
|
rewriteRef = refs/notes/amlog</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>Avoid "cherry-pick", as it does not propagate notes by design. Use
|
|
either "git commit --amend" or "git rebase" to make corrections to
|
|
an existing commit, even for a single-patch topic.</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>Make sure that a push refspec for 'refs/notes/amlog' is in the
|
|
remote configuration for publishing repositories. A few sample
|
|
configurations look like the following:</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>[remote "github"]
|
|
url = https://github.com/gitster/git
|
|
pushurl = github.com:gitster/git.git
|
|
mirror</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>[remote "github2"]
|
|
url = https://github.com/git/git
|
|
fetch = +refs/heads/*:refs/remotes/github2/*
|
|
pushurl = github.com:git/git.git
|
|
push = refs/heads/maint:refs/heads/maint
|
|
push = refs/heads/master:refs/heads/master
|
|
push = refs/heads/next:refs/heads/next
|
|
push = +refs/heads/seen:refs/heads/seen
|
|
push = +refs/notes/amlog</code></pre>
|
|
</div></div>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Review the last issue of "What’s cooking" message, review the
|
|
topics ready for merging (topic→master and topic→maint). Use
|
|
"Meta/cook -w" script (where Meta/ contains a checkout of the
|
|
<em>todo</em> branch) to aid this step.
|
|
</p>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>And perform the merge. Use "Meta/Reintegrate -e" script (see
|
|
later) to aid this step.</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ Meta/cook -w last-issue-of-whats-cooking.mbox</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git checkout master ;# or "git checkout maint"
|
|
$ echo ai/topic | Meta/Reintegrate -e ;# "git merge ai/topic"
|
|
$ git log -p ORIG_HEAD.. ;# final review
|
|
$ git diff ORIG_HEAD.. ;# final review
|
|
$ make test ;# final review</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>If the tip of 'master' is updated, also generate the preformatted
|
|
documentation and push the out result to git-htmldocs and
|
|
git-manpages repositories.</code></pre>
|
|
</div></div>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Handle the remaining patches:
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Anything unobvious that is applicable to <em>master</em> (in other
|
|
words, does not depend on anything that is still in <em>next</em>
|
|
and not in <em>master</em>) is applied to a new topic branch that
|
|
is forked from the tip of <em>master</em> (or the last feature release,
|
|
which is a bit older than <em>master</em>). This includes both
|
|
enhancements and unobvious fixes to <em>master</em>. A topic
|
|
branch is named as ai/topic where "ai" is two-letter string
|
|
named after author’s initial and "topic" is a descriptive name
|
|
of the topic (in other words, "what’s the series is about").
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
An unobvious fix meant for <em>maint</em> is applied to a new
|
|
topic branch that is forked from the tip of <em>maint</em> (or the
|
|
oldest and still relevant maintenance branch). The
|
|
topic may be named as ai/maint-topic.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Changes that pertain to an existing topic are applied to
|
|
the branch, but:
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
obviously correct ones are applied first;
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
questionable ones are discarded or applied to near the tip;
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Replacement patches to an existing topic are accepted only
|
|
for commits not in <em>next</em>.
|
|
</p>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>The initial round is done with:</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git checkout ai/topic ;# or "git checkout -b ai/topic master"
|
|
$ git am -sc3 --whitespace=warn mailbox</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>and replacing an existing topic with subsequent round is done with:</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git checkout master...ai/topic ;# try to reapply to the same base
|
|
$ git am -sc3 --whitespace=warn mailbox</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>to prepare the new round on a detached HEAD, and then</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git range-diff @{-1}...
|
|
$ git diff @{-1}</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>to double check what changed since the last round, and finally</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git checkout -B @{-1}</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>to conclude (the last step is why a topic already in 'next' is
|
|
not replaced but updated incrementally).</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>Whether it is the initial round or a subsequent round, the topic
|
|
may not build even in isolation, or may break the build when
|
|
merged to integration branches due to bugs. There may already
|
|
be obvious and trivial improvements suggested on the list. The
|
|
maintainer often adds an extra commit, with "SQUASH???" in its
|
|
title, to fix things up, before publishing the integration
|
|
branches to make it usable by other developers for testing.
|
|
These changes are what the maintainer is not 100% committed to
|
|
(trivial typofixes etc. are often squashed directly into the
|
|
patches that need fixing, without being applied as a separate
|
|
"SQUASH???" commit), so that they can be removed easily as needed.
|
|
The expectation is that the original author will make corrections
|
|
in a reroll.</code></pre>
|
|
</div></div>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
By now, new topic branches are created and existing topic
|
|
branches are updated. The integration branches <em>next</em>, <em>jch</em>,
|
|
and <em>seen</em> need to be updated to contain them.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
If there are topics that have been merged to <em>master</em> and should
|
|
be merged to <em>maint</em>, merge them to <em>maint</em>, and update the
|
|
release notes to the next maintenance release.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Review the latest issue of "What’s cooking" again. Are topics
|
|
that have been sufficiently long in <em>next</em> ready to be merged to
|
|
<em>master</em>? Are topics we saw earlier and are in <em>seen</em> now got
|
|
positive reviews and are ready to be merged to <em>next</em>?
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
If there are topics that have been cooking in <em>next</em> long enough
|
|
and should be merged to <em>master</em>, merge them to <em>master</em>, and
|
|
update the release notes to the next feature release.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
If there were patches directly made on <em>maint</em>, merge <em>maint</em> to
|
|
<em>master</em>; make sure that the result is what you want.
|
|
</p>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git checkout master
|
|
$ git merge -m "Sync with 'maint'" --no-log maint
|
|
$ git log -p --first-parent ORIG_HEAD..
|
|
$ make test</code></pre>
|
|
</div></div>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Prepare to update the <em>jch</em> branch, which is used to represent
|
|
somewhere between <em>master</em> and <em>seen</em> and often is slightly ahead
|
|
of <em>next</em>, and the <em>seen</em> branch, which is used to hold the rest.
|
|
</p>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ Meta/Reintegrate master..jch >Meta/redo-jch.sh</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>The result is a script that lists topics to be merged in order to
|
|
rebuild the current 'jch'. Do the same for 'seen'.</code></pre>
|
|
</div></div>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Review the Meta/redo-jch.sh and Meta/redo-seen.sh scripts. The
|
|
former should have a line <em># match next</em>---the idea is that
|
|
merging the topics listed before the line on top of <em>master</em>
|
|
should result in a tree identical to that of <em>next</em>.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
As newly created topics are usually merged near the tip of
|
|
<em>seen</em>, add them to the end of the Meta/redo-seen.sh script.
|
|
Among the topics that were in <em>seen</em>, there may be ones that
|
|
are not quite ready for <em>next</em> but are getting there. Move
|
|
them from Meta/redo-seen.sh to the end of Meta/redo-jch.sh.
|
|
The expectation is that you’d use <em>jch</em> as your daily driver
|
|
as the first guinea pig, so you should choose carefully.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Now we are ready to start rebuilding <em>jch</em> and merging topics to
|
|
<em>next</em>. For each branch whose tip is not merged to <em>next</em>, one
|
|
of three things can happen:
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
The commits are all next-worthy; merge the topic to next;
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
The new parts are of mixed quality, but earlier ones are
|
|
next-worthy; merge the early parts to next;
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Nothing is next-worthy; do not do anything.
|
|
</p>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>This step is aided with Meta/redo-jch.sh script created earlier.
|
|
If a topic that was already in 'next' gained a patch, the script
|
|
would list it as "ai/topic~1". To include the new patch to the
|
|
updated 'next', drop the "~1" part; to keep it excluded, do not
|
|
touch the line.</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>If a topic that was not in 'next' should be merged to 'next', add
|
|
it before the '### match next' line. Then:</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git checkout --detach master
|
|
$ sh Meta/redo-jch.sh -c1</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>to rebuild the 'jch' branch from scratch. "-c1" tells the script
|
|
to stop merging at the first line that begins with '###'
|
|
(i.e. the "### match next" line you added earlier).</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>At this point, build-test the result. It may reveal semantic
|
|
conflicts (e.g. a topic renamed a variable, another added a new
|
|
reference to the variable under its old name), in which case
|
|
prepare an appropriate merge-fix first (see appendix), and
|
|
rebuild the 'jch' branch from scratch, starting at the tip of
|
|
'master', this time without using "-c1" to merge all topics.</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>Then do the same to 'next'.</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git checkout next
|
|
$ sh Meta/redo-jch.sh -c1 -e</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>The "-e" option allows the merge message that comes from the
|
|
history of the topic and the comments in the "What's cooking" to
|
|
be edited. The resulting tree should match 'jch^{/^### match next'}'
|
|
as the same set of topics are merged on 'master'; otherwise there
|
|
is a mismerge. Investigate why and do not proceed until the mismerge
|
|
is found and rectified.</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>If 'master' was updated before you started redoing 'next', then</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git diff 'jch^{/^### match next}' next</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>would show differences that went into 'master' (which 'jch' has,
|
|
but 'next' does not yet---often it is updates to the release
|
|
notes). Merge 'master' back to 'next' if that is the case.</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git merge -m "Sync with 'master'" --no-log master</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>When all is well, clean up the redo-jch.sh script with</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ sh Meta/redo-jch.sh -u</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>This removes topics listed in the script that have already been
|
|
merged to 'master'. This may lose '### match next' marker;
|
|
add it again to the appropriate place when it happens.</code></pre>
|
|
</div></div>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Rebuild <em>seen</em> on top of <em>jch</em>.
|
|
</p>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git checkout -B seen jch
|
|
$ sh Meta/redo-seen.sh</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>When all is well, clean up the redo-seen.sh script with</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ sh Meta/redo-seen.sh -u</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>Double check by running</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git branch --no-merged seen '??/*'</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>to see there is no unexpected leftover topics.</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>At this point, build-test the result for semantic conflicts, and
|
|
if there are, prepare an appropriate merge-fix first (see
|
|
appendix), and rebuild the 'seen' branch from scratch, starting at
|
|
the tip of 'jch'.</code></pre>
|
|
</div></div>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Update "What’s cooking" message to review the updates to
|
|
existing topics, newly added topics and graduated topics.
|
|
</p>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>This step is helped with Meta/cook script.</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ Meta/cook</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>This script inspects the history between master..seen, finds tips
|
|
of topic branches, compares what it found with the current
|
|
contents in Meta/whats-cooking.txt, and updates that file.
|
|
Topics not listed in the file but are found in master..seen are
|
|
added to the "New topics" section, topics listed in the file that
|
|
are no longer found in master..seen are moved to the "Graduated to
|
|
master" section, and topics whose commits changed their states
|
|
(e.g. used to be only in 'seen', now merged to 'next') are updated
|
|
with change markers "<<" and ">>".</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>Look for lines enclosed in "<<" and ">>"; they hold contents from
|
|
old file that are replaced by this integration round. After
|
|
verifying them, remove the old part. Review the description for
|
|
each topic and update its doneness and plan as needed. To review
|
|
the updated plan, run</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ Meta/cook -w</code></pre>
|
|
</div></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>which will pick up comments given to the topics, such as "Will
|
|
merge to 'next'", etc. (see Meta/cook script to learn what kind
|
|
of phrases are supported).</code></pre>
|
|
</div></div>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Compile, test and install all four (five) integration branches;
|
|
Meta/Dothem script may aid this step.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Format documentation if the <em>master</em> branch was updated;
|
|
Meta/dodoc.sh script may aid this step.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Push the integration branches out to public places; Meta/pushall
|
|
script may aid this step.
|
|
</p>
|
|
</li>
|
|
</ul></div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_observations">Observations</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph"><p>Some observations to be made.</p></div>
|
|
<div class="ulist"><ul>
|
|
<li>
|
|
<p>
|
|
Each topic is tested individually, and also together with other
|
|
topics cooking first in <em>seen</em>, then in <em>jch</em> and then in <em>next</em>.
|
|
Until it matures, no part of it is merged to <em>master</em>.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
A topic already in <em>next</em> can get fixes while still in
|
|
<em>next</em>. Such a topic will have many merges to <em>next</em> (in
|
|
other words, "git log --first-parent next" will show many
|
|
"Merge branch <em>ai/topic</em> to next" for the same topic.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
An unobvious fix for <em>maint</em> is cooked in <em>next</em> and then
|
|
merged to <em>master</em> to make extra sure it is Ok and then
|
|
merged to <em>maint</em>.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Even when <em>next</em> becomes empty (in other words, all topics
|
|
prove stable and are merged to <em>master</em> and "git diff master
|
|
next" shows empty), it has tons of merge commits that will
|
|
never be in <em>master</em>.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
In principle, "git log --first-parent master..next" should
|
|
show nothing but merges (in practice, there are fixup commits
|
|
and reverts that are not merges).
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Commits near the tip of a topic branch that are not in <em>next</em>
|
|
are fair game to be discarded, replaced or rewritten.
|
|
Commits already merged to <em>next</em> will not be.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Being in the <em>next</em> branch is not a guarantee for a topic to
|
|
be included in the next feature release. Being in the
|
|
<em>master</em> branch typically is.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
<p>
|
|
Due to the nature of "SQUASH???" fix-ups, if the original author
|
|
agrees with the suggested changes, it is OK to squash them to
|
|
appropriate patches in the next round (when the suggested change
|
|
is small enough, the author should not even bother with
|
|
"Helped-by"). It is also OK to drop them from the next round
|
|
when the original author does not agree with the suggestion, but
|
|
the author is expected to say why somewhere in the discussion.
|
|
</p>
|
|
</li>
|
|
</ul></div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="_appendix">Appendix</h2>
|
|
<div class="sectionbody">
|
|
<div class="sect2">
|
|
<h3 id="_preparing_a_merge_fix">Preparing a "merge-fix"</h3>
|
|
<div class="paragraph"><p>A merge of two topics may not textually conflict but still have
|
|
conflict at the semantic level. A classic example is for one topic
|
|
to rename a variable and all its uses, while another topic adds a
|
|
new use of the variable under its old name. When these two topics
|
|
are merged together, the reference to the variable newly added by
|
|
the latter topic will still use the old name in the result.</p></div>
|
|
<div class="paragraph"><p>The Meta/Reintegrate script that is used by redo-jch and redo-seen
|
|
scripts implements a crude but usable way to work around this issue.
|
|
When the script merges branch $X, it checks if "refs/merge-fix/$X"
|
|
exists, and if so, the effect of it is squashed into the result of
|
|
the mechanical merge. In other words,</p></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ echo $X | Meta/Reintegrate</code></pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>is roughly equivalent to this sequence:</p></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git merge --rerere-autoupdate $X
|
|
$ git commit
|
|
$ git cherry-pick -n refs/merge-fix/$X
|
|
$ git commit --amend</code></pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>The goal of this "prepare a merge-fix" step is to come up with a
|
|
commit that can be squashed into a result of mechanical merge to
|
|
correct semantic conflicts.</p></div>
|
|
<div class="paragraph"><p>After finding that the result of merging branch "ai/topic" to an
|
|
integration branch had such a semantic conflict, say seen~4, check the
|
|
problematic merge out on a detached HEAD, edit the working tree to
|
|
fix the semantic conflict, and make a separate commit to record the
|
|
fix-up:</p></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git checkout seen~4
|
|
$ git show -s --pretty=%s ;# double check
|
|
Merge branch 'ai/topic' to seen
|
|
$ edit
|
|
$ git commit -m 'merge-fix/ai/topic' -a</code></pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>Then make a reference "refs/merge-fix/ai/topic" to point at this
|
|
result:</p></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git update-ref refs/merge-fix/ai/topic HEAD</code></pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>Then double check the result by asking Meta/Reintegrate to redo the
|
|
merge:</p></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ git checkout seen~5 ;# the parent of the problem merge
|
|
$ echo ai/topic | Meta/Reintegrate
|
|
$ git diff seen~4</code></pre>
|
|
</div></div>
|
|
<div class="paragraph"><p>This time, because you prepared refs/merge-fix/ai/topic, the
|
|
resulting merge should have been tweaked to include the fix for the
|
|
semantic conflict.</p></div>
|
|
<div class="paragraph"><p>Note that this assumes that the order in which conflicting branches
|
|
are merged does not change. If the reason why merging ai/topic
|
|
branch needs this merge-fix is because another branch merged earlier
|
|
to the integration branch changed the underlying assumption ai/topic
|
|
branch made (e.g. ai/topic branch added a site to refer to a
|
|
variable, while the other branch renamed that variable and adjusted
|
|
existing use sites), and if you changed redo-jch (or redo-seen) script
|
|
to merge ai/topic branch before the other branch, then the above
|
|
merge-fix should not be applied while merging ai/topic, but should
|
|
instead be applied while merging the other branch. You would need
|
|
to move the fix to apply to the other branch, perhaps like this:</p></div>
|
|
<div class="literalblock">
|
|
<div class="content">
|
|
<pre><code>$ mf=refs/merge-fix
|
|
$ git update-ref $mf/$the_other_branch $mf/ai/topic
|
|
$ git update-ref -d $mf/ai/topic</code></pre>
|
|
</div></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="footnotes"><hr /></div>
|
|
<div id="footer">
|
|
<div id="footer-text">
|
|
Last updated
|
|
2025-08-29 17:49:34 CEST
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|