Github我知道是什么姚糊,那么Githug這又是個啥?其實Githug是一個練習(xí)Git技能的命令行游戲,這里是它的GitHub倉庫铺根。
安裝方法
Github需要事先安裝Ruby 1.8.7+障涯,Ubuntu自帶的Ruby版本就是1.9.3罐旗,所以可以直接通過以下命令安裝膳汪。Windows系統(tǒng)或者M(jìn)ac系統(tǒng)的小伙伴可以查看上述GitHub地址,來獲取更加詳細(xì)的安裝方法九秀。
$ gem install githug
安裝完成后遗嗽,到你想要的目錄下,輸入githug
命令鼓蜒,按要求創(chuàng)建一個git_hug目錄痹换,進(jìn)入該目錄,即可開始游戲都弹。
游戲命令
- play 默認(rèn)命令晴音,檢查是否過關(guān)
- hint 提示
- reset 重置本關(guān)或到其他關(guān)
- levels 查看所有關(guān)卡
通過git levels
發(fā)現(xiàn)一共有55關(guān),真是任重而道遠(yuǎn)啊缔杉。
攻略
init
一個新的目錄'git_hug'被創(chuàng)建成功锤躁,要求初始化該目錄為一個倉庫。
$ git init
config
設(shè)置自己在Git中的名字和Email或详,這十分重要系羞,因為它們被用來標(biāo)識你的提交。
$ git config user.name 'sonack'
$ git config user.email 'my_email@qq.com'
也可以加上"--global"參數(shù)來全局設(shè)定霸琴。
add
在你的目錄中有一個叫做"README"的文件椒振,你應(yīng)該把它添加到你的暫存區(qū)(staging area)中,
$ git add README
commit
"README"文件已經(jīng)被加入你的暫存區(qū)中梧乘,現(xiàn)在提交(commit)它澎迎!
$ git commit -m 'add a README'
clone
克隆倉庫 https://github.com/Gazler/cloneme
$ git clone https://github.com/Gazler/cloneme
clone_to_folder
克隆倉庫 https://github.com/Gazler/cloneme 到 'my_cloned_repo'中。
$ git clone https://github.com/Gazler/cloneme my_cloned_repo
ignore
vim編輯器為所有當(dāng)前打開的文件都生成了以".swp"結(jié)尾的交換文件选调,我們不希望它們污染我們的倉庫夹供,讓這個倉庫忽略".swp"文件。
$ echo "*.swp" >> .gitignore
".gitignore"文件定義了忽略文件的規(guī)則仁堪。
include
注意到一些文件以".a"為后綴名哮洽,我們想要git忽略除了"lib.a"之外的所有".a"文件。
$ echo '!lib.a' >> .gitignore
$ echo '*.a' >> .gitignore
status
倉庫中有一些文件弦聂,其中之一沒有被Git跟蹤管理(untracked)鸟辅,找出它來!
$ git status
發(fā)現(xiàn)database.yml
沒有被跟蹤莺葫。
number_of_files_committed
倉庫中有一些文件匪凉,有多少文件會被提交(commit)呢?
$ git status
發(fā)現(xiàn)有兩個文件要被提交捺檬。
rm
一個文件已經(jīng)從工作區(qū)中被刪除了再层,但它還沒有從倉庫中刪除,找到這個文件并徹底刪除它!
$ git status
$ git add .
$ git commit -m '刪除'
或者使用git rm .
也可树绩。
rm_cached
一個文件無意間被添加進(jìn)了你的暫存區(qū)中萨脑,找出它并將它從暫存區(qū)中移出。
$ git rm --cached deleteme.rb
因為是初始提交饺饭,所以使用git rm
渤早,否則一般使用git reset HEAD
。
stash
你已經(jīng)做了一些更改瘫俊,然后想以后再繼續(xù)工作鹊杖。你應(yīng)該保存它們,但不要提交扛芽。
$ git stash
rename
我們有一個叫做"oldfile.txt"的文件骂蓖,現(xiàn)在我們想要重命名它為"newfile.txt"并且存儲這次改變。
$ git mv oldfile.txt newfile.txt
自動處于staged狀態(tài)川尖。
restructure
你在倉庫中添加了幾個文件登下,但是現(xiàn)在卻意識到你的工程需要重新組織結(jié)構(gòu)。創(chuàng)建一個新文件夾"src"叮喳,并使用Git來移動所有".html"文件到"src"中被芳。
$ mkdir src
$ git mv *.html src
使用git mv
來重命名或者移動文件。
log
最近提交的hash值是多少馍悟?為此你可能需要查看log信息畔濒。
$ git log --pretty=format:"%h" -1
tag
我們現(xiàn)在有一個Git倉庫,我們想給當(dāng)前提交加上一個標(biāo)簽“new_tag”锣咒。
$ git tag new_tag
默認(rèn)標(biāo)簽就是加在最新提交上的侵状。
push_tags
當(dāng)前分支有一些還沒有推送到遠(yuǎn)程倉庫的tags,現(xiàn)在推送它們毅整。
$ git push origin --tags
一次性推送所有尚未推送的本地標(biāo)簽到遠(yuǎn)程倉庫趣兄。
commit_amend
"README"文件已經(jīng)被提交了,但是似乎"forgotten_file.rb"被忘記提交了毛嫉。添加上這個文件诽俯,然后修正你的上一次提交,將它也提交進(jìn)去承粤。
$ git add forgotten_file.rb
$ git commit --amend
commit_in_future
以一個未來的日期來提交你的更改(比如,明天)闯团。
$ git commit --date="2099-9-1"
reset
有兩個文件要被提交辛臊,我們想單獨(dú)提交它們,然而它們卻意外地都被添加到了index中房交,利用reset命令先將文件"to_commit_second.rb"從index中撤出(注意不要commit)彻舰。
$ git reset HEAD to_commit_second.rb
reset_soft
你剛剛提交了不久,現(xiàn)在你想要撤銷最后一次提交,但是保留index中的內(nèi)容刃唤。
$ git reset --soft HEAD^
checkout_file
一個文件已經(jīng)被修改了隔心,但是你不想保留這次更改。將"config.rb"文件從上一次提交中checkout尚胞。
$ git checkout -- config.rb
remote
項目有一個遠(yuǎn)程倉庫硬霍,找出它。
$ git remote
發(fā)現(xiàn)遠(yuǎn)程倉庫的名字是"my_remote_repo"笼裳。
remote_url
遠(yuǎn)程倉庫有其相關(guān)聯(lián)的URL唯卖,請輸入遠(yuǎn)程倉庫"remote_location"的URL地址。
$ git remote -v
發(fā)現(xiàn)"remote_location"的URL是https://github.com/githug/not_a_repo躬柬。
pull
你需要從origin遠(yuǎn)程倉庫拉取更新拜轨。
$ git pull origin master
remote_add
添加一個叫作"origin"的遠(yuǎn)程倉庫,URL地址是https://github.com/githug/githug允青。
$ git remote add origin https://github.com/githug/githug
push
你的本地"master"分支和遠(yuǎn)程"origin/master"分支分叉了橄碾,在"origin/master"的基礎(chǔ)上rebase你的commit,然后推送到遠(yuǎn)端。
$ git rebase origin/master
$ git push origin master
有關(guān)rebase的詳細(xì)內(nèi)容颠锉,請參閱博文<a href="">git rebase的用法</a>法牲。
diff
自從你上次commit后,"app.rb"文件又被修改了木柬,找出它的哪行被修改了皆串。
$ git diff
發(fā)現(xiàn)第26行被修改了,關(guān)于git diff的格式如何理解眉枕,請參閱博文<a href="">git diff格式解析</a>
blame
某人在"config.rb"文件中放入了一個密碼恶复,找出來他是誰。
$ git blame -- config.rb
發(fā)現(xiàn)是Spider Man放入了密碼i<3evil速挑。
git blame會給出文件每行的commit SHA1谤牡,commiter,commit time and line number.
可以通過"-L"參數(shù)指定開始行和結(jié)束行姥宝,如
$ git blame -L 5,+2 F1.txt
會顯示F1.txt的第5,6行
$ git blame -L 5,-2 F1.txt
會顯示F1.txt的第4,5行
$ git blame -L n,m F1.txt
會顯示F1.txt的第min(n,m)到第max(n,m)行(閉區(qū)間)翅萤。
branch
你想要做一些危險的代碼編輯工作,創(chuàng)建一個叫"test_code"的分支腊满。
$ git branch test_code
checkout
創(chuàng)建并切換到一個叫作"my_branch"的新分支套么,你可能會像上一關(guān)一樣創(chuàng)建一個分支。
$ git checkout -b my_branch
checkout_tag
你需要在版本"v1.2"上修復(fù)一個BUG碳蛋,切換到標(biāo)簽"v1.2"
$ git checkout v1.2
checkout_tag_over_branch
你需要在版本"v1.2"上修復(fù)一個BUG胚泌,切換到標(biāo)簽"v1.2"。(注意:還有一個叫作"v1.2"的分支)
$ git checkout tags/v1.2
使用"tags/v1.2"來指定切換到tag而不是branch肃弟。
branch_at
你在上一次提交之前玷室,忘記創(chuàng)建分支了零蓉,直接提交在了本分支上。現(xiàn)在你要在上一次提交之前創(chuàng)建一個"test_branch"分支穷缤。
$ git branch test_branch HEAD^
即根據(jù)某個提交創(chuàng)建新分支
delete_branch
你創(chuàng)建了太多的分支敌蜂,現(xiàn)在你的倉庫中有一個叫作"delete_me"的老分支,你應(yīng)該刪除它津肛。
$ git branch -d delete_me
push_branch
你在本地倉庫做了一些修改章喉,希望與他人共享,但是并沒有準(zhǔn)備合并到master分支上快耿。只推送給遠(yuǎn)程倉庫"test_branch"這個分支囊陡。
$ git push origin test_branch
或者
$ git push origin test_branch:test_branch
merge
我們在"feature"分支中有一個文件,讓我們把它合并到"master"分支上掀亥。
$ git merge feature
fetch
看起來一個新分支已經(jīng)被推送到我們的遠(yuǎn)程倉庫中了撞反,取得這些修改,不要把它們合并到本地倉庫中搪花。
$ git fetch origin
其實遏片,git pull
就是 git fetch
和 git merge
的合體。
rebase
我們正在使用git freebase撮竿,"feature"分支已經(jīng)準(zhǔn)備好要合并進(jìn)"master"分支中了吮便,讓我們rebase這個"feature"分支到"master"分支上。
$ git rebase master feature
$ git checkout master
$ git merge feature ## ff
git rebase --onto <newbase> --root [<branch>]
幢踏,有關(guān)git rebase的詳細(xì)內(nèi)容髓需,請參閱博文<a href="">git rebase的用法</a>。
repack
優(yōu)化你的倉庫打包方式房蝉,以使得冗余的包裹(packs)被移除僚匆。
$ git repack -a -d
cherry-pick(擇優(yōu)選擇)
你的新feature失敗了,你想要刪除它搭幻。但是它有一個commit咧擂,其中填充了"README"文件,你想要這個commit保留在"master"分支上檀蹋。
$ git log --all # 查看feature填充README的commit SHA為ca32...
$ git cherry-pick ca32
這樣子松申,可以應(yīng)用其他分支的某一個commit的修改到另外的分支上。
grep
你的項目deadline即將到來俯逾,你應(yīng)該評估你的代碼中還有多少TODOs了贸桶。
純linux方法:
$ cat * | grep TODO | wc -l # 得出有4個TODO
git grep方法:
$ git grep TODO | wc -l
在代碼中根據(jù)正則表達(dá)式和條件進(jìn)行搜索,功能十分強(qiáng)大桌肴。
rename_commit
更正你的第一個提交(非根提交)的提交信息中的錯誤刨啸。
$ git rebase -i 046edb
046edb是根提交的SHA1值。
修改為
reword 4e8470d First coommit
pick 72ef1a3 Second commit
然后再修改提交信息即可识脆。
當(dāng)涉及修改commit時,使用git rebase -i
命令,它接受一個參數(shù)(commit SHA)灼捂,它將羅列出此提交之后的所有提交离例,然后根據(jù)提示來對每個提交依次進(jìn)行操作。
squash(壓扁)
你提交了好幾次悉稠,但是你想讓它們都合并成一個提交宫蛆。
$ git rebase -i e7757aff
修改為
pick 0559c6b Adding README
s 4c7e618 Updating README (squash this commit into Adding README)
s c0668f7 Updating README (squash this commit into Adding README)
s 9c4d834 Updating README (squash this commit into Adding README)
s(quash)表示使用該提交的修改,但和前一個提交融合的猛。
然后輸入新的提交信息即可耀盗。
或者使用f,和s相似卦尊,不同只是f直接丟棄被合并的commit的提交信息叛拷,直接使用Adding README。
merge_squash
合并所有"long-feature-branch"分支上的commit為一個單獨(dú)的commit岂却。
$ git merge --squash long-feature-branch
$ git commit -m 'merge long-feature-branch'
壓縮提交忿薇,不會更新HEAD,將所有變更都放入"index"中躏哩。
reorder
你提交了幾次署浩,但是提交順序錯了。請更正你的提交的順序扫尺。
$ git rebase -i 61d9af6c02b7df
調(diào)整順序即可筋栋。
* bisect(二分debug)
在工作過程中,一個BUG產(chǎn)生了正驻。你知道運(yùn)行ruby prog.rb 5
應(yīng)該輸出15弊攘,你也可以運(yùn)行make test
。請回答引入bug的commit的Hash值的前7位字符是什么拨拓?
$ git bisect start HEAD f608824
$ git bisect run make test
HEAD是當(dāng)前有BUG的commit肴颊,f608824是"First commit",沒有BUG的節(jié)點渣磷,在兩者之間查找婿着。
得到
18ed2ac1522a014412d4303ce7c8db39becab076 is the first bad commit
所以答案是"18ed2ac"。
stage_lines
你修改了一個同時屬于兩個不同"feature"的文件醋界,但是它們都還沒有被staged竟宋。請只Stage屬于第一個"feature"的變化。
$ git add -p feature.rb
diff --git a/feature.rb b/feature.rb
index 1a271e9..4a80dda 100644
--- a/feature.rb
+++ b/feature.rb
@@ -1 +1,3 @@
this is the class of my feature
+This change belongs to the first feature
+This change belongs to the second feature
Stage this hunk [y,n,q,a,d,/,e,?]?
$ e
# Manual hunk edit mode -- see bottom for a quick guide
@@ -1 +1,3 @@
this is the class of my feature
+This change belongs to the first feature
# ---
$ git diff
diff --git a/feature.rb b/feature.rb
index 3bccd0e..4a80dda 100644
--- a/feature.rb
+++ b/feature.rb
@@ -1,2 +1,3 @@
this is the class of my feature
This change belongs to the first feature
+This change belongs to the second feature
由git diff
的結(jié)果可以看到"feature1" 的修改已經(jīng)被staged進(jìn)index中了形纺。
git add -p(--patch):交互式地選擇調(diào)整由index到working tree的patch丘侠,然后把它們添加進(jìn)index中。它給了用戶在添加修改內(nèi)容到index中時的一個復(fù)查審閱不同的機(jī)會逐样。
使用git add --interactive
命令也能選擇patch操作蜗字,兩者是等價的打肝。
find_old_branch
你一直在某個分支上工作,但是中途被一次問題修復(fù)給搞亂了挪捕,忘記了之前分支的名字粗梭。請重回那個分支。
$ git reflog
發(fā)現(xiàn)之前從solve_world_hunger分支跳轉(zhuǎn)到BUG修復(fù)分支级零。
$ git checkout solve_world_hunger
git reflog
記錄了每一次重要的ref發(fā)生變更時候的操作断医。
revert
你提交了若干次,但現(xiàn)在想撤銷中間一次提交的操作奏纪。所有的commits都已經(jīng)推送了鉴嗤,所以你不能更改已經(jīng)存在的歷史。
$ git revert d0aaaacf11dd19c54928
git revert
只會撤銷某一次commit的修改序调,并不影響其后的commit醉锅,因此可能會產(chǎn)生沖突,屆時需要手工解決炕置。
restore
你決定通過運(yùn)行git reset --hard HEAD^
命令來刪除你的上一次提交(并不是個好方法)荣挨,但是你突然改變了主意,想要讓那個commit回來朴摊。請恢復(fù)被刪除的commit默垄。
$ git reflog
$ git reset --hard 14bd03f
通過git reflog
找到之前commit的SHA,即可通過git reset
恢復(fù)甚纲。
conflict
你需要合并"mybranch"分支到當(dāng)前分支("master"分支)口锭。但是在"mybranch"中似乎有一些可能會造成沖突的不正確的修改。解決你遇到的任何合并沖突介杆,完成合并操作鹃操。
$ git merge mybranch
$ vim poem.txt
$ git add poem.txt
$ git commit -m '合并'
注意沖突文件的格式。
Humpty dumpty
<<<<<<< HEAD
Categorized shoes by color
=======
Sat on a wall
>>>>>>> mybranch
Humpty dumpty
Had a great fall
其中"<<<<<<< HEAD"到"======="之間的內(nèi)容代表"HEAD"的修改春哨,"======="到">>>>>>> mybranch"之間的內(nèi)容代表"mybranch"的修改荆隘。手工修改,保留mybranch修改赴背,刪除HEAD修改椰拒,然后使用git add
確認(rèn)修改即可。
submodule
你想要包含倉庫 https://github.com/jackmaney/githug-include-me 中的文件到一個"./githug-include-me"文件夾中凰荚。不要用克隆倉庫的方式或者直接拷貝的方式來完成它燃观。
$ git submodule add https://github.com/jackmaney/githug-include-me ./githug-include-me
submodule是一種很方便地將一個倉庫分解為多個子模塊的命令,特別是項目比較大且依賴于其他git項目時便瑟,比如cocos2d-x缆毁。
contribute
這是最后一關(guān),目的是通過在Github上提起一個pull request來為這個項目倉庫貢獻(xiàn)源碼到涂。請注意脊框,這一關(guān)只是為了鼓勵你去為Githug項目做點貢獻(xiàn)颁督,并不是測試你去提起一個pull request的能力「肯荩可能被接受的貢獻(xiàn)種類是關(guān)卡适篙、BUG修復(fù)或者是文檔完善。
至此箫爷,所有關(guān)卡已經(jīng)完成。如果本文有什么錯誤或者問題聂儒,歡迎討論虎锚!
如果你對git的基本知識還不熟悉,歡迎參考我的另一篇博文git筆記總結(jié)衩婚。
參考資料: