merging.tex 17 KB
Newer Older
1 2
\documentclass[slidestop]{beamer}

Mihai's avatar
Mihai committed
3 4
\usepackage{framed}

5 6
\input{../shared/shared.tex}

Mihai's avatar
Mihai committed
7
\author{Mihai Lefter}
8 9
\title{\courseTitle}
\providecommand{\mySubTitle}{Combining changes by merging}
10
\providecommand{\myConference}{\courseTitle}
11
\providecommand{\myGroup}{}
12 13
\providecommand{\myDepartment}{Department of Human Genetics}
\providecommand{\myCenter}{Center for Human and Clinical Genetics}
14

Mihai's avatar
Mihai committed
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
\definecolor{cblack}{rgb}{0,0,0}
\definecolor{cwhite}{rgb}{1,1,1}
\definecolor{command-color}{rgb}{0,0.5,0}
\definecolor{git-color}{rgb}{0.94,0.23,0.18}
\definecolor{option-color}{rgb}{0.9,0.2,0.11}
\definecolor{argument-color}{rgb}{0.11,0.27,0.7}
\definecolor{pattern-color}{rgb}{0,0.5,0.5}
\definecolor{wildcard-color}{rgb}{0.75,0.3,0}
\definecolor{cli-text}{rgb}{0.15,0.15,0.15}
\definecolor{important-note}{rgb}{0.69,0.13,0.13}
\definecolor{redirection}{rgb}{0.99,0.13,0.13}
\definecolor{shadecolor}{rgb}{0.9,0.9,0.9}
\definecolor{one-dot}{rgb}{0.9,0.2,0.0}
\definecolor{two-dots}{rgb}{0.11,0.11,0.8}
\definecolor{slash}{rgb}{0.3,0.3,0.3}

\definecolor{head}{HTML}{B22222}
\definecolor{branch}{HTML}{20b2aa}
\definecolor{commit-id}{HTML}{b8860b}

35 36 37 38 39 40 41 42 43 44 45 46 47 48
\usetheme{lumc}

\lstset{
  basicstyle=\ttfamily,
  language=none,
  frame=none,
  numbers=none,
  numbersep=0
}

\AtBeginSection[]
{
  \begin{frame}
    \frametitle{Table of contents}
49
    \tableofcontents[currentsection, subsectionstyle=hide/hide]
50 51 52 53 54 55 56 57 58
  \end{frame}
}

\begin{document}

% This disables the \pause command, handy in the editing phase.
%\renewcommand{\pause}{}

% Make the title page.
Mihai's avatar
Mihai committed
59
\makeTitleSlide{\includegraphics[width=3.5cm]{../shared/git_logo.pdf}}
60 61

\section{The Git commit graph}
62 63
\subsection{A linear history}
\begin{pframe}
Mihai's avatar
Mihai committed
64 65 66 67
 \begin{center}
   \includegraphics[width=\textwidth]{images/commit_graph/commit_graph_00.pdf}
 \end{center}
\end{pframe}
68

Mihai's avatar
Mihai committed
69 70 71 72
\begin{pframe}
 \begin{center}
   \includegraphics[width=\textwidth]{images/commit_graph/commit_graph_01.pdf}
 \end{center}
73 74 75 76
\end{pframe}

\subsection{The default \lstinline{master} branch}
\begin{pframe}
Mihai's avatar
Mihai committed
77 78 79 80
 \begin{center}
   \includegraphics[width=\textwidth]{images/commit_graph/commit_graph_02.pdf}
 \end{center}
\end{pframe}
81

Mihai's avatar
Mihai committed
82 83 84 85 86
\subsection{The \lstinline{HEAD} pointer}
\begin{pframe}
 \begin{center}
   \includegraphics[width=\textwidth]{images/commit_graph/commit_graph_03.pdf}
 \end{center}
87
\end{pframe}
88

Mihai's avatar
Mihai committed
89
\subsection{Committing}
90
\begin{pframe}
Mihai's avatar
Mihai committed
91 92 93 94
 \begin{center}
   \includegraphics[width=\textwidth]{images/commit_graph/commit_graph_04.pdf}
 \end{center}
