added thing about workshop repo
[ai-gitworkshop.git] / git.tex
1 %&git
2 \begin{document}
3 \begin{frame}
4 \titlepage
5 \end{frame}
6
7 \section{What is GIT}
8 \subsection{Who am I?}
9 \begin{frame}
10 \frametitle{Who am I?}
11 \begin{itemize}
12 \item Mart Lubbers
13 \item Bachelors in Artificial Intelligence
14 \item 1th year master Software science
15 \item
16 {\tiny\url{https://ygdrassil.martlubbers.net/git/gitflashtalk.git}}
17 \item SHA of the commit of this presentation:
18 {\tiny\GITAbrHash}
19 \end{itemize}
20 \end{frame}
21
22 \subsection{What is git}
23 \begin{frame}
24 \frametitle{History of version control}
25 \begin{block}{What is version control?}
26 \begin{itemize}
27 \item Text files
28 \item Collaboration
29 \item Possibly centralized or distributed
30 \end{itemize}
31 \end{block}
32
33 \begin{block}{History}
34 \begin{tabular}{lllp{6em}l}
35 \toprule
36 Gen & Networking & Operations & Concurrency & Examples\\
37 \midrule
38 1 & None & One file & Locks & RCS, SCSS\\
39 2 & Centralized & Multi-file & Merge before commit & CVS, SVN\\
40 3 & Distributed & Changeset & Commit before merge &
41 Git, Mercurial\\
42 \bottomrule
43 \end{tabular}
44 {\tiny Table from \url{%
45 http://ericsink.com/vcbe/html/history_of_version_control.html}}
46 \end{block}
47 \end{frame}
48
49 \begin{frame}[fragile]
50 \frametitle{What is Git}
51 \begin{block}{Origins}
52 \begin{itemize}
53 \item Pronounce: \textipa{[g\'\i t]}
54 \item 2005 because \textit{Bitkeeper} changed terms
55 \item Linux kernel
56 \end{itemize}
57 \end{block}
58
59 \begin{block}{Initial \texttt{readme} from 2005}
60 \begin{minted}{text}
61 GIT - the stupid content tracker
62
63 "git" can mean anything, depending on your mood.
64
65 - random three-letter combination that is pronounceable, and not
66 actually used by any common UNIX command. The fact that it is a
67 mispronounciation of "get" may or may not be relevant.
68 - stupid. contemptible and despicable. simple. Take your pick from the
69 dictionary of slang.
70 - "global information tracker": you're in a good mood, and it actually
71 works for you. Angels sing, and a light suddenly fills the room.
72 - "goddamn idiotic truckload of sh*t": when it breaks
73 \end{minted}
74 \end{block}
75 \end{frame}
76
77 \begin{frame}
78 \frametitle{Why Git?}
79 \begin{block}{Pros}
80 \begin{itemize}
81 \item Fast
82 \item Scaleable
83 \item Simple
84 \item Support for non linear development
85 \item Intermediate stage between committing and pushing
86 \end{itemize}
87 \end{block}
88
89 \begin{block}{Cons}
90 \begin{itemize}
91 \item Binary files
92 \item Intermediate stage between committing and pushing
93 \end{itemize}
94 \end{block}
95 \end{frame}
96
97 \begin{frame}
98 \frametitle{Before we start}
99 \pause
100 \huge Git is not Github
101 \end{frame}
102
103 \section{Introduction}
104 \subsection{Installation}
105 \begin{frame}[fragile]
106 \begin{block}{{\Large\Smiley\Smiley} Linux}
107 Depending on the distribution you may have to do:\\
108 \mint{console}{# apt-get install git}
109 \mint{console}{# pacman -S git}
110 \mint{console}{# yum install git}
111 \mint{console}{# emerge --ask dev-vcs/git}
112 Etc\ldots
113 \end{block}
114
115 \begin{block}{{\Large\Frowny\Smiley} Mac}
116 Install via XCode tools. Just run \mintinline{console}{|\$| git} and
117 when Git is not installed it will prompt you with instructions.
118 \end{block}
119
120 \begin{block}{{\Large\Frowny\Frowny} Windows}
121 Downoad the binary from \url{http://git-scm.com/download/win} and
122 install.
123 \end{block}
124 \end{frame}
125
126 \begin{frame}[fragile]
127 \begin{block}{Linux/Mac}
128 \begin{itemize}
129 \item[Step 1.] Open your favourite terminal.
130 \item[Step 2.]
131 \begin{minted}{console}
132 |\$| git --version
133 git version 2.7.2
134 \end{minted}
135 \end{itemize}
136 \end{block}
137
138 \begin{block}{Windows}
139 \begin{itemize}
140 \item[Step 1.] Open \texttt{git-bash}. \texttt{git-bash} is a UNIX
141 like environment with all the necessary tools.
142 \item[Step 2.]
143 \begin{minted}{console}
144 frobnicator@frobmachine MINGW64 ~
145 |\$| git --version
146 git version 2.7.2.windows.1
147 \end{minted}
148 \end{itemize}
149 \end{block}
150 \end{frame}
151
152 \subsection{Repositories}
153 \begin{frame}[fragile]
154 \frametitle{Create your first repository}
155 \begin{block}{Command}
156 \begin{minted}{console}
157 |\$| cd projects
158 |\$| git init myfirstproject
159 Initialized empty Git repository in /home/frobnicator/projects/myfirstproject/.git/
160 \end{minted}
161 \end{block}
162
163 \begin{block}{Filesystem}
164 \begin{minted}{console}
165 |\$| ls -a myfirstproject
166 . .. .git
167 |\$| ls myfirstproject/.git
168 branches config description HEAD hooks info objects refs
169 \end{minted}
170 \end{block}
171 \end{frame}
172
173 \subsection{Workflow}
174 \begin{frame}
175 \frametitle{Four (five) stages}
176 \begin{itemize}
177 \item (Stash)
178 \item Workspace
179 \item Index
180 \item Local repo
181 \item Upstream repo
182 \end{itemize}
183 \end{frame}
184
185 \begin{frame}
186 \frametitle{Connect the stages}
187 \includegraphics[width=\linewidth]{workflow.png}
188 \end{frame}
189
190 \section{Local}
191 \begin{frame}
192 \frametitle{Everything is a commit}
193 \begin{block}{Forget what you have learned. These things are commits:}
194 \begin{itemize}
195 \item commit
196 \item tag
197 \item branch
198 \item \texttt{HEAD}
199 \end{itemize}
200 \end{block}
201 \begin{block}{Commits are structured in a tree}
202 \end{block}
203 \pause
204 \begin{block}{From now on: Tag along}
205 \end{block}
206 \end{frame}
207
208 \subsection{Add \& Commit}
209 \begin{frame}[fragile]
210 \frametitle{Add (1)}
211 \begin{block}{Command}
212 \mintinline{bash}{git add [opts] [<pathspec>...]}
213 \end{block}
214 \begin{block}{Example: Shopping list}
215 \begin{minted}{console}
216 |\$| git init shoppinglist
217 Initialized empty Git repository in
218 /home/frobnicator/projects/shoppinglist/.git/
219 |\$| cd shoppinglist/
220 |\$| echo "milk" > shopping.txt
221 |\$| echo "eggs" >> shopping.txt
222 |\$| echo "ham" >> shopping.txt
223 |\$| cat shopping.txt
224 milk
225 eggs
226 ham
227 \end{minted}
228 \end{block}
229 \begin{block}{Where is the data?}
230 \pause
231 Workspace
232 \end{block}
233 \end{frame}
234
235 \begin{frame}[fragile]
236 \frametitle{Add (2)}
237 \begin{minted}{console}
238 |\$| git status
239 On branch master
240
241 Initial commit
242
243 Untracked files:
244 (use "git add <file>..." to include in what will be committed)
245
246 shopping.txt
247
248 nothing added to commit but untracked files present (use "git add" to track)
249 |\$| git add shopping.txt #git add .
250 |\$| git status
251 On branch master
252
253 Initial commit
254
255 Changes to be committed:
256 (use "git rm --cached <file>..." to unstage)
257
258 new file: shopping.txt
259 \end{minted}
260 \end{frame}
261
262 \begin{frame}[fragile]
263 \frametitle{Commit (1)}
264 \begin{minted}{console}
265 |\$| export EDITOR=vim # nano, emacs, ed, ex, etc...
266 |\$| git commit # Editor opens
267
268 # Please enter the commit message for your changes. Lines starting
269 # with '#' will be ignored, and an empty message aborts the commit.
270 # On branch master
271 #
272 # Initial commit
273 #
274 # Changes to be committed:
275 # new file: shopping.txt
276 #
277 [master (root-commit) ae90376] Initial shopping list
278 1 file changed, 3 insertions(+)
279 create mode 100644 shopping.txt
280 \end{minted}
281 \end{frame}
282
283 \begin{frame}[fragile]
284 \frametitle{Commit (2)}
285 \begin{block}{Results}
286 \begin{minted}{console}
287 |\$| git status
288 On branch master
289 nothing to commit, working directory clean
290 |\$| ls -a
291 . .. .git shopping.txt
292 \end{minted}
293 \end{block}
294
295 \begin{block}{Where is the data}
296 \pause
297 Workspace + Local repository
298 \end{block}
299 \end{frame}
300
301 \begin{frame}[fragile]
302 \frametitle{Add \& Commit some more}
303 \begin{block}{We forgot the bread!}
304 \begin{minted}{console}
305 |\$| echo "Bread" >> shopping.txt
306 |\$| git add .
307 |\$| git commit -m "We forgot the bread, oops"
308 [master 8cb1d9b] We forgot the bread, oops
309 1 file changed, 1 insertion(+)
310 \end{minted}
311 \end{block}
312
313 \begin{block}{Even quicker, let's add beer}
314 \begin{minted}{console}
315 |\$| echo "Grolsch" >> shopping.txt
316 |\$| git commit -am "Beer added"
317 [master 99d65a3] Beer added
318 1 file changed, 1 insertion(+)
319 \end{minted}
320 \end{block}
321 \end{frame}
322
323 \subsection{Administration}
324 \begin{frame}[fragile]
325 \frametitle{Log}
326 \begin{minted}{console}
327 |\$| git log
328 commit 99d65a34c02f5766ffa8e04b7c7121dfe41136ec
329 Author: Frob Nicator <frob@nicat.or>
330 Date: Tue Mar 15 19:15:05 2016 +0100
331
332 Beer added
333
334 commit 8cb1d9bf8e4b45355b38600367a841fe9ceaae40
335 Author: Frob Nicator <frob@nicat.or>
336 Date: Tue Mar 15 19:13:55 2016 +0100
337
338 We forgot the bread, oops
339
340 commit ae903769895cbb7c24b096e17049d20a8456953c
341 Author: Frob Nicator <frob@nicat.or>
342 Date: Tue Mar 15 19:04:40 2016 +0100
343
344 Initial shopping list
345 \end{minted}
346 \end{frame}
347
348 \begin{frame}[fragile]
349 \frametitle{Checkout (1)}
350 \begin{minted}{console}
351 |\$| git log --oneline --decorate --graph --all
352 * 99d65a3 (HEAD, master) Beer added
353 * 8cb1d9b We forgot the bread, oops
354 * ae90376 Initial shopping list
355 |\$| cat shopping.txt
356 milk
357 eggs
358 ham
359 Bread
360 Grolsch
361 |\$| git checkout ae90376
362 Note: checking out 'ae90376'.
363
364 ... # long error about detached head state
365
366 HEAD is now at ae90376... Initial shopping list
367 \end{minted}
368 \end{frame}
369
370 \begin{frame}[fragile]
371 \frametitle{Checkout (2)}
372 \begin{minted}{console}
373 |\$| git log --oneline --decorate --graph --all
374 * 99d65a3 (master) Beer added
375 * 8cb1d9b We forgot the bread, oops
376 * ae90376 (HEAD) Initial shopping list
377 |\$| cat shopping.txt # We got our old shopping list back!
378 milk
379 eggs
380 ham
381 |\$| git checkout master # or 99d65a3
382 Previous HEAD position was ae90376... Initial shopping list
383 Switched to branch 'master'
384 |\$| git log --oneline --decorate --graph --all
385 * 99d65a3 (HEAD, master) Beer added
386 * 8cb1d9b We forgot the bread, oops
387 * ae90376 Initial shopping list
388 \end{minted}
389 \end{frame}
390
391 \begin{frame}[fragile]
392 \frametitle{Differences (1)}
393 \begin{block}{Behaviour}
394 \begin{itemize}
395 \item\mintinline{console}{git diff HASH}\\
396 Compare index to said hash
397 \item\mintinline{console}{git diff HASH1 HASH2}\\
398 Compare the hashes
399 \end{itemize}
400 \end{block}
401
402 \begin{minted}{console}
403 |\$| git diff ae90376
404 diff --git a/shopping.txt b/shopping.txt
405 index 1e19791..c41e7e5 100644
406 --- a/shopping.txt
407 +++ b/shopping.txt
408 @@ -1,3 +1,5 @@
409 milk
410 eggs
411 ham
412 +Bread
413 +Grolsch
414 \end{minted}
415 \end{frame}
416
417 \begin{frame}[fragile]
418 \frametitle{Differences (2)}
419 \begin{minted}{console}
420 |\$| git diff master
421 |\$| vi shopping.txt # remove bread
422 |\$| git diff master
423 diff --git a/shopping.txt b/shopping.txt
424 index c41e7e5..47c3623 100644
425 --- a/shopping.txt
426 +++ b/shopping.txt
427 @@ -1,5 +1,4 @@
428 milk
429 eggs
430 ham
431 -Bread
432 Grolsch
433 \end{minted}
434 \end{frame}
435
436 \begin{frame}[fragile]
437 \frametitle{Oops we didn't want to remove the bread}
438 \begin{minted}[escapeinside=]{console}
439 $ git stash
440 Saved working directory and index state WIP on master: 99d65a3 Beer added
441 HEAD is now at 99d65a3 Beer added
442 $ git log --oneline --decorate --graph --all
443 * 2c395dd (refs/stash) WIP on master: 99d65a3 Beer added
444 |\
445 | * 149d864 index on master: 99d65a3 Beer added
446 |/
447 * 99d65a3 (HEAD, master) Beer added
448 * 8cb1d9b We forgot the bread, oops
449 * ae90376 Initial shopping list
450 \end{minted}
451 \begin{block}{Stash}
452 This is material for an advanced git course.\\
453 Just remember you can checkout all hashes.
454 \end{block}
455 \end{frame}
456
457 \subsection{Branching}
458 \begin{frame}[fragile]
459 \frametitle{Branching}
460 \begin{block}{Let's start from scratch}
461 \begin{minted}{console}
462 |\$| git rm shopping.txt
463 rm 'shopping.txt'
464 |\$| echo -e "ham\nmilk\neggs" > list.txt
465 |\$| git add .
466 |\$| git status
467 On branch master
468 Changes to be committed:
469 (use "git reset HEAD <file>..." to unstage)
470
471 renamed: shopping.txt -> list.txt
472 \end{minted}
473 \end{block}
474 \pause
475 \begin{block}{Wait a minute, we removed that...}
476 \begin{minted}{console}
477 |\$| git commit -m "Start from scratch"
478 [master 33dff03] Start from scratch
479 1 file changed, 1 insertion(+), 3 deletions(-)
480 rename shopping.txt => list.txt (50%)
481 \end{minted}
482 \end{block}
483 \end{frame}
484
485 \begin{frame}[fragile]
486 \frametitle{Branching \& Merging (1) }
487 \begin{minted}[escapeinside=]{console}
488 $ git checkout -b vega # or git branch vega; git checkout vega
489 $ vi list.txt # change ham to tofu, add beans
490 $ cat list.txt
491 tofu
492 milk
493 eggs
494 beans
495 $ git commit -am "Added tofu and beans"
496 [vega e74256e] Added tofu and beans
497 1 file changed, 2 insertions(+), 1 deletion(-)
498 $ git log --oneline --decorate --graph --all
499 * e74256e (HEAD, vega) Added tofu and beans
500 * 33dff03 (master) Start from scratch
501 | * 2c395dd (refs/stash) WIP on master: 99d65a3 Beer added
502 | |\
503 |/ /
504 | * 149d864 index on master: 99d65a3 Beer added
505 |/
506 * 99d65a3 Beer added
507 * 8cb1d9b We forgot the bread, oops
508 * ae90376 Initial shopping list
509 \end{minted}
510 \end{frame}
511
512 \begin{frame}[fragile]
513 \frametitle{Branching \& Merging (2) }
514 \begin{minted}[escapeinside=]{console}
515 $ git checkout master
516 $ cat list.txt
517 ham
518 milk
519 eggs
520 $ git log --oneline --decorate --graph --all
521 * e74256e (vega) Added tofu and beans
522 * 33dff03 (HEAD, master) Start from scratch
523 | * 2c395dd (refs/stash) WIP on master: 99d65a3 Beer added
524 | |\
525 |/ /
526 | * 149d864 index on master: 99d65a3 Beer added
527 |/
528 * 99d65a3 Beer added
529 * 8cb1d9b We forgot the bread, oops
530 * ae90376 Initial shopping list
531 \end{minted}
532 \end{frame}
533
534 \begin{frame}[fragile]
535 \frametitle{Branching \& Merging (2) }
536 \begin{minted}[escapeinside=]{console}
537 $ vi list.txt # change ham to cheese
538 $ cat list.txt
539 cheese
540 milk
541 eggs
542 $ git commit -am "Change ham to cheese"
543 [master a77f1e5] Change ham to cheese
544 1 file changed, 1 insertion(+), 1 deletion(-)
545 $ git log --oneline --decorate --graph --all
546 * a77f1e5 (HEAD, master) Change ham to cheese
547 | * e74256e (vega) Added tofu and beans
548 |/
549 * 33dff03 Start from scratch
550 | * 2c395dd (refs/stash) WIP on master: 99d65a3 Beer added
551 | |\
552 |/ /
553 | * 149d864 index on master: 99d65a3 Beer added
554 |/
555 * 99d65a3 Beer added
556 * 8cb1d9b We forgot the bread, oops
557 * ae90376 Initial shopping list
558 \end{minted}
559 \end{frame}
560
561 \begin{frame}[fragile]
562 \frametitle{Merging (1)}
563 \begin{block}{Noes, conflicts}
564 \begin{minted}{console}
565 |\$| git merge vega
566 Auto-merging list.txt
567 CONFLICT (content): Merge conflict in list.txt
568 Automatic merge failed; fix conflicts and then commit the result.
569 \end{minted}
570 \end{block}
571 \begin{block}{Contents of \texttt{list.txt}}
572 \begin{minted}{text}
573 <<<<<<< HEAD
574 cheese
575 =======
576 tofu
577 >>>>>>> vega
578 milk
579 eggs
580 beans
581 \end{minted}
582 \end{block}
583 \end{frame}
584
585 \begin{frame}[fragile]
586 \frametitle{Merging (2)}
587 \begin{block}{Resolving merge conflicts}
588 \begin{itemize}
589 \item Open all files listed
590 \item Remove all \texttt{<<<<< \ldots} and \texttt{>>>> \ldots}
591 \end{itemize}
592 \end{block}
593 \begin{block}{Contents of commit when you have done that}
594 \begin{minted}{console}
595 Merge branch 'vega'
596
597 Conflicts:
598 list.txt
599 # ...
600
601 # ...
602 # On branch master
603 # All conflicts fixed but you are still merging.
604 #
605 # Changes to be committed:
606 # modified: list.txt
607 #
608 \end{minted}
609 \end{block}
610 \end{frame}
611
612 \begin{frame}[fragile]
613 \frametitle{Merging (3)}
614 \begin{block}{And done!}
615 \begin{minted}[escapeinside=]{console}
616 $ git commit -a
617 [master 10a9e9e] Merge branch 'vega'
618 $ git tree
619 * 10a9e9e (HEAD, master) Merge branch 'vega'
620 |\
621 | * e74256e (vega) Added tofu and beans
622 * | a77f1e5 Change ham to cheese
623 |/
624 * 33dff03 Start from scratch
625 | * 2c395dd (refs/stash) WIP on master: 99d65a3 Beer added
626 | |\
627 |/ /
628 | * 149d864 index on master: 99d65a3 Beer added
629 |/
630 * 99d65a3 Beer added
631 * 8cb1d9b We forgot the bread, oops
632 * ae90376 Initial shopping list
633 \end{minted}
634 \end{block}
635 \end{frame}
636
637 \subsection{Notes}
638 \begin{frame}
639 \frametitle{Some notes}
640 \begin{itemize}
641 \item Make short commits, per feature
642 \item Try to only commit working code
643 \item No generatable stuff in the repo
644 \item Commit messages formatten:
645 \begin{itemize}
646 \item 72 Chars title
647 \item Enter, Enter
648 \item Body of the message in \emph{Imperative Present Tense}
649 \emph{change}, not \emph{changed} or \emph{changes}
650 \end{itemize}
651 \item Master contains only major releases
652 \item Develop contains development release
653 \item Feature branches
654 \end{itemize}
655 \end{frame}
656
657 \section{Remote}
658 \begin{frame}
659 \frametitle{Clone (1)}
660 \begin{itemize}
661 \item Github(you can get 5 free repos via student mail)
662 \item BitBucket
663 \item Gitlab(runs on science servers)
664 \item \mintinline{console}{git clone CLONEURL}
665 \end{itemize}
666 \end{frame}
667
668 \begin{frame}[fragile]
669 \frametitle{Clone (2)}
670 \begin{block}{Clone}
671 \begin{minted}{console}
672 |\$| git clone https://github.com/githubuser/reponame # With optional folder
673 Cloning into 'reponame'...
674 remote: Counting objects: 44, done.
675 remote: Total 44 (delta 0), reused 0 (delta 0), pack-reused 44
676 Unpacking objects: 100% (44/44), done.
677 Checking connectivity... done.
678 \end{minted}
679 \end{block}
680 \end{frame}
681
682 \begin{frame}[fragile]
683 \frametitle{Push \& Pull}
684 \begin{block}{Pull}
685 Basically a merge of the remote branch with your \texttt{HEAD}. This
686 can lead to merge conflict. Only pull when you have committed
687 everything.
688 \begin{minted}{console}
689 |\$| git pull origin BRANCHNAME
690 \end{minted}
691 \end{block}
692
693 \begin{block}{Push}
694 Push your changes to the remote. You have to pull first.
695 \begin{minted}{console}
696 |\$| git push origin BRANCHNAME
697 \end{minted}
698 \end{block}
699 \end{frame}
700
701 \begin{frame}
702 \frametitle{Add your shopping list to the repo!}
703 \begin{block}{List your username and I'll give you write access}
704 \url{https://github.com/dopefishh/gitworkshop}
705 \end{block}
706 \end{frame}
707
708 \begin{frame}
709 \frametitle{Tags}
710 \begin{itemize}
711 \item \mintinline{console}{git tag TAGNAME}
712 \item Github interprets them as releases
713 \item Easy for releases
714 \item Literally a named commit
715 \item Push only tags:
716 \mintinline{console}{git push --tags origin master}
717 \end{itemize}
718 \end{frame}
719
720
721 \section{Post scriptum}
722 \subsection{Questions \& Conclusion}
723 \begin{frame}
724 \frametitle{Questions}
725 \begin{center}{\Huge?}\end{center}
726 \pause
727 \begin{block}{If you want to be an expert}
728 Read: \emph{Git from the bottom up}~\footnote{\url{%
729 http://ftp.newartisans.com/pub/git.from.bottom.up.pdf}}
730 \end{block}
731 \end{frame}
732
733 \subsection{Aliasing}
734 \begin{frame}[fragile]
735 \frametitle{Aliasing}
736 \begin{minted}{console}
737 |\$| cat ~/.gitconfig
738 [user]
739 name = Frob Nicator
740 email = frob@nicat.or
741
742 [alias]
743 tree = log --decorate --oneline --graph --all
744 pushm = push origin master
745 pushd = push origin develop
746 |\$| git tree
747 \end{minted}
748 \end{frame}
749
750 \subsection{Gitignore}
751 \begin{frame}[fragile]
752 \frametitle{Ignore certain files}
753 \begin{minted}{console}
754 |\$| cat ~/projects/somelatexproject/.gitignore
755 *.aux
756 *.fmt
757 *.log
758 *.out
759 *.pdf
760 \end{minted}
761 \end{frame}
762
763 \subsection{What is the difference betweeen all the clone urls?}
764 \begin{frame}
765 \frametitle{SSH or HTTPS}
766 \begin{itemize}
767 \item SSH preferred over HTTPS due to security issues
768 \item SSH saves you from entering the password all the time
769 \item For a how-to about setting up SSH checkout the github tutorial
770 \item HTTPS easy for onetime checkout
771 \end{itemize}
772 \end{frame}
773
774 \subsection{Host your own git server}
775 \begin{frame}[fragile]
776 \frametitle{Host your own git server}
777 \begin{block}{SSH (Easy)}
778 \begin{minted}{console}
779 # adduser --shell /usr/bin/git-shell git}
780 # su git -s /bin/bash
781 |\$| mkdir .ssh
782 |\$| chmod 700 .ssh
783 |\$| touch .ssh/authorized_keys # Put public keys in here
784 |\$| chmod 600 .ssh/*
785 |\$| git init --bare newrepo.git
786 \end{minted}
787 \end{block}
788
789 \begin{block}{HTTP webinterface (Medium)}
790 GitList\footnote{\url{http://gitlist.org/}}
791 This presentation:
792 {\tiny\url{https://ygdrassil.martlubbers.net/git/ai-gitworkshop.git/}}
793 \end{block}
794
795 \begin{block}{HTTP+SSH (Hard)}
796 GitLab\footnote{\url{gitlab.com}}
797 \end{block}
798 \end{frame}
799
800 \end{document}