Skip to content

Commit 4aeadf9

Browse files
committed
Add notes
Notes are much better than internal comments because they can be generated and released as a deliverable.
1 parent a2458c1 commit 4aeadf9

File tree

1 file changed

+78
-5
lines changed

1 file changed

+78
-5
lines changed

understanding-git.tex

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,14 @@ \section{Introduction}
9999
\begin{frame}
100100
\frametitle{Reading Git graphs}
101101
Git repositories are often represented using a directed acyclic graph (DAG).
102+
\note{
103+
\textbf{Directed:} The graph edges are one-way.\\
104+
\textbf{Acyclic:} There is no way to return to a node once you have passed it.\\
105+
\textbf{Graph:} A mathematical model with nodes and edges that connect nodes.
106+
107+
A DAG forms a tree structure, and you can refer to a connected Git DAG as a tree.\\
108+
}
109+
102110
\begin{figure}
103111
\centering
104112
\begin{tikzpicture}
@@ -123,12 +131,16 @@ \section{Introduction}
123131
\vfill
124132
\begin{block}{Arrows}
125133
The arrows point to the commit's parent(s), not the flow of time.
134+
\note{Think of the arrows as representing a ``depends on'' relationship.}
126135
\end{block}
127136
\end{frame}
128137

129138
\begin{frame}
130139
\frametitle{Our reference repository}
131140
\defaultrepo
141+
\note[item]{The initial commit is \grefspec{A}.}
142+
\note[item]{There are two branches, \gbranch{master} and \gbranch{topic}.}
143+
\note[item]{Commit \grefspec{D} was made after \gbranch{topic} split from the mainline.}
132144
\end{frame}
133145

