簡介
Git 作為分布式版本控制系統(tǒng),基于去中心化的設(shè)計(jì)思想,在每個分布式節(jié)點(diǎn)上都保存有完整的版本,降低了對中心倉庫的依賴,增加了版本安全性。
Git 的使用過程中,并不是必須設(shè)置中心倉庫,各個節(jié)點(diǎn)之間完全可以互相推送和拉取更新內(nèi)容。不過考慮到相互的通信問題和團(tuán)隊(duì)協(xié)作,所以一般會選擇一個 24 小時運(yùn)行的主機(jī)作為中心倉庫,以此來獲取和交換更新內(nèi)容,例如 GitHub 則提供了這樣的托管服務(wù)。
三種狀態(tài)
Git 對文件的跟蹤管理存在三個階段,工作區(qū)、暫存區(qū)和分支:
- 工作區(qū)就是實(shí)際操作的文件目錄;
- 暫存區(qū)是一個索引文件,記錄已跟蹤文件的目錄樹,保存文件的時間戳、大小等易比較的信息;
- 分支與暫存區(qū)類似,也保存有文件的目錄樹,用于記錄文件系統(tǒng)的快照。
暫存區(qū)和分支都依賴 .git/objects 目錄,該目錄稱為對象庫,記錄了真實(shí)文件系統(tǒng)的快照。暫存區(qū)只是一個 index 文件,存放在 .git 目錄中。當(dāng)工作區(qū)文件發(fā)生修改時,將工作區(qū)中文件的時間戳和大小,與 index 中記錄的文件時間戳和大小進(jìn)行比較,可以快速的判斷工作區(qū)文件是否發(fā)生了更改,然后再具體的進(jìn)行工作區(qū)文件內(nèi)容與 objects 中記錄文件內(nèi)容進(jìn)行比較。
暫存區(qū)的作用更像是工作區(qū)和分支之間的一個緩沖區(qū)域,或者稱之為 “預(yù)提交文件改動到分支” 的區(qū)域。暫存區(qū)的存在,允許我們在工作區(qū)和暫存區(qū)之間方便的進(jìn)行文件修改的添加與撤回,以及對修改內(nèi)容的分部分提交。例如當(dāng)工作中需要修改兩部分內(nèi)容,目前只完成了一部分的修改時,可以將完成的這部分添加到暫存區(qū),接著在工作區(qū)繼續(xù)修改另一部分,需要提交到分支上時,則提交緩存區(qū)的內(nèi)容,未修改完成的部分可以繼續(xù)修改。
因?yàn)榉种Ц匾淖饔檬蔷S護(hù)文件系統(tǒng)的版本序列,與遠(yuǎn)程倉庫的通信,所以如果沒有暫存區(qū)的存在,那么我們的文件修改則只能頻繁的與分支打交道,屆時版本序列將變得復(fù)雜且不易于維護(hù),且每個版本記錄保存的是文件系統(tǒng)快照,若頻繁的進(jìn)行文件修改和提交,則倉庫大小將快速膨脹。
Git 使用
Git 安裝
下載安裝 Git:| Mac OS X | Windows | Linux/Unix |
官網(wǎng)下載速度較慢,這里提供一個 Windows 版本的下載鏈接:Git for Windows
Git 配置
Git 安裝之后,首先進(jìn)行用戶名和郵箱的配置,配置信息會記錄到每次的提交記錄中,并且當(dāng)推送更新到 GitHub 上的項(xiàng)目時,會與 GitHub 賬號進(jìn)行匹配,在歷史提交記錄中會顯示出用戶頭像,并且點(diǎn)亮提交次數(shù)。
通過 git config
命令進(jìn)行用戶名和郵箱配置時存在三種級別:
-
--system
:當(dāng)前機(jī)器上的配置,面向所有用戶; -
--global
:當(dāng)前用戶的配置,面向當(dāng)前用戶的所有倉庫; -
--local
:當(dāng)前倉庫的配置,只對當(dāng)前倉庫生效。
配置使用的優(yōu)先級為:
local > global > system
,即范圍小的配置會覆蓋范圍大的配置。
配置文件所在位置為:
system:etc/gitconfig
global:~/.gitconfig
local:.git/config
windows 系統(tǒng)中的位置為:
system
:git 工具安裝位置的etc/gitconfig
global
:當(dāng)前用戶主目錄下的.gitconfig
local:.git/config
配置方式為:
git config --global user.name "abc"
git config --global user.email "abc@xxx.com"
查詢配置方式為:
git config --global --list
一般只需要對當(dāng)前用戶進(jìn)行配置即可,即使用 --global
級別,如果某個倉庫有特殊安排,則可以在具體的倉庫級別進(jìn)行配置即可。不明確指定級別的話,默認(rèn)設(shè)置的為 --local
級別。
對于版本號在 2.0.0 以上的 git
,提供了一個簡單的查詢配置文件目錄的命令:
git config --list --show-origin
本地倉庫與遠(yuǎn)程倉庫的通信方式有兩種,一個是使用http
方式,每次連接需要輸入用戶名和密碼進(jìn)行身份驗(yàn)證;另一個是使用ssh
方式,在遠(yuǎn)程站點(diǎn)配置個人公鑰信息,當(dāng)本地倉庫與遠(yuǎn)程連接通信時,通過自身的私鑰完成身份認(rèn)證。
ssh-keygen -t rsa -C 'email@example.com'
使用該命令會根據(jù)提供的郵箱信息生成公私鑰文件,過程中會提示輸入文件存放地址和密碼信息,全部回車忽略可以使用默認(rèn)值。公私鑰文件地址默認(rèn)為~/.ssh/id_rsa
和~/.ssh/id_rsa.pub
,密碼默認(rèn)為空,即不需要每次通信時輸入密碼驗(yàn)證。
將公鑰文件
id_rsa.pub
的內(nèi)容添加到遠(yuǎn)程站點(diǎn)的SSH key
中即可。如果存在多個不同的遠(yuǎn)程站點(diǎn),例如同時有github
和gitlab
,則可以生成兩對公私鑰文件,在~/.ssh
下建立config
文件,文件內(nèi)配置不同站點(diǎn)使用不同私鑰文件。
config
文件示例:
Host github
HostName github.com
User root
Port 22
IdentityFile ~/.ssh/id_rsa
Host gitlab
HostName gitlab.xxx.com
User root
Port 22
IdentityFile ~/.ssh/id_rsa_gitlab
創(chuàng)建倉庫
創(chuàng)建倉庫有兩種方式,選擇本地工作目錄初始化為倉庫,或者從遠(yuǎn)程倉庫克隆到本地。克隆倉庫的方式在下面的內(nèi)容中再進(jìn)行講述,這里首先使用初始化本地工作目錄為倉庫的方式。
進(jìn)入選定目錄,執(zhí)行如下命令即可:
git init
命令執(zhí)行之后,在當(dāng)前目錄中會生成 .git 文件夾,此時當(dāng)前目錄即為一個“嶄新”的倉庫。
之所以用“嶄新”來描述倉庫,是因?yàn)樵趫?zhí)行倉庫初始化命令后,無論當(dāng)前目錄下是否存在文件,.git 目錄生成后都不存在 index 文件,objects 目錄下的文件夾中也沒有具體的文件生成。即此時暫存區(qū)和分支都為空,只有向倉庫中添加文件后,才會生成暫存區(qū) index 文件,objects 目錄下才會生成文件。
記錄文件/更新
首先要明確一點(diǎn),工作目錄中的文件只有兩種狀態(tài),已跟蹤和未跟蹤,也就是已經(jīng)納入版本記錄,和未納入版本記錄。使用上面的 git init
命令生成倉庫時,工作目錄中的所有文件都是未跟蹤狀態(tài),從遠(yuǎn)程倉庫克隆生成本地倉庫時,工作目錄中的所有文件都是已跟蹤狀態(tài)。
對于未跟蹤文件,則無所謂文件是否發(fā)生了修改,因?yàn)椴粫櫽涗浽撐募臓顟B(tài)。對于已跟蹤文件,則會檢測記錄該文件是否發(fā)生了修改。
git add <file>
git add
命令面向兩種對象,一個是將未跟蹤文件納入暫存區(qū),進(jìn)行跟蹤記錄;另外一個是將已跟蹤文件的修改,添加到暫存區(qū),記錄文件的更新。當(dāng)命令后跟著一個目錄時,則遞歸添加目錄及目錄下所有文件。
git status
git status
命令用于查看文件的狀態(tài),未跟蹤文件只有一種狀態(tài):文件未跟蹤,或者稱為未納入暫存區(qū),狀態(tài)顯示為 Untracked files
。已跟蹤文件有兩種狀態(tài):一是納入暫存區(qū),等待提交到版本庫,狀態(tài)顯示為 Changes to be committed
;二是文件發(fā)生了修改,且修改部分尚未添加到暫存區(qū),狀態(tài)顯示為 Changes not staged for commit
。
刪除文件
git add
命令用于向暫存區(qū)添加文件,或記錄文件的更新內(nèi)容。若執(zhí)行此命令后,發(fā)現(xiàn)該文件并不需要跟蹤記錄,或者已經(jīng)添加到暫存區(qū)的文件更新內(nèi)容需要取消,git
提供了相應(yīng)的撤回操作命令。
git rm --cache <file>
git rm --cache <file>
命令用于從暫存區(qū)移除對文件的跟蹤。
git rm <file>
git rm <file>
命令不僅從暫存區(qū)移除對文件的跟蹤,并且從工作目錄中也刪除了該文件。
git rm --cache <file>
命令和git rm <file>
命令都存在一個-f
選項(xiàng),用于強(qiáng)制刪除。當(dāng)已跟蹤的文件發(fā)生了修改,并且修改未添加到暫存區(qū)時,則需要git rm --cache -f <file>
命令才能從暫存區(qū)移除對文件的跟蹤;當(dāng)已跟蹤的文件發(fā)生了修改,并且修改已經(jīng)添加到暫存區(qū)時,則需要git rm -f <file>
命令才能同時從暫存區(qū)和工作目錄中刪除文件。
刪除更新
這里的更新有兩種情況:
- 工作目錄下已跟蹤文件進(jìn)行了更新,且更新內(nèi)容尚未提交到暫存區(qū);
- 工作目錄下已跟蹤文件進(jìn)行了更新,且更新內(nèi)容已經(jīng)提交到暫存區(qū)。
git checkout -- <file>
git checkout -- <file>
命令用于撤銷第一種情況下的更新內(nèi)容,可以理解為拿暫存區(qū)的文件內(nèi)容替換掉工作區(qū)的文件內(nèi)容。
git reset HEAD <file>
git reset HEAD <file>
命令用于撤銷第二種情況下的更新內(nèi)容,可以理解為拿上個版本的系統(tǒng)快照替換掉暫存區(qū)的文件內(nèi)容。
git checkout HEAD <file>
git checkout HEAD <file>
命令能夠同時撤銷工作區(qū)和暫存區(qū)的更新內(nèi)容,可以理解為拿上個版本的系統(tǒng)快照替換掉工作區(qū)和暫存區(qū)的文件內(nèi)容。
因?yàn)槿菀滓鸸ぷ鲀?nèi)容丟失,所以使用
git checkout HEAD <file>
命令時需要注意。
提交文件
工作中對每一個文件修改完成后,將修改內(nèi)容依次添加到暫存區(qū),當(dāng)完成所有修改后,則提交暫存區(qū)文件到當(dāng)前分支上。
git commit
git commit
命令用于提交暫存區(qū)文件到當(dāng)前分支上,執(zhí)行該命令后會打開文本編輯器提示輸入提交信息。
可以直接執(zhí)行
git commit -m 'commit message'
命令,將提交信息寫入命令中。
git log
git log
命令用于查看提交歷史,每個提交都會記錄時間、用戶信息、輸入的 commit
信息及 commit
值 ,這里的 commit
值是一個 SHA1
校驗(yàn)和,在后續(xù)的版本回退中會使用到 。
git reflog
git reflog
命令用于查看 HEAD
變動歷史,當(dāng)執(zhí)行提交、分支切換以及版本回退這類改變 HEAD
指向的操作時,都可以通過該命令查詢出 HEAD
指向的提交值,即 SHA1
校驗(yàn)和。該命令更多時候用于版本回退時,若想撤銷回退操作,恢復(fù)到回退之前的記錄時,通過該命令可以查詢到回退之前的校驗(yàn)和。
分支切換
分支的使用很廣泛,修改 bug
,或者開發(fā)新功能,都可以拉出一個新分支,等功能開發(fā)完成并測試通過后,再合并分支內(nèi)容到主干分支上。
在 git
的分支使用中,不同的分支實(shí)際就是指向各個文件系統(tǒng)快照的指針,所以在諸多 VCS
中 git
提供了輕量級且高效的分支創(chuàng)建、切換操作。
HEAD
可以理解為一個指針,指向當(dāng)前訪問的分支。
git branch
git branch
命令用于查看當(dāng)前的分支情況。
git branch <name>
git branch <name>
命令用于創(chuàng)建新分支。
git branch -d <name>
git branch -d <name>
命令用于刪除指定分支。
git checkout <name>
git checkout <name>
命令用于切換到指定分支。
git checkout -b <name>
git checkout -b <name>
命令用于創(chuàng)建分支,并切換到新分支。相當(dāng)于 git branch <name>
和 git checkout <name>
兩條命令合并到一起。
分支合并與沖突解決
當(dāng)在功能分支上完成新需求的開發(fā)任務(wù)后,需要切換回主分支,并將修改內(nèi)容回合到主分支上,刪除該功能分支。
git merge <name>
git merge <name>
命令用于合并指定分支的修改內(nèi)容到當(dāng)前分支上。
以合并 dev
分支修改內(nèi)容到 master
分支為例,若 master
分支的指向處于 dev
分支的直接上游時,如圖 merge-1
所示,此時合并分支速度較快,因?yàn)橹恍枰?master
分支的指向即可。
此時的合并方式為
Fast-forward
方式,因?yàn)橹恍枰姆种У闹赶颍运俣容^快,且不會產(chǎn)生新的提交記錄。
若 master
分支的指向不處于 dev
的直接上游,如圖 merge-2
所示,則合并過程需要比較 C3
提交的修改內(nèi)容與 C4
提交的修改內(nèi)容。如果兩個提交中不存在對 同一處文件內(nèi)容 的修改,則此時可以順利合并修改內(nèi)容,并產(chǎn)生一次新的合并提交,如下圖中的 C5
;如果兩個提交中存在對 同一處文件內(nèi)容 的修改,則此時合并存在沖突,需要手動解決沖突并完成合并提交。
圖
merge-2
所示的合并方式為recursive
方式,或者稱之為三路合并方式。因?yàn)楹喜?C3
與C4
的提交,需要與公共上游C2
相比較,以達(dá)到與 同一處文件內(nèi)容 相比較的目的,所以該合并方式主要觀察C2
、C3
與C4
三個文件系統(tǒng)快照,所以稱為三路合并方式。因?yàn)閺?fù)雜情況下公共上游并不想圖中所示這么明顯,可能需要進(jìn)行多次迭代合并處理方可產(chǎn)生虛擬的公共上游,所以也稱此方式為recursive
方式。
git cherry-pick <commitId>
git cherry-pick <commitId>
命令用于合并其他分支上的某次提交到當(dāng)前分支上。
git cherry-pick <start_commitId>^..<end_commitId>
git cherry-pick <start_commitId>^..<end_commitId>
命令用于將其他分支上從 <start_commitId>
起始到 <end_commitId>
結(jié)束的提交合并到當(dāng)前分支上,包括起始和結(jié)束提交。
理想的
VCS
使用方式是,克隆、修改、提交代碼,不存在任何的bug
修改或者沖突解決問題,但這是不可能的,所以實(shí)際工作中總會遇到各樣的情形。例如暫時不準(zhǔn)備將某個特性分支的開發(fā)修改合入主干,但是又要引入特性分支的某次提交(bug
修改、配置管理或者安全處理),此時可以使用cherry-pick
來將指定的提交合入主干。
關(guān)聯(lián)遠(yuǎn)程倉庫
在團(tuán)隊(duì)協(xié)作過程中,經(jīng)常的場景就是團(tuán)隊(duì)的每位成員都 fork
一份項(xiàng)目代碼到自己的個人庫中,然后在自己的庫里面做修改,修改完成再合入到團(tuán)隊(duì)的項(xiàng)目代碼庫中。所以我們的本地倉庫一般關(guān)聯(lián)兩個遠(yuǎn)程倉庫,一個是團(tuán)隊(duì)空間的項(xiàng)目代碼,用于拉取最新更新內(nèi)容;一個是個人庫中的項(xiàng)目代碼,用于推送個人修改內(nèi)容。
git remote
git remote
命令用于展示當(dāng)前倉庫關(guān)聯(lián)的遠(yuǎn)程倉庫。
git remote add <name> <address>
git remote add <name> <address>
命令用于為當(dāng)前倉庫添加關(guān)聯(lián)的遠(yuǎn)程倉庫。
git remote remove <name>
git remote remove <name>
命令用于刪除當(dāng)前倉庫關(guān)聯(lián)的遠(yuǎn)程倉庫。
git fetch <name>
git fetch <name>
命令用于從遠(yuǎn)程倉庫拉取最新分支信息。
git fetch <name>
命令只會拉取分支信息,生成<remote_name>/<branch_name>
遠(yuǎn)程分支,并不會為本地倉庫生成分支。
git branch -u <remote_name>/<branch_name>
git branch -u <remote_name>/<branch_name>
命令用于將當(dāng)前分支與遠(yuǎn)程分支進(jìn)行關(guān)聯(lián),即建立關(guān)聯(lián)關(guān)系。
git checkout -b <branch_name> <remote_name>/<branch_name>
git checkout -b <branch_name> <remote_name>/<branch_name>
命令用于在本地倉庫上新建分支,并與遠(yuǎn)程分支進(jìn)行關(guān)聯(lián)。
git push <remote_name> <branch_name>
git push <remote_name> <branch_name>
命令用于推送本地倉庫的分支到遠(yuǎn)程倉庫上,相當(dāng)于在遠(yuǎn)程倉庫上建立新分支。命令 git push <remote_name> <local_branch>:<remote_branch>
提供同樣推送分支的作用,并且可以給遠(yuǎn)程分支命名。
使用該命令只會在遠(yuǎn)程倉庫上建立新分支,并不會自動與當(dāng)前倉庫上的分支進(jìn)行關(guān)聯(lián),
git push -u <remote_name> <branch_name>
命令可以在推送分支的同時進(jìn)行關(guān)聯(lián),所以一般在github
網(wǎng)站上新建倉庫時都會有類似的提示,表示用于從本地初始化倉庫,然后推送到遠(yuǎn)程倉庫上。
git push <remote_name> :<remote_branch>
git push <remote_name> :<remote_branch>
命令用于刪除遠(yuǎn)程倉庫上的指定分支。
當(dāng)使用
git clone <remote_address>
命令來構(gòu)造本地倉庫時,會自動建立本地分支master
,并與遠(yuǎn)程倉庫分支origin/master
進(jìn)行關(guān)聯(lián)。
當(dāng)本地分支已經(jīng)關(guān)聯(lián)到遠(yuǎn)程分支之后,拉取更新和推送更新都變得較為簡單。在分支上直接執(zhí)行
git push
即可推送更新到關(guān)聯(lián)的遠(yuǎn)程分支上,執(zhí)行git fetch
即可拉取關(guān)聯(lián)分支更新,然后執(zhí)行git merge
即可合入更新到當(dāng)前分支上。此外,git
還提供有命令可以直接拉取更新并合入到當(dāng)前分支上,git pull
命令相當(dāng)于合并了git fetch
和git merge
兩個命令的功能。
版本回退
雖然有了暫存區(qū)可以檢查待提交內(nèi)容的正確性,但是仍不免有錯誤或不恰當(dāng)?shù)膬?nèi)容被提交,git
提供了在分支上回退版本記錄的命令。
git reset <level> <commitId>
git reset <level> <commitId>
命令用于回退版本到指定提交記錄點(diǎn)。這里 commitId
是 SHA1
校驗(yàn)和,用于標(biāo)識待回退到的提交記錄點(diǎn)。回退的 level
有三種:
--soft
:修改HEAD
指向指定的提交記錄點(diǎn),并將指定記錄到最新提交記錄之間的修改回退至?xí)捍鎱^(qū),工作區(qū)不受影響。--mixed
:修改HEAD
指向指定的提交記錄點(diǎn),并將指定記錄與最新提交記錄之間的修改回退至工作區(qū),暫存區(qū)會被清除。--hard
:修改HEAD
指向指定的提交記錄點(diǎn),并將指定記錄到最新提交記錄之間的修改清除。
該命令不填寫具體
level
時,默認(rèn)級別為--mixed
。這里注意一下--hard
的使用,該級別會清除工作區(qū)和暫存區(qū)的修改,即便撤銷回退操作回到最新提交,工作區(qū)和暫存區(qū)的修改也不會恢復(fù),所以謹(jǐn)慎使用。同理,--mixed
級別也會清除暫存區(qū)的修改,所以版本回退過程中,需要注意選擇恰當(dāng)?shù)幕赝朔绞健?/p>
執(zhí)行版本回退命令時,并不一定每次都要提供指定版本記錄的校驗(yàn)和,也可以通過
HEAD
來指定回退到相鄰的哪一個版本記錄。HEAD^
表示回退到上一個版本記錄,HEAD^^
表示回退到上兩個版本記錄,HEAD~n
表示回退到上n
個版本記錄。
git revert <commitId>
git revert <commitId>
命令用于回退指定提交記錄。
git revert <commitId>
命令和git reset <level> <commitId>
命令都可以用于回退版本,不同之處在于reset
用于回退到指定提交記錄,revert
用于撤銷指定提交記錄,并且產(chǎn)生一個新的提交記錄。
除了對提交歷史的變動不同之外,
git revert <commitId>
和git reset <level> <commitId>
命令使用的側(cè)重場景也不同。reset
命令更多用于在本地分支進(jìn)行回退,避免對團(tuán)隊(duì)其他人的提交產(chǎn)生影響;revert
命令則可以使用在公共分支上,當(dāng)進(jìn)行代碼檢視時,發(fā)現(xiàn)提交歷史中的某一次提交存在bug
,則可以使用revert
命令撤銷那一次提交。
在本地倉庫的分支上執(zhí)行回退操作后,有些情況下可能要同步回退遠(yuǎn)程倉庫。
git push -f
git push -f
命令用于同步回退當(dāng)前分支關(guān)聯(lián)的遠(yuǎn)程分支,因?yàn)楫?dāng)前分支的版本落后于遠(yuǎn)程分支,所以需要加 -f
選項(xiàng),執(zhí)行強(qiáng)制推送。
文件異同
通過 git status
只能查看出文件的狀態(tài)以及是否發(fā)生了修改,并不能具體的展示出差異內(nèi)容。
git diff <file>
git diff <file>
命令為查看工作目錄的文件與暫存區(qū)文件的差異,也就是查看從上次提交文件修改到暫存區(qū)后,到目前為止,工作目錄的文件又做了什么修改。
git diff --cached <file>
git diff --cached <file>
命令為查看暫存區(qū)的文件與當(dāng)前分支的文件差異,也就是此次準(zhǔn)備提交到分支上的有哪些修改內(nèi)容。
git diff HEAD <file>
git diff HEAD <file>
命令為查看工作目錄的文件與當(dāng)前分支的文件差異,也就是查看從上次提交文件修改到分支后,到目前為止,工作目錄的文件又做了什么修改。
git diff
命令還有其他形式:
git diff <branch> <file>
git diff <branch> <file>
命令為查看當(dāng)前工作目錄文件與其他分支文件差異。
git diff --cached <branch> <file>
git diff --cached <branch> <file>
命令為查看當(dāng)前暫存區(qū)文件與其他分支文件差異。
git diff <branch1> <branch1> <file>
git diff <branch1> <branch1> <file>
命令為查看兩個分支文件差異。
git diff <commitId1> <commitId2> <file>
git diff <commitId1> <commitId2> <file>
命令為查看兩個版本記錄文件差異。
git diff
命令可以將文件的差異保存為補(bǔ)丁patch
文件,因?yàn)檠a(bǔ)丁文件相對于整個項(xiàng)目而言體量較小,所以在協(xié)作工作時,常用的方式為將自己的修改保存為補(bǔ)丁,發(fā)送補(bǔ)丁文件來提交自己的修改。
git diff <branch/commitId> > <patch_file>
該命令將當(dāng)前分支與<branch>
進(jìn)行比較,將修改保存為補(bǔ)丁文件。
git diff
方式生成的補(bǔ)丁文件,可以使用apply
命令進(jìn)行應(yīng)用。diff
的比較對象在前面已經(jīng)提到過很多種,這里的<branch/commitId>
僅作為示例,實(shí)際使用中可以自由發(fā)揮。
git apply --check <patch_file>
該命令用于檢查補(bǔ)丁文件是否可以順利的使用。
git apply <patch_file>
該命令用于使用diff
方式生成的補(bǔ)丁文件。
使用
diff,apply
的方式應(yīng)用修改,不會自動添加為commit
記錄,只會將修改應(yīng)用到工作目錄中,所以需要手動將修改提交到暫存區(qū)和版本記錄中。
除了diff,apply
方式之外,還可以使用format-patch
來生成git
專用的補(bǔ)丁文件,使用am
命令應(yīng)用補(bǔ)丁,使用format-patch
命令比較差異時,每一次提交都會生成一個patch
文件。
git format-patch -M <branch>
該命令將當(dāng)前分支與<branch>
進(jìn)行比較,將修改保存為補(bǔ)丁文件,-M
表示比較的對象是分支。
git format-patch <commitId>
該命令將<commitId>
提交記錄之后的所有提交都生成補(bǔ)丁文件。
git apply --stat <patch_file>
該命令用于檢查補(bǔ)丁文件的修改。
git apply --check <patch_file>
該命令用于檢查補(bǔ)丁文件能否順利的應(yīng)用。
git am <patch_file>
該命令用于應(yīng)用補(bǔ)丁文件。
am
命令可以一次應(yīng)用一個補(bǔ)丁文件,也可以將所有補(bǔ)丁文件放在一個目錄下,一次應(yīng)用所有補(bǔ)丁文件。使用該專用補(bǔ)丁方式,可以自動提交commit
記錄,即版本記錄不需要手動添加。在執(zhí)行am
命令使用補(bǔ)丁文件之前,推薦先執(zhí)行一次git am --abort
命令,用于清空之前的應(yīng)用補(bǔ)丁信息。
儲藏修改
當(dāng)工作過程中需要臨時解決某個問題,即需要在主分支上拉取 bugfix
分支修復(fù) bug
時,若當(dāng)前特性開發(fā)分支 dev
上的工作還沒有完成,無法立即提交。此時切換并拉取新分支會對工作目錄的修改內(nèi)容造成干擾,則此時需要把當(dāng)前修改存儲起來,保持工作目錄的整潔,然后再建立bugfix
分支修復(fù) bug
。
git stash
git stash
命令用于儲藏當(dāng)前工作目錄的修改和暫存區(qū)內(nèi)容到一個棧空間上,使得當(dāng)前的工作目錄和暫存區(qū)不存在任何修改,即保持干凈狀態(tài)。
git stash pop --index
git stash pop --index
命令用于恢復(fù)棧空間上的儲藏到工作目錄和暫存區(qū),即恢復(fù)原狀。命令的使用中若不加 --index
參數(shù),則儲藏會恢復(fù)到工作目錄,暫存區(qū)會清空。
該命令不僅適用于分支切換時,對于之前提到的版本回退命令,若可能造成工作目錄和暫存區(qū)內(nèi)容丟失,則可以使用該命令來儲藏信息。
分支誤刪恢復(fù)
git
的分支功能使用很頻繁,并且處理效率很高,無論創(chuàng)建新分支或者刪除分支,都能夠得到快速反饋,原因在前面的內(nèi)容中提到過,即分支和 HEAD
都是指向不同系統(tǒng)快照的指針。所以當(dāng)工作中對分支執(zhí)行了誤刪除時,可以根據(jù)系統(tǒng)快照的校驗(yàn)和很方便進(jìn)行恢復(fù)。
git branch <branch_name> <commitId>
git branch <branch_name> <commitId>
命令用于根據(jù)提交記錄的校驗(yàn)和創(chuàng)建出新分支,因?yàn)榉种е皇且粋€指向系統(tǒng)快照的指針,所以可以使用 git log
查看提交記錄,然后進(jìn)行分支創(chuàng)建。
準(zhǔn)確講,這個命令是用于創(chuàng)建新分支出來,而不是恢復(fù)分支,不過創(chuàng)建的分支與原分支的內(nèi)容相同,所以常使用該命令來完成分支恢復(fù)。
若不小心執(zhí)行了 git push <remote_name> :<branch_name>
命令,刪除了遠(yuǎn)程倉庫的分支時,可以使用前面提到的 git push <remote_name> <branch_name>
命令,根據(jù)本地分支在遠(yuǎn)程倉庫上創(chuàng)建一個新的分支。
當(dāng)然,使用該方式恢復(fù)遠(yuǎn)程分支的前提是,本地分支保存了遠(yuǎn)程分支的修改記錄,否則可能導(dǎo)致最新的提交丟失。
修改提交信息
在本地進(jìn)行開發(fā)時,有些時候可能將暫存區(qū)修改commit
之后才發(fā)現(xiàn),有些文件還沒有修改,或者有些文件修改沒有添加到暫存區(qū),如果想將本地的所有修改操作,作為一次commit
記錄進(jìn)行提交,以方便后續(xù)查看工作歷史,git
提供了--amend
參數(shù)完成重寫上一次的commit
信息。
git commit --amend -m <message>
將本地遺漏的修改添加到暫存區(qū)后,使用該命令可以將上一次的修改內(nèi)容與本地修改內(nèi)容合并,做為一次commit
記錄提交到版本歷史中。
如果沒有修改遺漏,只是單純的想修改上一次的
commit
描述信息<message>
,也可以使用該命令。