Git圖解
BY 童仲毅(geeeeeeeeek@github)
這是一篇在原文基礎(chǔ)上演繹的文章郎笆。原作者Mark Lodato塞栅,譯者wych鸣奔。原文采用創(chuàng)用CC 姓名標(biāo)示-非商業(yè)性-相同方式分享3.0 美國(guó)授權(quán)條款授權(quán)虱痕。
此頁圖解git中的最常用命令身冀。如果你稍微理解git的工作原理钝尸,這篇文章能夠讓你理解的更透徹。
基本用法
上面的四條命令在工作目錄搂根、stage緩存(也叫做索引)和commit歷史之間復(fù)制文件珍促。
-
git add files
把工作目錄中的文件加入stage緩存 -
git commit
把stage緩存生成一次commit,并加入commit歷史 -
git reset -- files
撤銷最后一次git add files
剩愧,你也可以用git reset
撤銷所有stage緩存文件 -
git checkout -- files
把文件從stage緩存復(fù)制到工作目錄猪叙,用來丟棄本地修改
你可以用 git reset -p
、git checkout -p
或 git add -p
進(jìn)入交互模式仁卷,也可以跳過stage緩存直接從commit歷史取出文件或者直接提交代碼穴翩。
-
git commit -a
相當(dāng)于運(yùn)行git add
把所有當(dāng)前目錄下的文件加入stage緩存再運(yùn)行git commit
。 -
git commit files
進(jìn)行一次包含最后一次提交加上工作目錄中文件快照的提交锦积,并且文件被添加到stage緩存芒帕。 -
git checkout HEAD -- files
回滾到復(fù)制最后一次提交。
約定
后文中以下面的形式使用圖片:
綠色的5位字符表示提交的ID丰介,分別指向父節(jié)點(diǎn)背蟆。分支用橙色顯示鉴分,分別指向特定的提交。當(dāng)前分支由附在其上的HEAD標(biāo)識(shí)淆储。
這張圖片里顯示最后5次提交冠场,ed489是最新提交家浇。 master分支指向此次提交本砰,另一個(gè)maint分支指向祖父提交節(jié)點(diǎn)。
命令詳解
Diff
有許多種方法查看兩次提交之間的變動(dòng)钢悲,下面是其中一些例子点额。
Commit
提交時(shí),git用stage緩存中的文件創(chuàng)建一個(gè)新的提交莺琳,并把此時(shí)的節(jié)點(diǎn)設(shè)為父節(jié)點(diǎn)还棱。然后把當(dāng)前分支指向新的提交節(jié)點(diǎn)。下圖中惭等,當(dāng)前分支是master珍手。
在運(yùn)行命令之前,master指向ed489辞做,提交后琳要,master指向新的節(jié)點(diǎn)f0cec并以ed489作為父節(jié)點(diǎn)。
即便當(dāng)前分支是某次提交的祖父節(jié)點(diǎn)秤茅,git會(huì)同樣操作稚补。下圖中,在master分支的祖父節(jié)點(diǎn)maint分支進(jìn)行一次提交框喳,生成了1800b课幕。
這樣,maint分支就不再是master分支的祖父節(jié)點(diǎn)五垮。此時(shí)乍惊,merge 或者 rebase 是必須的。
如果想更改一次提交放仗,使用 git commit --amend
润绎。git會(huì)使用與當(dāng)前提交相同的父節(jié)點(diǎn)進(jìn)行一次新提交,舊的提交會(huì)被取消匙监。
另一個(gè)例子是分離HEAD提交凡橱,在后面的章節(jié)中介紹。
Checkout
checkout命令用于從歷史提交(或者stage緩存)中拷貝文件到工作目錄亭姥,也可用于切換分支稼钩。
當(dāng)給定某個(gè)文件名(或者打開-p選項(xiàng),或者文件名和-p選項(xiàng)同時(shí)打開)時(shí)达罗,git會(huì)從指定的提交中拷貝文件到stage緩存和工作目錄坝撑。比如静秆,git checkout HEAD~ foo.c
會(huì)將提交節(jié)點(diǎn)HEAD~(即當(dāng)前提交節(jié)點(diǎn)的父節(jié)點(diǎn))中的foo.c
復(fù)制到工作目錄并且加到stage緩存中。如果命令中沒有指定提交節(jié)點(diǎn)巡李,則會(huì)從stage緩存中拷貝內(nèi)容抚笔。注意當(dāng)前分支不會(huì)發(fā)生變化。
當(dāng)不指定文件名侨拦,而是給出一個(gè)(本地)分支時(shí)殊橙,那么HEAD標(biāo)識(shí)會(huì)移動(dòng)到那個(gè)分支(也就是說,我們“切換”到那個(gè)分支了)狱从,然后stage緩存和工作目錄中的內(nèi)容會(huì)和HEAD對(duì)應(yīng)的提交節(jié)點(diǎn)一致膨蛮。新提交節(jié)點(diǎn)(下圖中的a47c3)中的所有文件都會(huì)被復(fù)制(到stage緩存和工作目錄中);只存在于老的提交節(jié)點(diǎn)(ed489)中的文件會(huì)被刪除季研;不屬于上述兩者的文件會(huì)被忽略敞葛,不受影響。
如果既沒有指定文件名与涡,也沒有指定分支名惹谐,而是一個(gè)標(biāo)簽、遠(yuǎn)程分支驼卖、SHA-1值或者是像master~3類似的東西氨肌,就得到一個(gè)匿名分支,稱作detached HEAD(被分離的HEAD標(biāo)識(shí))款慨。這樣可以很方便地在歷史版本之間互相切換儒飒。比如說你想要編譯1.6.6.1版本的git,你可以運(yùn)行git checkout v1.6.6.1
(這是一個(gè)標(biāo)簽檩奠,而非分支名)桩了,編譯,安裝埠戳,然后切換回另一個(gè)分支井誉,比如說git checkout master
。然而整胃,當(dāng)提交操作涉及到“分離的HEAD”時(shí)颗圣,其行為會(huì)略有不同,詳情見在下面屁使。
HEAD標(biāo)識(shí)處于分離狀態(tài)時(shí)的提交操作
當(dāng)HEAD處于分離狀態(tài)(不依附于任一分支)時(shí)在岂,提交操作可以正常進(jìn)行,但是不會(huì)更新任何已命名的分支蛮寂。你可以認(rèn)為這是在更新一個(gè)匿名分支蔽午。
一旦此后你切換到別的分支,比如說master酬蹋,那么這個(gè)提交節(jié)點(diǎn)(可能)再也不會(huì)被引用到及老,然后就會(huì)被丟棄掉了抽莱。注意這個(gè)命令之后就不會(huì)有東西引用2eecb。
但是骄恶,如果你想保存這個(gè)狀態(tài)食铐,可以用命令git checkout -b name
來創(chuàng)建一個(gè)新的分支。
Reset
reset命令把當(dāng)前分支指向另一個(gè)位置僧鲁,并且有選擇的變動(dòng)工作目錄和索引虐呻。也用來在從歷史commit歷史中復(fù)制文件到索引,而不動(dòng)工作目錄悔捶。
如果不給選項(xiàng)铃慷,那么當(dāng)前分支指向到那個(gè)提交单芜。如果用--hard
選項(xiàng)蜕该,那么工作目錄也更新,如果用--soft
選項(xiàng)洲鸠,那么都不變堂淡。
如果沒有給出提交點(diǎn)的版本號(hào),那么默認(rèn)用HEAD扒腕。這樣绢淀,分支指向不變,但是索引會(huì)回滾到最后一次提交瘾腰,如果用--hard
選項(xiàng)皆的,工作目錄也同樣。
如果給了文件名(或者 -p
選項(xiàng)), 那么工作效果和帶文件名的checkout差不多蹋盆,除了索引被更新费薄。
Merge
merge 命令把不同分支合并起來。合并前栖雾,索引必須和當(dāng)前提交相同楞抡。如果另一個(gè)分支是當(dāng)前提交的祖父節(jié)點(diǎn),那么合并命令將什么也不做析藕。
另一種情況是如果當(dāng)前提交是另一個(gè)分支的祖父節(jié)點(diǎn)召廷,就導(dǎo)致fast-forward合并。指向只是簡(jiǎn)單的移動(dòng)账胧,并生成一個(gè)新的提交竞慢。
否則就是一次真正的合并。默認(rèn)把當(dāng)前提交(ed489 如下所示)和另一個(gè)提交(33104)以及他們的共同祖父節(jié)點(diǎn)(b325c)進(jìn)行一次三方合并治泥。結(jié)果是先保存當(dāng)前目錄和索引筹煮,然后和父節(jié)點(diǎn)33104一起做一次新提交。
Cherry Pick
cherry-pick命令"復(fù)制"一個(gè)提交節(jié)點(diǎn)并在當(dāng)前分支做一次完全一樣的新提交车摄。
Rebase
rebase是合并命令的另一種選擇寺谤。合并把兩個(gè)父分支合并進(jìn)行一次提交仑鸥,提交歷史不是線性的。rebase在當(dāng)前分支上重演另一個(gè)分支的歷史变屁,提交歷史是線性的眼俊。
本質(zhì)上,這是線性化的自動(dòng)的 cherry-pick粟关。
上面的命令都在topic分支中進(jìn)行疮胖,而不是master分支,在master分支上重演闷板,并且把分支指向新的節(jié)點(diǎn)澎灸。注意舊提交沒有被引用,將被回收遮晚。
要限制回滾范圍性昭,使用--onto
選項(xiàng)。下面的命令在master分支上重演當(dāng)前分支從169a6以來的最近幾個(gè)提交县遣,即2c33a糜颠。
同樣有git rebase --interactive
讓你更方便的完成一些復(fù)雜操作,比如丟棄萧求、重排其兴、修改、合并提交夸政。
這篇文章是『git-recipes』的一部分元旬,點(diǎn)擊目錄查看所有章節(jié)。
如果你覺得文章對(duì)你有幫助守问,歡迎點(diǎn)擊右上角的Star:star2:或Fork:fork_and_knife:匀归。
如果你發(fā)現(xiàn)了錯(cuò)誤,或是想要加入?yún)f(xié)作酪碘,請(qǐng)參閱Wiki協(xié)作說明朋譬。