1.0.12.1: more bogus FIXNUM declarations in ROOM
[sbcl.git] / doc / GIT-FOR-SBCL-HACKERS.txt
blobaedbd96f5b3751bf02a9ad9a10d300ca26d65be8
1 Git For SBCL Hackers
2 ====================
4 Git is structured as a ton of programs called git-foo, accessible
5 either directly, or as "git foo". Commands "git help" and "git help
6 foo" provide the documentation -- which is there also as the manual
7 pages.
9 Make sure you have Git 1.5.something.
11 When running on tty the commands pipe their output through less
12 automatically, so you don't need to mentally add "| less" anywhere.
14 Let's get started. First off, we need a gitified SBCL repository to
15 clone. At the time of writing there are two Git mirrors for the CVS
16 history:
18  git://sbcl.boinkor.net/sbcl.git
20 and
22  git://repo.or.cz/sbcl.git
24 but the latter is actually a mirror of the first one, so it doesn't
25 matter which one you use, really.
27 The command
29  git clone git://sbcl.boinkor.net/sbcl.git sbcl-git
31 clones the SBCL Git mirror into the directory sbcl-git (there's a
32 naming convention in play here, but ignore that for now.) The clone
33 contains full history, and is an independent repository on its own
34 right. Doing the clone takes as long as downloading 25Mb takes on your
35 line, but after that things are very fast.
37 To update your clone from the original source at a later date, use
38 git-pull. Go ahead and try out now, to see that it works, and see how
39 snazzy a no-op pull is.
41  git pull
43 The directory .git inside the clone contains Git's view of the
44 repository -- no other Git files or directories are in the tree. Just
45 for kicks:
47  cd sbcl-git
48  rm -rf *                # leaves .git alone
49  time git reset --hard   # this takes < 2 seconds, restores everything
51 So, two commands so far:
53  git-clone
54    One-time operation to clone a repository.
56  git-reset
57    Used to restore state: using the --hard flag resets the entire tree
58    to the state of the last commit but doesn't delete new files which
59    may be in the tree. (It doesn't actually "restore state", or rather
60    does it as a side, effect, but you can learn the details on your
61    own.)
63 Let's hack a bit.
65  git branch hack-a-bit   # creates a new branch called "hack-a-bit"
66  git branch              # shows all branches and tells which one is active
67  git checkout hack-a-bit # switches to the "hack-a-bit" branch
68  git branch              # shows that we're now on "hack-a-bit"
70 Once you get your bearings you can do the create-branch-and-checkout
71 in one step, which you will be doing a lot, since branches are really
72 nice in Git! The magic is: "git checkout -b hack-a-bit-more" -- but
73 leave that for another time.
75 Let's do something. Edit version.lisp-expr, and maybe give SBCL some
76 love.
78  git diff                # shows you the changes in your tree
79  git status              # shows you the state of files in the tree
81 git-status will tell you that some files have been modified, but it
82 has "no changes added to commit". If you tried git-commit right now,
83 nothing would happen. What's going on?
85 Git has a notion of a separate "staging area", from which commits are
86 made. You can add content to the it by using git-add:
88  git add version.lisp-expr
89  git status
90  git diff
92 Now git-status shows changes as part of a pending commit, but git-diff
93 is silent!
95 By default git-diff shows the differences between the working tree and
96 the staging area (which starts out identical to HEAD after a checkout).
98 Edit version.lisp-expr again. Now you have three versions of it
99 (ignoring all the historical versions for a second) to compare:
101  git diff               # between tree and staging area
102  git diff HEAD          # between tree and last commit
103  git diff --cached      # between staging area and last commit
105 If we were to do a git-commit now, it would commit the version in the
106 staging area, not the one in the tree.
108 We like our latest version, so do
110  git add version.lisp-expr
112 again. Now the latest version is in the staging area, and version that
113 used to be there is gone. You don't need to worry about the staging
114 area. Either you will find out that it's pretty neat (consider it a
115 temporary commit), or you can mostly ignore it. Do
117  git commit
119 now, and we'll move on in a second. Just to call spade a spade, the
120 staging area is really called "index".
122 Now, our changes are in the repository, and git-status should show a
123 clean tree. (By the way, can you imagine how long all the diffs and
124 statuses you've done during this tutorial would have taken with CVS?)
126 To get the differences between your current branch, and the master
127 branch, do
129  git diff master
131 To view the last commit on master, do
133  git diff master^..master
135 To view the commit logs, do
137  git log
139 You'll see long hex-string at the head of each commit. This is the
140 commit id, which is a SHA1 hash based on the content of the tree, so
141 you can share these with other hackers, and they can use the same
142 commit id to poke at their own repositories. Locally any unique prefix
143 of the hash is enough to identify a commit, so you don't need to use
144 the full hashes.
146 This is where the fun starts. Pick an interesting looking commit a
147 while back, copy the commit id, and do
149  git diff <<paste commit id here>>
151 Git will show you all the changes between the commit you selected and
152 current version as a single diff. Similarly,
154  git diff -w <<commit id 1>> <<commit id 2>>
156 can be used to compare two arbitrary versions. The -w switch tells Git
157 to ignore whitespace changes -- you can usually leave it out, but it's
158 nice when diffing across the great whitespacification patches.
160 Onwards: just so that we have a bit more history on the branch, edit
161 version.lisp-expr again, and git-commit again. You can use
163  git commit -a
165 to automatically add all the changed files to the staging area to
166 speed things up. Repeat. Now git-log should show a few local changes.
168 Let's see how merging works. To create a new branch based on master
169 and switch to it do
171  git checkout -b merge-experiment master
173 Merge the changes we did on the hack-a-bit branch.
175  git merge hack-a-bit
177 Bing-bada-bing! Done. Have a look at git-log. You see that we have
178 full branch history merged. If there had been conflicts, the merge
179 would not have been automatic, but you would have been called to
180 resolve conflicts, etc.
182 This is very nice for merging short-lived local branches, but not
183 always so good for merging things back onto master, or into "mainline"
184 history since you get all the commits that happened on the branch:
186   "first cut at x"
187   "first cut at y"
188   "oops, x was wrong"
189   "implemented z"
190   "aargh, x was still wrong"
191   ...
193 When merging a branch like this, with oopses in the history, it is far
194 better if we are able to merge it as a few logical patches -- the
195 resulting history will be easier to understand.
197 First option is to use --squash to squash all the commits into a
198 single one.
200  git checkout -b merge-experiment-2 master
201  git merge --squash hack-a-bit
203 This has the side-effect of not committing the changes immediately.
205 This is in effect similar to the usual way of merging back changes
206 from a CVS branch: if we're told that the patch came from a branch, we
207 can then go and look at the branch history, but we don't see the
208 evolution of the branch in the mainline history.
210 If the changeset is small, --squash is exactly what we want, but for
211 long-lived branches that are best merged in a few steps we can use
213  git merge --squash <<commit id>>
215 to merge the changes upto a certain commit. Repeat a few times, and
216 you have the whole branch merged. Other Git commands provide more
217 advanced options. See eg. git-cherry-pick, which you will end up
218 using sooner or later.
220 Now, let's assume we have a private Git repository in ~/sbcl-git, and
221 we want to publish it to the world. The easiest way is to fire up a
222 browser, and go to
224  http://repo.or.cz/w/sbcl.git
226 There, click on the "fork" link, and set up your own SBCL repository,
227 called sbcl/yourname. Select the "push" mode, and write something
228 along the lines of "My private SBCL tree. Pulls from main sbcl.git
229 repository, and trickles changes back to upstream CVS manually --
230 from where they end up in sbcl.git. Turtles, you see." in the comment
231 box. Then you will be directed to set up an account, which you will
232 then have to add as a "pusher" to your SBCL fork. 
234 Finally, add the following snippet (adjusting for your own name) in
235 ~/sbcl-git/.git/config
237  [remote "public"]
238         url = git+ssh://repo.or.cz/srv/git/sbcl/yourname.git
240 After that is done, you're ready to publish your tree.
242  git push --all public
244 Now anyone can get at your repository at
246  git://repo.or.cz/sbcl/yourname.git
248 and you can publish your own hacks on it via git-push.
250  git push public <<name of branch to update>>
252 Since we're not (yet?) officially using Git, we want to get our
253 changes back into the CVS. git-cvsexport is the perfect tool for this.
254 This assumes that you have a developer CVS checkout in ~/sbcl-cvs, and
255 wish to commit the changes you have wrought on branch foo-hacks
256 (compared to master):
258  git checkout -b foo-hacks-to-cvs master
259  git merge --squash foo-hacks
260  edit version.lisp-expr to be "CVS ready"
261  git commit -a               # edit the message to be "CVS ready"
262  cd ~/sbcl-cvs
263  GIT_DIR=~/sbcl-git/.git git cvsexportcommit -v foo-hacks-to-cvs
264  review, fix any problems
265  cvs commit -F .msg
267 To make things a bit easier, add eg. this stanza to ~/sbcl-git/.git/config:
269  [alias]
270     sbcl-export = ! cd ~/sbcl-cvs && GIT_DIR=~/sbcl-git/.git git-cvsexportcommit -v
272 Then you can just run
274  git sbcl-export foo-hacks-to-cvs
276 from inside ~/sbcl-git/, and have it prepare your CVS tree for commit.
278 git-cvsexportcommit is fairly conservative by default, and will fail
279 if the patch doens't apply cleanly. If that happens, you can fix the
280 issues manually:
282  .cvsexportcommit.diff   -- holds the patch
283  .msg                    -- holds the commit message
285 Finally, delete the foo-hacks-to-cvs branch after you've committed
286 code to CVS. Of course, instead of using git-cvexportcommit you can
287 also manually make and apply patches, etc. For hairier cases it may
288 even be easier in the end:
290   git format-patch -p master..foo-hacks
292 Generates a patch for each commit between master and the HEAD of
293 foo-hacks, naming them
295   0001-first-line-of-commit-message.patch
296   0002-and-so-and-so-forth.patch
297   ...
299 To get latest changes from the CVS Git mirror you originally cloned
300 from, do
302   git pull
304 on the branch you want to update on your private repository.
306 This completes our whirlwind tour. I'm not saying this makes you
307 proficient in using Git, but at least you should be up and walking.
308 Reading
310  http://eagain.net/articles/git-for-computer-scientists/
311  http://www.kernel.org/pub/software/scm/git/docs/everyday.html
312  http://www.kernel.org/pub/software/scm/git/docs/user-manual.html
314 and various Git manual pages is a good idea.
316 One command I can in particular recommend getting familiar with is
317 git-rebase. git-gui, git-citool, and gitk provide graphical interfaces
318 for working with Git -- particularly gitk is an invaluable tool for
319 visualizing history.