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}
125 }
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%
138 }
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 :