\end{pframe}
95

Mihai's avatar
Mihai committed
96 97 98 99
\begin{pframe}
 \begin{center}
   \includegraphics[width=\textwidth]{images/commit_graph/commit_graph_05.pdf}
 \end{center}
100 101 102 103
\end{pframe}

\subsection{A non-linear history}
\begin{pframe}
Mihai's avatar
Mihai committed
104 105 106
 \begin{center}
   \includegraphics[width=\textwidth]{images/commit_graph/commit_graph_06.pdf}
 \end{center}
107
\end{pframe}
108

109 110
\subsection{Use branches to keep track of different code paths}
\begin{pframe}
Mihai's avatar
Mihai committed
111 112 113
 \begin{center}
   \includegraphics[width=\textwidth]{images/commit_graph/commit_graph_07.pdf}
 \end{center}
114
\end{pframe}
115

Mihai's avatar
Mihai committed
116
\subsection{Merging}
117
\begin{pframe}
Mihai's avatar
Mihai committed
118 119 120
 \begin{center}
   \includegraphics[width=\textwidth]{images/commit_graph/commit_graph_08.pdf}
 \end{center}
121
\end{pframe}
122 123

\section{Inspecting the commit graph}
124 125
\subsection{An example repository}
\begin{pframe}
Mihai's avatar
Mihai committed
126 127 128
 \begin{center}
   \includegraphics[width=\textwidth]{images/inspect_commit_graph/inspect_commit_graph_00.pdf}
 \end{center}
129
\end{pframe}
130

Mihai's avatar
Mihai committed
131
\subsection{Showing the current branch}
132
\begin{pframe}
Mihai's avatar
Mihai committed
133 134 135 136 137
  \begin{framed}
    \textcolor{cli-text}{\lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{status}}\\
    \lstinline{# On branch master}\\
    \lstinline{nothing to commit (working directory clean)}}
  \end{framed}
138

Mihai's avatar
Mihai committed
139
  Remember: you cannot type \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{status}} enough!
140 141
\end{pframe}

Mihai's avatar
Mihai committed
142
\subsection{The commit log}
143
\begin{pframe}
Mihai's avatar
Mihai committed
144 145 146 147 148 149 150 151 152 153 154 155 156 157
  \begin{framed}
    \textcolor{cli-text}{\lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{log}}
    \textcolor{argument-color}{\lstinline{--oneline --decorate}}\\
    \textcolor{commit-id}{\lstinline{c7f3bd9}} \lstinline{(}\textcolor{head}{\lstinline{HEAD}} \lstinline{->} \textcolor{branch}{\lstinline{master}}\lstinline{) Add .gitignore file}\\
    \textcolor{commit-id}{\lstinline{4a44c4e}} \lstinline{Merge branch 'license'}\\
    \textcolor{commit-id}{\lstinline{64af1ee}} \lstinline{Add course teachers to README}\\
    \textcolor{commit-id}{\lstinline{0fbe3e3}} \lstinline{(}\textcolor{branch}{\lstinline{license}}\lstinline{) Add MIT license}\\
    \textcolor{commit-id}{\lstinline{d1c7fd7}} \lstinline{Initial commit with README}
    }
  \end{framed}

  \textcolor{argument-color}{\lstinline{--oneline}}: Shows commit summary on one line.

  \textcolor{argument-color}{\lstinline{--decorate}}: Adds branch information.
158 159
\end{pframe}

