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

3 4
\input{../shared/shared.tex}

5
\author{Martijn Vermaat}
6 7
\title{\courseTitle}
\providecommand{\mySubTitle}{Combining changes by merging}
8
\providecommand{\myConference}{\courseTitle}
9
\providecommand{\myGroup}{}
10 11
\providecommand{\myDepartment}{Department of Human Genetics}
\providecommand{\myCenter}{Center for Human and Clinical Genetics}
12

13 14 15 16 17 18 19 20 21 22 23 24 25 26
\usetheme{lumc}

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

\AtBeginSection[]
{
  \begin{frame}
    \frametitle{Table of contents}
27
    \tableofcontents[currentsection, subsectionstyle=hide/hide]
28 29 30 31 32 33 34 35 36
  \end{frame}
}

\begin{document}

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

% Make the title page.
37
\makeTitleSlide{\includegraphics[width=3.5cm]{git_logo}}
38 39

\section{The Git commit graph}
40 41 42 43
\subsection{A linear history}
\begin{pframe}
  \includegraphics[width=10cm]{linear}
  \smallskip
44 45 46 47 48

  \begin{itemize}
    \item Every commit has a parent.
    \item {\em Committing} creates a new commit on top of the current one.
  \end{itemize}
49 50 51 52 53 54
\end{pframe}

\subsection{The default \lstinline{master} branch}
\begin{pframe}
  \includegraphics[width=10cm]{master}
  \smallskip
55 56 57

  \begin{itemize}
    \item A {\em branch} is a pointer to a commit.
58 59 60
    \item By default there is one branch: \lstinline{master}.
    \item \lstinline{HEAD} is a special pointer, it points to the current
      branch.
61
  \end{itemize}
62
\end{pframe}
63

64 65
\subsection{Committing moves the current branch pointer}
\begin{pframe}
66 67
  \begin{itemize}
    \item Committing moves the current branch to the new commit.
68
    \item (Of course, \lstinline{HEAD} moves with it.)
69
  \end{itemize}
70 71 72 73 74 75 76 77 78
  \bigskip

  \includegraphics[width=10cm]{commit}
\end{pframe}

\subsection{A non-linear history}
\begin{pframe}
  \includegraphics[width=10cm]{nonlinear}
  \smallskip
79 80 81 82 83

  \begin{itemize}
    \item The commit graph can become non-linear.
    \item Usually by committing from the same commit twice.
  \end{itemize}
84
\end{pframe}
85

86 87
\subsection{Use branches to keep track of different code paths}
\begin{pframe}
88 89 90 91
  \begin{itemize}
    \item Branch names are easier to remember than commit hashes.
    \item Branch names make it clear what commits are about.
  \end{itemize}
92 93 94 95
  \bigskip

  \includegraphics[width=6cm]{branches}
\end{pframe}
96

97 98
\subsection{Different code paths may later join}
\begin{pframe}
99 100 101 102
  \begin{itemize}
    \item Commits from different branches can be brought together.
    \item We call this {\em merging}.
  \end{itemize}
103
  \bigskip
104

105 106
  \includegraphics[width=6cm]{merge}
\end{pframe}
107 108

\section{Inspecting the commit graph}
109 110 111 112
\subsection{An example repository}
\begin{pframe}
  \includegraphics[width=8cm]{example}
  \smallskip
113 114

  \begin{itemize}
115 116 117 118 119
    \item Branches \lstinline{license} and \lstinline{interface} diverged from
      \lstinline{master}.
    \item Only \lstinline{license} has been merged back into
      \lstinline{master}.
    \item Current branch is \lstinline{master}.
120
  \end{itemize}
121
\end{pframe}
122

123 124
\subsection{Showing the current branch: \lstinline{git status}}
\begin{pframe}
125 126 127 128 129 130
  \begin{lstlisting}
$ git status
# On branch master
nothing to commit (working directory clean)
  \end{lstlisting}

131 132 133 134 135
  Remember: you cannot type \lstinline{git status} enough!
\end{pframe}

\subsection{The commit log: \lstinline{git log}}
\begin{pframe}
136 137 138 139 140 141 142 143 144
  \begin{lstlisting}
