mirror of
https://github.com/git-learning-game/oh-my-git.git
synced 2024-12-22 20:32:38 +01:00
Rework levels, and add some new ones
This commit is contained in:
parent
931e9b3beb
commit
35b4dc098a
47 changed files with 163 additions and 39 deletions
|
@ -9,3 +9,7 @@ Let's create some blobs! To do that, create a file with the desired content, and
|
|||
The flag -w means "write", and tells Git to actually write the new blob to the disk.
|
||||
|
||||
Create three new blobs!
|
||||
|
||||
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
|
||||
|
|
5
levels/blob-remove/description
Normal file
5
levels/blob-remove/description
Normal file
|
@ -0,0 +1,5 @@
|
|||
There's a simple command to remove all blobs that are not connected to anything:
|
||||
|
||||
$ git prune
|
||||
|
||||
Remove all blobs in this repository.
|
1
levels/blob-remove/goal
Normal file
1
levels/blob-remove/goal
Normal file
|
@ -0,0 +1 @@
|
|||
git prune
|
3
levels/blob-remove/start
Normal file
3
levels/blob-remove/start
Normal file
|
@ -0,0 +1,3 @@
|
|||
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
|
3
levels/blob-remove/win
Normal file
3
levels/blob-remove/win
Normal file
|
@ -0,0 +1,3 @@
|
|||
OBJECT_COUNT=$(git cat-file --batch-check='%(objectname) %(objecttype)' --batch-all-objects | wc -l)
|
||||
|
||||
test "$OBJECT_COUNT" -eq 0
|
|
@ -2,4 +2,6 @@ When using the commit-tree command, you can optionally specify a parent:
|
|||
|
||||
$ git commit-tree <tree> -m "Description" -p <parent commit>
|
||||
|
||||
Can you make a string of three commits? We placed an empty tree in your repo to get you started.
|
||||
Make a string of three commits!
|
||||
|
||||
Hint: What would be the easiest way to get a tree object?
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
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/')
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
git write-tree
|
10
levels/index-add/description
Normal file
10
levels/index-add/description
Normal file
|
@ -0,0 +1,10 @@
|
|||
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 permissions.
|
||||
|
||||
Even though it is possible to add an entry directly to the index, it's much more convenient to do it 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"?
|
4
levels/index-add/goal
Normal file
4
levels/index-add/goal
Normal file
|
@ -0,0 +1,4 @@
|
|||
echo "file 1" > file1
|
||||
echo "file 2" > file2
|
||||
echo "file 3" > file3
|
||||
git add .
|
0
levels/index-add/start
Normal file
0
levels/index-add/start
Normal file
1
levels/index-add/win
Normal file
1
levels/index-add/win
Normal file
|
@ -0,0 +1 @@
|
|||
test "$(git ls-files | wc -l)" -ge 3
|
5
levels/index-remove/description
Normal file
5
levels/index-remove/description
Normal file
|
@ -0,0 +1,5 @@
|
|||
To remove an entry from the index, use a command like this:
|
||||
|
||||
$ git update-index --force-remove <file>
|
||||
|
||||
Remove all entries from the index!
|
3
levels/index-remove/goal
Normal file
3
levels/index-remove/goal
Normal file
|
@ -0,0 +1,3 @@
|
|||
git update-index --force-remove file1
|
||||
git update-index --force-remove file2
|
||||
git update-index --force-remove file3
|
4
levels/index-remove/start
Normal file
4
levels/index-remove/start
Normal file
|
@ -0,0 +1,4 @@
|
|||
echo "file 1" > file1
|
||||
echo "file 2" > file2
|
||||
echo "file 3" > file3
|
||||
git add .
|
1
levels/index-remove/win
Normal file
1
levels/index-remove/win
Normal file
|
@ -0,0 +1 @@
|
|||
test "$(git ls-files | wc -l)" -eq 0
|
9
levels/index-update/description
Normal file
9
levels/index-update/description
Normal file
|
@ -0,0 +1,9 @@
|
|||
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!
|
2
levels/index-update/goal
Normal file
2
levels/index-update/goal
Normal file
|
@ -0,0 +1,2 @@
|
|||
echo "new content" > file1
|
||||
git update-index file1
|
4
levels/index-update/start
Normal file
4
levels/index-update/start
Normal file
|
@ -0,0 +1,4 @@
|
|||
echo "file 1" > file1
|
||||
echo "file 2" > file2
|
||||
echo "file 3" > file3
|
||||
git add .
|
1
levels/index-update/win
Normal file
1
levels/index-update/win
Normal file
|
@ -0,0 +1 @@
|
|||
test "$(git ls-files | wc -l)" -eq 0
|
|
@ -1,9 +1,9 @@
|
|||
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.
|
||||
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 start a ref's name with "refs/"! That's a convention that helps Git find all refs you create.
|
||||
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!
|
||||
|
|
5
levels/ref-move/description
Normal file
5
levels/ref-move/description
Normal file
|
@ -0,0 +1,5 @@
|
|||
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!
|
3
levels/ref-move/goal
Normal file
3
levels/ref-move/goal
Normal file
|
@ -0,0 +1,3 @@
|
|||
for REF in $(git for-each-ref --format='%(refname)'); do
|
||||
git update-ref "$REF" "$TREE"
|
||||
done
|
10
levels/ref-move/start
Normal file
10
levels/ref-move/start
Normal file
|
@ -0,0 +1,10 @@
|
|||
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"
|
1
levels/ref-move/win
Normal file
1
levels/ref-move/win
Normal file
|
@ -0,0 +1 @@
|
|||
test "$(git show-ref -s | uniq)" = "c7863f72467ed8dd44f4b8ffdb8b57ca7d91dc9e"
|
5
levels/ref-remove/description
Normal file
5
levels/ref-remove/description
Normal file
|
@ -0,0 +1,5 @@
|
|||
To delete a ref, use
|
||||
|
||||
git update-ref -d refs/<refname>
|
||||
|
||||
Delete all refs! :P
|
3
levels/ref-remove/goal
Normal file
3
levels/ref-remove/goal
Normal file
|
@ -0,0 +1,3 @@
|
|||
for REF in $(git for-each-ref --format='%(refname)'); do
|
||||
git update-ref -d "$REF"
|
||||
done
|
10
levels/ref-remove/start
Normal file
10
levels/ref-remove/start
Normal file
|
@ -0,0 +1,10 @@
|
|||
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"
|
1
levels/ref-remove/win
Normal file
1
levels/ref-remove/win
Normal file
|
@ -0,0 +1 @@
|
|||
test "$(git show-ref | wc -l)" -eq 0
|
|
@ -4,6 +4,4 @@ When that happens, they are called "symbolic refs". You can create or update a s
|
|||
|
||||
git symbolic-ref <name> <ref>
|
||||
|
||||
Usually, you will only encounter a special symbolic ref called "HEAD". This ref is special in that it doesn't start with "refs/"! You might already have seen it in the other levels - it's the only thing that's always there!
|
||||
|
||||
Try pointing HEAD to the refs in this repository!
|
||||
Create a symbolic ref called "refs/rainbow"!
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
git symbolic-ref HEAD refs/best_commit
|
||||
BLOB=$(git hash-object -w --stdin)
|
||||
git update-ref refs/double "$BLOB"
|
||||
git symbolic-ref refs/rainbow refs/double
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
TREE=$(git write-tree)
|
||||
COMMIT=$(git commit-tree $TREE -m "Initial commit")
|
||||
git update-ref refs/best_commit $COMMIT
|
||||
git update-ref refs/worst_commit $COMMIT
|
|
@ -1 +1 @@
|
|||
git symbolic-ref HEAD | grep _commit
|
||||
git symbolic-ref refs/rainbow
|
||||
|
|
7
levels/symref-no-deref/description
Normal file
7
levels/symref-no-deref/description
Normal file
|
@ -0,0 +1,7 @@
|
|||
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?
|
1
levels/symref-no-deref/goal
Normal file
1
levels/symref-no-deref/goal
Normal file
|
@ -0,0 +1 @@
|
|||
git update-ref --no-deref refs/fries "$BLOB2"
|
4
levels/symref-no-deref/start
Normal file
4
levels/symref-no-deref/start
Normal file
|
@ -0,0 +1,4 @@
|
|||
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
|
2
levels/symref-no-deref/win
Normal file
2
levels/symref-no-deref/win
Normal file
|
@ -0,0 +1,2 @@
|
|||
git symbolic-ref refs/fries && exit 1
|
||||
test "$(git show-ref -s refs/fries)" = "035e2968dafeea08e46e8fe6743cb8123e8b9aa6"
|
|
@ -1,21 +1,7 @@
|
|||
Blobs just have some content and an ID. It would be convenient to be able to give names to a blob, right?
|
||||
After carefully building the index we want, it would be nice to save a permanent snapshot of it, right?
|
||||
|
||||
The second type of Git object is called a "tree" - a tree points a bunch of blobs, and gives each of them a name!
|
||||
|
||||
How can we build our own trees? Introducing: the index!
|
||||
|
||||
The index is like a "work in progress" version of a tree, where we can add and remove blobs. When we're happy with what we have built, we can make it into a real tree object!
|
||||
|
||||
We can use
|
||||
|
||||
$ git update-index --add <file>
|
||||
|
||||
to make the file's content into a blob, and to add that blob to the index using the file's name.
|
||||
|
||||
When we're happy with out index, we can convert it into a tree using
|
||||
This is what the second type of objects is for: trees! You can convert the index into a tree using
|
||||
|
||||
$ git write-tree
|
||||
|
||||
That command will output the ID of the newly crated tree.
|
||||
|
||||
Build a tree containing just the 'noises' file, which we conveniently placed in your current directory! :)
|
||||
Try it! :)
|
||||
|
|
|
@ -1,5 +1 @@
|
|||
git update-index --add noises
|
||||
git write-tree
|
||||
|
||||
rm noises
|
||||
git update-index --remove noises
|
||||
|
|
|
@ -1 +1,4 @@
|
|||
echo 'meow' > noises
|
||||
echo "file 1" > file1
|
||||
echo "file 2" > file2
|
||||
echo "file 3" > file3
|
||||
git add .
|
||||
|
|
|
@ -1 +1 @@
|
|||
git cat-file -p c099013035060f20e8d8f5db69e158213fbec519
|
||||
git cat-file -p 21a638f28022064c1f1df20844278b494d197979
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Trees can also point to other trees! This way, they can basically describe nested directory structures.
|
||||
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 automatically do the correct thing.
|
||||
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, and to a tree that points to two blobs.
|
||||
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.
|
||||
|
|
5
levels/tree-read/description
Normal file
5
levels/tree-read/description
Normal file
|
@ -0,0 +1,5 @@
|
|||
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>
|
||||
|
||||
Try switching between the trees in this repository!
|
1
levels/tree-read/goal
Normal file
1
levels/tree-read/goal
Normal file
|
@ -0,0 +1 @@
|
|||
git read-tree "$TRIPLE_TREE"
|
15
levels/tree-read/start
Normal file
15
levels/tree-read/start
Normal file
|
@ -0,0 +1,15 @@
|
|||
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"
|
1
levels/tree-read/win
Normal file
1
levels/tree-read/win
Normal file
|
@ -0,0 +1 @@
|
|||
test "$(git ls-files | wc -l)" -gt 0
|
7
levels/welcome/description
Normal file
7
levels/welcome/description
Normal file
|
@ -0,0 +1,7 @@
|
|||
To the left, you see an empty Git repository!
|
||||
|
||||
The only thing that's always there is the HEAD reference - we'll look at what that is later.
|
||||
|
||||
You can drag and drop all nodes on the left, and reorder them how you want!
|
||||
|
||||
You can enter Bash commands in the line at the bottom.
|
Loading…
Reference in a new issue