forked from larics/git-tutorial-intro
-
Notifications
You must be signed in to change notification settings - Fork 0
/
basicbasics.tex
585 lines (438 loc) · 19.1 KB
/
basicbasics.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
\section{Keeping track of your code}
\begin{frame}
\frametitle{Version control system}
\begin{itemize}
\item \emph{VCS} - version control system
\end{itemize}
\begin{block}{Basic features}
\begin{itemize}
\item Keeps track of changes to our code
\item Facilitates collaboration in software and documentation development
\end{itemize}
\end{block}
\begin{block}{Additional requirements}
\begin{itemize}
\item Work offline
\item Support a distributed, decentralized workflow
\item Compatibility with existing protocols (e.g. ssh, http)
\item Data integrity protection
\item Efficiency
\end{itemize}
\end{block}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}
\frametitle{About git}
\begin{itemize}
\item Developed in 2005 by Linus Torvalds (in a single weekend!) to support Linux kernel development
\item Very powerful, has a reputation of being hard to learn
\begin{itemize}
\item We hope we will convince you otherwise :)
\end{itemize}
\item Supports different workflows
\begin{itemize}
\item We'll be using the \href{https://guides.github.com/introduction/flow/}{GitHub flow} (more or less)
\end{itemize}
\end{itemize}
\begin{block}{Meaning of the name \emph{git}}
\small
\emph{git} means "unpleasant person" in British slang. Linus: "I'm an egotistical bastard, and I name all my projects after myself."
\medskip
From the readme:
\begin{itemize}
\item "global information tracker": you're in a good mood, and it actually works for you. Angels sing, and a light suddenly fills the room.
\item "g*dd*mn idiotic truckload of sh*t": when it breaks
\end{itemize}
\end{block}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}
\frametitle{Basic terms: repository and commit}
\begin{block}{Repository (repo)}
A place where your work is kept. It contains your code and its complete history, stored as a collection of commits.
\end{block}
\begin{block}{Commit}
A basic unit of work in a project. Contains a \textbf{snapshot} of the complete project, a reference to a previous snapshot (the \textit{parent commit}), the commit message -- a textual description of the changes in the commit (with respect to the parent commit), the commit author name, and the commit date.
\end{block}
\end{frame}
\begin{frame}
\frametitle{Commit ID (SHA)}
\begin{block}{Commit ID}
\smallskip Every commit is marked with an alphanumeric identifier (SHA-1 hash) generated from the above information, which is used to uniquely identify the commit. \\For example: \textcolor{Maroon}{\texttt{bdfa760c07d8f621ff603a2dc5d6de810cd62e88}}
\smallskip
You can also use a prefix of the identifier to refer to this commit, usually 5 or 7 characters long, e.g. \textcolor{Maroon}{\texttt{bdfa760}}.
\end{block}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}
\frametitle{Basic terms: branch, main and head}
\begin{block}{Branch, main and head}
A \alert{branch} is simply a pointer to a commit. \alert{Main} is usually the name of the main branch (but does not have to be). \alert{HEAD} is a special pointer to the currently checked out commit. \\
\smallskip
The commits with their parent-child relationships form a directed acyclic graph (DAG).
\end{block}
\begin{figure}
\includegraphics[scale=0.26]{branches}
\end{figure}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}
\frametitle{Getting started on Github}
To begin working on a project using Github, you have to create a repository. There are three ways to do this:
\begin{itemize}
\item Create an empty repository
\begin{itemize}
\item When starting from scratch
\end{itemize}
\medskip
\item Fork another repository
\begin{itemize}
\item When you wish to improve and build upon another repository
\item This creates your personal copy of the repository in which you can make your own commits
\item Common in open source projects with many contributors
\end{itemize}
\medskip
\item \alert{Join an existing repository}
\begin{itemize}
\item The owner must add you to the repository
\item The most convenient collaboration mode for small and medium sized teams
\end{itemize}
\end{itemize}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}[fragile]
\frametitle{Forking a repo and adding a collaborator}
\begin{block}{Task A [Mirko]: Fork the example repository}
To fork a repository, simply click the \includegraphics[scale=0.35]{fork} \, icon in the top right corner of the repository webpage. For this tutorial, you will need to fork the \href{https://github.com/larics/git-tutorial-code.git}{larics/git-tutorial-code} repository.
\end{block}
\begin{block}{Task B [Mirko]: Add a collaborator to your forked repository}
In the GitHub user interface, on the \includegraphics[scale=0.35]{settings} \, tab of your forked repository, open the \texttt{Manage access} menu and add your partner as a collaborator with \texttt{Write} access.
\end{block}
\begin{block}{Task C [Slavko]: Accept the collaboration invitation}
Check your mail, or the list of notifications. Accept the collaboration invitation.
\end{block}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}[fragile]
\frametitle{Cloning the repository}
\begin{block}{Cloning}
Cloning creates a local copy of the repository, which includes all the commits in the repository -- the whole history.
\begin{minted}{console}
> git clone git@github.com:<Mirko>/git-tutorial-code.git
> cd <path to repo>
\end{minted}
\end{block}
\begin{block}{Task D [Mirko, Slavko]}
Clone Mirko's repository onto your computer and \texttt{cd} into it.
\end{block}
\begin{itemize}
\item NB -- if you committed something, it is in your local repo, (almost) permanently. Do not make it a habit to delete your local repositories -- if you "lose" a commit, it can be recovered (by its ID), even if you have deleted the branch!
\end{itemize}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}
\frametitle{Visualizing your repository}
\begin{itemize}
\item The \texttt{gitg} tool can visualize your repository
\item GitHub provides similar functionality with the Insights $\rightarrow$ Network menu.
\end{itemize}
\begin{block}{Task E [Mirko, Slavko]}
Visualize your repository with \texttt{gitg} and on GitHub.
\end{block}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}[fragile]
\frametitle{Repository structure}
What is contained in the repository directory?
\begin{minted}{console}
> cd <path to repo>
> ls -la
> git status
\end{minted}
\begin{itemize}
\item The \textit{working tree} -- current version of files ("checked out")
\item The hidden \texttt{.git} folder which contains repository metadata \\ (all the commits)
\item The \texttt{git status} command provides an overview of what is going on in the git repository.
\end{itemize}
\begin{minted}{console}
\end{minted}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}
\frametitle{Visualizing git operation}
\begin{figure}
\includegraphics[scale=0.4]{git-transport}
\end{figure}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}[fragile]
\frametitle{Your first branch}
\begin{block}{Task F [Mirko, Slavko]}
Create a branch, off of the \texttt{main} branch:
\begin{minted}{console}
> git checkout -b <your name>-git-tutorial
> git status
> git branch -v
> gitg&
\end{minted}
\end{block}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}[fragile]
\frametitle{Branching - recap}
\begin{itemize}
\item A \texttt{branch} is simply a "pointer" to a commit
\item \texttt{git checkout <branch>} updates the files in the working tree to match the specified branch
\item \texttt{git checkout -b <new branch>} creates a new branch at the current commit
\item You can use \texttt{gitg} to visualize your branches
\item Use descriptive branch names, separate words with dashes
\item Prefix "private" branches with your name
\item Branch early and often (but do not push every branch, and clean up regularly!)
\end{itemize}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}[fragile]
\frametitle{Your first commit}
\begin{block}{Task G [Mirko, Slavko]}
Open \texttt{README.md} and change the maintainer name (make yourself the maintainer), then save the file:
Run the following, and observe what is happening.
\begin{minted}{console}
> git status
> git diff
> git add README.md
> git status
> git gui&
> git commit -m "Change the maintainer"
> git status
> git log
\end{minted}
\end{block}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}[fragile]
\frametitle{Making a commit - recap}
\begin{enumerate}
\item Make a change in the working tree. For example:
\begin{itemize}
\item Edit a file
\item Create a file
\item Delete a file
\item Move a file (git considers moving as deleting + creating a new file)
\end{itemize}
\item \texttt {git add} the change to the \textit{staging area} ("index")
\item Perform a final inspection of the staged changes
\begin{itemize}
\item \texttt{git gui} is handy for this
\item The staged changes should make a logically grouped set of changes
\item Feel free to make as many commits as you like
\item "Commit early and often"
\end{itemize}
\item \texttt{git commit} your changes
\begin{itemize}
\item "50/72" rule - the title of the commit description should be {\raise.17ex\hbox{$\scriptstyle\sim$}}50 characters, the body should be wrapped to 72 characters
\item Use the imperative form as the first word in the title -- e.g. \\"Add prime checking", "Implement saving to file", "Fix broken build"
\end{itemize}
\end{enumerate}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}[fragile]
\frametitle{Discarding unstaged changes}
\begin{block}{Task I [Mirko, Slavko]}
\begin{itemize}
\item Delete a big chunk of text from \texttt{README.md}. Do not add or commit.
\item To find out what is going on, use \texttt{git status} and \texttt{git diff}.
\medskip
\item Discard the changes by retrieving ("checking out") the last commited version of the file (can also be a directory) using the \texttt{checkout} command:
\begin{minted}{console}
> git checkout README.md
\end{minted}
Note that the checked out version will contain the staged changes, i.e., \texttt{checkout} affect only the workspace, not the index.
\end{itemize}
\end{block}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}
\frametitle{Managing staged changes}
\begin{block}{Task H [Mirko, Slavko]}
Make some more changes to some file(s) in your working tree.
\end{block}
\begin{itemize}
\item To get a list of staged and unstaged files, run \texttt{git status}.
\item To unstage all changes, run \texttt{git reset}.
\item To view the \textbf{unstaged} changes in the \textit{diff} format, open \texttt{git gui},
\\or run \texttt{git diff}
\item To view the \textbf{staged} changes in the \textit{diff} format, you can also use \texttt{git gui}, or you can run \texttt{git diff --cached}
\item You can finely tune what goes into the commit by staging/unstaging individual lines using \texttt{git gui}.
(The shortcut for (un)staging all changes in a file is Ctrl-U)
\end{itemize}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}[fragile]
\frametitle{Making some more commits}
\begin{block}{Task J [Mirko, Slavko]: Adding a license and \texttt{.gitignore}}
\begin{itemize}
\item Add a license to the project. Create a \texttt{LICENSE.txt} file and copy the \href{https://www.apache.org/licenses/LICENSE-2.0.txt}{Apache License 2.0 text} into this file.
\item Create a \texttt{.gitignore} file, with the following two lines:
\begin{minted}{text}
cpp/build/
*.pyc
\end{minted}
\item After modifying the files in the working tree, make two separate commits, one for the license, and the other for \texttt{.gitignore}.
\end{itemize}
\end{block}
\begin{block}{Task K [Slavko]}
Open \texttt{README.md}. Under the package description (the second line), add and commit something to annoy your colleague, for example:
\begin{minted}{text}
Mirko is churning out more spaghetti code
than a trattoria in Napoli.
\end{minted}
\end{block}
\end{frame}
% -----------------------------------------------------------------------------
%\begin{frame}[fragile]
%
%\frametitle{Discarding many unwanted changes}
%
% \begin{itemize}
% \item If you have made many changes in your working tree, spanning several files, you can discard all of them at once (this also includes the staged changes):
% \begin{minted}{console}
%> git reset --hard
% \end{minted}
%
% \item This will restore all tracked files in the working tree to the most recently committed version (i.e. the \texttt{HEAD} commit).
% \end{itemize}
%
%\begin{block}{Task I [Mirko, Slavko]: Discarding several unwanted changes}
% \begin{itemize}
% \item Delete several files from the cloned example repository. Do not commit the changes.
% \item Check the output of \texttt{git status}.
% \item Discard all changes as shown above.
% \end{itemize}
%\end{block}
%
%\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}
\frametitle{Going back in time 1/3}
\begin{itemize}
\item A big point in using a version control system such as git is the ability to retrieve older versions of files in the project.
\item Note that writing good commit messages is important, because it will make identifying the right version much easier.
\item In the workflow we have described, the procedure for undoing mistakes is making additional commits which fix these mistakes.
\end{itemize}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}[fragile]
\frametitle{Going back in time 2/3}
\begin{block}{Task L: Checking out an earlier commit [Mirko, Slavko]}
\begin{itemize}
\item Identify an interesting commit in your history by either:
\begin{itemize}
\item running \texttt{git log} (add \texttt{--oneline} for an abbreviated list of commits),
\item using the \texttt{gitg} tool.
\end{itemize}
\item Check out that commit into your working tree
\begin{minted}{console}
> git checkout <commit ID>
\end{minted}
\item This will bring you in a so-called \emph{detached head} state (sounds more dangerous than it acually is :)
\item This is useful in situations where you want to build a previous version of your code that you know is working
\item Bring \texttt{HEAD} back to the tip of your tutorial branch
\begin{minted}{console}
> git checkout <your name>-git-tutorial
\end{minted}
\end{itemize}
\end{block}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}[fragile]
\frametitle{Going back in time 3/3}
Sometimes, you want to retrieve a previously committed version of a specific file.
\begin{block}{Task M [Mirko, Slavko]}
\begin{itemize}
\item Identify a specific file version in your commit history.
\item Perform the retrieval by running:
\begin{minted}{console}
> git checkout <commit ID> <file>
\end{minted}
\item Git will place the checked out version of the file in the \emph{staging area}.
\item How do you make further tweaks to the checked out version?
\item How do you discard this version?
\end{itemize}
\end{block}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}[fragile]
\frametitle{Pushing the changes to the remote repository}
\begin{itemize}
\item \texttt{commit} only saves changes \alert{locally}!
\item The command \texttt{git push} is used to upload the commits you have made to a branch in a remote repository (also known as just \textit{remote}).
\item When you are pushing a local branch for the first time, tell git that to track the remote branch with your local branch:
\begin{minted}{console}
> git push -u origin <branch name>
\end{minted}
\item On subsequent pushes you can simply call
\begin{minted}{console}
> git push
\end{minted}
\end{itemize}
\begin{block}{Task N [Mirko, Slavko]}
Push the commits you have made to Mirko's repository.
\end{block}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}
\frametitle{Binary files}
\begin{block}{Difference between text and binary files}
\begin{itemize}
\item Changes to files are stored incrementally, as commit diffs, which is very space-efficient for text-files.
\item For binary files, most of the time, the majority of the file is changed (e.g. when you edit a picture, or recompile an executable), which effectively means that the commit \textbf{contains a complete copy of the new version}.
\begin{itemize}
\item The old version \textbf{still persists} in the old commits, \textbf{even if you remove the file}, because git keeps the whole history.
\end{itemize}
\end{itemize}
\end{block}
\begin{block}{How to handle binary files}
Storing binary files (e.g. graphics) is acceptable if they are small and change infrequently. Otherwise, create a README file with instructions for downloading the files, or a script which downloads them into place.
\end{block}
\end{frame}
% -----------------------------------------------------------------------------
\begin{frame}[fragile]
\frametitle{Binary files - build output}
\begin{block}{Build output}
\begin{itemize}
\item \alert{Never} commit build output (even if it is text, e.g. documentation)! It can waste \alert{huge} amounts of space and it will create unnecessary conflicts
\item Add the appropriate entries to \texttt{.gitignore} so that git ignores \\ the build output
\begin{itemize}
\item This will also keep \texttt{git gui} and the output of \texttt{git status}\\ free from clutter related to build files
\end{itemize}
\end{itemize}
\end{block}
\end{frame}
% -----------------------------------------------------------------------------
%\begin{frame}[fragile]
%
%\frametitle{Amending the last commit}
%
%In the special case when you want to add aditional changes to the \textit{last commit} that you have made, \textbf{and if you have not yet pushed that commit}:
%
% \begin{enumerate}
% \item Stage the additional changes using \texttt{git add}
% \item Inspect the changes, as previously described
% \item Run \texttt{git commit --amend}
% \begin{itemize}
% \item In case you only wish to amend the commit description, just run \texttt{git commit --amend}, without staging any changes.
% \end{itemize}
% \end{enumerate}
%
% \begin{block}{Task O [Slavko]}
% Amend the description of the revert commit that you have just made: \texttt{Revert Mirko's rudeness}. Push the revert commit.
%
%\end{block}
%
% \begin{block}{Task P [Mirko]}
% Pull Slavko's changes.
% \end{block}
%
%
%\end{frame}
% -----------------------------------------------------------------------------