Tomorrow I will give a presentation to colleagues titled “Git Internal”. This will cover a simple overview of how git tracks changes and how they are represented and stored efficiently. This presentation, compared to my previous ones, will focus more on a demo at the CLI where I run a series of commands stepping through git objects (trees, commits, blobs and tags) and references. I also cover the HEAD pointer and how you would recover from a deleted branch and log, as well as a quiz on useful git commands. The demo is based on the walkthrough in Chapter 10 of the git docs with some edits and changes. For reference, these are the commands I plan to use in the demo (with the git hashes changed).

The .git folder slide 
(from xr repo)
cd .git
ls -l
ls objects
ls objects/00
ls objects/01

<!--more-->
Demonstrate the objects and commits
cd /tmp
mkdir git_test
cd git_test
git init
find .git/objects -type f
echo "some content" > text_file.txt
git add test_file.txt
find .git/objects -type f
git cat-file 2ef267e25bd6c6a300bb473e604b092b6a48523b -pvim 
git cat-file 2ef267e25bd6c6a300bb473e604b092b6a48523b -t
git commit -m "commit msg"
find .git/objects -type f
git cat-file 2ef267e25bd6c6a300bb473e604b092b6a48523b -p
git cat-file 2ef267e25bd6c6a300bb473e604b092b6a48523b -t
git cat-file 2ef267e25bd6c6a300bb473e604b092b6a48523b -p
git cat-file 2ef267e25bd6c6a300bb473e604b092b6a48523b -t

cp /usr/share/dict/words dict
vim dict
git add dict
git commit -m "add dict"
vim dict
	(alter the contents)
git add dict
git commit -m "alter dict"
git hash-object dict
git hash-object dict | xargs git cat-file -p
	(this isn't a diff. surely we could store a diff here? the files were so similar)
du .git/objects -h
	(we see that there are two objects of 1.7 M, so git doesn't store a diff?)

Packfiles slide
git gc
du .git/objects -h
git verify-pack -v .git/objects/pack/pack-49b9743b279afebd445f47821f0caf440ac50e92.idx

Reference/branches/Head slide
find .git/refs -type f
cat .git/HEAD
git checkout HEAD~1
gl master
cat .git/HEAD
git --no-pager log --pretty=oneline master
git update-ref refs/head/test_branch HEAD
find .git/refs -type f
find .git/refs -type f | xargs cat
gl
git switch test_branch
gl
cat .git/HEAD

Data Recovery
git switch master
gl
git reset --hard 1260d45ec7492d4977310838ee103140c66b16c9
(the solution here is use reflog to get the commit hash off the latest branch)
git --no-pager reflog
git log -g
git branch recover-branch 2e22d622d05d1362f5a78d8319b1ec2e17ee91c5
git branch -D recover-branch
rm -Rf .git/logs
git reflog
git fsck --full