A small Git implementation written in Go.
The main goals of this project were to learn about Git internals and Go. This small Git implementation is capable of initializing a repository, creating commits and cloning a public repository.
Basic commands:
init
: Initialize the git directory structurecommit
: Record changes to the repositorylog
: Show commit logs for a commit ID
Plumbing commands:
cat-file
: Provide content or type and size information for repository objectshash-object
: Compute object ID and optionally creates a blob from a filels-tree
: List the contents of a tree objectwrite-tree
: Create a tree object from the current working directorycommit-tree
: Create a new commit object
Remote commands:
clone
: Clone a repository into a new directoryls-remote
: List references in a remote repository
Clone command is implemented using the smart HTTP protocol only. What it does:
- Discover references in the remote repository
- Negotiate packfile transfer
- Transfer and unpack packfile (with deltas unpacking)
Clone uses loose objects, unpacking the packfile fully to .git/objects
.
$ go build -o git-go
$ ./git-go
Usage: git-go <command> [<args>...]
Commands:
init Initialize the git directory structure
cat-file Provide content or type and size information for repository objects
hash-object Compute object ID and optionally creates a blob from a file
ls-tree List the contents of a tree object
write-tree Create a tree object from the current working directory
commit-tree Create a new commit object
clone Clone a repository into a new directory
ls-remote List references in a remote repository
log Show commit logs for a commit ID
commit Record changes to the repository
$ ./testsuite.sh
Build successful
=== Running cat_file.sh ===
Initialized empty Git repository in /tmp/tmp.X9EiYylEQ5/.git/
[OK] good output
=> tests/cat_file.sh passed
...
$ mkdir test_repo
$ cd test_repo
$ git-go init
Initialized empty Git repository in /tmp/tmp.XpIeQSf7Ns/test_repo/.git/
$ git-go commit -m "first"
[70dbd5eedb3c888ee6be6f1dc00e45f190a8a856] first
$ git-go log
commit 70dbd5eedb3c888ee6be6f1dc00e45f190a8a856
Author: william <mygit>
Date: Thu Jun 13 00:11:03 2024 +0200
first
$ git-go cat-file -p 70dbd5eedb3c888ee6be6f1dc00e45f190a8a856
tree 581caa0fe56cf01dc028cc0b089d364993e046b6
author william <mygit> 1718230263 +0200
committer william <mygit> 1718230263 +0200
first
$ echo 'test' > test.txt
$ git-go hash-object test.txt
9daeafb9864cf43055ae93beb0afd6c7d144bfa4
$ git-go ls-tree 581caa0fe56cf01dc028cc0b089d364993e046b6
100644 blob 980a0d5f19a64b4b30a87d4206aade58726b60e3 hello.txt
$ cd $(mktemp -d)
$ git-go init
Initialized empty Git repository in /tmp/tmp.rl0ccY5hyN/.git/
$ echo 'hello world' > hello.txt
$ echo 'test' > test.txt
$ echo 'draft' > draft
$ git-go write-tree
16e7f5e6e626c055a249af61ff9631f863f0b5a7
$ cd $(mktemp -d)
$ git-go clone https://github.com/githubtraining/hellogitworld
Cloning into 'hellogitworld'...
remote: Number of objects: 1147
remote: Resolving deltas: 418
$ ls hellogitworld
build.gradle fix.txt pom.xml README.txt resources runme.sh src
- Pro Git Book
- Git Internals Plumbing and Porcelain
- Git Internals - git objects
- Git’s database internals I: packed object store
- Git Smart HTTP Transfer protocol doc
- Git Smart HTTP Transfer protocol stackoverflow
- Git clone in haskell from the bottom up
- Unpacking git packfiles
- gitprotocol-pack.txt
man gitformat-pack
- Git from the Bottom Up
- CodeCrafters Challenge