Mihai's avatar
Mihai committed
160
\subsection{The commit log as a graph}
161
\begin{pframe}
Mihai's avatar
Mihai committed
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
  \begin{framed}
    \textcolor{cli-text}{\lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{log}}
    \textcolor{argument-color}{\lstinline{--oneline --decorate --graph --all}}\\
    \lstinline{*} \textcolor{commit-id}{\lstinline{8fc25c1}} \lstinline{(}\textcolor{branch}{\lstinline{interface}}\lstinline{) Trivial Python interface}\\
    \lstinline{| *} \textcolor{commit-id}{\lstinline{c7f3bd9}} \lstinline{(}\textcolor{head}{\lstinline{HEAD}} \lstinline{->} \textcolor{branch}{\lstinline{master)}} \lstinline{Add .gitignore file}\\
    \lstinline{|/}\\
    \lstinline{*} \textcolor{commit-id}{\lstinline{4a44c4e}} \lstinline{Merge branch 'license'}\\
    \lstinline{|\\}\\
    \lstinline{| *} \textcolor{commit-id}{\lstinline{0fbe3e3}} \lstinline{(}\textcolor{branch}{\lstinline{license}}\lstinline{) Add MIT license}\\
    \lstinline{* |} \textcolor{commit-id}{\lstinline{64af1ee}} \lstinline{Add course teachers to README}\\
    \lstinline{|/}\\
    \lstinline{*} \textcolor{commit-id}{\lstinline{d1c7fd7}} \lstinline{Initial commit with README}
    }
  \end{framed}
  \vspace{-0.2cm}

  \textcolor{argument-color}{\lstinline{--graph}}: Shows the commit graph.

  \textcolor{argument-color}{\lstinline{--all}}: Includes all branches instead of just the current one.
181 182
\end{pframe}

Mihai's avatar
Mihai committed
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
% \subsection{Annotated log as an alias}
% \begin{pframe}
%   For convenience, we can create an alias for the \lstinline{git log} command
%   with all the arguments we just used:
%   \begin{lstlisting}
% $ git config --global alias.l \
%     'log --oneline --decorate --graph --all'
% $ git l
% * 8fc25c1 (interface) Trivial Python interface
% | * c7f3bd9 (HEAD, master) Add .gitignore file
% |/
% *   4a44c4e Merge branch 'license'
% ...
% \end{lstlisting}
% 
%   This alias is stored in the \lstinline{~/.gitconfig} file. You can also edit
%   that file manually.
% \end{pframe}

\section{Merging from remotes}
203 204 205

\subsection{Remote branches}
\begin{pframe}
Martijn Vermaat's avatar
Martijn Vermaat committed
206
  In this course, we don't really discuss branches, except:
207 208
  \begin{itemize}
    \item Commits from a remote show up as a remote branch.
209 210
    \item Even with only a \lstinline{master} branch, remotes might still
      diverge.
211 212 213
    \item Merging remote branches is just like merging local branches.
  \end{itemize}
  \bigskip
214
\end{pframe}
215

Mihai's avatar
Mihai committed
216
\subsection{Fast forward merging}
217 218
\begin{pframe}

Mihai's avatar
Mihai committed
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
 \begin{framed}
  \textcolor{cli-text}{\lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{fetch}} \textcolor{argument-color}{\lstinline{hue}} \vspace{-0.2cm}\\
  \tiny{
  \lstinline{remote: Counting objects: 5, done.} \vspace{-0.2cm}\\
  \lstinline{remote: Compressing objects: 100\% (2/2), done.} \vspace{-0.2cm}\\
  \lstinline{remote: Total 3 (delta 0), reused 0 (delta 0)} \vspace{-0.2cm}\\
  \lstinline{Unpacking objects: 100\% (3/3), done.} \vspace{-0.2cm}\\
  \lstinline{From 192.168.0.8:docs/tv-series} \vspace{-0.2cm}\\
  \lstinline{* [new branch]      master     -> hue/master}}
 }
  \end{framed}
  \pause
  \begin{center}
   \includegraphics[width=0.8\textwidth]{images/fast_forward/fast_forward_00.pdf} 
  \end{center}
234
\end{pframe}
235

