文末送書(shū) |(三)深入淺出圖解Git,入門(mén)到精通(保姆級(jí)教程)

原文:https://mp.weixin.qq.com/s/d7YwRi1mEkxUSUqxWD_B1Q
這一篇我們繼續(xù)圖解Git,上兩篇原創(chuàng)圖解了Git的基本操作,有興趣的可以看一看[(一)深入淺出圖解Git,入門(mén)到精通(保姆級(jí)教程)]和[(二)深入淺出圖解Git,入門(mén)到精通(保姆級(jí)教程)]。

這一篇寫(xiě)完基本Git的操作就圖解完了,如果想深入了解Git,這里可以推薦一些Git的硬核書(shū)籍:【精通Git】、【GitHub入門(mén)與實(shí)踐】、【Git權(quán)威指南】、【Git版本控制管理】、【GitHub實(shí)踐】。

這些都是一些關(guān)于Git的比較好的書(shū)籍,有興趣的可以可看一看,網(wǎng)上也有很多電子書(shū)。閑話(huà)不多說(shuō),下面就開(kāi)始我們的正題。

日志

Git查看日志前面有提到過(guò)可以通過(guò)git log命令進(jìn)行查看:

image

git log可以查看你「提交的時(shí)間、提交的作者、以及提交的id」都可以查到,如果你覺(jué)得查詢(xún)的信息太多,可以加上參數(shù)--pretty=oneline,只會(huì)顯示版本號(hào)和提交時(shí)的備注信息。

如果你想查最近的幾條歷史記錄,可以通過(guò)加參數(shù)"-n"的形式制定查詢(xún)幾條記錄,歷史記錄是「按照操作的時(shí)間」進(jìn)行排序的:

image

還可以通過(guò)加參數(shù)" --graph",以圖形化的形式展示歷史記錄,方便與查看歷史記錄與分支的關(guān)系:

image

還可以加參數(shù)"-p",可以查看每一個(gè)commit操作更改的文件的哪一行,加參數(shù)"-stat"查看哪些文件改動(dòng)了,進(jìn)行簡(jiǎn)要的統(tǒng)計(jì)。更加詳細(xì)的git log參數(shù)可以查看命令幫助。

Git查看歷史記錄的另一個(gè)命令是git reflog,它可以查看「所有分支的所有操作記錄,包括已經(jīng)刪除的commit記錄和reset記錄」。

image

衍合(rebase)

分支管理中有「合并」「衍合」操作,合并操作在在第二年篇的分支章節(jié)已經(jīng)詳細(xì)講解過(guò)了,就來(lái)講解一下衍合操作:git rebase操作。

假如有兩位開(kāi)發(fā)人員Tom和Jerry,Tom和Jerry都把遠(yuǎn)程的master分支簽出到本地,此時(shí)當(dāng)前的Tom和Jerry本地都是只有一條master分支:

image

此時(shí)Tom開(kāi)發(fā)人員,創(chuàng)建一條新的分支branch,并且將新的分支branch推向遠(yuǎn)程倉(cāng)庫(kù)(git push origin branch):

image

此時(shí)Tom本地倉(cāng)庫(kù)和遠(yuǎn)程倉(cāng)庫(kù)的分支保持一致,分支如下圖所示:

image

Tom在自己的分支branch上開(kāi)發(fā)自己的模塊,假如開(kāi)發(fā)期間Tom進(jìn)行了「兩次」的提交,最后Tom本地的分支形成如下所示:

image

也可以通過(guò)git log查看兩次提交的記錄:

image

若是,此時(shí)Tom開(kāi)發(fā)人員準(zhǔn)備把自己的branch的分支推向遠(yuǎn)程倉(cāng)庫(kù),但是,Jerry在此之前已經(jīng)在master提交了自己的開(kāi)發(fā)代碼,所以master分支相比之前記錄,已經(jīng)向前推進(jìn)了一個(gè)版本。

所以此時(shí)Tom想提交,必須先更新一下自己的本地分支:

image

