<?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 8.6.10" /> | |
<title>gitcore-tutorial(7)</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 overriden 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"> | |
/*<![CDATA[*/ | |
var asciidoc = { // Namespace. | |
///////////////////////////////////////////////////////////////////// | |
// Table Of Contents generator | |
///////////////////////////////////////////////////////////////////// | |
/* Author: Mihai Bazon, September 2002 | |
* http://students.infoiasi.ro/~mishoo | |
* | |
* Table Of Content generator | |
* Version: 0.4 | |
* | |
* Feel free to use this script under the terms of the GNU General Public | |
* License, as long as you do not remove or alter this notice. | |
*/ | |
/* modified by Troy D. Hanson, September 2006. License: GPL */ | |
/* modified by Stuart Rackham, 2006, 2009. License: GPL */ | |
// toclevels = 1..4. | |
toc: function (toclevels) { | |
function getText(el) { | |
var text = ""; | |
for (var i = el.firstChild; i != null; i = i.nextSibling) { | |
if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants. | |
text += i.data; | |
else if (i.firstChild != null) | |
text += getText(i); | |
} | |
return text; | |
} | |
function TocEntry(el, text, toclevel) { | |
this.element = el; | |
this.text = text; | |
this.toclevel = toclevel; | |
} | |
function tocEntries(el, toclevels) { | |
var result = new Array; | |
var re = new RegExp('[hH]([1-'+(toclevels+1)+'])'); | |
// 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="manpage"> | |
<div id="header"> | |
<h1> | |
gitcore-tutorial(7) Manual Page | |
</h1> | |
<h2>NAME</h2> | |
<div class="sectionbody"> | |
<p>gitcore-tutorial - | |
A Git core tutorial for developers | |
</p> | |
</div> | |
</div> | |
<div id="content"> | |
<div class="sect1"> | |
<h2 id="_synopsis">SYNOPSIS</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>git *</p></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_description">DESCRIPTION</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>This tutorial explains how to use the "core" Git commands to set up and | |
work with a Git repository.</p></div> | |
<div class="paragraph"><p>If you just need to use Git as a revision control system you may prefer | |
to start with "A Tutorial Introduction to Git" (<a href="gittutorial.html">gittutorial(7)</a>) or | |
<a href="user-manual.html">the Git User Manual</a>.</p></div> | |
<div class="paragraph"><p>However, an understanding of these low-level tools can be helpful if | |
you want to understand Git’s internals.</p></div> | |
<div class="paragraph"><p>The core Git is often called "plumbing", with the prettier user | |
interfaces on top of it called "porcelain". You may not want to use the | |
plumbing directly very often, but it can be good to know what the | |
plumbing does when the porcelain isn’t flushing.</p></div> | |
<div class="paragraph"><p>Back when this document was originally written, many porcelain | |
commands were shell scripts. For simplicity, it still uses them as | |
examples to illustrate how plumbing is fit together to form the | |
porcelain commands. The source tree includes some of these scripts in | |
contrib/examples/ for reference. Although these are not implemented as | |
shell scripts anymore, the description of what the plumbing layer | |
commands do is still valid.</p></div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content">Deeper technical details are often marked as Notes, which you can | |
skip on your first reading.</td> | |
</tr></table> | |
</div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_creating_a_git_repository">Creating a Git repository</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>Creating a new Git repository couldn’t be easier: all Git repositories start | |
out empty, and the only thing you need to do is find yourself a | |
subdirectory that you want to use as a working tree - either an empty | |
one for a totally new project, or an existing working tree that you want | |
to import into Git.</p></div> | |
<div class="paragraph"><p>For our first example, we’re going to start a totally new repository from | |
scratch, with no pre-existing files, and we’ll call it <em>git-tutorial</em>. | |
To start up, create a subdirectory for it, change into that | |
subdirectory, and initialize the Git infrastructure with <em>git init</em>:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ mkdir git-tutorial | |
$ cd git-tutorial | |
$ git init</code></pre> | |
</div></div> | |
<div class="paragraph"><p>to which Git will reply</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>Initialized empty Git repository in .git/</code></pre> | |
</div></div> | |
<div class="paragraph"><p>which is just Git’s way of saying that you haven’t been doing anything | |
strange, and that it will have created a local <code>.git</code> directory setup for | |
your new project. You will now have a <code>.git</code> directory, and you can | |
inspect that with <em>ls</em>. For your new empty project, it should show you | |
three entries, among other things:</p></div> | |
<div class="ulist"><ul> | |
<li> | |
<p> | |
a file called <code>HEAD</code>, that has <code>ref: refs/heads/master</code> in it. | |
This is similar to a symbolic link and points at | |
<code>refs/heads/master</code> relative to the <code>HEAD</code> file. | |
</p> | |
<div class="paragraph"><p>Don’t worry about the fact that the file that the <code>HEAD</code> link points to | |
doesn’t even exist yet — you haven’t created the commit that will | |
start your <code>HEAD</code> development branch yet.</p></div> | |
</li> | |
<li> | |
<p> | |
a subdirectory called <code>objects</code>, which will contain all the | |
objects of your project. You should never have any real reason to | |
look at the objects directly, but you might want to know that these | |
objects are what contains all the real <em>data</em> in your repository. | |
</p> | |
</li> | |
<li> | |
<p> | |
a subdirectory called <code>refs</code>, which contains references to objects. | |
</p> | |
</li> | |
</ul></div> | |
<div class="paragraph"><p>In particular, the <code>refs</code> subdirectory will contain two other | |
subdirectories, named <code>heads</code> and <code>tags</code> respectively. They do | |
exactly what their names imply: they contain references to any number | |
of different <em>heads</em> of development (aka <em>branches</em>), and to any | |
<em>tags</em> that you have created to name specific versions in your | |
repository.</p></div> | |
<div class="paragraph"><p>One note: the special <code>master</code> head is the default branch, which is | |
why the <code>.git/HEAD</code> file was created points to it even if it | |
doesn’t yet exist. Basically, the <code>HEAD</code> link is supposed to always | |
point to the branch you are working on right now, and you always | |
start out expecting to work on the <code>master</code> branch.</p></div> | |
<div class="paragraph"><p>However, this is only a convention, and you can name your branches | |
anything you want, and don’t have to ever even <em>have</em> a <code>master</code> | |
branch. A number of the Git tools will assume that <code>.git/HEAD</code> is | |
valid, though.</p></div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content">An <em>object</em> is identified by its 160-bit SHA-1 hash, aka <em>object name</em>, | |
and a reference to an object is always the 40-byte hex | |
representation of that SHA-1 name. The files in the <code>refs</code> | |
subdirectory are expected to contain these hex references | |
(usually with a final <code>\n</code> at the end), and you should thus | |
expect to see a number of 41-byte files containing these | |
references in these <code>refs</code> subdirectories when you actually start | |
populating your tree.</td> | |
</tr></table> | |
</div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content">An advanced user may want to take a look at <a href="gitrepository-layout.html">gitrepository-layout(5)</a> | |
after finishing this tutorial.</td> | |
</tr></table> | |
</div> | |
<div class="paragraph"><p>You have now created your first Git repository. Of course, since it’s | |
empty, that’s not very useful, so let’s start populating it with data.</p></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_populating_a_git_repository">Populating a Git repository</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>We’ll keep this simple and stupid, so we’ll start off with populating a | |
few trivial files just to get a feel for it.</p></div> | |
<div class="paragraph"><p>Start off with just creating any random files that you want to maintain | |
in your Git repository. We’ll start off with a few bad examples, just to | |
get a feel for how this works:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ echo "Hello World" >hello | |
$ echo "Silly example" >example</code></pre> | |
</div></div> | |
<div class="paragraph"><p>you have now created two files in your working tree (aka <em>working directory</em>), | |
but to actually check in your hard work, you will have to go through two steps:</p></div> | |
<div class="ulist"><ul> | |
<li> | |
<p> | |
fill in the <em>index</em> file (aka <em>cache</em>) with the information about your | |
working tree state. | |
</p> | |
</li> | |
<li> | |
<p> | |
commit that index file as an object. | |
</p> | |
</li> | |
</ul></div> | |
<div class="paragraph"><p>The first step is trivial: when you want to tell Git about any changes | |
to your working tree, you use the <em>git update-index</em> program. That | |
program normally just takes a list of filenames you want to update, but | |
to avoid trivial mistakes, it refuses to add new entries to the index | |
(or remove existing ones) unless you explicitly tell it that you’re | |
adding a new entry with the <code>--add</code> flag (or removing an entry with the | |
<code>--remove</code>) flag.</p></div> | |
<div class="paragraph"><p>So to populate the index with the two files you just created, you can do</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git update-index --add hello example</code></pre> | |
</div></div> | |
<div class="paragraph"><p>and you have now told Git to track those two files.</p></div> | |
<div class="paragraph"><p>In fact, as you did that, if you now look into your object directory, | |
you’ll notice that Git will have added two new objects to the object | |
database. If you did exactly the steps above, you should now be able to do</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ ls .git/objects/??/*</code></pre> | |
</div></div> | |
<div class="paragraph"><p>and see two files:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>.git/objects/55/7db03de997c86a4a028e1ebd3a1ceb225be238 | |
.git/objects/f2/4c74a2e500f5ee1332c86b94199f52b1d1d962</code></pre> | |
</div></div> | |
<div class="paragraph"><p>which correspond with the objects with names of <code>557db...</code> and | |
<code>f24c7...</code> respectively.</p></div> | |
<div class="paragraph"><p>If you want to, you can use <em>git cat-file</em> to look at those objects, but | |
you’ll have to use the object name, not the filename of the object:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git cat-file -t 557db03de997c86a4a028e1ebd3a1ceb225be238</code></pre> | |
</div></div> | |
<div class="paragraph"><p>where the <code>-t</code> tells <em>git cat-file</em> to tell you what the "type" of the | |
object is. Git will tell you that you have a "blob" object (i.e., just a | |
regular file), and you can see the contents with</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git cat-file blob 557db03</code></pre> | |
</div></div> | |
<div class="paragraph"><p>which will print out "Hello World". The object <code>557db03</code> is nothing | |
more than the contents of your file <code>hello</code>.</p></div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content">Don’t confuse that object with the file <code>hello</code> itself. The | |
object is literally just those specific <strong>contents</strong> of the file, and | |
however much you later change the contents in file <code>hello</code>, the object | |
we just looked at will never change. Objects are immutable.</td> | |
</tr></table> | |
</div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content">The second example demonstrates that you can | |
abbreviate the object name to only the first several | |
hexadecimal digits in most places.</td> | |
</tr></table> | |
</div> | |
<div class="paragraph"><p>Anyway, as we mentioned previously, you normally never actually take a | |
look at the objects themselves, and typing long 40-character hex | |
names is not something you’d normally want to do. The above digression | |
was just to show that <em>git update-index</em> did something magical, and | |
actually saved away the contents of your files into the Git object | |
database.</p></div> | |
<div class="paragraph"><p>Updating the index did something else too: it created a <code>.git/index</code> | |
file. This is the index that describes your current working tree, and | |
something you should be very aware of. Again, you normally never worry | |
about the index file itself, but you should be aware of the fact that | |
you have not actually really "checked in" your files into Git so far, | |
you’ve only <strong>told</strong> Git about them.</p></div> | |
<div class="paragraph"><p>However, since Git knows about them, you can now start using some of the | |
most basic Git commands to manipulate the files or look at their status.</p></div> | |
<div class="paragraph"><p>In particular, let’s not even check in the two files into Git yet, we’ll | |
start off by adding another line to <code>hello</code> first:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ echo "It's a new day for git" >>hello</code></pre> | |
</div></div> | |
<div class="paragraph"><p>and you can now, since you told Git about the previous state of <code>hello</code>, ask | |
Git what has changed in the tree compared to your old index, using the | |
<em>git diff-files</em> command:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git diff-files</code></pre> | |
</div></div> | |
<div class="paragraph"><p>Oops. That wasn’t very readable. It just spit out its own internal | |
version of a <em>diff</em>, but that internal version really just tells you | |
that it has noticed that "hello" has been modified, and that the old object | |
contents it had have been replaced with something else.</p></div> | |
<div class="paragraph"><p>To make it readable, we can tell <em>git diff-files</em> to output the | |
differences as a patch, using the <code>-p</code> flag:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git diff-files -p | |
diff --git a/hello b/hello | |
index 557db03..263414f 100644 | |
--- a/hello | |
+++ b/hello | |
@@ -1 +1,2 @@ | |
Hello World | |
+It's a new day for git</code></pre> | |
</div></div> | |
<div class="paragraph"><p>i.e. the diff of the change we caused by adding another line to <code>hello</code>.</p></div> | |
<div class="paragraph"><p>In other words, <em>git diff-files</em> always shows us the difference between | |
what is recorded in the index, and what is currently in the working | |
tree. That’s very useful.</p></div> | |
<div class="paragraph"><p>A common shorthand for <code>git diff-files -p</code> is to just write <code>git | |
diff</code>, which will do the same thing.</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git diff | |
diff --git a/hello b/hello | |
index 557db03..263414f 100644 | |
--- a/hello | |
+++ b/hello | |
@@ -1 +1,2 @@ | |
Hello World | |
+It's a new day for git</code></pre> | |
</div></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_committing_git_state">Committing Git state</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>Now, we want to go to the next stage in Git, which is to take the files | |
that Git knows about in the index, and commit them as a real tree. We do | |
that in two phases: creating a <em>tree</em> object, and committing that <em>tree</em> | |
object as a <em>commit</em> object together with an explanation of what the | |
tree was all about, along with information of how we came to that state.</p></div> | |
<div class="paragraph"><p>Creating a tree object is trivial, and is done with <em>git write-tree</em>. | |
There are no options or other input: <code>git write-tree</code> will take the | |
current index state, and write an object that describes that whole | |
index. In other words, we’re now tying together all the different | |
filenames with their contents (and their permissions), and we’re | |
creating the equivalent of a Git "directory" object:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git write-tree</code></pre> | |
</div></div> | |
<div class="paragraph"><p>and this will just output the name of the resulting tree, in this case | |
(if you have done exactly as I’ve described) it should be</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>8988da15d077d4829fc51d8544c097def6644dbb</code></pre> | |
</div></div> | |
<div class="paragraph"><p>which is another incomprehensible object name. Again, if you want to, | |
you can use <code>git cat-file -t 8988d...</code> to see that this time the object | |
is not a "blob" object, but a "tree" object (you can also use | |
<code>git cat-file</code> to actually output the raw object contents, but you’ll see | |
mainly a binary mess, so that’s less interesting).</p></div> | |
<div class="paragraph"><p>However — normally you’d never use <em>git write-tree</em> on its own, because | |
normally you always commit a tree into a commit object using the | |
<em>git commit-tree</em> command. In fact, it’s easier to not actually use | |
<em>git write-tree</em> on its own at all, but to just pass its result in as an | |
argument to <em>git commit-tree</em>.</p></div> | |
<div class="paragraph"><p><em>git commit-tree</em> normally takes several arguments — it wants to know | |
what the <em>parent</em> of a commit was, but since this is the first commit | |
ever in this new repository, and it has no parents, we only need to pass in | |
the object name of the tree. However, <em>git commit-tree</em> also wants to get a | |
commit message on its standard input, and it will write out the resulting | |
object name for the commit to its standard output.</p></div> | |
<div class="paragraph"><p>And this is where we create the <code>.git/refs/heads/master</code> file | |
which is pointed at by <code>HEAD</code>. This file is supposed to contain | |
the reference to the top-of-tree of the master branch, and since | |
that’s exactly what <em>git commit-tree</em> spits out, we can do this | |
all with a sequence of simple shell commands:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ tree=$(git write-tree) | |
$ commit=$(echo 'Initial commit' | git commit-tree $tree) | |
$ git update-ref HEAD $commit</code></pre> | |
</div></div> | |
<div class="paragraph"><p>In this case this creates a totally new commit that is not related to | |
anything else. Normally you do this only <strong>once</strong> for a project ever, and | |
all later commits will be parented on top of an earlier commit.</p></div> | |
<div class="paragraph"><p>Again, normally you’d never actually do this by hand. There is a | |
helpful script called <code>git commit</code> that will do all of this for you. So | |
you could have just written <code>git commit</code> | |
instead, and it would have done the above magic scripting for you.</p></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_making_a_change">Making a change</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>Remember how we did the <em>git update-index</em> on file <code>hello</code> and then we | |
changed <code>hello</code> afterward, and could compare the new state of <code>hello</code> with the | |
state we saved in the index file?</p></div> | |
<div class="paragraph"><p>Further, remember how I said that <em>git write-tree</em> writes the contents | |
of the <strong>index</strong> file to the tree, and thus what we just committed was in | |
fact the <strong>original</strong> contents of the file <code>hello</code>, not the new ones. We did | |
that on purpose, to show the difference between the index state, and the | |
state in the working tree, and how they don’t have to match, even | |
when we commit things.</p></div> | |
<div class="paragraph"><p>As before, if we do <code>git diff-files -p</code> in our git-tutorial project, | |
we’ll still see the same difference we saw last time: the index file | |
hasn’t changed by the act of committing anything. However, now that we | |
have committed something, we can also learn to use a new command: | |
<em>git diff-index</em>.</p></div> | |
<div class="paragraph"><p>Unlike <em>git diff-files</em>, which showed the difference between the index | |
file and the working tree, <em>git diff-index</em> shows the differences | |
between a committed <strong>tree</strong> and either the index file or the working | |
tree. In other words, <em>git diff-index</em> wants a tree to be diffed | |
against, and before we did the commit, we couldn’t do that, because we | |
didn’t have anything to diff against.</p></div> | |
<div class="paragraph"><p>But now we can do</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git diff-index -p HEAD</code></pre> | |
</div></div> | |
<div class="paragraph"><p>(where <code>-p</code> has the same meaning as it did in <em>git diff-files</em>), and it | |
will show us the same difference, but for a totally different reason. | |
Now we’re comparing the working tree not against the index file, | |
but against the tree we just wrote. It just so happens that those two | |
are obviously the same, so we get the same result.</p></div> | |
<div class="paragraph"><p>Again, because this is a common operation, you can also just shorthand | |
it with</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git diff HEAD</code></pre> | |
</div></div> | |
<div class="paragraph"><p>which ends up doing the above for you.</p></div> | |
<div class="paragraph"><p>In other words, <em>git diff-index</em> normally compares a tree against the | |
working tree, but when given the <code>--cached</code> flag, it is told to | |
instead compare against just the index cache contents, and ignore the | |
current working tree state entirely. Since we just wrote the index | |
file to HEAD, doing <code>git diff-index --cached -p HEAD</code> should thus return | |
an empty set of differences, and that’s exactly what it does.</p></div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content"> | |
<div class="paragraph"><p><em>git diff-index</em> really always uses the index for its | |
comparisons, and saying that it compares a tree against the working | |
tree is thus not strictly accurate. In particular, the list of | |
files to compare (the "meta-data") <strong>always</strong> comes from the index file, | |
regardless of whether the <code>--cached</code> flag is used or not. The <code>--cached</code> | |
flag really only determines whether the file <strong>contents</strong> to be compared | |
come from the working tree or not.</p></div> | |
<div class="paragraph"><p>This is not hard to understand, as soon as you realize that Git simply | |
never knows (or cares) about files that it is not told about | |
explicitly. Git will never go <strong>looking</strong> for files to compare, it | |
expects you to tell it what the files are, and that’s what the index | |
is there for.</p></div> | |
</td> | |
</tr></table> | |
</div> | |
<div class="paragraph"><p>However, our next step is to commit the <strong>change</strong> we did, and again, to | |
understand what’s going on, keep in mind the difference between "working | |
tree contents", "index file" and "committed tree". We have changes | |
in the working tree that we want to commit, and we always have to | |
work through the index file, so the first thing we need to do is to | |
update the index cache:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git update-index hello</code></pre> | |
</div></div> | |
<div class="paragraph"><p>(note how we didn’t need the <code>--add</code> flag this time, since Git knew | |
about the file already).</p></div> | |
<div class="paragraph"><p>Note what happens to the different <em>git diff-*</em> versions here. | |
After we’ve updated <code>hello</code> in the index, <code>git diff-files -p</code> now shows no | |
differences, but <code>git diff-index -p HEAD</code> still <strong>does</strong> show that the | |
current state is different from the state we committed. In fact, now | |
<em>git diff-index</em> shows the same difference whether we use the <code>--cached</code> | |
flag or not, since now the index is coherent with the working tree.</p></div> | |
<div class="paragraph"><p>Now, since we’ve updated <code>hello</code> in the index, we can commit the new | |
version. We could do it by writing the tree by hand again, and | |
committing the tree (this time we’d have to use the <code>-p HEAD</code> flag to | |
tell commit that the HEAD was the <strong>parent</strong> of the new commit, and that | |
this wasn’t an initial commit any more), but you’ve done that once | |
already, so let’s just use the helpful script this time:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git commit</code></pre> | |
</div></div> | |
<div class="paragraph"><p>which starts an editor for you to write the commit message and tells you | |
a bit about what you have done.</p></div> | |
<div class="paragraph"><p>Write whatever message you want, and all the lines that start with <em>#</em> | |
will be pruned out, and the rest will be used as the commit message for | |
the change. If you decide you don’t want to commit anything after all at | |
this point (you can continue to edit things and update the index), you | |
can just leave an empty message. Otherwise <code>git commit</code> will commit | |
the change for you.</p></div> | |
<div class="paragraph"><p>You’ve now made your first real Git commit. And if you’re interested in | |
looking at what <code>git commit</code> really does, feel free to investigate: | |
it’s a few very simple shell scripts to generate the helpful (?) commit | |
message headers, and a few one-liners that actually do the | |
commit itself (<em>git commit</em>).</p></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_inspecting_changes">Inspecting Changes</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>While creating changes is useful, it’s even more useful if you can tell | |
later what changed. The most useful command for this is another of the | |
<em>diff</em> family, namely <em>git diff-tree</em>.</p></div> | |
<div class="paragraph"><p><em>git diff-tree</em> can be given two arbitrary trees, and it will tell you the | |
differences between them. Perhaps even more commonly, though, you can | |
give it just a single commit object, and it will figure out the parent | |
of that commit itself, and show the difference directly. Thus, to get | |
the same diff that we’ve already seen several times, we can now do</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git diff-tree -p HEAD</code></pre> | |
</div></div> | |
<div class="paragraph"><p>(again, <code>-p</code> means to show the difference as a human-readable patch), | |
and it will show what the last commit (in <code>HEAD</code>) actually changed.</p></div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content"> | |
<div class="paragraph"><p>Here is an ASCII art by Jon Loeliger that illustrates how | |
various <em>diff-*</em> commands compare things.</p></div> | |
<div class="literalblock"> | |
<div class="content"> | |
<pre><code> diff-tree | |
+----+ | |
| | | |
| | | |
V V | |
+-----------+ | |
| Object DB | | |
| Backing | | |
| Store | | |
+-----------+ | |
^ ^ | |
| | | |
| | diff-index --cached | |
| | | |
diff-index | V | |
| +-----------+ | |
| | Index | | |
| | "cache" | | |
| +-----------+ | |
| ^ | |
| | | |
| | diff-files | |
| | | |
V V | |
+-----------+ | |
| Working | | |
| Directory | | |
+-----------+</code></pre> | |
</div></div> | |
</td> | |
</tr></table> | |
</div> | |
<div class="paragraph"><p>More interestingly, you can also give <em>git diff-tree</em> the <code>--pretty</code> flag, | |
which tells it to also show the commit message and author and date of the | |
commit, and you can tell it to show a whole series of diffs. | |
Alternatively, you can tell it to be "silent", and not show the diffs at | |
all, but just show the actual commit message.</p></div> | |
<div class="paragraph"><p>In fact, together with the <em>git rev-list</em> program (which generates a | |
list of revisions), <em>git diff-tree</em> ends up being a veritable fount of | |
changes. You can emulate <code>git log</code>, <code>git log -p</code>, etc. with a trivial | |
script that pipes the output of <code>git rev-list</code> to <code>git diff-tree --stdin</code>, | |
which was exactly how early versions of <code>git log</code> were implemented.</p></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_tagging_a_version">Tagging a version</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>In Git, there are two kinds of tags, a "light" one, and an "annotated tag".</p></div> | |
<div class="paragraph"><p>A "light" tag is technically nothing more than a branch, except we put | |
it in the <code>.git/refs/tags/</code> subdirectory instead of calling it a <code>head</code>. | |
So the simplest form of tag involves nothing more than</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git tag my-first-tag</code></pre> | |
</div></div> | |
<div class="paragraph"><p>which just writes the current <code>HEAD</code> into the <code>.git/refs/tags/my-first-tag</code> | |
file, after which point you can then use this symbolic name for that | |
particular state. You can, for example, do</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git diff my-first-tag</code></pre> | |
</div></div> | |
<div class="paragraph"><p>to diff your current state against that tag which at this point will | |
obviously be an empty diff, but if you continue to develop and commit | |
stuff, you can use your tag as an "anchor-point" to see what has changed | |
since you tagged it.</p></div> | |
<div class="paragraph"><p>An "annotated tag" is actually a real Git object, and contains not only a | |
pointer to the state you want to tag, but also a small tag name and | |
message, along with optionally a PGP signature that says that yes, | |
you really did | |
that tag. You create these annotated tags with either the <code>-a</code> or | |
<code>-s</code> flag to <em>git tag</em>:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git tag -s <tagname></code></pre> | |
</div></div> | |
<div class="paragraph"><p>which will sign the current <code>HEAD</code> (but you can also give it another | |
argument that specifies the thing to tag, e.g., you could have tagged the | |
current <code>mybranch</code> point by using <code>git tag <tagname> mybranch</code>).</p></div> | |
<div class="paragraph"><p>You normally only do signed tags for major releases or things | |
like that, while the light-weight tags are useful for any marking you | |
want to do — any time you decide that you want to remember a certain | |
point, just create a private tag for it, and you have a nice symbolic | |
name for the state at that point.</p></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_copying_repositories">Copying repositories</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>Git repositories are normally totally self-sufficient and relocatable. | |
Unlike CVS, for example, there is no separate notion of | |
"repository" and "working tree". A Git repository normally <strong>is</strong> the | |
working tree, with the local Git information hidden in the <code>.git</code> | |
subdirectory. There is nothing else. What you see is what you got.</p></div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content">You can tell Git to split the Git internal information from | |
the directory that it tracks, but we’ll ignore that for now: it’s not | |
how normal projects work, and it’s really only meant for special uses. | |
So the mental model of "the Git information is always tied directly to | |
the working tree that it describes" may not be technically 100% | |
accurate, but it’s a good model for all normal use.</td> | |
</tr></table> | |
</div> | |
<div class="paragraph"><p>This has two implications:</p></div> | |
<div class="ulist"><ul> | |
<li> | |
<p> | |
if you grow bored with the tutorial repository you created (or you’ve | |
made a mistake and want to start all over), you can just do simple | |
</p> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ rm -rf git-tutorial</code></pre> | |
</div></div> | |
<div class="paragraph"><p>and it will be gone. There’s no external repository, and there’s no | |
history outside the project you created.</p></div> | |
</li> | |
<li> | |
<p> | |
if you want to move or duplicate a Git repository, you can do so. There | |
is <em>git clone</em> command, but if all you want to do is just to | |
create a copy of your repository (with all the full history that | |
went along with it), you can do so with a regular | |
<code>cp -a git-tutorial new-git-tutorial</code>. | |
</p> | |
<div class="paragraph"><p>Note that when you’ve moved or copied a Git repository, your Git index | |
file (which caches various information, notably some of the "stat" | |
information for the files involved) will likely need to be refreshed. | |
So after you do a <code>cp -a</code> to create a new copy, you’ll want to do</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git update-index --refresh</code></pre> | |
</div></div> | |
<div class="paragraph"><p>in the new repository to make sure that the index file is up to date.</p></div> | |
</li> | |
</ul></div> | |
<div class="paragraph"><p>Note that the second point is true even across machines. You can | |
duplicate a remote Git repository with <strong>any</strong> regular copy mechanism, be it | |
<em>scp</em>, <em>rsync</em> or <em>wget</em>.</p></div> | |
<div class="paragraph"><p>When copying a remote repository, you’ll want to at a minimum update the | |
index cache when you do this, and especially with other peoples' | |
repositories you often want to make sure that the index cache is in some | |
known state (you don’t know <strong>what</strong> they’ve done and not yet checked in), | |
so usually you’ll precede the <em>git update-index</em> with a</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git read-tree --reset HEAD | |
$ git update-index --refresh</code></pre> | |
</div></div> | |
<div class="paragraph"><p>which will force a total index re-build from the tree pointed to by <code>HEAD</code>. | |
It resets the index contents to <code>HEAD</code>, and then the <em>git update-index</em> | |
makes sure to match up all index entries with the checked-out files. | |
If the original repository had uncommitted changes in its | |
working tree, <code>git update-index --refresh</code> notices them and | |
tells you they need to be updated.</p></div> | |
<div class="paragraph"><p>The above can also be written as simply</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git reset</code></pre> | |
</div></div> | |
<div class="paragraph"><p>and in fact a lot of the common Git command combinations can be scripted | |
with the <code>git xyz</code> interfaces. You can learn things by just looking | |
at what the various git scripts do. For example, <code>git reset</code> used to be | |
the above two lines implemented in <em>git reset</em>, but some things like | |
<em>git status</em> and <em>git commit</em> are slightly more complex scripts around | |
the basic Git commands.</p></div> | |
<div class="paragraph"><p>Many (most?) public remote repositories will not contain any of | |
the checked out files or even an index file, and will <strong>only</strong> contain the | |
actual core Git files. Such a repository usually doesn’t even have the | |
<code>.git</code> subdirectory, but has all the Git files directly in the | |
repository.</p></div> | |
<div class="paragraph"><p>To create your own local live copy of such a "raw" Git repository, you’d | |
first create your own subdirectory for the project, and then copy the | |
raw repository contents into the <code>.git</code> directory. For example, to | |
create your own copy of the Git repository, you’d do the following</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ mkdir my-git | |
$ cd my-git | |
$ rsync -rL rsync://rsync.kernel.org/pub/scm/git/git.git/ .git</code></pre> | |
</div></div> | |
<div class="paragraph"><p>followed by</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git read-tree HEAD</code></pre> | |
</div></div> | |
<div class="paragraph"><p>to populate the index. However, now you have populated the index, and | |
you have all the Git internal files, but you will notice that you don’t | |
actually have any of the working tree files to work on. To get | |
those, you’d check them out with</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git checkout-index -u -a</code></pre> | |
</div></div> | |
<div class="paragraph"><p>where the <code>-u</code> flag means that you want the checkout to keep the index | |
up to date (so that you don’t have to refresh it afterward), and the | |
<code>-a</code> flag means "check out all files" (if you have a stale copy or an | |
older version of a checked out tree you may also need to add the <code>-f</code> | |
flag first, to tell <em>git checkout-index</em> to <strong>force</strong> overwriting of any old | |
files).</p></div> | |
<div class="paragraph"><p>Again, this can all be simplified with</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git clone git://git.kernel.org/pub/scm/git/git.git/ my-git | |
$ cd my-git | |
$ git checkout</code></pre> | |
</div></div> | |
<div class="paragraph"><p>which will end up doing all of the above for you.</p></div> | |
<div class="paragraph"><p>You have now successfully copied somebody else’s (mine) remote | |
repository, and checked it out.</p></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_creating_a_new_branch">Creating a new branch</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>Branches in Git are really nothing more than pointers into the Git | |
object database from within the <code>.git/refs/</code> subdirectory, and as we | |
already discussed, the <code>HEAD</code> branch is nothing but a symlink to one of | |
these object pointers.</p></div> | |
<div class="paragraph"><p>You can at any time create a new branch by just picking an arbitrary | |
point in the project history, and just writing the SHA-1 name of that | |
object into a file under <code>.git/refs/heads/</code>. You can use any filename you | |
want (and indeed, subdirectories), but the convention is that the | |
"normal" branch is called <code>master</code>. That’s just a convention, though, | |
and nothing enforces it.</p></div> | |
<div class="paragraph"><p>To show that as an example, let’s go back to the git-tutorial repository we | |
used earlier, and create a branch in it. You do that by simply just | |
saying that you want to check out a new branch:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git checkout -b mybranch</code></pre> | |
</div></div> | |
<div class="paragraph"><p>will create a new branch based at the current <code>HEAD</code> position, and switch | |
to it.</p></div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content"> | |
<div class="paragraph"><p>If you make the decision to start your new branch at some | |
other point in the history than the current <code>HEAD</code>, you can do so by | |
just telling <em>git checkout</em> what the base of the checkout would be. | |
In other words, if you have an earlier tag or branch, you’d just do</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git checkout -b mybranch earlier-commit</code></pre> | |
</div></div> | |
<div class="paragraph"><p>and it would create the new branch <code>mybranch</code> at the earlier commit, | |
and check out the state at that time.</p></div> | |
</td> | |
</tr></table> | |
</div> | |
<div class="paragraph"><p>You can always just jump back to your original <code>master</code> branch by doing</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git checkout master</code></pre> | |
</div></div> | |
<div class="paragraph"><p>(or any other branch-name, for that matter) and if you forget which | |
branch you happen to be on, a simple</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ cat .git/HEAD</code></pre> | |
</div></div> | |
<div class="paragraph"><p>will tell you where it’s pointing. To get the list of branches | |
you have, you can say</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git branch</code></pre> | |
</div></div> | |
<div class="paragraph"><p>which used to be nothing more than a simple script around <code>ls .git/refs/heads</code>. | |
There will be an asterisk in front of the branch you are currently on.</p></div> | |
<div class="paragraph"><p>Sometimes you may wish to create a new branch <em>without</em> actually | |
checking it out and switching to it. If so, just use the command</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git branch <branchname> [startingpoint]</code></pre> | |
</div></div> | |
<div class="paragraph"><p>which will simply <em>create</em> the branch, but will not do anything further. | |
You can then later — once you decide that you want to actually develop | |
on that branch — switch to that branch with a regular <em>git checkout</em> | |
with the branchname as the argument.</p></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_merging_two_branches">Merging two branches</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>One of the ideas of having a branch is that you do some (possibly | |
experimental) work in it, and eventually merge it back to the main | |
branch. So assuming you created the above <code>mybranch</code> that started out | |
being the same as the original <code>master</code> branch, let’s make sure we’re in | |
that branch, and do some work there.</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git checkout mybranch | |
$ echo "Work, work, work" >>hello | |
$ git commit -m "Some work." -i hello</code></pre> | |
</div></div> | |
<div class="paragraph"><p>Here, we just added another line to <code>hello</code>, and we used a shorthand for | |
doing both <code>git update-index hello</code> and <code>git commit</code> by just giving the | |
filename directly to <code>git commit</code>, with an <code>-i</code> flag (it tells | |
Git to <em>include</em> that file in addition to what you have done to | |
the index file so far when making the commit). The <code>-m</code> flag is to give the | |
commit log message from the command line.</p></div> | |
<div class="paragraph"><p>Now, to make it a bit more interesting, let’s assume that somebody else | |
does some work in the original branch, and simulate that by going back | |
to the master branch, and editing the same file differently there:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git checkout master</code></pre> | |
</div></div> | |
<div class="paragraph"><p>Here, take a moment to look at the contents of <code>hello</code>, and notice how they | |
don’t contain the work we just did in <code>mybranch</code> — because that work | |
hasn’t happened in the <code>master</code> branch at all. Then do</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ echo "Play, play, play" >>hello | |
$ echo "Lots of fun" >>example | |
$ git commit -m "Some fun." -i hello example</code></pre> | |
</div></div> | |
<div class="paragraph"><p>since the master branch is obviously in a much better mood.</p></div> | |
<div class="paragraph"><p>Now, you’ve got two branches, and you decide that you want to merge the | |
work done. Before we do that, let’s introduce a cool graphical tool that | |
helps you view what’s going on:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ gitk --all</code></pre> | |
</div></div> | |
<div class="paragraph"><p>will show you graphically both of your branches (that’s what the <code>--all</code> | |
means: normally it will just show you your current <code>HEAD</code>) and their | |
histories. You can also see exactly how they came to be from a common | |
source.</p></div> | |
<div class="paragraph"><p>Anyway, let’s exit <em>gitk</em> (<code>^Q</code> or the File menu), and decide that we want | |
to merge the work we did on the <code>mybranch</code> branch into the <code>master</code> | |
branch (which is currently our <code>HEAD</code> too). To do that, there’s a nice | |
script called <em>git merge</em>, which wants to know which branches you want | |
to resolve and what the merge is all about:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git merge -m "Merge work in mybranch" mybranch</code></pre> | |
</div></div> | |
<div class="paragraph"><p>where the first argument is going to be used as the commit message if | |
the merge can be resolved automatically.</p></div> | |
<div class="paragraph"><p>Now, in this case we’ve intentionally created a situation where the | |
merge will need to be fixed up by hand, though, so Git will do as much | |
of it as it can automatically (which in this case is just merge the <code>example</code> | |
file, which had no differences in the <code>mybranch</code> branch), and say:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code> Auto-merging hello | |
CONFLICT (content): Merge conflict in hello | |
Automatic merge failed; fix conflicts and then commit the result.</code></pre> | |
</div></div> | |
<div class="paragraph"><p>It tells you that it did an "Automatic merge", which | |
failed due to conflicts in <code>hello</code>.</p></div> | |
<div class="paragraph"><p>Not to worry. It left the (trivial) conflict in <code>hello</code> in the same form you | |
should already be well used to if you’ve ever used CVS, so let’s just | |
open <code>hello</code> in our editor (whatever that may be), and fix it up somehow. | |
I’d suggest just making it so that <code>hello</code> contains all four lines:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>Hello World | |
It's a new day for git | |
Play, play, play | |
Work, work, work</code></pre> | |
</div></div> | |
<div class="paragraph"><p>and once you’re happy with your manual merge, just do a</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git commit -i hello</code></pre> | |
</div></div> | |
<div class="paragraph"><p>which will very loudly warn you that you’re now committing a merge | |
(which is correct, so never mind), and you can write a small merge | |
message about your adventures in <em>git merge</em>-land.</p></div> | |
<div class="paragraph"><p>After you’re done, start up <code>gitk --all</code> to see graphically what the | |
history looks like. Notice that <code>mybranch</code> still exists, and you can | |
switch to it, and continue to work with it if you want to. The | |
<code>mybranch</code> branch will not contain the merge, but next time you merge it | |
from the <code>master</code> branch, Git will know how you merged it, so you’ll not | |
have to do <em>that</em> merge again.</p></div> | |
<div class="paragraph"><p>Another useful tool, especially if you do not always work in X-Window | |
environment, is <code>git show-branch</code>.</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git show-branch --topo-order --more=1 master mybranch | |
* [master] Merge work in mybranch | |
! [mybranch] Some work. | |
-- | |
- [master] Merge work in mybranch | |
*+ [mybranch] Some work. | |
* [master^] Some fun.</code></pre> | |
</div></div> | |
<div class="paragraph"><p>The first two lines indicate that it is showing the two branches | |
with the titles of their top-of-the-tree commits, you are currently on | |
<code>master</code> branch (notice the asterisk <code>*</code> character), and the first | |
column for the later output lines is used to show commits contained in the | |
<code>master</code> branch, and the second column for the <code>mybranch</code> | |
branch. Three commits are shown along with their titles. | |
All of them have non blank characters in the first column (<code>*</code> | |
shows an ordinary commit on the current branch, <code>-</code> is a merge commit), which | |
means they are now part of the <code>master</code> branch. Only the "Some | |
work" commit has the plus <code>+</code> character in the second column, | |
because <code>mybranch</code> has not been merged to incorporate these | |
commits from the master branch. The string inside brackets | |
before the commit log message is a short name you can use to | |
name the commit. In the above example, <em>master</em> and <em>mybranch</em> | |
are branch heads. <em>master^</em> is the first parent of <em>master</em> | |
branch head. Please see <a href="gitrevisions.html">gitrevisions(7)</a> if you want to | |
see more complex cases.</p></div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content">Without the <em>--more=1</em> option, <em>git show-branch</em> would not output the | |
<em>[master^]</em> commit, as <em>[mybranch]</em> commit is a common ancestor of | |
both <em>master</em> and <em>mybranch</em> tips. Please see <a href="git-show-branch.html">git-show-branch(1)</a> | |
for details.</td> | |
</tr></table> | |
</div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content">If there were more commits on the <em>master</em> branch after the merge, the | |
merge commit itself would not be shown by <em>git show-branch</em> by | |
default. You would need to provide <code>--sparse</code> option to make the | |
merge commit visible in this case.</td> | |
</tr></table> | |
</div> | |
<div class="paragraph"><p>Now, let’s pretend you are the one who did all the work in | |
<code>mybranch</code>, and the fruit of your hard work has finally been merged | |
to the <code>master</code> branch. Let’s go back to <code>mybranch</code>, and run | |
<em>git merge</em> to get the "upstream changes" back to your branch.</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git checkout mybranch | |
$ git merge -m "Merge upstream changes." master</code></pre> | |
</div></div> | |
<div class="paragraph"><p>This outputs something like this (the actual commit object names | |
would be different)</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>Updating from ae3a2da... to a80b4aa.... | |
Fast-forward (no commit created; -m option ignored) | |
example | 1 + | |
hello | 1 + | |
2 files changed, 2 insertions(+)</code></pre> | |
</div></div> | |
<div class="paragraph"><p>Because your branch did not contain anything more than what had | |
already been merged into the <code>master</code> branch, the merge operation did | |
not actually do a merge. Instead, it just updated the top of | |
the tree of your branch to that of the <code>master</code> branch. This is | |
often called <em>fast-forward</em> merge.</p></div> | |
<div class="paragraph"><p>You can run <code>gitk --all</code> again to see how the commit ancestry | |
looks like, or run <em>show-branch</em>, which tells you this.</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git show-branch master mybranch | |
! [master] Merge work in mybranch | |
* [mybranch] Merge work in mybranch | |
-- | |
-- [master] Merge work in mybranch</code></pre> | |
</div></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_merging_external_work">Merging external work</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>It’s usually much more common that you merge with somebody else than | |
merging with your own branches, so it’s worth pointing out that Git | |
makes that very easy too, and in fact, it’s not that different from | |
doing a <em>git merge</em>. In fact, a remote merge ends up being nothing | |
more than "fetch the work from a remote repository into a temporary tag" | |
followed by a <em>git merge</em>.</p></div> | |
<div class="paragraph"><p>Fetching from a remote repository is done by, unsurprisingly, | |
<em>git fetch</em>:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git fetch <remote-repository></code></pre> | |
</div></div> | |
<div class="paragraph"><p>One of the following transports can be used to name the | |
repository to download from:</p></div> | |
<div class="dlist"><dl> | |
<dt class="hdlist1"> | |
SSH | |
</dt> | |
<dd> | |
<p> | |
<code>remote.machine:/path/to/repo.git/</code> or | |
</p> | |
<div class="paragraph"><p><code>ssh://remote.machine/path/to/repo.git/</code></p></div> | |
<div class="paragraph"><p>This transport can be used for both uploading and downloading, | |
and requires you to have a log-in privilege over <code>ssh</code> to the | |
remote machine. It finds out the set of objects the other side | |
lacks by exchanging the head commits both ends have and | |
transfers (close to) minimum set of objects. It is by far the | |
most efficient way to exchange Git objects between repositories.</p></div> | |
</dd> | |
<dt class="hdlist1"> | |
Local directory | |
</dt> | |
<dd> | |
<p> | |
<code>/path/to/repo.git/</code> | |
</p> | |
<div class="paragraph"><p>This transport is the same as SSH transport but uses <em>sh</em> to run | |
both ends on the local machine instead of running other end on | |
the remote machine via <em>ssh</em>.</p></div> | |
</dd> | |
<dt class="hdlist1"> | |
Git Native | |
</dt> | |
<dd> | |
<p> | |
<code>git://remote.machine/path/to/repo.git/</code> | |
</p> | |
<div class="paragraph"><p>This transport was designed for anonymous downloading. Like SSH | |
transport, it finds out the set of objects the downstream side | |
lacks and transfers (close to) minimum set of objects.</p></div> | |
</dd> | |
<dt class="hdlist1"> | |
HTTP(S) | |
</dt> | |
<dd> | |
<p> | |
<code>http://remote.machine/path/to/repo.git/</code> | |
</p> | |
<div class="paragraph"><p>Downloader from http and https URL | |
first obtains the topmost commit object name from the remote site | |
by looking at the specified refname under <code>repo.git/refs/</code> directory, | |
and then tries to obtain the | |
commit object by downloading from <code>repo.git/objects/xx/xxx...</code> | |
using the object name of that commit object. Then it reads the | |
commit object to find out its parent commits and the associate | |
tree object; it repeats this process until it gets all the | |
necessary objects. Because of this behavior, they are | |
sometimes also called <em>commit walkers</em>.</p></div> | |
<div class="paragraph"><p>The <em>commit walkers</em> are sometimes also called <em>dumb | |
transports</em>, because they do not require any Git aware smart | |
server like Git Native transport does. Any stock HTTP server | |
that does not even support directory index would suffice. But | |
you must prepare your repository with <em>git update-server-info</em> | |
to help dumb transport downloaders.</p></div> | |
</dd> | |
</dl></div> | |
<div class="paragraph"><p>Once you fetch from the remote repository, you <code>merge</code> that | |
with your current branch.</p></div> | |
<div class="paragraph"><p>However — it’s such a common thing to <code>fetch</code> and then | |
immediately <code>merge</code>, that it’s called <code>git pull</code>, and you can | |
simply do</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git pull <remote-repository></code></pre> | |
</div></div> | |
<div class="paragraph"><p>and optionally give a branch-name for the remote end as a second | |
argument.</p></div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content">You could do without using any branches at all, by | |
keeping as many local repositories as you would like to have | |
branches, and merging between them with <em>git pull</em>, just like | |
you merge between branches. The advantage of this approach is | |
that it lets you keep a set of files for each <code>branch</code> checked | |
out and you may find it easier to switch back and forth if you | |
juggle multiple lines of development simultaneously. Of | |
course, you will pay the price of more disk usage to hold | |
multiple working trees, but disk space is cheap these days.</td> | |
</tr></table> | |
</div> | |
<div class="paragraph"><p>It is likely that you will be pulling from the same remote | |
repository from time to time. As a short hand, you can store | |
the remote repository URL in the local repository’s config file | |
like this:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git config remote.linus.url http://www.kernel.org/pub/scm/git/git.git/</code></pre> | |
</div></div> | |
<div class="paragraph"><p>and use the "linus" keyword with <em>git pull</em> instead of the full URL.</p></div> | |
<div class="paragraph"><p>Examples.</p></div> | |
<div class="olist arabic"><ol class="arabic"> | |
<li> | |
<p> | |
<code>git pull linus</code> | |
</p> | |
</li> | |
<li> | |
<p> | |
<code>git pull linus tag v0.99.1</code> | |
</p> | |
</li> | |
</ol></div> | |
<div class="paragraph"><p>the above are equivalent to:</p></div> | |
<div class="olist arabic"><ol class="arabic"> | |
<li> | |
<p> | |
<code>git pull http://www.kernel.org/pub/scm/git/git.git/ HEAD</code> | |
</p> | |
</li> | |
<li> | |
<p> | |
<code>git pull http://www.kernel.org/pub/scm/git/git.git/ tag v0.99.1</code> | |
</p> | |
</li> | |
</ol></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_how_does_the_merge_work">How does the merge work?</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>We said this tutorial shows what plumbing does to help you cope | |
with the porcelain that isn’t flushing, but we so far did not | |
talk about how the merge really works. If you are following | |
this tutorial the first time, I’d suggest to skip to "Publishing | |
your work" section and come back here later.</p></div> | |
<div class="paragraph"><p>OK, still with me? To give us an example to look at, let’s go | |
back to the earlier repository with "hello" and "example" file, | |
and bring ourselves back to the pre-merge state:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git show-branch --more=2 master mybranch | |
! [master] Merge work in mybranch | |
* [mybranch] Merge work in mybranch | |
-- | |
-- [master] Merge work in mybranch | |
+* [master^2] Some work. | |
+* [master^] Some fun.</code></pre> | |
</div></div> | |
<div class="paragraph"><p>Remember, before running <em>git merge</em>, our <code>master</code> head was at | |
"Some fun." commit, while our <code>mybranch</code> head was at "Some | |
work." commit.</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git checkout mybranch | |
$ git reset --hard master^2 | |
$ git checkout master | |
$ git reset --hard master^</code></pre> | |
</div></div> | |
<div class="paragraph"><p>After rewinding, the commit structure should look like this:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git show-branch | |
* [master] Some fun. | |
! [mybranch] Some work. | |
-- | |
* [master] Some fun. | |
+ [mybranch] Some work. | |
*+ [master^] Initial commit</code></pre> | |
</div></div> | |
<div class="paragraph"><p>Now we are ready to experiment with the merge by hand.</p></div> | |
<div class="paragraph"><p><code>git merge</code> command, when merging two branches, uses 3-way merge | |
algorithm. First, it finds the common ancestor between them. | |
The command it uses is <em>git merge-base</em>:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ mb=$(git merge-base HEAD mybranch)</code></pre> | |
</div></div> | |
<div class="paragraph"><p>The command writes the commit object name of the common ancestor | |
to the standard output, so we captured its output to a variable, | |
because we will be using it in the next step. By the way, the common | |
ancestor commit is the "Initial commit" commit in this case. You can | |
tell it by:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git name-rev --name-only --tags $mb | |
my-first-tag</code></pre> | |
</div></div> | |
<div class="paragraph"><p>After finding out a common ancestor commit, the second step is | |
this:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git read-tree -m -u $mb HEAD mybranch</code></pre> | |
</div></div> | |
<div class="paragraph"><p>This is the same <em>git read-tree</em> command we have already seen, | |
but it takes three trees, unlike previous examples. This reads | |
the contents of each tree into different <em>stage</em> in the index | |
file (the first tree goes to stage 1, the second to stage 2, | |
etc.). After reading three trees into three stages, the paths | |
that are the same in all three stages are <em>collapsed</em> into stage | |
0. Also paths that are the same in two of three stages are | |
collapsed into stage 0, taking the SHA-1 from either stage 2 or | |
stage 3, whichever is different from stage 1 (i.e. only one side | |
changed from the common ancestor).</p></div> | |
<div class="paragraph"><p>After <em>collapsing</em> operation, paths that are different in three | |
trees are left in non-zero stages. At this point, you can | |
inspect the index file with this command:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git ls-files --stage | |
100644 7f8b141b65fdcee47321e399a2598a235a032422 0 example | |
100644 557db03de997c86a4a028e1ebd3a1ceb225be238 1 hello | |
100644 ba42a2a96e3027f3333e13ede4ccf4498c3ae942 2 hello | |
100644 cc44c73eb783565da5831b4d820c962954019b69 3 hello</code></pre> | |
</div></div> | |
<div class="paragraph"><p>In our example of only two files, we did not have unchanged | |
files so only <em>example</em> resulted in collapsing. But in real-life | |
large projects, when only a small number of files change in one commit, | |
this <em>collapsing</em> tends to trivially merge most of the paths | |
fairly quickly, leaving only a handful of real changes in non-zero | |
stages.</p></div> | |
<div class="paragraph"><p>To look at only non-zero stages, use <code>--unmerged</code> flag:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git ls-files --unmerged | |
100644 557db03de997c86a4a028e1ebd3a1ceb225be238 1 hello | |
100644 ba42a2a96e3027f3333e13ede4ccf4498c3ae942 2 hello | |
100644 cc44c73eb783565da5831b4d820c962954019b69 3 hello</code></pre> | |
</div></div> | |
<div class="paragraph"><p>The next step of merging is to merge these three versions of the | |
file, using 3-way merge. This is done by giving | |
<em>git merge-one-file</em> command as one of the arguments to | |
<em>git merge-index</em> command:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git merge-index git-merge-one-file hello | |
Auto-merging hello | |
ERROR: Merge conflict in hello | |
fatal: merge program failed</code></pre> | |
</div></div> | |
<div class="paragraph"><p><em>git merge-one-file</em> script is called with parameters to | |
describe those three versions, and is responsible to leave the | |
merge results in the working tree. | |
It is a fairly straightforward shell script, and | |
eventually calls <em>merge</em> program from RCS suite to perform a | |
file-level 3-way merge. In this case, <em>merge</em> detects | |
conflicts, and the merge result with conflict marks is left in | |
the working tree.. This can be seen if you run <code>ls-files | |
--stage</code> again at this point:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git ls-files --stage | |
100644 7f8b141b65fdcee47321e399a2598a235a032422 0 example | |
100644 557db03de997c86a4a028e1ebd3a1ceb225be238 1 hello | |
100644 ba42a2a96e3027f3333e13ede4ccf4498c3ae942 2 hello | |
100644 cc44c73eb783565da5831b4d820c962954019b69 3 hello</code></pre> | |
</div></div> | |
<div class="paragraph"><p>This is the state of the index file and the working file after | |
<em>git merge</em> returns control back to you, leaving the conflicting | |
merge for you to resolve. Notice that the path <code>hello</code> is still | |
unmerged, and what you see with <em>git diff</em> at this point is | |
differences since stage 2 (i.e. your version).</p></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_publishing_your_work">Publishing your work</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>So, we can use somebody else’s work from a remote repository, but | |
how can <strong>you</strong> prepare a repository to let other people pull from | |
it?</p></div> | |
<div class="paragraph"><p>You do your real work in your working tree that has your | |
primary repository hanging under it as its <code>.git</code> subdirectory. | |
You <strong>could</strong> make that repository accessible remotely and ask | |
people to pull from it, but in practice that is not the way | |
things are usually done. A recommended way is to have a public | |
repository, make it reachable by other people, and when the | |
changes you made in your primary working tree are in good shape, | |
update the public repository from it. This is often called | |
<em>pushing</em>.</p></div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content">This public repository could further be mirrored, and that is | |
how Git repositories at <code>kernel.org</code> are managed.</td> | |
</tr></table> | |
</div> | |
<div class="paragraph"><p>Publishing the changes from your local (private) repository to | |
your remote (public) repository requires a write privilege on | |
the remote machine. You need to have an SSH account there to | |
run a single command, <em>git-receive-pack</em>.</p></div> | |
<div class="paragraph"><p>First, you need to create an empty repository on the remote | |
machine that will house your public repository. This empty | |
repository will be populated and be kept up to date by pushing | |
into it later. Obviously, this repository creation needs to be | |
done only once.</p></div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content"><em>git push</em> uses a pair of commands, | |
<em>git send-pack</em> on your local machine, and <em>git-receive-pack</em> | |
on the remote machine. The communication between the two over | |
the network internally uses an SSH connection.</td> | |
</tr></table> | |
</div> | |
<div class="paragraph"><p>Your private repository’s Git directory is usually <code>.git</code>, but | |
your public repository is often named after the project name, | |
i.e. <code><project>.git</code>. Let’s create such a public repository for | |
project <code>my-git</code>. After logging into the remote machine, create | |
an empty directory:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ mkdir my-git.git</code></pre> | |
</div></div> | |
<div class="paragraph"><p>Then, make that directory into a Git repository by running | |
<em>git init</em>, but this time, since its name is not the usual | |
<code>.git</code>, we do things slightly differently:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ GIT_DIR=my-git.git git init</code></pre> | |
</div></div> | |
<div class="paragraph"><p>Make sure this directory is available for others you want your | |
changes to be pulled via the transport of your choice. Also | |
you need to make sure that you have the <em>git-receive-pack</em> | |
program on the <code>$PATH</code>.</p></div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content">Many installations of sshd do not invoke your shell as the login | |
shell when you directly run programs; what this means is that if | |
your login shell is <em>bash</em>, only <code>.bashrc</code> is read and not | |
<code>.bash_profile</code>. As a workaround, make sure <code>.bashrc</code> sets up | |
<code>$PATH</code> so that you can run <em>git-receive-pack</em> program.</td> | |
</tr></table> | |
</div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content">If you plan to publish this repository to be accessed over http, | |
you should do <code>mv my-git.git/hooks/post-update.sample | |
my-git.git/hooks/post-update</code> at this point. | |
This makes sure that every time you push into this | |
repository, <code>git update-server-info</code> is run.</td> | |
</tr></table> | |
</div> | |
<div class="paragraph"><p>Your "public repository" is now ready to accept your changes. | |
Come back to the machine you have your private repository. From | |
there, run this command:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git push <public-host>:/path/to/my-git.git master</code></pre> | |
</div></div> | |
<div class="paragraph"><p>This synchronizes your public repository to match the named | |
branch head (i.e. <code>master</code> in this case) and objects reachable | |
from them in your current repository.</p></div> | |
<div class="paragraph"><p>As a real example, this is how I update my public Git | |
repository. Kernel.org mirror network takes care of the | |
propagation to other publicly visible machines:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git push master.kernel.org:/pub/scm/git/git.git/</code></pre> | |
</div></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_packing_your_repository">Packing your repository</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>Earlier, we saw that one file under <code>.git/objects/??/</code> directory | |
is stored for each Git object you create. This representation | |
is efficient to create atomically and safely, but | |
not so convenient to transport over the network. Since Git objects are | |
immutable once they are created, there is a way to optimize the | |
storage by "packing them together". The command</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git repack</code></pre> | |
</div></div> | |
<div class="paragraph"><p>will do it for you. If you followed the tutorial examples, you | |
would have accumulated about 17 objects in <code>.git/objects/??/</code> | |
directories by now. <em>git repack</em> tells you how many objects it | |
packed, and stores the packed file in the <code>.git/objects/pack</code> | |
directory.</p></div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content">You will see two files, <code>pack-*.pack</code> and <code>pack-*.idx</code>, | |
in <code>.git/objects/pack</code> directory. They are closely related to | |
each other, and if you ever copy them by hand to a different | |
repository for whatever reason, you should make sure you copy | |
them together. The former holds all the data from the objects | |
in the pack, and the latter holds the index for random | |
access.</td> | |
</tr></table> | |
</div> | |
<div class="paragraph"><p>If you are paranoid, running <em>git verify-pack</em> command would | |
detect if you have a corrupt pack, but do not worry too much. | |
Our programs are always perfect ;-).</p></div> | |
<div class="paragraph"><p>Once you have packed objects, you do not need to leave the | |
unpacked objects that are contained in the pack file anymore.</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git prune-packed</code></pre> | |
</div></div> | |
<div class="paragraph"><p>would remove them for you.</p></div> | |
<div class="paragraph"><p>You can try running <code>find .git/objects -type f</code> before and after | |
you run <code>git prune-packed</code> if you are curious. Also <code>git | |
count-objects</code> would tell you how many unpacked objects are in | |
your repository and how much space they are consuming.</p></div> | |
<div class="admonitionblock"> | |
<table><tr> | |
<td class="icon"> | |
<div class="title">Note</div> | |
</td> | |
<td class="content"><code>git pull</code> is slightly cumbersome for HTTP transport, as a | |
packed repository may contain relatively few objects in a | |
relatively large pack. If you expect many HTTP pulls from your | |
public repository you might want to repack & prune often, or | |
never.</td> | |
</tr></table> | |
</div> | |
<div class="paragraph"><p>If you run <code>git repack</code> again at this point, it will say | |
"Nothing new to pack.". Once you continue your development and | |
accumulate the changes, running <code>git repack</code> again will create a | |
new pack, that contains objects created since you packed your | |
repository the last time. We recommend that you pack your project | |
soon after the initial import (unless you are starting your | |
project from scratch), and then run <code>git repack</code> every once in a | |
while, depending on how active your project is.</p></div> | |
<div class="paragraph"><p>When a repository is synchronized via <code>git push</code> and <code>git pull</code> | |
objects packed in the source repository are usually stored | |
unpacked in the destination. | |
While this allows you to use different packing strategies on | |
both ends, it also means you may need to repack both | |
repositories every once in a while.</p></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_working_with_others">Working with Others</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>Although Git is a truly distributed system, it is often | |
convenient to organize your project with an informal hierarchy | |
of developers. Linux kernel development is run this way. There | |
is a nice illustration (page 17, "Merges to Mainline") in | |
<a href="https://web.archive.org/web/20120915203609/http://www.xenotime.net/linux/mentor/linux-mentoring-2006.pdf">Randy Dunlap’s presentation</a>.</p></div> | |
<div class="paragraph"><p>It should be stressed that this hierarchy is purely <strong>informal</strong>. | |
There is nothing fundamental in Git that enforces the "chain of | |
patch flow" this hierarchy implies. You do not have to pull | |
from only one remote repository.</p></div> | |
<div class="paragraph"><p>A recommended workflow for a "project lead" goes like this:</p></div> | |
<div class="olist arabic"><ol class="arabic"> | |
<li> | |
<p> | |
Prepare your primary repository on your local machine. Your | |
work is done there. | |
</p> | |
</li> | |
<li> | |
<p> | |
Prepare a public repository accessible to others. | |
</p> | |
<div class="paragraph"><p>If other people are pulling from your repository over dumb | |
transport protocols (HTTP), you need to keep this repository | |
<em>dumb transport friendly</em>. After <code>git init</code>, | |
<code>$GIT_DIR/hooks/post-update.sample</code> copied from the standard templates | |
would contain a call to <em>git update-server-info</em> | |
but you need to manually enable the hook with | |
<code>mv post-update.sample post-update</code>. This makes sure | |
<em>git update-server-info</em> keeps the necessary files up to date.</p></div> | |
</li> | |
<li> | |
<p> | |
Push into the public repository from your primary | |
repository. | |
</p> | |
</li> | |
<li> | |
<p> | |
<em>git repack</em> the public repository. This establishes a big | |
pack that contains the initial set of objects as the | |
baseline, and possibly <em>git prune</em> if the transport | |
used for pulling from your repository supports packed | |
repositories. | |
</p> | |
</li> | |
<li> | |
<p> | |
Keep working in your primary repository. Your changes | |
include modifications of your own, patches you receive via | |
e-mails, and merges resulting from pulling the "public" | |
repositories of your "subsystem maintainers". | |
</p> | |
<div class="paragraph"><p>You can repack this private repository whenever you feel like.</p></div> | |
</li> | |
<li> | |
<p> | |
Push your changes to the public repository, and announce it | |
to the public. | |
</p> | |
</li> | |
<li> | |
<p> | |
Every once in a while, <em>git repack</em> the public repository. | |
Go back to step 5. and continue working. | |
</p> | |
</li> | |
</ol></div> | |
<div class="paragraph"><p>A recommended work cycle for a "subsystem maintainer" who works | |
on that project and has an own "public repository" goes like this:</p></div> | |
<div class="olist arabic"><ol class="arabic"> | |
<li> | |
<p> | |
Prepare your work repository, by running <em>git clone</em> on the public | |
repository of the "project lead". The URL used for the | |
initial cloning is stored in the remote.origin.url | |
configuration variable. | |
</p> | |
</li> | |
<li> | |
<p> | |
Prepare a public repository accessible to others, just like | |
the "project lead" person does. | |
</p> | |
</li> | |
<li> | |
<p> | |
Copy over the packed files from "project lead" public | |
repository to your public repository, unless the "project | |
lead" repository lives on the same machine as yours. In the | |
latter case, you can use <code>objects/info/alternates</code> file to | |
point at the repository you are borrowing from. | |
</p> | |
</li> | |
<li> | |
<p> | |
Push into the public repository from your primary | |
repository. Run <em>git repack</em>, and possibly <em>git prune</em> if the | |
transport used for pulling from your repository supports | |
packed repositories. | |
</p> | |
</li> | |
<li> | |
<p> | |
Keep working in your primary repository. Your changes | |
include modifications of your own, patches you receive via | |
e-mails, and merges resulting from pulling the "public" | |
repositories of your "project lead" and possibly your | |
"sub-subsystem maintainers". | |
</p> | |
<div class="paragraph"><p>You can repack this private repository whenever you feel | |
like.</p></div> | |
</li> | |
<li> | |
<p> | |
Push your changes to your public repository, and ask your | |
"project lead" and possibly your "sub-subsystem | |
maintainers" to pull from it. | |
</p> | |
</li> | |
<li> | |
<p> | |
Every once in a while, <em>git repack</em> the public repository. | |
Go back to step 5. and continue working. | |
</p> | |
</li> | |
</ol></div> | |
<div class="paragraph"><p>A recommended work cycle for an "individual developer" who does | |
not have a "public" repository is somewhat different. It goes | |
like this:</p></div> | |
<div class="olist arabic"><ol class="arabic"> | |
<li> | |
<p> | |
Prepare your work repository, by <em>git clone</em> the public | |
repository of the "project lead" (or a "subsystem | |
maintainer", if you work on a subsystem). The URL used for | |
the initial cloning is stored in the remote.origin.url | |
configuration variable. | |
</p> | |
</li> | |
<li> | |
<p> | |
Do your work in your repository on <em>master</em> branch. | |
</p> | |
</li> | |
<li> | |
<p> | |
Run <code>git fetch origin</code> from the public repository of your | |
upstream every once in a while. This does only the first | |
half of <code>git pull</code> but does not merge. The head of the | |
public repository is stored in <code>.git/refs/remotes/origin/master</code>. | |
</p> | |
</li> | |
<li> | |
<p> | |
Use <code>git cherry origin</code> to see which ones of your patches | |
were accepted, and/or use <code>git rebase origin</code> to port your | |
unmerged changes forward to the updated upstream. | |
</p> | |
</li> | |
<li> | |
<p> | |
Use <code>git format-patch origin</code> to prepare patches for e-mail | |
submission to your upstream and send it out. Go back to | |
step 2. and continue. | |
</p> | |
</li> | |
</ol></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_working_with_others_shared_repository_style">Working with Others, Shared Repository Style</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>If you are coming from a CVS background, the style of cooperation | |
suggested in the previous section may be new to you. You do not | |
have to worry. Git supports the "shared public repository" style of | |
cooperation you are probably more familiar with as well.</p></div> | |
<div class="paragraph"><p>See <a href="gitcvs-migration.html">gitcvs-migration(7)</a> for the details.</p></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_bundling_your_work_together">Bundling your work together</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>It is likely that you will be working on more than one thing at | |
a time. It is easy to manage those more-or-less independent tasks | |
using branches with Git.</p></div> | |
<div class="paragraph"><p>We have already seen how branches work previously, | |
with "fun and work" example using two branches. The idea is the | |
same if there are more than two branches. Let’s say you started | |
out from "master" head, and have some new code in the "master" | |
branch, and two independent fixes in the "commit-fix" and | |
"diff-fix" branches:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git show-branch | |
! [commit-fix] Fix commit message normalization. | |
! [diff-fix] Fix rename detection. | |
* [master] Release candidate #1 | |
--- | |
+ [diff-fix] Fix rename detection. | |
+ [diff-fix~1] Better common substring algorithm. | |
+ [commit-fix] Fix commit message normalization. | |
* [master] Release candidate #1 | |
++* [diff-fix~2] Pretty-print messages.</code></pre> | |
</div></div> | |
<div class="paragraph"><p>Both fixes are tested well, and at this point, you want to merge | |
in both of them. You could merge in <em>diff-fix</em> first and then | |
<em>commit-fix</em> next, like this:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git merge -m "Merge fix in diff-fix" diff-fix | |
$ git merge -m "Merge fix in commit-fix" commit-fix</code></pre> | |
</div></div> | |
<div class="paragraph"><p>Which would result in:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git show-branch | |
! [commit-fix] Fix commit message normalization. | |
! [diff-fix] Fix rename detection. | |
* [master] Merge fix in commit-fix | |
--- | |
- [master] Merge fix in commit-fix | |
+ * [commit-fix] Fix commit message normalization. | |
- [master~1] Merge fix in diff-fix | |
+* [diff-fix] Fix rename detection. | |
+* [diff-fix~1] Better common substring algorithm. | |
* [master~2] Release candidate #1 | |
++* [master~3] Pretty-print messages.</code></pre> | |
</div></div> | |
<div class="paragraph"><p>However, there is no particular reason to merge in one branch | |
first and the other next, when what you have are a set of truly | |
independent changes (if the order mattered, then they are not | |
independent by definition). You could instead merge those two | |
branches into the current branch at once. First let’s undo what | |
we just did and start over. We would want to get the master | |
branch before these two merges by resetting it to <em>master~2</em>:</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git reset --hard master~2</code></pre> | |
</div></div> | |
<div class="paragraph"><p>You can make sure <code>git show-branch</code> matches the state before | |
those two <em>git merge</em> you just did. Then, instead of running | |
two <em>git merge</em> commands in a row, you would merge these two | |
branch heads (this is known as <em>making an Octopus</em>):</p></div> | |
<div class="listingblock"> | |
<div class="content"> | |
<pre><code>$ git merge commit-fix diff-fix | |
$ git show-branch | |
! [commit-fix] Fix commit message normalization. | |
! [diff-fix] Fix rename detection. | |
* [master] Octopus merge of branches 'diff-fix' and 'commit-fix' | |
--- | |
- [master] Octopus merge of branches 'diff-fix' and 'commit-fix' | |
+ * [commit-fix] Fix commit message normalization. | |
+* [diff-fix] Fix rename detection. | |
+* [diff-fix~1] Better common substring algorithm. | |
* [master~1] Release candidate #1 | |
++* [master~2] Pretty-print messages.</code></pre> | |
</div></div> | |
<div class="paragraph"><p>Note that you should not do Octopus just because you can. An octopus | |
is a valid thing to do and often makes it easier to view the | |
commit history if you are merging more than two independent | |
changes at the same time. However, if you have merge conflicts | |
with any of the branches you are merging in and need to hand | |
resolve, that is an indication that the development happened in | |
those branches were not independent after all, and you should | |
merge two at a time, documenting how you resolved the conflicts, | |
and the reason why you preferred changes made in one side over | |
the other. Otherwise it would make the project history harder | |
to follow, not easier.</p></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_see_also">SEE ALSO</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p><a href="gittutorial.html">gittutorial(7)</a>, | |
<a href="gittutorial-2.html">gittutorial-2(7)</a>, | |
<a href="gitcvs-migration.html">gitcvs-migration(7)</a>, | |
<a href="git-help.html">git-help(1)</a>, | |
<a href="giteveryday.html">giteveryday(7)</a>, | |
<a href="user-manual.html">The Git User’s Manual</a></p></div> | |
</div> | |
</div> | |
<div class="sect1"> | |
<h2 id="_git">GIT</h2> | |
<div class="sectionbody"> | |
<div class="paragraph"><p>Part of the <a href="git.html">git(1)</a> suite</p></div> | |
</div> | |
</div> | |
</div> | |
<div id="footnotes"><hr /></div> | |
<div id="footer"> | |
<div id="footer-text"> | |
Last updated | |
2018-01-26 15:11:04 PST | |
</div> | |
</div> | |
</body> | |
</html> |