236
\begin{pframe}
Mihai's avatar
Mihai committed
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
 If a remote branch is ahead of us, it can be merged easily:
 \vspace{-0.4cm}
 \begin{framed}
  \textcolor{cli-text}{
   \lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{merge}} \textcolor{argument-color}{\lstinline{hue/master}} \vspace{-0.2cm}\\
   \tiny{
   \lstinline{Updating c7f3bd9..251a51b} \vspace{-0.2cm}\\
   \lstinline{Fast-forward} \vspace{-0.2cm}\\
   \lstinline{testlib.py |    2 +} \vspace{-0.2cm}\\
   \lstinline{1 file changed, 2 insertions(+)}
   }
  }
  \end{framed}
  \pause
  \begin{center}
   \includegraphics[width=0.9\textwidth]{images/fast_forward/fast_forward_01.pdf} 
  \end{center}
254
\end{pframe}
255

Mihai's avatar
Mihai committed
256
\subsection{Three-way merging}
257
\begin{pframe}
Mihai's avatar
Mihai committed
258 259 260 261
  \begin{center}
   \includegraphics[width=\textwidth]{images/three_way/three_way_00.pdf} 
  \end{center}
\end{pframe}
262

Mihai's avatar
Mihai committed
263 264 265 266 267 268 269 270 271 272 273 274 275
\begin{pframe}
  Let's merge the remote work on \lstinline{master} back into our local \lstinline{master}:
 \vspace{-0.8cm}
 \begin{framed}
  \textcolor{cli-text}{
   \lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{merge}} \textcolor{argument-color}{\lstinline{hue/master}} \vspace{-0.2cm}\\
   \tiny{
   \lstinline{Merge made by the 'recursive' strategy.} \vspace{-0.2cm}\\
   \lstinline{FACTS.md | 2 +-} \vspace{-0.2cm}\\
   \lstinline{1 file changed, 1 insertion(+), 1 deletion(-)} 
   }
  }
  \end{framed}
276
\end{pframe}
277

278
\begin{pframe}
Mihai's avatar
Mihai committed
279 280 281
  \begin{center}
   \includegraphics[width=\textwidth]{images/three_way/three_way_01.pdf} 
  \end{center}
282 283 284 285 286 287
\end{pframe}

\subsection{The other way around}
\begin{pframe}
  \lstinline{git push} also does an implicit \lstinline{git merge} on the
  remote.
Mihai's avatar
Mihai committed
288 289 290
  \begin{center}
   \includegraphics[width=0.9\textwidth]{images/three_way/three_way_02.pdf} 
  \end{center}
291
\end{pframe}
292 293

\section{Basic merge conflicts}
294 295
\subsection{Merge conflicts}
\begin{pframe}
296 297 298 299 300 301 302
  Git is pretty good at merging:
  \begin{itemize}
    \item The changes might have been in different files.
    \item Or in different parts of the same file.
    \item Git tries to figure out a sensible result.
  \end{itemize}
  \bigskip
303 304
  \pause

305 306 307
  Sometimes this is not possible:
  \begin{itemize}
    \item The changes might be incompatible.
308
    \item When we try \lstinline{git merge}, Git gives up.
309 310
    \item This situation is called a {\em merge conflict}.
  \end{itemize}
311
\end{pframe}
312

313 314
\subsection{Setting the stage (1/3)}
\begin{pframe}
Mihai's avatar
Mihai committed
315 316 317 318 319 320 321 322 323 324
 \begin{framed}
  \textcolor{cli-text}{
   \lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{log}}
   \textcolor{argument-color}{\lstinline{--oneline --decorate --graph --all}}\\
   \lstinline{* 5edaf08 (hue/master, hue/HEAD) State character ...}\\
   \lstinline{| * f1ef19c (HEAD, master) State character ...}\\
   \lstinline{|/}\\
   \lstinline{* 1f6d2ab Initial commit} 
  }
  \end{framed}
325

326 327 328 329 330
  We'd like to merge branch \lstinline{hue/master} into \lstinline{master}.
\end{pframe}

