diff --git a/levels/sequence b/levels/sequence index 9a16a07..8d87994 100644 --- a/levels/sequence +++ b/levels/sequence @@ -1,4 +1,5 @@ stash index +shit-happens time-machine low-level diff --git a/levels/shit-happens/bad-commit b/levels/shit-happens/bad-commit new file mode 100644 index 0000000..10669be --- /dev/null +++ b/levels/shit-happens/bad-commit @@ -0,0 +1,30 @@ +title = Undo a bad commit +cards = reset commit-a + +[description] + +Oh no, we made a bad commit! How can we undo making the commit, and go back to a point where we can try again? + +The answer is using `git reset [commit]`, which does two things: + +- It resets the current branch ref to the commit you specify. +- And it resets the index to that commit. + +It does not change your working directory in any way, which means that after that, you can try making the commit you want again. + +[setup] + +echo "1 2 3 4" > numbers +git add . +git commit -m "Initial commit" +echo "1 2 3 4 5 6 7 8 9 11" > numbers +git commit -am "More numberrrrrs" + +[win] + +# In the last main commit, the numbers file contains the numbers from 1 to 10. +test "$(git show main:numbers)" = "1 2 3 4 5 6 7 8 9 10" +# The commit message of that commit is "More numbers". +git log -1 --oneline | grep "More numbers" +# The commit with the typo is not part of the main branch anymore. +git log --oneline | grep -v "rrrrr" diff --git a/levels/shit-happens/pushed-something-broken b/levels/shit-happens/pushed-something-broken new file mode 100644 index 0000000..f8dce38 --- /dev/null +++ b/levels/shit-happens/pushed-something-broken @@ -0,0 +1,54 @@ +title = I pushed something broken +cards = revert push + +[description] + +We were talking about how to undo a commit, and fix it. This only helps when you haven't already pushed it to a remote. When that has happened, and you want to undo the effects of the commit completely, your best option is `git revert` + +[setup] + +echo "this is fine + +? + +? + +?" > text +git add . +git commit -m fine +echo "this is fine + +this is also fine + +? + +?" > text +git commit -am "also fine" +echo "this is fine + +this is also fine + +this is very bad + +?" > text +git commit -am "very bad" +echo "this is fine + +this is also fine + +this is very bad + +this is fine again" > text +git commit -am "fine again" + +git push team main +git branch -u team/main main + +[setup team] + +[win team] + +# The team's main branch no longer contains the bad thing. +! { git show main:text | grep -q "very bad"; } +# And the history has not been modified. +git show main^:text | grep -q "very bad" diff --git a/levels/shit-happens/reflog b/levels/shit-happens/reflog new file mode 100644 index 0000000..e21c4e7 --- /dev/null +++ b/levels/shit-happens/reflog @@ -0,0 +1,26 @@ +title = Go back to where you were before +cards = checkout reflog + +[description] + +Say you were looking at something in the past, and then switched back to the main branch. + +But then, you got reaaally distracted, and after your lunch break, you can't remember on which commit in the past you were before. How can you find out? + +There's a convenient command that shows you all the places your HEAD did point to in the past: + + git reflog + +[setup] + +for i in {1..10}; do + git commit --allow-empty -m $i + git branch $i +done +git checkout 3 +git checkout main + +[win] + +# Find out where you've been before, and go back there! +test "$(git rev-parse HEAD)" = "$(git rev-parse 3)" diff --git a/levels/shit-happens/restore-a-file b/levels/shit-happens/restore-a-file new file mode 100644 index 0000000..b51c108 --- /dev/null +++ b/levels/shit-happens/restore-a-file @@ -0,0 +1,21 @@ +title = Restore a file from the past +cards = checkout checkout-from commit + +[description] + +Here's a similar problem: you really liked the essay from the very first commit, and want to have it back! Well, checkout can also restore things from older commits, Here's how: + + git checkout [commit] [file] + +[setup] + +echo "good version" > essay +git add . +git commit -m "Initial commit" +echo "bad version" > essay +git commit -am "\"Improve\" essay" + +[win] + +# Get the first version of your essay, and make a new commit with it. +test "$(git show main:essay)" = "good version" diff --git a/levels/shit-happens/restore-a-file-from-the-past b/levels/shit-happens/restore-a-file-from-the-past new file mode 100644 index 0000000..17f74be --- /dev/null +++ b/levels/shit-happens/restore-a-file-from-the-past @@ -0,0 +1,22 @@ +title = Restore a deleted file +cards = checkout + +[description] + +Oops - you deleted the "essay" file, which you worked on all night! + +Luckily, Git is here to help! You can use `git checkout` to restore the file! + +[setup] + +echo important > essay +git add . +git commit -m "Initial commit" +echo "important content" > essay +git commit -am "Improve essay" +rm essay + +[win] + +# Make changes to all three files, and add all of them to the index. +test "$(cat essay)" = "important content" diff --git a/resources/cards.json b/resources/cards.json index f86aed1..4dfea4b 100644 --- a/resources/cards.json +++ b/resources/cards.json @@ -9,6 +9,11 @@ "command": "git checkout [commit, ref, file]", "description": "Drag this card to a commit or to a branch to travel to it!\n\nAlternatively, reset changes in a local file." }, + { + "id": "checkout-from", + "command": "git checkout [commit, ref] [file]", + "description": "Get the file contents from the specified commits, and reset both the working directory, as well as the index, to it." + }, { "id": "commit-a", "command": "git commit -a", @@ -64,6 +69,11 @@ "command": "git cherry-pick [commit]", "description": "Repeat the specified action on top of your current timeline." }, + { + "id": "revert", + "command": "git revert [commit]", + "description": "Make a new commit that reverts the changes of the speicified commit." + }, { "id": "bisect-start", "command": "git bisect start", @@ -114,6 +124,11 @@ "command": "git branch -D [ref]", "description": "Delete a branch." }, + { + "id": "reflog", + "command": "git reflog [ref, head]", + "description": "Display a log of there the ref pointed to in the past." + }, { "id": "file-new", "command": "touch [string]",