Convert "internal" levels to new level format

This commit is contained in:
Sebastian Morr 2020-10-12 18:54:27 +02:00
parent 613b1b9852
commit 53a6885ef9
108 changed files with 727 additions and 382 deletions

26
levels/internals/basics Normal file
View file

@ -0,0 +1,26 @@
[description]
For this prototype, we assume you have some experience with the command line. Here are some commands that will be useful:
- ls
- echo content > file
- cat file
- mkdir dir
Find the riddle in your current directory and put the answer into the file "answer"!
[congrats]
Omnomnom!
For technical reasons, you can't use `cd` in this prototype yet. But there won't be a lot of interaction with the file system anyways. :)
[setup]
mkdir riddle
echo "ppl p" > riddle/consonants
echo "ae ie" > riddle/vowels
[win]
cat answer | grep -i "apple \\?pie"

View file

@ -1,3 +0,0 @@
Omnomnom!
For technical reasons, you can't use `cd` in this prototype yet. But there won't be a lot of interaction with the file system anyways. :)

View file

@ -1,8 +0,0 @@
For this prototype, we assume you have some experience with the command line. Here are some commands that will be useful:
- ls
- echo content > file
- cat file
- mkdir dir
Find the riddle in your current directory and put the answer into the file "answer"!

View file

@ -1,3 +0,0 @@
mkdir riddle
echo "ppl p" > riddle/consonants
echo "ae ie" > riddle/vowels

View file

@ -1 +0,0 @@
cat answer | grep -i "apple \\?pie"

View file

@ -0,0 +1,38 @@
[description]
At its core, Git is very simple. It stores "objects", which are basically files identified by an "identifier" (short: ID).
There are four types of objects: blobs, trees, commits, and tags. The simplest type is a "blob", which is just a piece of text.
Let's create some blobs! To do that, create a file with the desired content, and then use
git hash-object -w <file>
The flag -w means "write", and tells Git to actually write the new blob to the disk.
Create three new blobs!
[congrats]
Tip: You can also use a command like this to create a blob in a single line:
echo "awesome content" | git hash-object -w --stdin
Did you already notice that you can drag and drop all objects? :)
[setup]
[setup goal]
echo "Hi" > file1
echo "Ho" > file2
echo "Hu" > file3
git hash-object -w file1
git hash-object -w file2
git hash-object -w file3
[win]
BLOB_COUNT=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep blob | wc -l)
test "$BLOB_COUNT" -gt 2

View file

@ -1,5 +0,0 @@
Tip: You can also use a command like this to create a blob in a single line:
echo "awesome content" | git hash-object -w --stdin
Did you already notice that you can drag and drop all objects? :)

View file

@ -1,11 +0,0 @@
At its core, Git is very simple. It stores "objects", which are basically files identified by an "identifier" (short: ID).
There are four types of objects: blobs, trees, commits, and tags. The simplest type is a "blob", which is just a piece of text.
Let's create some blobs! To do that, create a file with the desired content, and then use
git hash-object -w <file>
The flag -w means "write", and tells Git to actually write the new blob to the disk.
Create three new blobs!

View file

@ -1,6 +0,0 @@
echo "Hi" > file1
echo "Ho" > file2
echo "Hu" > file3
git hash-object -w file1
git hash-object -w file2
git hash-object -w file3

View file

@ -1,3 +0,0 @@
BLOB_COUNT=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep blob | wc -l)
test "$BLOB_COUNT" -gt 2

View file

@ -0,0 +1,27 @@
[description]
There's a simple command to remove all objects that are not referenced by anything:
git prune
Remove all blobs in this repository.
[congrats]
Generally, `git prune` will be useful if you want to clean up some objects you made.
Alternatively, you can also click the "Reload" button to restart a level.
[setup]
echo "My master password is a1b2c3d4e5" | git hash-object -w --stdin
echo "This blob really should not exist" | git hash-object -w --stdin
echo "This is a virus" | git hash-object -w --stdin
[setup goal]
[win]
OBJECT_COUNT=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | wc -l)
test "$OBJECT_COUNT" -eq 0

View file

@ -1,3 +0,0 @@
Generally, `git prune` will be useful if you want to clean up some objects you made.
Alternatively, you can also click the "Reload" button to restart a level.

View file

@ -1,5 +0,0 @@
There's a simple command to remove all objects that are not referenced by anything:
git prune
Remove all blobs in this repository.

View file

@ -1 +0,0 @@
git prune

