-
Notifications
You must be signed in to change notification settings - Fork 0
/
slides.tex
859 lines (780 loc) · 30.1 KB
/
slides.tex
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
\documentclass{beamer}
\mode<presentation>
{ \usetheme{CambridgeUS} }
\AtBeginSection[]
{
\begin{frame}
\frametitle{Outline}
\tableofcontents[currentsection]
\end{frame}
}
\usepackage{graphicx}
\usepackage{textcomp}
\usepackage{tikz}
\title{Understanding Git}
\author{Nelson Elhage\and Anders Kaseorg}
\institute[SIPB]{Student Information Processing Board}
\date{October 21, 2008}
\newcommand{\sh}[1]{\$ {\color{beamer@blendedblue}#1}}
\begin{document}
\begin{frame}
\titlepage
\end{frame}
\section{The Git model}
\begin{frame}
\frametitle{The Git model}
\begin{itemize}
\item A Git repository contains four kinds of \emph{objects}.
\item An object is either a \emph{blob} (file), a \emph{tree}
(directory), a \emph{commit} (revision), or a \emph{tag}.
\item Every object is uniquely identified by a 40 hex digit number,
which is the SHA-1 hash of its contents.
\begin{itemize}
\item Don't worry---identifiers can be abbreviated by truncation,
or referenced with human-readable names.
\end{itemize}
\item Some objects refer to other objects using their identifiers.
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Objects}
\begin{itemize}
\item A blob object is a file's contents.
\item A tree object is a directory---a list of zero or more
directory entries, each of which has
\begin{itemize}
\item a \emph{name}
\item a UNIX \emph{mode}
\item a tree id or blob id
\end{itemize}
\item A commit object contains
\begin{itemize}
\item a tree id
\item zero or more \emph{parents}, which are commit ids
\item an \emph{author} (name, email, date)
\item a \emph{committer} (name, email, date)
\item a \emph{log message}
\end{itemize}
\item A tag object contains
\begin{itemize}
\item a \emph{tag name}
\item a \emph{tagger} (name, email, date)
\item a reference to another object (usually a commit)
\item an optional \emph{log message}
\end{itemize}
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{A commit}
\includegraphics[width=12cm]{commit}
\end{frame}
\begin{frame}
\frametitle{More commits}
\includegraphics[width=12cm]{prctl}
\end{frame}
\begin{frame}
\frametitle{A Git repository}
\begin{itemize}
\item A Git repository is a collection of
\emph{refs}---\emph{branches} and \emph{tags}. (Branches are also
known as \emph{heads}.)
\item A ref is a named mutable pointer to an object (usually a
commit).
\begin{itemize}
\item \texttt{HEAD} $\to$ \texttt{refs/heads/master}
\item \texttt{refs/heads/master} $\to$ \texttt{commit fec6ed\ldots}
\item \texttt{refs/heads/ftrace} $\to$ \texttt{commit ce5c1e\ldots}
\item \texttt{refs/tags/v2.6.8} $\to$ \texttt{commit e8ce2f\ldots}
\item \texttt{refs/tags/v2.6.27} $\to$ \texttt{tag 4b5127\ldots}
\end{itemize}
\item The repository automatically stores the directed acyclic graph
of objects rooted at these refs.
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Branches}
\begin{itemize}
\item Git was designed to enable lightweight branching and merging.
\item Each repository can have any number of branches.
\item Branches are just refs---pointers into the DAG of
commits---and these pointers themselves are not versioned.
\begin{itemize}
\item So you don't need to be afraid of making throwaway branches
for experiments.
\end{itemize}
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Consequences of the Git model}
\begin{itemize}
\item Git tracks the history of your whole project, not the history
of individual files.
\begin{itemize}
\item Best practice is to keep projects that are logically
separate in separate Git repositories.
\end{itemize}
\item Git does not track renames as metadata in the repository.
\begin{itemize}
\item Instead, renames are automatically detected based on content
when this information is needed.
\end{itemize}
\item A commit ID cryptographically certifies the integrity of the
\emph{entire history} of the repository up to that commit.
\begin{itemize}
\item Git has powerful tools for rewriting history---but this
requires communication with everyone that has pulled any
affected commits from your repository.
\end{itemize}
\end{itemize}
\end{frame}
\section{Using Git}
\begin{frame}
\frametitle{Getting a Git repository}
\begin{description}[\texttt{git clone \textit{url}}]
\item[\texttt{git init}\hfill] Create an empty Git repository in the
current directory. By default it will have one branch named
\texttt{master}.
\item[\texttt{git clone \textit{url}}\hfill] Clone the Git
repository from \texttt{\textit{url}}. This may be over HTTP,
SSH, or the Git protocol, or it may be a path to another local
repository.
\end{description}
Both of these operations will create a \emph{working copy}.
\end{frame}
\begin{frame}
\frametitle{Working copy}
\begin{itemize}
\item Every working copy has its own Git repository in the
\texttt{.git} subdirectory (with arbitrarily many branches and
tags).
\begin{itemize}
\item The most important ref is \texttt{HEAD}, which refers to the
current branch.
\end{itemize}
\item The \texttt{.git} subdirectory also stores the \emph{index}: a
staging area for changes on top of \texttt{HEAD} that will become
part of the next commit.
\item Finally, the files outside of \texttt{.git} are the
\emph{working tree}.
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Git workflow}
\begin{itemize}
\item Changes made to the working tree can be \emph{added} to the
index.
\item The index can be \emph{committed} to the current branch (where
it will then become the new \texttt{HEAD}).
\end{itemize}
\begin{center}
\includegraphics[width=9cm]{index}
\end{center}
\end{frame}
\begin{frame}
\frametitle{Constructing commits}
\begin{description}[\texttt{git checkout \textit{file}}]
\item[\texttt{git add \textit{file}}\hfill] Add or update
\texttt{\textit{file}} from the working tree into the index.
\item[\texttt{git reset \textit{file}}\hfill] Unstage changes to
\texttt{\textit{file}} in the index, without touching the working
tree.
\item[\texttt{git checkout \textit{file}}\hfill] Undo modifications
to \texttt{\textit{file}} in the working tree by reading it back
from the index.
\item[\texttt{git rm \textit{file}}\hfill] Delete
\texttt{\textit{file}} from the index and the working tree.
\item[\texttt{git mv \textit{oldfile} \textit{newfile}}\hfill]
Shortcut for \texttt{mv \textit{oldfile} \textit{newfile}} plus
the appropriate additions and removals in the index.
\item[\texttt{git status}\hfill] Display the files changed in the
index and in the working tree.
\item[\texttt{git commit}\hfill] Make a commit out of the current
index.
\item[\texttt{git commit -a}\hfill] Shortcut for adding all modified
files to the index and committing.
\end{description}
\end{frame}
\begin{frame}
\frametitle{Referring to objects}
\begin{description}[\texttt{\textit{commit}\^{}2}]
\item[\texttt{fc8da7a06bb66b707e7f5406657d5a3b7ee42c66}\hfill] You
can always refer to an object by its full SHA-1 ID, but this gets
unwieldy very quickly.
\item[\texttt{fc8da7}\hfill] You can use a truncated SHA-1 as long
as it is unambiguous.
\item[\texttt{\textit{refname}}\hfill] You can refer to a branch or
tag by name.
\item[\texttt{\textit{commit}\^{}}\hfill] Append a \texttt{\^{}} to
get the (first) parent of a commit.
\item[\texttt{\textit{commit}\^{}2}\hfill] The second parent of a
commit, etc.
\item[\texttt{\textit{commit}\~{}4}\hfill] Short for
\texttt{\textit{commit}\^{}\^{}\^{}\^{}}---the
great-great-grandparent of a commit.
\item[\texttt{\textit{commit}:\textit{filename}}\hfill] The given
file or directory inside \texttt{\textit{commit}}'s tree.
\end{description}
\dots and more (see \texttt{git help rev-parse} for a full
description of the syntax).
\end{frame}
\begin{frame}
\frametitle{Displaying changes}
\begin{description}[\texttt{git diff --cached}]
\item[\texttt{git log}\hfill] List the commits on the current
branch.
\item[\texttt{git show \textit{object}}\hfill] Show an object (e.g.\
the log information and patch for a commit, or the contents of a
file).
\item[\texttt{git diff}\hfill] Show the differences between the
index and the working tree.
\item[\texttt{git diff --cached}\hfill] Show the differences between
\texttt{HEAD} and the index.
\item[\texttt{git diff \textit{commit}}\hfill] Show the differences
between \textit{commit} and the working tree.
\end{description}
\end{frame}
\begin{frame}
\frametitle{Manipulating branches and tags}
\begin{description}[\texttt{git branch -d \textit{branch}}]
\item[\texttt{git branch}\hfill] List the branches in your
repository, with the current branch highlighted.
\item[\texttt{git checkout \textit{branch}}\hfill] Switch to the
branch named \texttt{\textit{branch}}. This updates
\texttt{HEAD}, the index, and the working tree.
\item[\texttt{git checkout -b \textit{branch}
[\textit{commit}]}\hfill] Create a new branch named
\texttt{\textit{branch}} starting at \texttt{\textit{commit}}
(defaulting to current \texttt{HEAD}), and switch to it.
\item[\texttt{git branch -d \textit{branch}}\hfill] Delete the
branch \texttt{\textit{branch}}.
\item[\texttt{git branch -m \textit{oldbranch}
\textit{newbranch}}\hfill] Rename \texttt{\textit{oldbranch}} to
\texttt{\textit{newbranch}}.
\item[\texttt{git tag \textit{tag} [\textit{commit}]}\hfill] Attach
a new tag named \texttt{\textit{tag}} to \texttt{\textit{commit}}
(defaulting to current \texttt{HEAD}).
\item[\texttt{git tag -d \textit{tag}}\hfill] Delete the tag named
\texttt{\textit{tag}}.
\end{description}
\end{frame}
\begin{frame}[fragile]
\frametitle{Configuration hints}
\begin{itemize}
\item You should tell Git who you are:
\begin{semiverbatim}
\sh{git config --global user.name "\textit{Your Name}"}
\sh{git config --global user.email "\textit{your@email.edu}"}
\end{semiverbatim}
\item And, if you're feeling colorful,
\begin{semiverbatim}
\sh{git config --global color.ui auto}
\end{semiverbatim}
(This configuration is stored in \texttt{\~{}/.gitconfig}.)
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Merging}
\begin{description}[\texttt{git merge \textit{commit}}]
\item[\texttt{git merge \textit{commit}}\hfill] Merge
\texttt{\textit{commit}} into \texttt{HEAD}. The index must not
contain any staged changes.
\end{description}
\begin{itemize}
\item In the general case, this will result in a \emph{merge
commit}---a commit with more than one parent.
\begin{center}
\includegraphics[width=4cm]{merge}
\end{center}
\item If \texttt{\textit{commit}} is an ancestor of \texttt{HEAD},
then the merge is a no-op.
\item If \texttt{\textit{commit}} is a descendent of \texttt{HEAD},
then the merge degenerates into a \emph{fast-forward}.
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Resolving merge conflicts}
\begin{itemize}
\item \texttt{git merge} works roughly by creating a diff against
the common ancestor commit, and applying it against the current
\texttt{HEAD}. (The general case is much more complicated.)
\item Sometimes this patch will not apply to the current
\texttt{HEAD}. This situation is called a \emph{merge conflict}.
\begin{itemize}
\item Git will respond by inserting \emph{conflict markers} into
the conflicted files, and asking you resolve the conflict.
\item Don't panic!
\item To resolve the conflict, edit the conflicted files
appropriately and then \texttt{git add} them.
\item Alternatively, you can run \texttt{git mergetool} to resolve
the conflicts interactively in a graphical diff program.
\end{itemize}
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\frametitle{Merging example}
\begin{tikzpicture}
\useasboundingbox (0, 0) rectangle (12, 7);
\begin{scope}
\clip (0, 0) rectangle (12, 7);
\draw (0, 0) node[anchor=south west,inner sep=0pt] {\vbox{\footnotesize
\begin{semiverbatim}
\only<1->{\sh{seq 5 > numbers}
}\only<2->{\sh{git init}
Initialized empty Git repository in /tmp/foo/.git/
}\only<3->{\sh{git add numbers}
}\only<4->{\sh{git commit -m '1, 2, 3, 4, 5!'}
Created initial commit 4172330: 1, 2, 3, 4, 5!
1 files changed, 5 insertions(+), 0 deletions(-)
create mode 100644 numbers
}\only<5->{\sh{git checkout -b andersk}
Switched to a new branch "andersk"
}\only<6->{\sh{git branch}
* {\color{green}andersk}
master
}\only<7->{\sh{(echo 0; cat numbers) | sponge numbers}
}\only<8->{\sh{git diff}
\textbf{diff --git a/numbers b/numbers
index 8a1218a..e8371f0 100644
--- a/numbers
+++ b/numbers}
{\color{cyan}@@ -1,3 +1,4 @@}
{\color{green}+0}
1
2
3
}\only<9->{\sh{git add numbers}
}\only<10->{\sh{git commit -m 'Numbers start at 0.'}
Created commit 7aeb494: Numbers start at 0.
1 files changed, 1 insertions(+), 0 deletions(-)
}\only<11->{\sh{git checkout master}
Switched to branch "master"
}\only<12->{\sh{echo 6 >> numbers}
}\only<13->{\sh{git add numbers}
}\only<14->{\sh{git commit -m '6 is a number too.'}
Created commit 383c158: 6 is a number too.
1 files changed, 1 insertions(+), 0 deletions(-)
}\only<15->{\sh{git merge andersk}
Auto-merged numbers
Merge made by recursive.
numbers | 1 {\color{green}+}
1 files changed, 1 insertions(+), 0 deletions(-)
}\only<16->{\sh{cat numbers}
0
1
2
3
4
5
6
}\only<17->{\sh{git checkout andersk}
Switched to branch "andersk"
}\only<18->{\sh{echo 5\textonehalf >> numbers}
}\only<19->{\sh{git add numbers}
}\only<20->{\sh{git commit -m '5\textonehalf is a better number.'}
Created commit 5360c2d: 5\textonehalf is a better number.
1 files changed, 1 insertions(+), 0 deletions(-)
}\only<21->{\sh{git checkout master}
Switched to branch "master"
}\only<22->{\sh{git merge andersk}
Auto-merged numbers
CONFLICT (content): Merge conflict in numbers
Automatic merge failed; fix conflicts and then commit the result.
}\only<23->{\sh{git status}
numbers: needs merge
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
#
# {\color{red}unmerged: numbers}
#
no changes added to commit (use "git add" and/or "git commit -a")
}\only<24->{\sh{git mergetool}
Merging the files: numbers
Normal merge conflict for 'numbers':
{local}: modified
{remote}: modified
Hit return to start merge resolution tool (meld):
}\only<26->{\sh{cat numbers}
0
1
2
3
4
5
5\textonehalf
6
}\only<27->{\sh{git status}
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# {\color{green}modified: numbers}
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# {\color{red}numbers.orig}
}\only<28->{\sh{git commit}
Created commit fc8da7a: Merge branch 'andersk'
}
\end{semiverbatim}
\vspace{-2em}}};
\end{scope}
\draw (12.5, 8.2) node[anchor=north east] {
\only<4>{\includegraphics[width=8cm]{merge1}}%
\only<5-9>{\includegraphics[width=8cm]{merge2}}%
\only<10>{\includegraphics[width=8cm]{merge3}}%
\only<11-13>{\includegraphics[width=8cm]{merge4}}%
\only<14>{\includegraphics[width=8cm]{merge5}}%
\only<15-16>{\includegraphics[width=8cm]{merge6}}%
\only<17-19>{\includegraphics[width=8cm]{merge7}}%
\only<20>{\includegraphics[width=8cm]{merge8}}%
\only<21-27>{\includegraphics[width=8cm]{merge9}}%
\only<28>{\includegraphics[width=8cm]{merge10}}%
};
\only<25>{\draw (current bounding box.center) node {\includegraphics[width=11.5cm]{meld}};}
\end{tikzpicture}
\end{frame}
\begin{frame}
\frametitle{Getting out of trouble}
\begin{description}[\texttt{git reset --hard \textit{commit}}]
\item[\texttt{gitk HEAD --all}\hfill] The graphical repository browser is
immensely useful for visualizing what's going on in your
repository.
\item[\texttt{git reflog}\hfill] Show the \emph{reflog} entries for
\texttt{HEAD}.
\item[\texttt{git reflog show \textit{ref}}\hfill] Show the
\emph{reflog} entries for \texttt{\textit{ref}}.
\item[\texttt{git reset --hard \textit{commit}}\hfill] Resets the
\emph{ref} pointed to by \texttt{HEAD}, as well as the index and
working tree, to \texttt{\textit{commit}}.
\end{description}
\begin{itemize}
\item The reflog tracks all local changes to refs. Whenever a ref
is updated to point at a new commit, it gets an entry in the
reflog.
\item If you find yourself somewhere you don't expect, you can
examine the log or the reflog, and then use \texttt{reset} to get
back to a known point.
\item This works even in a conflicted merge or rebase, if you just
want to bail out and try something different.
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\frametitle{A peek at the reflog}
{\footnotesize
\begin{semiverbatim}
\sh{git reflog}
{\color{olive}fc8da7a...} HEAD@{0}: commit (merge): Merge branch 'andersk'
{\color{olive}994be80...} HEAD@{1}: checkout: moving from andersk to master
{\color{olive}5360c2d...} HEAD@{2}: commit: 5\textonehalf is a better number.
{\color{olive}7aeb494...} HEAD@{3}: checkout: moving from master to andersk
{\color{olive}994be80...} HEAD@{4}: merge andersk: Merge made by recursive.
{\color{olive}383c158...} HEAD@{5}: commit: 6 is a number too.
{\color{olive}4172330...} HEAD@{6}: checkout: moving from andersk to master
{\color{olive}7aeb494...} HEAD@{7}: commit: Numbers start at 0.
{\color{olive}4172330...} HEAD@{8}: checkout: moving from master to andersk
\sh{git reflog show master}
{\color{olive}fc8da7a...} master@{0}: commit (merge): Merge branch 'andersk'
{\color{olive}994be80...} master@{1}: merge andersk: Merge made by recursive.
{\color{olive}383c158...} master@{2}: commit: 6 is a number too.
{\color{olive}4172330...} master@{3}: commit (initial): 1, 2, 3, 4, 5!
\sh{git reflog show andersk}
{\color{olive}5360c2d...} andersk@{0}: commit: 5\textonehalf is a better number.
{\color{olive}7aeb494...} andersk@{1}: commit: Numbers start at 0.
{\color{olive}4172330...} andersk@{2}: branch: Created from HEAD
\end{semiverbatim}}
\end{frame}
\begin{frame}
\frametitle{Cherry-picking and reverting}
\begin{description}[\texttt{git cherry-pick \textit{commit}}]
\item[\texttt{git cherry-pick \textit{commit}}\hfill] Constructs a
new commit on \texttt{HEAD} that performs the same changes as
\texttt{\textit{commit}}.
\item[\texttt{git revert \textit{commit}}\hfill] Constructs a new
commit on \texttt{HEAD} that performs the reverse of the changes
in \texttt{\textit{commit}}.
\end{description}
\begin{itemize}
\item These commands construct a new commit that does not preserve
any parent information pointing back to the old one. Use with
care.
\item Instead of cherry-picking from your development branch into
your stable branch, for example, it is usually better to make the
commit on stable and merge the entire stable branch into
development.
\end{itemize}
\end{frame}
\section{Collaboration with Git}
\begin{frame}
\frametitle{Collaboration with Git}
\begin{itemize}
\item Git allows bidirectional communication between any pair of
repositories.
\item Git speaks many protocols.
\begin{itemize}
\item SSH
\item HTTP/HTTPS
\item DAV
\item Git protocol
\item rsync
\item direct filesystem access
\end{itemize}
\item This flexibility lets you implement a wide range of
centralized or distributed development models.
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{The simple case}
\begin{itemize}
\item A freshly cloned repository has one remote called
\texttt{origin}, which is the default source for pulls and
destination for pushes.
\end{itemize}
\begin{description}[\texttt{git branch -r}]
\item[\texttt{git fetch}\hfill] Download commits from
\texttt{origin}. Each remote branch \texttt{\textit{branch}} will
be made available with the name \texttt{origin/\textit{branch}}.
\item[\texttt{git branch -r}\hfill] List the available remote
branches.
\item[\texttt{git branch -a}\hfill] List the available local and
remote branches.
\end{description}
\begin{itemize}
\item Development is done on local branches. To work on a remote
branch, you first create a local \emph{tracking branch}, and then
push any changes back to the remote branch as a separate
operation.
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Tracking branches}
\begin{description}[\texttt{git push origin :\textit{branch}}]
\item[\texttt{git checkout -b \textit{branch}
origin/\textit{branch}}] Create and switch to a new tracking
branch named \texttt{\textit{branch}}, set up to track the remote
branch \texttt{origin/\textit{branch}}.
\item[\texttt{git pull}\hfill] Update the current tracking branch
from \texttt{origin/\textit{branch}}. Short for \texttt{git
fetch; git merge origin/\textit{branch}}.
\item[\texttt{git push}\hfill] Push the current tracking branch back
to \texttt{origin/\textit{branch}}. This will only fast-forward
the remote branch by default, so you may need to \texttt{git pull}
first.
\item[\texttt{git push origin :\textit{branch}}\hfill] Delete the
remote branch \texttt{\textit{branch}}.
\item[\texttt{git remote prune origin}\hfill] Clean up any refs to
branches that have been deleted remotely.
\end{description}
\end{frame}
\begin{frame}[fragile]
\frametitle{Remotes}
\begin{itemize}
\item A Git repository can be configured with references to any
number of \emph{remotes}.
\item By default, a newly cloned repository has one remote named
\texttt{origin} pointing to the source of the clone.
\end{itemize}
\begin{footnotesize}
\begin{semiverbatim}
\sh{git clone /mit/andersk/Public/git/nss_nonlocal.git}
Initialized empty Git repository in /tmp/nss_nonlocal/.git/
\sh{cat nss_nonlocal/.git/config}
\dots
[remote "origin"]
url = /mit/andersk/Public/git/nss_nonlocal.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
\end{semiverbatim}
\end{footnotesize}
\end{frame}
\begin{frame}
\frametitle{Hosting a public Git repository}
\begin{itemize}
\item A repository that's used for cloning, pulling, and pushing
should usually be a \emph{bare repository} (\texttt{git clone
--bare}). A bare repository has no working tree, and lives in a
directory named \texttt{\textit{project}.git} instead of
\texttt{\textit{project}/.git}.
\item The quickest solution at MIT is to drop your repository into
AFS.
\item To serve a repository on the web, you need to run \texttt{git
update-server-info}, and enable the \texttt{hooks/post-update}
hook.
\item To serve a repository via the Git protocol, you need to create
the \texttt{git-daemon-export-ok} file inside it.
\begin{itemize}
\item \texttt{scripts.mit.edu} provides a Git hosting service.
Drop your repository into
\texttt{/mit/\textit{locker}/Scripts/git/\textit{project}.git}
and access it at
\texttt{git://\textit{locker}.scripts.mit.edu/\textit{project}.git}.
\end{itemize}
\end{itemize}
\end{frame}
\section{Rewriting history}
\begin{frame}
\frametitle{Rewriting history}
\begin{itemize}
\item Git includes powerful tools for rewriting history.
\item Of course, since modifying a commit changes its SHA-1
identifier, by ``rewriting history'' we actually mean
``transforming a sequence of commits into a different sequence of
commits''.
\item You need to be careful about rewriting commits that others may
have already pulled.
\begin{itemize}
\item By default, Git will prevent you from pushing changes that
are not fast-forwards, unless you ask very hard.
\end{itemize}
\item Rewriting is extremely useful for cleaning up a private branch
before making it publicly available.
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Why rewriting is useful}
\begin{itemize}
\item A good history will include one commit for each self-contained
logical change to the tree.
\item Avoid cluttering the history with typos and trivial bugs that
are fixed in the following commits.
\begin{itemize}
\item This makes things more pleasant for anyone who wants to read
or review your changes.
\item It also makes it easier to pinpoint bugs with \texttt{git
bisect}.
\end{itemize}
\item You don't need to worry about making your commits perfect as
you write them, since you can rearrange them later.
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Resetting branches}
\begin{description}[\texttt{git reset --hard \textit{commit}}]
\item[\texttt{git reset --hard \textit{commit}}\hfill] Resets the
current \texttt{HEAD}, as well as the index and working tree, to
\texttt{\textit{commit}}.
\item[\texttt{git reset \textit{commit}}\hfill] Resets the current
\texttt{HEAD} and index to \textit{commit}, without touching the
working tree.
\item[\texttt{git reset --soft \textit{commit}}\hfill] Resets the
current \texttt{HEAD} to \textit{commit}, without touching the
index or the working tree.
\item[\texttt{git commit --amend}\hfill] Adds the modifications in
the index to the current commit at \texttt{HEAD} ``in place''.
Approximately equivalent to \texttt{git reset
HEAD\textasciicircum; git commit}.
\end{description}
\end{frame}
\begin{frame}
\frametitle{Rebasing}
\begin{description}[\texttt{git rebase \textit{commit}}]
\item[\texttt{git rebase \textit{commit}}\hfill] Rebase
\texttt{HEAD} onto \texttt{\textit{commit}}.
\item[\texttt{git pull --rebase}\hfill] Short for \texttt{git fetch;
git rebase origin/\textit{branch}}.
\end{description}
\begin{itemize}
\item \texttt{rebase} finds all commits that are in \texttt{HEAD}
but not in \texttt{\textit{commit}}, and re-applies them starting
with \texttt{\textit{commit}}. The current branch is reset to the
result.
\item This has a similar effect to a merge, but maintains a linear
history, at the cost of losing some information.
\item \texttt{rebase} \emph{changes the object identifiers} of the
re-applied commits.
\item \texttt{rebase} is often preferred to keep history clean.
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Rebase vs.\ merge}
\begin{itemize}
\only<1>{\item We have development on both a \emph{topic branch} and
\texttt{master}.}
\only<2>{\item \texttt{merge} results in a forked history:}
\only<3>{\item \texttt{rebase} rewrites commits and maintains a
linear history:}
\end{itemize}
\begin{center}
\only<1>{\includegraphics[width=5cm]{rebase1}}
\only<2>{\includegraphics[width=5cm]{rebase2}}
\only<3>{\includegraphics[width=5cm]{rebase3}}
\end{center}
\end{frame}
\begin{frame}
\frametitle{Interactive rebasing}
\begin{description}[\texttt{git rebase -i \textit{commit}}]
\item[\texttt{git rebase -i \textit{commit}}\hfill] Rebase
\texttt{HEAD} onto \texttt{\textit{commit}}, letting you
interactively edit the resulting history. (Typically
\texttt{\textit{commit}} will already be an ancestor of
\texttt{HEAD}, to edit history ``in place''.)
\end{description}
\begin{itemize}
\item Git will start your editor on a list of the commits to be
applied on top of \textit{commit}.
\item You can cut and paste to arbitrarily reorder the commits.
\item You can delete a line to remove that commit completely.
\item You can insert the \texttt{squash} directive to fuse a commit
into the previous commit.
\item You can insert the \texttt{edit} directive to have Git pause
after applying a commit, so you can amend it in place or insert
new commits, before further commits are applied.
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Advanced rewriting}
\begin{description}[\texttt{git filter-branch}]
\item[\texttt{git filter-branch}\hfill] Rewrite history by mapping
each commit through an arbitrary script.
\item[\texttt{.git/info/grafts}\hfill] Causes the local repository
to pretend that certain commits have different parents than their
real ones. (\texttt{git filter-branch} can then rewrite the fake
parents into real ones.)
\item[\texttt{git fast-export}\hfill] Dump history in a
human-readable format, with SHA-1 IDs replaced by symbolic marks,
so that it can be edited by hand.
\item[\texttt{git fast-import}\hfill] Read back commits produced by
\texttt{git fast-export}.
\end{description}
\end{frame}
\section{And beyond!}
\begin{frame}
\frametitle{Other awesome Git commands}
\begin{description}[\texttt{git format-patch}]
\item[\texttt{git bisect}\hfill] Easily pinpoint a regression in
your history using a repeated bisection search.
\item[\texttt{git blame}\hfill] Annotate each line of a file with
information about its last modification.
\item[\texttt{git cvsimport}, \texttt{git svn}\hfill] Use Git to
work with repositories in other formats. (I think Git makes a
much better CVS or SVN client than the native ones!)
\item[\texttt{git format-patch}, \texttt{git send-email},
\texttt{git am}\hfill] Send and receive Git patches by email.
\item[\texttt{git grep}\hfill] Search for a regex in a Git tree.
\item[\texttt{git stash}\hfill] Quickly stash away and reapply
temporary changes while you do other work.
\item[\texttt{git submodule}\hfill] Manage a group of related Git
repositories.
\end{description}
\end{frame}
\begin{frame}
\frametitle{Exploring Git yourself}
\begin{itemize}
\item There are many commands we haven't talked about, and the ones
we have take additional options that can help you work more
efficiently.
\item Anything you think you should be able to do within the Git
model can probably be done.
\item Git is designed to be conveniently scriptable.
\item Git has extensive documentation---start with \texttt{man git}.
\begin{itemize}
\item To get documentation on any \texttt{git \textit{command}},
run \texttt{git help \textit{command}} or (equivalently)
\texttt{man git-\textit{command}}.
\end{itemize}
\end{itemize}
\end{frame}
\end{document}