-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGit Tutorial.tex
520 lines (445 loc) · 56.7 KB
/
Git Tutorial.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
\documentclass[12pt, letterpaper]{article}
\usepackage[utf8]{inputenc}
\usepackage{graphicx}
\usepackage{parskip}
\usepackage[section]{placeins}
\usepackage{import}
\usepackage{xifthen}
\usepackage{pdfpages}
\usepackage{transparent}
\usepackage{xcolor}
\definecolor{light-gray}{gray}{0.75}
\usepackage{geometry}
\geometry{
a4paper,
total={6.5in,9in}
}
\usepackage{hyperref}
\hypersetup{
colorlinks=true,
linkcolor=blue,
filecolor=magenta,
urlcolor=cyan,
pdftitle={Overleaf Example},
pdfpagemode=FullScreen,
}
\graphicspath{{Images/}}
\title{Tyler Lab Git Tutorial}
\author{Nabeel Chowdhury}
\date{\today}
\newcommand{\incfig}[1]{%
\def\svgwidth{\columnwidth}
\import{Images/}{#1.pdf_tex}
}
\begin{document}
\maketitle
\tableofcontents
\newpage
\section{Why Use Git?}
\subsection{Who Uses Git?}
Git is a common version control system used in academia and industry to keep track of changes to code either when working individually or on a team. The power of git is its use of a centralized repository that is the main, ground truth of the code and individuals can pull their code from this central repository to make changes and push their local changes to this central repository.
\begin{figure}[ht]
\centering
\Huge
\resizebox{0.5\textwidth}{!}{\incfig{repositories}}
\end{figure}
\subsection{How Does Git Work?}
Git tracks all of the changes to a set of code in "commits". Commits are essentially points in time where you wanted to save the changes you have made. These commits are recorded as a history where you can go back to any of the times you committed changes. You can also have a branching commit history if you want to try multiple things at once or add features to your code without affecting the main code you want to use day to day. Different teams can also work on different features or fixes to the main code and merge it all back together for the production ready code. You can also "tag" specific points in your code as important releases that you can go back to if new features are not working. Saving changes like this instead of as multiple files allows for cleaner code and a much easier way to document how your code was made when passing it on to someone else.
\begin{figure}[ht]
\centering
\LARGE
\resizebox{0.99\textwidth}{!}{\incfig{commit-history}}
\end{figure}
\subsection{Where Does the Central Repository Go?}
You can set a hard drive as a central repository, but that can be difficult for a team to use especially when remote. For this reason, most people use repository hosting websites. One of the most used repository hosting sites is GitHub. It is popular due to its robust toolset, the fact that it is free, and you can host private repsoitories of your code for free. I would also encourage you to sync between multiple repositories just in case GitHub goes down one day and especially if you need to back up your code in other areas than your hard drive. My personal method is using GitHub, Bitbucket, and an external hard drive as three central repositories with identical copies of the same code I am working on.
\begin{figure}[ht]
\centering
\resizebox{0.4\textwidth}{!}{\incfig{remote-repos}}
\end{figure}
\subsection{How Do You Use Git?}
There are two main methods of using git, through the command line and from a desktop GUI. Both have their merits and I will go over them in some more detail in their own sections. My personal preference is the command line as it gives me much more control over what I am doing, but it does also require more memorization of commands. Desktop GUIs are much easier to use when making small changes and pushing those changes to your central repository, but making custom commands to take care of larger and more common tasks is not as easy. Finally, regardless of how small you think your code is, it is always a good idea to track your changes with git from the beginning. You never know when someone else will need part of the code you made or if you will need to go back to a specific point in time before you made a change.
\subsection{Learning to Use Git}
A basic graphical walkthrough is located at \href{https://learngitbranching.js.org/}{Learn Git Branching} Learn Git Branching is especially helpful as it walks you through how all of the basics work and gives you a visual example of what the commands are doing in the code history. The \href{https://git-scm.com/book/en/v2}{git handbook} is also a good resource for learning how git works and the commands you can use, but it does go into much more detail than you will likely need. \href{https://guides.github.com/introduction/git-handbook/}{GitHub} and \href{https://www.atlassian.com/git/tutorials/learn-git-with-bitbucket-cloud}{Bitbucket} have much simpler guides that I would suggest as well.
\section{Setting Up Git}
This tutorial is based heavily on the one from \href{https://docs.github.com/en/github/getting-started-with-github/set-up-git#setting-up-git}{GitHub}
\subsection{Git Download}
\begin{enumerate}
\item Download the \href{https://gitscm.com/downloads}{latest version of git}.
\begin{enumerate}
\item If you download the windows version, you should also install git bash or a similar terminal to have a terminal to enter commands in.
\end{enumerate}
\item If you would like to work using a GUI, download that now.
\begin{enumerate}
\item I suggest either \href{https://desktop.github.com/}{GitHub desktop} or \href{https://tortoisegit.org/}{Tortoise Git}. The git website also has a list of GUIs.
\end{enumerate}
\end{enumerate}
\subsection{Git Installation (In Terminal)}\
\begin{enumerate}
\item Once git is installed, open your terminal (gitbash on windows)
\item Set your name for git on your computer with the following steps in the terminal:
\begin{enumerate}
\item Type \colorbox{light-gray}{\textbf{git config - -global user.name}} followed by your name in quotes:
\begin{enumerate}
\item ex: \colorbox{light-gray}{\textbf{git config - -global user.name "Nabeel"}}
\item This sets the global user name for all commits to the name you enter. If you want to only set a local user name, use \colorbox{light-gray}{\textbf{- -local}} instead of \colorbox{light-gray}{\textbf{- -global}}
\end{enumerate}
\item enter \colorbox{light-gray}{\textbf{git config - -global user.name}} and check the output to see if your name was entered correctly
\end{enumerate}
\item Set your email for git using the following steps:
\begin{enumerate}
\item Type \colorbox{light-gray}{\textbf{git config - -global user.email}} followed by the email you want to use in quotes.
\begin{enumerate}
\item ex: \colorbox{light-gray}{\textbf{git config - -global user.email "nhc22@case.edu"}}
\end{enumerate}
\item If you want to keep your email private and you have a GitHub account, you may want to use the no reply email provided to you under the email setting of your profile.
\item Once again, if you want to set a local user email for a repository, use \colorbox{light-gray}{\textbf{- -local}} instead of \colorbox{light-gray}{\textbf{- -global}}.
\item Check the output of entering \colorbox{light-gray}{\textbf{git config - -global user.email}} to see if the email you entered is outputted.
\end{enumerate}
\end{enumerate}
\subsection{Setup Terminal Code Editor}
By default, the editor in the terminal will be vim. You can change this by following the following \href{https://docs.github.com/en/github/using-git/associating-text-editors-with-git}{instructions}
\begin{enumerate}
\item Type \colorbox{light-gray}{\textbf{git config - -global core.editor}} followed by the path to your editor of choice in quotes.
\begin{enumerate}
\item Note that some editors have shorter aliases that don’t need the full path. For example, for visual studio, you would only need to type \colorbox{light-gray}{\textbf{“code”}} instead of the path to visual studio.
\item You can also add flags after the path, but in the quotes to change how the editor opens. Refer to the linked website for examples of that.
\end{enumerate}
\end{enumerate}
\section{Create an SSH Key}
\subsection{Why Use an SSH Key?}
Without an SSH key, you have to log in and enter a password each time you push changes to GitHub. An SSH key allows you to use a password that you can add to your ssh environment that you only need to enter once when you open the terminal. An SSH key creates a private key on your computer that encrypts your commits that are pushed to an online repository. Your account on the online repository has a public key generated from your private key that decrypts your pushed changes. You can also use the same ssh key for different repository sites. You should note that an SSH key does not verify your commits, for this, we will add a GPG key in the next section.
Instructions for creating and adding an SSH key were found \href{https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh}{here}.
\subsection{How to Create an SSH Key}
\begin{enumerate}
\item Type the following into your terminal: \colorbox{light-gray}{\textbf{ssh-keygen -t rsa -b 4096 -C \textit{email}}} replacing email with your own.
\begin{enumerate}
\item This generates a private key that stays on your computer and a public key to save in your remote repositories like GitHub or Bitbucket.
\end{enumerate}
\item Wait for the ssh key to be generated.
\item When the message asks where to save the key, press enter for the default location. This will make a .ssh folder in your home location. For windows, this is under your C drive under Users and in the folder for your profile name on the computer.
\item Enter a password for your SSH key. Reenter the password to confirm it.
\item Start an ssh-agent with the following command: \colorbox{light-gray}{\textbf{eval \$(ssh-agent -s)}}
\item Add the SSH key to your ssh-agent using the following command: \\ \colorbox{light-gray}{\textbf{ssh-add $\sim$\slash .ssh\slash id\_rsa}}
\item These two commands will need to be run every time you open a new terminal to add the ssh key, but we will add an ssh alias at the end of this section to enter both for you.
\end{enumerate}
\subsection{Add Your SSH Public Key to GitHub}
\begin{enumerate}
\item Type the following into your terminal to copy the public key you generated to your clipboard: \colorbox{light-gray}{\textbf{clip $<$ $\sim$\slash .ssh\slash id\_rsa.pub}}
\item Go to settings in GitHub and find the SSH and GPG keys option.
\item Go to "Add a new SSH key".
\item Paste your public key into the new key field and make sure to name it.
\item You may be prompted to reenter your GitHub password to save the SSH key.
\item These instructions are common to most online repositories so you can add the same public key to multiple online repository hosting sites.
\end{enumerate}
\subsection{Check That Your SSH key is Communicating with GitHub}
\begin{enumerate}
\item Enter the following into your terminal: \colorbox{light-gray}{\textbf{ssh -T git@github.com}}.
\item If the terminal responds by outputting a welcome message with your username, the ssh key was set up correctly.
\item You can also check other sites you have repositories with this ssh key by changing the website in the above command.
\end{enumerate}
\subsection{Setup an SSH Alias for Adding an SSH Key}
Memorizing the correct commands to enter for starting an ssh-agent and entering your SSH key is doable, but annoying. You will also have to do this every time you start a new terminal if you don't want to have to enter you password for your SSH key every time you push changes. Follow the steps below to create a simple alias to enter both commands for you. These intructions were adapted from \href{https://scotch.io/tutorials/how-to-create-an-ssh-shortcut}{these} using method 2. For this example, we will also use vim as it is simpler to make this file.
\begin{enumerate}
\item Type \colorbox{light-gray}{\textbf{vim $\sim$\slash .bash\_aliases}} into the terminal.
\begin{enumerate}
\item This creates a file called .bash\_aliases in your home directory and allows you to write to it using vim. This is typically located in your profile's folder in the User directory of the C drive if you are using Windows.
\end{enumerate}
\item Press \colorbox{light-gray}{\textbf{i}} to start editing.
\begin{enumerate}
\item If you are unfamiliar with commands in vim, refer to this \href{https://vim.rtorr.com/}{guide}. I will list what you need to type as we go.
\end{enumerate}
\item Create an alias in the .bash\_aliases file by typing \colorbox{light-gray}{\textbf{alias connect=}} \\ \colorbox{light-gray}{\textbf{'eval \$(ssh-agent -s) \&\& ssh-add $\sim$\slash.ssh\slash id\_rsa'}}
\begin{enumerate}
\item It is important that the spacing is exactly as I have typed it here.
\item This creates an alias that enters both commands to start an ssh-agent and add the SSH key to the agent when you type \colorbox{light-gray}{\textbf{connect}} into the terminal.
\item When creating additional aliases, any commands you want to do need to be in single quotes and if you want to do multiple at the same time, remember to put \&\& between them.
\end{enumerate}
\item Save the file by hitting escape and typing \colorbox{light-gray}{\textbf{:wq}} and hitting enter. This command is to write (w) the changes to the file and quit (q) or close the file. The colon is to tell vim you are entering code to write and quit.
\item To tell the terminal that this alias exists, enter \colorbox{light-gray}{\textbf{source $\sim$\slash .bash\_aliases}}. This pulls the .bash\_aliases file from your home directory ($\sim$).
\begin{enumerate}
\item You will need to do this step each time you start a new terminal.
\item Typically, you can also use the tab key to auto fill the command with .bash\_aliases after typing the first part of the file name. The tab key can auto fill most commands.
\end{enumerate}
\item Now type \colorbox{light-gray}{\textbf{connect}} or whatever you named the alias to see if it worked. It should ask for you ssh key password
\begin{enumerate}
\item You will no longer need to enter the password until you reopen the terminal.
\end{enumerate}
\end{enumerate}
\subsection{Autoloading SSH Aliases}
Going one step further now, we can make it so git bash will autoload our aliases. To do this we will need to edit the .bashrc or .bash\_profile file in the home directory. If these files don't exist, add the .bashrc file by doing the following:
\begin{enumerate}
\item Navigate to the home directory by typing in \colorbox{light-gray}{\textbf{cd}}.
\item type \colorbox{light-gray}{\textbf{touch .bashrc}}. This will create an empty file named .bashrc.
\item type \colorbox{light-gray}{\textbf{vim .bashrc}} to open the file in vim.
\item copy the following code into this file.
\begin{itemize}
\item if [ -f $\sim$/.bash\_aliases ]; then
\\ . $\sim$/.bash\_aliases \\
fi
\end{itemize}
\item This makes a command that checks if a file called .bash\_aliases exists and if it does, use it.
\item Enter \colorbox{light-gray}{\textbf{source ~/.bashrc}} in the terminal to reload the .bashrc file. This will tell the terminal to autoload the aliases form now on
\end{enumerate}
Note that the next time your open git bash, you will see an error that says a .bash\_profile file, .bash\_login file, and .profile file does not exist. This is fine as it will auto generate the .bash\_profile file for you and the error will not occur again.
\section{Create a GPG Key}
The SSH key we made in the previous section was meant to encript your code changes between your local repositories and your remote repositories. A GPG key is similar in that it encrypts and signs your commits in your local repository so that your remote repository can verify that the commits were made by a trusted individual. Like the SSH key, you will have to generate a private and public key and add the public key to your remote repository hosting site of choice. This tutorial will focus on GitHub, but the same intructions will easily translate to other sites. This tutorial is based on those found \href{https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification/about-commit-signature-verification}{here}.
\subsection{Generate a New GPG Key}
\begin{enumerate}
\item Download the GPG key command line tools from \href{https://www.gnupg.org/download/}{here}.
\begin{enumerate}
\item Pick the correct download for your operating system.
\item For my Windows system, I picked the simple installer for GnuPG as I don't need the full featured version for what I want to do.
\end{enumerate}
\item Open Git Bash or whichever terminal you prefer using.
\item Create your GPG key by entering the following command:
\begin{enumerate}
\item If you have a version of git of 2.1.17 or later, enter \colorbox{light-gray}{\textbf{gpg - -full-generate-key}}.
\item If you are not on version 2.1.17 or later, use \\ \colorbox{light-gray}{\textbf{gpg - -default-new-key-algo rsa4096 - -gen-key}} \\ and skip to step 6.
\end{enumerate}
\item Press Enter for the defult key type. We are making an RSA key for this tutorial.
\item Enter \colorbox{light-gray}{\textbf{4096}} for the key size and hit enter.
\item For the length of time, hit enter if you want to accept the default expiration date of never or select the time frame from the options shown.
\item Enter your full name that you want to be associated with your key.
\item Enter your commit email. If you have set your email to private on GitHub or you don't want people to know your email, use the no reply email provided to you on GitHub under the email settings.
\begin{enumerate}
\item You need to make sure that this email matches the email you set in your config file when you set up git.
\end{enumerate}
\item You can add a comment to label what this key is for.
\item Create a password and confirm it.
\item Type \colorbox{light-gray}{\textbf{gpg - -list-secret-keys - -keyid-format=long}} to list your gpg key.
\item Copy the long form of the key from the sec: section of the output key. This is after the section that lists your key length (4096) and before the expiration date. In the below example this is \colorbox{light-gray}{\textbf{3AA5C34371567BD2}}
\begin{figure}[ht]
\includegraphics[scale=0.5]{GPG Key Listing}
\end{figure}
\item Type \colorbox{light-gray}{\textbf{gpg - -armor - -export 3AA5C34371567BD2}} replacing \\ \colorbox{light-gray}{\textbf{3AA5C34371567BD2}} with your key.
\item Copy the output key from \colorbox{light-gray}{\textbf{-----BEGIN PGP PUBLIC KEY BLOCK-----}} to \\ \colorbox{light-gray}{\textbf{-----END PGP PUBLIC KEY BLOCK-----}}.
\end{enumerate}
\subsection{Add Your GPG Key to GitHub}
We will add the GPG key in the same way as we added our SSH key.
\begin{enumerate}
\item Go to settings in GitHub and find the SSH and GPG keys option.
\item Click on to "New GPG key".
\item Paste your public key into the new key field.
\item You may be prompted to reenter your GitHub password to save the GPG key.
\end{enumerate}
\subsection{Add your GPG key to Git}
\begin{enumerate}
\item In the terminal copy your key's long form again. For this example, I will use \\ \colorbox{light-gray}{\textbf{3AA5C34371567BD2}}.
\item Enter the following replacing my key with yours: \\ \colorbox{light-gray}{\textbf{git config - -global user.signingkey 3AA5C34371567BD2}}.
\end{enumerate}
\subsection{Signing Commits}
\begin{enumerate}
\item If you want git to sign all commits in a specific repsitory, enter \\ \colorbox{light-gray}{\textbf{git config commit.gpgsign true}} into Git Bash. If you only want to sign in all repositories on the computer, enter \\ \colorbox{light-gray}{\textbf{git config - -global commit.gpgsign true}} into Git Bash.
\begin{enumerate}
\item Note that this only works in git versions 2.0.0 and above.
\end{enumerate}
\item If you want to sign a specific commit, add the \colorbox{light-gray}{\textbf{-S}} flag to the call to commit.
\begin{enumerate}
\item ex: \colorbox{light-gray}{\textbf{git commit -S}}.
\end{enumerate}
\item Once you commit changes, you will be prompted to input your password for your GPG key.
\begin{enumerate}
\item If you want to store your GPG key, Mac users can use \href{https://gpgtools.org/}{GPG Suite} and Windows users can use \href{https://www.gpg4win.org/}{Gpg4win}. Alternatively, you can use a gpg-agent, but this does not work as well on macs.
\end{enumerate}
\end{enumerate}
\subsection{Signing Tags}
\begin{enumerate}
\item Add a \colorbox{light-gray}{\textbf{-s}} flag to the tag.
\begin{enumerate}
\item ex: \colorbox{light-gray}{\textbf{git tag -s v1.0.0}}.
\item Note that this is a lower case s for tags and an uppercase S for commits.
\end{enumerate}
\item Verify a tag's signature using the \colorbox{light-gray}{\textbf{-v}} flag.
\begin{enumerate}
\item ex: \colorbox{light-gray}{\textbf{git tag -v v1.0.0}}.
\end{enumerate}
\end{enumerate}
\section{Creating Git Aliases}
\subsection{What are Git Aliases?}
Git aliases, just like SSH aliases I wrote about previously or any other aliases are meant to create shortened versions of commands for long or commonly used commands. Many of the aliases below are common and are listed \href{https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases}{here}. Below are the aliases I use day to day.
\subsection{Creating Git Aliases}
All calls to create an alias starts with the following command \\ \colorbox{light-gray}{\textbf{git config –global alias.}} where the shortened command follows the period and then the command to replace follows that after a space. The command is in single quotes. Replace the \colorbox{light-gray}{\textbf{- -global}} flag with \colorbox{light-gray}{\textbf{- -local}} if you want to make aliases for only a local repository.
These are the aliases I use. The format is such that the alias is followed by the command it replaces.
\begin{itemize}
\item \colorbox{light-gray}{\textbf{alias.co 'checkout'}}
\begin{itemize}
\item This simplifies the command to checkout a code branch.
\end{itemize}
\item \colorbox{light-gray}{\textbf{alias.br 'branch'}}
\begin{itemize}
\item This simplifies the command to create a new code branch.
\end{itemize}
\item \colorbox{light-gray}{\textbf{alias.ci 'commit'}}
\begin{itemize}
\item This shortens the command to commit changes.
\end{itemize}
\item \colorbox{light-gray}{\textbf{alias.st 'status'}}
\begin{itemize}
\item This shortens the command to check that code has been changed and staged for commiting.
\end{itemize}
\item \colorbox{light-gray}{\textbf{alias.unstage 'reset HEAD - -'}}
\begin{itemize}
\item This removes all staged changes.
\end{itemize}
\item \colorbox{light-gray}{\textbf{alias.lg 'log - -color - -graph - -pretty=format:'\%Cred\%h}} \\ \colorbox{light-gray}{\textbf{\%Creset -\%C(yellow)\%d\%Creset \%s \%Cgreen(\%cr)}} \\ \colorbox{light-gray}{\textbf{\%C(bold blue)$<$\%an$>$\%Creset' - -abbrev-commit'}}
\begin{itemize}
\item This outputs the history of my code changes in a nicer format.
\end{itemize}
\end{itemize}
Like the SSH aliases, you can string commands together with \colorbox{light-gray}{\textbf{\&\&}}.
\section{Basic Usage of Git in the Tyler Lab}
There are many things you can do with git, but there are a few standard practices you should know about version controlling code in relation to this lab. I would encourage you to read a guide on git to learn the intricicies of git or do the \href{https://learngitbranching.js.org/}{Learn Git Branching} tutorial for their interactive lessons.I will from this point assume you have done that when talking about how versions controlling occurs in the Tyler lab. Specifics you should understand are how to commit, create a branch, set up a new remote repository, push changes, pull changes, and create tags.I would also suggest you have a GitHub repository open to see what one looks like on their website. The explanations I will give are for using the terminal to use git. These commands will likely be buttons in a GUI as well.
\subsection{Local vs Remote Repository}
When using git, there are going to be two main types of repositories you will focus on, local and remote repositories. The local repository is the one you will be using on your computer directly and the remote repository is the one that is stored elsewhere that is pulled from and that your local repository pushes changes to. Your local repository and remote repository can technically be anywhere. You could make a remote repository that is on a flash drive and a local that is on your computer if you wanted to. You can also have multiple local and remote repositories. For simplicity, I will assume your local repository is the one you pull directly from the lab's GitHub repository and the remote is the copy of your code in this lab repository in GitHub. As I stated earlier though, I would suggest you keep multiple copies of your code that are all referenced to an identical remote so that in case one goes down, you can easily replace it.
\subsection{Access Levels of Git}
You may have noticed earlier the usage of \colorbox{light-gray}{\textbf{- -local}} or \colorbox{light-gray}{\textbf{- -global}} when creating entries into the git config file. These determine what level of access you are modifying the git config file for. Modifying local adds settings for the specific repository you are in at the time. This allows you to create special aliases in individual repositories and allows you to set specific main users of repositories. This is especially important at the VA for our lab as we use a shared profile when working on that computer. the global flag in contrast will apply changes to the git config file the the whole profile on the computer. This will essentially add aliases, user info, etc to all repositories on the computer if not superseded by local git config information. There is also a third flag aside from local and global called system. The system flag actually applies changes to all profiles on the entire computer assuming you have access to make changes at that level. These changes are superseded by the global profile.
\subsection{How to Save Changes to Code (Committing)}
When saving the changes that you have made, you do what is called a commit. In order to do this you first need to stage the changes you want in the commit first. To see a full list of files that are changed, you can look at the status of the repository with \textbf{git status}. This will list all files that have changed and will group code by what is unstaged, staged, and currently untracked. To add changed files to the stage, you use the \textbf{git add} command followed by the file name. A useful tip is you can usually autofill anything in the terminal including file names if you type the start of the file name and hit tab. Typically, you should only be trying to fix one problem at a time, so you will want all of the files in the commit. To add all files, type \colorbox{light-gray}{\textbf{git add .}}. The period signifies you want to all all changed files. Always make sure to check what files are changed with \colorbox{light-gray}{\textbf{git status}} before doing this.
When you are ready to commit type \colorbox{light-gray}{\textbf{git commit}}. This will bring up vim in the terminal so you can add a commit message. Commit messages exist so that when you are looking through your history of commits, you can tell what was done at each stage. When writing GitHub compatible commit message, the first line of the message should be 50 characters or below and be a general overview of changes. Two lines below this short message can be a detailed description of changes. When you are done writing your commit message, make sure to write and quit to save the changes and return the the main terminal. Once again, refer to the \href{https://vim.rtorr.com/}{guide} on vim to understand its usage or use your editor of choice.
\subsubsection{General Commit Practices}
\begin{itemize}
\item When starting to make changes to your code, make sure that you pull from the central repository on GitHub before doing anything. You want to make sure you have the most up-to-date code even if you are working on the code alone. Do this even if you think your code is up-to-date; you could have forgotten.
\item When making changes, commit often. If you question if this is a good time to commit, do it. It is better to have too many small changes to the code than have a giant number of changes that all could affect your code in different ways. Having only small changes in your commit history allows you to precisely dialback to where you code could have broken.
\item When writing a commit message, write a short commit at or below 50 character and a long description if it is needed. The short message is a general description that tells you the overall changes or the point of the changes you made at a glance and the longer description is the detailed log of the changes. Git bash should tell you when your short message is too long when the characters change colors. To enter a description in Git Bash, you need to hit enter twice after finishing your short commit message.
\begin{itemize}
\item Writing a commit message like this allows GitHubto show you your short messages on the website and then the long one when you click on it.
\item Write commit messages in the present tense. Ex: “Adds a random delay after the test begins.”
\item You don’t need to write a description message if you think your short commit explains everything. Remember that you want anyone that sees your commit message in the future to know exactly what you did.
\end{itemize}
\item Always push to your remote repository when you are finished making changes. If you are going to work on fixing another aspect of the code for some time or are taking a break also push your changes. This allows anyone else looking at your code or also working on it to have the most up-to-date version. When you are going to commit changes again, remember to pull again from the central repository.
\end{itemize}
\subsubsection{Conventional Commits}
Using the conventional commit format defined \href{https://www.conventionalcommits.org/}{here} has multiple benefits. The gist of this type of commit is to add a keyword in front of your commit message that categorizes your change into things like fixing a bug (\textbf{fix:}), adding a feature (\textbf{feat:}), adding to the documentation of the code (\textbf{docs:}), adding a commit that breaks backwards compatibility (\textbf{BREAKING \\ CHANGE:}), etc. Go to the link above to see all of the key words, but the ones I listed here are my most used ones. The main benefit of this style of committing is you get a 10,000 foot view of your code so you can hone in of a point in your commit history your are looking for. For example, if you want to find where you fixed a problem, you can just look at the fix keywords. This convention also makes it easier to write automated tools that can generate change logs for your repository if the lab chooses to do so in the future.
\subsection{Branching}
\begin{itemize}
\item When adding new features to your code or addressing a bug, create a new branch for the change first. You create a branch using the command \colorbox{light-gray}{\textbf{git branch}} followed by the name of the branch.
\begin{itemize}
\item This allows the code to still be used in experiments without your changes affecting the code.
\item When you are done changing the code, merge it into the main branch.
\item Once you have made a branch you need to remember to check it out before you make changes to the code.
\item Checking out a branch is done by entering \colorbox{light-gray}{\textbf{git checkout}} followed by the branch name
\begin{itemize}
\item A useful tip is that you can create a checkout a branch simultaneously but using the command \colorbox{light-gray}{\textbf{git checkout -b}} followed by the branch name you want to create.
\end{itemize}
\end{itemize}
\item Name the branch after the feature or bug you are fixing.
\item Once the feature or bug is addressed merge the changes into the main branch and delete the branch you were working in.
\begin{itemize}
\item This keeps the repository clean and free of unused branches.
\item Typically, you will now update the release number and\slash or close an issue calling for the changes you made, both topics that are addressed below.
\end{itemize}
\end{itemize}
\subsection{Merging Changes from a Feature Branch to the Main Branch}
When you have finished the changes in your branch, you will want to merge the changes back into the main branch of the repository. You do this by checking out the main branch again and then entering the command \colorbox{light-gray}{\textbf{git merge}} followed by the name of the branch you want to merge into the main branch. This can get confusing but think of it the same way you do when pulling changes from the remote repository. You are pulling the new changes to the place you currently are.
\subsubsection{Merge Conflicts}
Occasionally when you try to merge or pull changes, you will run into what is called a merge conflict. This usually occurs because you and another person with access to your repository have changed the same files at the same time. This is one of the main reasons we use branches to create our changes. It gives you a little sandbox to play in and make changes before incorporating them with changes others have made. Regardless you are likely to run into merge conflicts more often than not as the team grows. What occurs when you get a merge conflict is that git will add a copy of the conflicting code into your file as a section right below the conflicting code and ask you to pick between the conflicting changes. You can recognize this as it will start with $<<<<<<<$ HEAD, end with the branch you are trying the merge in, and will be separated by equal signs. HEAD is just a signal saying the commit you are located at or the "head" of the commit history has this code and the branch has the other set of code. All you need to do is delete one of the sets of code you don't want and try to merge again. This will auto generate a commit message that says you resolved a merge conflict. I highly suggest you change this message to reflect what happened and what changed.
\subsection{Git Log}
To visualize your commit history, you will enter the command \colorbox{light-gray}{\textbf{git log}}. Alone, this command will produce all of the commits you have made that you can scroll through with the arrow keys. You can leave the log by hitting the q key. Without adding flags to the command however, the log is not very informative which is why I have created the long alias shown above. A simple way you can also make the output informative is by adding the \colorbox{light-gray}{\textbf{- -oneline}}, \colorbox{light-gray}{\textbf{- -pretty}}, and \colorbox{light-gray}{\textbf{- -graph}} flags to make the output nicer and show a graph of the changes over time.
When looking at the commit history, you may notice that all of the commits have this long list of numbers and letters. This is the unique identifying SHA value of the commit. There is no other commit on earth that will have the same SHA value as yours. As a result, you can actually go back to previous commits by checking out commit by this number. You will usually only need the first five or six places of this number to check it out. You just need enough for it to be unique in your repository. In fact you may notice that on GitHub, your commits are only shown with this shortened form of the SHA value when looking at the commit history.
Remembering these SHA values is difficult, which is why we can also tag specific commits as significant points to go back to.
\subsection{Git Diff}
Often, you will want to see what changes have been made to a file, branch, or repository as a whole. Usually, you will use \colorbox{light-gray}{\textbf{git diff}} on its own to see what the uncommited changes change in the code. You can also use the diff command with two branches to compare those changes using \colorbox{light-gray}{\textbf{git diff branch1..branch2}}. Refer to this \href{https://www.atlassian.com/git/tutorials/saving-changes/git-diff#:~:text=git%20diff%20is%20a%20multi,%2C%20branches%2C%20files%20and%20more.&text=The%20git%20diff%20command%20is,state%20of%20a%20Git%20repo.}{guide} for more info on git diff.
\subsection{Creating Tags or Releases}
You can tag the commit you are currently on by entering \colorbox{light-gray}{\textbf{git tag}} followed by the tag name. This tag will then also show up when entering \colorbox{light-gray}{\textbf{git log}}.
\begin{itemize}
\item When adding tags or releases, you should follow a three number format (x.x.x).
\begin{itemize}
\item The first number denotes when you have made major changes. The first of those is when you have determined that the code is experiment ready. Update this number when your experiment is fundamentally changed by your code.
\begin{itemize}
\item ex: You add test conditions.
\end{itemize}
\item The second number is minor changes. This is mostly updated when you have added a feature to your code.
\item The third number represents bug fixes. These are very small changes like changing the formatting or adding comments.
\end{itemize}
\item Creating releases should be done on Github. The main difference is that the tag is generated with a message where you can create a change log from the previous release. Using Github allows you to use Markdown to do so.
\end{itemize}
\section{Intermediate Usage of Git}
Once you have gotten a grasp of the basic commands of git, there are a few commands that will push your skills a little further. I find myself using most of these commands at least a few times a month.
\subsection{Amending Commits}
Lets say you have just committed some changes and you find that you need to make another small change or fix something that should have been in that last commit. That is when you want to use the \colorbox{light-gray}{\textbf{- -amend}} flag to \colorbox{light-gray}{\textbf{git commit}}. Using this flag allows you to add anything staged to the previous commit you just made. When you commit in this way, the previous commit message will come up again if you want to change it. If don't want to change the message, just write and quit.
\subsection{Undoing Commits}
Lets say you want to undo the changes you have made from a commit. To do this, you have two different options: \colorbox{light-gray}{\textbf{git reset}} and \colorbox{light-gray}{\textbf{git revert}}.
\subsubsection{Resetting Commits}
In a nutshell, running \colorbox{light-gray}{\textbf{git reset}} will change where the HEAD of the repository is pointing to and delete commits depending on the flag you at to the command. using the \colorbox{light-gray}{\textbf{- -soft}} flag simply moves the HEAD of the repository to the commit you are requesting and undoes the commits past this point. You can then commit again to essentially amend the commit like was done in the previous section. Using the \colorbox{light-gray}{\textbf{- -mixed}} flag will do all of the following, but will also unstage everything so you can change what you want in the next commit. Using the \colorbox{light-gray}{\textbf{- -hard}} flag will undo the commits, unstage everything, \textbf{and delete all of the work after this commit}. Note that this is the version of the \colorbox{light-gray}{\textbf{git reset}} command than can be dangerous as it deletes work you have done. In the next section, we will look at a safer version of undoing. For more information look at the page on understanding \href{https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified}{git reset} from the git website.
\subsubsection{Reverting Commits}
A safer way to undo changes is to use \colorbox{light-gray}{\textbf{git revert}}. Using this command as opposed to reset takes the commit you want and finds how to apply the exact opposite changes to undo that commit. Then it allows you to commit those reverse changes. This is safer as it does not delete any commits, only adds more. For many, this is the preferred option, not just because it is safer, but also because it accurately shows how the code evolved over time. On the Other hand, when used too much, this will muddy your repository.
\subsubsection{Relative Referencing from HEAD}
This is a good point to talk about the different ways you can refer to commits. Previously, I mentioned that you can refer to commits using the SHA number or the tag value, but this may take some time as you will have to look up the SHA number or the tag number on GitHub or in the git log. Sometimes however, you know that the commit you want to go to or edit is a certain number of commit back or forward from the commit you are on currently. To do this, you can reference locations relative to the HEAD. The HEAD is a pointer to the current commit in the repository you are located at. Adding a carat ($\wedge$) or tilde ($\sim$) and a number will reference a certain number of commits back in the history. Using the carat vs tilde have slightly different meanings when looking at a merged history. When there are no merges, they will generally be used similarly. The carat alone means the first immediate parent. A carat followed by a number asks for that immediate parent number. For example, if commits B and C merge into commit A. If the HEAD is at commit A, HEAD\string^ = A\string^ = B and HEAD\string^2 = A\string^2 = C. Determining which is the first and second parent can be confusing. The only way to tell is by looking at the graph in git log and looking at the parents as right to left. Using the tilde is different in that it asks for the first parent in the previous number of generations back defined by the number after the tilde. The carat and the tilde can be combined to ask for specific commits and multiple carats and tildes can be used. Below is an illustration from \href{https://www.amazon.com/Version-Control-Git-collaborative-development/dp/1449316387}{Jon Loeliger} to illustrate how to look at this. Note that the tree is inverted, so the first parent is on the left, not the right.
\begin{figure}[ht]
\centering
\includegraphics[scale=0.85]{Git Tree}
\end{figure}
\subsection{Combining Commits}
The final way we can manipulate commits at the intermediate level is to combine them or "squash" the commits. There are two main ways to do this. The more advanced way is using rebasing, which I will talk about in the section on advanced usage of git. The easier and more typical way to squashing is to add the \colorbox{light-gray}{\textbf{- -squash}} flag when using \colorbox{light-gray}{\textbf{git merge}}. This will take all of the commits you have done in that branch and then combine them together on the merge. You can also do this manually in GitHub when merging there or submitting a Pull Request, which I will talk about later. You can also squash the last several commits by using \colorbox{light-gray}{\textbf{git reset --soft}} followed by the reference to the commit you want to go back to so you can commit again with all of the files together.
\subsection{Bisect}
The final intermediate command is \colorbox{light-gray}{\textbf{git bisect}}. Using bisect allows you to do a binary search through your commit history to find the moment your code stopped working or a change was made. to start the search, type \colorbox{light-gray}{\textbf{git bisect start}}. This will go to the middle commit of the history. If the code still works, you type \colorbox{light-gray}{\textbf{git bisect good}} to move earlier in the history when searching and type \colorbox{light-gray}{\textbf{git bisect bad}} if the current commit still has broken code. Following this process, you will quickly be directed to the commit that broke your code.
\section{Advanced Usage of Git}
This last section on the Usage of git are more advanced techniques that I have at least used on occasion, but are by no means the full extent on all of the other things you can do with git. I may need to make use of the things in this section a couple times a year or in special cases.
\subsection{Rebasing}
Rebasing is a powerful technique that allows you to drastically alter your commit history in multiple ways. If you enter the command \colorbox{light-gray}{\textbf{git rebase -i}} followed by a reference to how far back in the commit history you want to go, the terminal will change to a screen that uses vim that allows you to do mulitple commands listed at the bottom of the screen. On screen you will see a list of commits with their SHA values and to the left of each commit will be a keyword. By default the keyword will be pick. This keyword says that you want to change the messages of those commits. Another common keyword is drop. This tells the rebase that you want to delete those commits. \textbf{Only do this if you know everything in those commits is something you want to delete.} The final common keyword is squash. Like before, using squash will take all of those commits and combine them together. You will also have the option of changing the combined commit message or allow it to default to a list of all the commit messages. The last main usage of rebasing that I use is you can rearrange you commits on screen if you find a specific reason to. For example, you may want to group commits by the things they change. Beware of doing this if the commits work on the same files as you may accidentally revert a change. When you are done, you write and quit like usual and the rebasing will take effect. If you picked options that affect commit messages, you will keep getting screens where you can change the commit messages one by one in order of the commits on the rebasing screen.
\subsection{Cherry-picking}
Cherry-picking is a technique to take important commits out of other branches and make copies of them in your current branch. Lets say there is a case where someone is working on a feature and they find a way to fix a bug in the main code. They may not be done with the feature addition, but you want the fix as soon as possible. to accomplish this, they can commit the bug fix in their branch and you can "cherry-pick" or make a copy of that commit in the main branch by using \colorbox{light-gray}{\textbf{git cherry-pick}} followed by the commit's SHA value. This will leave the original commit in the feature branch and a copy in the main branch. Then the feature is merged in, that commit will be skipped over in the merge. For a more in-depth look at cherry-picking, refer to this \href{https://www.atlassian.com/git/tutorials/cherry-pick}{guide} from Atlassian.
\subsection{Stashing Incomplete Changes}
Lets say you are in a situation where you are working on some changes locally, but you don't think they are ready for a commit. You need to pull new changes from the central, remote repository or merge in a branch, but to do so would require to to either commit your changes or delete them. Instead, you can "stash" or save these changes using \colorbox{light-gray}{\textbf{git stash}} when you want to bring the changes back, use \colorbox{light-gray}{\textbf{git stash pop}}. You can also make multiple stashes and give them names using \colorbox{light-gray}{\textbf{git stash save}} followed by a name. You can then list the stashes using \colorbox{light-gray}{\textbf{git stash list}} and apply stashed changes back to the repository using \colorbox{light-gray}{\textbf{git stash apply}} followed by the index number of the stashed changes from the list.
\subsection{Submodules}
The final advanced technique I want to mention is using submodules. In a nutshell, using submodules allows you to clone a reference to a repository inside of another repository. When pulling the main repository, you will also be able to pull your submodules. The real strength of this in the lab is we can use shared repositories for tools, modeling, or supporting scripts that can be pulled inside of individual, experiment repositories, but all version controlled from the same place.
\section{Using GitHub}
There are three main reasons to directly go to GitHub instead of using the terminal or your GUI: to make the README, create a release, manage an issue.
\subsection{ReadMe}
The ReadMe of of your repository is meant to allow anyone that uses your code to know exactly how to setup your code and any equipment you need to run the code, how to use your code in and out of the lab, and what every part of your code does. No one should need to ask you anything about your code if you have a good ReadMe and if someone does, the questions you get are good things to add. GitHub allows you to write ReadMes in Markdown on their site. You can write the Markdown code in other tools, but GitHub allows you to preview the changes you are making as you make them. Refer to the \href{https://www.markdownguide.org/basic-syntax/}{Markdown guide} to learn the basic syntax. Below is my basic structure of a ReadMe, but do whatever you think is the most clear way to present your code.
\begin{itemize}
\item Table of contents
\begin{itemize}
\item This has links to all of the other section headings.
\end{itemize}
\item Description of the repository
\item Getting Started
\begin{itemize}
\item This section defines anything you need to know about how to run the code as a whole or what to setup beforehand in the code.
\item Inside of this section are several other sections
\begin{itemize}
\item Prerequisites
\begin{itemize}
\item The versions of other programs you need with links to where you can get those programs. For example matlab.
\item The equipment you need for the experiment.
\end{itemize}
\end{itemize}
\end{itemize}
\item Running the experiment
\begin{itemize}
\item This is a description of how the run the test as a whole.
\item Inside of this section is are two other sections.
\begin{itemize}
\item Running data collection.
\item Data Analysis
\end{itemize}
\end{itemize}
\item Author
\begin{itemize}
\item All individuals who contributed to the code
\end{itemize}
\item Acknowledgments
\begin{itemize}
\item Individuals you want to acknowledge as having impact on the research where this test is used.
\end{itemize}
\item Description of each script
\begin{itemize}
\item Set of subsections titled by the name of each script and then a description of what the script is and how to run it.
\item This list should bealphabetical.
\end{itemize}
\end{itemize}
\subsection{Creating Releases}
Creating a tagged release on GitHub is easier than in the terminal. There also may be an easy way to do this in a desktop GUI. When creating a release on GitHub, use the same three number tag number (0.0.0) format and use the description box to write a change log since the last tagged release. Remember to pull tags. Pulling the code does not pull tags automatically. If you want to push your code to a different repository, this also does not automatically push the tags. You need to specifically put the \colorbox{light-gray}{\textbf{- -tags}} command in the terminal when you push or pull changes.
\subsection{Creating Issues}
Issues are a great way to track any of the problems or improvements you want to make in your code. You can also assign jobs to others in the lab by assigning them issues. If you want to close an issue, you can do this manually in github, or you can close it with a commit message by following \href{https://docs.github.com/en/enterprise/2.16/user/github/managing-your-work-on-github/closing-issues-using-keywords#closing-multiple-issues}{these instructions}.
Documenting your bugs, features you want to add, and any future changes that need to be made is necessary for a few reasons. The main one is that it helps regulatory bodies like the FDA or the IRB know exactly when and how we found and solved problems in our code and how we did our due diligence in making sure we have safe code. Documenting issues also helps you keep your thoughts in order and your can even organize your issues into groups using projects on Github. I usually make a project for improving test code and another for analysis code. Projects also allow for automation in making issues into categories like to-do, in progress, done, and wont fix. Finally, making issues allows you to organize a team of people fixing code by allowing you to assign jobs to people and setting milestones in GitHub.
\subsubsection{Closing Issues with Commit}
GitHub allows you to close issues automatically when you add specific keywords to your commit messages. You can see a list of keywords \href{https://docs.devart.com/studio-for-sql-server/source-controlling-databases/associating-commits-with-github-issues.html}{here}, but I usually use the words Closes or Fixes followed by the number of the issue (ex: Closes \#1). Typically, when I'm writing my commit messages, I will add these keywords as a footer to the commit message under the description of the commit. The main benefit of closing your issues like this is that the issue is linked directly to the commit that closed it making it very easy to see the exact changes you made that resolved a problem in your code.
\subsection{Forking}
On GitHub, there is an option at the top labeled as fork. You can do this on any public or private repository that you have access to and it will create a copy of the repository in my personal profile. The benefit of this is you can make large changes to this copy of the repository without affecting the original. If you want to then add some or all of those changes to the original, you can submit a pull request, which I will talk about next. Be careful when making forks. This is not a way for you to make multiple copies of the same code as this defeats the purpose of version controlling. There may be better options depending on your situation like branching to add a feature or using submodules when you want the same support scripts in multiple repositories. The only real time to fork is if its a repository outside of the lab or you want to create a whole new experiment where you will be changing the code to the point where it would no longer work for its original purpose.
\subsection{Pull Requests}
The final information you need to know about GitHub is they have a feature called pull requests. This is something we would have to turn on for repositories and the main purpose of them is so that a senior person can verify code. It works similarly to an issue, but is usually done when merging a branch to the main code. It will signal a senior person and ask them to review the code before approving the pull request. As of writing this, the Tyler lab does not do pull requests as we are a small team that can self manage our code well enough, but as we get bigger and want to collaborate, we will want to enable pull requests on code we share to make sure we only accept code we want integrated into our repositories. Pull requests will generally by done directly on GitHub, but we can also make settings that make pull requests under certain conditions when people push code.
\section{Conclusion}
The most important thing for you to do is keep the central repository of code on GitHub up-to-date. We all use each other’s code so we need to know that what is on GitHub is experiment ready. Clear documentation is also important. I shouldn't need to ask you what something does or why you did something. The changes should be documented well in commit messages and your code should have enough comments for me to read it clearly. Add things to the ReadMe if you think it will make the usage of your code clearer.
Documenting your code is \textbf{NOT} something you do when you are done with it. Documentation of your code starts the moment you create your repository. Map out your organization beforehand. If you are organizing your code well, you do not need copies of the same code that do different things. Your versions will be documented or tagged and any features you are exploring should be in branches off of the main one. You should not run any code that is not in the main branch as well. That is the branch we know is experiment ready. You know you have done what you should if you can hand your code to any member of the lab and they can run your experiment without you there.
\end{document}