View file

@ -1,3 +0,0 @@
echo "My master password is a1b2c3d4e5" | git hash-object -w --stdin
echo "This blob really should not exist" | git hash-object -w --stdin
echo "This is a virus" | git hash-object -w --stdin

View file

@ -1,3 +0,0 @@
OBJECT_COUNT=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | wc -l)
test "$OBJECT_COUNT" -eq 0

View file

@ -0,0 +1,37 @@
[description]
So a tree describes a directory structure at a specific point in time.
It would be nice if we could remember when that state existed, and who authored it, right?
Enter: commits. They are objects that point to a tree and contain some additional metadata. You can create a commit using
git commit-tree <tree> -m "Description of your commit"
Make a commit from the tree in this repository!
[setup]
touch empty_file
git add .
git write-tree
rm empty_file
git update-index --remove empty_file
[setup goal]
touch empty_file
git add .
git write-tree
rm empty_file
git update-index --remove empty_file
git commit-tree 3185 -m 'Clever commit message'
[win]
COMMIT_COUNT=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep commit | wc -l)
test "$COMMIT_COUNT" -gt 0

View file

@ -1,9 +0,0 @@
So a tree describes a directory structure at a specific point in time.
It would be nice if we could remember when that state existed, and who authored it, right?
Enter: commits. They are objects that point to a tree and contain some additional metadata. You can create a commit using
git commit-tree <tree> -m "Description of your commit"
Make a commit from the tree in this repository!

View file

@ -1 +0,0 @@
git commit-tree 3185 -m 'Clever commit message'

View file

@ -1,6 +0,0 @@
touch empty_file
git add .
git write-tree
rm empty_file
git update-index --remove empty_file

View file

@ -1,3 +0,0 @@
COMMIT_COUNT=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep commit | wc -l)
test "$COMMIT_COUNT" -gt 0

View file

@ -0,0 +1,31 @@
[description]
When using the commit-tree command, you can optionally specify a parent:
git commit-tree <tree> -m "Description" -p <parent commit>
Make a string of three commits!
Hint: You'll need a tree object. What could be the easiest way to obtain one?
[setup]
[setup goal]
git write-tree
FIRST_COMMIT=$(git commit-tree 4b82 -m 'First commit :O')
SECOND_COMMIT=$(git commit-tree 4b82 -p $FIRST_COMMIT -m 'Second commit :D')
THIRD_COMMIT=$(git commit-tree 4b82 -p $SECOND_COMMIT -m 'Third commit \o/')
[win]
COMMITS=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep commit | cut -f1 -d" ")
for COMMIT in $COMMITS; do
echo a commit named $COMMIT
if [ $(git rev-list $COMMIT | wc -l) -ge 3 ]; then
return 0
fi
done
return 1

View file

@ -1,7 +0,0 @@
When using the commit-tree command, you can optionally specify a parent:
git commit-tree <tree> -m "Description" -p <parent commit>
Make a string of three commits!
Hint: You'll need a tree object. What could be the easiest way to obtain one?

View file

@ -1,4 +0,0 @@
git write-tree
FIRST_COMMIT=$(git commit-tree 4b82 -m 'First commit :O')
SECOND_COMMIT=$(git commit-tree 4b82 -p $FIRST_COMMIT -m 'Second commit :D')
THIRD_COMMIT=$(git commit-tree 4b82 -p $SECOND_COMMIT -m 'Third commit \o/')

View file

@ -1,10 +0,0 @@
COMMITS=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep commit | cut -f1 -d" ")
for COMMIT in $COMMITS; do
echo a commit named $COMMIT
if [ $(git rev-list $COMMIT | wc -l) -ge 3 ]; then
return 0
fi
done
return 1

View file

@ -0,0 +1,30 @@
[description]
A commit can have multiple parents! You can specify the -p option multiple times, like this:
git commit-tree <tree> -m "Description" -p <parent1> -p <parent2>
Build a rhombus shape from commits, where two commits point to the same parent, and then a fourth commit points to both of them.
[setup]
[setup goal]
TREE=$(git write-tree)
SOUTH=$(git commit-tree $TREE -m "South")
EAST=$(git commit-tree $TREE -m "East" -p $SOUTH)
WEST=$(git commit-tree $TREE -m "West" -p $SOUTH)
NORTH=$(git commit-tree $TREE -m "Nort" -p $EAST -p $WEST)
[win]
COMMITS=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep commit | cut -f1 -d" ")
for COMMIT in $COMMITS; do
# My first parent's parents has to be the same as my second parent's parent.
if [ "$(git rev-parse --verify -q $COMMIT^1^)" = "$(git rev-parse --verify -q $COMMIT^2^)" ]; then
return 0
fi
done
return 1

