Git 闯关游戏——githug

学习Git过程中缺乏实践?不如来玩一玩这款Git闯关游戏,通过git命令来闯关。玩着玩着就学会了Git,美滋滋!

githug

githug 是用Ruby开发为了帮助学习使用git的一个闯关游戏。和我之前推荐的学习Linux命令的Bandit游戏有点像。

其Github地址:https://github.com/Gazler/githug

安装过程也比较简单,首先安装好基本的Ruby环境(1.8.7)以上

因为国内可能会遇到用gem安装相关包因为https网络问题报错的情况,如果出现Unable to download data from https://rubygems.org/这样的报错信息

可以通过如下方式解决

1
2
sudo gem sources -r https://rubygems.org
sudo gem sources -a http://rubygems.org

当然安装完以后也别忘了设置回来

1
2
sudo gem sources -r http://rubygems.org
sudo gem sources -a https://rubygems.org

然后进行安装:

1
sudo gem install githug

安装完成以后运行githug会提示创建相关的文件夹,回复y就行了。

githug有4个基本命令:

1
2
3
4
play - 默认命令,查看当前状态和题目
hint - 给你当前level的一些提示
reset - 重新开始当前关卡
levels - 列出所有关卡

通过题解

有一些关卡比较简单,选取一些我觉得有点意思的关卡给出题解吧。

20 commit_in_futue

使用一个未来的时间作为提交,提交的时候指定–date选项,能够自定义提交的时间

1
2
3
4
5
6
$ git commit -m "future commit" --date=12.12.2018T22:00:00
[master (root-commit) 2f27bee] future commit
Date: Wed Dec 12 22:00:00 2018 +0800
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README

21 reset

git reset 常用来进行版本回推。要了解reset命令首先要了解git中的三棵树:
HEAD:是当前分支引用的指针,它总是指向该分支上的最后一次提交。 这表示 HEAD 将是下一次提交的父结点。
暂存区(Index):预期的下一次提交
工作区:git 实际管理的文件的目录

reset 命令以一种简单可预见的方式直接操纵三棵树,它做了三个基本操作:移动 HAED,重置索引,重置工作目录。实际上 reset 是以特定的顺序来重写三棵树,并在指定相应选项时停止:

  1. 移动 HEAD 分支的指向 (若指定了 –soft,则到此停止)
  2. 使索引看起来像 HEAD (–mixed,默认到此停止)
  3. 使工作目录看起来像索引 (若指定了 –hard,则进行这一步)
1
git reset to_commit_second.rb

22 reset_soft

使用 reset 命令的 –soft 选项

1
git reset --soft HEAD~

23 checkout_file

checkout 作用于文件的时候,会将文件从当前HEAD中检出,即让当前工作区的文件变成HEAD中的样子,命令格式为git checkout [-q] [<commit>] [--] <paths>...

1
git checkout config.rb

30 blame

可以通过 git blame 命令查看项目中具体哪一行代码是谁写的,什么时候引入的。

1
git blame config.rb

33 checkout_tag

检出到指定标签,通过checkout命令实现,能够创建一个临时分支指向tag所在的提交

1
git checkout v1.2

34 checkout_tag_over_branch

有的时候会遇到标签和分支的名字一样的情况,通过在前面添加前缀tags/来指定是tag的名字

1
git checkout tags/v1.2

35 branch_at

检出指定提交到一个新的命名分支

1
git checkout -b test_branch HEAD~

40 rebase

rebase命令可以用来整合来自不同分支

如上图所示,提取在 C4 中引入的补丁和修改,然后在 C3 的基础上再应用一次。在 Git 中,这种操作就叫做 变基

git rebase [<upstream> [<branch>] 命令将upstream的修改在branch上再应用一次

1
2
git checkout feature
git rebase master

41 rebase-onto

在对两个分支进行变基时,所生成的“重演”并不一定要在目标分支上应用,你也可以指定另外的一个分支进行应用。就像 从一个特性分支里再分出一个特性分支的提交历史 中的例子这样。

$ git rebase --onto master server client

以上命令的意思是:“取出 client 分支,找出处于 client 分支和 server 分支的共同祖先之后的修改,然后把它们在 master 分支上重演一遍”。

当master 和server 一致的时候,只需要写一个

1
git rebase --onto master wrong_branch

42 repack

git repack 对松散对象进行打包,凡是有引用关联的对象都被打在包里,未被关联的对象仍旧以松散对象的形式保存

1
git repack

43 cherry-pick

应用某一个提交的修改到当前分支

1
2
3
git checkout new-feature
git log
git cherry-pick ca32a6dac7b6f97975edbe19a4296c2ee7682f68

45 rename commit

当涉及提交修改时,应该想到 git rebase -i 命令,它接受可以一个参数(提交的哈希值),它将罗列出此提交之后的所有提交,将此提交作为一个root commit。用途为修改提交历史,其后跟一个某一条提交日志的哈希值,表示要修改这条日志之前的提交历史。

输入命令以后,会将提交从前到后显示。每一行的前面有一个命令词,表示对此次更新执行什么操作。

类似下面这种:

1
2
pick 06973a3 First coommit
pick 771b71d Second commit

前面的命令有以下几种:

  • “pick”,表示执行此次提交;
  • “reword”,表示执行此次提交,但要修改备注内容;
  • “edit”,表示可以修改此次提交,比如再追加文件或修改文件;
  • “squash”,表示把此次提交的内容合并到上次提交中,备注内容也合并到上次提交中;
  • “fixup”,和 “squash” 类似,但会丢弃掉此次备注内容;
  • “exec”,执行命令行下的命令;
  • “drop”,删除此次提交。

这一关是需要把第2次提交错误额comment修改过来,所以对第二次提交执行reword并修改备注就行了

46 squash

把多次修改合并成一次,这里用到的还是上面的git rebase -i的命令,只不过是将后面动作命令都变成squash

47 merge_squash

为了把分支的多次提交合并为主干上的一次提交,可以在merge命令后面加一个 squash 参数

git merge branch-name --squash

过关命令:

1
2
git merge long-feature-branch --squash
git commit -m "comment"

48 reorder

你提交了几次但是提交顺序多了,想把顺序换一下,这里用到的还是git rebase -i命令。需要把几次提交的顺序更换一下即可。

49 bisect

在程序持续迭代的过程中不免会引入 bug,除了定位 bug 的代码片断,我们还想知道 bug 是在什么时间被引入的,这时就可以借助 Git 提供的 bisect 工具来查找是哪次提交引入了 bug。bisect 是用二分法来查找的,就像用二分查找法查找数组元素那样。

其查找流程也比较简单,首先确定查找的commit范围,然后在每一次二分查找时给出程序执行是否正确的判断。这个时候bisect就会自动进行二分查找。

1
2
3
4
5
6
$ git bisect start
$ git bisect good f608824888b
$ git bisect bad 12628f463f4
$ make test
$ git bisect good
...

50 stage_lines

git add 命令可以把文件添加到暂存区,但如果你不想把文件中的全部修改都提交到暂存区,或者说你只想把文件中的部分修改提交到缓存区,那么你需要加上edit参数

这时 Git 会自动打开文本编辑器,编辑的内容就是 git diff 命令的结果,这时你就可以编辑2个文件之间的差异,只保留要提交到暂存区的差异,而删除不需要提交到暂存区的差异,然后保存退出,Git 就会按你编辑过的差异把相应的内容提交到暂存区。

1
git add file-name --edit

51 find_old_branch

使用git reflog 可以查看历史所在的分支和提交在哪里

52 revert

参考