mkdir -p .git/objects .git/refs
echo "ref: refs/heads/master" > .git/HEAD # instead of 'master' here can be any branch name
git status # or even more direct way
git rev-parse --is-inside-work-tree
What more git init
does? Creates few more empty directories for future logs and prepare exampled hook scripts.
Git uses concept called hash objects. Files are stored as blob objects. They are basicly simple text (but compressed) files and stored only file contenst without even file name or other properties.
To create blob objects we need for following file (ended with \n
)
print('Hello World!')
-
we need to know its size (in bytes)
$ printf "print('Hello World!')\n" | wc -c 22
-
compute md5 sum of its content preceded by a simple prefix containing hash object type (
blob
), single space, content size and char with ASCII code 0 (\0
). Then we have file content.blob 22\0print('Hello World!')\n #\ \ \ \_ file content # \ \ \_ ASCII 0 char # \ \_ content size # \_ hash object type
$ printf "blob 22\0print('Hello World!')\n" | shasum 73fb7c3fbdbf4258a2d08f15fa7d4cd8556d0b67 -
This will be needed as hash object filename.
-
and compress such string (file content with prefix) using zlib algorithm. We will use following Python script
# git_compress.py import sys import zlib # it exist in Python standard library stdin = sys.stdin.buffer.read() # this allows us to use it in pipe length = str(len(stdin)).encode() # we need size as "ASCII digits" not integer sys.stdout.buffer.write( zlib.compress( b'blob ' + length + b'\0' + stdin, # now we can provide only file content 1, # default value is 'Z_DEFAULT_COMPRESSION' (-1), git uses 'Z_BEST_SPEED' ), # see https://docs.python.org/3.8/library/zlib.html#zlib.Compress.compress )
I will save that script as
git_compress.py
, but it's cleaner to put this script in other directory to not polute local git working directory and apply following snippet to your case.$ printf "print('Hello World!')\n" | python ./git_compress.py xK��OR02b((��+�P�H����/�IQT��� 7%
and this is actual hash object content we want to store. We will store it in
objects
directory we created in the first part. The last requirements is that filename (md5 sum we got earlier) has to be split in the first two characters and the rest. The first two will become the folder name and the rest the actual filename. It is a form of mitigation some file systems limitation - it prevents storing to many files in one folder.$ mkdir .git/objects/73 $ printf "print('Hello World!')\n" | python ./git_compress.py \ > .git/objects/73/fb7c3fbdbf4258a2d08f15fa7d4cd8556d0b67
-
We can verify hash object content using
git cat-file
command$ git cat-file -p 73fb7c3fbdbf4258a2d08f15fa7d4cd8556d0b67 print('Hello World!') # the \n char is printed and evaluated by terminal to actual break line
-
and if just want to check hash object type
$ git cat-file -t 73fb # in many places we can use just first 4 characters of hash blob