Networking: Remove exercise about www.meineip.de.
[aple.git] / Git.m4
1 TITLE(«
2
3 The reason people have trouble wrapping their heads around git is
4 because they have been braindamaged by Github and Gitlab.
5
6 », __file__)
7
8 SECTION(«Version Control Systems»)
9
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
15 content over time.
16
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.
33
34 SUBSECTION(«Centralized and Distributed Version Control Systems»)
35
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.
45
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.
55
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.
68
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.
80
81 SUBSECTION(«VCS History»)
82
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
96 other VCSs further.
97
98 EXERCISES()
99
100 <ul>
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>
104
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
107 text. </li>
108
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>
114
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>
119 </ul>
120
121 HOMEWORK(«
122 Come up with use cases for the <code> diff </code> and <code> patch </code>
123 utilities which are unrelated to version control.
124 »)
125
126 SECTION(«Basic Git Usage»)
127
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.
132
133 SUBSECTION(«clone, init»)
134 - get started
135 - init: get a new repository
136 - clone: copy a repository
137
138 EXERCISES()
139
140 - read CMD(«git help init») and CMD(«git help clone»)
141 - create an empty repository and clone it
142
143 SUBSECTION(«add, commit»)
144 - add files
145 - commit changes
146
147 EXERCISES()
148
149 - add files to both repositories
150 - commit changes, write commit summary
151 - change files again
152 - commit changes again
153
154 HOMEWORK(«
155 - Initialize a new repository. Create an empty file
156 CMD(«fruits.txt»), add it to the staging area with CMD(«git
157 add») and commit it.
158 - Use CMD(«printf "apple\npear\n" >fruits.txt») to add some
159 fruits to the file. Add the modified file to the staging
160 area.
161 - Use CMD(«printf "orange\n" >>fruits.txt») to modify the
162 file again.
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?
167 », «
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»).
175
176 »)
177
178 SUBSECTION(«log»)
179 - view commit history
180
181 EXERCISES()
182
183 - Look at log in both repositories
184
185 SUBSECTION(«fetch, merge, pull»)
186 - get changes from others
187 - pull is fetch + merge
188
189 EXERCISES()
190
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
194
195 SUBSECTION(«checkout, reset»)
196 - reset: move HEAD
197 - checkout: undo changes, get older version
198
199 EXERCISES()
200
201 - Use checkout to look at older versions of your project
202
203 SUBSECTION(«tags, branches»)
204 - tag a release
205 - branch to start a new experimental feature
206
207 EXERCISES()
208
209 - Create a new branch, modify files
210 - Use checkout to switch between master and new branch
211
212
213 SUBSECTION(«alias»)
214 - remote: manage aliases for remote repositories
215
216 EXERCISES()
217
218 - use CMD(«git remote -v») on both repositories
219
220 SECTION(«Commit Graph»)
221
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).
234
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
243 sets of commits.
244
245 EXERCISES()
246
247 <ul>
248
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>
252
253 <li>
254 <div>
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»)
259 define(«dag_node», «
260 <circle
261 r="dag_node_size()"
262 cx="eval($1 + dag_margin())"
263 cy="eval($2 + dag_margin())"
264 fill="dag_node_bgcolor()"
265 />
266 <text
267 x="eval($1 + dag_margin())"
268 y="eval($2 + dag_margin())"
269 stroke="black"
270 text-anchor="middle"
271 dy="0.3em"
272 >$3</text>
273 »)
274 define(«dag_harrow», «
275 <line
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()
279 - 4)"
280 y2="eval($2 + dag_margin())"
281 stroke-width="dag_arrow_width()"
282 stroke="black"
283 marker-end="url(#arrow)"
284 />
285 »)
286
287 define(«dag_darrow», «
288 <line
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
292 - 4)"
293 y2="eval(dag_margin() + $2 + $3 - dag_node_size() * 100 / 142)"
294 stroke-width="dag_arrow_width()"
295 stroke="black"
296 marker-end="url(#arrow)"
297 />
298 »)
299 <svg
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"
304 >
305 <marker
306 id="arrow"
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" />
311 </marker>
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»)
317
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»)
323 </svg>
324 </div>
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>
328
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>
332
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>
337
338 <li> In the same repository, which commits are shown by the following
339 commands? Answer <em>before</em> you run the command. </li>
340
341 <ul>
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>
347 </ul>
348 </ul>
349
350 HOMEWORK(«
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)
356 define(«ril_node», «
357 <circle
358 r="ril_node_size()"
359 cx="$1"
360 cy="$2"
361 fill="ril_node_bgcolor()"
362 />
363 <text
364 x="$1"
365 y="$2"
366 stroke="black"
367 text-anchor="middle"
368 dy="0.3em"
369 >$3</text>
370 »)
371 define(«ril_rarrow», «
372 <line
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()"
378 stroke="black"
379 marker-end="url(#arrow)"
380 />
381 »)
382 define(«ril_larrow», «
383 <line
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()"
389 stroke="black"
390 marker-end="url(#arrow)"
391 />
392 »)
393 define(«ril_varrow», «
394 <line
395 x1="$1"
396 y1="eval($2 + ril_node_size())"
397 x2="$3"
398 y2="eval($4 - ril_node_size() - 4)"
399 stroke-width="ril_arrow_width()"
400 stroke="black"
401 marker-end="url(#arrow)"
402 />
403 »)
404 <div>
405 <svg
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"
410 >
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»)
421
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»)
432 </svg>
433 </div>
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.
437
438 <pre>
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.
441 </pre>
442 », «
443
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>.
448
449 <pre>
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
453 </pre>
454 »)
455
456 SECTION(«Git Objects and Refs»)
457
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.
471
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.
478
479 EXERCISES()
480
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.
489
490 HOMEWORK(«
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
493 commit-tree»).
494 »)
495
496 SECTION(«The Index»)
497
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.
502
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.
507
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
513 a common anchestor.
514
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.
520
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.
527
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.
531
532 EXERCISES()
533
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.
541
542 SECTION(«Reset»)
543
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.
551
552 The exercises of this section try to clarify the difference between
553 the three different flavors of resetting a branch.
554
555 EXERCISES()
556
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»).
567
568 SECTION(«Stashing»)
569
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>
575
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>
582
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>
587
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)»)
593 define(«str_node», «
594 <circle
595 r="str_node_size()"
596 cx="$1"
597 cy="$2"
598 fill="str_node_bgcolor()"
599 />
600 <text
601 x="$1"
602 y="$2"
603 stroke="black"
604 text-anchor="middle"
605 dy="0.3em"
606 >$3</text>
607 »)
608 define(«str_arrow», «
609 <line
610 x1="$1"
611 y1="$2"
612 x2="$3"
613 y2="$4"
614 stroke-width="str_arrow_width()"
615 stroke="black"
616 marker-end="url(#arrow)"
617 />
618 »)
619 <div>
620 <svg
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"
625 >
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)»)
639 </svg>
640 </div>
641
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>
648
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>
658 for details. </p>
659
660 The exercises of this section ask the reader to practice stashing
661 and unstashing in the "interrupted work flow" scenario described above.
662
663 EXERCISES()
664
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.
679
680 SECTION(«Blame»)
681
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.
685
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.
695
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:
700
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,
704 - the line number.
705
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.
709
710 EXERCISES()
711
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.
715
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.
720
721 SECTION(«Proposing and Discussing Changes»)
722
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.
735
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.
751
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.
761
762 EXERCISES()
763
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»)
778 command again.
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.
796
797 SECTION(«Remote Repositories, Push and Fetch»)
798
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»)
804
805 EXERCISES()
806
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»)
828 line).
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
834 repository.
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.
838
839 SECTION(«Rebase»)
840
841 - purpose: polish commits for the final merge to master
842 - reorder commits
843 - rewriting commit messages
844 - removing, splitting and joining commits
845 - interactive or non-interactive
846 - automated testing
847
848 EXERCISES()
849
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
858 to see the effect.
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
862 comes first.
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?
880
881 SECTION(«Conflict Resolution»)
882
883 - conflicts can happen during CMD(«merge»), CMD(«pull»),
884 CMD(«stash») operations.
885 - conflict markers
886 - stages: 1: base, 2: ours, 3: theirs
887 - rerere: replay recorded resolution
888
889 EXERCISES()
890
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)
908 output.
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.
914
915 SUPPLEMENTS()
916
917 SUBSECTION(«Diff Example»)
918
919 <div class="diffctx">&nbsp;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">&nbsp;for mere humans. </div>
926
927 SUBSECTION(«empty_repo.bash»)
928
929 <pre>
930 #!/bin/bash
931
932 set -e
933
934 GD=$(mktemp -d /tmp/ct-git-XXXXXX)
935 cd "$GD"
936 git init
937 echo cd "$GD"
938
939 </pre>
940
941 SUBSECTION(«two_branches.bash»)
942
943 <pre>
944 #!/bin/bash
945
946 set -e
947
948 GD=$(mktemp -d /tmp/ct-git-XXXXXX)
949 cd "$GD"
950 git init
951 echo hello > h
952 echo 'apples, peas' > fruits
953 git add h fruits
954 git commit -m initial
955
956 git checkout -b topic1
957 echo world >> h
958 echo apples > fruits
959 git commit -am 'add world, peas are no fruits'
960
961 git checkout -b topic2 master
962 echo people >> h
963 git commit -am 'add people'
964
965 echo cd "$GD"
966
967 </pre>
968
969 SUBSECTION(«merge.bash»)
970
971 <pre>
972 #!/bin/bash
973
974 set -e
975
976 GD=$(mktemp -d /tmp/ct-git-XXXXXX)
977 cd "$GD"
978 git init
979 echo hello > h
980 git add h
981 git commit -m initial
982
983 git checkout -b topic1
984 echo 'apples' > fruits
985 git add fruits
986 git commit -m fruits
987 echo 'pears' >> fruits
988 git commit -am 'more fruits'
989
990 git checkout -b topic2 master
991 echo 'peas' > vegetables
992 git add vegetables
993 git commit -m vegetables
994
995 git merge --no-edit topic1
996
997 echo Created merge example repository in:
998 echo "$PWD"
999 </pre>
1000
1001 SUBSECTION(«stash.bash»)
1002
1003 <pre>
1004 #!/bin/bash
1005
1006 set -e
1007
1008 GD=$(mktemp -d /tmp/ct-git-XXXXXX)
1009 f='apple-definition'
1010 cd "$GD"
1011 git init
1012
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"
1015
1016 git add "$f"
1017 git commit -m 'initial draft of apple definition'
1018
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"
1023
1024 </pre>
1025
1026 SUBSECTION(«rebase_example.bash»)
1027
1028 <pre>
1029 #!/bin/bash
1030
1031 set -e
1032
1033 GD=$(mktemp -d /tmp/ct-git-XXXXXX)
1034 cd "$GD"
1035 git init
1036 f1='apfelwein'
1037 f2='culture'
1038
1039 echo 'Apfelwein or Most are German words for cider. It is also
1040 regionaly known as Ebbelwoi, Äppler, Stöffsche, Apfelmost Viez,
1041 and saurer Most.
1042 ' > "$f1"
1043 git add "$f1"
1044 git commit -m 'Add initial definition of Ebbelwoi.'
1045
1046 echo '
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.
1050 ' >> "$f1"
1051 git commit -am 'Add section on Speierling.'
1052
1053 git checkout -b 'bembel'
1054 echo '
1055 Apfelwein is served in a "Geripptes", a glass with a lozenge cut that
1056 refracts light and improves grip.
1057 ' > "$f2"
1058 git add "$f2"
1059 git commit -m 'Initial draft of culture file.'
1060
1061 git checkout master
1062 echo '
1063 The juice or must is fermented with yeast to produce an alcoholic
1064 beverage usually around 6% abv.
1065 ' >> "$f1"
1066 git commit -am 'Mention that Apfelwein is an alcoholic beverage.'
1067
1068 git checkout 'bembel'
1069 echo '
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
1072 in many countries.
1073
1074 ' >> "$f2"
1075 git commit -am 'Add section on bembel to culture file.'
1076
1077 sed -i 's/regionaly/regionally/g' "$f1"
1078 git commit -am 'Fix typo in apfelwein section.'
1079
1080 sed -i '/^Most establishments/,$d' "$f2"
1081 echo '
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.
1085 ' >> "$f2"
1086 git commit -am 'Rewrite section on Bembel.'
1087
1088 sed -i 's/bembel/Bembel/g' "$f2"
1089 git commit -am 'Always spell Bembel in upper case.'
1090
1091 echo "cd $GD"
1092 </pre>