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
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}
|
|
|