134146
\begin{frame}
@@ -149,8 +161,13 @@ \subsection{Introduction}
149161
\item Commits record the changes of a repository.
150162
\item Commits also include a message, a timestamp (usually of creation), and an author.
151163
\item Except for the first commit, commits reference one or more parent commits.
164+
\note[item]{More precisely, root commits have no parent. The first commit is a root commit, but a repo can have multiple root commits.}
152165
\item Commits are identified by a SHA-1 hash. This hash can be abbreviated to its unique prefix (usually 7).
166+
\note[item]{The minimum abbreviated hash length is 4 characters.}
167+
\note[item]{Commits are effectively read-only because changing any of the properties of a commit changes its hash.}
168+
\note[item]{Linux Torvalds on SHA-1 collisions: \url{https://marc.info/?l=git&m=148787047422954}}
153169
\item The bulk of the Git model is the DAG of commits.
170+
\note[item]{The rest of the Git model is the plumbing and the Git file system. This is highly out of scope for this presentation.}
154171
\end{itemize}
155172
\end{frame}
156173

@@ -315,6 +332,12 @@ \subsection{\gitcmd{commit}}
315332

316333
After entering a commit message in the editor, commit \grefspec{F} is added containing the staged changes.
317334
\gHEAD{} and \gbranch{topic} are advanced to \grefspec{F}.
335+
336+
\note{
337+
The commit message can be entered on the command line using the \gflag{-m} (\gflag{--message}) flag, with multiple \gflag{-m} flags being combined as multiple paragraphs.
338+
Using this flag may create bad commit message habits, so consider using \gflag{-m} to start your message
339+
and additionally pass the \gflag{-e} (\gflag{--edit}) flag to bring up the editor to continue editing your message.
340+
}
318341
\end{frame}
319342

320343
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -355,6 +378,11 @@ \subsection{\gitcmd{cherry-pick}}
355378
\end{tikzpicture}
356379
\end{figure}
357380
A new commit, \grefspec{D$'$}, that contains the same changes as \grefspec{D} was added on top of \grefspec{E}. \gHEAD{} and \gbranch{topic} were advanced to \grefspec{D$'$}.
381+
382+
\note{
383+
This is a bad example because it would be better to do a \gitsubcmd{rebase} or a \gitsubcmd{merge} in this case,
384+
but it is one of the simplest examples.
385+
}
358386
\end{frame}
359387

360388
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -368,6 +396,11 @@ \subsection{Introduction}
368396
\item Branches represent a line of development.
369397
\item Branches are lightweight labels that reference commits.
370398
\item Branches should \textbf{not} be thought of as a series of commits.
399+
\note{
400+
The last point is worth repeating: branches should \textbf{not} be thought of as a series of commits.
401+
Much confusion about how branch operations in Git work can be caused by thinking of branches as a series of commits.
402+
Though it seems to contradict the first point, upon closer inspection, it does not.
403+
}
371404
\end{itemize}
372405
\vfill
373406
\begin{block}{\gbranch{master}}
@@ -532,6 +565,12 @@ \subsection{\gitcmd{checkout}}
532565
followed by a\\
533566
\hspace{2em}\gitcmd{checkout newbranch}.
534567
\end{block}
568+
569+
\note{
570+
Another useful trick is to pass a \texttt{-} as the argument,
571+
which checks out the last branch, commit or tag that you performed a \gitsubcmd{checkout} on.
572+
Read the man page to see how you can go even further back.
573+
}
535574
\end{frame}
536575

537576
\begin{frame}
@@ -592,11 +631,13 @@ \subsection{\gitcmd{checkout}}
592631

593632
\begin{itemize}
594633
\item Directly checking out a commit or tag results in a ``detached \gHEAD{}''.
634+
\note[item]{A detached \gHEAD{} results in any situation where the ref that is checked out cannot normally be updated. Tags cannot be updated by issuing a \gitcmd{commit}, for example, so checking out a tag results in a detached \gHEAD{}.}
595635
\item Commits from this commit may be made, but they will be lost unless a branch or tag is made.
596636
\end{itemize}
597637
\vfill
598638
\begin{block}{Unreachable and dangling commits}
599639
Unreachable commits are commits that are not referenced by a branch or tag. Dangling commits are unreachable commits that aren't referenced by another commit. Unreachable commits may be checked out using their SHA-1 hash until they are garbage collected.
640+
\note[item]{By default, garbage collection usually removes unneeded objects after two weeks. See the man page for \gitcmd{gc} for details.}
600641
\end{block}
601642
\end{frame}
602643

@@ -762,8 +803,10 @@ \subsection{\gitcmd{rebase}}
762803
\vfill
763804
\begin{block}{Rebasing shared public branches}
764805
Don't rebase branches that others are working on or have branched off from, especially \gbranch{master}. Complications arise downstream when such a rebase is performed, and it is generally considered rude to rewrite public history.
765-
%%% man git-rebase
806+
807+
\note[item]{The \texttt{git-rebase(1)} man page has a section on recovering from an upstream rebase.}
766808
\end{block}
809+
\note[item]{\gitcmd{rebase} can do a lot more than reapplying commits to another base, including editing and reordering commits. More details can be found in the man page.}
767810
\end{frame}
768811

769812
\begin{frame}
@@ -797,6 +840,11 @@ \subsection{\gitcmd{rebase}}
797840
\end{figure}
798841

799842
New commits \grefspec{C$'$} and \grefspec{E$'$} with the same changes as \grefspec{C} and \grefspec{E} respectively were applied onto the tip of \gbranch{master} (\grefspec{D}). Commits \grefspec{C} and \grefspec{E} have become unreachable.
843+
844+
\note{
845+
Git visualizations will show branches where one is a direct ancestor of the other in a straight line like this.
846+
This kind of presentation reinforces two facts: 1) \gbranch{master} is not special to Git, and 2) branches are just labels.
847+
}
800848
\end{frame}
801849