\subsection{Setting the stage (2/3)}
\begin{pframe}
Mihai's avatar
Mihai committed
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
 The last commit on \lstinline{master}:
 \vspace{-0.3cm}
 \begin{framed}
  \textcolor{cli-text}{
   \lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{show}}\\
   \lstinline{f1ef19c State character preference}\\
   \lstinline{diff --git a/FACTS.md b/FACTS.md}\\
   \lstinline{index de15194..ef40359 100644}\\
   \lstinline{--- a/FACTS.md}\\
   \lstinline{+++ b/FACTS.md}\\
   \lstinline{@@ -1,2 +1,4 @@}\\
   \lstinline{Facts about television series}\\
   \lstinline{=============================}\\
   \lstinline{+}\\
   \lstinline{+My favorite character is Eric Cartman.}
  }
  \end{framed}
348
\end{pframe}
349

350 351
\subsection{Setting the stage (3/3)}
\begin{pframe}
Mihai's avatar
Mihai committed
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
 The last commit on \lstinline{hue/master}:
 \vspace{-0.3cm}
 \begin{framed}
  \textcolor{cli-text}{
   \lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{show}}
   \textcolor{argument-color}{\lstinline{--oneline}} \textcolor{argument-color}{\lstinline{hue/master}}\\
   \lstinline{5edaf08 State character preference}\\
   \lstinline{diff --git a/FACTS.md b/FACTS.md}\\
   \lstinline{index de15194..5e69508 100644}\\
   \lstinline{--- a/FACTS.md}\\
   \lstinline{+++ b/FACTS.md}\\
   \lstinline{@@ -1,2 +1,4 @@}\\
   \lstinline{Facts about television series}\\
   \lstinline{=============================}\\
   \lstinline{+}\\
   \lstinline{+My favorite character is Milhouse.}
  }
  \end{framed}
370
\end{pframe}
371

