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

Laros's avatar
Laros committed
3
4
\input{../shared/shared.tex}

Laros's avatar
Laros committed
5
\author{Martijn Vermaat}
Laros's avatar
Laros committed
6
7
\title{\courseTitle}
\providecommand{\mySubTitle}{Combining changes by merging}
Laros's avatar
Laros committed
8
\providecommand{\myConference}{\courseTitle}
Laros's avatar
Laros committed
9
\providecommand{\myGroup}{}
10
11
\providecommand{\myDepartment}{Department of Human Genetics}
\providecommand{\myCenter}{Center for Human and Clinical Genetics}
Laros's avatar
Laros committed
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}
Laros's avatar
Laros committed
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.
Laros's avatar
Laros committed
37
\makeTitleSlide{\includegraphics[width=3.5cm]{git_logo}}
38
39

\section{The Git commit graph}
Laros's avatar
Laros committed
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}
Laros's avatar
Laros committed
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.
Laros's avatar
Laros committed
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}
Laros's avatar
Laros committed
62
\end{pframe}
63

Laros's avatar
Laros committed
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.
Laros's avatar
Laros committed
68
    \item (Of course, \lstinline{HEAD} moves with it.)
69
  \end{itemize}
Laros's avatar
Laros committed
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}
Laros's avatar
Laros committed
84
\end{pframe}
85

Laros's avatar
Laros committed
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}
Laros's avatar
Laros committed
92
93
94
95
  \bigskip

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

Laros's avatar
Laros committed
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}
Laros's avatar
Laros committed
103
  \bigskip
104

Laros's avatar
Laros committed
105
106
  \includegraphics[width=6cm]{merge}
\end{pframe}
107
108

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

  \begin{itemize}
Laros's avatar
Laros committed
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}
Laros's avatar
Laros committed
121
\end{pframe}
122

Laros's avatar
Laros committed
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}

Laros's avatar
Laros committed
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}

Laros's avatar
Laros committed
145
  \lstinline{--oneline}: Shows commit summary on one line.
146

Laros's avatar
Laros committed
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}

Laros's avatar
Laros committed
165
  \lstinline{--graph}: Shows the commit graph.
166

Laros's avatar
Laros committed
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:
Vermaat's avatar
Vermaat committed
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}

Laros's avatar
Laros committed
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}
Vermaat's avatar
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.
Laros's avatar
Laros committed
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
Laros's avatar
Laros committed
199
200
  \includegraphics[width=10cm]{example-hue}
\end{pframe}
201

Vermaat's avatar
Vermaat committed
202
\section{Merging from remotes}
Laros's avatar
Laros committed
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}
Laros's avatar
Laros committed
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}.
Vermaat's avatar
Vermaat committed
215
    \item It is called a {\em fast forward merge}.
216
  \end{itemize}
Laros's avatar
Laros committed
217
\end{pframe}
218

Laros's avatar
Laros committed
219
220
\subsection{Fast forward merging: \lstinline{git merge}}
\begin{pframe}
Vermaat's avatar
Vermaat committed
221
  If a remote branch is ahead of us, it can be merged easily:
222
  \begin{lstlisting}
Vermaat's avatar
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}

Laros's avatar
Laros committed
230
231
  \includegraphics[width=10cm]{example-hue-merged}
\end{pframe}
232

Laros's avatar
Laros committed
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}
Laros's avatar
Laros committed
241
    \item \lstinline{git merge hue/master}
Vermaat's avatar
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}
Laros's avatar
Laros committed
246
\end{pframe}
247

Laros's avatar
Laros committed
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}
Vermaat's avatar
Vermaat committed
253
$ git merge hue/master
254
Merge made by the 'recursive' strategy.
Vermaat's avatar
Vermaat committed
255
256
 FACTS.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
257
258
  \end{lstlisting}

Laros's avatar
Laros committed
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.
Vermaat's avatar
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

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

\section{Basic merge conflicts}
Laros's avatar
Laros committed
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
Laros's avatar
Laros committed
287
288
  \pause

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

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

Laros's avatar
Laros committed
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}
Vermaat's avatar
Vermaat committed
313
314
f1ef19c State character preference
diff --git a/FACTS.md b/FACTS.md
315
index de15194..ef40359 100644
Vermaat's avatar
Vermaat committed
316
317
--- a/FACTS.md
+++ b/FACTS.md
318
@@ -1,2 +1,4 @@
Vermaat's avatar
Vermaat committed
319
320
Facts about television series
=============================
321
322
323
+
+My favorite character is Eric Cartman.
  \end{lstlisting}
Laros's avatar
Laros committed
324
\end{pframe}
325

Laros's avatar
Laros committed
326
327
328
\subsection{Setting the stage (3/3)}
\begin{pframe}
  The last commit on \lstinline{hue/master}:
329
  \begin{lstlisting}
Vermaat's avatar
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 @@
Vermaat's avatar
Vermaat committed
337
338
Facts about television series
=============================
339
+
Vermaat's avatar
Vermaat committed
340
+My favorite character is Milhouse.
341
  \end{lstlisting}
Laros's avatar
Laros committed
342
\end{pframe}
343

Laros's avatar
Laros committed
344
345
346
\subsection{Creating a merge conflict}
\begin{pframe}
  \vspace{-0.5cm}
347
  \begin{lstlisting}
Vermaat's avatar
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.
Laros's avatar
Laros committed
353

354
355
356
357
358
359
$ git status
# On branch master
# Unmerged paths:
#   (use "git add/rm <file>.." as appropriate to
#    mark resolution)
#
Vermaat's avatar
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}
Laros's avatar
Laros committed
365
\end{pframe}
366

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

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

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

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

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

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

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

Laros's avatar
Laros committed
412
413
\subsection{Aborting a merge}
\begin{pframe}
414
  If you don't feel like resolving the merge conflict, you can go back with
Laros's avatar
Laros committed
415
  \lstinline{git merge --abort}.
416
  \begin{lstlisting}
Vermaat's avatar
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}
Laros's avatar
Laros committed
423

424
425
426
  \begin{lstlisting}
$ git merge --abort
  \end{lstlisting}
Laros's avatar
Laros committed
427

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

Laros's avatar
Laros committed
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:
Vermaat's avatar
Vermaat committed
442
FACTS.md
443

Vermaat's avatar
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}
Laros's avatar
Laros committed
449
\end{pframe}
450

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

Laros's avatar
Laros committed
456
457
  Tools like Meld provide an editable three-way diff.
\end{pframe}
458

Laros's avatar
Laros committed
459
460
461
462
463
\makeAcknowledgementsSlide{
  \begin{tabular}{l}
    \acknowledgements
  \end{tabular}
  \bigskip
464

Laros's avatar
Laros committed
465
  \hfill\includegraphics[width=3.5cm]{git_logo}
466

Laros's avatar
Laros committed
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}