-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
1591 lines (1309 loc) · 70 KB
/
index.html
File metadata and controls
1591 lines (1309 loc) · 70 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://code.cdn.mozilla.net/fonts/fira.css">
<meta charset="utf-8">
<title>git gud</title>
<meta name="description" content="A dive into git's internals">
<meta name="author" content="Pieter Moris">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="css/reveal-custom.css">
<link rel="stylesheet" href="css/theme/black-custom.css" id="theme">
<!-- Theme used for syntax highlighting of code -->
<link rel="stylesheet" href="lib/css/zenburn.css">
<!-- Printing and PDF exports -->
<script>
var link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css';
document.getElementsByTagName( 'head' )[0].appendChild( link );
</script>
<!--[if lt IE 9]>
<script src="lib/js/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div class="reveal">
<!-- Any section element inside of this container is displayed as a slide -->
<div class="slides">
<section>
<h1 style="font-weight: 400; font-family:ds-font;">git gud</h1>
<!-- <h3>or (Don't Fear) the CLI</style></h3> -->
<h3>or "How I Learned to Stop Worrying and Love the blob"</h3>
<!-- <h3>or "It's the Final Commit"</h3>
<h3>or "(Don't Fear) the Git"</h3> -->
<p>
<small>Created by Pieter Moris <small>and contributors</small></small>
</p>
</section>
<section>
<section data-menu-title="Git frustrations">
<p>All in all, git is pretty</p>
<div class="sl-block" data-block-type="text">
<div class="sl-block-content" style="transition-duration: 2s; transition-delay: 1s;" data-animation-type="slide-left">
<h1 style="font-family:cursive;"><span class="rainbow">amazing!</span></h1>
</div>
</div>
<br>
<span class="fragment">At least, that's what everyone keeps telling me.</span>
</section>
<section>
<h3>Does this situation sound familiar?</h3>
<img style="border: 0;" height="50%" data-src="assets/img/xkcd-on-git.png" alt="xkcd-git">
</section>
<section>
<img data-src="assets/img/use-git-they-said-itll-be-fun-they-said.jpg" alt="they-said">
</section>
<section>
<p style="margin: 0 0 20px 0;
font-family: 'Fira Sans Light', 'Source Sans Pro', Helvetica, sans-serif;
font-weight: 600;
line-height: 1.2;
letter-spacing: normal;
text-transform: uppercase;
text-shadow: none;
word-wrap: break-word;
font-size: 2em;">
Keep calm</p>
<p>and</p>
<!-- <span class="fragment">and</span> -->
</section>
<section data-background="#000000">
<!-- <audio data-autoplay src="assets/media/you-died.mp3"></audio> -->
<div class="sl-block" data-block-type="text">
<div class="sl-block-content" style="transition-duration: 2.5s; transition-delay: 0.2s;" data-animation-type="fade-in">
<p style="margin: 0 0 20px 0;
font-weight: 600;
line-height: 1.2;
letter-spacing: normal;
text-transform: uppercase;
text-shadow: none;
word-wrap: break-word;
font-size: 2em;
font-weight: 400;
font-family:ds-font;
color:#974551">git gud</p>
</div>
</div>
</section>
<!-- <section>
<audio data-autoplay src="assets/media/you-died.mp3"></audio>
<h1>Keep calm</h1>
<h2 class="fragment scale-down" style="font-weight: 400; font-family:ds-font;">and git gud</h2>
</section>
</section> -->
</section>
<section>
<section data-markdown data-menu-title="Goals of this talk">
<script type="text/template">
### Goals
- Reveal the nuts and bolts that make `git` tick, so that you will feel less intimidated during day-to-day use.
- Make you reassess that XKCD-mindset.
- Provide adequate background knowledge & tools, so that you can explore and digest `git` documentation on your own.
</script>
<aside class="notes">
too much jargon
difficulty to solve problems
common operations hidden by GUIs despite good intentions
</aside>
</section>
<section data-menu-title="Resources and links">
<h5>DISCLAIMER</h5>
<h6>Resources created by people more knowledgeable and witty than I</h6>
<ul style="font-size: 0.4em">
<li>The Pro Git book, contains everything and more: <a href=https://git-scm.com/book/en/v2>https://git-scm.com/book/en/v2</a></li>
<li>A visual <bold>reference</bold> guide for most situations in git: <a href="https://marklodato.github.io/visual-git-guide/index-en.html">https://marklodato.github.io/visual-git-guide/index-en.html</a></li>
<li>For those who prefer audio over text:<ul>
<li>Git from the Bottom Up: <a href=https://jwiegley.github.io/git-from-the-bottom-up/>https://jwiegley.github.io/git-from-the-bottom-up/</a></li>
<li>Git from the inside out: <a href=https://maryrosecook.com/blog/post/git-from-the-inside-out>https://maryrosecook.com/blog/post/git-from-the-inside-out</a></li>
<li>How Git Works - Fear Not The SHA! (gitlab): <a href=https://youtu.be/P6jD966jzlk>https://youtu.be/P6jD966jzlk</a></li>
<li>OSCON 2016: Dissecting Git's Guts - Git Internals - Emily Xie: <a href=https://youtu.be/YUCwr1Y6bFI>https://youtu.be/YUCwr1Y6bFI</a></li>
<li>Advanced Git: Graphs, Hashes, and Compression, Oh My!: <a href=https://youtu.be/ig5E8CcdM9g>https://youtu.be/ig5E8CcdM9g</a></li>
</ul></li>
<li>Visualisations and thinking with graphs:<ul>
<li>A highly recommended guide for the perplexed (advanced beginners): <a href="http://think-like-a-git.net/">http://think-like-a-git.net/</a></li>
<li>Visualizing Git Concepts with D3 (a brilliant resource to get a feel for what different commands actually do!) <a href=https://onlywei.github.io/explain-git-with-d3/>https://onlywei.github.io/explain-git-with-d3/</a></li>
<li>Visualizing Git’s Merkle DAG with D3.js: <a href=https://tylercipriani.com/blog/2016/03/21/Visualizing-Git-Merkle-DAG-with-D3.js/>https://tylercipriani.com/blog/2016/03/21/Visualizing-Git-Merkle-DAG-with-D3.js/</a></li>
<li>Git for Computer Scientists: <a href=http://eagain.net/articles/git-for-computer-scientists/>http://eagain.net/articles/git-for-computer-scientists/</a></li>
<li>Git is a Directed Acyclic Graph and What the Heck Does That Mean?: <a href=https://medium.com/girl-writes-code/git-is-a-directed-acyclic-graph-and-what-the-heck-does-that-mean-b6c8dec65059>https://medium.com/girl-writes-code/git-is-a-directed-acyclic-graph-and-what-the-heck-does-that-mean-b6c8dec65059</a></li>
</ul></li>
</ul>
<p><small>Anytime you experience an insightful "AHA!"-moment, you should probably be praising these people, rather than me. Idem ditto whenever you chuckle.</small></p>
</section>
</section>
<section>
<section data-background-transition="zoom" data-background="#21704b">
<h1>A brief recap of git</h1>
</section>
<section>
<p>TL;DR</p>
<p><a href="https://rogerdudler.github.io/git-guide/">https://rogerdudler.github.io/git-guide/</a></p>
</section>
<section data-menu-title="Git beginner guides">
<h6>A few more resources for the absolute beginner</h6>
<ul style="font-size: 0.6em">
<li>The Pro Git book chapter 1-3: <a href=https://git-scm.com/book/en/v2>https://git-scm.com/book/en/v2</a></li>
<li>A 10 minute read by GitHub: <a href=https://guides.github.com/introduction/git-handbook/>https://guides.github.com/introduction/git-handbook/</a></li>
<li>A very nice and accessible collection of topics by Atlassian (GitBucket): <a href=https://www.atlassian.com/git/tutorials/setting-up-a-repository>https://www.atlassian.com/git/tutorials/setting-up-a-repository</a></li>
</ul>
</section>
<section data-menu-title="Glossary of terms">
<h4>Glossary of terms</h4>
<p style="font-size: 0.85em">Come back to this slide at the end of the presentation.</p>
<ul style="font-size: 0.65em">
<li><strong>Repository</strong>: Archive with snapshots of working directory (commits). Defined by <code>.git</code> directory. Can be local or remote. Contains references to branches (heads), tags and remote branches.</li>
<li><strong>Working tree or directory</strong>: a directory containing a <code>.git</code> folder.</li>
<li><strong>Index or staging area</strong>: a (conceptual) area in between your working directory and repository.</li>
<li><strong>Commit</strong>: a snapshot of your working directory at a specific point in time.</li>
<li><strong>Branch</strong>: a reference/name/pointer/alias for a specific commit.</li>
<li><strong>master</strong>: the default name for your local branch.</li>
<li><strong>origin</strong>: the default name for your main remote repository.</li>
<li><strong>HEAD</strong>: a file pointing to the currently checked-out branch or commit.</li>
</ul>
<p style="font-size: 0.5em">Source: <a href="https://jwiegley.github.io/git-from-the-bottom-up/">https://jwiegley.github.io/git-from-the-bottom-up/</a></p>
</section>
<section>
<h4>git</h4>
<h4>=</h4>
<h4>distributed version control system</h4>
<ul style="font-size: 0.83em">
<li class="fragment"><span style="font-style: italic">Snapshots</span>: keep track of previous versions of files <span style="font-size: 25px">(no more FINAL_final_revised_project3.code files cluttering up your folders)</span>.</li>
<li class="fragment"><span style="font-style: italic">Distributed</span>: mirror your project (and its history) on different machines.
<ul style="font-size: 25px">
<li>There can be many remote repositories, <code>GitHub</code> is just one example.</li>
<li>Allows you to work offline.</li>
</ul></li>
</ul>
</section>
<section data-markdown>
<script type="text/template">
<!-- .slide: style="font-size: 32px" -->
## What's in a name?
* **random three-letter combination** that is pronounceable, and not actually used by any common UNIX command. The fact that it is a mispronunciation of "get" may or may not be relevant.
* **stupid**. contemptible and despicable. simple. Take your pick from the dictionary of slang.
* **"global information tracker"**: you're in a good mood, and it actually works for you. Angels sing, and a light suddenly fills the room.
* **"goddamn idiotic truckload of sh*t"**: when it breaks.
Source: https://github.com/git/git/blob/master/README.md
</script>
</section>
<section>
<p>The following commands are referred to as <br><span class="emphasized">git porcelain</span> commands;<br>the ones the user normally interacts with.</p>
<br>
<p>Later on, we'll encounter the so-called <br><span class="emphasized">git plumbing</span> commands;<br>low-level commands to manipulate and inspect objects.</p>
</section>
<section data-markdown>
<script type="text/template">
<!-- .slide: style="font-size: 35px" -->
## Creation
```sh
# create a new repository
git init
# or retrieve an existing one
git clone username@host:/path/to/repository
```
</script>
</section>
<section data-markdown>
<script type="text/template">
## Tracking changes
```sh
git add file1 file2 # or git add -A
git commit -m "my first commit!"
```
<!-- .element height="30%" width="30%" -->
Source:<!-- .element: style="font-size: 20px" --> https://git-scm.com/about/staging-area<!-- .element: style="font-size: 20px" -->
</script>
<aside class="notes">
Do some work followed by a snapshot or backup
two steps:
- stage or mark changes
- finalise them
</aside>
</section>
<section data-markdown>
<script type="text/template">
## Branches
```sh
git checkout -b feature_x # create and move to branch
#
# do some work
#
git checkout master # hop back to main branch
git merge feature_x # pull in changes
```
 <!-- .element height="50%" width="50%" -->
Source:<!-- .element: style="font-size: 20px" --> https://rogerdudler.github.io/git-guide/<!-- .element: style="font-size: 20px" -->
</script>
<aside class="notes">
branches allow you to work on a separate feature without affecting the original copy
changes made at different points in time can be merged and reconciled
</aside>
</section>
<section data-markdown>
<script type="text/template">
## Sharing
```sh
# sharing your changes
git remote add origin <server>
git push origin master
# retrieving changes
git pull origin master
# or fetch and merge
git fetch origin
git merge master
```
</script>
<aside class="notes">
different repositories that can be synchronised
either online or even to an external hard drive
</aside>
</section>
<section data-background="#dddddd">
<img style="border: 0;" height="50%" data-src="assets/img/git-transport.png" alt="they-said">
<p style="font-size: 20px">Source: <a href="https://blog.osteele.com/2008/05/my-git-workflow/">https://blog.osteele.com/2008/05/my-git-workflow/</a></p>
</section>
<section>
<p>You might have heard that git is represented by a</p>
<h4 style="color:#2f8e5a;">Directed Acyclic Graph (DAG)</h4>
</br>
<p>But what are the nodes and edges of this graph?</p>
<p>And how does it track files?</p>
</section>
<section class="fig-container"
data-fig-id="fig-diagram1"
data-file="assets/d3js/naive-graph.html">
</section>
</section>
<section>
<section data-background-transition="zoom" data-background="#21704b">
<h1>Enter the .git directory</h1>
</section>
<section data-background-video="assets/media/creation2.webm" data-background-size="contain" data-background-video-muted="true" data-background-color="#000000">
<aside class="notes">
.git directory is what defines a repository
created by init
bunch of files, mostly configuration
objects dir is where the magic happens
staged files are referened here
</aside>
</section>
<section>
<p>That file in <pre><code class="sh">cf/bc74af89ccf0d0ddbe488b4a2df7318786759d</code></pre> is what git refers to as a <span class="emphasized">blob</span>.</p>
<br>
<p>Blobs are created when you <code>git add</code> files. They're the most basic building block of git.</p>
<br>
<p class="fragment">But both its name and contents look like nonsense, right?</p>
</section>
</section>
<section>
<section data-background-transition="zoom" data-background="#21704b" data-menu-title="SHA-1">
<h1>two, three,</h1>
<h1>cha, cha, SHA-1?</h1>
</section>
<section>
<h5>Git is a content-addressable filesystem</h5>
</br>
<span class="fragment">
<p>Any kind of content you insert into the repository can be retrieved using a unique key or fingerprint</p>
<p>That key is a <span class="emphasized">SHA-1</span> checksum of the contents of the file <span style="font-size: 30px">(and a short header)</span>.</p>
<p>You've probably encountered these before as the names of your commits.</p>
</span>
</section>
<section data-markdown>
<script type="text/template">
#### SHA-1 is a cryptographic hash function.
Given an input, it provides an output of a fixed size (a hash).
- Deterministic
- One-way
- Few collisions
In git, hashes are usually 40 characters long, but often only the first 7 are needed.
</script>
</section>
</section>
<section>
<section data-background-transition="zoom" data-background="#21704b" data-menu-title="Git objects: blobs">
<h1>Git objects</h1>
<h2>Blobs 🍮</h2>
</section>
<section>
<h4>So what did <code style="font-weight: normal">git add dog</code> achieve?</h4>
<br>
<ul>
<li>New <span class="emphasized">blob</span> file in <code>.git/objects/</code>.</li>
<li>Uniquely named by hashing the file content (and a header).</li>
<li>The first two characters of the 40 character <span class="emphasized">SHA-1</span> digest form a sub-directory.</li>
<li>Remainder forms the file name.</li>
</ul>
<span style="font-size: 20px">Note: the index or stage is also prepped in this step. <a href="#index">More on that later</a>.</span>
</section>
<!-- <section data-markdown>
<script type="text/template">
#### Blobs and plumbing commands
Git provides us with a bunch of tools to inspect and even create blobs ourselves.
```{python}
$ tree .git/objects
.git/objects/
├── cf
│ └── bc74af89ccf0d0ddbe488b4a2df7318786759d
├── info
└── pack
$ git hash-object dog
cfbc74af89ccf0d0ddbe488b4a2df7318786759d
# file contents (and size) produce the hash
$ echo "woof" | git hash-object --stdin
cfbc74af89ccf0d0ddbe488b4a2df7318786759d
$ printf "blob 5\000woof\n" | openssl sha1
(stdin)= cfbc74af89ccf0d0ddbe488b4a2df7318786759d
```
</script>
</section> -->
<section>
<h4>Git provides us with a bunch of plumbing commands to inspect and even create blobs ourselves.</h4>
<pre><code style="font-size:0.58em" class="python" data-trim contenteditable>
$ tree .git/objects
.git/objects/
├── cf
│ └── bc74af89ccf0d0ddbe488b4a2df7318786759d
├── info
└── pack
# Compute the hash of the file in your directory
$ git hash-object dog
cfbc74af89ccf0d0ddbe488b4a2df7318786759d
# ONLY file contents (and size) determine the hash
$ echo "woof" | git hash-object --stdin
cfbc74af89ccf0d0ddbe488b4a2df7318786759d
$ printf "blob 5\000woof\n" | openssl sha1
(stdin)= cfbc74af89ccf0d0ddbe488b4a2df7318786759d
</code></pre>
</section>
<section>
<h4>directed acyclic graph structure</h4>
<img style="border: 0; background: none; width: 200px; height: 200px;" data-src="assets/img/blob.png" alt="blob">
<p style="font-size: 30px">These blob objects form the beginning of our graph.</p>
</section>
<section data-markdown>
<script type="text/template">
#### Blobs and plumbing commands
Git usually only requires a few hash digits to uniquely identify objects.
```sh
# get object type using short identifier
$ git cat-file -t cfbc74a
blob
# read object content
$ git cat-file -p cfbc74a
woof
```
</script>
</section>
<section data-markdown>
<script type="text/template">
#### Blobs and plumbing commands
We couldn't read the contents of the blob directly because files are compressed with zlib first.
```sh
$ python2 -c 'import sys,zlib; \
$ print zlib.decompress(sys.stdin.read());' \
$ < .git/objects/cf/bc74af89ccf0d0ddbe488b4a2df7318786759d
blob 5woof
```
Blob contents: type - bytes - content
</script>
</section>
<section id="fragments">
<p>Every text file with the contents "woof" that you'll ever create in your project (or any future projects) will point to the <span class="emphasized"><em>same blob</em></span>, regardless of its filename.</p>
<p class="fragment">This means that if you'd been following along, you will have ended up with the exact same blob.</p>
<p class="fragment">This is part of what makes git's storage method so efficient. <a href="#storage"><span style="font-size:30px; color:white">But more on that later.</span></a></p>
</section>
<section data-markdown>
<script type="text/template">
You can even manually create git objects in this manner.
```python
$ echo 'miauw' | git hash-object -w --stdin
$ tree .git/objects/
.git/objects/
├── 99
│ └── 809ef5ef2a4458e883f53c0ce55fc9f7061844
├── cf
│ └── bc74af89ccf0d0ddbe488b4a2df7318786759d
├── info
└── pack
```
However, the filename is nowhere to be found.
<!-- However, there are no associated file names for this object yet. -->
That's where <span class="emphasized">trees</span> come into play.
</script>
</section>
</section>
<section>
<section data-background-transition="zoom" data-background="#21704b" data-menu-title="Git objects: trees">
<h1>Git objects</h1>
<h2>Trees 🌳</h2>
</section>
<section>
<p>One of the biggest hurdles to wrapping your head around git, is all of its jargon.</p>
</br>
<span class="fragment">
<p>Whenever you see the term <span class="emphasized"><em>tree</em></span>, just think <span class="emphasized"><em>directory</em></span>.</p>
<span style="font-size: 20px">Note: you might see some people refer to the git graph as a tree as well.</span>
</span>
</section>
<section data-background-video="assets/media/tree.webm" data-background-size="contain" data-background-video-muted="true" data-background-color="#000000">
</section>
<!-- <section>
<video data-autoplay class="contain" data-src="assets/media/tree.webm"></video>
</section> -->
<section style="font-size: 40px">
<h4>Tree objects record the directory structure.</h4>
<pre><code style="font-size: 23px" class="sh" data-trim contenteditable>
$ tree .git/objects
.git/objects
├── 35
│ └── eaf2cfe26d5a30558c7aceaad5fadc72a09164
├── 99
│ └── 809ef5ef2a4458e883f53c0ce55fc9f7061844
├── cf
│ └── bc74af89ccf0d0ddbe488b4a2df7318786759d
├── fa
│ └── b9dd251f10ff00622bfd0f069e98b492d433c8
├── info
└── pack
# view contents of tree object
$ git cat-file -p 35eaf2c
100644 blob cfbc74af89ccf0d0ddbe488b4a2df7318786759d dog
</code></pre>
<p style="font-size: 30px">
Two new files showed up after committing: <code>35eaf2c</code> and <code>fab9dd2</code>.
<br>
The first of these is a so-called tree object.
</p>
</section>
<section>
<h4>Tree objects record the directory structure.</h4>
<pre style="width: 100%"><code style="font-size: 25px" class="sh" data-trim contenteditable>
$ git cat-file -p 35eaf2c
100644 blob cfbc74af89ccf0d0ddbe488b4a2df7318786759d dog
</code></pre>
<ul style="font-size: 30px">
<li>Stored in <code>.git/objects</code> with SHA-1-derived name.</li>
<li>Contents: 1 line with associated mode, type, filename and SHA-1 hash per target node => <em>this is enough to restore any file</em>.</li>
<li>DAG-view: nodes that point to blobs or other trees (i.e. sub-directories).</li>
<li>Trees are created from the current state of the <span class="emphasized">index</span> (more on that later).</li>
<li>Trees are stored whenever a commit is made via <code>git commit</code>.</li>
<li>Trees made up of the same blobs/trees always hash to the same digest (type, size, contents).</li>
</ul>
</section>
<section>
<h4>directed acyclic graph structure</h4>
<p>Blobs record the content of files.</p>
<p>Trees record the directory structure by <em>pointing to blobs</em>.</p>
<img style="border: 0; background: none;" class="stretch" data-src="assets/img/graph-tree.png" alt="graph-tree">
</section>
</section>
<section>
<section data-background-transition="zoom" data-background="#21704b" data-menu-title="Git objects: commits">
<h1>Git objects</h1>
<h2>Commits 💾</h2>
</section>
<section>
<p>We now have a bunch of tree and blob objects, but we haven't yet found a way to:</p>
<br>
<ul>
<li>Record <em>meta-data</em> about the snapshots (who what where?).</li>
<li><em>Traverse</em> these snapshots.</li>
</ul>
<br><br>
<p>The final type of git object, the <span class="emphasized">commit</span>, takes care of this.</p>
</section>
<section>
<pre style="width: 100%"><code style="font-size: 20px" class="sh" data-trim contenteditable>
$ tree .git/objects
.git/objects
├── 35
│ └── eaf2cfe26d5a30558c7aceaad5fadc72a09164
//
├── fa
│ └── b9dd251f10ff00622bfd0f069e98b492d433c8
├── info
└── pack
# view contents of commit object
$ git cat-file -p fab9dd2
tree 35eaf2cfe26d5a30558c7aceaad5fadc72a09164
author Pieter <13552343+pmoris@users.noreply.github.com> 1535631839 +0200
committer Pieter <13552343+pmoris@users.noreply.github.com> 1535631839 +0200
Initial commit
</code></pre>
<ul style="font-size: 30px">
<li>Created alongside the tree object via <code>git commit</code>.</li>
<li>DAG-view: a commit points to a specific tree (or directory states)</li>
<li>Contains author, committer, time stamp and commit message.</li>
<li>Name derived from <span class="emphasized">SHA-1</span> digest of contents <span style="font-size: 25px">(and will thus <em>always</em> be unique</span>).</li>
</ul>
</section>
<section>
<h4>directed acyclic graph structure</h4>
<img style="border: 0; background: none;" class="stretch" data-src="assets/img/graph-commit.png" alt="graph-tree">
</section>
<section>
<p>This gives us three <em>"levels"</em> of git objects:</p>
</br>
<ul style="font-size: 35px">
<li class="fragment">Level 1: <span class="emphasized">Blobs</span> record the content of files. Each new file or change gets its own blob.</li>
<li class="fragment">Level 2: <span class="emphasized">Trees</span> record a snapshot of the <em>staged(!)</em> directory structure; a collection of folders and file revisions, by pointing to blobs.</li>
<li class="fragment">Level 3: <span class="emphasized">Commits</span> point to trees and provide meta-data.</li>
</ul>
</section>
</section>
<section>
<section style="font-size: 35px" data-menu-title="Committing via git plumbing commands">
<h5>Do you recall that <span class="emphasized">cat blob</span> we created manually?</h5>
<p>It's possible, using only <emp>git plumbing commands</emp>, to create a tree object that references it.</p>
<p>It's also possible to manually create a commit object that points to this tree and to notify our repo that this commit exists in our branch, in order to make it reachable.</p>
<br>
<p style="font-size: 25px">You can refer to <a href="https://jwiegley.github.io/git-from-the-bottom-up/1-Repository/4-how-trees-are-made.html">this</a> and <a href="https://git-scm.com/book/en/v2/Git-Internals-Git-Objects">this</a> guide for a full overview.</p>
</section>
<section>
<p>1. Add the file to the staging area (or index).</p>
<pre><code style="font-size: 24px" class="sh" data-trim contenteditable>
# add file to staging area
# - normally handled by `git add`
$ master 1 git update-index --add \
--cacheinfo 100644 \
99809ef5ef2a4458e883f53c0ce55fc9f7061844 cat
# the index references all files and directories that
# will be recorded by the tree
$ master 1 git ls-files --stage
100644 blob 99809ef5ef2a4458e883f53c0ce55fc9f7061844 cat
100644 blob cfbc74af89ccf0d0ddbe488b4a2df7318786759d dog
</code></pre>
</section>
<section>
<p>2. Write the index contents to a tree object.</p>
<pre><code style="font-size: 24px" class="sh" data-trim contenteditable>
# create tree object from index
# - normally handled by `git commit`
$ master ● 1 ✚ 1 git write-tree
a8fd4f7e27f7b943a6b1ae5e84430d56d234526c
# view its contents
$ master ● 1 ✚ 1 git cat-file -p a8fd
100644 blob 99809ef5ef2a4458e883f53c0ce55fc9f7061844 cat
100644 blob cfbc74af89ccf0d0ddbe488b4a2df7318786759d dog
</code></pre>
</section>
<section style="font-size: 30px">
<p>3. Create a new commit object and chain it to the previous commit (parent).</p>
<pre><code style="font-size: 23px" class="python" data-trim contenteditable>
# create commit object - normally handled by `git commit`
$ master ● 1 ✚ 1 echo "2nd commit manual" | \
git commit-tree a8fd4f7 -p fab9dd2
0ed44be76b3ae96cb3fa7e3501f8ba56e488f7f1
# view its contents
$ master ● 1 ✚ 1 git cat-file -p \
0ed44be76b3ae96cb3fa7e3501f8ba56e488f7f1
tree a8fd4f7e27f7b943a6b1ae5e84430d56d234526c
parent fab9dd251f10ff00622bfd0f069e98b492d433c8
author Pieter <13552343+pmoris@users.noreply.github.com> 1535829462 +0200
committer Pieter <13552343+pmoris@users.noreply.github.com> 1535829462 +0200
2nd commit manual
</code></pre>
<p class="fragment">This second commit has an extra line for the previous commit object!</p>
<p class="fragment">We're now ready to see how git keeps track of a project's <em>history</em>.</p>
</section>
<!--
<section>
<p>We're now ready to see how git keeps track of the history of your project.</p>
</section> -->
<section>
<h4>directed acyclic graph structure</h4>
<img style="border: 0; background: none;" class="stretch" data-src="assets/img/graph-manual-noref.png" alt="graph-manual-noref">
<p style="font-size: 30px">By chaining commits, each one pointing to its parent(s), a history is formed.</p>
</section>
<section>
<ul style="font-size: 35px">
<li>Level 1: <span class="emphasized">Blobs</span> record content of files. Each new file or change gets its own blob. <span class="fragment"><strong>Identical blobs are re-used by trees.</strong></span></li>
<li>Level 2: <span class="emphasized">Trees</span> record a snapshot of the directory structure; a collection of folders and file revisions, by pointing to blobs.</li>
<li>Level 3: <span class="emphasized">Commits</span> point to trees, provide meta-data <span class="fragment"><strong>and form a history or timeline by pointing to parent commits.</strong>.</span></li>
</ul>
<br>
<br>
<h5 class="fragment">New commits <strong>always</strong> point to their parents (i.e. backwards in time), never the other way around!<br><span style="font-size: 30px">(cf. <span class="emphasized">directed acyclic graph</span>)</span></h5>
</section>
<section>
<p>At this point, we can recall the history by invoking the <code>log</code> command <em>directly on the new commit</em>.</p>
<pre><code style="font-size: 22px" class="sh" data-trim contenteditable>
$ master ● 1 ✚ 1 git log --stat 0ed44be
commit 0ed44be76b3ae96cb3fa7e3501f8ba56e488f7f1
Author: Pieter <13552343+pmoris@users.noreply.github.com>
Date: Sat Sep 1 21:17:42 2018 +0200
2nd commit manual
cat | 1 +
1 file changed, 1 insertion(+)
commit fab9dd251f10ff00622bfd0f069e98b492d433c8 (HEAD -> master)
Author: Pieter <13552343+pmoris@users.noreply.github.com>
Date: Sat Sep 1 21:14:04 2018 +0200
Initial commit
dog | 1 +
1 file changed, 1 insertion(+)
</code></pre>
</section>
<section>
<p>So far so good, we've <span style="font-size:30px">(almost)</span> successfully reproduced the <span class="emphasized">porcelain</span> command <code>git commit</code>.</p>
<br>
<p class="fragment">But why wouldn't the regular <code>git log</code> command work at this point? And where do branches come into play?</p>
</section>
</section>
<section>
<section data-background-transition="zoom" data-background="#21704b">
<h1>References and branches ⎇</h1>
</section>
<section>
<p>So how does git keep track of what commit we're <em>currently on</em>?</p>
<p class="fragment">The answer is <span class="emphasized">branches</span>!</p>
<p class="fragment">Their nature and behaviour will also become more clear when we look at them from a DAG perspective.</p>
</section>
<section>
<h4>Branches are nothing more than <span class="emphasized">references</span> or pointers or aliases to specific commit objects.</h4>
<br>
<p class="fragment">They provide names for certain points in the graph and allow us to easily access them, instead of having to remember the hash digests of specific commits.</p>
</section>
<section>
<p>Branches reside in...</p>
<pre><code class="sh" data-trim contenteditable>
$ master ● 1 ✚ 1 ls .git/refs/heads/
master
</code></pre>
<br>
<p>And are simply <span class="emphasized">plain text files</span> pointing to a commit.</p>
<pre><code class="sh" data-trim contenteditable>
$ master ● 1 ✚ 1 cat .git/refs/heads/master
fab9dd251f10ff00622bfd0f069e98b492d433c8
</code></pre>
</section>
<!-- <section>
<h4>directed acyclic graph structure</h4>
<img style="border: 0; background: none;" class="stretch" data-src="assets/img/graph-master.png" alt="graph-master">
<p>Currently our branch is still pointing to our initial commit object.</p>
</section> -->
<section>
<h4>directed acyclic graph structure</h4>
<img style="border: 0; background: none;" class="stretch" data-src="assets/img/graph-master-manual.png" alt="graph-master">
<p style="font-size: 35px">The master branch is pointing to the initial commit that we created using the regular <span class="emphasized">porcelain</span> command <code>git commit</code>.</p>
<!-- <p>These are the objects we created using the <span class="emphasized">plumbing</span> commands.</p> -->
</section>
<section>
<p style="font-size: 30px">We can update the master reference to point to the new commit.</p>
<pre style="width: 100%"><code style="font-size: 23px" class="sh" data-trim contenteditable>
# change ref file for master branch to a new commit object
$ master ● 1 ✚ 1 git update-ref refs/heads/master 0ed44be
$ master ✚ 1 cat .git/refs/heads/master
0ed44be76b3ae96cb3fa7e3501f8ba56e488f7f1
$ master ✚ 1 git log
commit 0ed44be76b3ae96cb3fa7e3501f8ba56e488f7f1 (HEAD -> master)
Author: Pieter <13552343+pmoris@users.noreply.github.com>
Date: Sat Sep 1 21:17:42 2018 +0200
2nd commit manual
commit fab9dd251f10ff00622bfd0f069e98b492d433c8
Author: Pieter <13552343+pmoris@users.noreply.github.com>
Date: Sat Sep 1 21:14:04 2018 +0200
Initial commit
</code></pre>
<p class="fragment" style="font-size: 30px">Normally, this moving of the reference branch happens behind the scenes when we use the <span class="emphasized">porcelain</span> command <code>git commit</code>.</p>
<!-- <p class="fragment" style="font-size: 30px">This is the final aspect of what happens behind the scenes when we use the <span class="emphasized">porcelain</span> command <code>git commit</code>.</p> -->
</section>
<section>
<h4>directed acyclic graph structure</h4>
<img style="border: 0; background: none;" class="stretch" data-src="assets/img/graph-manual-updated.png" alt="graph-manual-updated">
</section>
<section>
<p>Let's create a new branch now to see how it affects the graph.</p>
</section>
<section>
<pre><code style="font-size: 24px" class="sh" data-trim contenteditable>
# Retrieve the cat object from our repository
# and place it in the working directory
# Why? the file never existed except as a blob
$ master ✚ 1 git cat-file -p 99809ef5 > cat
# Create new branch
$ master git checkout -b "no-cats-allowed"
Switched to a new branch 'no-cats-allowed'
# Check references
$ no-cats-allowed ✚ 1 cat .git/refs/heads/no-cats-allowed
0ed44be76b3ae96cb3fa7e3501f8ba56e488f7f1
# Check current commit
$ no-cats-allowed ✚ 1 git rev-parse HEAD
0ed44be76b3ae96cb3fa7e3501f8ba56e488f7f1
# or just use git log
</code></pre>
<p style="font-size: 35px">Creating a new branch merely adds a reference to the same commit that we were on before. It is literally <span class="emphasized">just a text file</span>.</p>
</section>
<section>
<h4>directed acyclic graph structure</h4>
<img style="border: 0; background: none;" class="stretch" data-src="assets/img/graph-branch.png" alt="graph-branch">
</section>
<section>
<h4>Let's diverge the branch</h4>
<pre><code class="sh" data-trim contenteditable>
$ no-cats-allowed git rm cat
rm 'cat'
$ no-cats-allowed ● 1 mkdir doge
$ no-cats-allowed ● 1 echo "bark" > doge/much
$ no-cats-allowed ● 1 … 1 echo "floof" > doge/very
$ no-cats-allowed ● 1 … 1 git add doge/
$ no-cats-allowed ● 3 git status
On branch no-cats-allowed
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: cat
new file: doge/much
new file: doge/very
</code></pre>
</section>
<section>
<h4>New commit</h4>
<pre><code class="sh" data-trim contenteditable>
$ no-cats-allowed ● 3 git commit -m "doggies"
[no-cats-allowed 40da2ef] doggies
3 files changed, 2 insertions(+), 1 deletion(-)
delete mode 100644 cat
create mode 100644 doge/much
create mode 100644 doge/very
$ no-cats-allowed git rev-parse HEAD
40da2ef175b6693c785251467946f1cdaf5e6552
$ no-cats-allowed git cat-file -p HEAD
tree 60c51895339b14261e18cb4555b4a43d1cfdc397
parent 0ed44be76b3ae96cb3fa7e3501f8ba56e488f7f1
author Pieter <13552343+pmoris@users.noreply.github.com> 1535872422 +0200
committer Pieter <13552343+pmoris@users.noreply.github.com> 1535872422 +0200
doggies
</code></pre>
</section>
<section>
<h4>directed acyclic graph structure</h4>
<img style="border: 0; background: none;" class="stretch" data-src="assets/img/graph-branch2.png" alt="graph-branch2">
</section>
</section>
<section>
<section data-background-transition="zoom" data-background="#21704b">
<h1>Don't lose your <em>HEAD</em></h1>
</section>
<section>
<p>How does git know which working directory to show us and which branch to operate on when we use porcelain commands like <code>git commit</code>?</p>
</br>
<p class="fragment">That's where <span class="emphasized">HEAD</span> comes into play.</p>
</section>
<section>
<pre><code style="font-size:22px" class="sh" data-trim contenteditable>
# HEAD points to a ref or branch name
$ no-cats-allowed cat .git/HEAD
ref: refs/heads/no-cats-allowed
# the branch references a commit
$ no-cats-allowed cat .git/refs/heads/no-cats-allowed
40da2ef175b6693c785251467946f1cdaf5e6552
# shorthand for commit id
$ no-cats-allowed git rev-parse HEAD
40da2ef175b6693c785251467946f1cdaf5e6552
# shorthand for commit contents
$ no-cats-allowed git cat-file -p HEAD
tree 60c51895339b14261e18cb4555b4a43d1cfdc397
parent 0ed44be76b3ae96cb3fa7e3501f8ba56e488f7f1
author Pieter <13552343+pmoris@users.noreply.github.com> 1535872422 +0200
committer Pieter <13552343+pmoris@users.noreply.github.com> 1535872422 +0200
doggies
</code></pre>
<p class="fragment" style="font-size: 35px">This is the final aspect of what happens behind the scenes when we use the <span class="emphasized">porcelain</span> command <code>git commit</code>.</p>
</section>
<section>
<h4>HEAD...</h4>
<ul>
<li>Is a flat text file in the <code>.git</code> directory.</li>
<li>Points to the current branch (ref), i.e. it's a label for a specific commit.</li>
<li>Is updated whenever we <code>commit</code> or <code>checkout</code> a branch (or commit).</li>
</ul>
<!-- <br><br>
<p class="fragment" style="font-size: 35px">More slightly confusing jargon: “head” refers to any one of the named refs in the repository; “HEAD” refers to the currently active one.</p> -->
</section>