A commit ties a tree to an author, a committer, and a message. Assemble those lines in the right order, hash them, and you get a commit id that matches real Git exactly. Today you build your first commit object.
Build a commit object for a root tree with no parent and hash it to its exact id.
A commit object is just structured text. The lines come in a fixed order: tree
and its id, then (later) any parent lines, then the author line, the
committer line, a single blank line, and finally the commit message. That is
the entire format. Wrap it as a commit object and hash it, exactly as with blobs
and trees.
Because every part feeds the hash, the tree id, both identity lines, and the
message all determine the commit id. With our fixed identity and timestamp, this
initial commit over the root tree is always f18e98d3.... You can reproduce it in
real Git with git commit-tree and the same dates, and get the same id back. A
commit is thus a content-addressed snapshot-plus-metadata: it names a whole tree
(the entire project state) with one id.
// "tree <id>\n" + "author <ident>\n" + "committer <ident>\n" + "\n" + messagebody := "tree " + tree + "\n"body += "author " + ident + "\n"body += "committer " + ident + "\n"body += "\n" + message // message already ends in "\n"id, _ := r.WriteObject("commit", []byte(body))