Project

General

Profile

Git » History » Version 9

Adam Sutton, 2013-02-27 11:03

1 1 Adam Sutton
h1. Git for TVH Dummies
2
3
As I get quite a few people asking me what the right way to work with git is, in particular in relation to submitting patches upstream, I thought it might be a good idea to write a quick wiki entry to help with some common tasks.
4
5
I'm also fairly new to git, I'd only touched it occasionally before getting involved in Tvheadend, but I've now been using it solidly for about a year. So while I'm by no means an expert, I'll at least point out some of the things I've learnt over that year.
6
7
h2. Github
8
9 3 Adam Sutton
Tvheadend hosts its primary repository on "github":https://github.com, this is a useful community site as not only does it provide basic git hosting but also some useful tools for managing the project. This includes the ability for users to create public forks, submit Pull Requests and to comment on commits and other things.
10 1 Adam Sutton
11
The main project page can be found at https://github.com/tvheadend/tvheadend.
12
13
If you don't intend to actively contribute to the development you can simply clone the repository for the purpose of [[Building]] and the rest of this article is probably not relevant. However should you later decide you do want to push stuff back upstream then there are some useful hints below.
14
15
h2. Forking
16
17
The first thing you should do if you intend to actively develop and push features/fixes upstream is to create a public fork on "github":https://github.com (you can use other services, but it won't fit as well with the general project workflow and the [[Team]] may get grumpy!).
18
19 2 Adam Sutton
To create the fork simply click on the fork icon: !fork.png!
20
21
This will create a new personal fork on github, which will allow you to publish your own changes etc.
22
23
You will also need to add an SSH key to your account to be able to push changes to your fork. If you're unsure how to do this please visit the "github ssh help page":https://help.github.com/articles/generating-ssh-keys.
24
25
Once that is all done you should create a clone of your repository using the SSH access URL (this will give you push access):
26
27
!clone.png!
28
29
<pre>
30
git clone [email protected]:USERNAME/tvheadend.git
31
</pre>
32
33 9 Adam Sutton
h3. Syncing with upstream
34
35
If you want to keep up to date with upstream changes (in the main repository) then you should add a remote (typically called upstream):
36
37
<pre>
38
git remote add upstream git://github.com/tvheadend/tvheadend.git
39
</pre>
40
41
To pull the latest state of that repository:
42
<pre>
43
git fetch upstream
44
</pre>
45
46
And to merge changes into your local branch:
47
<pre>
48
git merge upstream/BRANCH
49
</pre>
50
51 2 Adam Sutton
h3. Fixing upstream clone
52
53
If you have already cloned the upstream (tvheadend/tvheadend.git) repository and now want to create you're own github fork, while still retaining your local repository (possibly with commits you've already made). First create the github fork as above, and instead of cloning that repository do the following within your existing local repository:
54
55
<pre>
56
git remote rename origin upstream
57
git remote add origin SSH_URL
58
git fetch origin
59 1 Adam Sutton
git branch --set-upstream master origin/master
60 3 Adam Sutton
</pre>
61
62
h2. Branches
63
64
It is highly recommended that when you're looking to make changes, especially those you eventually want to submit upstream, that you create a branch.
65
66
There are several ways to create branches within git, but the two most common that I use are:
67
68
<pre>
69
git branch BRANCHNAME
70
</pre>
71
72
and
73
74
<pre>
75
git checkout -b BRANCHNAME
76
</pre>
77
78
This will both create a new branch (called BRANCHNAME) from the currently HEAD. The only difference is the second command will also switch you to the newly created branch.
79
80
If at any time you want to checkout another (existing) branch, do the following:
81
82
<pre>
83
git checkout BRANCHNAME
84
</pre>
85
86
Finally should you want to create a local branch from an existing branch on another fork (such as the upstream tvheadend fork), you can do the following:
87
88
<pre>
89
git checkout -t REMOTENAME/BRANCHNAME
90
</pre>
91
92
This will create a new local branch, with the same name as the remote branch, set it up to track (this means git will among other things tell you the status of your branch relative to the tracked version) and switch to the new branch.
93
94
To publish this branch to your public repository, as always with git there are a number of different ways of doing this. However for simplicity I usually do the following:
95
96
<pre>
97 1 Adam Sutton
</pre>
98 6 Adam Sutton
git push -u origin HEAD
99 3 Adam Sutton
100
This will publish a new branch to your public repository, using the same name as the local branch. It will also set the local branch to track the remote one.
101
102
If you need to send subsequent updates, you can simply do the following:
103
104
<pre>
105 6 Adam Sutton
git push origin HEAD
106 3 Adam Sutton
</pre>
107
108
Note: Both of the above commands assume that you've already checked out the branch you want to publish.
109
110
h2. Pull Requests
111
112
Eventually you've hopefully created some wonderful new feature or fixed some horrendous bug and you want to share that with the rest of the project. The way this is done is by creating a Pull Request (PR for short).
113
114
A PR is basically a way of saying "hey I've got this cool code, please include it upstream". The development team (or whoever you submit the PR to) can then review your commit, will possibly make comments and ask for changes. And hopefully, if the change is a good one, it will eventually be pulled into the upstream fork and the rest of the world will benefit.
115
116
To begin the PR process, you should hopefully already have a branch that you intend to submit. If not create one now, it'll save you hassle later. The reason being that when you submit a PR you're basically saying pull from this branch, so any commits you add to that branch will automatically be added to the PR. And then make sure this has been published to your public fork.
117
118
If you visit your github project page, you should now see something like this:
119
120
!newbranch.png!
121
122
Click the "Pull Request" button, fill in the form and hit "Send Pull Request". And that's it, code submitted and ready for review.
123
124
h3. Rebasing
125
126
One thing that you should really think about doing before submitting a PR is to clean up the branch, if you don't you'll mostly likely be asked to when you do submit it.
127
128
The bare minimum you should look to do is rebase your commits on top of the current upstream master. This ensures that the code will cleanly merge and that no conflicts exist. It will also make the commit history cleaner and easier to review.
129
130
To do the rebasing, run the following command:
131
132
<pre>
133
git rebase upstream/master
134
</pre>
135
136
You could also squash some commits, this can be especially useful if the branch is littered with lots of commits as you to and fro your way to a solution (mine certainly are usually like that!). The way I usually do this is to use the interactive rebase tool:
137
138
<pre>
139
git rebase -i upstream/master
140
</pre>
141
142
This will present you with a list of your commits, something like:
143
144
<pre>
145
pick 46f2170 update readme date
146
147
# Rebase 2e25766..46f2170 onto 2e25766
148
# Some helpful info...
149
</pre>
150
151
From here you can reorder commits, by simply moving the lines around, squash commits (change pick to fixup or f), remove commits completely (delete the line) or simply change the commit message (change pick to reword or r). Save the file and git will start to apply the changes.
152
153
If the process encounters problems, such as conflicts, then you will need to intervene. The conflicting files will need to be edited to resolve the conflicts, then added back into the commit and finally the rebase continued:
154
155
<pre>
156
edit FILE(s) - manually resolve conflicts
157
git add FILE(s)
158
git rebase --continue
159
</pre>
160
161
How you go about resolving conflicts is down to you.
162
163
It's also worth noting that when you rebase things you're changing history and this may cause problems when trying to push to a remote (if the commits you've modified were already upstream). To resolve this you may be forced to forcefully push the updates, using:
164
165
<pre>
166 6 Adam Sutton
git push -f origin HEAD
167 3 Adam Sutton
</pre>
168
169
h3. Changes
170
171
Should you want to make changes, or be asked by the upstream [[Team]], then you will need to first make these in the local copy of the branch used for the PR. You then simply publish those changes upstream:
172
173
<pre>
174
git push
175 2 Adam Sutton
</pre>
176 4 Adam Sutton
177
h2. Remote's
178
179
Remote's were briefly mentioned in the earlier sections without really making it clear what they are. In essence, a remote is simply another git repository/fork that is not the local one. Because of the distributed nature of git, you can easily interact with numerous forks at the same time. Pulling change from one and pushing to another etc.
180
181
Normally when working with github (and other hosted solutions) you will normally have 1 or 2 remotes by default:
182
183
<pre>
184
origin - This is the hosted/public copy that your local fork is notionally attached to.
185
upstream - This is typically the hosted/public copy of the parent of origin.
186
</pre>
187
188
There is nothing particularly special about the names origin and upstream, they are simply convention. But I'd recommend sticking with that convention.
189
190
You can also add any other repository you like to your list of remotes and that will give you the ability to pull and push (depending on your access) to those repositories. For example I've currently got this horrible mess of remotes:
191
192
<pre>
193
adamsutton	[email protected]:adamsutton/tvheadend.git (fetch)
194
adamsutton	[email protected]:adamsutton/tvheadend.git (push)
195
andyb2000	git://github.com/andyb2000/tvheadend.git (fetch)
196
andyb2000	git://github.com/andyb2000/tvheadend.git (push)
197
bombadil	aps@home:Workspace/xbmc/tvheadend/tvheadend (fetch)
198
bombadil	aps@home:Workspace/xbmc/tvheadend/tvheadend (push)
199
btbn	        git://github.com/BtbN/tvheadend.git (fetch)
200
btbn	        git://github.com/BtbN/tvheadend.git (push)
201
krka	        git://github.com/krka/tvheadend.git (fetch)
202
krka	        git://github.com/krka/tvheadend.git (push)
203
manio	        git://github.com/manio/tvheadend.git (fetch)
204
manio	        git://github.com/manio/tvheadend.git (push)
205
origin	        [email protected]:tvheadend/tvheadend.git (fetch)
206
origin	        [email protected]:tvheadend/tvheadend.git (push)
207
tornblom	https://github.com/john-tornblom/tvheadend.git (fetch)
208
tornblom	https://github.com/john-tornblom/tvheadend.git (push)
209
</pre>
210
211
It includes my own github fork, the fork on my TVH server (bombadil) and several user repositories I've interacted with recently. Its worth noting that I have no upstream. This is because this is my fork of the tvheadend/tvheadend.git repository, which as the root of all the forks does not itself have a parent.
212
213
To add a new remote simply do the following:
214
215
<pre>
216
git remote add REMOTENAME REMOTEURL
217
</pre>
218
219
You can then sync you local copy of that repository (yes you have all the info for each repository stored locally, though due to the way git is built most of it will already exist on your disk and not require lots of extra space):
220
221
<pre>
222
git fetch REMOTENAME
223
</pre>
224
225
If you want to checkout a remote branch, maybe to have a quick play, you can simply do:
226
227
<pre>
228
git checkout REMOTENAME/BRANCHNAME
229
</pre>
230
231
This will created what is known as a "detached HEAD", it means that its not part of a branch and so you shouldn't make commits (as they'll be lost when you switch to another branch). If you want to create a new branch from the detached state, you can simply do:
232
233
<pre>
234
git checkout -b BRANCHNAME
235
</pre>
236 5 Adam Sutton
237
h2. Tips and Tricks
238
239 7 Adam Sutton
Just a random collection of git commands that might help with using git, finding info, etc...
240
241
h3. Log output
242
243
<pre>
244
git log --oneline --decorate
245
</pre>
246
247 8 Adam Sutton
I alias this as _*gl*_ as it provide a very nice compact git log output.
248 7 Adam Sutton
249
<pre>
250
git shortlog -nse
251
</pre>
252
253
Useful to find out who has contributed to TVH (some of this can be seen on github).