]> git.ipfire.org Git - thirdparty/git.git/blame - Documentation/howto/using-topic-branches.txt
mailsplit: allow empty input from stdin
[thirdparty/git.git] / Documentation / howto / using-topic-branches.txt
CommitLineData
a2f15a81
JH
1Date: Mon, 15 Aug 2005 12:17:41 -0700
2From: tony.luck@intel.com
3Subject: Some tutorial text (was git/cogito workshop/bof at linuxconf au?)
f358c10f
JH
4Abstract: In this article, Tony Luck discusses how he uses GIT
5 as a Linux subsystem maintainer.
a2f15a81
JH
6
7Here's something that I've been putting together on how I'm using
8GIT as a Linux subsystem maintainer.
9
a2f15a81
JH
10-Tony
11
f37d0cc3 12Last updated w.r.t. GIT 0.99.9f
23e86730 13
a2f15a81
JH
14Linux subsystem maintenance using GIT
15-------------------------------------
16
17My requirements here are to be able to create two public trees:
18
191) A "test" tree into which patches are initially placed so that they
20can get some exposure when integrated with other ongoing development.
21This tree is available to Andrew for pulling into -mm whenever he wants.
22
232) A "release" tree into which tested patches are moved for final
24sanity checking, and as a vehicle to send them upstream to Linus
25(by sending him a "please pull" request.)
26
27Note that the period of time that each patch spends in the "test" tree
28is dependent on the complexity of the change. Since GIT does not support
29cherry picking, it is not practical to simply apply all patches to the
30test tree and then pull to the release tree as that would leave trivial
31patches blocked in the test tree waiting for complex changes to accumulate
32enough test time to graduate.
33
a4adf54d 34Back in the BitKeeper days I achieved this by creating small forests of
a2f15a81
JH
35temporary trees, one tree for each logical grouping of patches, and then
36pulling changes from these trees first to the test tree, and then to the
37release tree. At first I replicated this in GIT, but then I realised
38that I could so this far more efficiently using branches inside a single
39GIT repository.
40
41So here is the step-by-step guide how this all works for me.
42
43First create your work tree by cloning Linus's public tree:
44
3af849a3 45 $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work
a2f15a81
JH
46
47Change directory into the cloned tree you just created
48
49 $ cd work
50
23e86730
TL
51Set up a remotes file so that you can fetch the latest from Linus' master
52branch into a local branch named "linus":
53
54 $ cat > .git/remotes/linus
3af849a3 55 URL: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
23e86730
TL
56 Pull: master:linus
57 ^D
a2f15a81 58
23e86730
TL
59and create the linus branch:
60
61 $ git branch linus
a2f15a81
JH
62
63The "linus" branch will be used to track the upstream kernel. To update it,
64you simply run:
65
23e86730
TL
66 $ git fetch linus
67
68you can do this frequently (and it should be safe to do so with pending
69work in your tree, but perhaps not if you are in mid-merge).
a2f15a81 70
23e86730
TL
71If you need to keep track of other public trees, you can add remote branches
72for them too:
a2f15a81 73
23e86730
TL
74 $ git branch another
75 $ cat > .git/remotes/another
76 URL: ... insert URL here ...
77 Pull: name-of-branch-in-this-remote-tree:another
78 ^D
a2f15a81 79
23e86730
TL
80and run:
81
82 $ git fetch another
a2f15a81
JH
83
84Now create the branches in which you are going to work, these start
85out at the current tip of the linus branch.
86
accd952f
TL
87 $ git branch test linus
88 $ git branch release linus
a2f15a81
JH
89
90These can be easily kept up to date by merging from the "linus" branch:
91
f37d0cc3
TL
92 $ git checkout test && git merge "Auto-update from upstream" test linus
93 $ git checkout release && git merge "Auto-update from upstream" release linus
a2f15a81 94
23e86730
TL
95Set up so that you can push upstream to your public tree (you need to
96log-in to the remote system and create an empty tree there before the
97first push).
a2f15a81 98
23e86730
TL
99 $ cat > .git/remotes/mytree
100 URL: master.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
101 Push: release
102 Push: test
103 ^D
a2f15a81 104
23e86730 105and the push both the test and release trees using:
a2f15a81 106
23e86730
TL
107 $ git push mytree
108
109or push just one of the test and release branches using:
110
111 $ git push mytree test
112or
113 $ git push mytree release
a2f15a81
JH
114
115Now to apply some patches from the community. Think of a short
116snappy name for a branch to hold this patch (or related group of
117patches), and create a new branch from the current tip of the
118linus branch:
119
120 $ git checkout -b speed-up-spinlocks linus
121
122Now you apply the patch(es), run some tests, and commit the change(s). If
123the patch is a multi-part series, then you should apply each as a separate
124commit to this branch.
125
126 $ ... patch ... test ... commit [ ... patch ... test ... commit ]*
127
128When you are happy with the state of this change, you can pull it into the
129"test" branch in preparation to make it public:
130
f37d0cc3 131 $ git checkout test && git merge "Pull speed-up-spinlock changes" test speed-up-spinlocks
a2f15a81
JH
132
133It is unlikely that you would have any conflicts here ... but you might if you
134spent a while on this step and had also pulled new versions from upstream.
135
136Some time later when enough time has passed and testing done, you can pull the
137same branch into the "release" tree ready to go upstream. This is where you
138see the value of keeping each patch (or patch series) in its own branch. It
139means that the patches can be moved into the "release" tree in any order.
140
f37d0cc3 141 $ git checkout release && git merge "Pull speed-up-spinlock changes" release speed-up-spinlocks
a2f15a81
JH
142
143After a while, you will have a number of branches, and despite the
144well chosen names you picked for each of them, you may forget what
145they are for, or what status they are in. To get a reminder of what
146changes are in a specific branch, use:
147
148 $ git-whatchanged branchname ^linus | git-shortlog
149
150To see whether it has already been merged into the test or release branches
151use:
152
153 $ git-rev-list branchname ^test
154or
155 $ git-rev-list branchname ^release
156
157[If this branch has not yet been merged you will see a set of SHA1 values
158for the commits, if it has been merged, then there will be no output]
159
160Once a patch completes the great cycle (moving from test to release, then
161pulled by Linus, and finally coming back into your local "linus" branch)
162the branch for this change is no longer needed. You detect this when the
163output from:
164
165 $ git-rev-list branchname ^linus
166
167is empty. At this point the branch can be deleted:
168
e66ab03f 169 $ git branch -d branchname
a2f15a81 170
accd952f
TL
171Some changes are so trivial that it is not necessary to create a separate
172branch and then merge into each of the test and release branches. For
173these changes, just apply directly to the "release" branch, and then
174merge that into the "test" branch.
175
a2f15a81
JH
176To create diffstat and shortlog summaries of changes to include in a "please
177pull" request to Linus you can use:
178
179 $ git-whatchanged -p release ^linus | diffstat -p1
180and
181 $ git-whatchanged release ^linus | git-shortlog
182
accd952f
TL
183
184Here are some of the scripts that I use to simplify all this even further.
185
186==== update script ====
187# Update a branch in my GIT tree. If the branch to be updated
188# is "linus", then pull from kernel.org. Otherwise merge local
189# linus branch into test|release branch
190
191case "$1" in
192test|release)
f37d0cc3 193 git checkout $1 && git merge "Auto-update from upstream" $1 linus
accd952f
TL
194 ;;
195linus)
23e86730
TL
196 before=$(cat .git/refs/heads/linus)
197 git fetch linus
198 after=$(cat .git/refs/heads/linus)
accd952f
TL
199 if [ $before != $after ]
200 then
201 git-whatchanged $after ^$before | git-shortlog
202 fi
203 ;;
204*)
205 echo "Usage: $0 linus|test|release" 1>&2
206 exit 1
207 ;;
208esac
209
210==== merge script ====
211# Merge a branch into either the test or release branch
212
213pname=$0
214
215usage()
216{
217 echo "Usage: $pname branch test|release" 1>&2
218 exit 1
219}
220
221if [ ! -f .git/refs/heads/"$1" ]
222then
223 echo "Can't see branch <$1>" 1>&2
224 usage
225fi
226
227case "$2" in
228test|release)
229 if [ $(git-rev-list $1 ^$2 | wc -c) -eq 0 ]
230 then
231 echo $1 already merged into $2 1>&2
232 exit 1
233 fi
f37d0cc3 234 git checkout $2 && git merge "Pull $1 into $2 branch" $2 $1
accd952f
TL
235 ;;
236*)
237 usage
238 ;;
239esac
240
241==== status script ====
242# report on status of my ia64 GIT tree
243
244gb=$(tput setab 2)
245rb=$(tput setab 1)
246restore=$(tput setab 9)
247
9dcc829f 248if [ `git-rev-list release ^test | wc -c` -gt 0 ]
accd952f
TL
249then
250 echo $rb Warning: commits in release that are not in test $restore
251 git-whatchanged release ^test
252fi
253
254for branch in `ls .git/refs/heads`
255do
256 if [ $branch = linus -o $branch = test -o $branch = release ]
257 then
258 continue
259 fi
260
261 echo -n $gb ======= $branch ====== $restore " "
262 status=
263 for ref in test release linus
264 do
9dcc829f 265 if [ `git-rev-list $branch ^$ref | wc -c` -gt 0 ]
accd952f
TL
266 then
267 status=$status${ref:0:1}
268 fi
269 done
270 case $status in
271 trl)
272 echo $rb Need to pull into test $restore
273 ;;
274 rl)
275 echo "In test"
276 ;;
277 l)
278 echo "Waiting for linus"
279 ;;
280 "")
281 echo $rb All done $restore
282 ;;
283 *)
284 echo $rb "<$status>" $restore
285 ;;
286 esac
287 git-whatchanged $branch ^linus | git-shortlog
288done