3 The reason people have trouble wrapping their heads around git is
4 because they have been braindamaged by Github and Gitlab.
8 SECTION(«Version Control Systems»)
10 The term <em>version control</em> (also <em>revision control</em>
11 or <em>source control</em>) refers to the <em>change management</em>
12 of files. For example, some sort of change management is needed if a
13 team of geographically dispersed people concurrently make changes to
14 the files that comprise a document, fixing mistakes and adding new
17 A simple form of change management is "version control by email"
18 where the collaborators send revised copies of the document to each
19 other. While this approach can work for a small group of authors, it
20 quickly gets messy as more people are involved. One problem arises
21 when more than one person change the current version at the same
22 time because it is unclear how these changes should be combined,
23 in particular if the changes conflict with each other. For example,
24 a conflict arises if one person adds a reference to a portion of text
25 while a second person rewords the referenced text and moves it to a
26 different chapter. One way to work around this problem is to require
27 that only a single person is supposed to make changes at any given
28 time. This person edits the files and sends the revised version to
29 the next author. While this approach avoids conflicts, it is highly
30 inefficient. <em>Version control systems</em> (VCSs) are software tools
31 which help the collaborators to maintain different versions of a set of
32 files and to deal with concurrent and potentially conflicting changes.
34 SUBSECTION(«Centralized and Distributed Version Control Systems»)
36 The idea of a VCS is to track the changes that are made to a tree of
37 files over time. All revisions of all files are stored in a database
38 which is called the <em>repository</em> of the project. The
39 recorded changes are organized as <em>commits</em>. Besides the
40 file contents, each commit carries metadata about the change, like
41 date and time and the name and the email address of the person who
42 made the change. Moreover, each time a commit is being created, the
43 author is asked to provide a <em>commit message</em>, a text which
44 is supposed to document why this particular change was made.
46 Most VCSs are <em>content agnostic</em> in that they do not know or
47 care about the types of the files that are stored in the repository. In
48 order to visualize the difference between two versions of a file,
49 they have to rely on third party tools which understand the file
50 format. For plain text files, they usually employ the <em>diff</em>
51 algorithm and file format. The exercises of this section invite you to
52 take a look at the <code>diff(1)</code> command and its counterpart,
53 <code>patch(1)</code>. A rough understanding of the diff format is
54 fundamental for using any VCS.
56 The basic operations offered by VCSs are to retrieve ("check out")
57 old versions of the tree, to list the difference ("diff") between
58 two revisions, and to create new revisions from modified versions
59 of tracked files ("check in"). Most VCSs also have the concept of
60 <em>branches</em>. Branching becomes necessary if there is no single
61 "master" version, but two or more different versions that have to be
62 maintained concurrently. For example, in a repository which contains
63 the source code of some software project, there might be one "stable"
64 branch where only bugs get fixed, while new features are developed
65 in another "development" branch. Another feature each VCS needs to
66 implement is some kind of download service which lets (authenticated)
67 collaborators download a copy of the repository.
69 VCSs can be classified as being either <em>centralized</em> or
70 <em>distributed</em>. A centralized VCS is characterized by taking a
71 client-server approach to change management. For a centralized VCS, the
72 basic operations outlined above all involve the server. For example, to
73 check in a change, the server is contacted to record the new revision
74 in its database. With distributed VCSs, on the other hand, there is
75 no central instance. Instead, all repositories are self-contained
76 in that they contain the full change database. Repositories are
77 synchronized in a peer-to-peer fashion, which has many advantages,
78 including speed and scalability. This is why many people consider
79 centralized VCSs obsolete.
81 SUBSECTION(«VCS History»)
83 Probably the earliest VCS was the <em>Source Code Control System</em>
84 (SCCS) which was originally developed at Bell Labs in 1972. Although
85 it was single file based and hence did not have the concept of
86 a repository, it was the dominant VCS for Unix in the 1970s and
87 1980s. SCCS was also used as the "backend" for newer VCSs, notably RCS
88 (1982) and CVS (1990). The latter was the dominant VCS of the 1990s,
89 at least in the open source world. It was eventually superseded
90 by <em>Subversion</em> (SVN), initially released in 2000, which is
91 conceptually similar to CVS. In the late 1990s the distributed VCS
92 emerged, and have rendered the older centralized VCSs like CVS and SVN
93 obsolete. As of 2018, there are several distributed VCSs under active
94 development, of which <em>git</em> (started 2005 by Linus Torvalds,
95 the creator of Linux) is the most popular by far. We won't discuss
101 <li> Read the Wikipedia Article on the <a
102 href="https://en.wikipedia.org/wiki/Diff_utility">diff</a> utility,
103 in particular the section on the unified diff format. </li>
105 <li> Given this <a href="#diff_example">example</a> of a file
106 in unified diff format, determine the original text and the new
109 <li> Save the original text of the previous exercise in the
110 file <code>v1.txt</code> and the new text in <code>v2.txt</code>.
111 Then run <code>diff -u v1.txt v2.txt</code> to produce a diff. You
112 will notice that the diff output contains some additional lines.
113 Explain the meaning of these lines. </li>
115 <li> Save the diff output into a file with <code>diff -u v1.txt v2.txt
116 > v1-v2.diff</code>. Then run <code>patch v1.txt < v1-v2.diff</code>.
117 Examine <code>v1.txt</code>, then run <code>diff v1.txt v2.txt</code>
118 to confirm that the two files are identical. </li>
122 Come up with use cases for the <code> diff </code> and <code> patch </code>
123 utilities which are unrelated to version control.
126 SECTION(«Basic Git Usage»)
128 SUBSECTION(«Getting Help»)
129 - CMD(«git help») shows commands.
130 - CMD(«git help pull») help for pull.
131 - CMD(«git pull -h») short overview of pull options.
133 SUBSECTION(«clone, init»)
135 - init: get a new repository
136 - clone: copy a repository
140 - read CMD(«git help init») and CMD(«git help clone»)
141 - create an empty repository and clone it
143 SUBSECTION(«add, commit»)
149 - add files to both repositories
150 - commit changes, write commit summary
152 - commit changes again
155 - Initialize a new repository. Create an empty file
156 CMD(«fruits.txt»), add it to the staging area with CMD(«git
158 - Use CMD(«printf "apple\npear\n" >fruits.txt») to add some
159 fruits to the file. Add the modified file to the staging
161 - Use CMD(«printf "orange\n" >>fruits.txt») to modify the
163 - CMD(«git status») will show the file twice, why?
164 - Which version of the file (which fruits) will be committed
165 by CMD(«git commit -m "new fruits arrived"»)?
166 - How do you get the version with oranges commited?
168 The second CMD(«git add») command adds the "apple and pear" version
169 to the staging area. Appending CMD(«orange») does not change what
170 has been staged, so the first version is listed under "Changes to be
171 committed", while the just modified version is listed under "Changes
172 not staged for commit". A simple CMD(«git commit») will commit the
173 staged version. To commit the other version (with oranges) one must
174 add the file again and then run CMD(«git commit»).
179 - view commit history
183 - Look at log in both repositories
185 SUBSECTION(«fetch, merge, pull»)
186 - get changes from others
187 - pull is fetch + merge
191 - use 'git pull' to get both repositories into the same state
192 - try create an edit conflict: change both repositories and use pull
193 - resolve the edit conflict
195 SUBSECTION(«checkout, reset»)
197 - checkout: undo changes, get older version
201 - Use checkout to look at older versions of your project
203 SUBSECTION(«tags, branches»)
205 - branch to start a new experimental feature
209 - Create a new branch, modify files
210 - Use checkout to switch between master and new branch
214 - remote: manage aliases for remote repositories
218 - use CMD(«git remote -v») on both repositories
220 SECTION(«Commit Graph»)
222 The git version control system has been designed for
223 EMPH(«distributed») development where more than one person
224 makes changes to the source tree simultaneously and each does
225 so independently of the other. The history of a source tree that
226 evolves in this manner can not be described by a simple linked list
227 of changes which could sequentially be applied to the original source
228 tree in order to obtain the "current version" of the tree. In fact,
229 there is no such thing as a "current version". Moreover, in general
230 two commits are not related to each other in the sense that the second
231 commit comes after the first, or vice versa. Instead, the relationship
232 between commits can only be described adequately by a structure known
233 in graph theory as EMPH(«directed, acyclic graph») (DAG).
235 Many git commands operate on the DAG that corresponds to the commits
236 of the repository at hand. It is therefore useful to have a rough
237 understanding of the basic concepts of graph theory, and of DAGs in
238 particular. The exercises of this section ask the reader to translate
239 between the abstract, mathematical notion of a graph and its concrete
240 realization as commits in a git repository. We cover the partial order
241 of a DAG, and the derived concepts of reachabilty and infimum. Another
242 exercise aims to get the reader fluent in git's way of specifying
249 <li> Recall the definition of a <a
250 href="https://en.wikipedia.org/wiki/Directed_acyclic_graph">directed
251 and acyclic graph</a>. </li>
255 define(«dag_node_size», «13»)
256 define(«dag_margin», «dag_node_size()»)
257 define(«dag_node_bgcolor», «#ccc»)
258 define(«dag_arrow_width», «2»)
262 cx="eval($1 + dag_margin())"
263 cy="eval($2 + dag_margin())"
264 fill="dag_node_bgcolor()"
267 x="eval($1 + dag_margin())"
268 y="eval($2 + dag_margin())"
274 define(«dag_harrow», «
276 x1="eval($1 + dag_margin() + dag_node_size())"
277 y1="eval($2 + dag_margin())"
278 x2="eval($1 + $3 + dag_margin() - dag_node_size()
280 y2="eval($2 + dag_margin())"
281 stroke-width="dag_arrow_width()"
283 marker-end="url(#arrow)"
287 define(«dag_darrow», «
289 x1="eval($1 + dag_margin() + dag_node_size() * 100 / 142)"
290 y1="eval($2 + dag_margin() + dag_node_size() * 100 / 142)"
291 x2="eval(dag_margin() + $1 + $3 - dag_node_size() * 100 / 142
293 y2="eval(dag_margin() + $2 + $3 - dag_node_size() * 100 / 142)"
294 stroke-width="dag_arrow_width()"
296 marker-end="url(#arrow)"
300 width="180" height="66"
301 xmlns="http://www.w3.org/2000/svg"
302 xmlns:xlink="http://www.w3.org/1999/xlink"
303 preserveAspectRatio="xMinYMin meet"
307 viewBox="0 0 10 10" refX="5" refY="5"
308 markerWidth="4" markerHeight="4"
309 orient="auto-start-reverse">
310 <path d="M 0 0 L 10 5 L 0 10 z" />
312 dag_node(«0», «0», «I»)
313 dag_node(«100», «0», «1»)
314 dag_node(«40», «40», «A»)
315 dag_node(«90», «40», «2»)
316 dag_node(«140», «40», «M»)
318 dag_darrow(«0», «0», «40»)
319 dag_harrow(«0», «0», «100»)
320 dag_darrow(«100», «0», «40»)
321 dag_harrow(«40», «40», «50»)
322 dag_harrow(«90», «40», «50»)
325 Determine the partial order of the simple DAG on the left by
326 listing those pairs of vertices (X, Y) for which X is smaller or
327 equal to Y. Determine the infimum of 1 and 2. </li>
329 <li> The set of vertices <em>reachable</em> from a vertex Y consists
330 of all vertices X which are smaller or equal than Y. Determine the
331 vertices reachable from M and A. </li>
333 <li> Realize that this DAG is equivalent to the commit graph of the
334 repository created by this <a href="#merge.bash">script</a>. Determine
335 for each vertex in the DAG its counterpart of the git repository. Then
336 run <code>git log --graph</code> to verify. </li>
338 <li> In the same repository, which commits are shown by the following
339 commands? Answer <em>before</em> you run the command. </li>
342 <li> <code>git show topic1..topic2</code> </li>
343 <li> <code>git show topic1...topic2</code> </li>
344 <li> <code>git log -1 topic2~2</code> </li>
345 <li> <code>git log -1 topic2^2</code> </li>
346 <li> <code>git log topic1...master</code> </li>
351 define(«ril_node_size», «13»)
352 define(«ril_node_bgcolor», «#ccc»)
353 define(«ril_arrow_width», «2»)
354 define(«ril_alpha», «eval(ril_node_size() * 4 / 10)»)
355 define(«ril_beta», «eval(ril_node_size() * 92 / 100)») dnl sqrt(1 - alpha^2)
361 fill="ril_node_bgcolor()"
371 define(«ril_rarrow», «
373 x1="eval($1 + ril_alpha())"
374 y1="eval($2 + ril_beta())"
375 x2="eval($3 - ril_alpha() - 3)"
376 y2="eval($4 - ril_beta() - 2)"
377 stroke-width="ril_arrow_width()"
379 marker-end="url(#arrow)"
382 define(«ril_larrow», «
384 x1="eval($1 - ril_alpha())"
385 y1="eval($2 + ril_beta())"
386 x2="eval($3 + ril_alpha() + 3)"
387 y2="eval($4 - ril_beta() - 2)"
388 stroke-width="ril_arrow_width()"
390 marker-end="url(#arrow)"
393 define(«ril_varrow», «
396 y1="eval($2 + ril_node_size())"
398 y2="eval($4 - ril_node_size() - 4)"
399 stroke-width="ril_arrow_width()"
401 marker-end="url(#arrow)"
406 width="160" height="170"
407 xmlns="http://www.w3.org/2000/svg"
408 xmlns:xlink="http://www.w3.org/1999/xlink"
409 preserveAspectRatio="xMinYMin meet"
411 ril_node(«15», «15», «G»)
412 ril_node(«55», «15», «H»)
413 ril_node(«95», «15», «I»)
414 ril_node(«135», «15», «J»)
415 ril_node(«35», «60», «D»)
416 ril_node(«75», «60», «E»)
417 ril_node(«115», «60», «F»)
418 ril_node(«75», «105», «B»)
419 ril_node(«115», «105», «C»)
420 ril_node(«95», «150», «A»)
422 ril_rarrow(«15», «15», «35», «60»)
423 ril_larrow(«55», «15», «35», «60»)
424 ril_rarrow(«95», «15», «115», «60»)
425 ril_larrow(«135», «16», «115», «60»)
426 ril_rarrow(«35», «60», «75», «105»)
427 ril_varrow(«75», «60», «75», «105»)
428 ril_larrow(«115», «60», «75», «105»)
429 ril_varrow(«115», «60», «115», «105»)
430 ril_rarrow(«75», «105», «95», «150»)
431 ril_larrow(«115», «105», «95», «150»)
434 For each of the following revision parameters, determine the commit
435 it refers to with respect to the commit graph on the left. Parent
436 commits are ordered left-to-right.
439 A^0, A^, A^1, A^^^2, B^3^, A~1, A^2, A^^, A^1^1, A^^2,
440 B^3^2, A^^3^2. A~2^2, A^^3^, A^^^, A^1^1^1, A~3.
444 The suffix <code>^</code> to a revision parameter means the
445 first parent. <code>^n</code> means the n-th parent. The suffix
446 <code>~n</code> means the n-th generation ancestor, following only
447 the first parents. See <code>gitrevisions(7)</code>.
450 A^0 = A, A^ = A^1 = B, A^^^2 = H, B^3^ = I, A~1 = B, A^2 = C,
451 A^^ = A^1^1 = D, A^^2 = E, B^3^2 = A^^3^2 = J, A~2^2 = H, A^^3^ = I,
452 A^^^ = A^1^1^1 = A~3 = G
456 SECTION(«Git Objects and Refs»)
458 Unlike centralized version control systems like CVS and SVN, each copy
459 of a git repository contains the full history of the source tree,
460 rather than only a few recent revisions. This speeds up operations
461 like CMD(«git log») or CMD(«git diff») because all operations
462 are local. It also makes it possible to work offline as no network
463 connection is needed for most operations. The git database, which
464 is hidden inside the CMD(«.git») subdirectory of the repository,
465 contains all revisions of all tracked files as well as meta data like
466 file names, access permissions and commit messages. All contents are
467 stored as EMPH(«git objects») and the database is indexed by the
468 SHA1 hash value of the objects' contents. This indexing method is
469 called EMPH(«content-based addressing») because the hash value of
470 the contents of an object is used as the lookup key for the database.
472 Depending on the size of the repository, the git database may contain
473 millions of objects, but there are only four different types of
474 objects: blob, tree, commit, and tag. The exercises of this section
475 invite the reader to look at each object type in more detail. Another
476 aim is to demystify the differences between heads, tags, refs and
477 branches, which all denote a reference to a commit object.
481 - Recall the properties of a
482 XREFERENCE(«https://en.wikipedia.org/wiki/Cryptographic_hash_function»,
483 «cryptographic hash function»).
484 - How many objects of each type exist in the repo created by this
485 REFERENCE(two_branches.bash, script)? Check with CMD(git fsck -v).
486 - Clone the user-info repository with CMD(«git clone
487 git://ilm.eb.local/user-info») and explore all files in the
488 CMD(«.git/refs») directory.
491 - Learn how to manually create a commit with CMD(«git hash-object»),
492 CMD(«git update-index»), CMD(«git write-tree»), and CMD(«git
498 Every version control system needs some kind of EMPH(«tree object»)
499 which records the information about one particular state of the source
500 tree. A commit then corresponds to a transition from one tree object
501 to another and is described by an edge in the commit graph.
503 Git exposes one tree object in a special staging area called the
504 EMPH(«index»). One can think of the index as a table which contains
505 one row for each tracked file, which contains the information necessary
506 to generate a tree object.
508 Under normal circumstances each row of the index has three columns:
509 The permission bits of the file, the file name, and the hash value
510 of the file's contents. When resolving merge conflicts, however,
511 it is handy to have additional columns which contain the hash values
512 of the two conflicting versions of the file plus the hash value of
515 Many git commands operate on the index. For example the command
516 CMD(«git commit») (with no arguments) creates a commit from the
517 index. It does not even look at the working tree. Another example is
518 CMD(«git add foo»), which updates the hash column of CMD(«foo»)
519 in the index to match the version of CMD(«foo») in the working tree.
521 From the above it should be clear that the concept of an index is
522 quite natural in the context of version control systems. The fact
523 that git exposes the index, rather than hiding it as other version
524 control systems do, gives the user a great deal of control over the
525 next commit. Being able to tweak the index as needed is a good thing
526 not only for conflict handling.
528 The exercises of this section try to convince the reader that the index
529 is by no means an advanced concept that is so hard to understand that
530 it should be hidden from the user.
534 - In any repository, add a modified tracked file and run CMD(«git diff»),
535 and CMD(«git diff --cached»).
536 - Make two unrelated changes to the same file, then run CMD(«tig»),
537 CMD(«git gui») or CMD(«git add -i») to record only one of the changes to
538 the index. Run CMD(«git diff --cached») to verify before you commit.
539 - During a merge, the index contains references to up to three versions
540 of each file. Explain to which commits these three versions correspond.
544 Resetting a branch means to let the branch head point to a different
545 commit. This so-called EMPH(«soft») reset operates only on the
546 commit graph, but it touches neither the index nor the working tree.
547 By default git performs a EMPH(«medium») reset which additionally
548 resets the index to make it match the tree object of the new
549 commit. Finally, a EMPH(«hard») reset additionally updates the
550 working tree accordingly.
552 The exercises of this section try to clarify the difference between
553 the three different flavors of resetting a branch.
557 - In the repo created with REFERENCE(«two_branches.bash»,
558 «script»), create a new temporary branch with CMD(«git checkout
559 -b tmp topic2»). Reset this branch to its parent commit with
560 CMD(«git reset --hard HEAD^») Repeat using the CMD(«--soft»)
561 and CMD(--medium) options. Examine the index at each step.
562 - When given one or more paths, CMD(«git reset») has a different
563 meaning: It copies named entries from the given revision to the
564 index. In the two-branches repo, run CMD(«git reset HEAD^ h») and
565 investigate the working copy and the index with CMD(«git diff»)
566 and CMD(«git diff --cached»).
570 <p> The command <code>git reset --hard</code> throws away any
571 uncommitted changes in the working tree and the index. It returns to
572 a <em>clean state</em> where index and working tree match the tree
573 of the HEAD commit. Sometimes, however, one would like to return to
574 a clean state without losing or committing the local changes. </p>
576 <p> For example, suppose that your working tree has several modified
577 files because you are in the middle of something. Then you notice
578 an unrelated flaw in one of the files. Fixing this flaw has higher
579 priority than your current work and should be quick and easy. But you
580 don't want to lose your local changes and you don't want to commit
581 them either because this work is not yet complete. </p>
583 <p> In this situation <code>git stash</code> can help you out. This
584 command records the current state of the working directory and the
585 index. The modifications can be restored later, possibly on top of
586 a different commit. </p>
588 define(«str_node_size», «13»)
589 define(«str_node_bgcolor», «#ccc»)
590 define(«str_arrow_width», «2»)
591 dnl sin(pi/3) = sqrt(3)/2 = 0.866
592 define(«str_offset», «eval(str_node_size() * 87 / 100)»)
598 fill="str_node_bgcolor()"
608 define(«str_arrow», «
614 stroke-width="str_arrow_width()"
616 marker-end="url(#arrow)"
621 width="100" height="75"
622 xmlns="http://www.w3.org/2000/svg"
623 xmlns:xlink="http://www.w3.org/1999/xlink"
624 preserveAspectRatio="xMinYMin meet"
626 str_node(«20», «65», «H»)
627 str_node(«80», «65», «I»)
628 str_node(«50», «13», «W»)
629 str_arrow(«eval(20 + str_node_size())», «65»,
630 «eval(80 - str_node_size() - 4)», «65»)
631 str_arrow(«eval(20 + str_node_size() / 2)»,
632 «eval(65 - str_offset())»,
633 «eval(50 - str_node_size() / 2 - 2)»,
634 «eval(str_node_size() + str_offset() + 2)»)
635 str_arrow(«eval(80 - str_node_size() / 2)»,
636 «eval(65 - str_offset())»,
637 «eval(50 + str_node_size() / 2 + 2)»,
638 «eval(str_node_size() + str_offset() + 2)»)
642 <p> Stashes are stored in a git repository as illustrated in the graph
643 to the left. H stands for the <code>HEAD</code> commit, I for a commit
644 that records the state of the index. W is a commit which includes
645 the changes of the working tree, relative to the <code> HEAD </code>
646 commit. It is reasonable to store W as a child of I since usually
647 the staged version corresponds to an earlier version of the tree. </p>
649 <p> After <code>git stash</code> the index and the working tree
650 are both reset to H so that <code>git status</code> reports
651 a clean state. <code>git stash pop</code> and <code>git stash
652 apply</code> apply the changes between H and W to the current working
653 directory. Since the working directory might be completely different
654 at this point, this operation can fail. Note that neither <code>git
655 stash pop</code> nor <code>git stash apply</code> restore the changes
656 to the index recorded in the stash. For this you need to specify
657 the <code> --index</code> option. Consult <code>git-stash(1)</code>
660 The exercises of this section ask the reader to practice stashing
661 and unstashing in the "interrupted work flow" scenario described above.
665 - Run the REFERENCE(«stash.bash», «stash example script»)
666 below. It creates a single commit and leaves the working tree
667 in a dirty state. Run CMD(«git diff») and CMD(«git status»)
668 to see the uncommited changes. Suppose at this point you realize
669 the typo in the first sentence ("pomacous" instead of "pomaceous").
670 Run CMD(«git stash») to stash away your modifications, then fix the
671 typo and create a commit with this typo fix only. Run CMD(«git stash
672 pop») to bring back the stashed modification. This will result in
673 a conflict as is verified with CMD(«git status»). Fix the conflict
674 by editing the file, and resolve the conflict by re-adding the file
675 with CMD(«git add»). Commit the modification and investigate all
676 three commits with CMD(«git log -p»).
677 - Discuss the difference and the pros and cons of stashing versus
678 creating a commit in a temporary branch.
682 Version control systems track every version of every file. Therefore
683 they can, at least in principle, compute for each line of a tracked
684 file the commit that introduced it.
686 For example, this information can be used to identify the commit which
687 introduced a certain bug in a source file of a software project. The
688 commit meta data tells who made the problematic change and when,
689 and the commit message (hopefully) explains why the change was made
690 in this way, who was involved in the discussion, and who reviewed or
691 approved the change. This information can be very valuable because
692 it helps to avoid similar bugs in the future. It is common practice
693 to mention the ID of the problematic commit in the commit message of
694 the fixup commit that eliminates the bug.
696 git provides a simple way to annotate any tracked text file with
697 the commit information. This functionality is implemented as the
698 EMPH(«blame») subcommand. In the simplest form, CMD(«git blame»)
699 adds the following information to each line of the given file:
701 - the (abbreviated) ID of the commit that introduced the line,
702 - the name of the author of that commit,
703 - the date and time of the commit,
706 The exercises of this section aim to make the reader aware of the
707 CMD(«blame») command and to convince her that the command can be
708 helpful at times, and that it is actually very easy to use.
712 - Clone the user-info repo with CMD(«git clone
713 git://ilm.eb.local/user-info») and run CMD(«git blame
714 doc/user-guide/user-guide.txi») and discuss each column of the output.
716 - Repeat the CMD(«blame») command, but this time add the
717 CMD(«--line-porcelain») option and discuss what kind of statistics
718 could be created from the output of this command if it was run on
719 all files of a large software project.
721 SECTION(«Proposing and Discussing Changes»)
723 More often than not, even simple changes have to be tweaked to
724 perfection in several steps. The problem is that the text or code
725 always looks great to the person who just wrote it, while another
726 person, or even the author herself a day later, finds serious
727 flaws. Also, coming up with a good commit message is much easier
728 EMPH(«without») having all the details in short term memory. The sad
729 truth is that there's nothing that can be done about that, as this
730 is just how the human brain works. In view of this unfixable human
731 limitation, the highest quality is achieved by EMPH(«peer review»),
732 which is why the policy of many software projects demands that each
733 commit has to be reviewed and approved by somebody else before it
734 hits the master branch of a repository.
736 The CMD(«send-email») subcommand of git makes peer review as easy as
737 it can get. It sends the specified range of commits to the recipients
738 given at the command line or in the commit messages. The recipients
739 can apply the patch series to their own local repository with CMD(«git
740 am») ("am" is short for "apply mailbox"). As CMD(«git send-email»)
741 sends each commit as a separate email, controverse changes can be
742 discussed by simply replying to the corresponding emails. If some
743 particular commit triggers a discussion, it probably needs to be
744 adjusted according to the reviewer's comments, and the author should
745 send a revised version later. In this case also the commit message
746 should be adjusted to include a summary of the discussion. This process
747 can be iterated several times if necessary. Once the reviewers have
748 no more objections, the CMD(«Reviewed-by») tags can be added to
749 the final version of each patch in the series and the series can be
750 applied to the master branch.
752 This way of discussing commits by email has several advantages. For
753 one, it does not force everyone into a specific development tool or
754 platform, as everybody can use his favorite email client to review
755 the patches and reply to the patch emails. Second, no additional
756 infrastructure is required and no accounts or access persmissions need
757 to be maintained. In fact, it is the EMPH(«point») of distributed
758 development to have no central infrastructure that could become the
759 single point of failure. Third, additional people can be included in
760 the discussion simply by adding them to the CC list.
764 - Preparation: Clone the user-info repo with CMD(«git clone
765 git://ilm.eb.local/user-info»).
766 - Create and check out a branch that points as the same commit as
767 the master branch: CMD(«git checkout -b user-guide origin/master»).
768 - Open the CMD(«doc/user-guide/user-guide.txi») file with an
769 editor and add a sentence to the first section. Create a commit
770 with CMD(«git commit -av») and send this commit to yourself with
771 CMD(«git send-email HEAD^..»), then check your mail.
772 - In practice you would send the commit to the maintainer of the repo
773 rather than to yourself. Assume you already did this and the maintainer
774 replied that your change is good, but has some minor issue. Edit
775 the file again and change the sentence. Run CMD(«git commit -av
776 --amend») to replace your commit. Double check with CMD(«git show»)
777 that everything is fine. Then run the above CMD(«git send-email»)
779 - Now suppose you are the maintainer of the project, and you received
780 the patch by email from somebody else and want to apply it to your
781 repository. Get rid of the commit with CMD(«git reset --hard HEAD^»),
782 save the patch email into the file CMD(«improvement.patch») and
783 copy the file to the machine on which your repo is stored. Then run
784 CMD(«git am improvement.patch») to apply the patch. Note:
785 - there is no need to remove the email headers,
786 - the commit message and author information stays intact,
787 - the SHA1 number of the commit has changed.
788 - If your repository is world-readable and the project maintainer
789 can log in into the machine on which it is stored, CMD(«git
790 request-pull») is an alternative to CMD(«git send-email»). Run
791 CMD(«git request-pull HEAD^ $PWD») to see how your pull request
792 looks like. Then run CMD(«git request-pull HEAD^ $PWD | mail -s
793 "[Pull] documentation improvements" $LOGNAME») to send the pull
794 request to yourself. In practice, you would of course send the pull
795 request to the maintainer.
797 SECTION(«Remote Repositories, Push and Fetch»)
799 - CMD(«push»): update remote refs using local refs
800 - input: URL of the remote repo, refs (branches or tags) to push
801 - refspec, e.g., CMD(«+refs/heads/master:refs/remotes/mpi/master»)
802 - forcing a push or fetch
803 - deleting branches from a remote with CMD(«git push :topic»)
807 - Recall the definition of a fast-forward merge in
808 CMD(«gitglossary(7)»).
809 - In the refspec CMD(«<src>:<dst>») which kind of objects are
810 allowed for CMD(«<src>») and CMD(«<dst>»)?
811 - By default CMD(«git push <src>:<dst>») fails if the remote
812 branch CMD(«<dst>») does not fast-forward to the commit specified by
813 CMD(«<src>»). The optional leading CMD(«+») tells git to update the
814 destination ref anyway. Discuss why this "forced push" is dangerous.
815 - Create an REFERENCE(«empty_repo.bash», «empty repo») and a second
816 repo with REFERENCE(«two_branches.bash», «two branches»). Change
817 the CWD to this second repository. All operations below are to be
818 executed from this location.
819 - Push one of the branches from the two-branch repo to the empty
820 repo by executing a suitable CMD(«git push») command. Check out
821 one of the two branches and modify the commit message with CMD(«git
822 commit --amend»). Then run the same CMD(«push command») again and
823 understand the error message you get. Find two ways to force the push.
824 - Add a suitable CMD(«URL») line to the CMD(«.git/config») file of
825 the two-branch repo that lets you refer to the other repo by name. Run
826 CMD(«git ls-remote <name>») to list the branches of this repository
827 (where CMD(«<name>») is the name you have chosen in the CMD(«URL»)
829 - Add a suitable CMD(«push») line to the configuration file of the
830 two-branch repo so that simply running CMD(«git push») pushes one
831 branch to the second repository.
832 - Remove one branch of the formerly empty repository by running a
833 suitable CMD(«git push :<branch>») command from the two-branch
835 - Discuss what should happen if the branch to be removed with
836 CMD(«git push :<branch>») is currently checked out in the remote
837 repository. Then check if git does what you suspect.
841 - purpose: polish commits for the final merge to master
843 - rewriting commit messages
844 - removing, splitting and joining commits
845 - interactive or non-interactive
850 - Run the REFERENCE(«rebase_example.bash», «rebase example script»)
851 to create a repository with a (stable) master branch, and a (rather
852 messy) topic branch (called "bembel") and CMD(«cd») into the top
853 level directory of this git repo.
854 - Execute CMD(«tig master bembel») to visualize the commit graph
855 and the indiviual commits.
856 - Check out the topic branch and rebase it on top of master with
857 CMD(«git rebase master»). Run the above CMD(«tig») command again
859 - The topic branch contains one commit which is actually unrelated to
860 the topic. Identify this commit and run CMD(«git rebase -i master»)
861 to change the order of the commits so that the unrelated commit
863 - Find the SHA1 of the unrelated commit with CMD(«git log») and
864 merge only this commit into the master branch with CMD(«git checkout
865 master»), CMD(«git merge <sha1>»). Note that this is a fast-forward
866 merge, so no merge commit is created.
867 - Check out the topic branch and run CMD(«git rebase -i master»)
868 again to combine all commits to a single commit. This is done by
869 replacing CMD(«pick») by CMD(«squash») for all but the first
870 commit. Note that you are asked to combine the individual commit
871 messages into a single (meaningful) one.
872 - Create a test script (CMD(«grep bembel * || exit 1»)) that checks
873 that the word "bembel" is never spelled in lower case. On the topic
874 branch, run CMD(«git rebase -i master») and add one line between
875 each commit that runs your test script. Hint: Read the comments at
876 the bottom of the message.
877 - Merge the topic branch into the master branch with CMD(«git checkout
878 master») and CMD(«git merge bembel»). Then delete the topic branch
879 with CMD(«git branch -d bembel»). Does this lose any commits?
881 SECTION(«Conflict Resolution»)
883 - conflicts can happen during CMD(«merge»), CMD(«pull»),
884 CMD(«stash») operations.
886 - stages: 1: base, 2: ours, 3: theirs
887 - rerere: replay recorded resolution
891 - Run this REFERENCE(merge.bash, script) which creates a git repository
892 with two branches in a subdirectory of the current directory. Try to
893 merge the two branches with CMD(git merge topic1). Understand why the
894 command fails. Explain the output of CMD(git status), CMD(git diff)
895 and CMD(git diff --cached), CMD(git log -p --merge).
896 - The terms "merge base", "ours", "theirs" are frequently used to
897 denote commits during a conflicted merge. Determine these commits for
898 the conflict at hand. Run CMD(git ls-files -u) and CMD(git ls-tree
899 $X) for CMD(X=master, topic1, topic2) and describe the meaning of
900 each column in the output.
901 - Look at the two diffs from each branch: CMD(git log --merge -p) and
902 at the three originals: CMD(git show :$X:h), where CMD(«X=1,2,3»).
903 - Resolve the conflict with CMD(echo "hello all" > h), followed
904 by CMD(git add h). Check how the output of CMD(git status) CMD(git
905 ls-files -u) has changed. Run CMD(git commit -m "resolved") to record
906 your conflict resolution and verify with CMD(git log --graph). Describe
907 the meaning of the two SHA1 numbers shown in the CMD(git log -1)
909 - Activate the EMPH(«rerere») feature by adding CMD(«enabled =
910 true») to the CMD(«rerere») section of your CMD(«.git/config»)
911 file. Run CMD(«git reset --hard HEAD^») to get rid of the merge
912 commit and to return to the previous commit. Repeat the merge, notice:
913 git records the conflict and the resolution. Reset and repeat again.
917 SUBSECTION(«Diff Example»)
919 <div class="diffctx"> The git version control system is a powerful </div>
920 <div class="diffdel">-open source tool. Unfortunately, with more </div>
921 <div class="diffdel">-than 100 subcommands and even more command </div>
922 <div class="diffdel">-line options, it is way too difficult to use </div>
923 <div class="diffadd">+open source tool. Fortunately, thanks to the </div>
924 <div class="diffadd">+Unix course web pages it is easy to learn even </div>
925 <div class="diffctx"> for mere humans. </div>
927 SUBSECTION(«empty_repo.bash»)
934 GD=$(mktemp -d /tmp/ct-git-XXXXXX)
941 SUBSECTION(«two_branches.bash»)
948 GD=$(mktemp -d /tmp/ct-git-XXXXXX)
952 echo 'apples, peas' > fruits
954 git commit -m initial
956 git checkout -b topic1
959 git commit -am 'add world, peas are no fruits'
961 git checkout -b topic2 master
963 git commit -am 'add people'
969 SUBSECTION(«merge.bash»)
976 GD=$(mktemp -d /tmp/ct-git-XXXXXX)
981 git commit -m initial
983 git checkout -b topic1
984 echo 'apples' > fruits
987 echo 'pears' >> fruits
988 git commit -am 'more fruits'
990 git checkout -b topic2 master
991 echo 'peas' > vegetables
993 git commit -m vegetables
995 git merge --no-edit topic1
997 echo Created merge example repository in:
1001 SUBSECTION(«stash.bash»)
1008 GD=$(mktemp -d /tmp/ct-git-XXXXXX)
1009 f='apple-definition'
1013 echo 'The apple tree (Malus domestica) is a deciduous tree in the rose
1014 family best known for its sweet, pomacous fruit, the apple.' > "$f"
1017 git commit -m 'initial draft of apple definition'
1019 echo 'The apple tree (Malus domestica) is a deciduous tree in the rose
1020 family best known for its sweet, pomacous fruit, the apple. The tree
1021 originated in Central Asia, where its wild ancestor, Malus sieversii,
1022 is still found today.' > "$f"
1026 SUBSECTION(«rebase_example.bash»)
1033 GD=$(mktemp -d /tmp/ct-git-XXXXXX)
1039 echo 'Apfelwein or Most are German words for cider. It is also
1040 regionaly known as Ebbelwoi, Äppler, Stöffsche, Apfelmost Viez,
1044 git commit -m 'Add initial definition of Ebbelwoi.'
1047 In the Frankfurt area, berries from the service tree (Sorbus
1048 domestica), are added to increase astringency. This specific
1049 type of Apfelwein is called Speierling.
1051 git commit -am 'Add section on Speierling.'
1053 git checkout -b 'bembel'
1055 Apfelwein is served in a "Geripptes", a glass with a lozenge cut that
1056 refracts light and improves grip.
1059 git commit -m 'Initial draft of culture file.'
1063 The juice or must is fermented with yeast to produce an alcoholic
1064 beverage usually around 6% abv.
1066 git commit -am 'Mention that Apfelwein is an alcoholic beverage.'
1068 git checkout 'bembel'
1070 Most establishments will also serve Apfelwein by the Bembel (a specific
1071 Apfelwein jug), much like how beer can be purchased by the pitcher
1075 git commit -am 'Add section on bembel to culture file.'
1077 sed -i 's/regionaly/regionally/g' "$f1"
1078 git commit -am 'Fix typo in apfelwein section.'
1080 sed -i '/^Most establishments/,$d' "$f2"
1082 Most establishments will also serve Apfelwein by the Bembel (a specific
1083 Apfelwein jug). The paunchy bembel is made from salt-glazed stoneware
1084 and always has a basic grey colour with blue-painted detailing.
1086 git commit -am 'Rewrite section on Bembel.'
1088 sed -i 's/bembel/Bembel/g' "$f2"
1089 git commit -am 'Always spell Bembel in upper case.'