本篇文章給大家分享的是有關(guān)Git各指令的本質(zhì)以及用法是什么,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
專注于為中小企業(yè)提供網(wǎng)站制作、網(wǎng)站設(shè)計服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)常山免費做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了近千家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。
1.1 Git的優(yōu)勢
Git
是一個分布式
代碼管理工具,在討論分布式之前避免不了提及一下什么是中央式
代碼管理倉庫
1.2 文件狀態(tài)
在Git中文件大概分為三種狀態(tài):
已修改(modified)、已暫存(staged)、已提交(committed)
修改:Git可以感知到工作目錄中哪些文件被修改了,然后把修改的文件加入到modified區(qū)域
暫存:通過add命令將工作目錄中修改的文件提交到暫存區(qū),等候被commit
提交:將暫存區(qū)文件commit至Git目錄中永久保存
1.3 commit節(jié)點
為了便于表述,本篇文章我會通過
節(jié)點
代稱commit提交
在Git中每次提交都會生成一個
節(jié)點
,而每個節(jié)點都會有一個哈希值作為唯一標(biāo)示,多次提交會形成一個線性
節(jié)點鏈(不考慮merge的情況),如圖1-1
節(jié)點上方是通過 SHA1計算的哈希值
C2
節(jié)點包含C1
提交內(nèi)容,同樣C3
節(jié)點包含C1、C2
提交內(nèi)容1.4 HEAD
HEAD
是Git中非常重要的一個概念,你可以稱它為指針
或者引用
,它可以指向任意一個節(jié)點
,并且指向的節(jié)點始終為當(dāng)前工作目錄,換句話說就是當(dāng)前工作目錄(也就是你所看到的代碼)就是HEAD
指向的節(jié)點。還以圖1-1舉例,如果
HEAD
指向C2
那工作目錄對應(yīng)的就是C2
節(jié)點。具體如何移動HEAD
指向后面會講到,此處不要糾結(jié)。同時
HEAD
也可以指向一個分支
,間接指向分支
所指向的節(jié)點
1.5 遠(yuǎn)程倉庫
雖然Git會把代碼以及歷史保存在本地,但最終還是要提交到服務(wù)器上的遠(yuǎn)程倉庫。通過
clone
命令可以把遠(yuǎn)程倉庫的代碼下載到本地,同時也會將提交歷史
、分支
、HEAD
等狀態(tài)一并同步到本地,但這些狀態(tài)并不會實時更新,需要手動從遠(yuǎn)程倉庫去拉取,至于何時拉、怎么拉后面章節(jié)會講到。通過遠(yuǎn)程倉庫為中介,你可以和你的同事進(jìn)行協(xié)同開發(fā),開發(fā)完新功能后可以申請?zhí)峤恢吝h(yuǎn)程倉庫,同時也可以從遠(yuǎn)程倉庫拉取你同事的代碼。
注意點
因為你和你的同事都會以遠(yuǎn)程倉庫的代碼為基準(zhǔn),所以要時刻保證遠(yuǎn)程倉庫的代碼質(zhì)量,切記不要將未經(jīng)檢驗測試的代碼提交至遠(yuǎn)程倉庫
2. 分支
2.1 什么是分支?
分支
也是Git中相當(dāng)重要的一個概念,當(dāng)一個分支
指向一個節(jié)點
時,當(dāng)前節(jié)點
的內(nèi)容即是該分支
的內(nèi)容,它的概念和HEAD
非常接近同樣也可以視為指針
或引用
,不同的是分支
可以存在多個,而HEAD
只有一個。通常會根據(jù)功能
或版本
建立不同的分支那分支有什么用呢?
舉個例子:你們的 App 經(jīng)歷了千辛萬苦終于發(fā)布了
v1.0
版本,由于需求緊急v1.0
上線之后便馬不停蹄的開始v1.1
,正當(dāng)你開發(fā)的興起時,QA同學(xué)說用戶反饋了一些bug,需要修復(fù)然后重新發(fā)版,修復(fù)v1.0
肯定要基于v1.0
的代碼,可是你已經(jīng)開發(fā)了一部分v1.1
了,此時怎么搞?面對上面的問題通過引入
分支
概念便可優(yōu)雅的解決,如圖2-1
先看左邊示意圖,假設(shè)
C2
節(jié)點既是v1.0
版本代碼,上線后在C2
的基礎(chǔ)上新建一個分支ft-1.0
再看右邊示意圖,在
v1.0
上線后可在master
分支開發(fā)v1.1
內(nèi)容,收到QA同學(xué)反饋后提交v1.1
代碼生成節(jié)點C3
,隨后切換到ft-1.0
分支做bug修復(fù),修復(fù)完成后提交代碼生成節(jié)點C4
,然后再切換到master
分支并合并ft-1.0
分支,到此我們就解決了上面提出的問題除此之外利用分支還可以做很多事情,比如現(xiàn)在有一個需求不確定要不要上線,但是得先做,此時可以單獨創(chuàng)建一個分支開發(fā)該功能,等到啥時候需要上線直接合并到主分支即可。分支適用的場景很多就不一一列舉了。
注意點
當(dāng)在某個節(jié)點創(chuàng)建一個分支后,并不會把該節(jié)點對應(yīng)的代碼復(fù)制一份出來,只是將新分支指向該節(jié)點,因此可以很大程度減少空間上的開銷。一定要記著不管是
HEAD
還是分支
它們都只是引用而已,量級非常輕3. 命令詳解
3.1 提交相關(guān)
前面我們提到過,想要對代碼進(jìn)行提交必須得先加入到暫存區(qū),Git中是通過命令
add
實現(xiàn)添加某個文件到暫存區(qū):
git add 文件路徑
添加所有文件到暫存區(qū):
git add .
同時Git也提供了撤銷
工作區(qū)
和暫存區(qū)
命令撤銷工作區(qū)改動:
git checkout -- 文件名
清空暫存區(qū):
git reset HEAD 文件名
提交:
將改動文件加入到暫存區(qū)后就可以進(jìn)行提交了,提交后會生成一個新的提交節(jié)點,具體命令如下:
git commit -m "該節(jié)點的描述信息"
3.2 分支相關(guān)
創(chuàng)建分支
創(chuàng)建一個分支后該分支會與
HEAD
指向同一節(jié)點,說通俗點就是HEAD
指向哪創(chuàng)建的新分支就指向哪,命令如下:
git branch 分支名
切換分支
當(dāng)切換分支后,默認(rèn)情況下
HEAD
會指向當(dāng)前分支,即HEAD
間接指向當(dāng)前分支指向的節(jié)點
git checkout 分支名
同時也可以創(chuàng)建一個分支后立即切換,命令如下:
git checkout -b 分支名
刪除分支
為了保證倉庫分支的簡潔,當(dāng)某個分支完成了它的使命后應(yīng)該被刪除。比如前面所說的單獨開一個分支完成某個功能,當(dāng)這個功能被合并到主分支后應(yīng)該將這個分支及時刪除。
刪除命令如下:
git branch -d 分支名
3.3 合并相關(guān)
關(guān)于合并的命令是最難掌握同時也是最重要的。我們常用的合并命令大概有三個
merge
、rebase
、cherry-pick
merge
merge
是最常用的合并命令,它可以將某個分支或者某個節(jié)點的代碼合并至當(dāng)前分支。具體命令如下:
git merge 分支名/節(jié)點哈希值
如果需要合并的分支完全領(lǐng)先于當(dāng)前分支,如圖3-1所示
由于分支
ft-1
完全領(lǐng)先分支ft-2
即ft-1
完全包含ft-2
,所以ft-2
執(zhí)行了“git merge ft-1”
后會觸發(fā)fast forward(快速合并)
,此時兩個分支指向同一節(jié)點,這是最理想的狀態(tài)。但是實際開發(fā)中我們往往碰到是是下面這種情況:如圖3-2(左)當(dāng)左邊示意圖的
ft-1.0
執(zhí)行了git rebase master
后會將C4
節(jié)點復(fù)制一份到C3
后面,也就是C4'
,C4
與C4'
相對應(yīng),但是哈希值卻不一樣。
rebase
相比于merge
提交歷史更加線性、干凈,使并行的開發(fā)流程看起來像串行,更符合我們的直覺。既然rebase
這么好用是不是可以拋棄merge
了?其實也不是了,下面我羅列一些merge
和rebase
的優(yōu)缺點:merge優(yōu)缺點:
優(yōu)點:每個節(jié)點都是嚴(yán)格按照時間排列。當(dāng)合并發(fā)生沖突時,只需要解決兩個分支所指向的節(jié)點的沖突即可
缺點:合并兩個分支時大概率會生成新的節(jié)點并
分叉
,久而久之提交歷史會變成一團(tuán)亂麻rebase優(yōu)缺點:
優(yōu)點:會使提交歷史看起來更加線性、干凈
缺點:雖然提交看起來像是線性的,但并不是真正的按時間排序,比如圖3-3中,不管
C4
早于或者晚于C3
提交它最終都會放在C3
后面。并且當(dāng)合并發(fā)生沖突時,理論上來講有幾個節(jié)點rebase
到目標(biāo)分支就可能處理幾次沖突對于網(wǎng)絡(luò)上一些
只用rebase
的觀點,作者表示不太認(rèn)同,如果不同分支的合并使用rebase
可能需要重復(fù)解決沖突,這樣就得不償失了。但如果是本地推到遠(yuǎn)程并對應(yīng)的是同一條分支可以優(yōu)先考慮rebase
。所以我的觀點是 根據(jù)不同場景合理搭配使用merge
和rebase
,如果覺得都行那優(yōu)先使用rebase
cherry-pick
cherry-pick
的合并不同于merge
和rebase
,它可以選擇某幾個節(jié)點進(jìn)行合并,如圖3-4命令行:
git cherry-pick 節(jié)點哈希值
假設(shè)當(dāng)前分支是
master
,執(zhí)行了git cherry-pick C3(哈希值),C4(哈希值)
命令后會直接將C3
、C4
節(jié)點抓過來放在后面,對應(yīng)C3'
和C4'
3.4 回退相關(guān)
分離HEAD
在默認(rèn)情況下HEAD是指向分支的,但也可以將HEAD從分支上取下來直接指向某個節(jié)點,此過程就是
分離HEAD
,具體命令如下:
git checkout 節(jié)點哈希值
//也可以直接脫離分支指向當(dāng)前節(jié)點
git checkout --detach由于哈希值是一串很長很長的亂碼,在實際操作中使用哈希值分離HEAD很麻煩,所以Git也提供了HEAD基于某一特殊位置(分支/HEAD)直接指向
前一個
或前N個
節(jié)點的命令,也即相對引用,如下:
//HEAD分離并指向前一個節(jié)點
git checkout 分支名/HEAD^
//HEAD分離并指向前N個節(jié)點
git checkout 分支名~N將
HEAD分離
出來指向節(jié)點有什么用呢?舉個例子:如果開發(fā)過程發(fā)現(xiàn)之前的提交有問題,此時可以將HEAD指向?qū)?yīng)的節(jié)點,修改完畢后再提交,此時你肯定不希望再生成一個新的節(jié)點,而你只需在提交時加上--amend
即可,具體命令如下:
git commit --amend
回退
回退場景在平時開發(fā)中還是比較常見的,比如你巴拉巴拉寫了一大堆代碼然后提交,后面發(fā)現(xiàn)寫的有問題,于是你想將代碼回到前一個提交,這種場景可以通過
reset
解決,具體命令如下:
//回退N個提交
git reset HEAD~N
reset
和相對引用
很像,區(qū)別是reset
會使分支
和HEAD
一并回退。3.5 遠(yuǎn)程相關(guān)
當(dāng)我們接觸一個新項目時,第一件事情肯定是要把它的代碼拿下來,在Git中可以通過
clone
從遠(yuǎn)程倉庫復(fù)制一份代碼到本地,具體命令如下:
git clone 倉庫地址
前面的章節(jié)我也有提到過,
clone
不僅僅是復(fù)制代碼,它還會把遠(yuǎn)程倉庫的引用(分支/HEAD)
一并取下保存在本地,如圖3-5所示:其中
origin/master
和origin/ft-1
為遠(yuǎn)程倉庫的分支,而遠(yuǎn)程的這些引用狀態(tài)是不會實時更新到本地的,比如遠(yuǎn)程倉庫origin/master
分支增加了一次提交,此時本地是感知不到的,所以本地的origin/master
分支依舊指向C4
節(jié)點。我們可以通過fetch
命令來手動更新遠(yuǎn)程倉庫狀態(tài)小提示:
并不是存在服務(wù)器上的才能稱作是遠(yuǎn)程倉庫,你也可以
clone
本地倉庫作為遠(yuǎn)程,當(dāng)然實際開發(fā)中我們不可能把本地倉庫當(dāng)作公有倉庫,說這個只是單純的幫助你更清晰的理解分布式
fetch
說的通俗一點,
fetch
命令就是一次下載
操作,它會將遠(yuǎn)程新增加的節(jié)點以及引用(分支/HEAD)
的狀態(tài)下載到本地,具體命令如下:
git fetch 遠(yuǎn)程倉庫地址/分支名
pull
pull
命令可以從遠(yuǎn)程倉庫的某個引用拉取代碼,具體命令如下:
git pull 遠(yuǎn)程分支名
其實
pull
的本質(zhì)就是fetch
+merge
,首先更新遠(yuǎn)程倉庫所有狀態(tài)
到本地,隨后再進(jìn)行合并。合并完成后本地分支會指向最新節(jié)點
另外
pull
命令也可以通過rebase
進(jìn)行合并,具體命令如下:
git pull --rebase 遠(yuǎn)程分支名
push
push
命令可以將本地提交推送至遠(yuǎn)程,具體命令如下:
git push 遠(yuǎn)程分支名
如果直接
push
可能會失敗,因為可能存在沖突,所以在push
之前往往會先pull
一下,如果存在沖突本地解決。push
成功后本地的遠(yuǎn)程分支引用會更新,與本地分支指向同一節(jié)點綜上所述
不管是
HEAD
還是分支
,它們都只是引用
而已,引用
+節(jié)點
是 Git 構(gòu)成分布式的關(guān)鍵
merge
相比于rebase
有更明確的時間歷史,而rebase
會使提交更加線性應(yīng)當(dāng)優(yōu)先使用通過移動
HEAD
可以查看每個提交對應(yīng)的代碼
clone
或fetch
都會將遠(yuǎn)程倉庫的所有提交
、引用
保存在本地一份
pull
的本質(zhì)其實就是fetch
+merge
,也可以加入--rebase
通過rebase方式合并以上就是Git各指令的本質(zhì)以及用法是什么,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降摹OM隳芡ㄟ^這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
網(wǎng)站標(biāo)題:Git各指令的本質(zhì)以及用法是什么
本文網(wǎng)址:http://weahome.cn/article/ggedcs.html