summaryrefslogtreecommitdiff
path: root/documentation/gitcheatsheet.mdwn
blob: 4a0e46209a99e67a79b8e8d72db947de9918bcd1 (plain)
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
[[!meta title="Documentation/GitCheatSheet"]]
[[!meta author="Chris"]]
[[!meta date="2016-04-28T18:32:38Z"]]


[[!toc]]

Git cheat sheet
===============

This document is here to help NetSurf developers who are more used to
non-distributed revision control systems, or to DVCSs which are not
`git`. It also contains a few helpful hints for people used to `git` so
it's worth a skim even to those who think they know it all already.

`Git` is one of the least obvious, least intuitive distributed revision
control systems out there. However it is also very powerful and very
fast. `Git` appears to have won the DVCS race for the most part, and as
such, NetSurf uses it.

Identify yourself
=================

Every commit you make with `git` contains an identity. (Actually you can
differentiate between the identity of the author of a patch and the
person committing it to the repository if you want.) As such, you must
teach `git` who you are.

`git config --global user.name "My Name"`  
`git config --global user.email whoever@domain.name`

Note that if you don't specify `--global` the name/email address will
only be local to the `git` tree you are inside when you run the command.

The first time you make a commit, if you have not configured your
identity, `git` will give you a reminder.

Useful bits and bobs
====================

It's well worth running:

`git config --global push.default current`

Since it tells git to only push the branch you're on.

Repositories, Trees and Branches
================================

