Skip to content

Instantly share code, notes, and snippets.

What would you like to do?

How to make a commit with plumbing commands

1. Setup Git repo

  • Make empty folder called git-plumbing. Git is not initialised!
  • Make .git directory where all the Git system will reside. Git is not initialised!
  • Git repository is a collection of object and a system for naming those objects (refs). Let's make objects and refs subfolders.
  • Let's make .git/refs/heads which keep track of branches. Git is not initialised!
  • The last missing piece to initialise a Gitrepo is a HEAD file with content:
ref: refs/heads/master

2. Hash data into a blob

  • Now we can create a hash of some data and generate a loose object (blob) out of it:
$ echo "In Xanadu did Kubla Kahn" | git hash-object --stdin -w
  • I can see the actual content of the blob with:
$ git cat-file -p bf8feb # -p is for pretty-print
In Xanadu did Kubla Kahn
  • I can find out what kind of Git object is with:
$ git cat-file -t bf8feb # -t is for type
  • I can find out the size of Git object with:
$ git cat-file -s bf8feb # -s is for size in bytes
  • Git status doesn't detect anything yet

3. Growing a tree

  • Let's put the object in the staging area (index). 100644 is a magic number for permissions and I also have to specify to which file the content belongs to.
$ git update-index --add --cacheinfo 100644 bf8febed0fafd7638ad2799f5925a9383039f58e coleridge.txt
  • We need to represent a directory structure. Git doesn't care about single files. We need a tree:
$ git write-tree

$ git cat-file -t de31c7

$ git cat-file -p de31c7 # printing content of tree
100644 blob bf8febed0fafd7638ad2799f5925a9383039f58e    coleridge.txt

4. The first commit

  • Git status doesn't care at all about my tree. I need to make a commit. The commit is the snapshot:
$ git commit-tree de31c7 -m "Initial commit" f915575e03beebcef20778b99ae7aba5d00c0e9a # this is the commit hash

$ git cat-file -p f91557 # equivalent to git log --format=raw
tree de31c78155075dcebcc969331b213d5ed81c6636
author Simone Stefani <> 1518941735 +0100
committer Simone Stefani <> 1518941735 +0100

Initial commit
  • Git status is still not happy since the HEAD ref has not been adjusted. The ref folder doesn't have info about our commit. Let's add it:
$ echo f915575e03beebcef20778b99ae7aba5d00c0e9a > .git/refs/heads/master

$ git log
commit f915575e03beebcef20778b99ae7aba5d00c0e9a (HEAD -> master)
Author: Simone Stefani <>
Date:   Sun Feb 18 09:15:35 2018 +0100

    Initial commit
  • Let's checkout the file. The -- is a way for Git to apply the first part of the command only to some objects. We simply ask Git to take out the file coleridge.txt and put it into the working directory.
$ git checkout -- coleridge.txt
  • Now status is happy and we can see the file in the folder
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment