1A short git tutorial 2==================== 3May 2005 4 5 6Introduction 7------------ 8 9This is trying to be a short tutorial on setting up and using a git 10archive, mainly because being hands-on and using explicit examples is 11often the best way of explaining what is going on. 12 13In normal life, most people wouldn't use the "core" git programs 14directly, but rather script around them to make them more palatable. 15Understanding the core git stuff may help some people get those scripts 16done, though, and it may also be instructive in helping people 17understand what it is that the higher-level helper scripts are actually 18doing. 19 20The core git is often called "plumbing", with the prettier user 21interfaces on top of it called "porcelain". You may want to know what 22the plumbing does for when the porcelain isn't flushing... 23 24 25Creating a git archive 26---------------------- 27 28Creating a new git archive couldn't be easier: all git archives start 29out empty, and the only thing you need to do is find yourself a 30subdirectory that you want to use as a working tree - either an empty 31one for a totally new project, or an existing working tree that you want 32to import into git. 33 34For our first example, we're going to start a totally new archive from 35scratch, with no pre-existing files, and we'll call it "git-tutorial". 36To start up, create a subdirectory for it, change into that 37subdirectory, and initialize the git infrastructure with "git-init-db": 38 39 mkdir git-tutorial 40 cd git-tutorial 41 git-init-db 42 43to which git will reply 44 45 defaulting to local storage area 46 47which is just git's way of saying that you haven't been doing anything 48strange, and that it will have created a local .git directory setup for 49your new project. You will now have a ".git" directory, and you can 50inspect that with "ls". For your new empty project, ls should show you 51three entries: 52 53 - a symlink called HEAD, pointing to "refs/heads/master" 54 55 Don't worry about the fact that the file that the HEAD link points to 56 doesn't even exist yet - you haven't created the commit that will 57 start your HEAD development branch yet. 58 59 - a subdirectory called "objects", which will contain all the git SHA1 60 objects of your project. You should never have any real reason to 61 look at the objects directly, but you might want to know that these 62 objects are what contains all the real _data_ in your repository. 63 64 - a subdirectory called "refs", which contains references to objects. 65 66 In particular, the "refs" subdirectory will contain two other 67 subdirectories, named "heads" and "tags" respectively. They do 68 exactly what their names imply: they contain references to any number 69 of different "heads" of development (aka "branches"), and to any 70 "tags" that you have created to name specific versions of your 71 repository. 72 73 One note: the special "master" head is the default branch, which is 74 why the .git/HEAD file was created as a symlink to it even if it 75 doesn't yet exist. Basically, the HEAD link is supposed to always 76 point to the branch you are working on right now, and you always 77 start out expecting to work on the "master" branch. 78 79 However, this is only a convention, and you can name your branches 80 anything you want, and don't have to ever even _have_ a "master" 81 branch. A number of the git tools will assume that .git/HEAD is 82 valid, though. 83 84 [ Implementation note: an "object" is identified by its 160-bit SHA1 85 hash, aka "name", and a reference to an object is always the 40-byte 86 hex representation of that SHA1 name. The files in the "refs" 87 subdirectory are expected to contain these hex references (usually 88 with a final '\n' at the end), and you should thus expect to see a 89 number of 41-byte files containing these references in this refs 90 subdirectories when you actually start populating your tree ] 91 92You have now created your first git archive. Of course, since it's 93empty, that's not very useful, so let's start populating it with data. 94 95 96 Populating a git archive 97 ------------------------ 98 99We'll keep this simple and stupid, so we'll start off with populating a 100few trivial files just to get a feel for it. 101 102Start off with just creating any random files that you want to maintain 103in your git archive. We'll start off with a few bad examples, just to 104get a feel for how this works: 105 106 echo "Hello World" > a 107 echo "Silly example" > b 108 109you have now created two files in your working directory, but to 110actually check in your hard work, you will have to go through two steps: 111 112 - fill in the "cache" aka "index" file with the information about your 113 working directory state 114 115 - commit that index file as an object. 116 117The first step is trivial: when you want to tell git about any changes 118to your working directory, you use the "git-update-cache" program. That 119program normally just takes a list of filenames you want to update, but 120to avoid trivial mistakes, it refuses to add new entries to the cache 121(or remove existing ones) unless you explicitly tell it that you're 122adding a new entry with the "--add" flag (or removing an entry with the 123"--remove") flag. 124 125So to populate the index with the two files you just created, you can do 126 127 git-update-cache --add a b 128 129and you have now told git to track those two files. 130 131In fact, as you did that, if you now look into your object directory, 132you'll notice that git will have added two new objects to the object 133store. If you did exactly the steps above, you should now be able to do 134 135 ls .git/objects/??/* 136 137and see two files: 138 139 .git/objects/55/7db03de997c86a4a028e1ebd3a1ceb225be238 140 .git/objects/f2/4c74a2e500f5ee1332c86b94199f52b1d1d962 141 142which correspond with the object with SHA1 names of 557db... and f24c7.. 143respectively. 144 145If you want to, you can use "git-cat-file" to look at those objects, but 146you'll have to use the object name, not the filename of the object: 147 148 git-cat-file -t 557db03de997c86a4a028e1ebd3a1ceb225be238 149 150where the "-t" tells git-cat-file to tell you what the "type" of the 151object is. Git will tell you that you have a "blob" object (ie just a 152regular file), and you can see the contents with 153 154 git-cat-file "blob" 557db03de997c86a4a028e1ebd3a1ceb225be238 155 156which will print out "Hello World". The object 557db... is nothing 157more than the contents of your file "a". 158 159[ Digression: don't confuse that object with the file "a" itself. The 160object is literally just those specific _contents_ of the file, and 161however much you later change the contents in file "a", the object we 162just looked at will never change. Objects are immutable. ] 163 164Anyway, as we mentioned previously, you normally never actually take a 165look at the objects themselves, and typing long 40-character hex SHA1 166names is not something you'd normally want to do. The above digression 167was just to show that "git-update-cache" did something magical, and 168actually saved away the contents of your files into the git content 169store. 170 171Updating the cache did something else too: it created a ".git/index" 172file. This is the index that describes your current working tree, and 173something you should be very aware of. Again, you normally never worry 174about the index file itself, but you should be aware of the fact that 175you have not actually really "checked in" your files into git so far, 176you've only _told_ git about them. 177 178However, since git knows about them, you can how start using some of the 179most basic git commands to manipulate the files or look at their status. 180 181In particular, let's not even check in the two files into git yet, we'll 182start off by adding another line to "a" first: 183 184 echo "It's a new day for git" >> a 185 186and you can now, since you told git about the previous state of "a", ask 187git what has changed in the tree compared to your old index, using the 188"git-diff-files" command: 189 190 git-diff-files 191 192oops. That wasn't very readable. It just spit out its own internal 193version of a "diff", but that internal version really just tells you 194that it has noticed that "a" has been modified, and that the old object 195contents it had have been replaced with something else. 196 197To make it readable, we can tell git-diff-files to output the 198differences as a patch, using the "-p" flag: 199 200 git-diff-files -p 201 202which will spit out 203 204 diff --git a/a b/a 205 --- a/a 206 +++ b/a 207 @@ -1 +1,2 @@ 208 Hello World 209 +It's a new day for git 210 211ie the diff of the change we caused by adding another line to "a". 212 213In other words, git-diff-files always shows us the difference between 214what is recorded in the index, and what is currently in the working 215tree. That's very useful. 216 217 218 Committing git state 219 -------------------- 220 221Now, we want to go to the next stage in git, which is to take the files 222that git knows about in the index, and commit them as a real tree. We do 223that in two phases: creating a "tree" object, and committing that "tree" 224object as a "commit" object together with an explanation of what the 225tree was all about, along with information of how we came to that state. 226 227Creating a tree object is trivial, and is done with "git-write-tree". 228There are no options or other input: git-write-tree will take the 229current index state, and write an object that describes that whole 230index. In other words, we're now tying together all the different 231filenames with their contents (and their permissions), and we're 232creating the equivalent of a git "directory" object: 233 234 git-write-tree 235 236and this will just output the name of the resulting tree, in this case 237(if you have does exactly as I've described) it should be 238 239 3ede4ed7e895432c0a247f09d71a76db53bd0fa4 240 241which is another incomprehensible object name. Again, if you want to, 242you can use "git-cat-file -t 3ede4.." to see that this time the object 243is not a "blob" object, but a "tree" object (you can also use 244git-cat-file to actually output the raw object contents, but you'll see 245mainly a binary mess, so that's less interesting). 246 247However - normally you'd never use "git-write-tree" on its own, because 248normally you always commit a tree into a commit object using the 249"git-commit-tree" command. In fact, it's easier to not actually use 250git-write-tree on its own at all, but to just pass its result in as an 251argument to "git-commit-tree". 252 253"git-commit-tree" normally takes several arguments - it wants to know 254what the _parent_ of a commit was, but since this is the first commit 255ever in this new archive, and it has no parents, we only need to pass in 256the tree ID. However, git-commit-tree also wants to get a commit message 257on its standard input, and it will write out the resulting ID for the 258commit to its standard output. 259 260And this is where we start using the .git/HEAD file. The HEAD file is 261supposed to contain the reference to the top-of-tree, and since that's 262exactly what git-commit-tree spits out, we can do this all with a simple 263shell pipeline: 264 265 echo "Initial commit" | git-commit-tree $(git-write-tree) > .git/HEAD 266 267which will say: 268 269 Committing initial tree 3ede4ed7e895432c0a247f09d71a76db53bd0fa4 270 271just to warn you about the fact that it created a totally new commit 272that is not related to anything else. Normally you do this only _once_ 273for a project ever, and all later commits will be parented on top of an 274earlier commit, and you'll never see this "Committing initial tree" 275message ever again. 276 277 278 Making a change 279 --------------- 280 281Remember how we did the "git-update-cache" on file "a" and then we 282changed "a" afterward, and could compare the new state of "a" with the 283state we saved in the index file? 284 285Further, remember how I said that "git-write-tree" writes the contents 286of the _index_ file to the tree, and thus what we just committed was in 287fact the _original_ contents of the file "a", not the new ones. We did 288that on purpose, to show the difference between the index state, and the 289state in the working directory, and how they don't have to match, even 290when we commit things. 291 292As before, if we do "git-diff-files -p" in our git-tutorial project, 293we'll still see the same difference we saw last time: the index file 294hasn't changed by the act of committing anything. However, now that we 295have committed something, we can also learn to use a new command: 296"git-diff-cache". 297 298Unlike "git-diff-files", which showed the difference between the index 299file and the working directory, "git-diff-cache" shows the differences 300between a committed _tree_ and the index file. In other words, 301git-diff-cache wants a tree to be diffed against, and before we did the 302commit, we couldn't do that, because we didn't have anything to diff 303against. 304 305But now we can do 306 307 git-diff-cache -p HEAD 308 309(where "-p" has the same meaning as it did in git-diff-files), and it 310will show us the same difference, but for a totally different reason. 311Now we're not comparing against the index file, we're comparing against 312the tree we just wrote. It just so happens that those two are obviously 313the same. 314 315"git-diff-cache" also has a specific flag "--cached", which is used to 316tell it to show the differences purely with the index file, and ignore 317the current working directory state entirely. Since we just wrote the 318index file to HEAD, doing "git-diff-cache --cached -p HEAD" should thus 319return an empty set of differences, and that's exactly what it does. 320 321However, our next step is to commit the _change_ we did, and again, to 322understand what's going on, keep in mind the difference between "working 323directory contents", "index file" and "committed tree". We have changes 324in the working directory that we want to commit, and we always have to 325work through the index file, so the first thing we need to do is to 326update the index cache: 327 328 git-update-cache a 329 330(note how we didn't need the "--add" flag this time, since git knew 331about the file already). 332 333Note what happens to the different git-diff-xxx versions here. After 334we've updated "a" in the index, "git-diff-files -p" now shows no 335differences, but "git-diff-cache -p HEAD" still _does_ show that the 336current state is different from the state we committed. In fact, now 337"git-diff-cache" shows the same difference whether we use the "--cached" 338flag or not, since now the index is coherent with the working directory. 339 340Now, since we've updated "a" in the index, we can commit the new 341version. We could do it by writing the tree by hand, and committing the 342tree (this time we'd have to use the "-p HEAD" flag to tell commit that 343the HEAD was the _parent_ of the new commit, and that this wasn't an 344initial commit any more), but the fact is, git has a simple helper 345script for doing all of the non-initial commits that does all of this 346for you, and starts up an editor to let you write your commit message 347yourself, so let's just use that: 348 349 git-commit-script 350 351Write whatever message you want, and all the lines that start with '#' 352will be pruned out, and the rest will be used as the commit message for 353the change. If you decide you don't want to commit anything after all at 354this point (you can continue to edit things and update the cache), you 355can just leave an empty message. Otherwise git-commit-script will commit 356the change for you. 357 358(Btw, current versions of git will consider the change in question to be 359so big that it's considered a whole new file, since the diff is actually 360bigger than the file. So the helpful comments that git-commit-script 361tells you for this example will say that you deleted and re-created the 362file "a". For a less contrived example, these things are usually more 363obvious). 364 365You've now made your first real git commit. And if you're interested in 366looking at what git-commit-script really does, feel free to investigate: 367it's a few very simple shell scripts to generate the helpful (?) commit 368message headers, and a few one-liners that actually do the commit itself. 369 370 371 Checking it out 372 --------------- 373 374While creating changes is useful, it's even more useful if you can tell 375later what changed. The most useful command for this is another of the 376"diff" family, namely "git-diff-tree". 377 378git-diff-tree can be given two arbitrary trees, and it will tell you the 379differences between them. Perhaps even more commonly, though, you can 380give it just a single commit object, and it will figure out the parent 381of that commit itself, and show the difference directly. Thus, to get 382the same diff that we've already seen several times, we can now do 383 384 git-diff-tree -p HEAD 385 386(again, "-p" means to show the difference as a human-readable patch), 387and it will show what the last commit (in HEAD) actually changed. 388 389More interestingly, you can also give git-diff-tree the "-v" flag, which 390tells it to also show the commit message and author and date of the 391commit, and you can tell it to show a whole series of diffs. 392Alternatively, you can tell it to be "silent", and not show the diffs at 393all, but just show the actual commit message. 394 395In fact, together with the "git-rev-list" program (which generates a 396list of revisions), git-diff-tree ends up being a veritable fount of 397changes. A trivial (but very useful) script called "git-whatchanged" is 398included with git which does exactly this, and shows a log of recent 399activity. 400 401To see the whole history of our pitiful little git-tutorial project, we 402can do 403 404 git-whatchanged -p --root 405 406(the "--root" flag is a flag to git-diff-tree to tell it to show the 407initial aka "root" commit as a diff too), and you will see exactly what 408has changed in the repository over its short history. 409 410With that, you should now be having some inkling of what git does, and 411can explore on your own. 412 413[ to be continued.. cvs2git, tagging versions, branches, merging.. ]