Git 命令使用

簡(jiǎn)介

Git 作為分布式版本控制系統(tǒng),基于去中心化的設(shè)計(jì)思想,在每個(gè)分布式節(jié)點(diǎn)上都保存有完整的版本,降低了對(duì)中心倉(cāng)庫(kù)的依賴,增加了版本安全性。

Git 的使用過(guò)程中,并不是必須設(shè)置中心倉(cāng)庫(kù),各個(gè)節(jié)點(diǎn)之間完全可以互相推送和拉取更新內(nèi)容。不過(guò)考慮到相互的通信問(wèn)題和團(tuán)隊(duì)協(xié)作,所以一般會(huì)選擇一個(gè) 24 小時(shí)運(yùn)行的主機(jī)作為中心倉(cāng)庫(kù),以此來(lái)獲取和交換更新內(nèi)容,例如 GitHub 則提供了這樣的托管服務(wù)。

三種狀態(tài)

Git 對(duì)文件的跟蹤管理存在三個(gè)階段,工作區(qū)、暫存區(qū)和分支:

  • 工作區(qū)就是實(shí)際操作的文件目錄;
  • 暫存區(qū)是一個(gè)索引文件,記錄已跟蹤文件的目錄樹,保存文件的時(shí)間戳、大小等易比較的信息;
  • 分支與暫存區(qū)類似,也保存有文件的目錄樹,用于記錄文件系統(tǒng)的快照。

暫存區(qū)和分支都依賴 .git/objects 目錄,該目錄稱為對(duì)象庫(kù),記錄了真實(shí)文件系統(tǒng)的快照。暫存區(qū)只是一個(gè) index 文件,存放在 .git 目錄中。當(dāng)工作區(qū)文件發(fā)生修改時(shí),將工作區(qū)中文件的時(shí)間戳和大小,與 index 中記錄的文件時(shí)間戳和大小進(jìn)行比較,可以快速的判斷工作區(qū)文件是否發(fā)生了更改,然后再具體的進(jìn)行工作區(qū)文件內(nèi)容與 objects 中記錄文件內(nèi)容進(jìn)行比較。

暫存區(qū)的作用更像是工作區(qū)和分支之間的一個(gè)緩沖區(qū)域,或者稱之為 “預(yù)提交文件改動(dòng)到分支” 的區(qū)域。暫存區(qū)的存在,允許我們?cè)诠ぷ鲄^(qū)和暫存區(qū)之間方便的進(jìn)行文件修改的添加與撤回,以及對(duì)修改內(nèi)容的分部分提交。例如當(dāng)工作中需要修改兩部分內(nèi)容,目前只完成了一部分的修改時(shí),可以將完成的這部分添加到暫存區(qū),接著在工作區(qū)繼續(xù)修改另一部分,需要提交到分支上時(shí),則提交緩存區(qū)的內(nèi)容,未修改完成的部分可以繼續(xù)修改。

因?yàn)榉种Ц匾淖饔檬蔷S護(hù)文件系統(tǒng)的版本序列,與遠(yuǎn)程倉(cāng)庫(kù)的通信,所以如果沒(méi)有暫存區(qū)的存在,那么我們的文件修改則只能頻繁的與分支打交道,屆時(shí)版本序列將變得復(fù)雜且不易于維護(hù),且每個(gè)版本記錄保存的是文件系統(tǒng)快照,若頻繁的進(jìn)行文件修改和提交,則倉(cāng)庫(kù)大小將快速膨脹。

Git 使用

Git 安裝

下載安裝 Git:| Mac OS X | Windows | Linux/Unix |

官網(wǎng)下載速度較慢,這里提供一個(gè) Windows 版本的下載鏈接:Git for Windows


Git 配置

Git 安裝之后,首先進(jìn)行用戶名和郵箱的配置,配置信息會(huì)記錄到每次的提交記錄中,并且當(dāng)推送更新到 GitHub 上的項(xiàng)目時(shí),會(huì)與 GitHub 賬號(hào)進(jìn)行匹配,在歷史提交記錄中會(huì)顯示出用戶頭像,并且點(diǎn)亮提交次數(shù)。