View file

@ -1,5 +0,0 @@
A commit can have multiple parents! You can specify the -p option multiple times, like this:
git commit-tree <tree> -m "Description" -p <parent1> -p <parent2>
Build a rhombus shape from commits, where two commits point to the same parent, and then a fourth commit points to both of them.

View file

@ -1,5 +0,0 @@
TREE=$(git write-tree)
SOUTH=$(git commit-tree $TREE -m "South")
EAST=$(git commit-tree $TREE -m "East" -p $SOUTH)
WEST=$(git commit-tree $TREE -m "West" -p $SOUTH)
NORTH=$(git commit-tree $TREE -m "Nort" -p $EAST -p $WEST)

View file

@ -1,10 +0,0 @@
COMMITS=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep commit | cut -f1 -d" ")
for COMMIT in $COMMITS; do
# My first parent's parents has to be the same as my second parent's parent.
if [ "$(git rev-parse --verify -q $COMMIT^1^)" = "$(git rev-parse --verify -q $COMMIT^2^)" ]; then
return 0
fi
done
return 1

43
levels/internals/conflict Normal file
View file

@ -0,0 +1,43 @@
[description]
(This is not a real puzzle yet.)
Try merging the two branches together!
git merge <otherbranch>
[setup]
echo ? > bikeshed_color
git add .
git commit -m "Initial commit"
echo green > bikeshed_color
git commit -a -m "My suggestion"
git switch -c alternative HEAD^
echo blue > bikeshed_color
git commit -a -m "This is way better"
git switch main
[setup goal]
echo ? > bikeshed_color
git add .
git commit -m "Initial commit"
echo green > bikeshed_color
git commit -a -m "My suggestion"
git switch -c alternative HEAD^
echo blue > bikeshed_color
git commit -a -m "This is way better"
git switch main
git merge alternative
echo blue-green > bikeshed_color
git add .
git commit -m "Merge"
git prune

View file

@ -1,5 +0,0 @@
(This is not a real puzzle yet.)
Try merging the two branches together!
git merge <otherbranch>

View file

@ -1,5 +0,0 @@
git merge alternative
echo blue-green > bikeshed_color
git add .
git commit -m "Merge"
git prune

View file

@ -1,12 +0,0 @@
echo ? > bikeshed_color
git add .
git commit -m "Initial commit"
echo green > bikeshed_color
git commit -a -m "My suggestion"
git switch -c alternative HEAD^
echo blue > bikeshed_color
git commit -a -m "This is way better"
git switch main

View file

@ -0,0 +1,37 @@
[description]
Blobs usually represent the content of a file. But on their own, they don't have any metadata, not even a name!
Git has a very powerful concept to store metadata related to blobs: the index! It's a list that relates blobs to filenames and access permissions.
The most convenient option to add an entry to the index is via an existing file:
echo "my content" > file
git update-index --add file
Add three entries to the index! For a bonus challenge: can you add a file that is inside of a directory, like "directory/file"?
[congrats]
There's another way to add an entry to the index directly:
git update-index --add --cacheinfo <mode>,<blobhash>,<name>
The first three numbers of the mode describe the type of the entry, "100" is a regular file.
The second three number describe the permissions. Only "644" (non-executable) and "755" (executable) are supported.
You can insert the hash of an object into the terminal by right-clicking on it! :)
[setup]
[setup goal]
echo "file 1" > file1
echo "file 2" > file2
echo "file 3" > file3
git add .
[win]
test "$(git ls-files | wc -l)" -ge 3

View file

@ -1,9 +0,0 @@
There's another way to add an entry to the index directly:
git update-index --add --cacheinfo <mode>,<blobhash>,<name>
The first three numbers of the mode describe the type of the entry, "100" is a regular file.
The second three number describe the permissions. Only "644" (non-executable) and "755" (executable) are supported.
You can insert the hash of an object into the terminal by right-clicking on it! :)

View file