Each `git` repository is a project. As such, NetSurf has many
repositories. NetSurf's repositories reside on the NetSurf
[Gitano](http://www.gitano.org.uk/) instance. We will refer to this as
the *server* from now on.

You acquire a copy of a repository by asking `git` to *clone* it.

`git clone `[`git://git.netsurf-browser.org/buildsystem.git`](git://git.netsurf-browser.org/buildsystem.git)

By default, `git` will create a directory named after the repository and
clone all the branches in that repository into it.

When you have a local clone of a repository, we refer to that as a
*tree*. `Git` may also refer to it as a *working tree* and it is where
changes are made and commits are done.

Each repository may have many branches. `Git` keeps them tucked away,
showing you only one at a time in your tree. You can list your local
branches with:

`git branch`

By default, a fresh clone will only contain one branch called `master`
which is the equivalent of Subversion's *trunk*.

You can switch between local branches with:

`git checkout branchname`

Different bits of `git` documentation may also refer to *refs*. In `git`
branches, tags, etc are all represented by their commits. To give those
commits useful-to-a-human names, `git` has the concept of a *ref* which
is simply a name given to a commit. Refs in the namespace `refs/heads/`
are referred to as branches.

Revisions and commits
=====================

There are no traditional revision numbers in `git`. Instead each commit
is given a unique identifier. It is a long (40 character) hexadecimal
string but it is also commonly shortened to its first 7 characters. For
example, at the time of writing, the tip of the `master` branch in the
`NetSurf` repository was `00f76b5`.

Remotes
=======

Because your `git` tree is also a full local copy of the repository,
`git` keeps track of the server's copy of the repository in a data
structure called a *remote*. The default name for a remote is `origin`
and you will see that crop up in various places as we continue.

You can update your local view of the server with the command:

`git remote update`

Or, assuming you're on `master` you may find *pull* to be of more use:

`git pull`

If you *pull* then `git` first updates its view of the remote, and then
attempts to merge in changes from the remote into your local branch. If
you've not made changes locally then this will be done by
*fast-forwarding* you to the server's revision.

You can see the branches available on any remotes you have registered in
your tree with:

`git branch -r`

Making a branch to work on
==========================

We recommend that everyone work on branches, merging to `master` only
when work is ready for others. In the past we've all worked on `trunk`
because it was such a pain in Subversion to merge work. However one of
`git`'s strengths is its merge functionality so this habit should end.

Before making a new branch, it's customary to ensure that you've got
everything up-to-date from the server:

`git remote update`

Then you can create a new branch, from the server's idea of `master`
with:

`git checkout -b username/branch origin/master`

You should put your own username in for *username* (note it should be
the username which the server has for you. You can find that out by
running `ssh nsgit@netsurf-browser.org whoami`).

For the branch name, give it something reasonably descriptive but not
too long. For example `fandango-experiment` is good, where
`experiment-with-new-layout-engine-idea` is probably too long.

The `origin/master` is where you tell `git` that you want to track the
`master` branch of the `origin` remote. This not only gives you a
starting point for your branch, but also informs `git` where to get
changes from if you run `git pull` while you have that branch checked
out.

To then inform the server of your new branch, run:

`git push origin username/branch`

When you wish to inform the server of new commits on your branch, you
can subsequently just run:

`git push`

Deleting a branch
=================

To delete a branch from the server when it is no longer required:

`git push origin :username/branch`

Making changes and committing them
==================================

You can make any amount of local changes before you commit, although we
recommend each commit be a reasonable self-contained "patch". Obviously
it is better to commit early and often; and `git` does contain a variety
of tools for helping you to turn a long line of small commits into a
neater set of commits ready for merging. We're not too bothered about
that with NetSurf for now; but if you want further reading on the
subject, go and search the web for *git rebase*.

You can ask `git` about your working tree any time you like with:

`git status`

You can see changes in your working tree which you've not told `git`
about yet, with:

`git diff`

When you have edited the code and you are ready to commit, you should
run:

`git add filename another/filename etc/etc/etc`

You can run `git add` as many times as you like. Each time you do,
you're saying to `git` *I want you to remember this file just like it is
right now*.

If you need to remove files then run:

`git rm filename`

You can see the diff which `git` has prepared for committing, with

`git diff --cached`

Once you're happy you've told git about any edited, new or deleted
files, you can run:

`git commit`

This will pop up an editor, telling you what will be committed and
encouraging you to write a change comment. The first line of the change
comment should be short (60 or so chars or less) and pithy. It will be
shown on the IRC channel as the commit message and also forms what `git`
refers to as the *short log message*. The rest of the message (ideally
separated from the first line by a blank) should explain what you did
and why. Normal good commit message etiquette applies here.

You can see the log with:

`git log`

Don't forget to `git push` your commits to the server if you want anyone
else to see them.

Merging branches
================

Since we're encouraging work on branches, we also need to know how to
merge those into the `master` branch. In order to keep things neat and
tidy, we ask that branches be merged in the following way:

`# Switch to the master branch`  
`git checkout master`  
`# Ensure we're up-to-date relative to the server`  
`git pull`  
`# Merge the local branch in`  
`git merge --no-commit --no-ff username/branch`  
`# Review the changes here (git diff --cached)`  
`# Commit the changes`  
`git commit`

Note that the commit will default to a message about the merge. That is
sufficient, although obviously any more useful message would be
appreciated. If the branch is not a local one, but one retrieved from
the server, then simply insert `origin/` in front of the branch name (so
it becomes `origin/username/branch`) to tell `git` the location of the
branch.

Once the commit is done on `master` you can `git push` it to the server.

The options to `git merge` are important. The `--no-commit` causes `git`
to leave the tree at the point that it has done the merge but hasn't
committed it to the branch. By default, `git` will commit merges which
had no conflicts. Since our code base is complex this is not always
sufficient, hence the review step above. The `--no-ff` causes `git` to
prepare a merge commit. Without it, if the `master` has not moved on
from where the branch was created, `git` will instead simply shunt the
commits onto the `master` branch. While not a bad thing in and of
itself, this would mean that when you did `git push` the `CIA.vc` bot
would announce every single commit from the branch.

Merging changes from a 3rd party's repo
=======================================

To merge from the "foo" branch of Somebody's github clone of the NetSurf
repo we can do this:

`git remote add somebody `[`git://github.com/Somebody/netsurf`](git://github.com/Somebody/netsurf)  
`git remote update somebody`  
`git merge --no-ff --no-commit somebody/foo`  
`git diff --cached`

Check that the diff shows what we want to merge. If so, commit it.

If you don't want to keep the remote around:

`git remote rm somebody`