Git 不用背,這篇文章幫助你簡(jiǎn)化 Git 的學(xué)習(xí)過(guò)程
當(dāng)你學(xué)習(xí) Git 時(shí),可能會(huì)被其龐大的命令集和各種概念所嚇到。但實(shí)際上,Git 并不要求死記硬背每一個(gè)命令,更重要的是理解其工作流程和使用場(chǎng)景。這篇文章的目的就是幫助你簡(jiǎn)化 Git 的學(xué)習(xí)過(guò)程,讓你發(fā)現(xiàn) Git 其實(shí)并不需要刻意去背,只需要真正理解它,就能輕松掌握?,F(xiàn)在,就讓我們一起踏上探索 Git 世界的旅程吧!
Git 基本概念
1. Git 歷史
Git 是最流行的分布式版本控制系統(tǒng)(Distributed Version Control System,簡(jiǎn)稱 DVCS)。它由 Linus Torvalds 創(chuàng)建,當(dāng)時(shí)非常需要一個(gè)快速、高效和大規(guī)模分布式的源代碼管理系統(tǒng),用于管理 Linux 源代碼。
由于 Linus 對(duì)幾乎所有現(xiàn)有的源代碼管理系統(tǒng)抱有強(qiáng)烈的反感,因此他決定編寫自己的源代碼管理系列。2005 年 4 月,Git 就誕生了。到了 2005 年 7 月,維護(hù)工作就交給了 Junio Hamano,自此他就一直在維護(hù)這個(gè)項(xiàng)目。
雖然最初只用于 Linux 內(nèi)核,但 Git 項(xiàng)目迅速傳播,并很快被用于管理許多其他 Linux 項(xiàng)目。現(xiàn)在,幾乎所有的軟件開(kāi)發(fā),尤其是在開(kāi)源世界中,都是通過(guò) Git 進(jìn)行的。
2. 版本控制系統(tǒng)
版本控制是指對(duì)軟件開(kāi)發(fā)過(guò)程中各種程序代碼、配置文件及說(shuō)明文檔等文件變更的管理,是軟件配置管理的核心思想之一。版本控制技術(shù)是團(tuán)隊(duì)協(xié)作開(kāi)發(fā)的橋梁,助力于多人協(xié)作同步進(jìn)行大型項(xiàng)目開(kāi)發(fā)。軟件版本控制系統(tǒng)的核心任務(wù)就是查閱項(xiàng)目歷史操作記錄、實(shí)現(xiàn)協(xié)同開(kāi)發(fā)。
常見(jiàn)版本控制主要有兩種:集中式版本控制和分布式版本控制。
(1)集中式版本控制系統(tǒng)
集中式版本控制系統(tǒng),版本庫(kù)是集中存放在中央服務(wù)器的。工作時(shí),每個(gè)人都要先從中央服務(wù)器獲取最新的版本。完成之后,再把自己添加/修改的內(nèi)容提交到中央服務(wù)器。所有文件和歷史數(shù)據(jù)都存儲(chǔ)在中央服務(wù)器上。SVN 是最流行的集中式版本控制系統(tǒng)之一。
集中式版本控制系統(tǒng)的缺點(diǎn)就是必須聯(lián)網(wǎng)才能使用,如果使用局域網(wǎng)還好,速度會(huì)比較快。而如果是使用互聯(lián)網(wǎng),網(wǎng)速慢的話,就可能需要等待很長(zhǎng)時(shí)間。除此之外,如果中央服務(wù)器出現(xiàn)故障,那么版本控制將不可用。如果中心數(shù)據(jù)庫(kù)損壞,若數(shù)據(jù)未備份,數(shù)據(jù)就會(huì)丟失。
(2)分布式版本控制系統(tǒng)
分布式版本控制系統(tǒng),每臺(tái)終端都可以保存版本庫(kù),版本庫(kù)可以不同,可以對(duì)每個(gè)版本庫(kù)進(jìn)行修改,修改完成后可以集中進(jìn)行更新。雖然它沒(méi)有中心服務(wù)器,但可以有一個(gè)備份服務(wù)器,它的功能有點(diǎn)類似于 SVN 的中央服務(wù)器,但它的作用僅是方便交換修改,而不像 SVN 那樣還要負(fù)責(zé)源代碼的管理。Git 是最流行的分布式版本控制系統(tǒng)之一。
和集中式版本控制系統(tǒng)相比,分布式版本控制系統(tǒng)的安全性要高很多,因?yàn)槊總€(gè)人電腦里都有完整的版本庫(kù),某一個(gè)人的電腦損壞不會(huì)影響到協(xié)作的其他人。
(3)SVN vs Git
Git 相較于 SVN:
- 提交速度更快: 因?yàn)樵?SVN 中需要更頻繁地提交到中央存儲(chǔ)庫(kù),所以網(wǎng)絡(luò)流量會(huì)減慢每個(gè)人的速度。而使用 Git,主要在本地存儲(chǔ)庫(kù)上工作,只需每隔一段時(shí)間才提交到中央存儲(chǔ)庫(kù)。
- 沒(méi)有單點(diǎn)故障: 使用 SVN,如果中央存儲(chǔ)庫(kù)出現(xiàn)故障,則在修復(fù)存儲(chǔ)庫(kù)之前,其他開(kāi)發(fā)人員無(wú)法提交他們的代碼。使用 Git,每個(gè)開(kāi)發(fā)人員都有自己的存儲(chǔ)庫(kù),因此中央存儲(chǔ)庫(kù)是否損壞并不重要。開(kāi)發(fā)人員可以繼續(xù)在本地提交代碼,直到中央存儲(chǔ)庫(kù)被修復(fù),然后就可以推送他們的更改;
- 可以離線使用: 與 SVN 不同,Git 可以離線工作,即使網(wǎng)絡(luò)失去連接,也可以繼續(xù)工作而不會(huì)丟失功能。
3. Git 安裝
在Git官網(wǎng)下載、安裝即可:https://git-scm.com/download。
安裝完成之后,可以使用以下命令來(lái)查看 Git 是否安裝成功:
git --version
如果安裝成功,終端會(huì)打印安裝的 Git 的版本:
4. Git 初始化
要給項(xiàng)目初始化一個(gè)Git倉(cāng)庫(kù),可以在終端中打開(kāi)項(xiàng)目目錄,執(zhí)行以下命令即可:
git init
初始化之后,就會(huì)創(chuàng)建一個(gè)名為.git的新子文件夾,其中包含 Git 將用于跟蹤項(xiàng)目更改的多個(gè)文件和更多子目錄:
在使用 Git 進(jìn)行代碼管理時(shí),不希望一些文件出現(xiàn)在跟蹤列表中,比如node_modules文件。這種情況下,可以在項(xiàng)目的根目錄中創(chuàng)建一個(gè)名為.gitignore的文件,在該文件中列出要忽略的文件和文件夾,來(lái)看一個(gè)示例:
# 所有以.md結(jié)尾的文件
*.md
# lib.a不能被忽略
!lib.a
# node_modules和.vscode文件被忽略
node_modules
.vscode
# build目錄下的文件被忽略
build/
# doc目錄下的.txt文件被忽略
doc/*.txt
# doc目錄下多層目錄的所有以.pdf結(jié)尾的文件被忽略
doc/**/*.pdf
注意:以 # 符號(hào)開(kāi)頭的行是注釋。
我們可以在本地克隆Git存儲(chǔ)庫(kù)上的代碼,首先要找到Git存儲(chǔ)庫(kù)上的HTTPS或SSH的地址,如下:
圖片
然后使用以下命令將遠(yuǎn)程倉(cāng)庫(kù)克隆到本地:
git clone https://github.com/facebook/react.git
5. Git 結(jié)構(gòu)和狀態(tài)
從Git的角度來(lái)看,可以在三個(gè)區(qū)域進(jìn)行文件更改:工作區(qū),暫存區(qū)和存儲(chǔ)庫(kù)。
- 工作區(qū): 本地看到的工作目錄;
- 暫存區(qū): 一般存放在 .git 目錄下的 index 文件(.git/index)中,所以暫存區(qū)有時(shí)也叫作索引(index)。暫存區(qū)是一個(gè)臨時(shí)保存修改文件的地方;
- 版本庫(kù): 工作區(qū)有一個(gè)隱藏目錄 .git,這個(gè)不算工作區(qū),而是 Git 的版本庫(kù),版本庫(kù)中存儲(chǔ)了很多配置信息、日志信息和文件版本信息等。
Git 工作目錄下的文件存在兩種狀態(tài):
- untracked:未跟蹤,未被納入版本控制,即該文件沒(méi)有被Git版本管理;
- tracked:已跟蹤,被納入版本控制,即該文件已被Git版本管理。
其中已跟蹤狀態(tài)可以細(xì)分為以下三種狀態(tài):
- Unmodified:未修改狀態(tài)
- Modified:已修改狀態(tài)
- Staged:已暫存狀態(tài)
可以通過(guò)運(yùn)行以下命令來(lái)檢查當(dāng)前分支的狀態(tài):
git status
顯示結(jié)果如下:
此命令不會(huì)更改或更新任何內(nèi)容。它會(huì)打印出哪些文件被修改、暫存或未跟蹤。未跟蹤的文件是尚未添加到 git 索引的文件,而自上次提交以來(lái)已更改的文件將被視為已被 git 修改。
Git 入門
1. 全局配置
當(dāng)安裝Git后首先要做的就是配置所有本地存儲(chǔ)庫(kù)中使用的用戶信息。每次Git提交都會(huì)使用該用戶信息。
config 命令適用于不同的級(jí)別:
- 本地級(jí)別: 所有配置都僅限于項(xiàng)目目錄。默認(rèn)情況下, 如果未通過(guò)任何配置, 則git config將在本地級(jí)別寫入;
- 全局級(jí)別: 此配置特定于操作系統(tǒng)上的用戶,配置值位于用戶的主目錄中;
- 系統(tǒng)級(jí)別: 這些配置放在系統(tǒng)的根路徑下,它跟蹤操作系統(tǒng)上的所有用戶和所有存儲(chǔ)庫(kù)。
下面的配置均為寫入系統(tǒng)級(jí)別:
(1)設(shè)置用戶名
可以使用以下命令設(shè)置使用 Git 時(shí)的用戶名:
git config --global user.name "name"
可以使用以下命令查看設(shè)置的user.name:
git config user.name
(2)設(shè)置郵箱
可以使用以下命令設(shè)置使用 Git 時(shí)的郵箱:
git config --global user.email "email"
可以使用以下命令查看設(shè)置的 email:
git config user.email
(3)設(shè)置命令顏色
除了上述兩個(gè)基本的設(shè)置之外,還可以設(shè)置命令的顏色,以使輸出具有更高的可讀性:
git config --global color.ui auto
(4)查看所有配置
通過(guò)上面的命令設(shè)置的信息會(huì)保存在本地的.gitconfig文件中??梢允褂靡韵旅畈榭此信渲眯畔ⅲ?/p>
git config --list
如果在全局輸入這個(gè)命令,就會(huì)顯示全局的配置:
如果在使用 Git 的項(xiàng)目中輸入該命令,除了會(huì)顯示全局的配置之外,還會(huì)顯式本地倉(cāng)庫(kù)的一些配置信息,如下:
(5)設(shè)置別名
git config 命令為我們提供了一種創(chuàng)建別名的方法,這種別名通常用于縮短現(xiàn)有的命令或者創(chuàng)建自定義命令。來(lái)看一個(gè)例子:
git config --global alias.cm "commit -m"
這里為commit -m創(chuàng)建一個(gè)別名 cm,這樣在提交暫存區(qū)文件時(shí),只需要輸入以下命令即可:
git cm <message>
2. 分支操作
分支是源代碼控制的核心概念,它允許將工作分離到不同的分支中,這樣就可以自由地處理源代碼,而不會(huì)影響其他任何人的工作或主分支中的代碼。下面來(lái)看一些常見(jiàn)的分支操作。
(1)查看分支
可以使用以下命令來(lái)查看當(dāng)然所在的分支以及該項(xiàng)目所有的分支情況:
git branch
該命令可以列出項(xiàng)目所有的本地分支,顯示綠色的分支就是當(dāng)前分支:
可以使用以下命令來(lái)列出所有的遠(yuǎn)程分支:
git branch -r
可以使用以下命令來(lái)查看所有的本地分支和遠(yuǎn)程分支:
git branch -a
(2)創(chuàng)建分支
我們?cè)谟?jì)算機(jī)上只能訪問(wèn)本地分支,在將分支推送到遠(yuǎn)程倉(cāng)庫(kù)之前,需要先創(chuàng)建一個(gè)本地分支。
可以使用以下命令來(lái)創(chuàng)建分支:
git checkout <branch>
加上-b
就可以在創(chuàng)建新的分支之后,直接切換到新創(chuàng)建的分支上:
git checkout -b <branch>
如果想將新建的本地分支推送到遠(yuǎn)程倉(cāng)庫(kù),以在遠(yuǎn)程倉(cāng)庫(kù)添加這個(gè)分支??梢詧?zhí)行以下命令:
git push -u origin <branch>
(3)刪除分支
可以使用以下命令來(lái)刪除本地分支:
git branch -d <branch>
需要注意,在刪除分支之前,要先切換到其他分支,否則就會(huì)報(bào)錯(cuò):
切換到其他分支再刪除即可:
有時(shí) Git 會(huì)拒絕刪除本地分支,因?yàn)橐獎(jiǎng)h的分支可能有未提交的代碼。這是為了保護(hù)代碼以避免意外丟失數(shù)據(jù)??梢允褂靡韵旅顏?lái)強(qiáng)制刪除本地分支:
git branch -D <branch>
這樣就刪除成功了:
當(dāng)然,我們也可以刪除遠(yuǎn)程倉(cāng)庫(kù)分支,執(zhí)行以下命令即可:
git push origin --delete <name>
(4)重命名分支
可以使用以下命令來(lái)將分支重命名:
git branch -m <oldname> <newname>
如果newname名字分支已經(jīng)存在,則需要使用-M來(lái)強(qiáng)制重命名:
git branch -M <oldname> <newname>
(5)合并分支(git merge)
可以使用以下命令將其他分支的代碼合并到當(dāng)前分支:
git merge <branch>
如果想將A分支合并到B分支,就要先切換到B分支,然后執(zhí)行命令:git merge A
。
(6)合并分支(git rebase)
git rebase 用于將一個(gè)分支的提交記錄合并到另一個(gè)分支上。
原理: 通過(guò)找到兩個(gè)分支的最近共同祖先,然后提取當(dāng)前分支相對(duì)于該祖先的歷次提交,保存為臨時(shí)文件。接著,將當(dāng)前分支指向目標(biāo)分支的最新提交,最后依序應(yīng)用之前保存的修改。這樣,就可以將一個(gè)分支上的修改“移動(dòng)”到另一個(gè)分支上,實(shí)現(xiàn)代碼的整合。
使用git rebase的步驟如下:
- 確保在正確的分支上,并且該分支已經(jīng)與遠(yuǎn)程分支同步??梢允褂胓it checkout命令切換到目標(biāo)分支,并使用git pull命令拉取最新的代碼。
- 執(zhí)行g(shù)it rebase命令,并指定要合并的分支。例如,如果你想要將當(dāng)前分支的提交記錄合并到名為feature的分支上,可以執(zhí)行g(shù)it rebase feature命令。
- Git會(huì)開(kāi)始分析兩個(gè)分支的提交記錄,并嘗試自動(dòng)合并它們。如果出現(xiàn)沖突,你需要手動(dòng)解決沖突,并使用git add命令標(biāo)記已解決的文件。然后,使用git rebase --continue命令繼續(xù)合并過(guò)程。
- 如果在合并過(guò)程中遇到無(wú)法自動(dòng)解決的沖突,可以使用git rebase --abort命令中止合并,并返回到原來(lái)的狀態(tài)。
- 一旦所有提交記錄都成功合并,可以使用git push命令將更改推送到遠(yuǎn)程倉(cāng)庫(kù)。
假設(shè)有一個(gè)名為feature的分支,它包含了一些新功能的開(kāi)發(fā)代碼。同時(shí),還有一個(gè)名為master的主分支,用于發(fā)布穩(wěn)定版本的代碼。現(xiàn)在,想要將feature分支上的代碼合并到master分支上。首先,切換到master分支,并拉取最新的代碼:
git checkout master
git pull origin master
然后,執(zhí)行rebase命令,將feature分支的提交記錄合并到master分支上:
git rebase feature
Git會(huì)開(kāi)始分析兩個(gè)分支的提交記錄,并嘗試自動(dòng)合并它們。如果出現(xiàn)沖突,需要手動(dòng)解決沖突,并使用git add命令標(biāo)記已解決的文件。例如,假設(shè)在合并過(guò)程中出現(xiàn)了一個(gè)名為conflict.txt的文件沖突,你可以使用文本編輯器打開(kāi)該文件,解決沖突,然后執(zhí)行以下命令:
git add conflict.txt
git rebase --continue
一旦所有沖突都解決并且所有提交記錄都成功合并,可以使用git push命令將更改推送到遠(yuǎn)程倉(cāng)庫(kù):
git push origin master
這樣就成功地將feature分支上的代碼合并到了master分支上,并保持了提交歷史的清晰和整潔。
git rebase和git merge都是用于將不同分支的代碼整合到一起的Git命令,但它們?cè)趯?shí)現(xiàn)方式、結(jié)果和適用場(chǎng)景上有一些區(qū)別。
- 實(shí)現(xiàn)方式:git merge是通過(guò)找到兩個(gè)分支的最佳同源合并點(diǎn),將兩個(gè)分支中的所有提交都合并到一起,并創(chuàng)建一個(gè)新的合并提交。而git rebase則是通過(guò)找到兩個(gè)分支的最近共同祖先,提取當(dāng)前分支相對(duì)于該祖先的歷次提交,然后將當(dāng)前分支指向目標(biāo)分支的最新提交,最后依序應(yīng)用之前保存的修改。
- 結(jié)果:從最終效果來(lái)看,git merge和git rebase都是將不同分支的代碼融合在一起。但是,它們生成的代碼樹(shù)稍有不同。git merge會(huì)生成一個(gè)新的合并點(diǎn),保留了歷史記錄中的多個(gè)分支合并點(diǎn),使得歷史記錄更加復(fù)雜。而git rebase則會(huì)將提交歷史“拉直”,使得提交歷史看起來(lái)像是一條直線,沒(méi)有分叉,歷史記錄更加簡(jiǎn)潔。
- 適用場(chǎng)景:git merge適用于保留完整的提交歷史,因?yàn)樗A袅嗣總€(gè)分支的合并點(diǎn),有助于追蹤歷史記錄。它是更為保守的合并方法,相對(duì)簡(jiǎn)單。而git rebase適用于追求整潔的提交歷史,因?yàn)樗ㄟ^(guò)重寫歷史記錄來(lái)避免不必要的合并提交和分叉。然而,使用rebase時(shí)需要更多的注意力和精細(xì)的操作,因?yàn)樗赡軐?dǎo)致原有的提交變得不可用。
3. 基礎(chǔ)操作
Git 數(shù)據(jù)工作流程如下:
(1)暫存文件
可以使用以下命令來(lái)暫存已修改的文件,命令最后需要指定要暫存的文件名稱:
git add <filename>
如果想要將所有未跟蹤和修改的文件添加到暫存區(qū),可以執(zhí)行以下命令:
git add .
此時(shí)分支的狀態(tài)如下:
(2)提交暫存
可以使用以下命令將暫存區(qū)的文件修改提交到本地倉(cāng)庫(kù),
git commit -m "meaasge"
其中-m參數(shù)表示message日志信息,參數(shù)后面要加一個(gè)日志信息,用雙引號(hào)括起來(lái)。
此時(shí)分支的狀態(tài)如下:
如果上次提交暫存的messge寫錯(cuò)了怎么辦呢?可以使用使用以下命令來(lái)更新提交,而不需要撤銷并重新提交:
git commit --amend -m <message>
如果有一個(gè)新的文件修改,也想提交到上一個(gè)commit中,可以使用以下命令來(lái)保持相同的提交信息:
git add .
git commit --amend --no-edit
(3)存儲(chǔ)更改
假如我們正在開(kāi)發(fā)迭代功能,但是還沒(méi)開(kāi)發(fā)完。這時(shí)有一個(gè)緊急的bug需要修復(fù)上線??赡芫托枰袚Q到一個(gè)hotfix分支去修復(fù)bug。這時(shí)對(duì)于開(kāi)發(fā)了一部分的功能創(chuàng)建提交是沒(méi)有邏輯意義的。可以使用以下任一命令來(lái)存儲(chǔ)修改的內(nèi)容:
git stash
git stash push
git stash push -m "<stash message>"
該命令回保存所有未提交的更改并恢復(fù)到上次提交時(shí)存儲(chǔ)庫(kù)的狀態(tài)。
當(dāng)想再次繼續(xù)開(kāi)發(fā)此功能時(shí),就可以使用以下命令檢查所有存儲(chǔ):
git stash list
這時(shí)終端中就會(huì)顯示帶有時(shí)間戳的所有已經(jīng)暫存的列表??梢允褂靡韵氯我幻顏?lái)取回所有的更改:
git stash apply
git stash pop
apply 和 pop 之間的區(qū)別在于,pop 應(yīng)用了 stash 中的更改并將其也從 stash 中刪除,但 apply 即使在應(yīng)用后仍將更改保留在 stash 中。
可以使用以下任一命令應(yīng)用存儲(chǔ)列表中的第 N 個(gè)存儲(chǔ):
git stash apply stash@{N}
git stash apply <n>
整個(gè)過(guò)程的輸出如下:
(4)合并指定提交
在不同分支之間進(jìn)行代碼合并時(shí),通常會(huì)有兩種情況:一種情況是需要另一個(gè)分支的所有代碼變動(dòng),那么就可以直接合并(git merge),另一種情況是只需要部分代碼的變動(dòng)(某幾次提交),這時(shí)就可以使用以下命令來(lái)合并指定的提交:
git cherry-pick <commit hash>
建議添加 -x 標(biāo)志,因?yàn)樗鼤?huì)生成標(biāo)準(zhǔn)化的提交消息,通知用戶它是從哪里pick出來(lái)的:
git cherry-pick -x <commit hash>
那么這個(gè)commit hash是從哪里來(lái)的呢?可以在需要被合并的分支上執(zhí)行以下命令:
git log
這時(shí)終端就會(huì)顯示出所有的提交信息:
這里黃色文字中commit后面的部分就是commit hash,復(fù)制即可。
(5)檢查提交
Git允許我們?cè)诒镜貦z查特定的提交。輸入以下命令就可以查看有關(guān)當(dāng)前提交的詳細(xì)信息:
git show
輸出的結(jié)構(gòu)如下,可以看到,它顯示出了上次提交的commit id、作者信息(郵箱和姓名)、提交日期、commit message、代碼diff等:
還可以使用HEAD~n語(yǔ)法或提交哈希來(lái)檢查過(guò)去的提交。使用以下命令就可以獲取往前數(shù)的第三次提交的詳細(xì)信息:
git show HEAD~3
除此之外,還可以添加一個(gè)--oneline標(biāo)志,以簡(jiǎn)化輸出信息:
git show --oneline
這樣提交信息就簡(jiǎn)潔了很多:
(6)查看貢獻(xiàn)者
可以使用以下命令來(lái)返回每個(gè)貢獻(xiàn)者的commit次數(shù)以及每次commit的commit message:
$ git shortlog
其可以添加兩個(gè)參數(shù):
- s:省略每次 commit 的注釋,僅僅返回一個(gè)簡(jiǎn)單的統(tǒng)計(jì)。
- n:按照 commit 數(shù)量從多到少的順利對(duì)用戶進(jìn)行排序。
加上這兩個(gè)參數(shù)之后就可以看到每個(gè)用戶中的提交次數(shù)以及排名情況:
git shortlog -sn
這樣就會(huì)顯示出該項(xiàng)目所有貢獻(xiàn)者的commit次數(shù),從上到下依次減?。?/p>
除此之外,還可以添加一個(gè)--no-merges標(biāo)志,以忽略合并提交的次數(shù):
git shortlog -sn --no-merges
(7)倉(cāng)庫(kù)提交歷史
git rev-list 用于列出倉(cāng)庫(kù)中的提交(commit)記錄。它按照時(shí)間倒序顯示提交記錄,并可以根據(jù)不同的選項(xiàng)和參數(shù)進(jìn)行篩選和排序。
下面是git rev-list的一些基本用法:
列出所有提交記錄:
git rev-list
這將顯示倉(cāng)庫(kù)中所有的提交記錄,按照時(shí)間倒序排列。每個(gè)提交記錄都有一個(gè)唯一的SHA-1哈希值作為標(biāo)識(shí)。
列出某個(gè)分支的提交記錄:
git rev-list <branch-name>
將<branch-name>替換為你要查看的分支的名稱。這將顯示該分支上的所有提交記錄。
列出某個(gè)提交之后的提交記錄:
git rev-list <commit-id>..
將<commit-id>替換為你要查看的提交的SHA-1哈希值。這將顯示該提交之后的所有提交記錄。
列出兩個(gè)提交之間的提交記錄:
git rev-list <commit-id1>..<commit-id2>
將<commit-id1>和<commit-id2>替換為你要查看的兩個(gè)提交的SHA-1哈希值。這將顯示從<commit-id1>到<commit-id2>之間的所有提交記錄。
列出某個(gè)文件的所有提交記錄:
bash復(fù)制代碼
git rev-list -- <file-path>
將<file-path>替換為你要查看的文件的路徑。這將顯示涉及該文件的所有提交記錄。
(8)添加注釋或備注
git notes允許用戶為Git對(duì)象(如提交、樹(shù)、標(biāo)簽等)添加注釋或備注信息。這些注釋信息是以鍵值對(duì)的形式存儲(chǔ)的,其中鍵是一個(gè)唯一的引用,而值則是與該引用關(guān)聯(lián)的注釋內(nèi)容。
要使用git notes,可以按照以下步驟進(jìn)行操作:
添加注釋:使用git notes add -m "Your note message" <object>命令向一個(gè)對(duì)象添加注釋。例如,要向提交abc123添加注釋,可以執(zhí)行g(shù)it notes add -m "This is a note for commit abc123" abc123。
- 顯示注釋:使用git notes show <object>命令顯示一個(gè)對(duì)象的注釋內(nèi)容。例如,要顯示提交abc123的注釋,可以執(zhí)行g(shù)it notes show abc123。
- 編輯注釋:如果要編輯已存在的注釋,可以使用git notes edit <object>命令。這將打開(kāi)文本編輯器,允許編輯已存在的注釋內(nèi)容。編輯完成后,保存并關(guān)閉編輯器即可。
- 顯示所有注釋:使用git notes list命令可以顯示所有對(duì)象的注釋信息。這將列出所有帶有注釋的Git對(duì)象及其對(duì)應(yīng)的注釋內(nèi)容。
(9)追溯文件歷史修改記錄
git blame 用于追溯文件歷史修改記錄,它可以顯示指定文件中每一行代碼的最后修改者以及修改時(shí)間,幫助開(kāi)發(fā)者了解代碼的演變過(guò)程。
以按照以下步驟使用git blame命令:
- 打開(kāi)終端或命令行界面,并導(dǎo)航到Git倉(cāng)庫(kù)的根目錄。
- 運(yùn)行g(shù)it blame <file>命令,其中<file>是要查看歷史修改記錄的文件的路徑。
git blame命令將列出文件的每一行,并顯示最后一次修改該行的提交信息,包括提交的哈希值、作者、修改時(shí)間和提交注釋等。這樣,你可以輕松地找到代碼中引入bug的提交,或者識(shí)別特定代碼段的貢獻(xiàn)者。
除了基本的用法,git blame命令還接受一些參數(shù)來(lái)調(diào)整輸出。例如,使用-L <start>,<end>參數(shù)可以指定查看的行范圍,只顯示指定行范圍內(nèi)的代碼修改信息。使用-p參數(shù)可以顯示每一行的詳細(xì)信息,包括提交的哈希值、作者、時(shí)間戳和行號(hào)。此外,還可以使用-C和-M選項(xiàng)來(lái)查找代碼重命名和移動(dòng)的情況,以便更好地追蹤代碼的變化。
(10)創(chuàng)建存檔
git archive 用于創(chuàng)建存檔(archive)文件,通常是一個(gè)壓縮文件,包含了Git倉(cāng)庫(kù)中的特定文件或目錄。這個(gè)命令允許你將Git倉(cāng)庫(kù)中的文件打包成一個(gè)獨(dú)立的文件,方便備份、傳輸或發(fā)布。
要使用git archive命令,需要指定存檔文件的格式(如.zip、.tar等),以及要包含的文件或目錄。以下是一些常用的git archive命令的用法:
- 創(chuàng)建tar格式的存檔文件,包含當(dāng)前分支的最新代碼:
git archive --format=tar --prefix=my-project/ HEAD | gzip > my-project.tar.gz
這個(gè)命令將創(chuàng)建一個(gè)名為my-project.tar.gz的壓縮文件,其中包含了當(dāng)前分支(HEAD)的最新代碼。--prefix選項(xiàng)用于在存檔文件中添加一個(gè)前綴目錄my-project/。
- 創(chuàng)建zip格式的存檔文件,只包含指定的文件或目錄:
git archive --format=zip --output=my-files.zip path/to/file1 path/to/file2
這個(gè)命令將創(chuàng)建一個(gè)名為my-files.zip的壓縮文件,其中只包含了指定的文件或目錄。你可以通過(guò)路徑來(lái)指定要包含的文件或目錄。
注意,git archive命令只會(huì)包含文件的當(dāng)前版本,而不會(huì)包含Git的元數(shù)據(jù)(如提交歷史、分支信息等)。因此,存檔文件主要用于備份或發(fā)布代碼,而不是作為完整的Git倉(cāng)庫(kù)來(lái)使用。
(11)驗(yàn)證提交
git verify-commit用于驗(yàn)證提交(commit)的GPG簽名。GPG(GNU Privacy Guard)是一種加密軟件,可以用于為Git提交添加數(shù)字簽名,以確保提交的完整性和真實(shí)性。
要使用git verify-commit命令,需要先確保已經(jīng)為Git配置了GPG簽名,并且至少有一個(gè)提交是帶有GPG簽名的。然后按照以下步驟進(jìn)行操作:
- 打開(kāi)終端或命令行界面,并導(dǎo)航到Git倉(cāng)庫(kù)的根目錄。
- 運(yùn)行g(shù)it verify-commit <commit>命令,其中<commit>是要驗(yàn)證的提交的哈希值或引用(如分支名、標(biāo)簽名等)。
git verify-commit命令將檢查指定提交的GPG簽名,并輸出驗(yàn)證結(jié)果。如果簽名有效且未被篡改,命令將顯示“Good signature”或類似的消息。如果簽名無(wú)效或存在問(wèn)題,命令將顯示相應(yīng)的錯(cuò)誤消息。
除了基本的用法,git verify-commit命令還接受一些參數(shù)來(lái)調(diào)整輸出和行為。例如,使用--raw參數(shù)可以打印原始的GPG狀態(tài)輸出,而不是人類可讀的輸出。使用--verbose參數(shù)可以打印提交對(duì)象的詳細(xì)內(nèi)容,以便更詳細(xì)地了解驗(yàn)證過(guò)程。
注意,要使用git verify-commit命令,必須已經(jīng)為Git配置了GPG簽名,并且至少有一個(gè)提交是帶有GPG簽名的。如果提交沒(méi)有簽名或簽名無(wú)效,該命令將無(wú)法驗(yàn)證提交的真實(shí)性。
4. 遠(yuǎn)程操作
(1)查看遠(yuǎn)程倉(cāng)庫(kù)
可以使用以下命令來(lái)查看遠(yuǎn)程倉(cāng)庫(kù):
git remote
該命令會(huì)列出指定的每一個(gè)遠(yuǎn)程服務(wù)器的簡(jiǎn)寫。如果已經(jīng)克隆了遠(yuǎn)程倉(cāng)庫(kù),那么至少應(yīng)該能看到 origin ,這是 Git 克隆的倉(cāng)庫(kù)服務(wù)器的默認(rèn)名字:
可以執(zhí)行以下命令來(lái)獲取遠(yuǎn)程倉(cāng)庫(kù)的地址:
git remote -v
其中fetch是獲取,push是推送:
可以使用以下命令來(lái)查看更加詳細(xì)的信息:
git remote show origin
輸出結(jié)果如下:
(2)添加遠(yuǎn)程倉(cāng)庫(kù)
可以使用以下命令來(lái)將本地項(xiàng)目鏈接到遠(yuǎn)程倉(cāng)庫(kù):
git remote add <remote_name> <remote_url>
其中:
- remote_name:倉(cāng)庫(kù)名稱(默認(rèn)是origin)
- remote_url:遠(yuǎn)程倉(cāng)庫(kù)地址
該命令允許 Git 跟蹤遠(yuǎn)程存儲(chǔ)庫(kù)并將本地存儲(chǔ)庫(kù)連接到遠(yuǎn)程倉(cāng)庫(kù)。
(3)移除遠(yuǎn)程倉(cāng)庫(kù)
可以使用命令來(lái)移除遠(yuǎn)程倉(cāng)庫(kù):
git remote rm origin
需要注意,該命令只是從本地移除遠(yuǎn)程倉(cāng)庫(kù)的記錄(也就是解除本地倉(cāng)庫(kù)和遠(yuǎn)程倉(cāng)庫(kù)的關(guān)系),并不會(huì)真正影響到遠(yuǎn)程倉(cāng)庫(kù)。
(4)從遠(yuǎn)程倉(cāng)庫(kù)抓取與拉取
可以使用以下命令來(lái)從遠(yuǎn)程倉(cāng)庫(kù)獲取最新版本到本地倉(cāng)庫(kù),不會(huì)自動(dòng)merge(合并數(shù)據(jù)):
git fetch
由于該命令不會(huì)自定合并數(shù)據(jù),所以該命令執(zhí)行完后需要手動(dòng)執(zhí)行 git merge 遠(yuǎn)程分支到所在的分支。
可以使用以下命令來(lái)將遠(yuǎn)程指定分支拉取到本地指定分支上:
git pull origin <遠(yuǎn)程分支名>:<本地分支名>
使用以下命令來(lái)將遠(yuǎn)程指定分支拉取到本地當(dāng)前分支上:
git pull origin <遠(yuǎn)程分支名>
使用以下命令開(kāi)將與本地當(dāng)前分支同名的遠(yuǎn)程分支拉取到本地當(dāng)前分支上:
git pull
注意:如果當(dāng)前本地倉(cāng)庫(kù)不是從遠(yuǎn)程倉(cāng)庫(kù)克隆,而是本地創(chuàng)建的倉(cāng)庫(kù),并且倉(cāng)庫(kù)中存在文件,此時(shí)再?gòu)倪h(yuǎn)程倉(cāng)庫(kù)拉取文件的時(shí)候會(huì)報(bào)錯(cuò)(fatal: refusing to merge unrelated histories ),解決此問(wèn)題可以在git pull命令后加入?yún)?shù)--allow-unrelated-histories,即:
git pull --allow-unrelated-histories
(5)推送到遠(yuǎn)程倉(cāng)庫(kù)
可以使用以下命令將本地指定分支推送到遠(yuǎn)程指定分支上:
git push origin <本地分支名>:<遠(yuǎn)程分支名>
可以使用以下命令將本地指定分支推送到與本地當(dāng)前分支同名的遠(yuǎn)程分支上:
git push origin <本地分支名>
使用以下命令將本地當(dāng)前分支推送到與本地當(dāng)前分支同名的遠(yuǎn)程分支上:
git push
可以使用以下命令來(lái)將本地分支與遠(yuǎn)程同名分支相關(guān)聯(lián):
git push -u origin <本地分支名>
由于遠(yuǎn)程庫(kù)是空的,第一次推送master分支時(shí),加上了-u參數(shù),Git不但會(huì)把本地的master分支內(nèi)容推送的遠(yuǎn)程新的master分支,還會(huì)把本地的master分支和遠(yuǎn)程的master分支關(guān)聯(lián)起來(lái),在以后的推送或者拉取時(shí)就可以簡(jiǎn)化命令為git push。
Git 進(jìn)階
1. 修改操作
如果只是簡(jiǎn)單地從工作目錄中手工刪除文件,運(yùn)行 git status 時(shí)就會(huì)在 Changes not staged for commit 的提示
(1)刪除文件
可以使用以下命令將文件從暫存區(qū)和工作區(qū)中刪除:
git rm <filename>
如果刪除之前修改過(guò)并且已經(jīng)放到暫存區(qū)域的話,則必須要用強(qiáng)制刪除選項(xiàng) -f:
git rm -f <filename>
如果想把文件從暫存區(qū)域移除,但仍然希望保留在當(dāng)前工作目錄中,換句話說(shuō),僅是從跟蹤清單中刪除,使用 --cached 選項(xiàng)即可:
git rm --cached <filename>
可以使用以下命令進(jìn)行遞歸刪除,即如果后面跟的是一個(gè)目錄做為參數(shù),則會(huì)遞歸刪除整個(gè)目錄中的所有子目錄和文件:
git rm –r *
進(jìn)入某個(gè)目錄中,執(zhí)行此語(yǔ)句,就會(huì)刪除該目錄下的所有文件和子目錄。
(2)取消修改
取消修改有三種情況:
未使用 git add 將修改文件添加到暫存區(qū)這種情況下,可以使用以下命令來(lái)撤銷所有還沒(méi)有加入到緩存區(qū)的修改:
git checkout -- <filename>
需要注意,此文件不會(huì)刪除新建的文件,因?yàn)樾陆ǖ奈募€沒(méi)加入到Git管理系統(tǒng)重,所以對(duì)Git來(lái)說(shuō)事未知的,需要手動(dòng)刪除。
已使用 git add 將修改文件添加到暫存區(qū),未使用 git commit 提交緩存這種情況下,相當(dāng)于撤銷了 git add 命令對(duì)于文件修改的緩存:
git reset HEAD <filename>
上面的命令可以撤銷指定文件的緩存,要想放棄所有文件的緩存,可以執(zhí)行以下命令:
git reset HEAD
需要注意,在使用此命令后,本地的修改并不會(huì)消失,而會(huì)回到第一種情況。要想撤銷本地的修改,執(zhí)行第一種情況中的命令即可。
除此之外,還可以指定返回到N次提交之前的階段,執(zhí)行以下命令即可:
git reset HEAD~N
這樣就能退回到n個(gè)版本之前,同樣不會(huì)修改本地文件的內(nèi)容,這些新的內(nèi)容會(huì)變成未更新到緩存區(qū)的狀態(tài)。
已使用 git commit 提交緩存這種情況下,可以使用以下命令來(lái)回退到上一次 commit 的狀態(tài):
git reset --hard HEAD^
也可以使用以下命令來(lái)回退到任意版本:
git reset --hard <commit_id>
注意,使用 git log 命令來(lái)查看 git 提交歷史和 commit id。
(3)恢復(fù)刪除內(nèi)容
這是一個(gè)很重要的命令,假如回退到某個(gè)舊版本,現(xiàn)在想恢復(fù)到新版本,又找不到新版本的commit id怎么辦?Git 提供了下面的命令用來(lái)記錄每一次命令:
git reflog show HEAD
git reflog
執(zhí)行之后輸出如下:
可以看到,最左側(cè)黃色字體就是修改的 commit id,根據(jù)這個(gè)id就可以將代碼恢復(fù)到對(duì)應(yīng)節(jié)點(diǎn)位置。HEAD@{n}表示HEAD更改歷史記錄,最近的操作在上面。
假如需要把代碼回退到HEAD@{5}處,可以執(zhí)行以下命令:
git reset --hard HEAD@{5}
或者執(zhí)行下面的命令:
git reset --hard 8a0fd74
需要注意,如果有任何本地修改,該命令也會(huì)將其銷毀,因此在reset
之前建議使用stash
將本地修改儲(chǔ)存。
(4)刪除未跟蹤文件
git clean 用于從工作目錄中刪除未跟蹤的文件。這些文件通常是那些由編輯器、構(gòu)建過(guò)程或其他工具生成的臨時(shí)文件或副產(chǎn)品,而不是Git倉(cāng)庫(kù)中的一部分。使用git clean命令可以幫助保持工作目錄的整潔,避免這些未跟蹤的文件干擾正常的Git操作或?qū)е乱馔獾奶峤弧?/p>
git clean命令的基本語(yǔ)法如下:
git clean [-dfnxq] [-e <pattern>] [-i] [-n] [-f] [-r | -R] [<path>...]
下面是一些常用的選項(xiàng)和參數(shù):
- -d:刪除未跟蹤的目錄和文件。默認(rèn)情況下,git clean只刪除未跟蹤的文件。
- -f:強(qiáng)制執(zhí)行刪除操作,不會(huì)提示用戶確認(rèn)。
- -n:僅顯示將要?jiǎng)h除的文件和目錄列表,而不實(shí)際刪除它們。這可以用于檢查將要?jiǎng)h除的內(nèi)容。
- -x:刪除所有未跟蹤的文件和目錄,包括被.gitignore文件忽略的文件和目錄。
- -q:靜默模式,不輸出任何信息。
- -e <pattern>:指定要排除的文件模式??梢允褂猛ㄅ浞麃?lái)匹配要排除的文件或目錄。
- -i:交互式模式,會(huì)提示用戶確認(rèn)每個(gè)要?jiǎng)h除的文件或目錄。
- <path>...:指定要清理的路徑。如果不指定路徑,將默認(rèn)清理整個(gè)工作目錄。
以下是一些使用git clean命令的示例:
刪除所有未跟蹤的文件和目錄:
git clean -df
僅顯示將要?jiǎng)h除的文件和目錄列表:
git clean -n
強(qiáng)制執(zhí)行刪除操作,不提示用戶確認(rèn):
git clean -f
刪除所有未跟蹤的文件和目錄,包括被.gitignore文件忽略的內(nèi)容:
git clean -dfx
注意,使用git clean命令時(shí)要小心,確保不會(huì)誤刪除重要的文件。在執(zhí)行刪除操作之前,最好先使用-n選項(xiàng)來(lái)預(yù)覽要?jiǎng)h除的內(nèi)容。
git rm 和 git clean 都是刪除文件,那他們之間有什么區(qū)別呢?
- git rm主要用于從暫存區(qū)及版本庫(kù)中刪除已跟蹤的文件。換句話說(shuō),這個(gè)命令針對(duì)的是已經(jīng)被Git管理的文件。如果你嘗試使用git rm刪除一個(gè)未被Git跟蹤的文件,它將不會(huì)有任何效果。
- git clean命令則主要用于刪除工作區(qū)中的未跟蹤文件,即那些未被Git管理的文件。這些文件可能是由編輯器、構(gòu)建過(guò)程或其他工具生成的臨時(shí)文件或副產(chǎn)品。git clean操作其實(shí)更像純粹的rm命令,但能夠方便地刪除未跟蹤文件。
2. 標(biāo)簽操作
標(biāo)簽指的是某個(gè)分支某個(gè)特定時(shí)間點(diǎn)的狀態(tài),通過(guò)標(biāo)簽可以很方便的了解到標(biāo)記時(shí)的狀態(tài)。
標(biāo)簽有兩種類型 :
- 輕量標(biāo)簽 : 只是某個(gè)commit 的引用,可以理解為是一個(gè)commit的別名;
- 附注標(biāo)簽 : 存儲(chǔ)在Git倉(cāng)庫(kù)中的一個(gè)完整對(duì)象,包含打標(biāo)簽者的名字、電子郵件地址、日期時(shí)間 以及其他的標(biāo)簽信息。它是可以被校驗(yàn)的,可以使用 GNU Privacy Guard (GPG) 簽名并驗(yàn)證。
(1)展示標(biāo)簽
可以使用以下命令來(lái)獲取所有標(biāo)簽:
git tag
它會(huì)列出所有標(biāo)簽的名稱:
可以使用以下命令來(lái)查看某一個(gè)標(biāo)簽的詳細(xì)信息:
git show <tag_name>
還可以根據(jù)條件來(lái)顯示標(biāo)簽,比如列出以v1.開(kāi)頭的所有tag:
git tag -l "v1."
(2)創(chuàng)建標(biāo)簽
可以使用以下命令在本地創(chuàng)建新標(biāo)簽:
git tag <tag_name>
例如:
git tag v1.0.0
通常遵循的命名模式如下:
v<major>.<minor>.<patch>
- major(主版本號(hào)):重大變化
- minor(次要版本號(hào)):版本與先前版本兼容
- patch(補(bǔ)丁號(hào)):bug修復(fù)
除此之外,我們還可以為特定的commit創(chuàng)建標(biāo)簽,其命令格式如下:
git tag <tagname> <commit_sha>
以上面的的形式創(chuàng)建的標(biāo)簽都屬于輕量標(biāo)簽,下面來(lái)看看如何創(chuàng)建一個(gè)附注標(biāo)簽。
在創(chuàng)建標(biāo)簽時(shí),可以添加一個(gè)-a
標(biāo)志以創(chuàng)建一個(gè)帶備注的標(biāo)簽,備注信息使用-m message
來(lái)指定:
git tag -a <tagname> -m "<message>"
(3)推送標(biāo)簽
標(biāo)簽創(chuàng)建完成之后就可以使用以下命令將其推送到遠(yuǎn)程倉(cāng)庫(kù):
git push origin --tags
以上命令會(huì)將本地所有tag都推送到遠(yuǎn)程倉(cāng)庫(kù)。如果想推送指定標(biāo)簽,可以執(zhí)行以下命令:
git push origin <tagname>
(4)切換標(biāo)簽
可以使用以下命令來(lái)切換標(biāo)簽:
git checkout <tagname>
(5)刪除標(biāo)簽
可以使用以下命令來(lái)刪除本地倉(cāng)庫(kù)指定標(biāo)簽:
git tag -d <tagname>
可以使用以下命令來(lái)刪除遠(yuǎn)程倉(cāng)庫(kù)指定標(biāo)簽:
git push origin :refs/tags/<tagname>
也可以使用以下命令來(lái)刪除遠(yuǎn)程倉(cāng)庫(kù)的指定標(biāo)簽:
git push origin --delete <tagname>
(6)拉取標(biāo)簽
可以使用以下命令來(lái)將遠(yuǎn)程倉(cāng)庫(kù)的標(biāo)簽拉?。ㄍ剑┑疆?dāng)前分支:
git fetch --tags
(7)檢出標(biāo)簽
檢出標(biāo)簽實(shí)際上就是在標(biāo)簽的基礎(chǔ)上進(jìn)行其他開(kāi)發(fā)或操作。需要以標(biāo)簽指定的版本為基礎(chǔ)版本,新建一個(gè)分支,繼續(xù)其他的操作。執(zhí)行以下命令即可:
git checkout -b <branch> <tagname>
(8)驗(yàn)證標(biāo)簽
git verify-tag 用于驗(yàn)證標(biāo)簽(tag)的 GPG 簽名。GPG(GNU Privacy Guard)是一種用于文件簽名的工具,它可以確保標(biāo)簽的完整性和真實(shí)性,防止標(biāo)簽被篡改或偽造。
要使用 git verify-tag 命令,需要先確保已經(jīng)為 Git 配置了 GPG 簽名。然后,可以按照以下步驟進(jìn)行操作:
- 打開(kāi)終端或命令行界面,并導(dǎo)航到 Git 倉(cāng)庫(kù)的根目錄。
- 運(yùn)行 git verify-tag <tag> 命令,其中 <tag> 是要驗(yàn)證的標(biāo)簽名稱。
git verify-tag 命令將檢查指定標(biāo)簽的 GPG 簽名,并輸出驗(yàn)證結(jié)果。如果簽名有效且未被篡改,命令將顯示 "Good signature" 或類似的消息。如果簽名無(wú)效或存在問(wèn)題,命令將顯示相應(yīng)的錯(cuò)誤消息。
除了基本的用法,git verify-tag 命令還接受一些參數(shù)來(lái)調(diào)整輸出和行為。例如,使用 --raw 參數(shù)可以打印原始的 GPG 狀態(tài)輸出,而不是人類可讀的輸出。使用 --verbose 參數(shù)可以打印標(biāo)簽對(duì)象的詳細(xì)內(nèi)容,以便更詳細(xì)地了解驗(yàn)證過(guò)程。
3. 日志記錄
(1)基礎(chǔ)日志
可以使用以下命令來(lái)查看分支的歷史提交信息:
git log
這是其最基礎(chǔ)的用法,輸出如下:
可以看到,終端上輸出了該分支近期的提交記錄,它包含了所有貢獻(xiàn)者的提交。
(2)按作者查看
如果想只看某個(gè)人的提交,可以添加過(guò)濾條件:
git log --author="username"
當(dāng)然也可以搜索多個(gè)作者的提交信息,只需要在用|分隔用戶名即可,注意需要使用\來(lái)對(duì)|進(jìn)行轉(zhuǎn)義:
git log --author="username1\|usernmae2"
這里列出的是每次提交的詳細(xì)信息,如果指向看到每個(gè)提交的概要,可以在命令中添加--oneline
標(biāo)志:
git log --author="username" --oneline
(3)按時(shí)間查看
除了可以按照作者來(lái)查看日志之外,還可以按照時(shí)間查看日志??梢圆榭茨硞€(gè)時(shí)間之前的日志,也可以查看某個(gè)日期之后的日志:
//某個(gè)日期之后
git log --since=<date>
git log --after=<date>
//某個(gè)日期之前
git log --until=<date>
git log --before=<date>
如果想查看某個(gè)具體時(shí)間區(qū)間之間的日志,可以組合以上參數(shù):
git log --since="2022.05.15" --until="2022.05.20"
(4)按文件查看
如果我們想查看某個(gè)文件都在哪些提交中修改了內(nèi)容,也是可以的。使用以下命令即可:
git log -- <path>
比如查看README.md文件的修改記錄:
(5)按合并查看
在歷史提交中可能會(huì)有很多次合并的提交記錄,想要只查看代碼合并的記錄,可以執(zhí)行以下命令:
git log --merges
如果想查看非合并操作的操作記錄,可以執(zhí)行以下命令:
git log --no-merges
(6)按分支查看
可以按照分支查看日志,如果想查看test分支比master分支多提交了哪些內(nèi)容,就可以執(zhí)行以下命令:
git log master..test
相反,如果想看master分支比test分支多提交了哪些內(nèi)容,就可以執(zhí)行以下命令:
git log test..master
(7)美化日志
git log命令可以用來(lái)查看提交歷史,此命令的問(wèn)題在于,隨著項(xiàng)目復(fù)雜性的增加,輸出變得越來(lái)越難閱讀??梢允褂靡韵旅顏?lái)美化日志的輸出:
git log --graph --oneline --decorate
輸出結(jié)果如下,這樣就能看到更簡(jiǎn)潔的細(xì)分以及不同分支如何連接在一起:
(8)其他標(biāo)志
上面我們提到了,可以使用--oneline標(biāo)志來(lái)簡(jiǎn)化日志的輸出:
git log --oneline
可以使用--stat標(biāo)志來(lái)簡(jiǎn)要顯示文件增改行數(shù)統(tǒng)計(jì),每個(gè)提交都列出了修改過(guò)的文件,以及其中添加和移除的行數(shù),并在最后列出所有增減行數(shù)小計(jì):
git log --stat
可以添加-N標(biāo)志來(lái)僅顯示最近N次的提交,其中N是一個(gè)正整數(shù),例如查看最近三次提交:
git log -3
可以使用-p標(biāo)志來(lái)展開(kāi)顯示每次提交的內(nèi)容差異對(duì)比:
git log -p
注意,以上這些命令標(biāo)識(shí)符都可以組合使用。
4. 差異對(duì)比
git diff 命令可以用來(lái)比較文件的不同,即比較文件在暫存區(qū)和工作區(qū)的差異。
(1)未緩存改動(dòng)
當(dāng)工作區(qū)有改動(dòng),暫存區(qū)為空時(shí), diff對(duì)比的是工作區(qū)與最后一次commit提交的共同文件;當(dāng)工作區(qū)有改動(dòng),暫存區(qū)不為空時(shí),diff對(duì)比的是工作區(qū)與暫存區(qū)的共同文件。
(2)已緩存改動(dòng)
當(dāng)已緩存改動(dòng)時(shí),可以使用以下任一命令來(lái)顯示暫存區(qū)(已a(bǔ)dd但未commit文件)和最后一次commit(HEAD)之間的所有不相同文件的差異對(duì)比:
git diff --cached
git diff --staged
(3)已緩存和未緩存改動(dòng)
可以使用以下命令來(lái)顯示工作目錄(已修改但未add文件)和暫存區(qū)(已a(bǔ)dd但未commit文件)與最后一次commit之間的的所有不相同文件的差異對(duì)比:
git diff HEAD
(4)不同分支差異
可以使用以下命令來(lái)比較兩個(gè)分支上最后 commit 的內(nèi)容的差別:
git diff <分支名1> <分支名2>
這樣就可以顯示出兩個(gè)分支的詳細(xì)差異,如果只是想看有哪些文件存在差異,可以在命令中添加--stat
標(biāo)志,這樣就不會(huì)顯示每個(gè)文件的內(nèi)容的詳細(xì)對(duì)比:
git diff <分支名1> <分支名2> --stat
5. 定位問(wèn)題
git bisect 采用二分查找算法來(lái)幫助開(kāi)發(fā)者快速定位引入問(wèn)題的提交。當(dāng)在代碼庫(kù)中遇到錯(cuò)誤,但不確定何時(shí)引入時(shí),git bisect可以顯著提高查找錯(cuò)誤的效率。
原理:git bisect使用二分查找算法來(lái)縮小引入問(wèn)題的提交范圍。它首先將提交歷史分為兩半,然后詢問(wèn)開(kāi)發(fā)者哪一半包含引入錯(cuò)誤的提交。基于開(kāi)發(fā)者的反饋,git bisect會(huì)繼續(xù)將范圍縮小到更小的一半,直到找到引入問(wèn)題的確切提交。
使用git bisect的基本步驟如下:
- 確定一個(gè)包含錯(cuò)誤的提交(bad commit)和一個(gè)不包含錯(cuò)誤的提交(good commit)。這通常通過(guò)手動(dòng)檢查提交歷史或使用其他工具來(lái)完成。
- 從頂層工作目錄開(kāi)始,執(zhí)行g(shù)it bisect start來(lái)啟動(dòng)二分查找過(guò)程。
- 使用git bisect bad <bad-commit>將包含錯(cuò)誤的提交標(biāo)記為bad。
- 使用git bisect good <good-commit>將不包含錯(cuò)誤的提交標(biāo)記為good。
- Git現(xiàn)在會(huì)計(jì)算出中間提交,并簽出該提交。你需要通過(guò)測(cè)試來(lái)確定該提交是否包含錯(cuò)誤。
- 如果中間提交包含錯(cuò)誤,執(zhí)行g(shù)it bisect bad。如果不包含錯(cuò)誤,執(zhí)行g(shù)it bisect good。
- Git將基于你的反饋繼續(xù)縮小范圍,并簽出下一個(gè)中間提交。重復(fù)步驟5和6,直到找到引入問(wèn)題的確切提交。
- 一旦找到引入問(wèn)題的提交,git bisect將打印出相應(yīng)的提交哈希。你可以使用git bisect reset來(lái)重置工作樹(shù),完成整個(gè)查找過(guò)程。
假設(shè)發(fā)現(xiàn)了一個(gè)錯(cuò)誤。不確定這個(gè)錯(cuò)誤是在何時(shí)引入的,但是知道在某個(gè)特定版本的代碼中該錯(cuò)誤是不存在的。
- 首先,確定一個(gè)包含錯(cuò)誤的提交(bad commit)和一個(gè)不包含錯(cuò)誤的提交(good commit)。假設(shè)你知道在提交abc123時(shí)代碼是工作的,而在提交def456時(shí)代碼已經(jīng)出現(xiàn)了錯(cuò)誤。
- 從項(xiàng)目的頂層工作目錄開(kāi)始,執(zhí)行g(shù)it bisect start。
- 使用git bisect bad def456將提交def456標(biāo)記為bad。
- 使用git bisect good abc123將提交abc123標(biāo)記為good。
- Git將計(jì)算出這兩個(gè)提交之間的中間提交,并簽出該提交。你需要測(cè)試這個(gè)提交來(lái)確定是否包含錯(cuò)誤。
- 假設(shè)測(cè)試結(jié)果顯示中間提交包含錯(cuò)誤,執(zhí)行g(shù)it bisect bad。Git將繼續(xù)在bad和中間提交之間查找。
- 重復(fù)步驟5和6,直到Git找到引入問(wèn)題的確切提交。
- 一旦找到引入問(wèn)題的提交,可以使用git bisect reset來(lái)重置工作樹(shù),并繼續(xù)你的開(kāi)發(fā)工作。
Git 實(shí)用工具
1. GitLens
GitLens 是一個(gè)VS Code插件,可以用來(lái)查看項(xiàng)目的提交記錄、文件修改記錄、顯示每行代碼的提交記錄等。通過(guò)豐富的可視化和強(qiáng)大的比較命令獲得有價(jià)值的見(jiàn)解。
2. Git History
Git History 是一個(gè)VS Code插件,增強(qiáng)了Git 的功能,它可以用來(lái)查看日志信息,查看和搜索歷史,進(jìn)行分支對(duì)比、提交對(duì)比,跨提交對(duì)比文件等。
3. Git Automator
Git Automator 是一個(gè)VS Code插件,主要用來(lái)自動(dòng)化Git提交消息和 Git 工作流程。它允許用一個(gè)快捷方式添加和提交文件。它還為提交信息提供了自動(dòng)填充功能。當(dāng)動(dòng)作很明顯時(shí),例如你刪除了一個(gè)文件,Git Automator 會(huì)猜測(cè)該動(dòng)作并將其添加到預(yù)填充的提交消息中。
4. LearnGitBranching
LearnGitBranching 是一個(gè) git 存儲(chǔ)庫(kù)可視化工具、沙箱和一系列教程和挑戰(zhàn)。它的主要目的是幫助開(kāi)發(fā)人員通過(guò)可視化的力量來(lái)理解 git。這是通過(guò)不同級(jí)別的游戲來(lái)熟悉不同的git命令來(lái)實(shí)現(xiàn)的。
Github:https://github.com/pcottle/learnGitBranching。