372 373
\subsection{Creating a merge conflict}
\begin{pframe}
Mihai's avatar
Mihai committed
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
 \vspace{-0.5cm}
 \begin{framed}
  \textcolor{cli-text}{
   \lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{merge}}
   \textcolor{argument-color}{\lstinline{hue/master}}\\
   \lstinline{Auto-merging FACTS.md}\\
   \lstinline{CONFLICT (content): Merge conflict in FACTS.md}\\
   \lstinline{Automatic merge failed; fix conflicts and then}\\
   \lstinline{commit the result.}\\
   \lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{status}}\\
   \lstinline{# On branch master}\\
   \lstinline{# Unmerged paths:}\\
   \lstinline{#   (use "git add/rm <file>.." as appropriate)}\\
   \lstinline{#    to mark resolution)}\\
   \lstinline{#              both modified:      FACTS.md}\\
   \lstinline{# no changes added to commit (use "git add" and/or}\\
   \lstinline{# "git commit -a")}
  }
  \end{framed}
393
\end{pframe}
394

Mihai's avatar
Mihai committed
395
\subsection{Resolving a merge conflict (1/3)}
396
\begin{pframe}
Mihai's avatar
Mihai committed
397 398 399 400 401 402 403 404 405 406 407 408 409
 \begin{framed}
  \textcolor{cli-text}{
   \lstinline{$} \textcolor{command-color}{\lstinline{cat}} \textcolor{argument-color}{\lstinline{FACTS.md}}\\
   \lstinline{Facts about television series}\\
   \lstinline{=============================}\\
   \textcolor{white}{\lstinline{S}}\\
   \lstinline{<<<<<<< HEAD}\\
   \lstinline{My favorite character is Eric Cartman.}\\
   \lstinline{=======}\\
   \lstinline{My favorite character is Milhouse.}\\
   \lstinline{>>>>>>> hue/master}
  }
  \end{framed}
410 411 412 413

  What we had is under \lstinline{HEAD}, what \lstinline{hue/master} had is
  above \lstinline{hue/master}.
\end{pframe}
414

Mihai's avatar
Mihai committed
415
\subsection{Resolving a merge conflict (2/3)}
416
\begin{pframe}
417
  We resolve the conflict by hand.
Mihai's avatar
Mihai committed
418 419 420 421 422 423 424 425 426 427 428 429
 \begin{framed}
  \textcolor{cli-text}{
   \lstinline{$} \textcolor{command-color}{\lstinline{nano}} \textcolor{argument-color}{\lstinline{FACTS.md}} \\
   \lstinline{$} \textcolor{command-color}{\lstinline{cat}} \textcolor{argument-color}{\lstinline{FACTS.md}} \\
   \lstinline{Facts about television series}\\
   \lstinline{=============================}\\
   \textcolor{white}{\lstinline{S}}\\
   \lstinline{My favorite characters are Eric Cartman}\\
   \lstinline{and Milhouse.}
  }
  \end{framed}
\end{pframe}
430

Mihai's avatar
Mihai committed
431 432
\subsection{Resolving a merge conflict (3/3)}
\begin{pframe}
433
  And can now finish the merge commit.
Mihai's avatar
Mihai committed
434 435 436 437 438 439 440 441
 \begin{framed}
  \textcolor{cli-text}{
   \lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{add}} \textcolor{argument-color}{\lstinline{FACTS.md}} \\
   \lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{commit}} \\
   \lstinline{[master 1e496cb] Merge remote-tracking branch}\\
   \lstinline{'hue/master'}
  }
  \end{framed}
442
\end{pframe}
443

Mihai's avatar
Mihai committed
444

445 446
\subsection{Aborting a merge}
\begin{pframe}
447
  If you don't feel like resolving the merge conflict, you can go back with
448
  \lstinline{git merge --abort}.
Mihai's avatar
Mihai committed
449 450 451 452 453 454 455 456 457 458 459 460 461
 \begin{framed}
  \textcolor{cli-text}{
   \lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{merge}} \textcolor{argument-color}{\lstinline{hue/master}} \\
   \lstinline{Auto-merging FACTS.md}\\
   \lstinline{CONFLICT (content): Merge conflict in FACTS.md}\\
   \lstinline{Automatic merge failed; fix conflicts and then}\\
   \lstinline{commit the result.}\\
   \lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{merge}} \textcolor{argument-color}{\lstinline{--abort}} \\
   \lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{status}}\\
   \lstinline{# On branch master}\\
   \lstinline{# nothing to commit (working directory clean)}
  }
  \end{framed}
462
\end{pframe}
463

464 465
\subsection{Resolving conflicts with \lstinline{git mergetool}}
\begin{pframe}
466
  We can also use graphical merge tools such as {\em Meld}.
Mihai's avatar
Mihai committed
467 468 469 470 471 472 473 474 475 476 477 478 479
 \begin{framed}
  \textcolor{cli-text}{
   \lstinline{$} \textcolor{git-color}{\lstinline{git}} \textcolor{command-color}{\lstinline{mergetool}}\\
   \lstinline{merge tool candidates: meld opendiff kdiff3 ...}\\
   \lstinline{Merging:}\\
   \lstinline{FACTS.md}\\
   \textcolor{white}{\lstinline{S}}\\
   \lstinline{Normal merge conflict for 'FACTS.md':}\\
   \textcolor{white}{\lstinline{ss}}\lstinline{local: modified file}\\
   \textcolor{white}{\lstinline{ss}}\lstinline{remote: modified file}\\
   \lstinline{Hit return to start merge resolution tool (meld):}
  }
  \end{framed}
480
\end{pframe}
481

482 483 484 485
\subsection{Meld example}
\begin{pframe}
  \includegraphics[width=11cm]{meld}
  \smallskip
486

487 488
  Tools like Meld provide an editable three-way diff.
\end{pframe}
489

490 491 492 493 494
\makeAcknowledgementsSlide{
  \begin{tabular}{l}
    \acknowledgements
  \end{tabular}
  \bigskip
495

Mihai's avatar
Mihai committed
496
  \hfill\includegraphics[width=3.5cm]{../shared/git_logo.pdf}
497

498 499 500 501 502
  \begin{tabular}{l}
    \small\url{http://git-scm.com/book}\\
    \small\url{https://www.atlassian.com/git}
  \end{tabular}
}
503 504

\end{document}