Skip to content

Instantly share code, notes, and snippets.

@SimoneStefani
Last active February 18, 2018 12:54
Show Gist options
  • Save SimoneStefani/5488f915c1af94a35c3b76a7cd3b4e99 to your computer and use it in GitHub Desktop.
Save SimoneStefani/5488f915c1af94a35c3b76a7cd3b4e99 to your computer and use it in GitHub Desktop.

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
bf8febed0fafd7638ad2799f5925a9383039f58e
  • 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
blob
  • I can find out the size of Git object with:
$ git cat-file -s bf8feb # -s is for size in bytes
25
  • 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
de31c78155075dcebcc969331b213d5ed81c6636

$ git cat-file -t de31c7
tree

$ 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 <[email protected]> 1518941735 +0100
committer Simone Stefani <[email protected]> 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 <[email protected]>
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