From a3c970405ab7c18868480f6a2c996e283ebca0d6 Mon Sep 17 00:00:00 2001 From: Ben Thayer Date: Sat, 8 Aug 2020 15:15:37 -0500 Subject: [PATCH 1/5] Added The Truth level --- gitgud/skills/rewriting/__init__.py | 1 + gitgud/skills/rewriting/_truth/details.yaml | 10 ++++++++++ gitgud/skills/rewriting/_truth/explanation.txt | 12 ++++++++++++ gitgud/skills/rewriting/_truth/goal.txt | 1 + gitgud/skills/rewriting/_truth/setup.spec | 6 ++++++ gitgud/skills/rewriting/_truth/solution.txt | 7 +++++++ gitgud/skills/rewriting/_truth/test.spec | 6 ++++++ 7 files changed, 43 insertions(+) create mode 100644 gitgud/skills/rewriting/_truth/details.yaml create mode 100644 gitgud/skills/rewriting/_truth/explanation.txt create mode 100644 gitgud/skills/rewriting/_truth/goal.txt create mode 100644 gitgud/skills/rewriting/_truth/setup.spec create mode 100644 gitgud/skills/rewriting/_truth/solution.txt create mode 100644 gitgud/skills/rewriting/_truth/test.spec diff --git a/gitgud/skills/rewriting/__init__.py b/gitgud/skills/rewriting/__init__.py index a3469a0c..5e4d407e 100644 --- a/gitgud/skills/rewriting/__init__.py +++ b/gitgud/skills/rewriting/__init__.py @@ -17,5 +17,6 @@ def status(self): 'Rewriting History', 'rewriting', [ + SentenceLevel('The Truth', 'truth', __name__) ] ) diff --git a/gitgud/skills/rewriting/_truth/details.yaml b/gitgud/skills/rewriting/_truth/details.yaml new file mode 100644 index 00000000..12cd0fd1 --- /dev/null +++ b/gitgud/skills/rewriting/_truth/details.yaml @@ -0,0 +1,10 @@ +'1': + message: This +'2': + message: is +'3': + message: an +'4': + message: easy +'5': + message: level diff --git a/gitgud/skills/rewriting/_truth/explanation.txt b/gitgud/skills/rewriting/_truth/explanation.txt new file mode 100644 index 00000000..8d423040 --- /dev/null +++ b/gitgud/skills/rewriting/_truth/explanation.txt @@ -0,0 +1,12 @@ +You've already seen some of the stuff "git rebase -i" can do. +"git rebase -i" can also be used to reoder commits. +>>> +When the editor opens, simply re-order the commits to be in the order you want them to be in. +On a technical level, Git is changing the parent of each of the commits. The order of the commits is determined by looking at the parents of each commit. +>>> +For this level, each commit has a single word message that are meant to come together to form the sentence "This is an easy level" when viewing them in chronological order. You are meant to put the commits in order and form that sentence. +>>> +You can see the commits in chronological order by running "git log --reversed". +Git normally tries to show you the most recent commit first since that's normally more useful. That's why you need the "--reversed" flag +>>> +Run "git rebase -i " for more details. It contains useful information diff --git a/gitgud/skills/rewriting/_truth/goal.txt b/gitgud/skills/rewriting/_truth/goal.txt new file mode 100644 index 00000000..f19949e3 --- /dev/null +++ b/gitgud/skills/rewriting/_truth/goal.txt @@ -0,0 +1 @@ +Using git rebase -i, make the log messages form the sentence "This is an easy level" diff --git a/gitgud/skills/rewriting/_truth/setup.spec b/gitgud/skills/rewriting/_truth/setup.spec new file mode 100644 index 00000000..d4a2bdf5 --- /dev/null +++ b/gitgud/skills/rewriting/_truth/setup.spec @@ -0,0 +1,6 @@ +1 +4 +3 +2 +5 (master) +master diff --git a/gitgud/skills/rewriting/_truth/solution.txt b/gitgud/skills/rewriting/_truth/solution.txt new file mode 100644 index 00000000..90b20afb --- /dev/null +++ b/gitgud/skills/rewriting/_truth/solution.txt @@ -0,0 +1,7 @@ +git checkout master~4 +git cherry-pick master~1 +git cherry-pick master~2 +git cherry-pick master~3 +git cherry-pick master +git branch -D master +git checkout -b master diff --git a/gitgud/skills/rewriting/_truth/test.spec b/gitgud/skills/rewriting/_truth/test.spec new file mode 100644 index 00000000..120e3a76 --- /dev/null +++ b/gitgud/skills/rewriting/_truth/test.spec @@ -0,0 +1,6 @@ +1 +2' +3' +4' +5' (master) +master From 9c502a02bfb9349cf54d44ed6143a37963d49afc Mon Sep 17 00:00:00 2001 From: Ben Thayer Date: Mon, 10 Aug 2020 00:50:06 -0500 Subject: [PATCH 2/5] Added content for The Truth --- gitgud/skills/rampup/__init__.py | 1 - .../skills/rampup/_detaching/explanation.txt | 18 -------- gitgud/skills/rampup/_detaching/goal.txt | 1 - gitgud/skills/rampup/_detaching/setup.spec | 5 -- gitgud/skills/rampup/_detaching/solution.txt | 4 -- gitgud/skills/rampup/_detaching/test.spec | 5 -- .../skills/rewriting/_truth/explanation.txt | 46 +++++++++++++++---- gitgud/skills/rewriting/_truth/goal.txt | 4 +- gitgud/test_commands.py | 6 +-- 9 files changed, 44 insertions(+), 46 deletions(-) delete mode 100644 gitgud/skills/rampup/_detaching/explanation.txt delete mode 100644 gitgud/skills/rampup/_detaching/goal.txt delete mode 100644 gitgud/skills/rampup/_detaching/setup.spec delete mode 100644 gitgud/skills/rampup/_detaching/solution.txt delete mode 100644 gitgud/skills/rampup/_detaching/test.spec diff --git a/gitgud/skills/rampup/__init__.py b/gitgud/skills/rampup/__init__.py index 845fc9ec..299b231a 100644 --- a/gitgud/skills/rampup/__init__.py +++ b/gitgud/skills/rampup/__init__.py @@ -5,7 +5,6 @@ 'Rampup', 'rampup', [ - BasicLevel("Detaching HEAD", 'detaching', __name__), BasicLevel("Relative References I: Using (^)", 'relrefs1', __name__), BasicLevel("Relative References II: Using (~)", 'relrefs2', __name__), BasicLevel("Reversing Changes in Git", 'reversing', __name__) diff --git a/gitgud/skills/rampup/_detaching/explanation.txt b/gitgud/skills/rampup/_detaching/explanation.txt deleted file mode 100644 index f35f9c8e..00000000 --- a/gitgud/skills/rampup/_detaching/explanation.txt +++ /dev/null @@ -1,18 +0,0 @@ -This skill will introduce the idea of detaching your HEAD! ->>> -Don't worry, we don't mean your head; we mean the head of your commit tree. First, what is the HEAD of a commit tree? ->>> -The HEAD is used to refer to the commit that is currently checked out. The HEAD is often used by git commands that make changes to the working tree. ->>> -The HEAD usually points to the commit that you are working on top of. Normally, the HEAD points to the branch that you have checked out. In this way, when bugFix is updated, HEAD is updated as well. -Example: HEAD -> bugFix -> C1 //HEAD points to bugFix. - HEAD -> bugFix -> C2 //A commit moved bugFix to C2, HEAD effectively points to C2 ->>> - What if we HEAD to point at a commit rather than a branch? - (e.g., HEAD -> C1 instead of HEAD -> bugFix -> C1) ->>> -In comes the concept of detaching HEAD. Simply use "git checkout " to modify HEAD so that it points to the commit instead of the branch. ->>> -The commit hash is a unique identifier for each commit node. Use "git gud show-tree" to see the git commit tree. The hashes look something like: "d6ba740...". Since each commit hash is unique, you only need to type the first four characters of the hash to refer to the commit. (e.g. "git checkout d6ba" will detach the HEAD onto the commit of that hash) ->>> -Congratulations! You've learned how to detach HEADs in git. Try using "git gud show-tree" to see how the HEAD changes before and after a detach. Use what you've learned to move the HEAD from master to commit 4. diff --git a/gitgud/skills/rampup/_detaching/goal.txt b/gitgud/skills/rampup/_detaching/goal.txt deleted file mode 100644 index bd32dfda..00000000 --- a/gitgud/skills/rampup/_detaching/goal.txt +++ /dev/null @@ -1 +0,0 @@ -Enter a detached head state by checking out commit 4 \ No newline at end of file diff --git a/gitgud/skills/rampup/_detaching/setup.spec b/gitgud/skills/rampup/_detaching/setup.spec deleted file mode 100644 index fcfb2482..00000000 --- a/gitgud/skills/rampup/_detaching/setup.spec +++ /dev/null @@ -1,5 +0,0 @@ -1 -2 : 1 (master) -3 : 1 -4 (bugFix) -master diff --git a/gitgud/skills/rampup/_detaching/solution.txt b/gitgud/skills/rampup/_detaching/solution.txt deleted file mode 100644 index 43815ac6..00000000 --- a/gitgud/skills/rampup/_detaching/solution.txt +++ /dev/null @@ -1,4 +0,0 @@ -# User would instead check out the commit hash using only one command -git checkout bugFix -git checkout @^ -git checkout @{1} \ No newline at end of file diff --git a/gitgud/skills/rampup/_detaching/test.spec b/gitgud/skills/rampup/_detaching/test.spec deleted file mode 100644 index 0030e139..00000000 --- a/gitgud/skills/rampup/_detaching/test.spec +++ /dev/null @@ -1,5 +0,0 @@ -1 -2 : 1 (master) -3 : 1 -4 (bugFix) -4 diff --git a/gitgud/skills/rewriting/_truth/explanation.txt b/gitgud/skills/rewriting/_truth/explanation.txt index 8d423040..9db43ca9 100644 --- a/gitgud/skills/rewriting/_truth/explanation.txt +++ b/gitgud/skills/rewriting/_truth/explanation.txt @@ -1,12 +1,42 @@ -You've already seen some of the stuff "git rebase -i" can do. -"git rebase -i" can also be used to reoder commits. +There's something you need to know about... >>> -When the editor opens, simply re-order the commits to be in the order you want them to be in. -On a technical level, Git is changing the parent of each of the commits. The order of the commits is determined by looking at the parents of each commit. +The truth is... >>> -For this level, each commit has a single word message that are meant to come together to form the sentence "This is an easy level" when viewing them in chronological order. You are meant to put the commits in order and form that sentence. +What you did with "git rebase -i"... >>> -You can see the commits in chronological order by running "git log --reversed". -Git normally tries to show you the most recent commit first since that's normally more useful. That's why you need the "--reversed" flag +Can be done by... >>> -Run "git rebase -i " for more details. It contains useful information +Detatching your head! Eek! +>>> +Let me clarify, I'm actually talking about your HEAD. +>>> +HEAD is used to refer to the commit or branch that is currently checked out. +This basically means that when you're on branch master, HEAD means master, which itself means a commit. +>>> +This is important because when you're in a 'detached HEAD' state, cherry-picking still works the same way, and you can do exactly what you just did in the last level. +>>> +Normally, HEAD points to the branch that you have checked out, so it refers to whichever commit the branch does, even if there is a new commit! +For example, if you have bugFix checked out, then when bugFix is updated, HEAD is updated as well, just like this: + + HEAD -> bugFix -> C1 // HEAD points to bugFix. + HEAD -> bugFix -> C2 // A commit moved bugFix to C2, HEAD effectively points to C2 + +For us, since no branches point to the first commit, we can't check it out while staying on a branch. +>>> +What if we HEAD to point at a commit rather than a branch? +(e.g., HEAD -> C1 instead of HEAD -> bugFix -> C1) +>>> +In comes the concept of the 'detached HEAD' state. Simply use "git checkout " to modify HEAD so that it points to the commit instead of the branch. +>>> +As you've seen, a commit hash is a unique identifier for a commit. +Use "git log" or "git gud status" to see the commit tree and to look for the hashes. +>>> +The hashes look something like: "d6ba740". +The full commit hash is 40 characters long, and every one is unique. +>>> +In general, if you only have a few commits, even just the first few characters of the commit hash are going to be unique, so you can use as few as the first four characters to refer to the commit. +Using the example has above "git checkout d6ba" will detach the HEAD so it refers to the commit with the hash "d6ba740" +>>> +Finally, to beat this level, you're going to need to check out the first commit (detaching HEAD) then cherry-pick the rest of the commits so they are in the right order. +Finish the job by making a new branch with the re-ordered commits. +It can be named anything, but don't check it out so we know you detached your HEAD! diff --git a/gitgud/skills/rewriting/_truth/goal.txt b/gitgud/skills/rewriting/_truth/goal.txt index f19949e3..a3f47f49 100644 --- a/gitgud/skills/rewriting/_truth/goal.txt +++ b/gitgud/skills/rewriting/_truth/goal.txt @@ -1 +1,3 @@ -Using git rebase -i, make the log messages form the sentence "This is an easy level" +Just like last level, make the log messages form the sentence "This is an easy level" +This time, instead of rebasing, detach HEAD using git checkout then use git cherry-pick. +Save your changes on a new branch named whatever you want, but don't check it out. diff --git a/gitgud/test_commands.py b/gitgud/test_commands.py index c454f930..05f584dd 100644 --- a/gitgud/test_commands.py +++ b/gitgud/test_commands.py @@ -8,10 +8,10 @@ def test_load(gg): load_tests = [ ('git gud load 1', all_skills["1"]["1"]), ('git gud load rampup', all_skills["rampup"]["1"]), - ('git gud load 2 detaching', all_skills["2"]["detaching"]), - ('git gud load rampup 4', all_skills["rampup"]["4"]), + ('git gud load 2 relrefs1', all_skills["2"]["relrefs1"]), + ('git gud load rampup 3', all_skills["rampup"]["3"]), ('git gud load 5-octopus', all_skills["5"]["octopus"]), - ('git gud load rampup-4', all_skills["rampup"]["4"]), + ('git gud load rampup-3', all_skills["rampup"]["3"]), ('git gud load -2', all_skills["rampup"]["2"]) ] From 45a10317097bff53a73145fd96dd9b3fe1d2bc9c Mon Sep 17 00:00:00 2001 From: Ben Thayer Date: Wed, 12 Aug 2020 17:15:38 -0500 Subject: [PATCH 3/5] Updated The Truth levels per review --- gitgud/skills/rewriting/_truth/details.yaml | 15 +++++++++++++++ gitgud/skills/rewriting/_truth/explanation.txt | 15 ++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/gitgud/skills/rewriting/_truth/details.yaml b/gitgud/skills/rewriting/_truth/details.yaml index 12cd0fd1..457a37e2 100644 --- a/gitgud/skills/rewriting/_truth/details.yaml +++ b/gitgud/skills/rewriting/_truth/details.yaml @@ -1,10 +1,25 @@ '1': message: This + add-files: + This.txt: + - "Hello, this file doesn't do anything." '2': message: is + add-files: + is.txt: + - "Hello, this file doesn't do anything." '3': message: an + add-files: + an.txt: + - "Hello, this file doesn't do anything." '4': message: easy + add-files: + easy.txt: + - "Hello, this file doesn't do anything." '5': message: level + add-files: + level.txt: + - "Hello, this file doesn't do anything." diff --git a/gitgud/skills/rewriting/_truth/explanation.txt b/gitgud/skills/rewriting/_truth/explanation.txt index 9db43ca9..29fad693 100644 --- a/gitgud/skills/rewriting/_truth/explanation.txt +++ b/gitgud/skills/rewriting/_truth/explanation.txt @@ -11,20 +11,25 @@ Detatching your head! Eek! Let me clarify, I'm actually talking about your HEAD. >>> HEAD is used to refer to the commit or branch that is currently checked out. -This basically means that when you're on branch master, HEAD means master, which itself means a commit. +This basically means that when you're on branch "master", HEAD resolves to "master", which itself resolves to a commit. >>> This is important because when you're in a 'detached HEAD' state, cherry-picking still works the same way, and you can do exactly what you just did in the last level. >>> Normally, HEAD points to the branch that you have checked out, so it refers to whichever commit the branch does, even if there is a new commit! For example, if you have bugFix checked out, then when bugFix is updated, HEAD is updated as well, just like this: - HEAD -> bugFix -> C1 // HEAD points to bugFix. - HEAD -> bugFix -> C2 // A commit moved bugFix to C2, HEAD effectively points to C2 +// HEAD points to bugFix. +C1 +^ bugFix < HEAD + +// A new commit (C2) caused bugFix to move to C2, HEAD effectively points to C2 +C1 ---- C2 + ^ bugFix < HEAD For us, since no branches point to the first commit, we can't check it out while staying on a branch. >>> -What if we HEAD to point at a commit rather than a branch? -(e.g., HEAD -> C1 instead of HEAD -> bugFix -> C1) +What if we have HEAD to point at a commit rather than a branch? +(e.g., HEAD > C1 instead of HEAD > bugFix > C1) >>> In comes the concept of the 'detached HEAD' state. Simply use "git checkout " to modify HEAD so that it points to the commit instead of the branch. >>> From dceca8405e4a305e20f5d89b504b10184fd29cfe Mon Sep 17 00:00:00 2001 From: Ben Thayer Date: Fri, 11 Sep 2020 19:13:14 -0500 Subject: [PATCH 4/5] Get commits from detached head in level tree --- gitgud/operations.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gitgud/operations.py b/gitgud/operations.py index 0e440736..afa71496 100644 --- a/gitgud/operations.py +++ b/gitgud/operations.py @@ -278,6 +278,8 @@ def get_current_tree(self): commits = set() visited = set() + commits.add(repo.head.commit) + for branch in repo.branches: commits.add(branch.commit) commit_hash = branch.commit.hexsha From f68c1c31f4f2805e14d66179824ce6a8841f188a Mon Sep 17 00:00:00 2001 From: Ben Thayer Date: Fri, 11 Sep 2020 20:01:27 -0500 Subject: [PATCH 5/5] Detach head and check for new branch created --- gitgud/skills/rewriting/__init__.py | 18 +++++++++++++++++- gitgud/skills/rewriting/_truth/setup.spec | 2 ++ gitgud/skills/rewriting/_truth/solution.txt | 3 +-- gitgud/skills/rewriting/_truth/test.spec | 11 ++++++++--- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/gitgud/skills/rewriting/__init__.py b/gitgud/skills/rewriting/__init__.py index 5e4d407e..2bbbd7b7 100644 --- a/gitgud/skills/rewriting/__init__.py +++ b/gitgud/skills/rewriting/__init__.py @@ -1,3 +1,5 @@ +from gitgud import operations + from gitgud.skills.level_builder import BasicLevel from gitgud.skills.util import Skill @@ -13,10 +15,24 @@ def status(self): simulate_command('git log --reverse --oneline') +class Truth(SentenceLevel): + def _test(self): + if not super()._test(): + return False + + file_operator = operations.get_operator() + + for branch in file_operator.repo.branches: + if branch.commit == file_operator.repo.head.commit: + return True + + return False + + skill = Skill( 'Rewriting History', 'rewriting', [ - SentenceLevel('The Truth', 'truth', __name__) + Truth('The Truth', 'truth', __name__) ] ) diff --git a/gitgud/skills/rewriting/_truth/setup.spec b/gitgud/skills/rewriting/_truth/setup.spec index d4a2bdf5..b7eae34d 100644 --- a/gitgud/skills/rewriting/_truth/setup.spec +++ b/gitgud/skills/rewriting/_truth/setup.spec @@ -1,3 +1,5 @@ +# Commits here are out of order +# When the commits are in the correct order, they read "This is an easy level" 1 4 3 diff --git a/gitgud/skills/rewriting/_truth/solution.txt b/gitgud/skills/rewriting/_truth/solution.txt index 90b20afb..2f7bccfe 100644 --- a/gitgud/skills/rewriting/_truth/solution.txt +++ b/gitgud/skills/rewriting/_truth/solution.txt @@ -3,5 +3,4 @@ git cherry-pick master~1 git cherry-pick master~2 git cherry-pick master~3 git cherry-pick master -git branch -D master -git checkout -b master +git branch random-branch-name diff --git a/gitgud/skills/rewriting/_truth/test.spec b/gitgud/skills/rewriting/_truth/test.spec index 120e3a76..8d65cc46 100644 --- a/gitgud/skills/rewriting/_truth/test.spec +++ b/gitgud/skills/rewriting/_truth/test.spec @@ -1,6 +1,11 @@ +# The commits on master and in setup.spec are out of order 1 -2' +4 +3 +2 +5 (master) +2' : 1 3' 4' -5' (master) -master +5' +5'