802850
\begin{frame}
@@ -807,7 +855,8 @@ \subsection{\gitcmd{rebase}}
807855
\item Perform a \gitsubcmd{reset --hard} to the target branch. This is the ``unwinding'' step.
808856
\item \gitsubcmd{cherry-pick} each commit one by one from the fork point to the former tip of the branch, excluding merge commits.
809857
\end{enumerate}
810-
%%% http://think-like-a-git.net/sections/rebase-from-the-ground-up/using-git-cherry-pick-to-simulate-git-rebase.html
858+
859+
\note{Adapted from:\\{\scriptsize\url{http://think-like-a-git.net/sections/rebase-from-the-ground-up/using-git-cherry-pick-to-simulate-git-rebase.html}}}
811860
\end{frame}
812861

813862
\begin{frame}
@@ -937,6 +986,11 @@ \subsection{\gitcmd{rebase}}
937986
\end{figure}
938987

939988
Creating a temporary branch before the rebase prevents the original commits from becoming unreachable, meaning that restoring the original branch is as simple as doing a \gitsubcmd{reset} to the temporary branch.
989+
990+
\note{
991+
\gitcmd{reflog} makes this trick unnecessary (unless you need to prevent the old commits from being garbage collected),
992+
but creating a branch is simple to understand.
993+
}
940994
\end{frame}
941995

942996
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -954,9 +1008,16 @@ \subsection{\gitcmd{merge}}
9541008
\begin{block}{Octopus merge}
9551009
A merge involving more than two branches is called an ``octopus merge''.
9561010
Support for such merges were added to Git for combining independent driver updates.
957-
%%% https://redd.it/1vsvgs
958-
%%% https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2cde51fbd0f3
959-
%%% https://github.com/torvalds/linux/commit/2cde51fbd0f3
1011+
\note{
1012+
Using octopus merges reduces the noise in the branch.
1013+
If five branches need to be merged into another, there only needs to be one octopus merge commit instead of five regular merge commits.
1014+
1015+
There is a commit in the Linux kernel tree that has 66 parents, which Torvalds called a ``Cthulhu merge''.
1016+
It made the visualization of the graph hard to read, so in response, he suggested that octopus merges be kept to a maximum of 10--15 parents.
1017+
1018+
\url{https://marc.info/?l=linux-kernel&m=139033182525831}\\
1019+
\url{https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2cde51fbd0f3}\\
1020+
}
9601021
\end{block}
9611022
\end{frame}
9621023

@@ -1168,6 +1229,7 @@ \subsection{\gitcmd{fetch}}
11681229
\framesubtitle{``Download objects and refs from another repository''}
11691230
\begin{itemize}
11701231
\item Downloads commits, branches and tags from a remote repository and makes them available in your local repository.
1232+
\note{Fetching tags can be suppressed with the \gflag{--no-tags} option.}
11711233
\item Updates any remote branch references, but does not update any local ones.
11721234
\item Does not move \gHEAD{}.
11731235
\end{itemize}
@@ -1364,6 +1426,10 @@ \subsection{\gitcmd{pull}}
13641426
\end{figure}
13651427

13661428
Git treats \gremotebranch{origin/topic} like any other branch. Since \gbranch{topic} is not a direct ancestor, a merge commit \grefspec{I} is made.
1429+
\note{
1430+
Strictly speaking, \gremotebranch{origin/topic} is just another ref, which is something that resolves to a commit.
1431+
Branches and tags are examples of refs.
1432+
}
13671433
\end{frame}
13681434

13691435
\begin{frame}
@@ -1405,12 +1471,15 @@ \subsection{\gitcmd{push}}
14051471
\item Pushes commits to a remote repository.
14061472
\item Updates the remote branch reference.
14071473
\item Will fail if the remote branch is not an ancestor of the local branch unless \gflag{--force} (\gflag{-f}) is used.
1474+
\note[item]{The behaviour of \gitcmd{push} can be configured using the \texttt{push.default} option in the configuration file.}
14081475
\item Tags must be pushed separately with the \gflag{--tags} flag.
1476+
\note[item]{It is not entirely true that tags must be pushed separately. Tags can be specified as arguments along with branches and they will be pushed.}
14091477
\end{itemize}
14101478
\vfill
14111479
\begin{block}{\gflag{--force-with-lease}}
14121480
The \gflag{--force} flag is dangerous and should not be used lightly because it can cause another person's work to be lost.
14131481
The \gflag{--force-with-lease} flag is safer since it will only force-push if the tracking branch points to the same commit as on the remote repo.
1482+
\note[item]{To make it easier to specify \gflag{--force-with-lease}, you can make an alias.}
14141483
\end{block}
14151484
\end{frame}
14161485

@@ -1583,6 +1652,10 @@ \subsection{\gitcmd{push}}
15831652
\end{figure}
15841653

15851654
Commit \grefspec{F} is lost since the remote branch reference was forcibly updated.
1655+
\note{
1656+
Since Git is distributed, someone else \emph{might} have a copy of commit \grefspec{F} and you can recover from there,
1657+
but do not rely on that being the case.
1658+
}
15861659
\end{frame}
15871660

15881661
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

0 commit comments

Comments
 (0)