Git Game v2: Copying and Pasting From Stack Overflow

文章目录

这是 git-game 的第二版,也就是 git-game-v2,关于 git-game 的那篇在这里,两篇文章的基本格式是一样的

首先还是 clone Repo 并转到对应目录下:

$ git clone https://github.com/git-game/git-game-v2.git
$ cd git-game-v2

在 Level 1 开始首先查看 README.md 的提示,在每次操作后应该再次查看这个文件确认是否到达了下一个 Level 并且按照提示继续游戏,即:

$ cat README.md

文章格式约定

对于每一个 Level,首先是 <h3> 大小的标题,之后是关于这一个 Level 的简介,以两条分隔线作为和其他内容的区分,然后一堆 xjb 乱写最后用粗体的 Solution 和相关代码给出进入下一个 Level 的方式

Level 1


The first level demonstrates the power of git ls-files.
Running git ls-files lists all the files in the current commit.
Checkout the documentation for more details.
Can you figure out why running the standard Unix ls doesn't list all the files in the current commit?

Your task for this level is to use git ls-files to count the total number of lines in this commit.
In other words, count the number of lines in each file, then add all these numbers together to get the total.

To advance to level 2 you need to checkout the branch named after the total.
So if the total number is 780 then you would run:

$ git checkout 780

Hint: You will need to combine git ls-files with other Unix utilities using pipes.
This stackoverflow question has a useful example that will get you started.


emmmmm……需要用管道命令配合对 git ls-files 输出的所有文件计算行数并汇总,点击进入提供的 Stack Overflow Question 然后复制粘贴,运行:

$ git ls-files | xargs cat | wc -l

或者:

$ git ls-files | xargs wc -l

不过用第二个的方式显示的是所有的文件各自的行数以及总和,第一个仅显示最终的结果即一个数字:

6861

可知所有相关文件的行数和是 6861,然后转到以 6861 命名的分支进入 Level 2

Solution

$ git checkout 6861

Level 2


You're now in level 2! The purpose of this level is to show you the power of git show.
Running this command shows one or more objects (blobs, trees, tags and commits).
Look at the documentation for more details.

Your task for this level is to find the answer to the riddle below:

I have many keys but useless locks. I have space but no room. You can enter and also escape. What am I?

The answer to this riddle is in one of the commit messages.
Use git log to find the commit hash corresponding to the commit message.
Then run git show on that hash.
This will bring up instructions on how to proceed to level3.

Hint: if you're stuck, look at this stack overflow question.


要找到谜底对应的那个提交,谜底很容易想到,就是键盘 keyboard,查看提交记录

$ git log --pretty=oneline

可以看到 keyboard 对应的提交 ID 是 16a28de,再按照提示使用 git show 命令:

$ git show 16a28de

这里显示的是这次提交对应的修改内容,跟着给出的提示进入 snowden 分支,也就是 Level 3

Solution

$ git checkout snowden

Level 3


Congratulations on making it to level 3! So I see you have mastered the art of using git show.
Now in order to proceed to next level, you must find out who contributed the most to this branch!
You can do this by running a shorter version of the git log command.
Once you find out how to do this, checkout the branch name of this certain contributor.

We think git shortlog is pretty helpful in this situation, but that is just us!


运行:

$ git shortlog

查看输出并找到提交次数最多的 anon,然后进入同名分支

Solution

$ git checkout anon

Level 4


Looks like you know your stuff! I see you were able to find who contributed the most to the snowden branch!
On this level you will need to use a command that finds the most recent tag that is reachable from this current commit.
Once you find the name of the tag, checkout to it so you may advance.

To find the name of the tag, you will need the help of the git describe command.

Hint: If your output is word-0-676767, then you should only use word when you checkout to the next step.

Hint: When you arrive to the tag indicated, make sure to READ the README for further instructions.


运行:

$ git describe

查看最近一个 tag 的相关信息,可以看到显示的是 return-1005-g3a38b52,即最近一个 tag 是 return,那么还是按照提示 checkout 即可

$ git checkout return

查看一下 README:

Congratulations! You have found the tag that is closest to your current commit. To proceed to level 4 use the following command:

$ git checkout pretty

Solution

$ git checkout return
$ git checkout pretty

Level 5


Welcome to level 5.
This level isn’t as pretty as you might want it to be but it teaches a new way to view the log.
The objective is to find the options to pass into this command git log [<options>].
This link will help you in finding the options needed to pass into git log [<options>].
The options you are to pass will allow you to view the tree hashes of the tree object is in git repository.

Once you find the appropiate flags your next step is to use them to find the commit message associated with the tree hash 3331d0b.

After finding the correct commit message associated with the above hash, checkout the branch of the same name as the message.
It should only be one word!

Hint: There are many different flags that can be associated with git log. Outputting using pretty is most likely what you should be looking for.

Extra: If you want to further your understanding of git objects, you can read about how git stores these objects.


需要显示提交的 tree hash,用 pretty 格式化输出即可,根据文档可知参数 %tabbreviated tree hash%ssubject,为了找到对应的那个 hash,用管道命令配合 grep 匹配即可

$ git log --pretty=format:"%t %s" | grep 3331d0b

然后切换进入和输出的 commit message 同名的分支:

3331d0b SIGPOLL

Solution

$ git checkout SIGPOLL

Level 6


You made it to level 6! As you have just experienced, things will be slightly harder from now on.
Within this branch are four submodules.
Submodules allow foreign repositories to be embedded within a dedicated subdirectory of the source tree, always pointed at a particular commit.
In order to fill the directories you must use the git submodule command.

Once you fill the directories, the clue to the next level lies in the README.md of the submodule whose name is the answer to the riddle below.

I take your sleep away. I can script and create objects. I am both a language and the name of a bean. What am I?

The answer may be obvious but getting to the README.md is a bit more challenging.
Are you ready?
Begin!

Hint: you will need two submodule commands to correctly fill the directories.

Hint: the second answer to this stack overflow question may be of assistance if you are stuck.


首先谜底是 Java,然后再次复制粘贴运行 submodule 相关的命令 initupdate,进入子模块的目录并查看 README:

$ git submodule init Java
$ git submodule update Java

$ cd Java
$ cat README.md

进入目录查看输出如下:

You found me! Now if you want to get to the next level use cd .. and then use the command below:

$ git checkout history

Solution

$ git submodule init Java
$ git submodule update Java

$ cd Java
$ cat README.md
$ cd ..

$ git checkout history

Level 7


You made it to level 7! Awesome!!!

Are you ready for an even bigger git challenge? Yes? Okay!
It appears that a group of malicious hackers have hacked GitHub and deleted an important file in our repo.
This file contained the personal emails of Linus Torvalds, Richard Stallman, and the name of the next branch!
They also made hundreds commits after they deleted it so we can't look through the commit history by hand.
Now this is where you come in!

You must use git grep to search through the whole commit history to find these emails.
Your next clue is the name of the user that is before the domain name hint.edu.
When you find it checkout the branch name that shares this name.

For example, if the email was yahoo@hint.edu then you are to checkout the the branch called yahoo.

Hint: It's best to use git grep with git rev-list as specificied by this stack overflow question.

Hint: If you followed the link in the above hint, DO NOT use the --all option.


虽然不知道是些什么鬼但是当然还是可以直接复制粘贴啊!

$ git grep "@hint.edu" $(git rev-list --all)

需要比前面的命令稍微长一点的时间,大概不让加 --all 选项也是这个原因

不过其实最后给的总结里面写的,是这样的:

$ git grep "@hint" $(git rev-list history)

当然 history 也可以换成 HEAD

不管是用的哪种,结果还是都能看得到的,也就是 cherry

Solution

$ git checkout cherry

Level 8


You made it to level 8!
It appears you have gained a deeper knowledge of git grep!

But alas! The same malicious hackers have hidden the content of the next clue amidst the commits of two other branches.
Each of these commits has a file, one of which has the consonants of the next clue and the other has the vowels.
The hackers were nice enough to leave us with the following text:

The first branch is arachnid. The commit is four below its most recent commit

The second branch is insect. The commit is three below its most recent commit

In order to retrieve the two files containing the contents we will need to use the
git cherry-pick command. What this commands does is when given one or more existing commits, it applies the change each one introduces to our commit history,
recording a new commit for each one that was "cherry picked".

Your task is to first find out what commits to cherry pick, and then cherry pick them.
The note the hackers left should give you insight on where to find the two commits.
You can see an example of how to use git cherry-pick on this stack overflow question.

Important: In order for the command to work properly you must checkout to both the branches that contain the commits. Then checkout back to the cherry branch and cherry-pick accordingly.
Once you do this, you are to output the file contents properly using cat to see how the consonants and vowels combine,
The name of the next branch will be the output that you get. Checkout the branch to continue on your journey.

Hint: for outputting the files properly you would want to you do something like: cat consonants.txt && cat vowels.txt. The output of the above command may look a little weird at first, but remember it is one word!

Hint: HEAD is also a reference to the currently checked out commit of a branch, typically the most recent commit. (i.e. HEAD~1 means 1 below the HEAD of a current branch while master~1 means one below the HEAD of the master branch).


按照提供的分支名切换分支,然后找出对应的提交 ID

$ git checkout arachnid
$ git log --pretty=oneline

需要的第一个提交 ID 是 180fc7b,实际上也就是第一个名为 “HACKED” 的提交
再切回 cherry 分支用拿到的提交 ID 运行cherry-pick

$ git checkout cherry
$ git cherry-pick 180fc7b

同样的方法可以进行对另一个分支的操作,这次对应的提交 ID 是 b441b5b,最后查看两个文件的内容:

$ git checkout insect
$ git log --pretty=oneline

$ git checkout cherry
$ git cherry-pick b441b5b

$ cat consonants.txt && cat vowels.txt

提示信息为:

l ghth  s
 i    ou e

也就是一个存着辅音字母一个存着元音字母 = =
拼起来就是下一个分支名 lighthouse

Solution

$ git checkout lighthouse

Level 9


The hackers have finally left!
But before they escaped they ruined the lyrics of our favorite song twinkle twinkle little star!
The hackers changed the lyrics of our favorite song from twinkle twinkle little star to racecar racecar little star.
Your task is as follows: use git bisect to repair the lyrics to their original format.
Since there are so many commits, we can use git bisect to find the bug by using a binary search on our commit history.

Note: Next, we recommend that you open a second terminal.

git bisect needs a starting point before the error was introduced since we need to know the bounds for the binary search. The first step is to initalize git bisect by typing in git bisect start which will begin the searching process.
Next, run the command git log --pretty=oneline --reverse | head -1. This will automatically give you the commit hash of the initial commit.
Then you should run git bisect good followed by the inital commit hash. This gives the first bound for the binary search.

Next run the following command in the second terminal: git log --pretty=oneline --reverse | tail -1. This gives you the commit hash of the most recent commit.
Then run git bisect bad followed by the commit hash of the most recent commit. This gives the second bound for the binary search.

At this point, git bisect will now execute the binary search traversing through history.
As you are traversing through the commits, cat the twinkle.txt file, if you see the words racecar within the file, type the command git bisect bad, indicating that the error is within this half of the commits.
If you do not see the words racecar and instead see twinkle, that represents a good commit since the error was not yet introduced before that point. You should type the command git bisect good.
If the twinkle.txt is not present and it's just the README.md in the directory, this represents a point in time that the file did not exist.
This means no error existed either, so therefore you would type in git bisect good.

Once git bisect gives you the message is the first bad commit, run the ls command.
If there is a file named message view its contents to proceed forth to glory!
If not, run git bisect reset and restart the process.