@ -1,10 +0,0 @@
Blobs usually represent the content of a file. But on their own, they don't have any metadata, not even a name!
Git has a very powerful concept to store metadata related to blobs: the index! It's a list that relates blobs to filenames and access permissions.
The most convenient option to add an entry to the index is via an existing file:
echo "my content" > file
git update-index --add file
Add three entries to the index! For a bonus challenge: can you add a file that is inside of a directory, like "directory/file"?

View file

@ -1,4 +0,0 @@
echo "file 1" > file1
echo "file 2" > file2
echo "file 3" > file3
git add .

View file

@ -1 +0,0 @@
test "$(git ls-files | wc -l)" -ge 3

View file

@ -0,0 +1,29 @@
[description]
To remove an entry from the index, use a command like this:
git update-index --force-remove <file>
Remove all entries from the index!
[setup]
echo "file 1" > file1
echo "file 2" > file2
echo "file 3" > file3
git add .
[setup goal]
echo "file 1" > file1
echo "file 2" > file2
echo "file 3" > file3
git add .
git update-index --force-remove file1
git update-index --force-remove file2
git update-index --force-remove file3
[win]
test "$(git ls-files | wc -l)" -eq 0

View file

@ -1,5 +0,0 @@
To remove an entry from the index, use a command like this:
git update-index --force-remove <file>
Remove all entries from the index!

View file

@ -1,3 +0,0 @@
git update-index --force-remove file1
git update-index --force-remove file2
git update-index --force-remove file3

View file

@ -1,4 +0,0 @@
echo "file 1" > file1
echo "file 2" > file2
echo "file 3" > file3
git add .

View file

@ -1 +0,0 @@
test "$(git ls-files | wc -l)" -eq 0

View file

@ -0,0 +1,33 @@
[description]
Instead of removing an entry from the index and adding one with the same name, you can also directly update that entry!
Put the content you want in a file with a matching name, and then run
git update-index <file>
This will create a new blob, and update the hash of the entry to that blob.
Update an entry in the index!
[setup]
echo "file 1" > file1
echo "file 2" > file2
echo "file 3" > file3
git add .
[setup goal]
echo "file 1" > file1
echo "file 2" > file2
echo "file 3" > file3
git add .
echo "new content" > file1
git update-index file1
[win]
# This is not really a good test for the winning condition...
test "$(git ls-files -s | git hash-object --stdin)" != "10c4b28623e7e44e09f5a596450a50ab7ac31fbe" -a "$(git ls-files | wc -l)" -eq 3

View file

@ -1,9 +0,0 @@
Instead of removing an entry from the index and adding one with the same name, you can also directly update that entry!
Put the content you want in a file with a matching name, and then run
git update-index <file>
This will create a new blob, and update the hash of the entry to that blob.
Update an entry in the index!

View file

@ -1,2 +0,0 @@
echo "new content" > file1
git update-index file1

View file

@ -1,4 +0,0 @@
echo "file 1" > file1
echo "file 2" > file2
echo "file 3" > file3
git add .

View file

@ -1,2 +0,0 @@
# This is not really a good test for the winning condition...
test "$(git ls-files -s | git hash-object --stdin)" != "10c4b28623e7e44e09f5a596450a50ab7ac31fbe" -a "$(git ls-files | wc -l)" -eq 3

View file

@ -0,0 +1,44 @@
[description]
Delete all objects in this repository using git commands only!
Useful commands:
git prune
git fsck
git reflog expire
Note: I'm not sure how to beat this level. :D
[setup]
echo foo > foo
BLOB=$(git hash-object -w foo)
echo bar > bar
git add .
git commit -m "Initial commit"
echo blabber >> bar
git commit -a -m "Second commit"
git update-ref refs/important HEAD
git update-ref refs/interesting "$BLOB"
[setup goal]
echo foo > foo
BLOB=$(git hash-object -w foo)
echo bar > bar
git add .
git commit -m "Initial commit"
echo blabber >> bar
git commit -a -m "Second commit"
git update-ref refs/important HEAD
git update-ref refs/interesting "$BLOB"
TREE=$(git mktree)
git read-tree $TREE
rm -rf .git/refs/*
rm -rf .git/objects/*
[win]
test "$(git cat-file --batch-check --batch-all-objects | wc -l)" -eq 0

View file

@ -1,9 +0,0 @@
Delete all objects in this repository using git commands only!
Useful commands:
git prune
git fsck
git reflog expire
Note: I'm not sure how to beat this level. :D

View file

@ -1,4 +0,0 @@
TREE=$(git mktree)
git read-tree $TREE
rm -rf .git/refs/*
rm -rf .git/objects/*

View file

@ -1,9 +0,0 @@
echo foo > foo
BLOB=$(git hash-object -w foo)
echo bar > bar
git add .
git commit -m "Initial commit"
echo blabber >> bar
git commit -a -m "Second commit"
git update-ref refs/important HEAD
git update-ref refs/interesting "$BLOB"

View file

@ -1 +0,0 @@
test "$(git cat-file --batch-check --batch-all-objects | wc -l)" -eq 0

View file

@ -1,3 +1,21 @@
[description]
Create two trees pointing to the same blob!
[setup]
[setup goal]
BLOB=$(echo "I am precious" | git hash-object -w --stdin)
git update-index --add --cacheinfo 100644,$BLOB,a
git write-tree
git update-index --force-remove a
git update-index --add --cacheinfo 100644,$BLOB,b
git write-tree
git update-index --force-remove b
[win]
TREES=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep tree | cut -f1 -d" ") TREES=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep tree | cut -f1 -d" ")
ALL_TREE_CHILDREN=$(for TREE in $TREES; do ALL_TREE_CHILDREN=$(for TREE in $TREES; do

View file

@ -1 +0,0 @@
Create two trees pointing to the same blob!

View file

@ -1,7 +0,0 @@
BLOB=$(echo "I am precious" | git hash-object -w --stdin)
git update-index --add --cacheinfo 100644,$BLOB,a
git write-tree
git update-index --force-remove a
git update-index --add --cacheinfo 100644,$BLOB,b
git write-tree
git update-index --force-remove b

View file

@ -1,3 +1,19 @@
[description]
Construct a chain of three trees, which don't point to anything else.
This is hard! The `git mktree` command might be useful.
[setup]
[setup goal]
git mktree
TREE=$(echo -e "040000 tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\tdir" | git mktree)
echo -e "040000 tree $TREE\tdir" | git mktree
[win]
TREES=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep tree | cut -f1 -d" ") TREES=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep tree | cut -f1 -d" ")
for TREE in $TREES; do for TREE in $TREES; do

View file

@ -1,3 +0,0 @@
Construct a chain of three trees, which don't point to anything else.
This is hard! The `git mktree` command might be useful.

View file

@ -1,3 +0,0 @@
git mktree
TREE=$(echo -e "040000 tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\tdir" | git mktree)
echo -e "040000 tree $TREE\tdir" | git mktree

View file

@ -0,0 +1,42 @@
[description]
Let's take a look at "refs" (short for "references")! Refs are not objects, but rather very simple *pointers* to objects! They can help you keep track of what's where.
You can create or update a ref with
git update-ref refs/<refname> <newvalue>
Make sure to always start a ref's name with "refs/"! That's a convention that helps Git find all refs you create. If you forget the "refs/", you will not see the ref.
Create refs that point to all objects in this repository!
[setup]
echo hello > hello
echo world > world
BLOB1=$(git hash-object -w hello)
BLOB2=$(git hash-object -w world)
git add .
TREE=$(git write-tree)
COMMIT=$(git commit-tree $TREE -m "Initial commit")
[setup goal]
echo hello > hello
echo world > world
BLOB1=$(git hash-object -w hello)
BLOB2=$(git hash-object -w world)
git add .
TREE=$(git write-tree)
COMMIT=$(git commit-tree $TREE -m "Initial commit")
git update-ref refs/a $BLOB1
git update-ref refs/b $BLOB2
git update-ref refs/c $TREE
git update-ref refs/d $COMMIT
[win]
OBJECTS=$(git cat-file --batch-check='%(objectname)' --batch-all-objects | sort)
REF_TARGETS=$(git show-ref -s | sort | uniq)
test "$OBJECTS" = "$REF_TARGETS"

View file

@ -1,9 +0,0 @@
Let's take a look at "refs" (short for "references")! Refs are not objects, but rather very simple *pointers* to objects! They can help you keep track of what's where.
You can create or update a ref with
git update-ref refs/<refname> <newvalue>
Make sure to always start a ref's name with "refs/"! That's a convention that helps Git find all refs you create. If you forget the "refs/", you will not see the ref.
Create refs that point to all objects in this repository!

View file

@ -1,4 +0,0 @@
git update-ref refs/a $BLOB1
git update-ref refs/b $BLOB2
git update-ref refs/c $TREE
git update-ref refs/d $COMMIT

View file

@ -1,7 +0,0 @@
echo hello > hello
echo world > world
BLOB1=$(git hash-object -w hello)
BLOB2=$(git hash-object -w world)
git add .
TREE=$(git write-tree)
COMMIT=$(git commit-tree $TREE -m "Initial commit")

View file

@ -1,3 +0,0 @@
OBJECTS=$(git cat-file --batch-check='%(objectname)' --batch-all-objects | sort)
REF_TARGETS=$(git show-ref -s | sort | uniq)
test "$OBJECTS" = "$REF_TARGETS"

41
levels/internals/ref-move Normal file
View file

@ -0,0 +1,41 @@
[description]
You can point refs to a new location using the same command you use to create them:
git update-ref refs/<refname> <object>
As an exercise, make all refs in this repository point to the tree object!
[setup]
echo hello > hello
echo world > world
BLOB1=$(git hash-object -w hello)
BLOB2=$(git hash-object -w world)
git add .
TREE=$(git write-tree)
COMMIT=$(git commit-tree $TREE -m "Initial commit")
git update-ref refs/a "$BLOB1"
git update-ref refs/b "$COMMIT"
[setup goal]
echo hello > hello
echo world > world
BLOB1=$(git hash-object -w hello)
BLOB2=$(git hash-object -w world)
git add .
TREE=$(git write-tree)
COMMIT=$(git commit-tree $TREE -m "Initial commit")
git update-ref refs/a "$BLOB1"
git update-ref refs/b "$COMMIT"
for REF in $(git for-each-ref --format='%(refname)'); do
git update-ref "$REF" "$TREE"
done
[win]
test "$(git show-ref -s | sort -u)" = "c7863f72467ed8dd44f4b8ffdb8b57ca7d91dc9e"

View file

@ -1,5 +0,0 @@
You can point refs to a new location using the same command you use to create them:
git update-ref refs/<refname> <object>
As an exercise, make all refs in this repository point to the tree object!

View file

@ -1,3 +0,0 @@
for REF in $(git for-each-ref --format='%(refname)'); do
git update-ref "$REF" "$TREE"
done

View file

@ -1,10 +0,0 @@
echo hello > hello
echo world > world
BLOB1=$(git hash-object -w hello)
BLOB2=$(git hash-object -w world)
git add .
TREE=$(git write-tree)
COMMIT=$(git commit-tree $TREE -m "Initial commit")
git update-ref refs/a "$BLOB1"
git update-ref refs/b "$COMMIT"

View file

@ -1 +0,0 @@
test "$(git show-ref -s | sort -u)" = "c7863f72467ed8dd44f4b8ffdb8b57ca7d91dc9e"

View file

@ -0,0 +1,41 @@
[description]
And finally, to delete a ref, use
git update-ref -d refs/<refname>
Delete all refs! :P (Well, except for HEAD. HEAD is special.)
[setup]
echo hello > hello
echo world > world
BLOB1=$(git hash-object -w hello)
BLOB2=$(git hash-object -w world)
git add .
TREE=$(git write-tree)
COMMIT=$(git commit-tree $TREE -m "Initial commit")
git update-ref refs/best_blob_ever "$BLOB1"
git update-ref refs/beautiful_commit "$COMMIT"
[setup goal]
echo hello > hello
echo world > world
BLOB1=$(git hash-object -w hello)
BLOB2=$(git hash-object -w world)
git add .
TREE=$(git write-tree)
COMMIT=$(git commit-tree $TREE -m "Initial commit")
git update-ref refs/best_blob_ever "$BLOB1"
git update-ref refs/beautiful_commit "$COMMIT"
for REF in $(git for-each-ref --format='%(refname)'); do
git update-ref -d "$REF"
done
[win]
test "$(git show-ref | wc -l)" -eq 0

View file

@ -1,5 +0,0 @@
And finally, to delete a ref, use
git update-ref -d refs/<refname>
Delete all refs! :P (Well, except for HEAD. HEAD is special.)

View file

@ -1,3 +0,0 @@
for REF in $(git for-each-ref --format='%(refname)'); do
git update-ref -d "$REF"
done

View file

@ -1,10 +0,0 @@
echo hello > hello
echo world > world
BLOB1=$(git hash-object -w hello)
BLOB2=$(git hash-object -w world)
git add .
TREE=$(git write-tree)
COMMIT=$(git commit-tree $TREE -m "Initial commit")
git update-ref refs/best_blob_ever "$BLOB1"
git update-ref refs/beautiful_commit "$COMMIT"

View file

@ -1 +0,0 @@
test "$(git show-ref | wc -l)" -eq 0

View file

@ -1,3 +1,5 @@
[description]
Instead of pointing directly to objects, refs can also point to other refs! Instead of pointing directly to objects, refs can also point to other refs!
When that happens, they are called "symbolic refs". You can create or update a symbolic ref using When that happens, they are called "symbolic refs". You can create or update a symbolic ref using
@ -5,3 +7,15 @@ When that happens, they are called "symbolic refs". You can create or update a s
git symbolic-ref <name> <ref> git symbolic-ref <name> <ref>
Create a symbolic ref called "refs/rainbow"! Create a symbolic ref called "refs/rainbow"!
[setup]
[setup goal]
BLOB=$(git hash-object -w --stdin)
git update-ref refs/double "$BLOB"
git symbolic-ref refs/rainbow refs/double
[win]
git symbolic-ref refs/rainbow

View file

@ -1,3 +0,0 @@
BLOB=$(git hash-object -w --stdin)
git update-ref refs/double "$BLOB"
git symbolic-ref refs/rainbow refs/double

View file

@ -1 +0,0 @@
git symbolic-ref refs/rainbow

View file

@ -0,0 +1,46 @@
[description]
When you have a symbolic ref (a ref pointing at another ref), and you decide you want it to be a regular ref again (pointing to an object), you're in for some trouble! :)
What happens when you try pointing the symbolic ref directly to the blob using `git update-ref`?
Oops! Turns out that when you reference a symbolic ref, it acts as if you had specified the ref it points to. To de-symbolic-ize it, use the `--no-deref` option directly after `update-ref`!
Weird, huh?
[congrats]
Whew, we've covered a lot of things: Blobs! The index! Trees! Commits! Refs!
You now know about almost everything about how Git repositories look like on the inside! We think that's pretty cool! :)
Everything else is just convention and high-level commands that make interacting with the objects more convenient.
We haven't covered:
- tag objects (they are the fourth object type - a bit like refs with a description and an author)
- configuration (allows you to specify remote repositories, for example)
- working with local files (which is, uh, arguably pretty important :P)
Thanks for playing! You're welcome to check out the "puzzle" levels in the dropdown, some of them are more advanced!
[setup]
BLOB1=$(echo delicious | git hash-object -w --stdin)
BLOB2=$(echo very | git hash-object -w --stdin)
git update-ref refs/curly "$BLOB1"
git symbolic-ref refs/fries refs/curly
[setup goal]
BLOB1=$(echo delicious | git hash-object -w --stdin)
BLOB2=$(echo very | git hash-object -w --stdin)
git update-ref refs/curly "$BLOB1"
git symbolic-ref refs/fries refs/curly
git update-ref --no-deref refs/fries "$BLOB2"
[win]
git symbolic-ref refs/fries && return 1
test "$(git show-ref -s refs/fries)" = "035e2968dafeea08e46e8fe6743cb8123e8b9aa6"

View file

@ -1,13 +0,0 @@
Whew, we've covered a lot of things: Blobs! The index! Trees! Commits! Refs!
You now know about almost everything about how Git repositories look like on the inside! We think that's pretty cool! :)
Everything else is just convention and high-level commands that make interacting with the objects more convenient.
We haven't covered:
- tag objects (they are the fourth object type - a bit like refs with a description and an author)
- configuration (allows you to specify remote repositories, for example)
- working with local files (which is, uh, arguably pretty important :P)
Thanks for playing! You're welcome to check out the "puzzle" levels in the dropdown, some of them are more advanced!

View file

@ -1,7 +0,0 @@
When you have a symbolic ref (a ref pointing at another ref), and you decide you want it to be a regular ref again (pointing to an object), you're in for some trouble! :)
What happens when you try pointing the symbolic ref directly to the blob using `git update-ref`?
Oops! Turns out that when you reference a symbolic ref, it acts as if you had specified the ref it points to. To de-symbolic-ize it, use the `--no-deref` option directly after `update-ref`!
Weird, huh?

View file

@ -1 +0,0 @@
git update-ref --no-deref refs/fries "$BLOB2"

View file

@ -1,4 +0,0 @@
BLOB1=$(echo delicious | git hash-object -w --stdin)
BLOB2=$(echo very | git hash-object -w --stdin)
git update-ref refs/curly "$BLOB1"
git symbolic-ref refs/fries refs/curly

View file

@ -1,2 +0,0 @@
git symbolic-ref refs/fries && return 1
test "$(git show-ref -s refs/fries)" = "035e2968dafeea08e46e8fe6743cb8123e8b9aa6"

View file

@ -0,0 +1,35 @@
[description]
After carefully building the index we want, it would be nice to save a permanent snapshot of it, right?
This is what the second type of objects is for: trees! You can convert the index into a tree using
git write-tree
Try it! :)
[congrats]
Nice!
Can you make a different tree? Modify the index, then call `git write-tree` again!
[setup]
echo "file 1" > file1
echo "file 2" > file2
echo "file 3" > file3
git add .
[setup goal]
echo "file 1" > file1
echo "file 2" > file2
echo "file 3" > file3
git add .
git write-tree
[win]
git cat-file -p 21a638f28022064c1f1df20844278b494d197979

View file

@ -1,3 +0,0 @@
Nice!
Can you make a different tree? Modify the index, then call `git write-tree` again!

View file

@ -1,7 +0,0 @@
After carefully building the index we want, it would be nice to save a permanent snapshot of it, right?
This is what the second type of objects is for: trees! You can convert the index into a tree using
git write-tree
Try it! :)

View file

@ -1 +0,0 @@
git write-tree

View file

@ -1,4 +0,0 @@
echo "file 1" > file1
echo "file 2" > file2
echo "file 3" > file3
git add .

View file

@ -1 +0,0 @@
git cat-file -p 21a638f28022064c1f1df20844278b494d197979

View file

@ -1,3 +1,25 @@
[description]
Trees can also point to other trees! This way, they can describe nested directory structures.
When you add a file inside of a directory to the index, and then call `git write-tree`, it will create a nested tree for the directory, and attach the blob to it.
To solve this level, build a little stick figure, as shown on the left - a tree that points to two blobs, as well to a tree that points to two blobs.
[setup]
[setup goal]
echo "I'm the left arm" > arm1
echo "I'm the right arm" > arm2
mkdir hip
echo "I'm the left leg" > hip/leg1
echo "I'm the right leg" > hip/leg2
git add .
git write-tree
[win]
TREES=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep tree | cut -f1 -d" ") TREES=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | grep tree | cut -f1 -d" ")
for OUTER_TREE in $TREES; do for OUTER_TREE in $TREES; do

View file

@ -1,5 +0,0 @@
Trees can also point to other trees! This way, they can describe nested directory structures.
When you add a file inside of a directory to the index, and then call `git write-tree`, it will create a nested tree for the directory, and attach the blob to it.
To solve this level, build a little stick figure, as shown on the left - a tree that points to two blobs, as well to a tree that points to two blobs.

View file

@ -1,7 +0,0 @@
echo "I'm the left arm" > arm1
echo "I'm the right arm" > arm2
mkdir hip
echo "I'm the left leg" > hip/leg1
echo "I'm the right leg" > hip/leg2
git add .
git write-tree

View file

@ -0,0 +1,51 @@
[description]
As soon as you have some tree objects, you can always read them and set the index exactly to their content! Unsurprisingly, the command is called
git read-tree <tree>
For <tree>, you can provide the hash of any tree object - you can right-click one to insert its hash into the terminal!
Try reading some of the trees in this repository into the index!
[setup]
EMPTY_TREE=$(git write-tree)
echo "file 1" > file1
echo "file 2" > file2
git add .
git write-tree
rm *
echo "file A" > fileA
echo "file B" > fileB
echo "file C" > fileC
git add .
TRIPLE_TREE=$(git write-tree)
git read-tree "$EMPTY_TREE"
[setup goal]
EMPTY_TREE=$(git write-tree)
echo "file 1" > file1
echo "file 2" > file2
git add .
git write-tree
rm *
echo "file A" > fileA
echo "file B" > fileB
echo "file C" > fileC
git add .
TRIPLE_TREE=$(git write-tree)
git read-tree "$EMPTY_TREE"
git read-tree "$TRIPLE_TREE"
[win]
test "$(git ls-files | wc -l)" -gt 0

View file

@ -1,7 +0,0 @@
As soon as you have some tree objects, you can always read them and set the index exactly to their content! Unsurprisingly, the command is called
git read-tree <tree>
For <tree>, you can provide the hash of any tree object - you can right-click one to insert its hash into the terminal!
Try reading some of the trees in this repository into the index!

Some files were not shown because too many files have changed in this diff Show more