通過(guò) git config 命令進(jìn)行用戶名和郵箱配置時(shí)存在三種級(jí)別:

  • --system:當(dāng)前機(jī)器上的配置,面向所有用戶;
  • --global:當(dāng)前用戶的配置,面向當(dāng)前用戶的所有倉(cāng)庫(kù);
  • --local:當(dāng)前倉(cāng)庫(kù)的配置,只對(duì)當(dāng)前倉(cāng)庫(kù)生效。

配置使用的優(yōu)先級(jí)為:local > global > system,即范圍小的配置會(huì)覆蓋范圍大的配置。
配置文件所在位置為:
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

一般只需要對(duì)當(dāng)前用戶進(jìn)行配置即可,即使用 --global 級(jí)別,如果某個(gè)倉(cāng)庫(kù)有特殊安排,則可以在具體的倉(cāng)庫(kù)級(jí)別進(jìn)行配置即可。不明確指定級(jí)別的話,默認(rèn)設(shè)置的為 --local 級(jí)別。

對(duì)于版本號(hào)在 2.0.0 以上的 git,提供了一個(gè)簡(jiǎn)單的查詢配置文件目錄的命令:

git config --list --show-origin

本地倉(cāng)庫(kù)與遠(yuǎn)程倉(cāng)庫(kù)的通信方式有兩種,一個(gè)是使用http方式,每次連接需要輸入用戶名和密碼進(jìn)行身份驗(yàn)證;另一個(gè)是使用ssh方式,在遠(yuǎn)程站點(diǎn)配置個(gè)人公鑰信息,當(dāng)本地倉(cāng)庫(kù)與遠(yuǎn)程連接通信時(shí),通過(guò)自身的私鑰完成身份認(rèn)證。

ssh-keygen -t rsa -C 'email@example.com'

使用該命令會(huì)根據(jù)提供的郵箱信息生成公私鑰文件,過(guò)程中會(huì)提示輸入文件存放地址和密碼信息,全部回車忽略可以使用默認(rèn)值。公私鑰文件地址默認(rèn)為~/.ssh/id_rsa~/.ssh/id_rsa.pub,密碼默認(rèn)為空,即不需要每次通信時(shí)輸入密碼驗(yàn)證。

將公鑰文件id_rsa.pub的內(nèi)容添加到遠(yuǎn)程站點(diǎn)的SSH key中即可。如果存在多個(gè)不同的遠(yuǎn)程站點(diǎn),例如同時(shí)有githubgitlab,則可以生成兩對(duì)公私鑰文件,在~/.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)建倉(cāng)庫(kù)

創(chuàng)建倉(cāng)庫(kù)有兩種方式,選擇本地工作目錄初始化為倉(cāng)庫(kù),或者從遠(yuǎn)程倉(cāng)庫(kù)克隆到本地。克隆倉(cāng)庫(kù)的方式在下面的內(nèi)容中再進(jìn)行講述,這里首先使用初始化本地工作目錄為倉(cāng)庫(kù)的方式。

進(jìn)入選定目錄,執(zhí)行如下命令即可:

git init

命令執(zhí)行之后,在當(dāng)前目錄中會(huì)生成 .git 文件夾,此時(shí)當(dāng)前目錄即為一個(gè)“嶄新”的倉(cāng)庫(kù)。

之所以用“嶄新”來(lái)描述倉(cāng)庫(kù),是因?yàn)樵趫?zhí)行倉(cāng)庫(kù)初始化命令后,無(wú)論當(dāng)前目錄下是否存在文件,.git 目錄生成后都不存在 index 文件,objects 目錄下的文件夾中也沒(méi)有具體的文件生成。即此時(shí)暫存區(qū)和分支都為空,只有向倉(cāng)庫(kù)中添加文件后,才會(huì)生成暫存區(qū) index 文件,objects 目錄下才會(huì)生成文件。


記錄文件/更新

首先要明確一點(diǎn),工作目錄中的文件只有兩種狀態(tài),已跟蹤和未跟蹤,也就是已經(jīng)納入版本記錄,和未納入版本記錄。使用上面的 git init 命令生成倉(cāng)庫(kù)時(shí),工作目錄中的所有文件都是未跟蹤狀態(tài),從遠(yuǎn)程倉(cāng)庫(kù)克隆生成本地倉(cāng)庫(kù)時(shí),工作目錄中的所有文件都是已跟蹤狀態(tài)。

