------------------------------------------------
and you can now, since you told Git about the previous state of `hello`, ask
Git what has changed in the tree compared to your old index, using the
'git diff-files' command:
------------
$ git diff-files
------------
Oops. That wasn't very readable. It just spit out its own internal
version of a 'diff', but that internal version really just tells you
that it has noticed that "hello" has been modified, and that the old object
contents it had have been replaced with something else.
To make it readable, we can tell 'git diff-files' to output the
differences as a patch, using the `-p` flag:
------------
$ git diff-files -p
diff --git a/hello b/hello
index 557db03..263414f 100644
--- a/hello
+++ b/hello
@@ -1 +1,2 @@
Hello World
+It's a new day for git
------------
i.e. the diff of the change we caused by adding another line to `hello`.
In other words, 'git diff-files' always shows us the difference between
what is recorded in the index, and what is currently in the working
tree. That's very useful.
A common shorthand for `git diff-files -p` is to just write `git
diff`, which will do the same thing.
------------
$ git diff
diff --git a/hello b/hello
index 557db03..263414f 100644
--- a/hello
+++ b/hello
@@ -1 +1,2 @@
Hello World
+It's a new day for git
------------
Committing Git state
--------------------
Now, we want to go to the next stage in Git, which is to take the files
that Git knows about in the index, and commit them as a real tree. We do
that in two phases: creating a 'tree' object, and committing that 'tree'
object as a 'commit' object together with an explanation of what the
tree was all about, along with information of how we came to that state.
Creating a tree object is trivial, and is done with 'git write-tree'.
There are no options or other input: `git write-tree` will take the
current index state, and write an object that describes that whole
index. In other words, we're now tying together all the different
filenames with their contents (and their permissions), and we're
creating the equivalent of a Git "directory" object:
------------------------------------------------
$ git write-tree
------------------------------------------------
and this will just output the name of the resulting tree, in this case
(if you have done exactly as I've described) it should be
----------------
8988da15d077d4829fc51d8544c097def6644dbb
----------------
which is another incomprehensible object name. Again, if you want to,
you can use `git cat-file -t 8988d...` to see that this time the object
is not a "blob" object, but a "tree" object (you can also use
`git cat-file` to actually output the raw object contents, but you'll see
mainly a binary mess, so that's less interesting).
However -- normally you'd never use 'git write-tree' on its own, because
normally you always commit a tree into a commit object using the
'git commit-tree' command. In fact, it's easier to not actually use
'git write-tree' on its own at all, but to just pass its result in as an
argument to 'git commit-tree'.
'git commit-tree' normally takes several arguments -- it wants to know
what the 'parent' of a commit was, but since this is the first commit
ever in this new repository, and it has no parents, we only need to pass in
the object name of the tree. However, 'git commit-tree' also wants to get a
commit message on its standard input, and it will write out the resulting
object name for the commit to its standard output.
And this is where we create the `.git/refs/heads/master` file
which is pointed at by `HEAD`. This file is supposed to contain
the reference to the top-of-tree of the master branch, and since
that's exactly what 'git commit-tree' spits out, we can do this
all with a sequence of simple shell commands:
------------------------------------------------
$ tree=$(git write-tree)
$ commit=$(echo 'Initial commit' | git commit-tree $tree)
$ git update-ref HEAD $commit
------------------------------------------------