$ git log --oneline --decorate
c7f3bd9 (HEAD, master) Add .gitignore file
4a44c4e Merge branch 'license'
64af1ee Add course teachers to README
0fbe3e3 (license) Add MIT license
d1c7fd7 Initial commit with README
  \end{lstlisting}

145
  \lstinline{--oneline}: Shows commit summary on one line.
146

147 148 149 150 151
  \lstinline{--decorate}: Adds branch information.
\end{pframe}

\subsection{The commit log as a graph: \lstinline{git log}}
\begin{pframe}
152 153 154 155 156 157 158 159 160 161 162 163 164
  \begin{lstlisting}
$ git log --oneline --decorate --graph --all
* 8fc25c1 (interface) Trivial Python interface
| * c7f3bd9 (HEAD, master) Add .gitignore file
|/
*   4a44c4e Merge branch 'license'
|\
| * 0fbe3e3 (license) Add MIT license
* | 64af1ee Add course teachers to README
|/
* d1c7fd7 Initial commit with README
  \end{lstlisting}

165
  \lstinline{--graph}: Shows the commit graph.
166

167 168 169 170 171 172 173
  \lstinline{--all}: Includes all branches instead of just the current.
\end{pframe}

\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:
174 175 176 177 178 179 180 181 182 183 184
  \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}

185 186 187 188 189 190
  This alias is stored in the \lstinline{~/.gitconfig} file. You can also edit
  that file manually.
\end{pframe}

\subsection{Remote branches}
\begin{pframe}
Martijn Vermaat's avatar
Martijn Vermaat committed
191
  In this course, we don't really discuss branches, except:
192 193
  \begin{itemize}
    \item Commits from a remote show up as a remote branch.
194 195
    \item Even with only a \lstinline{master} branch, remotes might still
      diverge.
196 197 198
    \item Merging remote branches is just like merging local branches.
  \end{itemize}
  \bigskip
199 200
  \includegraphics[width=10cm]{example-hue}
\end{pframe}
201

Martijn Vermaat's avatar
Martijn Vermaat committed
202
\section{Merging from remotes}
203 204 205 206 207 208 209 210
\subsection{An example repository}
\begin{pframe}
  \includegraphics[width=10cm]{example-hue}
  \smallskip

  Branch \lstinline{master} on \lstinline{hue} is one commit ahead of our
  \lstinline{master} and we have already seen how to merge
  \lstinline{hue/master} into \lstinline{master}:
211
  \begin{itemize}
212 213 214
    \item \lstinline{git merge hue/master}
    \item This was easy: Git just moves \lstinline{master} (and
      \lstinline{HEAD}) to point to \lstinline{hue/master}.
Martijn Vermaat's avatar
Martijn Vermaat committed
215
    \item It is called a {\em fast forward merge}.
216
  \end{itemize}
217
\end{pframe}
218

219 220
\subsection{Fast forward merging: \lstinline{git merge}}
\begin{pframe}
Martijn Vermaat's avatar
Martijn Vermaat committed
221
  If a remote branch is ahead of us, it can be merged easily:
222
  \begin{lstlisting}
Martijn Vermaat's avatar
Martijn Vermaat committed
223 224 225 226 227
$ git merge hue/master
Updating c7f3bd9..251a51b
Fast-forward
testlib.py |    2 +
1 file changed, 2 insertions(+)
228 229
  \end{lstlisting}

230 231
  \includegraphics[width=10cm]{example-hue-merged}
\end{pframe}
232

233 234 235 236 237 238 239
\subsection{An example repository}
\begin{pframe}
  \includegraphics[width=8cm]{example-hue-diverged}
  \smallskip

  Branch \lstinline{master} on \lstinline{hue} and our \lstinline{master} have
  diverged and merging now seems less straightforward.
240
  \begin{itemize}
241
    \item \lstinline{git merge hue/master}
Martijn Vermaat's avatar
Martijn Vermaat committed
242 243 244
    \item Git will create a new commit in which it combines both changes.
    \item It is called a {\em three-way merge}.
    \item The {\em merge commit} has two parents.
245
  \end{itemize}
246
\end{pframe}
247