Tom中通過(guò)git log命令可以查看到Jerry的提交記錄情況,說(shuō)明此時(shí)分支已經(jīng)與遠(yuǎn)程倉(cāng)庫(kù)同步:

image

此時(shí)Tom更新分之后,本地的分支情況如下所致,相比原來(lái)master指向c1,現(xiàn)在向前推進(jìn)了一個(gè)版本指向c4:

image

此時(shí),Tom必須重新合并分支進(jìn)行提交,把branch的代碼合并到master分支上,現(xiàn)在Tom可以有兩種方式:

  1. 直接git merge
  2. git rebase,然后git merge。

(1)若是使用第一種方法直接在master分支上執(zhí)行git merge命令,「Git會(huì)把master分支上最新的提交c4的內(nèi)容和branch分支上最新的提交c3 合并后生成一個(gè)新的提交點(diǎn)c5」

image

上面實(shí)在沒(méi)有沖突的前提下,若是有沖突,則解決沖突:

image
image

此時(shí)就完成了master和branch分支的合并。

(2)若是使用第二個(gè)方法,先master也需要拉取到最新版本,然后是切換到branch分支,這個(gè)也就是要切換到rebase的分支,這里指的是branch分支。

在branch分支執(zhí)行git rebase master,表示chanch上新提交的c4節(jié)點(diǎn)會(huì)在master上的最新提交點(diǎn)后重新設(shè)立起點(diǎn)重新執(zhí)行,若是有沖突則解決沖突,沒(méi)有沖突執(zhí)行git add,最后執(zhí)行git rebase --continue。

image

通過(guò)git log查看你可以發(fā)現(xiàn),之前branch分支上進(jìn)行【「刪除HELLO ABC」】的操作commit hash已經(jīng)發(fā)生改變,最后切換到master分支,執(zhí)行git merge master

通過(guò)測(cè)試可以發(fā)現(xiàn),原來(lái)branch分支上重新commit的節(jié)點(diǎn)c4在rebase到master分之后hash發(fā)生了改變,并且提交的內(nèi)容被復(fù)制保留,從而使得master分支整個(gè)呈現(xiàn)線(xiàn)性的commit記錄,而不是直接git merge后的分叉記錄。

在master分支進(jìn)行branch分支rebase的原理圖如下:

image

注意:「一般不是在branch進(jìn)行rebase主分支master的提交,因?yàn)闀?huì)導(dǎo)致master的新提交在本地丟失,這樣有可能會(huì)導(dǎo)致本地倉(cāng)庫(kù)與遠(yuǎn)程倉(cāng)庫(kù)發(fā)生沖突,從而無(wú)法push操作」。

「總結(jié)」「git merge會(huì)將兩個(gè)分支的最新提交點(diǎn)進(jìn)行一次合并,形成一個(gè)新的提交點(diǎn),最終形成樹(shù)狀的提交記錄」,但是有些人并不是喜歡merge,覺(jué)得merge之后出現(xiàn)的分叉會(huì)難以管理,那么可以選擇rebase操作來(lái)替代merge。

「git rebase操作是將要rebase的分支最新提交點(diǎn)作為新的基礎(chǔ)點(diǎn),將當(dāng)前執(zhí)行g(shù)it rebase master的分支的新commit點(diǎn)重新生成commit hash值,rebase完后再次切換到另一條分支進(jìn)行合并,就可以保證線(xiàn)性的commit的記錄」

「最后只選擇merge還是rebase取決于個(gè)人和時(shí)機(jī)情況,假如你想提交記錄呈現(xiàn)線(xiàn)性整潔那么選擇rebase,否則選擇merge,實(shí)際情況也有可能是這樣的,每個(gè)人本地開(kāi)發(fā),可能會(huì)提交非常的多次,有些提交可能是修一些簡(jiǎn)單的bug,那么最后的提交只想做一次完整、正確的提交,那么也可以使用rebase?!?/strong>

標(biāo)簽管理

Git中使用的標(biāo)簽有兩種類(lèi)型:「輕量級(jí)的(lightweight)和含附注的(annotated)」。輕量級(jí)標(biāo)簽只需在git tag后加上標(biāo)簽的名字,就可以添加標(biāo)簽。