對(duì)于未跟蹤文件,則無(wú)所謂文件是否發(fā)生了修改,因?yàn)椴粫?huì)跟蹤記錄該文件的狀態(tài)。對(duì)于已跟蹤文件,則會(huì)檢測(cè)記錄該文件是否發(fā)生了修改。

git add <file>

git add 命令面向兩種對(duì)象,一個(gè)是將未跟蹤文件納入暫存區(qū),進(jìn)行跟蹤記錄;另外一個(gè)是將已跟蹤文件的修改,添加到暫存區(qū),記錄文件的更新。當(dāng)命令后跟著一個(gè)目錄時(shí),則遞歸添加目錄及目錄下所有文件。

git status

git status 命令用于查看文件的狀態(tài),未跟蹤文件只有一種狀態(tài):文件未跟蹤,或者稱為未納入暫存區(qū),狀態(tài)顯示為 Untracked files。已跟蹤文件有兩種狀態(tài):一是納入暫存區(qū),等待提交到版本庫(kù),狀態(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ū)移除對(duì)文件的跟蹤。

git rm <file>

git rm <file> 命令不僅從暫存區(qū)移除對(duì)文件的跟蹤,并且從工作目錄中也刪除了該文件。

git rm --cache <file> 命令和 git rm <file> 命令都存在一個(gè) -f 選項(xiàng),用于強(qiáng)制刪除。當(dāng)已跟蹤的文件發(fā)生了修改,并且修改未添加到暫存區(qū)時(shí),則需要git rm --cache -f <file> 命令才能從暫存區(qū)移除對(duì)文件的跟蹤;當(dāng)已跟蹤的文件發(fā)生了修改,并且修改已經(jīng)添加到暫存區(qū)時(shí),則需要git rm -f <file> 命令才能同時(shí)從暫存區(qū)和工作目錄中刪除文件。


刪除更新

這里的更新有兩種情況:

  1. 工作目錄下已跟蹤文件進(jìn)行了更新,且更新內(nèi)容尚未提交到暫存區(qū);
  2. 工作目錄下已跟蹤文件進(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)容,可以理解為拿上個(gè)版本的系統(tǒng)快照替換掉暫存區(qū)的文件內(nèi)容。

git checkout HEAD <file>

git checkout HEAD <file> 命令能夠同時(shí)撤銷工作區(qū)和暫存區(qū)的更新內(nèi)容,可以理解為拿上個(gè)版本的系統(tǒng)快照替換掉工作區(qū)和暫存區(qū)的文件內(nèi)容。

因?yàn)槿菀滓鸸ぷ鲀?nèi)容丟失,所以使用 git checkout HEAD <file> 命令時(shí)需要注意。


提交文件

工作中對(duì)每一個(gè)文件修改完成后,將修改內(nèi)容依次添加到暫存區(qū),當(dāng)完成所有修改后,則提交暫存區(qū)文件到當(dāng)前分支上。

git commit

git commit 命令用于提交暫存區(qū)文件到當(dāng)前分支上,執(zhí)行該命令后會(huì)打開(kāi)文本編輯器提示輸入提交信息。

可以直接執(zhí)行 git commit -m 'commit message' 命令,將提交信息寫入命令中。

git log

git log 命令用于查看提交歷史,每個(gè)提交都會(huì)記錄時(shí)間、用戶信息、輸入的 commit 信息及 commit 值 ,這里的 commit 值是一個(gè) SHA1 校驗(yàn)和,在后續(xù)的版本回退中會(huì)使用到 。

git reflog

git reflog 命令用于查看 HEAD 變動(dòng)歷史,當(dāng)執(zhí)行提交、分支切換以及版本回退這類改變 HEAD 指向的操作時(shí),都可以通過(guò)該命令查詢出 HEAD 指向的提交值,即 SHA1 校驗(yàn)和。該命令更多時(shí)候用于版本回退時(shí),若想撤銷回退操作,恢復(fù)到回退之前的記錄時(shí),通過(guò)該命令可以查詢到回退之前的校驗(yàn)和。


分支切換

分支的使用很廣泛,修改 bug,或者開(kāi)發(fā)新功能,都可以拉出一個(gè)新分支,等功能開(kāi)發(fā)完成并測(cè)試通過(guò)后,再合并分支內(nèi)容到主干分支上。

