branching.tex 14 KB
Newer Older
1 2
\documentclass[slidestop]{beamer}

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

5
\author{Martijn Vermaat}
6 7
\title{\courseTitle}
\providecommand{\mySubTitle}{Working with branches in Git}
8
\providecommand{\myConference}{Git course}
9
\providecommand{\myGroup}{}
10 11
\providecommand{\myDepartment}{Department of Human Genetics}
\providecommand{\myCenter}{Center for Human and Clinical Genetics}
12

13 14
\usetheme{lumc}

15 16 17 18 19 20 21 22 23 24 25 26
\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
  \end{frame}
}

31 32 33 34 35 36
\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
  \begin{itemize}
46 47
    \item Every commit has a parent.
    \item {\em Committing} creates a new commit on top of the current one.
48
  \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
  \begin{itemize}
57
    \item A {\em branch} is a pointer to a commit.
58
    \item By default there is one branch: \lstinline{master}.
59
  \end{itemize}
60
\end{pframe}
61

62 63
\subsection{The current commit: \lstinline{HEAD}}
\begin{pframe}
64
  \begin{itemize}
65 66
    \item The current commit is called \lstinline{HEAD} (shown in blue here).
    \item \lstinline{HEAD} is actually a pointer to the current branch.
Martijn Vermaat's avatar
Martijn Vermaat committed
67 68
    \item (Or to the current commit if there is no current branch -- this is
      called detached head state.)
69
  \end{itemize}
70 71 72 73
  \bigskip

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

75 76
\subsection{Committing moves \lstinline{HEAD} and the current branch}
\begin{pframe}
77
  \begin{itemize}
78
    \item Committing moves the current branch to the new commit.
79 80
    \item Of course, \lstinline{HEAD} moves with it.
    \item (In detached head state, only \lstinline{HEAD} moves.)
81
  \end{itemize}
82 83 84 85 86 87 88 89 90
  \bigskip

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

\subsection{A non-linear history}
\begin{pframe}
  \includegraphics[width=10cm]{nonlinear}
  \smallskip
91 92

  \begin{itemize}
93 94
    \item The commit graph can become non-linear.
    \item Usually by committing from the same commit twice.
95
  \end{itemize}
96
\end{pframe}
97

98 99
\subsection{Use branches to keep track of different code paths}
\begin{pframe}
100
  \begin{itemize}
101 102
    \item Branch names are easier to remember than commit hashes.
    \item Branch names make it clear what commits are about.
103
  \end{itemize}
104
  \bigskip
105

106 107 108 109 110
  \includegraphics[width=6cm]{branches}
\end{pframe}

\subsection{Different code paths may later join}
\begin{pframe}
111
  \begin{itemize}
112 113
    \item Commits from different branches can be brought together.
    \item We call this {\em merging}.
114
  \end{itemize}
115
  \bigskip
116

117 118
  \includegraphics[width=6cm]{merge}
\end{pframe}
119

120
\section{Inspecting the commit graph}
121 122 123 124
\subsection{An example repository}
\begin{pframe}
  \includegraphics[width=8cm]{example}
  \smallskip
125

126
  \begin{itemize}
127 128 129 130 131
    \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}.
132
  \end{itemize}
133
\end{pframe}
134

135 136
\subsection{Showing the current branch: \lstinline{git status}}
\begin{pframe}
137 138 139 140 141 142
  \begin{lstlisting}
$ git status
# On branch master
nothing to commit (working directory clean)
  \end{lstlisting}

143 144 145 146 147
  Remember: you cannot type \lstinline{git status} enough!
\end{pframe}

\subsection{Listing branches: \lstinline{git branch}}
\begin{pframe}
148 149 150 151 152 153
  \begin{lstlisting}
$ git branch
  interface
  license
* master
  \end{lstlisting}
154 155

  Three branches, current branch is \lstinline{master}.
156
  \pause
157

158 159 160 161 162 163 164
  \begin{lstlisting}
$ git branch -v
  interface 8fc25c1 Trivial Python interface
  license   0fbe3e3 Add MIT license
* master    c7f3bd9 Add .gitignore file
  \end{lstlisting}

