\documentclass[twoside,11pt]{report}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Packages %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{makeidx}
\usepackage{graphicx}
\usepackage{fourier}
\usepackage{float}
\raggedbottom
\usepackage{array}
\usepackage{multirow}
\usepackage{gensymb} % Just for the degree symbol
\usepackage{ccicons} % Creative Commons icons; now we can delete an image
\usepackage{lettrine} % Drop caps
\usepackage{wrapfig} % Let's wrap some images
\usepackage{hanging} % For hanging indents in a script
\usepackage{fancyvrb} % Use line numbers with code samples
\usepackage{fvextra} % Break lines inside Verbatim environment:
\usepackage{enumitem} % Control spacing in lists
\usepackage{setspace} % Better control over line-spacing
\usepackage{nicefrac} % Use nice fractions
\usepackage[bottom]{footmisc} % Keep the footnotes at the bottom of the page
\usepackage{tabto} % Use tab stops when we need to (especially in footnotes)
\usepackage{microtype} % Make things neater. Thanks /u/-LeopardShark-
\usepackage{tabularray} % Easy tables
\usepackage[]{FiraSans} % sans-serif font; https://tug.org/FontCatalogue/firasansregular
\usepackage[]{footmisc}
\usepackage{setspace}

%\usepackage{showframe}
%\renewcommand*\ShowFrameColor{\color{red}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Indices %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage{imakeidx}
\makeindex[intoc]


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Line Spacing %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\setstretch{1.1}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Commands %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\graphicspath{{images/}} % Where are our images?
\usepackage{multicol} % Include two- or three-column sections
%\counterwithout{footnote}{chapter} % Stop resetting the footnote count after each chapter
\NumTabs{18} % Define 18 tab stops (at 1/4" intervals) [tabto package]
\raggedbottom  % Don't force text to fill page
\setlength{\belowcaptionskip}{4pt} % Adjust space between caption and figure
\renewcommand*\contentsname{In This Issue…} % Change the name of the TOC


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Document Setup%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage{geometry}
\geometry{
	paperheight=11in,
	paperwidth=8.26in,
	heightrounded,
	inner=1.75in,
	outer=1.50in,
	textheight=9.00in,
	top=1.00in,
}

%\addtolength{\topmargin}{0.4in} % Adjust and bottom margin
%\addtolength{\textheight}{-0.75in} % Adjust the bottom margin


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Page Headers%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage{fancyhdr}
\pagestyle{fancy}
 \fancyhf{}
 \fancyhead[LE,RO]{A Git Primer}
 \fancyhead[RE,LO]{Part 1}
 \cfoot{Page \thepage}
\renewcommand{\footrulewidth}{0.5pt}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Chapter Title Spacing %%%%%%%%%%%%%%%%%%%%
\usepackage{titlesec}
\titleformat{\chapter}[display]
    {\normalfont\huge\bfseries}
    {\chaptertitlename\ \thechapter}
    {20pt}
    {\Huge}
\titlespacing*{\chapter}{0pt}{0pt}{40pt}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Custom Macros %%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Make a nice border and box for the tops of our examples
\newcommand\klab[3]{\vspace{#1}\noindent{}\hrulefill\fbox{\texttt{~#2~}}\hrulefill\vspace{#3}}

% Add an \hrule with space above and below
\newcommand\krule[2]{\vspace{#1}\hrule\vspace{#2}}

% Make hrefs easier (must load package hyperref}
\newcommand\kref[2]{\href{#1}{{\texttt{#2}}}}

% Rotate text in tables easier
% https://tex.stackexchange.com/questions/89115/how-to-rotate-text-in-multirow-table
\newcommand\krot[3]{\parbox[t]{#1}{\multirow{#2}{*}{\rotatebox[origin=c]{90}{#3}}}}

% Make diversions easier (and uniform!)
\newcommand\kdivb[2]{
	\medskip
	\hrule
	\medskip
	\noindent{}\textbf{#1}
	\vspace{#2mm}
	\begin{multicols}{2}
}

\newcommand\kdive[1]{
	\end{multicols} 
	\vspace{#1mm}
	\hrule
	\medskip
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Include URLS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Be sure to load this package last
% [hidelinks option to hide big red box. Thanks /u/0b0101011001001011
\usepackage[hidelinks]{hyperref} % Inlcude URLs, but load this package last


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Document Information %%%%%%%%%%%%%%%%%%%%%
\author{Kenneth John Odle}
\title{
	{\fontsize{36}{40}\selectfont A Git Primer}\\
	\vspace{10mm}
	{\fontsize{12}{16}\selectfont Typeset in \LaTeX{}}
}
\date{\begin{small}\today{}\end{small}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Let's get it started %%%%%%%%%%%%%%%%%%%%%

\begin{document}
\maketitle

\section*{Impressum}
All contents  \copyright\the\year{} Kenneth John Odle



\tableofcontents

\chapter{Introduction}

Git is version control software. That is, it allows you to record and track changes to a set of files over time. You can then compare different revisions or even revert some files or the entire project back to a previous version. 

Git also allows you to experiment easily without worrying about messing up your current work by creating a branch and doing your experimental work on the branch. If you like the experimental work, you can merge it into your main branch, or if you decide you don't like it, you can delete it. Git makes experimenting easier for you. 

\section{What Git Can Do For You}

Git is great if you are a software developer, because as you work you make a \textit{lot} of changes to your code. It's also great if you are a writer, because you can experiment as much as you want and not have to worry about losing or overwriting something. You can just revert to an earlier version, or \textit{branch} in order to experiment. But more about that later.

Git works best with text-based files\index{files, text-based}—basically, anything that has a \texttt{.txt}, \texttt{.html}, \texttt{.css}, \texttt{.php}, etc. extension will work. There's no reason that you can't add binaries, such as images, pdfs, Microsoft Word files, or LibreOffice files. (I'm writing this zine in \LaTeX{}, and do include a few images in most issues, for example.) The issue is that because they are binaries, Git won't be able to tell you the difference between versions. (I would add, though, that if you are writing, you really should separate out the content and the styling from the beginning, so that you can focus on the story you want to tell. Plain text files are your friends.)

\section{Git Concepts}

If this is your first exposure to version control software you'll make faster progress if you understand some of the basic concepts. If you are coming to Git from a different version control software, then some or all of these concepts will be familiar to you, although they will probably have different names and probably different functions. Keep in mind that all of these technologies work differently, so you may have to retrain your brain to follow a different workflow.

\paragraph{Concept One: Git exists in both time and space.} This is true of just about all version control software, or at least all the different types I am aware of.

\paragraph{Concept Two: The basic time unit of Git is a \textit{commit}.} A commit is simply a snapshot of where your project stands at any given moment. When you make a commit, it's like taking a picture of your project at that particular moment.

\paragraph{Concept Three: The basic space unit of Git is a \textit{repository}.} All those commmits have to live somewhere, and a repository is just a place where all those commits exist. Repositories (or ``repos'' for short) can be \textit{local}—that is, they exist on your computer only—or they can be \textit{remote}—meaning that can live on other computers somewhere else. That ``somewhere else'' is usually a publicly available server. You can create your own or you can get an account at some place like Gitlab or GitHub, which are privately run for-profit companies, or at someplace like Codeberg,\footnote{\kref{https://codeberg.org/}{https://codeberg.org/}} which is run by a non-profit entity. 

You can work with a local repository only, or you can decide to work with one or more remote repositories. The choice is up to you. 

\paragraph{Concept Four: Repositories are multi-dimensional.} If you make a series of commits to a repository, it will be linear in nature. This is perfectly ordinary. But you may get to a point where you want to experiment with something and you're not sure whether you'll like the new version or the old version better. Rather than commit that new version, which overrides the original version, you can \textit{branch} and have both versions existing at the same time. A branch is basically a copy of a repository at this point in time (i.e., from the last commit). You can then switch between branches and test things out. You can treat it like a sandbox, essentially.

\section{Git Clients}

Git is a command line based technology. Yes, there are GUIs (Graphical User Interfaces) out there for Git, and if you are on Windows or macOS, you may find them useful. You can see a fairly comprehensive list at \kref{https://git-scm.com/book/en/v2/Appendix-A:-Git-in-Other-Environments-Graphical-Interfaces}{https://git-scm.com/book/en\\/v2/Appendix-A:-Git-in-Other-Environments-Graphical-Interfaces}.

In general, I advise against using any type of GUI with Git. For one thing, Git is fairly easy to manage from the command line, so using a GUI just adds a level of abstraction that we don't really need. For another, the command line is forever, but GUIs come and go. If your GUI gets to a point where it's development is discontinued, or it decides to adopt a subscription model that you can't afford, you're in trouble.

A GUI can also obscure what Git is actually doing, meaning that you might end up with less understanding of Git than you would by working on the command line.

\section{Assumptions}

That said, this document assumes that you are familiar with working on the command line in whatever OS you are accustomed to. You do not have to be an expert with it (that comes with time) but you should know how to open a terminal window, enter commands, and interpret whatever feedback you get. 

\chapter{Local Repositories}

Repositories are the basic space unit of Git. You can have as many of them as you want, both locally and remotely. Most people only have a single local repository, so let's start there.

Assuming you have a folder full of files you want to track using Git, open a terminal window in that location (which is now called your ``working directory'') and type \texttt{git init}. Congratulations! You now have a local Git repo!

What has happened is that Git has created an invisible directory (\texttt{.git}) that it will use to store the metadata and database for your project. Do \textbf{not} delete this folder! 

Technically, the \texttt{.git} directory is the actual repository. But most people think of the folder that contains your working files along with the \texttt{.git} directory as a repo. As far as I can tell, it doesn't really matter. Just be aware that a) this distinction exists, and b) some people on the internet can be incredibly pedantic about it (sometimes with reason, and often without).

We haven't made any commits yet, though. All we have are files in our working directory. To make a commit, we need to \textit{stage} our files by using the \texttt{git add} command. You can do this a couple of different ways: we can either list each file one by one (i.e., \texttt{git add file1.txt file2.txt}) or we can just add them all in a single go by using the \texttt{*} wildcard (\texttt{git add *} which will \textit{not} add invisible files, or \texttt{git add -A} which \textit{will} add invisible files).

Before you stage files, though, it's a good idea to examine the status of your project. The command for that is \texttt{git status}.

Now that you've added your files, they are considered to be \textit{staged}, which means that they are ready to commit. You can make a commit now, or you can modify or create new files, and then add them as well. The choice is yours—Git doesn't penalize you either way. Personally, I prefer to make many smaller commits to avoid losing data (and metadata).

If you're happy with the files you've staged, we can now commit them by using \texttt{git commit -m "<commit message>"}. Note that you have to add a commit message. This can be anything you like, but it helps to make it something that will be useful down the road like ``updated chapter three''. You'll get some miscellaneous messages about what Git is doing and then it is done. You've created your first commit, and all of your staged files are now \texttt{committed}.

\chapter{Branches}

If you want to experiment, the best way to do that is to create a \textit{branch}. To do that, just use \texttt{git branch <name>}. To move to that branch, you check it out using \texttt{git branch checkout <branchname>}.

Of course, there's a shortcut to this. You can use 

\input{include/checkout}

\noindent{}which creates a branch called ``branchname'' and moves you to it automatically. 

This is the point where you can experiment and have fun on this branch without worrying about messing up your main branch. If you like the changes that you made on this branch, you can then go back to your main branch (\texttt{git checkout main}) and \textit{merge} those changes. 

\input{include/merge}

It's always a good idea to clean up after ourselves. If we don't need that experimental branch any more, we can delete it with \texttt{git branch -d <branchname>}.

In reality, things are rarely going to be this simple, unless you are only making very basic changes to a branch. You'll possibly get all sorts of error messages or warning messages, and will get confused or even scared. The nice thing about Git is that most of the solutions you need are easily found at the other end of a web search.

\section{A Basic Branching Example}

To get a basic understanding of how branching works in Git, let's start with a simple example. We'll assume that we have a single document called \texttt{doc\_a.txt}. It only contains two lines:

\begin{Verbatim}[frame=lines, numbers=left, xleftmargin=5mm, framesep=3mm, breaklines=true, label=\fbox{doc\_a.txt Initial Contents}]
This is line A1.
This is line A2.
\end{Verbatim}

Let's go ahead and commit those using the following set of commands:

\input{include/branch001}

Notice that we don't have a remote repository at this point, so all we are doing is making commits.
  

\chapter{Remote Repositories}

Remote repositories make it possible to share your work and to collaborate with others. You can do all sorts of things locally, but at some point, you're probably going to want to put your work out there, or just to show off.

\section{Getting a Remote Repository}

If you set up a remote repo on some place like GitHub, or you find a repo somewhere that you would like to work with on your own, you can \textit{clone} that remote repo like this:

\input{include/clone}

For example, if you wanted to get a copy of the Apollo 11 Guidance Computer source code because you happen to be planning a trip to the moon of your own,\footnote{I was delighted to find out that this was available on GitHub. I first learned about this in the Volume Thirty-Eight, Number Four issue of \textit{2600} in an article called ``Supply and Demand, Apollo 11, and GitHub''.} you would just type \texttt{git clone https://github.com/chrisl\\garry/Apollo-11}. Git would create a directory called ``Apollo-11'' and clone a local version of that entire repository into it.

If you want to see the remotes attached to this repo, you can just type \texttt{git remote -v}. In this case, it would show you something like this:

\begin{Verbatim}[]
origin	https://github.com/chrislgarry/Apollo-11 (fetch)
origin	https://github.com/chrislgarry/Apollo-11 (push)
\end{Verbatim}

Of course, those remote repositories don't belong to you, so you can't push any changes you make to them. What you can do is create your own remote repo on a Git-hosting system. I'll do that on my Git site at \kref{https://git.kjodle.net/kjodle/Apollo-11}{https://git.kjodle.net/kjodle/Apollo-11}. To add that remote to my local repo, I will use this:

\input{include/remoteadd}

And running the \texttt{git remote -v} command again shows that I have two different remotes:

\begin{Verbatim}[]
ogit    https://git.kjodle.net/kjodle/Apollo-11 (fetch)
ogit    https://git.kjodle.net/kjodle/Apollo-11 (push)
origin  https://github.com/chrislgarry/Apollo-11 (fetch)
origin  https://github.com/chrislgarry/Apollo-11 (push)
\end{Verbatim}

I named my remote ``ogit'', which is the first letter of my last name combined with ``git''. I need to get rid of those remotes on GitHub, since I can't push any changes to them anyway. To do that I'll use this command:

\input{include/remoteremove}

Running \texttt{git remote -v} again shows that I now just have the remote on my own website:

\begin{Verbatim}[]
ogit    https://git.kjodle.net/kjodle/Apollo-11 (fetch)
ogit    https://git.kjodle.net/kjodle/Apollo-11 (push)
\end{Verbatim}

Are we ready to upload this code from my local repository to my remote repo? Not yet. Let's see what our local branches are by running \texttt{git branch}, which gives us this:

\begin{Verbatim}[]
* master
\end{Verbatim}

In this case, I only have a single branch, which is named ``master''. It also has an asterisk because it's the current branch. The problem here is that my Git website always names branches ``main''. So I need to change that branch name by running 

\input{include/branchrename}

Running \texttt{git branch} again confirms that our branch has been renamed:

\begin{Verbatim}[]
* main
\end{Verbatim}

\section{Pushing Changes to a Remote Repository}

Okay, I have a local repository, I have a remote repository attached to that local repository, and the current branch on both repos have the same name. It's time to move that code from the local repository to the remote one. For that I'll use \texttt{git push} <name of remote repo> <name of current branch>. Since the remote is named ``ogit'' and the branch is named ``main'', the full command looks like this:

\input{include/push}

I did that, and Git thought for a moment, and produced this output:

\begin{Verbatim}[breaklines=true]
Enumerating objects: 3414, done.
Counting objects: 100% (3414/3414), done.
Delta compression using up to 4 threads
Compressing objects: 100% (1077/1077), done.
Writing objects: 100% (3414/3414), 3.01 MiB | 1.69 MiB/s, done.
Total 3414 (delta 2327), reused 3414 (delta 2327), pack-reused 0
remote: . Processing 1 references
remote: Processed 1 references in total
To https://git.kjodle.net/kjodle/Apollo-11
 * [new branch]      main -> main
\end{Verbatim}

That really did take only about 1 second to push 3.1 MiB\footnote{That's not a typo. MiB stands for a \texttt{mebibyte}. See ``The Later Salad Days'' in issue \#2 for more information.} of data. One of the nice things about Git is that it is remarkably fast. 

If you visit that original repository that I cloned on GitHub, you'll see that it has 547 commits. If you then visit the repository I created at \kref{https://git.kjodle.net/kjodle/Apollo-11}{https://git.kjodle.net/kjodle/Apollo-11}, you'll see that it also has 547 commits. This is one of the nice things about Git: when you clone that remote repository, you are getting \textit{everything} associated with that repo. Other version control applications just checkout the most recent version. Hence the term ``clone'' rather than ``checkout''.

For what it's worth, you can have multiple remotes. I can create a remote repository on GitHub, clone it to my local machine, then create a remote somewhere else and add that remote to my local repo. To keep both remotes up to date with local changes, you'll need to push twice, once with \texttt{git push remote1 main} and again with \texttt{git push remote2 main}.

There is a lot more to it than this (I haven't even talked about \texttt{git status} yet!), so I guess I will leave that for part 2 of this primer.

\chapter{Collaborating With Yourself}

I mentioned earlier that you could use Git if you're a writer to keep track of changes to projects, provided you were willing to work with text files. My goal here is to provide at least one workflow for doing that. I'm going to assume a few things:

\begin{enumerate}[noitemsep]
\item You have a remote somewhere on a repository host (like GitHub or your own website).
\item You write all your stories in plain text files in a local repo.
\item Your repository host allows you to edit files on their website. (I can do this on my own site with Gitea\footnote{\kref{https://gitea.com/}{https://gitea.com/}} but I'm not sure about other sites.
\end{enumerate}

The advantage to the workflow I'm describing here is that you can work on your files even if you are not working from your normal machine. Thanks to family medical issues, I sometimes spend a lot of time in hospital waiting rooms and I bring my Chromebook with me. I can edit my files on the web, and then pull down changes to my main laptop (which never leaves my house) when I get home. This is how I do it.

I'll physically go to wherever we are for the day (library, caf\'e, hospital waiting room, etc.) and login to my repository host. I can edit files online using this button:

\begin{center}
\noindent{}\frame{\includegraphics[scale=0.75]{gitea-online-edit}}
\end{center}

At the end of the day, I'll home and go into my local repo, open a terminal in that directory and use the \texttt{git pull} command:

\input{include/pull}

What does \texttt{git pull} do? It's a combination of two Git commands: \texttt{fetch} and \texttt{merge}. 

\texttt{git fetch} gets the change history of the tracked remote and branch, whereas \texttt{git merge} combines the current branch with the specified branch. My local repository will now look like My remote repository. I can write to my heart's content, push those changes, and call it a day. If I'm back at the hospital waiting room again some time later, I can just repeat the process.\footnote{Again, for a visual depiction of this, please visit \kref{https://www.youtube.com/watch?v=FG1NrQYXjLU}{https://www.youtube.com/watch?v=\\FG1NrQYXjLU}.}

\chapter{Other Things}

\section{Extra Files}

If you pull or clone a remote repository, you may notice files like \texttt{.gitignore} and \texttt{README.md}. The first tells Git which files to \textit{not} track. (And yes, you will want to make use of this at some point.) The second is a text document written in Markdown (hence the \texttt{.md} file extension) which appears on the front page of the online repo.

\section{Forks and Pull Requests}

These things aren't a part of Git, but they are something that is offered by GitHub and other repository hosts, so I just want to give the briefest of descriptions here for clarity and completion. 

To \textit{fork} a remote repository is to make a copy of it so that you can contribute to this project. You fork somebody else's project, clone it locally, make your changes, push those changes to your remote repo, and then make a \textit{pull request}, which alerts the owner of the original repository that you have changes you'd like them to incorporate into their project. They can then pull those changes in, or they can ignore them. 

\chapter{Summary of Git Commands}

One of my favorite aspects of Git is that it's fairly intuitive to understand and start using right out of the box, but it's also robust enough to meet the needs of large teams and organizations. What I've done in the following table is to summarize the commands I've used in this primer, along with examples where appropriate. 

\begin{longtblr}
[
	caption = {Summary of Git Commands},
	label   = {tb:gitcommsum},
%	theme   = {custom1}
]{
	width      = {\textwidth},
	colspec    = { X[20,l] X[80,l] },
	hlines     = {0.5pt,solid},
	vline{1,3} = {0.5pt,solid},
	rows       = {5mm, m, rowsep=1.5pt},
	rowhead    = 1,
	cells	   = {font=\sffamily\fontsize{8pt}{11pt}\selectfont},
	row{1}     = {font=\bfseries},
}
Command & Purpose {\& Example, if applicable} \\
\texttt{git init}	& {Creates a local git repository \\ \texttt{git init} } \\
\texttt{git clone}	& {Clones a remote repository locally \\ \texttt{git clone} <URL of remote reposistory> } \\
\texttt{git -{}-version}	& Displays the version of git installed on your system \\
\texttt{git add}	& {Stages (i.e., adds) files to a commit \\ \texttt{git add file1 file2} } \\
\texttt{git add *}	& Stages (i.e., adds) all visible files to a commit \\
{\texttt{git add -A} \\ \texttt{git add --all}}	& Stages (i.e., adds) all files (including invisible ones) to a commit \\
\texttt{git branch}	& Show all branches (the current branch is labeled with an asterisk) \\
\texttt{git branch -{}-show-current}			& Show only the current branch \\
\texttt{git commit}	& {Commits stages files \\ \texttt{git commit -m} ``<commit message>'' } \\
\texttt{git fetch} & Get the change history of a specific tracked remote and branch \\
\texttt{git log} & \\
\texttt{git merge} & Incorporate changes from the named commits into the current branch \\
\texttt{git pull} & A combination of \texttt{fetch} and \texttt{merge} \\
\texttt{git push}	& {Pushes a commit from a local repo to a remote repo \\ \texttt{git push} <name of remote repo> <name of remote branch> } \\
\texttt{git remote}		& {Show only the names of remote repos  \\ \texttt{git remote} } \\
\texttt{git remote -v}	& {Show both the names and URLs of remote repos  \\ \texttt{git remote -v} } \\
\texttt{git rev-list} & \\
\texttt{git status}	& Show which files have been staged and which files are waiting to be staged \\
\texttt{git status -s}	& As above, but in short form \\
\texttt{git status -u}	& As above, but only show untracked files \\
\end{longtblr}


\printindex


\end{document}