Hint: If you are still having trouble, here is a wonderful tutorial on how to use git bisect.


emmmm……用 git 提供的二分搜索 bisect 把小星星的歌词复原
按照给出的步骤照做:

$ git bisect start
$ git log --pretty=oneline --reverse | head -1
$ git bisect good 3942179

打开第二个终端,进入相同的目录下运行:

$ git log --pretty=oneline --reverse | tail -1
$ git bisect bad 662efa3

以上的两个 hash 都是由前一步的 log 命令输出的,head -1 对应第一次提交,tail -1 对应目前为止的最后一次提交

之后需要查看当前目录下的 twinkle.txt 文件,如果其中有 "racecar" 这个单词那么就输入 git bisect bad,如果没有这个词或者没有这个文件那么输入 git bisect good,直到给出 is the first bad commit 信息

实际上,可以在两个终端轮流重复以下过程实现这个二分搜索:

c=>start: Continue  
e=>end: End  
r=>end: Repeat  
cat=>operation: cmd-CAT  
good=>operation: cmd-GOOD  
bad=>operation: cmd-BAD  
match=>condition: cdt-Match  
msg=>condition: cdt-Show

c->cat->match  
match(yes)->bad  
match(no)->good  
bad->msg  
good->msg  
msg(yes)->e  
msg(no)->r  

流程图

这个图本来也是用 Markdown 写的……没想到 Ghost 竟然不滋瓷渲染流程图……这是坠痛苦的

其中三个简写的 commad 对应的完整命令如下:

$ cat twinkle.txt | grep racecar #cmd-CAT

$ git bisect bad #cmd-BAD

$ git bisect good #cmd-GOOD

而两个简写的 condition 意义分别是:

  • cdt-Match:cmd-CAT 运行后是否匹配到文件中的文本

  • cdt-Show:cmd-BADcmd-GOOD 运行后是否显示 "is the first bad commit"

进入 Repeat 以后应该是换另一个终端重复操作,在 shell 里按上方向键找到所需命令回车即可

最后进入 End,即 bisect 显示了以下信息:

fd8673785769f62b1dca4e5bd480edfb0d87e995 is the first bad commit  
commit fd8673785769f62b1dca4e5bd480edfb0d87e995  
Author: Calvin Kwan <hkwan003@ucr.edu>  
Date:   Thu Jun 11 01:25:56 2015 -0700

      adding racecar

:100644 000000 99ab09b99f35add4d846db3b5c4954237625cd60 0000000000000000000000000000000000000000 D    message
:100644 100644 4858722748c9b056836ad6836b76482fc941d00f 5cca52987fd4394b23672d0d015213b7fdb3636f M    twinkle.txt
:000000 100644 0000000000000000000000000000000000000000 4858722748c9b056836ad6836b76482fc941d00f A    twinkle.txt-e

这个时候文件夹下应该有个 message 文件,内容如下:

Congratulations on using git bisect to find the error, checkout the root branch to cross the finish line

Solution

$ git checkout root

所以是到此结束了,查看此时的 README.md

The End

Wow, look at you! You completed git-game-v2 which means you are very good at git! If you are curious, below are the commands you should have used.

Level 1: $ git ls-files | xargs wc -l

Level 2: $ git show *commit hash*

Level 3: $ git shortlog

Level 4: $ git describe

Level 5: $ git log --pretty=format: ''tree hash: %t --> subject: %s''

Level 6: $ git submodule init #then $ git submodule update

Level 7: $ git grep "@hint" $(git rev-list history)

Level 8: $ git cherry-pick arachnid~4 insect~3

Level 9: $ git bisect Following the tutorial is best

We hope you learned a lot and will continue to learn more git! Thank you very much!

真 · 完结撒花~

这个版本相对于之前那个就有些难度了,不过大部分按照 README 操作还是没问题的,实在不行就 Copying and Pasting From Stack Overflow 嘛