Documentation / tutorial.txton commit Add "git" and "git-log-script" helper scripts. (e764b8e)
   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.. ]