248 249 250 251
\subsection{Three-way merging: \lstinline{git merge}}
\begin{pframe}
  Let's merge the remote work on \lstinline{master} back into our local
  \lstinline{master}:
252
  \begin{lstlisting}
Martijn Vermaat's avatar
Martijn Vermaat committed
253
$ git merge hue/master
254
Merge made by the 'recursive' strategy.
Martijn Vermaat's avatar
Martijn Vermaat committed
255 256
 FACTS.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
257 258
  \end{lstlisting}

259 260 261 262 263 264 265
  \includegraphics[width=9cm]{example-hue-merged2}
\end{pframe}

\subsection{The other way around}
\begin{pframe}
  \lstinline{git push} also does an implicit \lstinline{git merge} on the
  remote.
Martijn Vermaat's avatar
Martijn Vermaat committed
266 267 268 269 270 271
  \begin{itemize}
    \item We send our local commits to the remote.
    \item They are merged into the remote branch.
    \item But only if this is a fast-forward merge.
    \item Diverging commits {\em cannot be pushed directly}.
  \end{itemize}
272 273
  \bigskip

274 275
  \includegraphics[width=10cm]{example-hue-pushed}
\end{pframe}
276 277

\section{Basic merge conflicts}
278 279
\subsection{Merge conflicts}
\begin{pframe}
280 281 282 283 284 285 286
  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
287 288
  \pause

289 290 291
  Sometimes this is not possible:
  \begin{itemize}
    \item The changes might be incompatible.
292
    \item When we try \lstinline{git merge}, Git gives up.
293 294
    \item This situation is called a {\em merge conflict}.
  \end{itemize}
295
\end{pframe}
296

297 298
\subsection{Setting the stage (1/3)}
\begin{pframe}
299
  \begin{lstlisting}
Martijn Vermaat's avatar
Martijn Vermaat committed
300 301
* 5edaf08 (hue/master, hue/HEAD) State character preference
| * f1ef19c (HEAD, master) State character preference
302
|/
Martijn Vermaat's avatar
Martijn Vermaat committed
303
* 1f6d2ab Initial commit
304 305
  \end{lstlisting}

306 307 308 309 310 311
  We'd like to merge branch \lstinline{hue/master} into \lstinline{master}.
\end{pframe}

\subsection{Setting the stage (2/3)}
\begin{pframe}
  The last commit on \lstinline{master}:
312
  \begin{lstlisting}
Martijn Vermaat's avatar
Martijn Vermaat committed
313 314
f1ef19c State character preference
diff --git a/FACTS.md b/FACTS.md
315
index de15194..ef40359 100644
Martijn Vermaat's avatar
Martijn Vermaat committed
316 317
--- a/FACTS.md
+++ b/FACTS.md
318
@@ -1,2 +1,4 @@
Martijn Vermaat's avatar
Martijn Vermaat committed
319 320
Facts about television series
=============================
321 322 323
+
+My favorite character is Eric Cartman.
  \end{lstlisting}
324
\end{pframe}
325

326 327 328
\subsection{Setting the stage (3/3)}
\begin{pframe}
  The last commit on \lstinline{hue/master}:
329
  \begin{lstlisting}
Martijn Vermaat's avatar
Martijn Vermaat committed
330 331 332 333 334 335
$ git show --oneline hue/master
5edaf08 State character preference
diff --git a/FACTS.md b/FACTS.md
index de15194..5e69508 100644
--- a/FACTS.md
+++ b/FACTS.md
336
@@ -1,2 +1,4 @@
Martijn Vermaat's avatar
Martijn Vermaat committed
337 338
Facts about television series
=============================
339
+
Martijn Vermaat's avatar
Martijn Vermaat committed
340
+My favorite character is Milhouse.
341
  \end{lstlisting}
342
\end{pframe}
343

344 345 346
\subsection{Creating a merge conflict}
\begin{pframe}
  \vspace{-0.5cm}
347
  \begin{lstlisting}
Martijn Vermaat's avatar
Martijn Vermaat committed
348 349 350
$ git merge hue/master
Auto-merging FACTS.md
CONFLICT (content): Merge conflict in FACTS.md
351 352
Automatic merge failed; fix conflicts and then
commit the result.
353