git 的分支使用中,不同的分支實(shí)際就是指向各個(gè)文件系統(tǒng)快照的指針,所以在諸多 VCSgit 提供了輕量級(jí)且高效的分支創(chuàng)建、切換操作。

HEAD 可以理解為一個(gè)指針,指向當(dāng)前訪問(wèn)的分支。

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)在功能分支上完成新需求的開(kāi)發(fā)任務(wù)后,需要切換回主分支,并將修改內(nèi)容回合到主分支上,刪除該功能分支。

git merge <name>

git merge <name> 命令用于合并指定分支的修改內(nèi)容到當(dāng)前分支上。

merge-1

以合并 dev 分支修改內(nèi)容到 master 分支為例,若 master 分支的指向處于 dev 分支的直接上游時(shí),如圖 merge-1 所示,此時(shí)合并分支速度較快,因?yàn)橹恍枰?master 分支的指向即可。

after_merge

此時(shí)的合并方式為 Fast-forward 方式,因?yàn)橹恍枰姆种У闹赶?,所以速度較快,且不會(huì)產(chǎn)生新的提交記錄。

merge-2

master 分支的指向不處于 dev 的直接上游,如圖 merge-2 所示,則合并過(guò)程需要比較 C3 提交的修改內(nèi)容與 C4 提交的修改內(nèi)容。如果兩個(gè)提交中不存在對(duì) 同一處文件內(nèi)容 的修改,則此時(shí)可以順利合并修改內(nèi)容,并產(chǎn)生一次新的合并提交,如下圖中的 C5;如果兩個(gè)提交中存在對(duì) 同一處文件內(nèi)容 的修改,則此時(shí)合并存在沖突,需要手動(dòng)解決沖突并完成合并提交。

after_merge

merge-2 所示的合并方式為 recursive 方式,或者稱之為三路合并方式。因?yàn)楹喜?C3C4 的提交,需要與公共上游 C2 相比較,以達(dá)到與 同一處文件內(nèi)容 相比較的目的,所以該合并方式主要觀察 C2、C3C4三個(gè)文件系統(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 修改或者沖突解決問(wèn)題,但這是不可能的,所以實(shí)際工作中總會(huì)遇到各樣的情形。例如暫時(shí)不準(zhǔn)備將某個(gè)特性分支的開(kāi)發(fā)修改合入主干,但是又要引入特性分支的某次提交(bug 修改、配置管理或者安全處理),此時(shí)可以使用 cherry-pick 來(lái)將指定的提交合入主干。


關(guān)聯(lián)遠(yuǎn)程倉(cāng)庫(kù)

在團(tuán)隊(duì)協(xié)作過(guò)程中,經(jīng)常的場(chǎng)景就是團(tuán)隊(duì)的每位成員都 fork 一份項(xiàng)目代碼到自己的個(gè)人庫(kù)中,然后在自己的庫(kù)里面做修改,修改完成再合入到團(tuán)隊(duì)的項(xiàng)目代碼庫(kù)中。所以我們的本地倉(cāng)庫(kù)一般關(guān)聯(lián)兩個(gè)遠(yuǎn)程倉(cāng)庫(kù),一個(gè)是團(tuán)隊(duì)空間的項(xiàng)目代碼,用于拉取最新更新內(nèi)容;一個(gè)是個(gè)人庫(kù)中的項(xiàng)目代碼,用于推送個(gè)人修改內(nèi)容。

git remote

git remote 命令用于展示當(dāng)前倉(cāng)庫(kù)關(guān)聯(lián)的遠(yuǎn)程倉(cāng)庫(kù)。

git remote add <name> <address>

git remote add <name> <address> 命令用于為當(dāng)前倉(cāng)庫(kù)添加關(guān)聯(lián)的遠(yuǎn)程倉(cāng)庫(kù)。

git remote remove <name>

git remote remove <name> 命令用于刪除當(dāng)前倉(cāng)庫(kù)關(guān)聯(lián)的遠(yuǎn)程倉(cāng)庫(kù)。

git fetch <name>

git fetch <name> 命令用于從遠(yuǎn)程倉(cāng)庫(kù)拉取最新分支信息。

git fetch <name> 命令只會(huì)拉取分支信息,生成 <remote_name>/<branch_name> 遠(yuǎn)程分支,并不會(huì)為本地倉(cāng)庫(kù)生成分支。

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> 命令用于在本地倉(cāng)庫(kù)上新建分支,并與遠(yuǎn)程分支進(jìn)行關(guān)聯(lián)。

git push <remote_name> <branch_name>

git push <remote_name> <branch_name> 命令用于推送本地倉(cāng)庫(kù)的分支到遠(yuǎn)程倉(cāng)庫(kù)上,相當(dāng)于在遠(yuǎn)程倉(cāng)庫(kù)上建立新分支。命令 git push <remote_name> <local_branch>:<remote_branch> 提供同樣推送分支的作用,并且可以給遠(yuǎn)程分支命名。

使用該命令只會(huì)在遠(yuǎn)程倉(cāng)庫(kù)上建立新分支,并不會(huì)自動(dòng)與當(dāng)前倉(cāng)庫(kù)上的分支進(jìn)行關(guān)聯(lián),git push -u <remote_name> <branch_name> 命令可以在推送分支的同時(shí)進(jìn)行關(guān)聯(lián),所以一般在 github 網(wǎng)站上新建倉(cāng)庫(kù)時(shí)都會(huì)有類似的提示,表示用于從本地初始化倉(cāng)庫(kù),然后推送到遠(yuǎn)程倉(cāng)庫(kù)上。

git push <remote_name> :<remote_branch>

git push <remote_name> :<remote_branch> 命令用于刪除遠(yuǎn)程倉(cāng)庫(kù)上的指定分支。

當(dāng)使用 git clone <remote_address> 命令來(lái)構(gòu)造本地倉(cāng)庫(kù)時(shí),會(huì)自動(dòng)建立本地分支 master,并與遠(yuǎn)程倉(cāng)庫(kù)分支 origin/master 進(jìn)行關(guān)聯(lián)。

當(dāng)本地分支已經(jīng)關(guān)聯(lián)到遠(yuǎn)程分支之后,拉取更新和推送更新都變得較為簡(jiǎ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 fetchgit merge 兩個(gè)命令的功能。


版本回退

雖然有了暫存區(qū)可以檢查待提交內(nèi)容的正確性,但是仍不免有錯(cuò)誤或不恰當(dāng)?shù)膬?nèi)容被提交,git 提供了在分支上回退版本記錄的命令。

