You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1250 lines
36 KiB

\documentclass[aspectratio=169]{beamer}
\usepackage{pgfpages}
%showNotes%\setbeameroption{show notes on second screen=right}
%\setbeamertemplate{note page}{\pagecolor{yellow!5}\insertnote}
%showNotes%\setbeamertemplate{note page}{%
%showNotes%\setlength{\parskip}{12pt}\pagecolor{yellow!5}\vfill\insertnote\vfill}
%onlyNotes%\setbeameroption{show only notes}
%onlyNotes%\setbeamertemplate{note page}{%
%onlyNotes%\begin{center} \insertslideintonotes{0.3} \end{center}
%onlyNotes%\setlength{\parskip}{12pt} \pagecolor{yellow!5} \tiny\insertnote }
\setlength{\parskip}{12pt}
\usepackage{palatino}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{pdfpages}
\usepackage{tikz}
\usepackage[UKenglish]{babel}%
\usetikzlibrary{shapes.geometric, arrows}
\tikzstyle{commit} = [circle, text centered, line width=2,
minimum size=1.5cm, draw=blue, fill=blue!80, text=white]
\tikzstyle{branch} = [ellipse, text centered, text=green]
\tikzstyle{arrow} = [thick, <-, draw=blue]
\usepackage{dirtree}
\usepackage{csquotes}
%\usepackage{gitdags}
\usepackage{minted}
\setminted{%
autogobble,
fontsize=\footnotesize,
breaklines
}
\usetheme{default}
\beamertemplatenavigationsymbolsempty
\hypersetup{%
colorlinks=true,
urlcolor=blue,
%pdfpagemode=UseNone
} % don't show bookmarks on initial view
%\lstset{%
% breaklines=true,
% postbreak=\mbox{$\hookrightarrow$\space},
% basicstyle=\footnotesize,
% %keywordstyle=\color{blue},
% morekeywords=git
%}
\usepackage{graphicx}
\graphicspath{ {./auto-images/} }
\makeatletter
\def\input@path{{auto-images/}}
%or: \def\input@path{{/path/to/folder/}{/path/to/other/folder/}}
\makeatother
%Information to be included in the title page:
\title{Git}
\author{Jonathan Hodgson (Archie)}
\date{\today}
%\titlegraphic{\includegraphics[width=1cm,keepaspectratio]{auto-xkcd-1597.png})
\institute{
\includegraphics[width=\textwidth,height=.5\textheight,keepaspectratio]{auto-xkcd-1597.png}%
}
\begin{document}
\frame{
\titlepage
\note{%
A few people recently have asked me about Git.
Git has a reputation for being hard. I think this is (at least partly) because so much of
its inner workings are abstracted away making the interface feel like magic. Not to mention
videos with titles like "Learn git in 15 minutes"
I think that understanding a bit about how Git works under the hood will help de-mistily it.
It certainly did for me.
Git's data model is actually quite simple (beautiful even). Understanding the basics of this
can really help.
}
}
\begin{frame}
\frametitle{What is Git}
A very versatile Version Control System
\begin{itemize}
\item Keep track of source code (or other folders and files) and its history
\item Facilitate collaboration
\item Distributed
\end{itemize}
\note{%
It keeps track by maintaining a series of snapshots containing all of the files and folders
at each point.
It's useful even if you're working on things by your self. This presentation is version
controlled.
You can use it to find out when something broke. I won't be covering it today but there is a
tool called git bisect that can take a unit test (or script) to analyse when something broke
using a binary search.
Being distributed means you can work on repositories offline (Unlike SVN).
}
\end{frame}
\begin{frame}
\frametitle{What is Git}
\begin{center}
\Huge Git $\ne$ Github
\end{center}
\note{%
Although the names are similar, Git and Github are separate projects. Github is a Microsoft
owned, closed source company that is a remote repository for Git projects.
There are others such as Bitbucket, Gitlab, Gitea
}
\end{frame}
\begin{frame}
\frametitle{Naïve Approach}
\begin{columns}
\begin{column}{0.5\textwidth}
\dirtree{%
.1 Project.
.2 draft.
.3 some.
.3 files.
.2 final-draft.
.3 some.
.3 files.
.2 final.
.3 some.
.3 files.
}
\end{column}
\begin{column}{0.5\textwidth}
\textbf{Pros}
\begin{itemize}
\item Simple
\item No dependencies
\item No Learning curve
\end{itemize}
\vspace{1em}
\textbf{Cons}
\begin{itemize}
\item Difficult to collaborate
\item Lot's of wasted disk space
\item Hard to find particular versions of files
\end{itemize}
\end{column}
\end{columns}
\note{%
There are many approaches you could take to version control
I think, being honest, we have all done this. This sort of works, if you're working on
something by yourself. Once you start collaborating on software, you are going to have a bad
time.
You could add time stamps and zip up changes when you need to collaborate.
Git has a well thought out model that allows us to address these problems.
}
\end{frame}
\begin{frame}
\frametitle{Files and Folders}
\textbf{Blob} In Git, a file is called a blob.
\textbf{Tree} In Git, a directory is called a tree.
\note{%
Git needs a way of modeling files and folders in a file system independent way.
These concepts are pretty familiar. A tree can contain other trees or blobs.
At its core, Git is a content addressed storage tool. All files and folders are addressed by
a (hardened) sha1 hash.
}
\end{frame}
\begin{frame}
\frametitle{Commits}
\framesubtitle{(Snapshots)}
\begin{center}
\begin{tikzpicture}
%\draw (-1.5,-1.5) rectangle (7.5,1.5);
%\node at (-2.5,0) {master};
\node[commit,minimum size=2cm] at (0,0) (commit1) {Draft};
\node[commit,minimum size=2cm] at (3,0) (commit2) {Final Draft};
\node[commit,minimum size=2cm,draw=red] at (6,0) (commit3) {Final};
\draw[arrow] (commit1) -- (commit2);
\draw[arrow] (commit2) -- (commit3);
\node[draw,text width=1.8cm,anchor=north,align=center] at (0, -1.5) {\small \vdots\\[0.1cm] };
\node[draw,text width=1.8cm,anchor=north,align=center] at (3, -1.5) {\small \vdots\\[0.1cm] Draft };
\node[draw,text width=1.8cm,anchor=north,align=center] at (6, -1.5) {\small \vdots\\[0.1cm] Final Draft };
\end{tikzpicture}
\end{center}
\note{%
\begin{itemize}
\item We could then think of history as a linear series of snapshots.
\item Each circle here represents a snapshot.
\item The previous snapshot is referenced somewhere in each snapshot.
\item We then just need to record the most recent version somewhere.
\end{itemize}
}
\end{frame}
\begin{frame}
\frametitle{Commits}
\begin{center}
\begin{tikzpicture}
%\draw (-1.5,-1.5) rectangle (7.5,1.5);
%\node at (-2.5,0) {master};
\node[commit] at (0,0) (commit1) {93e4d3d\ldots};
\node[commit] at (3,0) (commit2) {2557962\ldots};
\node[commit,draw=red] at (6,0) (commit3) {od68560\ldots};
\draw[arrow] (commit1) -- (commit2);
\draw[arrow] (commit2) -- (commit3);
\node[draw,text width=1.8cm,anchor=north,align=center] at (0, -1.5) {\small \vdots\\[0.1cm] };
\node[draw,text width=1.8cm,anchor=north,align=center] at (3, -1.5) {\small \vdots\\[0.1cm] 93e4d3d\ldots };
\node[draw,text width=1.8cm,anchor=north,align=center] at (6, -1.5) {\small \vdots\\[0.1cm] 2557962\ldots };
\end{tikzpicture}
\end{center}
\note{%
\begin{itemize}
\item Rather than human readable names, Git references each snapshot (called a commit)
by a cryptographic hash. Currently using a hardened sha1 but there is an effort to
move to sha256.
\item Similarly to the model above, each commit references the previous (except the
first obviously)
\item The commit also includes meta information such as the committer, a timestamp and a
message.
\item We will look at this in more detail a bit later.
\end{itemize}
}
\end{frame}
\begin{frame}[fragile]
\frametitle{Install}
\begin{minted}{bash}
# Ubuntu / Debian / Kali
sudo apt install git
# Centos / Fedora / Red Hat
sudo dnf install git
# Arch / Antergos / Manjaro
sudo pacman -S git
# Mac
brew install git
# Get the Version
git --version
\end{minted}
Git for Windows: \href{https://gitforwindows.org/}{https://gitforwindows.org/}
\note{%
Git is probably already installed if you are on a Linux system. However, if not, it will
definitely be in your standard repositories.
There is a version of Git provided with xcode, but it is old. Most of the stuff we cover
today should still work but (for example) some things need to be run from the root directory
in old versions of git that don't in newer versions.
If you have the misfortune to be using windows, I've heard good things about Git for Windows
but have not used it personally. It includes Bash emulation.
Hopefully you have a version greater than 2.23.0 - if not, it's not the end of the world.
}
\end{frame}
\begin{frame}[fragile]
\frametitle{Setting It Up}
\framesubtitle{User}
\begin{minted}{bash}
git config --global user.name "Jonathan Hodgson"
git config --global user.email "git@jonathanh.co.uk"
\end{minted}
\note{%
Hopefully you have Git installed. I will be running it on Linux although the commands should
all be the same for Windows and Mac.
Note that I am not using my primary email address. The email address you provide here will
be available to anyone with access to repositories you work on.
These settings are stored in \mintinline{bash}{~/.gitconfig}.
}
\end{frame}
\begin{frame}[fragile]
\frametitle{Setting It Up}
\framesubtitle{Editor}
\textbf{Pick One}
\begin{minted}{bash}
# Set editor to vim
git config --global core.editor "vim"
# Set editor to nano
git config --global core.editor "nano"
# Set editor to VS Code
git config --global core.editor "code -w"
# Set editor to Sublime
git config --global core.editor "subl -w"
\end{minted}
\note{%
There are several times that Git will need to open a text editor. By default, it will use
\mintinline{bash}{EDITOR}. If neither is set, it will use VI.
Note that if you are using a GUI editor, you might have to set the wait flag. This makes it
so the executable doesn't return until you close it.
}
\end{frame}
\begin{frame}
\frametitle{Create a repository}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-git-init.pdf}
\end{center}
\note{%
Do this in a live terminal. MAKE SURE YOU MAKE YOUR FONT BIGGER
Show that the \mintinline{bash}{.git} folder has been created and do a tree to show what is
in it.
}
\end{frame}
\begin{frame}
\frametitle{Create a repository}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-tree-empty-git.pdf}
\end{center}
\note{%
Do this in a live terminal. MAKE SURE YOU MAKE YOUR FONT BIGGER
Show that the \mintinline{bash}{.git} folder has been created and do a tree to show what is
in it.
}
\end{frame}
\begin{frame}[fragile]
\frametitle{Git status}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-touch-git-status.pdf}
\end{center}
\note{%
Create repo and create a file called greeting.py. Make sure to mark it as executable.
Here we see the branch we are on (Master), we are told that there are no commits yet and we
see that Git can see the file we've just made but it isn't tracking it.
}
\end{frame}
\begin{frame}
\frametitle{Staging Area}
\begin{itemize}
\item Sometimes called the git index
\item An intermediate area in which you can pick files to be included in the next commit.
\item Also allows you to exclude some files from your version history.
\begin{itemize}
\item Log files
\item Binary files
\item Minified files
\end{itemize}
\end{itemize}
\note{%
This is the last thing before we start actually doing stuff (promise).
This is particularly useful if you have multiple logically unrelated changes and want to
make separate snapshots for each.
Also useful if when programming you write your tests along side your code, you would
normally want those to be separate snapshots.
We will talk about .gitignore later which is another way of ignoring files
}
\end{frame}
\begin{frame}[fragile]
\frametitle{Staging Area}
\begin{minted}{bash}
# Add files / or directories
git add <file|directory> [<file|directory>...]
# Add everything not in gitignore
git add -A
\end{minted}
\note{%
}
\end{frame}
\begin{frame}
\frametitle{Staging Area}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-show-staging-area.pdf}
\end{center}
\note{%
Here can use git status to see what is in the staging area. They are listed in the ``Changes
to be committed" section. By default, they will also be green if you have colour switched
on.
}
\end{frame}
\begin{frame}
\frametitle{Committing}
\begin{itemize}
\item First line should be concise summary around 50 chars
\item Body Should be wrapped to around 70 chars
\item There should be an empty line separating summary from body
\item If contributing to a project, check per-project guidelines
\begin{itemize}
\item Normally in contributing.md or similar
\end{itemize}
\item Use the imperative: ``Fix bug" and not ``Fixed bug" or ``Fixes bug."
\end{itemize}
\note{%
First line is often shown by various tools
70 chars allows for good email etiquette. Allowing for 80 char hard wrap with after a few
reply indents
Generally you will want to write in imperative as this is what automatic commits like merge
do.
}
\end{frame}
\begin{frame}
\frametitle{When should you commit?}
\framesubtitle{Commit early, commit often}
\begin{itemize}
\item Every time you complete a small change or fix a bug
\item For each point on a detailed to-do list
\item You don't normally want to commit broken code (intentionally at least)
\item In some instances you might want to auto-commit - but probably not too often.
\begin{itemize}
\item Normally this works if changes can't break something. E.g. Password Manager
\end{itemize}
\end{itemize}
\note{%
Unfortunately, this doesn't have one simple answer.
Some examples of auto-committing are for your password manager.
}
\end{frame}
\begin{frame}
\frametitle{Commit Messages}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-xkcd-1296.png}
\end{center}
\note{%
In case you hadn't noticed, I quite like Randall Munroe.
I am bad for this, particularly on personal projects.
}
\end{frame}
\begin{frame}[fragile]
\frametitle{Commit}
\begin{minted}{bash}
# Open editor for message
git commit
# Read message from file
git commit -F <file or - for stdin>
# Provide message directly
git commit -m "<message>"
\end{minted}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-first-commit.pdf}
\end{center}
\note{%
Running git commit will open your editor.
I only really use -F if I am doing so from a script
}
\end{frame}
\begin{frame}[fragile]
\frametitle{Diff}
\begin{minted}{bash}
# Diff between last commit and current state
git diff
# Diff between 2 commits or references
git diff commit1..commit2
# Same as above but on a single file
git diff a/file
\end{minted}
\note{%
Diff is pretty smart. It will normally work for whatever combinations of commits, references
(more on that later) or files.
Change Hello to Hello World
}
\end{frame}
\begin{frame}
\frametitle{Diff}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-first-diff.pdf}
\end{center}
\note{%
These are hopefully quite easy to understand. Red lines mean a line was removed, green means
a line was added.
}
\end{frame}
\begin{frame}
\frametitle{Log}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-second-commit-with-log.pdf}
\end{center}
\note{%
Here we see a commit done with the -m flag. I generally only use -m if it is a trivial
change like this and there is no need to have a body.
You can see that the log shows a list of the two commits we have made on this project.
The git log command has a lot of flags. We will see some of them later.
}
\end{frame}
\begin{frame}
\frametitle{Under the hood}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-first-cat-commit-file.pdf}
\end{center}
\note{%
I said earlier that we would be looking at how all this works at quite a low level. This is
where that starts.
We can also use the cat-file command built into git to do the same thing. We can see that
Commits, trees and blobs are all stored in the same way.
You will also see that you can often use a prefix of the first 4 or more characters of a
hash. It is quite common to use the first 7 or 8.
Hopefully you will see from this that the inner workings of git isn't that complicated.
}
\end{frame}
\begin{frame}[fragile]
\frametitle{.gitignore}
This file tells git which files not to track.
\begin{minted}{bash}
*.log
*.doc
*.pem
*.docx
*.jpg
*.jpeg
*.pdf
*.png
.DS_Store/
*.min.css
*.min.js
dist/
\end{minted}
\note{%
This will not stop git tracking a file if it's already being tracked.
If you start tracking large binary files, git isn't going to be able to compress them. This
will result in a massive repo and a headache for everyone. If at all possible, don't track
large files, especially if they are going to be changed. Remember, git stores each version
of each file. With text, this is fine as it can be compressed efficiently. If it's not text,
it can't.
You should probably also try to avoid including minified files as git won't be able to merge
them automatically.
}
\end{frame}
\begin{frame}
\frametitle{References}
\begin{itemize}
\item We have just seen that commits are simply (compressed) text files, addressed by a
hash.
\item References are a way of addressing them without remembering the hash.
\item Unlike the hashes, references can change - and they do change.
\end{itemize}
\note{%
We've seen a couple of these (sort of)
}
\end{frame}
\begin{frame}
\frametitle{References}
\begin{itemize}
\item Branches
\begin{itemize}
\item Parallel development
\end{itemize}
\item Tags
\begin{itemize}
\item Special points in history (Release versions)
\end{itemize}
\item HEAD
\begin{itemize}
\item Current position in history
\end{itemize}
\end{itemize}
\note{%
Branches allow for parallel development, individually or multiple people. We well look at
these in more detail in a minute.
Tags allow you to mark special commits. Normally this is used for release versions or
similar.
HEAD refers to the commit or branch you are currently looking at. We will see in a minute
that you can revert a whole project to a previous point in time. This is how git knows
where (when?) you are.
}
\end{frame}
\begin{frame}
\frametitle{References}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-log-with-decoration.pdf}
\end{center}
\note{%
There are two references we can see here, master and HEAD.
}
\end{frame}
\begin{frame}
\frametitle{References}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-cat-master-and-head.pdf}
\end{center}
\begin{itemize}
\item References are stored in the \mintinline{bash}{.git/refs} folder
\item The \mintinline{bash}{heads} folder contains references to the heads (or tips) of all
local branches
\end{itemize}
\note{%
}
\end{frame}
\begin{frame}
\frametitle{Branches}
\begin{itemize}
\item By default Git will create a branch called Master (maybe?).
\item Allows multiple features to be developed in parallel without interference.
\item Allows multiple people to collaborate easily.
\end{itemize}
\note{%
So, when I originally wrote this slide, git would create a branch called master by default.
The convention was that this was your "main" branch. Currently on my system it still does
although there is a movement to switch the default to main or primary or something similar.
I have no intentions to make this a political talk so make of it what you want.
}
\end{frame}
\begin{frame}
\frametitle{Commits / Branches}
\begin{center}
\begin{tikzpicture}
%\draw (-1.5,-1.5) rectangle (7.5,1.5);
%\node at (-2.5,0) {master};
\node[commit] at (0,0) (commit1) {};
\node[commit] at (2,0) (commit2) {A};
\node[commit] at (4,0) (commit3) {B};
\node[commit] at (4,-2) (commit3b) {C};
\node[anchor=west] at (4.5,0.5) {+Bugfix};
\node[anchor=west] at (4.5,-2.5) {+Feature};
\draw[arrow] (commit1) -- (commit2);
\draw[arrow] (commit2) -- (commit3);
\draw[arrow] (commit2) -- (commit3b);
\draw[draw=red] (-1,1) rectangle (6.5,-0.99);
\node[fill=red,text=white,anchor=north west] at (-1,1) {Branch 1};
\draw[draw=green] (-1,-1) rectangle (6.5,-3);
\node[fill=green,text=white,anchor=north west] at (-1,-1) {Branch 2};
\end{tikzpicture}
\end{center}
\note{%
The linear graph we just saw is an overly simplistic representation. In reality, Git
represents history using a Directed acyclic graph which allows parents to be shared my
multiple commits. This is useful because it allows for Branches.
It is good practice to develop features on a separate branch. This allows for multiple
people to work on a project as well as allowing things like bug-fixes to be deployed without
having to worry about interference from a new feature.
}
\end{frame}
\begin{frame}
\frametitle{Commits / Branches}
\begin{center}
\begin{tikzpicture}
%\draw (-1.5,-1.5) rectangle (7.5,1.5);
%\node at (-2.5,0) {master};
\node[commit] at (0,0) (commit1) {};
\node[commit] at (2,0) (commit2) {};
\node[commit] at (5,0) (commit4) {A};
\node[commit] at (8,0) (commit5) {C};
\node[commit] at (4,-2) (commit3b) {};
\node[commit] at (6,-2) (commit4b) {B};
\node[anchor=west] at (5.5,0.5) {+Bugfix};
\node[anchor=west] at (6.5,-2.5) {+Feature};
\node[anchor=south west] at (8.7,-0.2) {\parbox{\textwidth}{+Bugfix \\ +Feature}};
\draw[arrow] (commit1) -- (commit2);
\draw[arrow] (commit2) -- (commit4);
\draw[arrow] (commit4) -- (commit5);
\draw[arrow] (commit2) -- (commit3b);
\draw[arrow] (commit3b) -- (commit4b);
\draw[arrow] (commit4b) -- (commit5);
\draw[draw=red] (-1,1) rectangle (10.5,-0.99);
\node[fill=red,text=white,anchor=north west] at (-1,1) {Branch 1};
\draw[draw=green] (-1,-1) rectangle (10.5,-3);
\node[fill=green,text=white,anchor=north west] at (-1,-1) {Branch 2};
\end{tikzpicture}
\end{center}
\note{%
As well as 2 commits' ability to share a parent, the opposite is also true, Here, we see
that a commit is able to have multiple parents.
This is called a merge commit - because it merges two branches. In a lot of situations git
is smart enough to auto-merge branches although at times human intervention is necessary.
}
\end{frame}
\begin{frame}[fragile]
\begin{minted}{bash}
# List Branches
git branch # -v adds more info
# Create a branch called test
git branch test # or
cp ~/.git/refs/heads/master ~/.git/refs/heads/test
# Switch to new branch
git switch test # or
git checkout test
# Create and switch in one go
git switch -c test # or
git checkout -b test
\end{minted}
\note{%
Branches are represented in git as references in the heads folder.
They can be created by simply creating a file there.
The git checkout command does A LOT of stuff. It can be confusing so it's functionality has
been split up into several smaller commands. If you have git 2.23.0 or newer, you will be
able to use it.
Be aware that a lot of tutorials etc. will use the checkout command. Version 2.23.0 was
released in August 2019.
}
\end{frame}
\begin{frame}
\frametitle{Branches}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-create-first-branch.pdf}
\end{center}
\note{%
As we saw, there are numerous ways to create the commit.
What is interesting to note here is that both are still currently pointing at the same
commit.
Head is pointing at test so any new commits will be on this branch.
Also take note of the git log command. \mintinline{bash}{--on-line} shows a short version
and \mintinline{bash}{--all} shows all branches.
}
\end{frame}
\begin{frame}
\frametitle{Differing Branches}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-differing-branches-simple.pdf}
\end{center}
\note{%
}
\end{frame}
\begin{frame}
\frametitle{Differing Branches}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-branch-diff.pdf}
\end{center}
\note{%
This shows what would be needed to take you from master to test.
Notice the \mintinline{bash}{--graph} flag which adds the drawing to the left
}
\end{frame}
\begin{frame}
\frametitle{Simple Merge}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-simple-merge.pdf}
\end{center}
\note{%
After working on septate branches, you will probably want to merge them eventually.
In this situation, Git was able to work everything out itself.
}
\end{frame}
\begin{frame}
\frametitle{Tidy Up}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-delete-test-branch.pdf}
\end{center}
\note{%
Now that we have finished with that branch, we can delete it.
}
\end{frame}
\begin{frame}
\frametitle{More Complex merge}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-complex-merge.pdf}
\end{center}
\note{%
At times, git won't be able to merge automatically.
Dealing with merges is something that there are around a million different tools you can use but
I think they over complicate what is actually quite a simple process.
}
\end{frame}
\begin{frame}
\frametitle{More Complex merge}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-cat-complex-merge.pdf}
\end{center}
\note{%
Here you can see that the bit(s) git couldn't work out are delimited by
\mintinline{bash}{<<<<<<<} and \mintinline{bash}{>>>>>>>} and separated by
\mintinline{bash}{=======}.
All you (the programmer) needs to do is fix it.
}
\end{frame}
\begin{frame}
\frametitle{More Complex merge}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-fix-complex-merge.pdf}
\end{center}
\note{%
}
\end{frame}
\begin{frame}[fragile]
\frametitle{Time Travel}
\begin{minted}{bash}
# Print a version of a file
git show <commit or reference>:<file>
# Restore a file from a previous version
git restore -s <commit or reference> file # or
git checkout <commit or reference> -- file
# Go back in time to a commit
git switch --detach <commit or reference> # or
git checkout <commit or reference>
\end{minted}
\note{%
Note that for the show command, you need to provide the full path (relative to the root of
the project), not the relative path
Both the restore command and the switch command can also be achieved with checkout on older
versions of git.
In the case of restore and checkout, they are not identical. Checkout will also stage the
file whereas restore wont (without an additional flag)
}
\end{frame}
\begin{frame}
\frametitle{Remotes}
\begin{itemize}
\item The majority of Git commands only affect your local repository.
\item Git has a concept called remotes which you can think of as other instances of the same
repository
\item Git has a selection of commands that are used to communicate with these remote
repositories
\item It can communicate on multiple protocols including
\begin{itemize}
\item HTTP(S)
\item SSH
\item Local Filesystem
\end{itemize}
\end{itemize}
\note{%
The most common public remote is Git hub. This is one of many options.
The most common protocols are HTTP and SSH, both offering advantages over the other.
HTTP is easier to use and allows for anonymous access (useful for public repositories)
SSH allows for easier authentication but there is no anonymous authentication.
For ease of automating screen shots, I will be using local file system although all commands
are the same.
}
\end{frame}
\begin{frame}
\frametitle{Adding a remote}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-add-remote.pdf}
\end{center}
\note{%
In this example, I am using a local folder as a URL but you can use anything.
}
\end{frame}
\begin{frame}[fragile]
\frametitle{Pushing your code}
\framesubtitle{Long Way}
\begin{minted}{bash}
git push <remote> <local-branch>:<remote-branch>
# E.g.
git push origin master:master
\end{minted}
\note{%
Although this is usable, it is a bit annoying since you will normally want to create a 1 to
1 correspondence between your local branches and the remote branches.
}
\end{frame}
\begin{frame}[fragile]
\frametitle{Pushing your code}
\framesubtitle{Easy way}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-set-upstream-push.pdf}
\end{center}
\note{%
Admittedly, this looks like a longer way. However, the first command only needs to be run
the once. Git will then remember that the remote branch origin/master should be linked with
the local branch master.
As you can see from the git-status now, it tells us that the current branch is up to date
with the remote branch.
}
\end{frame}
\begin{frame}
\frametitle{Retrieving changes from the remote}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-fetch-merge-pull.pdf}
\end{center}
\note{%
Here another user has pushed changes to the master branch.
You can see here that the git fetch command downloads the required information. However, it
doesn't change your working tree.
In order to update our local master, we can simply do a git merge
Also note that after the git fetch command, the git status gives us some useful information.
This is another advantage of setting the corresponding upstream branch.
\begin{itemize}
\item We are 1 commit behind the remote version
\item The branch can be fast forwarded.
\end{itemize}
}
\end{frame}
\begin{frame}[fragile]
\frametitle{Git Pull}
\framesubtitle{Shortcut}
\begin{minted}{bash}
git pull
git pull <remote> <branch>
\end{minted}
\note{%
Git has a command called pull which does the equivalent of a fetch then a merge.
The short version will only work if you have the local branch linked with a remote branch.
}
\end{frame}
\begin{frame}[fragile]
\frametitle{Cloning}
\begin{minted}{bash}
# Clone a repository into a folder
git clone <URL> <folder>
# Clone a repository into a folder on a specific branch
git clone --branch <branch> <URL> <folder>
# Shallow clone a repository into a folder
git clone --shallow <URL> <folder>
\end{minted}
\note{%
If you would like to start from an existing remote repository, you can use the git clone
command.
This will automatically set up the link between the local and remote branches.
A shallow clone doesn't download all of the history.
}
\end{frame}
\begin{frame}
\frametitle{Issues}
\begin{itemize}
\item Not part of Git, rather something most Git hosting providers offer.
\item You can normally reference issues in commit messages using \# symbol.
\end{itemize}
\note{%
Demonstrate this in a browser using Github
}
\end{frame}
\begin{frame}
\frametitle{Pull Requests}
\framesubtitle{Merge Requests}
\begin{enumerate}
\item Fork
\item Clone
\item Branch
\item Commit
\item Push
\end{enumerate}
\note{%
\begin{itemize}
\item Not part of Git, rather something most Git hosting providers offer.
\item It allows for people to contribute code to repositories that they don't have
write access to
\end{itemize}
}
\end{frame}
\begin{frame}
\frametitle{Useful supporting tools}
\framesubtitle{Shell Integration}
Git ships with completion for bash, zsh and tcsh. You may need to source it in the relevant rc
file.
Prompt customisation is available out of the box for bash and zsh.
\note{%
If you haven't ever tried zsh, give it a shot. Tab completion is so much more useful than
Bach's.
}
\end{frame}
\begin{frame}
\frametitle{Useful supporting tools}
\framesubtitle{Editor Plugin}
\begin{itemize}
\item Git Gutters
\item Easy staging of parts of a file
\item Merge Conflict Resolution
\end{itemize}
\note{%
There are obviously hundreds of editors so find one that works well with yours.
I think Atom and VS Code have built in integration.
I use vim-fugitive. I've heard good things about magit for emacs.
}
\end{frame}
\begin{frame}
\frametitle{Useful supporting tools}
\framesubtitle{BFG Repo Cleaner}
You'll need something like this when you realise you have just committed your ssh keys
\href{https://rtyley.github.io/bfg-repo-cleaner/}{https://rtyley.github.io/bfg-repo-cleaner/}
\note{%
For the time that you accidentally commit your ssh keys.
I accidentally committed a database for an Woocommerce site.
}
\end{frame}
\begin{frame}
\frametitle{Useful supporting tools}
\framesubtitle{Git Crypt}
For storing sensitive information in a git repository.
\href{https://github.com/AGWA/git-crypt}{https://github.com/AGWA/git-crypt}
\note{%
This will encrypt files with gpg key(s) and transparently decrypt them on the file system.
}
\end{frame}
\begin{frame}
\frametitle{Useful supporting tools}
\framesubtitle{Git Large File Storage}
A solution to the issue of storing binary files
\href{https://git-lfs.github.com/}{https://git-lfs.github.com/}
\note{%
As mentioned, git is not good at storing binary files because they can't be compressed or
diff-ed or merged.
This allows you to store links to large files and transparently add them to the file system
as though they were normal git blobs.
}
\end{frame}
\begin{frame}
\frametitle{Useful supporting tools}
\framesubtitle{Bat}
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-download-aHR0cHM6Ly9jYW1vLmdpdGh1YnVzZXJjb250ZW50LmNvbS82N2U0NGY0YTY4MTUwMzI1Zjc0YjNhNDY4MjBiNzQ3M2ZmN2I5MWE2LzY4NzQ3NDcwNzMzYTJmMmY2OTJlNjk2ZDY3NzU3MjJlNjM2ZjZkMmYzMjZjNTM1NzM0NTI0NTJlNzA2ZTY3.png}
\end{center}
\href{https://github.com/sharkdp/bat}{https://github.com/sharkdp/bat}
\note{%
Bat is described as cat with wings.
It adds syntax highlighting to files. Useful even if you're not using Git
As this is a git talk, it shows lines that have changed since the last commit
}
\end{frame}
\begin{frame}
\frametitle{Useful supporting tools}
\framesubtitle{RipGrep / Fd / Exa}
\textbf{FD} replaces find
\href{https://github.com/sharkdp/fd}{https://github.com/sharkdp/fd}
\textbf{RigGrep} replaces grep
\href{https://github.com/BurntSushi/ripgrep}{https://github.com/BurntSushi/ripgrep}
\textbf{Exa} replaces ls
\href{https://github.com/ogham/exa}{https://github.com/ogham/exa}
\note{%
Fd and RipGrep will respect your gitignore by default.
}
\end{frame}
\begin{frame}
\frametitle{Useful supporting tools}
\framesubtitle{Pass}
\begin{itemize}
\item Password Manager
\item Uses Git for keeping track of history
\item Syncs using Git
\item Everything is encrypted with a GPG key
\item Has compatible android, ios and browser apps.
\end{itemize}
\href{https://www.passwordstore.org/}{https://www.passwordstore.org/}
\note{%
A password manager that uses Git for sync and history.
}
\end{frame}
\begin{frame}
\frametitle{Useful supporting tools}
\framesubtitle{tldr}
The man page for git pull is over 700 lines.
\begin{center}
\includegraphics[width=\textwidth,height=0.8\textheight,keepaspectratio]{auto-shell-tldr.pdf}
\end{center}
\href{https://github.com/tldr-pages/tldr}{https://github.com/tldr-pages/tldr}
\note{%
Sometimes incredibly thorough documentation isn't what you want. Sometimes you know the
command you need but you can't remember exactly how to use it.
This is not specific to git commands, it covers a LOT.
}
\end{frame}
\begin{frame}
\frametitle{Questions}
You can find this presentation here:
\href{https://git.jonathanh.co.uk/jab2870/Git-Presentation}{https://git.jonathanh.co.uk/jab2870/Git-Presentation}
\note{%
Yes, this presentation uses git for version control
}
\end{frame}
\end{document}