Code

ORR 2010 → ALIT 2011.
[talk-dvcs-git.git] / main.tex
1 \usetheme{default}
2 \setbeamertemplate{navigation symbols}{}
4 \mode<beamer>
5 {
6   \setbeamercolor{background canvas}{bg=black!10}
7 }
8 \setbeamercolor*{block body}{fg=black,bg=white}
9 \setbeamercolor*{block title}{use=titlelike,fg=titlelike.fg!80!black,bg=black!10}
11 \usepackage{ngerman}
12 \usepackage[utf8]{inputenc}
14 \usepackage{listings}
15 \usepackage{xcolor}
16 \definecolor{darkgreen}{rgb}{0,0.39,0}
18 \usepackage{graphicx}
19 \usepackage{icomma}
20 \usepackage[normalem]{ulem}
22 \usepackage{multirow}
24 \usepackage[overlay,absolute]{textpos}
26 \usepackage{tikz}
27 \usetikzlibrary{shadows}
28 \usetikzlibrary{decorations.pathreplacing}
29 \usetikzlibrary{shapes.geometric}
31 \usepackage{wasysym}
33 \title[Versionierung für OpenSourcler]{{\small Verteilte Versionskontrolle mit Git}\\
34   \LARGE Versionierung für OpenSourcler}
36 \author[Sebastian "`tokkee"' Harl]{Sebastian "`tokkee"' Harl\\
37   $<$tokkee@debian.org$>$}
38 %\institute{Debian RRDtool Team}
40 \date[ALIT 2011]{\textbf{Augsburger Linux-Infotag 2011}\\ 26.\ März 2011}
42 \subject{Versionierung für OpenSourcler}
44 \titlegraphic{
45   \vspace*{-10mm}
46   \hfill
47   \begin{minipage}[c]{13mm}
48     \includegraphics[height=25mm]{gitlogo.pdf}
49   \end{minipage}
50 }
52 % This is rather a hack, but it's easier than defining custom beamer themes
53 % for now.
54 \setbeamertemplate{frametitle}{}
55 \newenvironment{frameframe}[1]
56   {
57     \begin{frame}[fragile,environment=frameframe]
58     % width of a slide is 128 mm
59     \begin{textblock*}{116mm}(6mm,4mm)
60       \begin{tikzpicture}[x=1mm,y=1mm]
61         \filldraw[fill=white,rounded corners=2mm,very thick]
62           (0,0) rectangle (116,75);
63         \draw[thin] (58,75) node [fill=white,drop shadow,draw]
64           { \usebeamerfont*{frametitle}\usebeamercolor[fg]{frametitle}#1 };
65         \draw (58,78) node {};
66       \end{tikzpicture}
67     \end{textblock*}
68     \begin{textblock*}{122mm}(3mm,85mm)
69       \hfill
70       \begin{minipage}[c]{105mm}
71         \centering
72         {\tiny \insertshorttitle{}
73          \hspace{3mm}---\hspace{3mm}
74          \insertshortauthor{}
75          \hspace{3mm}---\hspace{3mm}
76          \insertframenumber\,/\,\inserttotalframenumber}
77       \end{minipage}
78       \hfill
79       \begin{minipage}[c]{5mm}
80         \includegraphics[width=5mm]{gitlogo.pdf}
81       \end{minipage}
82     \end{textblock*}
83     \begin{textblock*}{\textwidth}(10mm,12mm)
84       % even hackier ... ;-)
85       % vertically center the text in the frame
86       \begin{minipage}[c]{-1pt}\rule{0mm}{71mm}
87       \end{minipage}\begin{minipage}[c]{\textwidth}
88   }
89   {
90       \end{minipage}
91     \end{textblock*}
92     \end{frame}
93   }
95 \AtBeginSection[]
96 {
97   \begin{frame}
98     % width of a slide is 128 mm
99     \begin{textblock*}{116mm}(6mm,4mm)
100       \begin{tikzpicture}[x=1mm,y=1mm]
101         \filldraw[fill=white,rounded corners=2mm,very thick]
102           (0,0) rectangle (116,75);
103         \draw (58,78) node {};
104       \end{tikzpicture}
105     \end{textblock*}
106     \begin{textblock*}{122mm}(3mm,85mm)
107       \hfill
108       \begin{minipage}[c]{105mm}
109         \centering
110         {\tiny \insertshorttitle{}
111          \hspace{3mm}---\hspace{3mm}
112          \insertshortauthor{}
113          \hspace{3mm}---\hspace{3mm}
114          \insertframenumber\,/\,\inserttotalframenumber}
115       \end{minipage}
116       \hfill
117       \begin{minipage}[c]{5mm}
118         \includegraphics[width=5mm]{gitlogo.pdf}
119       \end{minipage}
120     \end{textblock*}
121     \begin{textblock*}{\textwidth}(10mm,14mm)
122       \tableofcontents[currentsection,hideothersubsections]
123     \end{textblock*}
124   \end{frame}
127 \begin{document}
129 \lstset{%
130   basicstyle=\scriptsize,%
131   language=C,%
132   identifierstyle=\color{black}\bfseries,%
133   keywordstyle=\color{darkgreen}\bfseries,%
134   commentstyle=\color{teal},%
135   stringstyle=\color{red},
136   showstringspaces=false,%
137   tabsize=4%
140 \begin{frame}
141   % width of a slide is 128 mm
142   \begin{textblock*}{116mm}(6mm,6mm)
143     \begin{tikzpicture}[x=1mm,y=1mm]
144       \filldraw[fill=white,rounded corners=2mm,very thick]
145         (0,0) rectangle (116,84);
146     \end{tikzpicture}
147   \end{textblock*}
148   \begin{textblock*}{\textwidth}(10mm,16mm)
149     \titlepage
150   \end{textblock*}
151 \end{frame}
153 \begin{frameframe}{Statistiken: Wer seid ihr?}
154   \begin{itemize}
155     \item<+-> Wer bezeichnet sich als Programmierer?
156     \item<+-> Wer arbeitet an einem OpenSource-Projekt?
157     \begin{itemize}
158       \item<+-> … mit mehr als 1 Entwickler?
159       \item<+-> … mit mehr als 10 Entwicklern?
160       \item<+-> … mit mehr als 100 Entwicklern?
161       \item<+-> … mit mehr als 1000 Entwicklern?
162     \end{itemize}
163     \item<+-> Wer hat schon ein Versionsverwaltungssystem (VCS) verwendet?
164     \item<+-> Wer hat schon ein zentrales VCS (CVS, SVN, …) verwendet?
165     \item<+-> Wer hat schon ein dezentrales VCS (Git, bzr, Mercurial, …)
166       verwendet?
167     \item<+-> Wer hat schon mit Git gearbeitet?
168   \end{itemize}
169 \end{frameframe}
171 \section{Grundlagen: Was ist Versionskontrolle?}
172 \begin{frameframe}{Grundlagen: Was ist Versionskontrolle?}
173   \begin{itemize}
174     \item technisch gesehen: ein Haufen Dateien mit Meta-Informationen und
175       irgendwelchen Beziehungen untereinander \smiley{}
177     \vspace{5mm}
179     \uncover<2>{
180     \item Protokollieren von Änderungen an (Quell-)text
181     \item Archivierung mit "`Rücksetz-Operation"'
182     \item koordinierter Zugriff
183     \item parallele Entwicklungszweige (neue Features, alte Releases)
184     }
185   \end{itemize}
186 \end{frameframe}
188 \begin{frameframe}{Grundlagen: Typen von VCSen}
189   \begin{textblock*}{\textwidth}(10mm,30mm)
190     \begin{itemize}
191       \item lock/modify/write
192       \item copy/modify/merge
194       \vspace{5mm}
196       \uncover<2->{
197       \item \alert<2>{lokale Versionierung}
198       \item \alert<3>{zentrale Versionierung}
199       \item \alert<5>{dezentrale Versionierung}
200       }
201     \end{itemize}
202   \end{textblock*}
204   \only<4>{
205     \begin{textblock*}{\textwidth}(10mm,20mm)
206       \centering
207       \begin{tikzpicture}[x=1mm,y=1mm]
208         \filldraw[fill=white,color=white] (-52,-27) rectangle (52,27);
209         \draw (0,0) node[thin,rounded corners=2mm,draw]
210           (repo) { zentrales Repo };
211         \draw (-30, 10) node[rounded corners,fill=yellow,draw]
212           (c0) { Committer 0 };
213         \draw (0, 20) node[rounded corners,fill=yellow,draw]
214           (c1) { Committer 1 };
215         \draw (30, 10) node[rounded corners,fill=yellow,draw]
216           (c2) { Committer 2 };
217         \draw (30, -10) node[rounded corners,fill=yellow,draw]
218           (c3) { Committer 3 };
219         \draw (0, -20) node { \LARGE … };
220         \draw [->] (c0.south east) -- (repo.north west);
221         \draw [->] (c1.south) -- (repo.north);
222         \draw [->] (c2.south west) -- (repo.north east);
223         \draw [->] (c3.north west) -- (repo.south east);
224       \end{tikzpicture}
225     \end{textblock*}
226   }
227 \end{frameframe}
229 \section{Dezentrale Versionskontrolle}
230 \begin{frameframe}{Workflow in OpenSource Projekten}
231   \begin{textblock*}{\textwidth}(10mm,30mm)
232     \begin{itemize}
233       \item üblicherweise ein/wenige Hauptentwickler/Projektleiter
234       \item viele Mitwirkende (versch.\ Umfang/Arbeitsgebiet)
235       \item ggf.\ Subsystem-Verantwortliche;\newline
236         Entwickler mit mehreren Arbeitsrechnern
237       \item ein "`zentraler"'/"`offizielles"' Repository
238       \item temporäre und Feature-Branches
239     \end{itemize}
240   \end{textblock*}
242   \only<2>{
243     \begin{textblock*}{\textwidth}(10mm,20mm)
244       \centering
245       \begin{tikzpicture}[x=1mm,y=1mm]
246         \filldraw[fill=white,color=white] (-52,-27) rectangle (52,27);
247         \draw (0,0) node[thin,rounded corners=2mm,draw]
248           (r0) { Repo 0 };
249         \draw (-25, 10) node[rounded corners,fill=yellow,draw]
250           (r1) { Repo 1 };
251         \draw (0, 20) node[rounded corners,fill=yellow,draw]
252           (r2) { Repo 2 };
253         \draw (-30, 27) node[rounded corners,fill=yellow,draw]
254           (r3) { Repo 3 };
255         \draw (30, 10) node[rounded corners,fill=yellow,draw]
256           (r4) { Repo 4 };
257         \draw (30, -10) node[rounded corners,fill=yellow,draw]
258           (r5) { Repo 5 };
259         \draw (0, -20) node { \LARGE … };
260         \draw [<->] (r1.south east) -- (r0.west);
261         \draw [<->] (r2.south west) -- (r1.north east);
262         \draw [<->] (r3.south) -- (r1.north);
263         \draw [<->] (r3.east) -- (r2.north west);
264         \draw [<->] (r4.south west) -- (r0.north east);
265         \draw [<->] (r5.north west) -- (r0.south east);
266         \draw [<->] (r5.north) -- (r4.south);
267       \end{tikzpicture}
268     \end{textblock*}
269   }
270 \end{frameframe}
272 \begin{frameframe}{Grundlagen von dezentralen VCSen}
273   \begin{itemize}
274     \item "`Peer-to-Peer"' Ansatz
275     \item jede Arbeitskopie bringt ein komplettes Repository mit (Klon)
276     \item gearbeitet wird auf lokalem Repository\newline
277       $\Rightarrow$ kein Netzwerk-Zugriff nötig\newline
278       $\Rightarrow$ Operationen schnell\newline
279       $\Rightarrow$ Offline-Arbeit möglich
280     \item automatisches "`Backup"' durch Repository-Klons
281     \item Zusammenführen meist auf Basis eines "`Web-of-Trust"'
282   \end{itemize}
283 \end{frameframe}
285 \begin{frameframe}{Arbeitsweise}
286   {
287   \vspace*{-5mm}
288   \hspace*{10mm}
289   \begin{tikzpicture}[x=1mm,y=1mm]
290     \node[cylinder,draw,shape border rotate=90,black,%
291       minimum width=25mm, minimum height=10mm,%
292       cylinder uses custom fill,cylinder end fill=yellow!90,%
293       cylinder body fill=yellow!60] at (0,0) {};
294     \draw (25, 0) node[anchor=west] { Repository };
295     \node[cylinder,draw,shape border rotate=90,black,%
296       minimum width=25mm, minimum height=10mm,%
297       cylinder uses custom fill,cylinder end fill=orange!90,%
298       cylinder body fill=orange!60] at (0,20) {};
299     \draw (25, 20) node[anchor=west] { Arbeitskopie };
301     \uncover<2,7>{
302       \draw[thick,->] (12.5, 5) -- (12.5, 17);
303       \draw (15,11) node[anchor=west] { \ttfamily checkout };
304     }
306     \uncover<3,7>{
307       \draw[thick,->] (0,25) .. controls (7,35) and (-7,35) .. (0,25);
308       \draw (0, 37.5) node { \ttfamily modify };
309     }
311     \uncover<4,7>{
312       \draw[thick,->] (-12.5, 17) -- (-12.5, 5);
313       \draw (-10,11) node[anchor=west] { \ttfamily commit };
314     }
316     \only<5->{
317       \node[cylinder,draw,shape border rotate=90,black,%
318         minimum width=25mm, minimum height=10mm,%
319         cylinder uses custom fill,cylinder end fill=yellow!90,%
320         cylinder body fill=yellow!60] at (0,-20) {};
321       \draw (25, -20) node[anchor=west] { anderes Repository };
323       \uncover<6>{
324         \draw[thick,->] (12.5, -15) -- (12.5, -3);
325         \draw (15,-9) node[anchor=west] { \ttfamily fetch };
326       }
328       \uncover<8>{
329         \draw[thick,->] (-12.5, -3) -- (-12.5, -15);
330         \draw (-10,-9) node[anchor=west] { \ttfamily push };
331       }
332     }
333   \end{tikzpicture}
334   }
335 \end{frameframe}
337 % TODO - Datenhaltung in Git (-> Git for Computer Scientists)
339 \section{Arbeiten mit Git}
340 \begin{frameframe}{Git: Übersicht}
341   \begin{itemize}
342     \item \url{http://www.git.or.cz/}
343     \item VCS (Version Control System)
344     \item 2005 von Linus Torvalds initiiert\newline
345       (aktueller Maintainer: Junio C. Hamano)
346     \item dezentral
347     \item schnell und effizient
348     \item kryptographisch gesichert
349     \item "`Toolkit design"'
350     \item OpenSource (GPLv2)
351     \item weit verbreitet im Einsatz (z.B.\ Linux Kernel, Ruby on Rails, Perl,
352       WINE, X.org, GNOME, Qt, Debian, …)
353   \end{itemize}
354 \end{frameframe}
356 \begin{frameframe}{Arbeiten mit Git: Grundlagen}
357   \begin{itemize}
358     \item $>>$ 100 einzelne Befehle
359     \item "`Porcelains"' und "`Plumbing"'
360     \item Dokumentation als Manpages - \texttt{git(7)}
361     \item \texttt{git help}, \texttt{git $<$command$>$ -h}
362     \item Benutzer Handbuch:
363       \url{http://www.kernel.org/pub/software/scm/git/docs/user-manual.html}
364   \end{itemize}
365 \end{frameframe}
367 \begin{frameframe}{Datenhaltung: Git Objektdatenbank}
368   \begin{itemize}
369     \item DAG (directed acyclic graph)
370     \item Objekte identifiziert durch SHA-1 Summe
371   \end{itemize}
373   \hspace*{15mm}
374   \begin{tikzpicture}[x=1mm,y=1mm]
375     \draw (0,0) node[thin,rounded corners=2mm,draw]
376       (blob) { blob };
378     \uncover<2->{
379       \draw (0, 20) node[thin,rounded corners=2mm,draw]
380         (tree) { tree };
381       \draw [->] (tree.south) -- (blob.north);
382       \draw (2,10) node[anchor=west] { \footnotesize name, mode };
383       \draw [->] (tree.north east) .. controls (10,25) and (10,15)
384         .. (tree.south east);
385       \draw (10, 20) node[anchor=west] { \footnotesize subdir };
386     }
388     \uncover<3->{
389       \draw (0,40) node[thin,rounded corners=2mm,draw]
390         (commit) { commit };
391       \draw [->] (commit.south) -- (tree.north);
392       \draw [->] (commit.north east) .. controls (15,45) and (15,35)
393         .. (commit.south east);
394       \draw (15,40) node[anchor=west] { \footnotesize parents };
395     }
397     \uncover<4->{
398       \draw (-20,40) node[thin,draw,fill=yellow]
399         (branch) { branch };
400       \draw [->] (branch.east) -- (commit.west);
401       \draw (-20,30) node[thin,draw,fill=yellow]
402         (head) { HEAD };
403       \draw[dashed,->] (head.north) -- (branch.south);
404     }
406     \uncover<5->{
407       \draw (-20,10) node[thin,draw,fill=orange]
408         (tag) { tag };
409       \draw [->] (tag.north east) -- (commit.south west);
410       \draw (-20, 3) node { \footnotesize name, message };
411     }
412   \end{tikzpicture}
413 \end{frameframe}
415 \begin{frameframe}{Git konfigurieren}
416   \begin{block}{Sich Git vorstellen}
417   \begin{itemize}
418     \item \texttt{git config --global user.name $<$Dein Name$>$}
419     \item \texttt{git config --global user.email $<$du@deine-domain.tld$>$}
420     \item $\rightarrow$ Benutzerinformationen für Commit-Metadaten
421   \end{itemize}
422   \end{block}
424   \uncover<2>{
425   \begin{block}{Bunt und in Farbe}
426   \begin{itemize}
427     \item \texttt{git config --global color.ui auto}
428     \item $\rightarrow$ farbige \texttt{branch}, \texttt{diff}, \texttt{grep},
429       \texttt{status} Ausgaben
430   \end{itemize}
431   \end{block}
432   }
433 \end{frameframe}
435 \begin{frameframe}{Repositories erstellen}
436   \begin{block}{Neues, leeres Repository}
437     \ttfamily
438     \footnotesize
439     \$ mkdir project\newline
440     \$ cd project\newline
441     \$ git init\newline
442     Initialized empty Git\newline
443     repository in .../.git/
444   \end{block}
446   \vspace{5mm}
448   \uncover<2>{
449   \begin{block}{Bestehendes Repository "`klonen"'}
450     \ttfamily
451     \footnotesize
452     \$ git clone $<$rep$>$\newline
453     ...
454   \end{block}
455   }
456 \end{frameframe}
458 \begin{frameframe}{Änderungen vornehmen}
459   \begin{block}{Ändern}
460     {\ttfamily
461     \footnotesize
462     \$ vim foo bar\newline
463     \$ git add foo bar
464     }
466     \begin{itemize}
467       \item \texttt{add}, \texttt{rm}, \texttt{mv}
468     \end{itemize}
469   \end{block}
471   \uncover<2>{
472   \begin{block}{Geschichte fortführen/ändern}
473     {\ttfamily
474     \footnotesize
475     \$ git commit
476     }
478     \vspace{5mm}
480     {\ttfamily
481     \footnotesize
482     \$ git reset --hard HEAD\textasciicircum
483     }
485     \begin{itemize}
486       \item \texttt{reset}, \texttt{revert}, \texttt{checkout}
487     \end{itemize}
488   \end{block}
489   }
490 \end{frameframe}
492 \begin{frameframe}{Exkurs: Commit Meldungen schreiben}
493   \begin{itemize}
494     \item Einzeilige, kurze ($<$ 80, optimal $<$ 50 Zeichen)
495         Zusammenfassung
496     \item Leerzeile
497     \item Detaillierte Beschreibung/Erklärung
498     \item nicht vorgeschrieben, aber "`common practice"' und von vielen
499         Tools erwartet
500   \end{itemize}
501 \end{frameframe}
503 \begin{frameframe}{Exkurs: Commit Meldungen schreiben}
504     \footnotesize
505     \begin{verbatim}
506 git-remote: do not use user input in a printf format string
508 'git remote show' substituted the remote name into a string that
509 was later used as a printf format string. If a remote name contains
510 a printf format specifier like this:
512    $ git remote add foo%sbar .
514 then the command
516    $ git remote show foo%sbar
518 would print garbage (if you are lucky) or crash. This fixes it.
519     \end{verbatim}
520 \end{frameframe}
522 \begin{frameframe}{Aus der Geschichte lernen}
523   \begin{block}{Status der Arbeitskopie}
524     \ttfamily
525     \footnotesize
526     \$ git status\newline
527     \$ git diff
528   \end{block}
530   \uncover<2->{
531   \begin{block}{Historie betrachten}
532     \ttfamily
533     \footnotesize
534     \$ git log\newline
535     \$ tig
536   \end{block}
537   }
539   \uncover<3->{
540   \begin{block}{Objekte betrachten}
541     {\ttfamily
542     \footnotesize
543     \$ git show\newline
544     \$ git show HEAD:foo
545     }
547     \begin{itemize}
548       \item Commits, Trees, Blobs, Tags
549     \end{itemize}
550   \end{block}
551   }
552 \end{frameframe}
554 \begin{frameframe}{Tags}
555   {\ttfamily
556   \footnotesize
557   \$ git tag -m ``$<$Beschreibung$>$'' $<$Name$>$ $<$Commit$>$\newline
558   \$ git tag -l
559   }
561   \vspace{5mm}
563   \begin{itemize}
564     \item "`Zeiger"' auf einen Commit\newline
565       optional mit Metadaten ("'annotated tag"')
566     \item Kennzeichnung von bestimmten Entwicklungsständen (insb.\ Releases)
567     \item "`annotated tag"': Autor, Datum, Beschreibung, optional GnuPG
568       Signatur
569   \end{itemize}
570 \end{frameframe}
572 \begin{frameframe}{Branching und Merging}
573   \begin{itemize}
574     \item Branch: "`automatischer"' Zeiger auf eine Reihe von Commits
575     \item \texttt{HEAD}: Zeiger auf den aktuellen Branch
576     \item \texttt{master}: "`Standard"'-Branch
577     \item Merge: Zusammenführen von zwei Entwicklungssträngen
578   \end{itemize}
580   \begin{block}{Branch erzeugen}
581     \ttfamily
582     \footnotesize
583     \$ git checkout -b $<$Name$>$
585     \vspace{5mm}
587     \uncover<2>{
588     \$ git branch\newline
589     \hspace*{1em}master\newline
590     * new-branch
591     }
592   \end{block}
593 \end{frameframe}
595 \begin{frameframe}{Branching und Merging}
596   \begin{block}{Branches zusammenführen}
597     \ttfamily
598     \footnotesize
599     \$ git merge master\newline
600     \$ git rebase master
601   \end{block}
603   \uncover<2>{
604   \begin{block}{Konflikte auflösen}
605     \begin{itemize}
606       \item Konflikte entstehen, wenn die gleiche Stelle unterschiedlich
607         geändert wurde\newline
608         $\Rightarrow$ manuelles Eingreifen nötig
609       \item Commit-Erzeugung wird unterbrochen
610       \item Konfliktanzeiger in den betroffenen Dateien
611       \item manuelle Entscheidung, wie beide Änderungen zusammengeführt werden
612     \end{itemize}
613   \end{block}
614   }
615 \end{frameframe}
617 \begin{frameframe}{Arbeiten mit anderen Repositories}
618   \begin{block}{Repository klonen}
619     \ttfamily
620     \footnotesize
621     \$ git clone <rep>
622   \end{block}
624   \begin{block}{Austauschen von Änderungen}
625     {\ttfamily
626     \footnotesize
627     \$ git pull\newline
628     \$ git push
629     }
631     \vspace{5mm}
633     Alternativ:
634     \begin{itemize}
635       \item \texttt{git format-patch}, \texttt{git send-mail}
636     \end{itemize}
637   \end{block}
638 \end{frameframe}
640 \begin{frameframe}{Arbeiten mit anderen Repositories}
641   \begin{itemize}
642     \item "`remote"': Repository, dessen Änderungen verfolgt werden
643     \item "`remote branch"': Branch, welcher der Zustand in einem anderen
644       Repository wiederspiegelt
645     \item technisch: Branch in einem anderen Namensraum mit anderer Semantik
646   \end{itemize}
648   \vspace{5mm}
650   \begin{block}{Arbeiten mit "`remotes"'}
651     \ttfamily
652     \footnotesize
653     \$ git remote add $<$Name$>$ URL\newline
654     \$ git remote update $<$Name$>$
655   \end{block}
656 \end{frameframe}
658 \begin{frameframe}{Repository URLs}
659   \begin{itemize}
660     \item lokal: \texttt{/path/to/repository/}
661     \item http: \texttt{http://domain.tld/repository.git}
662     \item git: \texttt{git://domain.tld/repository.git}
663     \item ssh: \texttt{domain.tld:path/to/repository/}
664   \end{itemize}
665 \end{frameframe}
667 \begin{frameframe}{Frontends}
668   \begin{itemize}
669     \item \texttt{tig} (ncurses)
670     \item \texttt{gitk} (Tk, read-only)
671     \item \texttt{qgit} (Qt)
672     \item \texttt{magit} (emacs)
673   \end{itemize}
674 \end{frameframe}
676 \begin{frameframe}{Goodies}
677   \begin{itemize}
678     \item<+-> \texttt{git reflog}
679     \item<+-> \texttt{git rebase -i}
680     \item<+-> \texttt{git commit --amend}
681     \item<+-> \texttt{git add -p}
682     \item<+-> \texttt{git stash}
683     \item<+-> \texttt{git bisect}
684     \item<+-> \texttt{git cherry} / \texttt{git-wtf}
685     \item<+-> \texttt{git diff color-words}
686     \item<+-> \texttt{git svn}
687   \end{itemize}
688 \end{frameframe}
690 \begin{frameframe}{\insertshorttitle{}}
691   \begin{center}
692     Vielen Dank für die Aufmerksamkeit!
694     \vspace{10mm}
696     {\Large Gibt es Fragen?}
698     \vspace{10mm}
700     Kontakt:\\
701     Sebastian "`tokkee"' Harl\\
702     $<$tokkee@debian.org$>$
703   \end{center}
704 \end{frameframe}
706 \end{document}
708 % vim: set shiftwidth=2 softtabstop=2 tabstop=8 spelllang=de_de :