git reset <level> <commitId>

git reset <level> <commitId> 命令用于回退版本到指定提交記錄點(diǎn)。這里 commitIdSHA1 校驗(yàn)和,用于標(biāo)識(shí)待回退到的提交記錄點(diǎn)。回退的 level 有三種:

  • --soft:修改 HEAD 指向指定的提交記錄點(diǎn),并將指定記錄到最新提交記錄之間的修改回退至?xí)捍鎱^(qū),工作區(qū)不受影響。

  • --mixed:修改 HEAD 指向指定的提交記錄點(diǎn),并將指定記錄與最新提交記錄之間的修改回退至工作區(qū),暫存區(qū)會(huì)被清除。

  • --hard:修改 HEAD 指向指定的提交記錄點(diǎn),并將指定記錄到最新提交記錄之間的修改清除。

該命令不填寫具體 level 時(shí),默認(rèn)級(jí)別為 --mixed。這里注意一下 --hard 的使用,該級(jí)別會(huì)清除工作區(qū)和暫存區(qū)的修改,即便撤銷回退操作回到最新提交,工作區(qū)和暫存區(qū)的修改也不會(huì)恢復(fù),所以謹(jǐn)慎使用。同理, --mixed 級(jí)別也會(huì)清除暫存區(qū)的修改,所以版本回退過(guò)程中,需要注意選擇恰當(dāng)?shù)幕赝朔绞健?/p>

執(zhí)行版本回退命令時(shí),并不一定每次都要提供指定版本記錄的校驗(yàn)和,也可以通過(guò) HEAD 來(lái)指定回退到相鄰的哪一個(gè)版本記錄。HEAD^ 表示回退到上一個(gè)版本記錄,HEAD^^ 表示回退到上兩個(gè)版本記錄,HEAD~n 表示回退到上 n 個(gè)版本記錄。

git revert <commitId>

git revert <commitId> 命令用于回退指定提交記錄。

git revert <commitId> 命令和 git reset <level> <commitId> 命令都可以用于回退版本,不同之處在于 reset 用于回退到指定提交記錄,revert 用于撤銷指定提交記錄,并且產(chǎn)生一個(gè)新的提交記錄。