354 355 356 357 358 359
$ git status
# On branch master
# Unmerged paths:
#   (use "git add/rm <file>.." as appropriate to
#    mark resolution)
#
Martijn Vermaat's avatar
Martijn Vermaat committed
360
#              both modified:      FACTS.md
361 362 363 364
#
no changes added to commit (use "git add" and/or
"git commit -a")
  \end{lstlisting}
365
\end{pframe}
366

367 368
\subsection{Resolving a merge conflict (1/2)}
\begin{pframe}
369
  \begin{lstlisting}
Martijn Vermaat's avatar
Martijn Vermaat committed
370
$ cat FACTS.md
371 372 373 374 375 376
Facts about television series
=============================

<<<<<<< HEAD
My favorite character is Eric Cartman.
=======
Martijn Vermaat's avatar
Martijn Vermaat committed
377 378
My favorite character is Milhouse.
>>>>>>> hue/master
379
  \end{lstlisting}
380 381 382

  What we had is under \lstinline{HEAD}, what \lstinline{hue/master} had is
  above \lstinline{hue/master}.
383
  \pause
384

385
  \begin{lstlisting}
Martijn Vermaat's avatar
Martijn Vermaat committed
386
$ nano FACTS.md
387
  \end{lstlisting}
388
\end{pframe}
389

390 391
\subsection{Resolving a merge conflict (2/2)}
\begin{pframe}
392 393
  We resolve the conflict by hand.
  \begin{lstlisting}
Martijn Vermaat's avatar
Martijn Vermaat committed
394
$ cat FACTS.md
395 396 397 398
Facts about television series
=============================

My favorite characters are Eric Cartman
Martijn Vermaat's avatar
Martijn Vermaat committed
399
and Milhouse.
400 401
  \end{lstlisting}
  \pause
402

403 404
  And can now finish the merge commit.
  \begin{lstlisting}
Martijn Vermaat's avatar
Martijn Vermaat committed
405
$ git add FACTS.md
406
$ git commit
407 408
[master 1e496cb] Merge remote-tracking branch
'hue/master'
409
  \end{lstlisting}
410
\end{pframe}
411

412 413
\subsection{Aborting a merge}
\begin{pframe}
414
  If you don't feel like resolving the merge conflict, you can go back with
415
  \lstinline{git merge --abort}.
416
  \begin{lstlisting}
Martijn Vermaat's avatar
Martijn Vermaat committed
417 418 419
$ git merge hue/master
Auto-merging FACTS.md
CONFLICT (content): Merge conflict in FACTS.md
420 421 422
Automatic merge failed; fix conflicts and then
commit the result.
  \end{lstlisting}
423

424 425 426
  \begin{lstlisting}
$ git merge --abort
  \end{lstlisting}
427

428 429 430 431 432
  \begin{lstlisting}
$ git status
# On branch master
nothing to commit (working directory clean)
  \end{lstlisting}
433
\end{pframe}
434

435 436
\subsection{Resolving conflicts with \lstinline{git mergetool}}
\begin{pframe}
437 438 439 440 441
  We can also use graphical merge tools such as {\em Meld}.
  \begin{lstlisting}
$ git mergetool
merge tool candidates: meld opendiff kdiff3 ...
Merging:
Martijn Vermaat's avatar
Martijn Vermaat committed
442
FACTS.md
443

Martijn Vermaat's avatar
Martijn Vermaat committed
444
Normal merge conflict for 'FACTS.md':
445 446 447 448
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (meld):
  \end{lstlisting}
449
\end{pframe}
450

451 452 453 454
\subsection{Meld example}
\begin{pframe}
  \includegraphics[width=11cm]{meld}
  \smallskip
455

456 457
  Tools like Meld provide an editable three-way diff.
\end{pframe}
458

459 460 461 462 463
\makeAcknowledgementsSlide{
  \begin{tabular}{l}
    \acknowledgements
  \end{tabular}
  \bigskip
464

465
  \hfill\includegraphics[width=3.5cm]{git_logo}
466

467 468 469 470 471
  \begin{tabular}{l}
    \small\url{http://git-scm.com/book}\\
    \small\url{https://www.atlassian.com/git}
  \end{tabular}
}
472 473

\end{document}