This kata is derived from How Git Works on Pluralsight by Paolo Perrotta. In that training, Paolo clearly illustrates the Git object model and how Git works behind the scenes. This kata will help reinforce the learnings about the Git Object Model.
Command | Notes |
---|---|
echo "Apple Pie" | git hash-object --stdin | This provides you with the SHA1 hash of the object. |
git cat-file -t | Tells you the type of the object - blob, tree, etc |
git cat-file -p | Pretty prints the content of the object |
git init | Initializes a git repo |
git add * | Adds file(s) to the index (staging area) |
git commit -m "message" | Commits file(s) in the index to the repository |
git log | Show the git commit history |
Learning |
---|
There are 4 main object types in git: - blobs: Contain data - trees: Contain pointers to other trees and blobs - commits: Contain pointers to a tree, along with metadata (who, comments) - tags: A label for an object. Has a pointer to an object and the label (this is not covered in this kata) |
Every object in git has a unique SHA1 hash |
A commit points to a single tree, the root tree of that particular commit Trees point to: - Other tree object(s) - Blob object(s) |
Branches are pointers to commits |
HEAD points to a branch |
There are 4 main areas in git: - Working directory: This is where you work with (add, edit, delete) files - Index: A staging area where you stage changes before committing them to the Repository - Repository: Stores all the objects - Stash: A place to temporarily store changes |
Objective | Command | Notes |
---|---|---|
Understand the Object Model | ||
Create the test files by running the setup script | ./setup.sh | This will initialize a git repo, create index.md at the root and a chapters directory with one file, chapter1.md |
cd into the kata directory | cd kata | |
Show that the git objects database does not have any files | ls -lt .git/objects/ | There are 2 directories, but no objects |
Show the git status | git status | This shows that there are 2 untracked files. The files are in the working directory, but not in the index. |
Perform the initial commit | git add * git commit -m "Initial Commit" |
|
Show the objects in the .git objects database | ls -lt .git/objects/ | There are now 5 new objects added. The objects are stored in directories that start with the first 2 characters of the objects sha1. The 5 objects are: 1 Commit, 2 Trees (the root and the chapters direcotry) and 2 files. We will explore these in more detail in a moment. |
Show the git commit history | git log | You will see the 1 commit you just made. On my machine the output looks something like this:�� commit 9fd535694a85ab312c7919d3421241a6bb643e46 (HEAD -> master) Author: Rob Bagby [email protected] Date: Wed May 29 13:20:40 2019 -0700 Initial Commit |
Show the content of the first commit | git cat-file -p <commit sha> | On my machine, I ran: git cat-file -p 9fd535694a85ab312c7919d3421241a6bb643e46 tree 0933ed499b266f596e52ad24dc2a3a15ff2ae8f6 author Rob Bagby [email protected] 1559840863 -0700 committer Rob Bagby [email protected] 1559840863 -0700 Initial Commit�� You can see from the output above, the first commit points to a single tree, which is the root of this commit |
Show the content of the tree object that the commit is pointing to | git cat-file -p <tree sha> | On my machine, I ran: git cat-file -p 0933ed499b266f596e52ad24dc2a3a15ff2ae8f6 040000 tree e68b491f4b9db667647987cfa879724f0986e8e3 chapters 100644 blob e031062f4cf45cf2990aa450a7eb8b08dfe0f932 index.md You can see that the root tree contains the sha to: - The blob for index.md - The tree for the chapters directory |
Show the git objects again | ls -lt .git/objects/ | The following are the results on my machine:�� total 0 drwxr-xr-x 3 robbagby staff 96 Jun 6 10:07 09 drwxr-xr-x 3 robbagby staff 96 Jun 6 10:07 9f drwxr-xr-x 3 robbagby staff 96 Jun 6 10:07 e6 drwxr-xr-x 3 robbagby staff 96 Jun 6 10:07 e0 drwxr-xr-x 3 robbagby staff 96 Jun 6 10:07 e1 drwxr-xr-x 2 robbagby staff 64 Jun 6 10:05 info drwxr-xr-x 2 robbagby staff 64 Jun 6 10:05 pack You can see that there are several directories that start with 2 characters. Git stores the objects in directories whose names start with the first two characters of the object sha |
Show the contents of the directory that contains the object representing index.md | ls -lt .git/objects/<first 2 letters of the sha for index.md> | On my machine, I ran: ls -lt .git/objects/e0� total 8 -r--r--r-- 1 robbagby staff 40 Jun 6 10:07 31062f4cf45cf2990aa450a7eb8b08dfe0f932 Notice that the file name is the sha1 of index.md without the first 2 characters |
Show the contents of the object representing index.md | git cat-file -p <index.md_sha> | On my machine, I ran: �git cat-file -p e031062f4cf45cf2990aa450a7eb8b08dfe0f932 [Chapter 1](chapters/chapter1.md) This is a markdown link to chapters/chapter1.md |
Understand Branches | ||
Show the branches | git branch | Although we have not created any branches, git created one by default named master ��git branch * master |
Show where the branches are stored | ls -lt .git/refs/heads | ls -lt .git/refs/heads� total 8 -rw-r--r-- 1 robbagby staff 41 Jun 6 10:07 master Git stores the branches in .git/refs/heads. There is a file for each branch |
Show the content of the branch file | cat .git/refs/heads/master | cat .git/refs/heads/master�� 9fd535694a85ab312c7919d3421241a6bb643e46 The master holds a pointer to the first commit. You can prove this by running git log to see the sha1 of the first commit. So, as you can see, branches are merely references to commits. |
Create a new branch | git branch feature1 | |
Show how branches are stored in .git | ls -lt .git/refs/heads | ls -lt .git/refs/heads total 16 -rw-r--r-- 1 robbagby staff 41 Jun 6 10:40 feature1 -rw-r--r-- 1 robbagby staff 41 Jun 6 10:07 master |
Show the content of the feature1 branch file | cat .git/refs/heads/feature1 | cat .git/refs/heads/lisa�� 9fd535694a85ab312c7919d3421241a6bb643e46 ��Note that this branch has the same pointer as master |
Show the branches | git branch | git branch� feature1 * master There are now 2 branches. The asterisk indicates that the current branch is 'master' |
Understand HEAD | ||
Show how HEAD is stored in git | cat .git/HEAD | cat .git/HEAD�� ref: refs/heads/master ��The HEAD file has a pointer to a single branch in the refs/heads folder |
Checkout the feature1 branch | git checkout feature1 | git checkout feature1 Switched to branch 'feature1' |
Show how HEAD is stored in git | cat .git/HEAD | cat .git/HEAD ref: refs/heads/feature1 The HEAD file now has a pointer to the feature1 branch |