除了對(duì)提交歷史的變動(dòng)不同之外,git revert <commitId>git reset <level> <commitId> 命令使用的側(cè)重場(chǎng)景也不同。reset 命令更多用于在本地分支進(jìn)行回退,避免對(duì)團(tuán)隊(duì)其他人的提交產(chǎn)生影響;revert 命令則可以使用在公共分支上,當(dāng)進(jìn)行代碼檢視時(shí),發(fā)現(xiàn)提交歷史中的某一次提交存在 bug,則可以使用 revert 命令撤銷那一次提交。

在本地倉(cāng)庫(kù)的分支上執(zhí)行回退操作后,有些情況下可能要同步回退遠(yuǎn)程倉(cāng)庫(kù)。

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)制推送。


文件異同

通過(guò) 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> 命令為查看兩個(gè)分支文件差異。

git diff <commitId1> <commitId2> <file>

git diff <commitId1> <commitId2> <file> 命令為查看兩個(gè)版本記錄文件差異。

git diff命令可以將文件的差異保存為補(bǔ)丁patch文件,因?yàn)檠a(bǔ)丁文件相對(duì)于整個(gè)項(xiàng)目而言體量較小,所以在協(xié)作工作時(shí),常用的方式為將自己的修改保存為補(bǔ)丁,發(fā)送補(bǔ)丁文件來(lái)提交自己的修改。

git diff <branch/commitId> > <patch_file>

該命令將當(dāng)前分支與<branch>進(jìn)行比較,將修改保存為補(bǔ)丁文件。

git diff方式生成的補(bǔ)丁文件,可以使用apply命令進(jìn)行應(yīng)用。diff的比較對(duì)象在前面已經(jīng)提到過(guò)很多種,這里的<branch/commitId>僅作為示例,實(shí)際使用中可以自由發(fā)揮。

git apply --check <patch_file>

該命令用于檢查補(bǔ)丁文件是否可以順利的使用。

git apply <patch_file>

該命令用于使用diff方式生成的補(bǔ)丁文件。

使用diff,apply的方式應(yīng)用修改,不會(huì)自動(dòng)添加為commit記錄,只會(huì)將修改應(yīng)用到工作目錄中,所以需要手動(dòng)將修改提交到暫存區(qū)和版本記錄中。

除了diff,apply方式之外,還可以使用format-patch來(lái)生成git專用的補(bǔ)丁文件,使用am命令應(yīng)用補(bǔ)丁,使用format-patch命令比較差異時(shí),每一次提交都會(huì)生成一個(gè)patch文件。

git format-patch -M <branch>

該命令將當(dāng)前分支與<branch>進(jìn)行比較,將修改保存為補(bǔ)丁文件,-M表示比較的對(duì)象是分支。

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)用一個(gè)補(bǔ)丁文件,也可以將所有補(bǔ)丁文件放在一個(gè)目錄下,一次應(yīng)用所有補(bǔ)丁文件。使用該專用補(bǔ)丁方式,可以自動(dòng)提交commit記錄,即版本記錄不需要手動(dòng)添加。在執(zhí)行am命令使用補(bǔ)丁文件之前,推薦先執(zhí)行一次git am --abort命令,用于清空之前的應(yīng)用補(bǔ)丁信息。


儲(chǔ)藏修改

當(dāng)工作過(guò)程中需要臨時(shí)解決某個(gè)問(wèn)題,即需要在主分支上拉取 bugfix 分支修復(fù) bug 時(shí),若當(dāng)前特性開(kāi)發(fā)分支 dev 上的工作還沒(méi)有完成,無(wú)法立即提交。此時(shí)切換并拉取新分支會(huì)對(duì)工作目錄的修改內(nèi)容造成干擾,則此時(shí)需要把當(dāng)前修改存儲(chǔ)起來(lái),保持工作目錄的整潔,然后再建立bugfix 分支修復(fù) bug 。

git stash

git stash 命令用于儲(chǔ)藏當(dāng)前工作目錄的修改和暫存區(qū)內(nèi)容到一個(gè)??臻g上,使得當(dāng)前的工作目錄和暫存區(qū)不存在任何修改,即保持干凈狀態(tài)。

git stash pop --index