165 166 167 168 169
  \lstinline{-v}: Shows the commit each branch points to.
\end{pframe}

\subsection{The commit log: \lstinline{git log}}
\begin{pframe}
170 171 172 173 174 175 176 177 178
  \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}

179 180 181 182
  \lstinline{--oneline}: Shows commit summary on one line.

  \lstinline{--decorate}: Adds branch information.
\end{pframe}
183

184 185
\subsection{The commit log as a graph: \lstinline{git log}}
\begin{pframe}
186 187 188 189 190 191 192 193 194 195 196 197 198
  \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}

199 200 201 202
  \lstinline{--graph}: Shows the commit graph.

  \lstinline{--all}: Includes all branches instead of just the current.
\end{pframe}
203

204 205
\subsection{Switching to another branch: \lstinline{git checkout}}
\begin{pframe}
206 207 208 209
  \begin{lstlisting}
$ git checkout interface
Switched to branch 'interface'
  \end{lstlisting}
210 211

  This points \lstinline{HEAD} to the named branch and updates your working
212 213
  directory.
  \pause
214

215 216 217 218
  \begin{lstlisting}
$ git status
# On branch interface
nothing to commit (working directory clean)
219
  \end{lstlisting}
220
\end{pframe}
221 222

\section{Manipulating the commit graph}
223 224 225 226
\subsection{An example repository}
\begin{pframe}
  \includegraphics[width=8cm]{example}
  \smallskip
227

228
  \begin{itemize}
229 230 231 232 233
    \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}.
234
  \end{itemize}
235
\end{pframe}
236

237 238
\subsection{Creating a new branch: \lstinline{git branch}}
\begin{pframe}
239 240 241
  \begin{lstlisting}
$ git branch lib
  \end{lstlisting}
242 243

  Creates branch \lstinline{lib} at \lstinline{HEAD}.
244
  \pause
245

246 247 248
  \begin{lstlisting}
$ git checkout lib
Switched to branch 'lib'
249
  \end{lstlisting}
250
  \pause
251

252 253 254 255 256
  Or, for Git pro's, in one command:
  \begin{lstlisting}
$ git checkout -b lib
Switched to a new branch 'lib'
  \end{lstlisting}
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272

  At this point, \lstinline{lib} is just a label to the same commit as
  \lstinline{master}.
\end{pframe}

\subsection{Our example repository}
\begin{pframe}
  \includegraphics[width=8cm]{example-branched}
  \smallskip

  Created branch \lstinline{lib} from \lstinline{master}.
\end{pframe}

\subsection{Working on a branch: \lstinline{git commit}}
\begin{pframe}
  We can extend the \lstinline{lib} branch by adding commits.
273 274 275 276 277 278
  \begin{lstlisting}
$ echo 'VERSION=1' > testlib.py
$ git add testlib.py
$ git commit -m 'Add empty testlib'
  \end{lstlisting}
  \pause
279

280 281 282 283 284 285 286 287 288 289 290
  \begin{lstlisting}
$ git log --oneline --decorate --graph --all
* 251a51b (HEAD, lib) Add empty testlib
* c7f3bd9 (master) Add .gitignore file
| * 8fc25c1 (interface) Trivial Python interface
|/
*   4a44c4e Merge branch 'license'
|\
| * 0fbe3e3 (license) Add MIT license
...
  \end{lstlisting}
291 292 293 294 295 296 297 298 299 300 301 302 303
\end{pframe}

\subsection{Our example repository}
\begin{pframe}
  \includegraphics[width=8cm]{example-committed}
  \smallskip

  Extended branch \lstinline{lib}.
\end{pframe}

\subsection{Fast forward merging: \lstinline{git merge}}
\begin{pframe}
  Let's merge our work on \lstinline{lib} back into \lstinline{master}.
304 305 306 307 308 309 310 311 312 313
  \begin{lstlisting}
$ git checkout master
Switched to branch 'master'
$ git merge lib
Updating c7f3bd9..251a51b
Fast-forward
 testlib.py |    1 +
 1 file changed, 1 insertion(+)
 create mode 100644 testlib.py
  \end{lstlisting}