標(biāo)簽管理作為開(kāi)發(fā)人員可能很少使用,可以作為了解,「tag是針對(duì)Git中某一時(shí)間某一版本打上標(biāo)簽」,tag的使用命令也是非常的簡(jiǎn)單。

新建標(biāo)簽

新建一個(gè)標(biāo)簽,默認(rèn)是在HEAD新建,可以指定commit id新建,具體命令如下所示:

$ git tag <標(biāo)簽名> $ git tag <標(biāo)簽名> <commit id> $ git tag -a <標(biāo)簽名> -m "備注" </pre>

刪除標(biāo)簽

刪除標(biāo)簽若是標(biāo)簽沒(méi)有推向遠(yuǎn)程倉(cāng)庫(kù),直接使用以下命令刪除:

$ git tag -d <標(biāo)簽名>

若是標(biāo)簽已經(jīng)推向遠(yuǎn)程倉(cāng)庫(kù),先刪除本地,再刪除遠(yuǎn)程倉(cāng)庫(kù)的標(biāo)簽:

-git tag -d git push origin :refs/tags

查看標(biāo)簽

git tag的方式是查看所有的標(biāo)簽,git show <標(biāo)簽名>的方式是查看每個(gè)特定的標(biāo)簽

$ git tag $ git show <標(biāo)簽名> </pre>

推送標(biāo)簽到遠(yuǎn)程

推送標(biāo)簽也是分兩種情況,一種是指定標(biāo)簽的推送,另一種是推送所有標(biāo)簽。

git push origin <標(biāo)簽名> git push origin --tags` </pre>

提交了錯(cuò)誤代碼

代碼錯(cuò)誤提交了怎么辦,重新再一次提交一個(gè)版本唄,這個(gè)可能是很多人的解決方案,當(dāng)然Git也是有提供自己的解決方案的命令。

第一種就是再次將修改文件然后git add .到暫存區(qū),最后git commit --amend提交修改 ,它的原理圖如下所示:

image.gif

這種方法只能修改當(dāng)前HEAD,也就是最新的提交,那么要修改是倒數(shù)第二個(gè)或者倒數(shù)第三個(gè)的提交呢?

這時(shí)候就要使用rebase -i「交互式rebase」)進(jìn)行操作了,這個(gè)命令是指定commit鏈中哪一個(gè)commit需要修改。

比如執(zhí)行命令:git rebase -i HEAD^。它表示的含義就是把當(dāng)前commit內(nèi)容rebase到HEAD之前的一個(gè)commit上。

若是想直接丟棄最新的commit的修改,則直接使用命令:git reset --hard HEAD^。他表示當(dāng)前commit往前移動(dòng)一次。

image

那想丟棄某一次的修改呢?并不是最新的commit,通用也是要使用rebase的交互式操作:git rebase -onto HEAD^^ HEAD^ master。他表示的含義就是以倒數(shù)第二個(gè)為起點(diǎn),master為終點(diǎn),rebase到倒數(shù)第三個(gè)commit上。

image

最后

好了圖解Git操作基本講解完了,其他的一些細(xì)節(jié)操作基本都是在基本操作的基礎(chǔ)上加參數(shù),詳細(xì)的參數(shù)大家可以參考官網(wǎng)或者相關(guān)的書(shū)籍。

在公司的實(shí)際應(yīng)用這三篇圖解Git操作基本可以應(yīng)付了,上面說(shuō)的交互式操作,基本沒(méi)用過(guò),只做大致的了解,但是之前在面試華為的時(shí)候有被問(wèn)到Git的交互操作。

最后,幫助粉絲Git的進(jìn)階,由北京大學(xué)出版社贊助給粉絲送福利,送出兩本書(shū) 「《Git入門(mén)到精通》」,最后獲得書(shū)籍的形式在本文的「留言區(qū)前兩名的粉絲」可以獲得,活動(dòng)時(shí)間到「10/8 18:00 -10/10 12:00」。

image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容