git stash pop --index 命令用于恢復(fù)??臻g上的儲(chǔ)藏到工作目錄和暫存區(qū),即恢復(fù)原狀。命令的使用中若不加 --index 參數(shù),則儲(chǔ)藏會(huì)恢復(fù)到工作目錄,暫存區(qū)會(huì)清空。

該命令不僅適用于分支切換時(shí),對(duì)于之前提到的版本回退命令,若可能造成工作目錄和暫存區(qū)內(nèi)容丟失,則可以使用該命令來(lái)儲(chǔ)藏信息。


分支誤刪恢復(fù)

git 的分支功能使用很頻繁,并且處理效率很高,無(wú)論創(chuàng)建新分支或者刪除分支,都能夠得到快速反饋,原因在前面的內(nèi)容中提到過(guò),即分支和 HEAD 都是指向不同系統(tǒng)快照的指針。所以當(dāng)工作中對(duì)分支執(zhí)行了誤刪除時(shí),可以根據(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)榉种е皇且粋€(gè)指向系統(tǒng)快照的指針,所以可以使用 git log 查看提交記錄,然后進(jìn)行分支創(chuàng)建。

準(zhǔn)確講,這個(gè)命令是用于創(chuàng)建新分支出來(lái),而不是恢復(fù)分支,不過(guò)創(chuàng)建的分支與原分支的內(nèi)容相同,所以常使用該命令來(lái)完成分支恢復(fù)。

若不小心執(zhí)行了 git push <remote_name> :<branch_name> 命令,刪除了遠(yuǎn)程倉(cāng)庫(kù)的分支時(shí),可以使用前面提到的 git push <remote_name> <branch_name> 命令,根據(jù)本地分支在遠(yuǎn)程倉(cāng)庫(kù)上創(chuàng)建一個(gè)新的分支。

當(dāng)然,使用該方式恢復(fù)遠(yuǎn)程分支的前提是,本地分支保存了遠(yuǎn)程分支的修改記錄,否則可能導(dǎo)致最新的提交丟失。

修改提交信息

在本地進(jìn)行開(kāi)發(fā)時(shí),有些時(shí)候可能將暫存區(qū)修改commit之后才發(fā)現(xiàn),有些文件還沒(méi)有修改,或者有些文件修改沒(méi)有添加到暫存區(qū),如果想將本地的所有修改操作,作為一次commit記錄進(jìn)行提交,以方便后續(xù)查看工作歷史,git提供了--amend參數(shù)完成重寫上一次的commit信息。

git commit --amend -m <message>

將本地遺漏的修改添加到暫存區(qū)后,使用該命令可以將上一次的修改內(nèi)容與本地修改內(nèi)容合并,做為一次commit記錄提交到版本歷史中。

如果沒(méi)有修改遺漏,只是單純的想修改上一次的commit描述信息<message>,也可以使用該命令。

最后編輯于
?著作權(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)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、電腦本地初始化一個(gè)倉(cāng)庫(kù) 1. git init: 初始化一個(gè)電腦上本地倉(cāng)庫(kù) 終端進(jìn)入項(xiàng)目目錄,輸入: 該命令將...
    dragon_li閱讀 3,120評(píng)論 1 4
  • (預(yù)警:因?yàn)樵敿?xì),所以行文有些長(zhǎng),新手邊看邊操作效果出乎你的預(yù)料) 一:Git是什么? Git是目前世界上最先進(jìn)的...
    axiaochao閱讀 2,006評(píng)論 1 8
  • Git 基礎(chǔ) 基本原理 客戶端并不是只提取最新版本的文件快照,而是把代碼倉(cāng)庫(kù)完整的鏡像下來(lái)。這樣一來(lái),任何一處協(xié)同...
    __silhouette閱讀 16,196評(píng)論 5 147
  • Git 命令行學(xué)習(xí)筆記 Git 基礎(chǔ) 基本原理 客戶端并不是只提取最新版本的文件快照,而是把代碼倉(cāng)庫(kù)完整的鏡像下來(lái)...
    sunnyghx閱讀 4,152評(píng)論 0 11
  • 我是真的很喜歡睡覺(jué)。據(jù)說(shuō)還是嬰兒時(shí)的我可以從前一天的下午睡到第二天的下午,中間不用起來(lái)吃奶,以至我爸著急地看了我好...
    白椿耳閱讀 384評(píng)論 0 0

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