314

315
  This merge was easy:
316
  \begin{itemize}
317 318 319
    \item \lstinline{lib} was directly upstream of \lstinline{master}.
    \item Git just moves \lstinline{HEAD} and \lstinline{master} to point to
      \lstinline{lib}.
320
    \item This is called a {\em fast forward merge}.
321
  \end{itemize}
322 323 324 325 326 327 328 329 330 331 332 333 334
\end{pframe}

\subsection{Our example repository}
\begin{pframe}
  \includegraphics[width=8cm]{example-merged-ff}
  \smallskip

  Merged branch \lstinline{lib} into \lstinline{master} (fast forward).
\end{pframe}

\subsection{Three-way merging: \lstinline{git merge}}
\begin{pframe}
  Let's merge our work on \lstinline{interface} back into \lstinline{master}.
335 336 337 338 339 340 341
  \begin{lstlisting}
$ git merge interface
Merge made by the 'recursive' strategy.
 interface.py |    3 +++
 1 file changed, 3 insertions(+)
 create mode 100755 interface.py
  \end{lstlisting}
342 343
  \vspace{-0.25cm}

344 345
  This merge was harder:
  \begin{itemize}
346 347 348 349
    \item \lstinline{interface} and \lstinline{master} had diverged.
    \item Git determines changes in \lstinline{interface} and
      \lstinline{master} since their most recent common ancestor and creates a
      new commit from that.
350 351 352
    \item This is called a {\em recursive three-way merge} and the resulting
      merge a {\em merge commit}.
  \end{itemize}
353 354 355 356 357 358
\end{pframe}

\subsection{Our example repository}
\begin{pframe}
  \includegraphics[width=8cm]{example-merged}
  \smallskip
359

360 361
  Merged branch \lstinline{interface} into \lstinline{master}.
\end{pframe}
362

363 364
\subsection{Deleting branches: \lstinline{git branch}}
\begin{pframe}
365 366 367 368 369
  Old branches that have been merged can be deleted.
  \begin{lstlisting}
$ git branch -d interface
Deleted branch interface (was 8fc25c1).
  \end{lstlisting}
370

371 372 373 374 375 376
  \begin{lstlisting}
$ git branch -d lib license
Deleted branch lib (was 251a51b).
Deleted branch license (was 0fbe3e3).
  \end{lstlisting}

377 378
  No history is lost, just labels removed.
\end{pframe}
379

380
\section{Basic merge conflicts}
381 382
\subsection{Merge conflicts}
\begin{pframe}
383 384 385 386 387 388 389
  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
390 391
  \pause

392 393 394
  Sometimes this is not possible:
  \begin{itemize}
    \item The changes might be incompatible.
395
    \item When we try \lstinline{git merge}, Git gives up.
396 397
    \item This situation is called a {\em merge conflict}.
  \end{itemize}
398
\end{pframe}
399

400 401
\subsection{Setting the stage (1/3)}
\begin{pframe}
402 403 404 405 406 407 408 409
  \begin{lstlisting}
$ git log --oneline --decorate --graph --all
* 9d2ad27 (HEAD, master) State character preference
| * 374ab60 (simpsons) State character preference
|/
* 4012f4f Initial commit
  \end{lstlisting}

410 411 412 413 414 415
  We'd like to merge branch \lstinline{simpsons} into \lstinline{master}.
\end{pframe}

\subsection{Setting the stage (2/3)}
\begin{pframe}
  The last commit on \lstinline{master}:
416 417 418 419 420 421 422 423 424 425 426 427 428
  \begin{lstlisting}
$ git show --oneline
9d2ad27 State character preference
diff --git a/README b/README
index de15194..ef40359 100644
--- a/README
+++ b/README
@@ -1,2 +1,4 @@
 Facts about television series
 =============================
+
+My favorite character is Eric Cartman.
  \end{lstlisting}
429
\end{pframe}
430

431 432 433
\subsection{Setting the stage (3/3)}
\begin{pframe}
  The last commit on \lstinline{simpsons}:
434 435 436 437 438 439 440 441 442 443 444 445 446
  \begin{lstlisting}
$ git show --oneline simpsons
374ab60 State character preference
diff --git a/README b/README
index de15194..9dd729b 100644
--- a/README
+++ b/README
@@ -1,2 +1,4 @@
 Facts about television series
 =============================
+
+My favorite character is Homer Simpson.
  \end{lstlisting}
447
\end{pframe}
448

449 450 451
\subsection{Creating a merge conflict}
\begin{pframe}
  \vspace{-0.5cm}
452 453 454 455 456 457
  \begin{lstlisting}
$ git merge simpsons
Auto-merging README
CONFLICT (content): Merge conflict in README
Automatic merge failed; fix conflicts and then
commit the result.
458

459 460 461 462 463 464 465 466 467 468 469
$ git status
# On branch master
# Unmerged paths:
#   (use "git add/rm <file>.." as appropriate to
#    mark resolution)
#
#              both modified:      README
#
no changes added to commit (use "git add" and/or
"git commit -a")
  \end{lstlisting}
470
\end{pframe}
471

472 473
\subsection{Resolving a merge conflict (1/2)}
\begin{pframe}
474 475 476 477 478 479 480 481 482 483 484
  \begin{lstlisting}
$ cat README
Facts about television series
=============================

<<<<<<< HEAD
My favorite character is Eric Cartman.
=======
My favorite character is Homer Simpson.
>>>>>>> simpsons
  \end{lstlisting}
485 486 487

  What we had is under \lstinline{HEAD}, what \lstinline{simpsons} had is above
  \lstinline{simpsons}.
488
  \pause
489

490 491 492
  \begin{lstlisting}
$ emacs README
  \end{lstlisting}
493
\end{pframe}
494

495 496
\subsection{Resolving a merge conflict (2/2)}
\begin{pframe}
497 498 499 500 501 502 503 504 505 506
  We resolve the conflict by hand.
  \begin{lstlisting}
$ cat README
Facts about television series
=============================

My favorite characters are Eric Cartman
and Homer Simpson.
  \end{lstlisting}
  \pause
507

508 509 510 511 512 513
  And can now finish the merge commit.
  \begin{lstlisting}
$ git add README
$ git commit
[master 1e496cb] Merge branch 'simpsons'
  \end{lstlisting}
514
\end{pframe}
515

516 517
\subsection{Aborting a merge}
\begin{pframe}
518
  If you don't feel like resolving the merge conflict, you can go back with
519
  \lstinline{git merge --abort}.
520 521 522 523 524 525 526
  \begin{lstlisting}
$ git merge simpsons
Auto-merging README
CONFLICT (content): Merge conflict in README
Automatic merge failed; fix conflicts and then
commit the result.
  \end{lstlisting}
527

528 529 530
  \begin{lstlisting}
$ git merge --abort
  \end{lstlisting}
531

532 533 534 535 536
  \begin{lstlisting}
$ git status
# On branch master
nothing to commit (working directory clean)
  \end{lstlisting}
537
\end{pframe}
538

539 540
\subsection{Resolving conflicts with \lstinline{git mergetool}}
\begin{pframe}
541 542 543 544 545 546 547 548 549 550 551 552
  We can also use graphical merge tools such as {\em Meld}.
  \begin{lstlisting}
$ git mergetool
merge tool candidates: meld opendiff kdiff3 ...
Merging:
README

Normal merge conflict for 'README':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (meld):
  \end{lstlisting}
553
\end{pframe}
554

555 556 557 558
\subsection{Meld example}
\begin{pframe}
  \includegraphics[width=11cm]{meld}
  \smallskip
559

560 561
  Tools like Meld provide an editable three-way diff.
\end{pframe}
562

563 564 565 566 567
\makeAcknowledgementsSlide{
  \begin{tabular}{l}
    \acknowledgements
  \end{tabular}
  \bigskip
568

569
  \hfill\includegraphics[width=3.5cm]{git_logo}
570

571 572 573 574 575
  \begin{tabular}{l}
    \small\url{http://git-scm.com/book}\\
    \small\url{https://www.atlassian.com/git}
  \end{tabular}
}
576 577

\end{document}