-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgitWellSoon.tex
More file actions
295 lines (207 loc) · 15.5 KB
/
gitWellSoon.tex
File metadata and controls
295 lines (207 loc) · 15.5 KB
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
% !TEX TS-program = pdfLaTeX
% !TEX encoding = UTF-8 unicode
\documentclass[11pt, a4paper, english]{article}
% Layout packages
\usepackage{changepage} %for margins
\usepackage{wrapfig} %for sidebars
\usepackage{tabularx} %for tables
\usepackage[noheadfoot,margin=1in]{geometry}
\setlength{\parindent}{0cm}
\setlength{\parskip}{2ex plus 0.5ex minus 0.2ex}
%Environment packages
\usepackage{graphicx} %for images
\usepackage{tcolorbox} %for background colours
\usepackage{hyperref} %for URLs
%usability packages
\usepackage{todonotes} %for keeping track
\usepackage[l2tabu, orthodox]{nag} %forces LaTeX commands
%Environments
\newenvironment{wrapbox}
{
%\begin{wrapfigure}{#1}{0.5\textwidth}
\begin{tcolorbox}
}
{
\end{tcolorbox}
%\end{wrapfigure}
}
\begin{document}
\title{Git Well Soon: a crash course in version control}
\maketitle
\begin{wrapbox}
If you're not familiar with using a terminal to navigate, all you need for this session are the following commands: \verb|$cd [folder]| will move you into [folder]; \verb|$cd ..| will move you up to the parent folder; \verb|$ls| will show files in the current folder; and \verb|$mkdir [name]| will create a new directory called [name].
\end{wrapbox}
Ciaran has a set of SAR tools he is maintaining using a Github source code repository; \url{https://github.com/Ciaran1981/geospatial-learn} Here's how you can get that code for your own use, make any changes you feel are needed and share it with anyone else who would require it.
\underline{What is Git?}
Git is a way of managing and keeping track of a piece of software's history -- who made what change when. It is also a way combining code from multiple developers together into a single piece of software, while still keeping track of who did what.
\underline{Installing Git}
If you're on Windows, then you can install Git for Windows via the University's Program Installer. If you're on an Ubuntu or other Linux machine, then Git is usually pre-installed. If not, then you can install it with
\begin{verbatim}
$ sudo apt-get install git-all
\end{verbatim}
on the command line.
\begin{wrapbox}
From here out, it's assuming that you are using a standard Bash terminal for navigation. If you are on Windows, a good enough emulation comes with Git for Windows; just type 'Git Bash' into the search bar.
\end{wrapbox}
\underline{Getting the code}
First, navigate to a convenient empty directory using cd and mkdir, as appropriate. Once there:
\begin{verbatim}
$git clone https://github.com/Ciaran1981/geospatial-learn.git
\end{verbatim}
This is now the \textbf{root} of your local repository -- as far as Git is concerned, everything is relative to this point.
%\missingfigure{diagram of clone}
\underline{What is happening here}
This will copy all of Ciaran's code from Github to your machine into a \textbf{local repository}, complete with the history and branches [see later] of his project right to the beginning -- you can view this with the command \verb|$ git log|. Press 'q' to exit the log viewer.
\underline{Why do this?}
As well as getting the entire project's codebase, when you cloned the repository with \verb|$ git clone|, you also cloned its history and configuration. This means that you can:
\begin{itemize}
\item Keep it up to date with any revisions Ciaran might make in the future
\item Review any changes he might have made in the past, and understand why he made those changes.
\item If you make a huge, unfixable mistake, or if the code was working last Tuesday and isn't now, you can roll the entire project back to a point where everything was working
\item Fix any bugs or glitches you might find
\item Add any further features that you think the code might need, and share those features with anyone else.
\end{itemize}
\underline{Keeping the code up-to-date}
Whenever Ciaran or anyone else makes a change or adds a new feature, you can easily update his code on your own machine with this command:
\begin{verbatim}
$git pull
\end{verbatim}
You should now see a short summary of what has been changed; you can get more information using the command \verb|$ git diff|, or see the later section on using graphical tools.
\textbf{IF YOU DO NOT WISH TO EDIT ANY CODE, YOU CAN STOP HERE.}
\underline{Editing code of your own}
Before you go any further in this tutorial, you will need to go to www.github.com and register an account.
Let's say you wanted to add a function to Ciaran's codebase. You've written the script -- let's call it [newthing] -- in a file of its own (\verb|newthing.py|), and now you want to add it to Ciaran's repository so everyone else can use it. This process has a few steps.
\begin{enumerate}
\item Put newthing.py in a sensible place in your local repository using a file manager. You can check it's there with \verb|$git status|
As you might gather from the status message, Git does not know that you want to add newthing.py to the repository.
\item Use the command
\begin{verbatim}
$git add FILEPATH
\end{verbatim}
where \verb|FILEPATH| is the path from the root of your local repository. If in doubt, use the message that git status gives you.
This adds newthing.py to your staging area. This is where any changes you make are stored until you commit them to your local repository in the next step.
\item Commit the changes to your local repository with the command
\begin{verbatim}
$git commit --m "some informative message here"
\end{verbatim}
The message you write in here is what will appear when anyone runs \verb|$ git log|, so make sure it's informative and clean(ish)
\begin{wrapbox}
If you forget the --m option, by default Git will open vim; a powerful but non-intuitive text editor. To exit Vim, press 'esc' then type ':q!' without the quotes. If you want to \textit{learn} Vim, clear an hour in your schedule and run \verb|vimtutor| from the command line.
\end{wrapbox}
\begin{wrapbox} \underline{When to commit:} “Early and often” is the mantra from the community; the smaller each commit is, the more powerful the 'time-travel' tools become. Find a commit pace that works for you, but if in doubt more often is usually better.
\end{wrapbox}
This commits snapshots of your code to your local repository;
\item Continue to edit and \verb|$ git commit| your code, using [add] to add new files as required. Bear in mind none of these changes will go to Ciaran's repository yet.
\item Once you are happy with your new feature and are reasonably sure that it doesn't break anything else, use the command
\begin{verbatim}
$git push
\end{verbatim}
to put your changes into Cieron's repository. You might be prompted for your Github username and password here.
\end{enumerate}
\begin{wrapbox}
When you're doing a large commit (such as adding a new feature to a repo), it's good to write a longer commit message using a text editor -- the default is Vim, but you can change this using the command git config --global core.editor [editor]. For a quick guide to writing useful commit messages, see \url{https://chris.beams.io/posts/git-commit/}.
\end{wrapbox}
\underline{Branching}
It is a sad fact that when working on improving a piece of code, you will almost certainly break it or something else instead. To avoid this and the associated recriminations, Git allows you to make local timelines of the project that you can mess around with as you please, without affecting anyone else's work. These local timelines are called 'branches'.
By convention, each Git repository starts with a branch called 'master'. Once the initial code repository is written, this is usually the 'this code works' branch -- anyone wanting to use Cieran's tools will use the code stored in 'master'.
\textbf{It is good practice whenever you are writing a new feature to create a branch to develop it in.} This way, others can still use the original version of the program and also contribute to your improved version, and you can test your new features without having to worry about breaking the software for everyone.
To create a new branch, use the command
\begin{verbatim}
$git branch [branchname]
\end{verbatim}
to create the branch, and the command
\begin{verbatim}
$git checkout [branchname]
\end{verbatim}
to start work in the new branch. As long as you have commited your work, you can move between branches with the \verb|$git checkout| command and see the difference between them with \verb|$git diff [branch1] [branch2]|.
This branch is in your \textbf{local repository}. If you \verb|$ git push| while you're working in a branch, Git will add that branch to the \textbf{remote repository} for others to access.
\underline{Merging}
Merging is when you take the changes made in one branch and apply them to another branch. Git is very smart about this, and changes are done more or less line-by-line - even if two people are working on different parts of the same file in different branches, Git can collate those changes without user input (but see the next section). There are two situations where you need to merge regularly;
\begin{itemize}
\item \underline{When you have finished work on a branch:} You will want to merge your shiny new feature into the 'master' branch, so everyone can use it. To do this, first make sure you have \verb|$ git commit| -ed your changes to your branch. Then, move to the 'master' branch using
\begin{verbatim}
$git checkout master
\end{verbatim}
Once there, use the command
\begin{verbatim}
$ git merge [branchname]
\end{verbatim}
This will bring the changes out have made in [branchname] into the 'master' branch; you can then push that branch to the remote repository using \verb|$ git push|.
\item \underline{Someone else has made a change to 'master' while you are working on your branch:} you will want to make sure that this new change does not affect your work. Therefore, you will want to merge the changes made in 'master' with your own branch.
To do this, first you will need to pull the changes from the remote repository to your local repository. Make sure you are in [branchname] using \verb|git status|, then use:
\begin{verbatim}
$git fetch origin master
\end{verbatim}
to get the change. This actually creates a new branch, 'origin/master' in your local repository that contains said changes. Then use
\begin{verbatim}
git merge origin/master
\end{verbatim}
to bring the changes into [branchname].
\end{itemize}
\underline{Conflicts}
It can happen that two people working on the same repository both change the same part of the same file in different branches. When this happens, Git does not know how to combine the two files - this is a \textbf{merge conflict}, and it will cause the merge to fail. Git can't solve this on its own; you will have to talk it over and decide which revision to keep, how to reconcile the conflict, ect. Them make the edits and commit as normal.
\underline{Rolling back}
The final basic trick that Git provides is rolling back. Think of this a time-machine for your project; you can jump back to any point in the project's history that was \verb|$git commit| -ed. As a rule, any piece of work that was committed is recoverable \textit{somehow}; it is quite difficult to permanently lose work with Git. If you have lost some work that you've committed, talk to the repo administrator -- they can probably get it back for you.
You might have noticed so far that each commit has a long string of meaningless numbers and letters associated with it; this is that commit's \textbf{hash}. Any time you need to refer to a given commit, you can use \textbf{the first four characters} of it's hash.
\underline{Rolling individual files back to the last checkout}
If you've made some changes to a file since your last commit and want to restore it to its original state
\begin{verbatim}
$git checkout -- [filename]
\end{verbatim}
will overwrite the current version of [filename] with the last version you committed. Be careful; \textbf{this will lose your changes for good}.
\underline{Looking backwards in time}
If you wish to see what the project looked like at a given commit point,
\begin{verbatim}
$git checkout [hash of commit]
\end{verbatim}
will move your project back to the state it was in at that point in time.
If you want to make changes from that point, you will need to start a new branch. Instead of the above, use the command
\begin{verbatim}
$git checkout -b [new branch name] [hash of commit]
\end{verbatim}
This will start a new branch from that point that you can checkout and merge as required.
You can return to the present with
\begin{verbatim}
$git checkout [branch you were working on]
\end{verbatim}
\underline{Undoing large changes}
If you wish to undo a specific commit;
\begin{verbatim}
$git revert [hash of commit]
\end{verbatim}
This will create a new commit that removes the effects of the old commit -- this has the same effect as you going over each of the changes from the old commit one-by-one and putting them back the way they were, but with far less effort.
NOTE: This does not work back through the history; it only undoes the changes made by \textbf{that specific commit}. If you want to know more, Git has a more sophisticated way of defining ranges of commits: \url{see https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection}.
\underline{GUI-based Git}
If you prefer something you can click on, rin \verb|$ gitk| on the command line. This will open up a history viewer for the repo you are presently in. There is also a full GUI for controlling Git included in the Windows distribution; most of the commands here you can do via that, if you prefer.
\underline{Acknowledgements and further reading}
Most of the content of this guide came from Pro Git, by Scott Chacon and Ben Straub. The whole book is available for free here:\url{ https://git-scm.com/book/en/v2}. I recommend reading through chapters 2 and 3 (especially 3.5), and sections 7.1, 7.2 and 7.3. Remember, the arrows in the diagrams point backwards in time.
You can also work through an online introduction to Git at \url{https://try.github.io}.
As mentioned above, I also recommend you read \url{https://chris.beams.io/posts/git-commit/} for a set of instructions about writing informative and useful commit messages.
This document was written under source control; you are welcome to clone it from \url{www.github.com/Thingus/GitWellSoon}.
\underline{Some last words to remember}
\begin{itemize}
\item Always \verb|$ git commit| before you \verb|$git pull|
\item Always \verb|$ git pull| before you \verb|$git push|
\item Never use any command with --force unless you're \textit{absolutely sure} you know what you are doing. Even if the Internet says otherwise.
\end{itemize}
\pagebreak
\underline{Quick reference table}
\begin{tabular}[c]{|p{0.4\textwidth}|p{0.6\textwidth}|}
\hline
\textbf{When you want to...} & \textbf{Use the commands...} \\ \hline
Add a new code repository & \verb|$git clone [repo URL]| \\ \hline
Get any changes made to that code & \verb|$git pull| \\ \hline
View those changes & \verb|$git log| \\ \hline
Check what files you've changed since your last commit & \verb|$git log| \\ \hline
Add a new file to your local repo &
\verb|$git add [files]| \\
&\verb|$git status| \\
&\verb|$git commit -m 'Some informative message'| \\ \hline
Branch the repo to start work on a new feature &
\verb|$git branch [branchname]| \\& \verb|$git checkout [branchname]| \\ \hline
Merge changes from another branch & \verb|$git merge [otherbranch]| \\ \hline
Move a file back to it's last commit (LOSING ANY CHANGES YOU'VE MADE SINCE THEN) & \verb|$git checkout -- [filename]| \\ \hline
Rewind the entire project back to a certain revision & \verb|$git checkout [hash]| \\ \hline
Create a new commit that undoes any changes made in commit[hash] & \verb|$git revert [hash]| \\ \hline
\end{tabular}
\end{document}