提交 ID
顯式引用和隱式引用用來指代每一次提交。盡管有時(shí)兩種引用都不方便,但是幸運(yùn)的是, Git 提供了許多不同的機(jī)制來為提交命名,這些機(jī)制有各自的優(yōu)勢,需要根據(jù)上下文來選擇。
顯式引用
由于輸入一個(gè) 40 位十六進(jìn)制的 SHA1 數(shù)字是一項(xiàng)繁瑣且容易出錯(cuò)的工作,因此Git 允許你使用版本庫的對(duì)象庫中唯一的前綴來縮短這個(gè)數(shù)字。
隱式引用
引用(ref)是一個(gè) SHA1 散列值,指向 Git 對(duì)象庫中的對(duì)象。雖然一個(gè)引用可以指向任何 Git 對(duì)象,但是它通常指向提交對(duì)象。符號(hào)引用(symbolic reference) ,或稱為 symref,間接指向 Git 對(duì)象。它仍然只是一個(gè)引用。
本地特性分支名稱、遠(yuǎn)程跟蹤分支名稱和標(biāo)簽名都是引用。
- refs/heads/ref 代表本地分支
- refs/remotes/ref 代表遠(yuǎn)程跟蹤分支
- refs/tags/ref 代表標(biāo)簽
特殊引用
HEAD
HEAD始終指向當(dāng)前分支的最近提交。當(dāng)切換分支時(shí), HEAD 會(huì)更新為指向新分支的最近提交。
ORIG_HEAD
某些操作,例如合并(merge)和復(fù)位(reset) ,會(huì)把調(diào)整為新值之前的先前版
本的HEAD記錄到 ORIG-HEAD 中??梢允褂?ORIG-HEAD 來恢復(fù)或回滾到之前的狀態(tài)或者做一個(gè)比較。
FETCH_HEAD
當(dāng)使用遠(yuǎn)程庫時(shí), git fetch 命令將所有抓取分支的頭記錄到 .git/FETCH_HEAD 中。FETCH-HEAD 是最近抓取(fetch)的分支 HEAD 的簡寫,并且僅在剛剛抓取操作之后才有效。使用這個(gè)符號(hào)引用,哪怕是一個(gè)對(duì)沒有指定分支名的匿名抓取操作,都可以也在 git fetch 時(shí)找到提交的 HEAD。
MERGE_HEAD
當(dāng)一個(gè)合并操作正在進(jìn)行時(shí),其他分支的頭暫時(shí)記錄在 MERGE-HEAD 中。換言
之, MERGE-HEAD 是正在合并進(jìn) HEAD 的提交。
所有這些符號(hào)引用都可以用底層命令git symbolic-ref 進(jìn)行管理
show
如果在執(zhí)行 git show 命令的時(shí)候沒有顯式指定提交碼, 它將只顯示最近一次提交的詳細(xì)信息。
show-branch
查看所有分支的提交歷史
git show-branch
查看特定分支的提交歷史
git show-branch feature1 feature2
也可以使用通配符
git show-branch 'feature*'
git show-branch 的輸出被一排破折號(hào)分為兩部分。分隔符上方的部分列出分支名,并用方括號(hào)括起來,每行一個(gè)。每個(gè)分支名跟著一行輸出,前面用感嘆號(hào)或星號(hào)(如果它是當(dāng)前分支)標(biāo)記。為了便于參考,上半部分的每個(gè)分支都列出該分支最近提交的日志消息的第一行。
輸出的下半部分是一個(gè)表示每個(gè)分支中提交的矩陣。同樣,每個(gè)提交后面跟著該提交中日志消息的第一行。如果有一個(gè)加號(hào)(+)、星號(hào)(*)或減號(hào)(-)在分支的列中,對(duì)應(yīng)的提交就會(huì)在該分支中顯示。加號(hào)表示提交在一個(gè)分支中,星號(hào)突出顯示存在于活動(dòng)分支的提交,減號(hào)表示一個(gè)合并提交。
git show-branch 將會(huì)在在第一個(gè)共同提交處停止是默認(rèn)啟發(fā)策略,這個(gè)行為是合理的。據(jù)推測,達(dá)到這樣一個(gè)共同的點(diǎn)會(huì)產(chǎn)生足夠的上下文來了解分支之間的相互關(guān)系。如果由于某種原因,你想要更多提交歷史記錄,使用 --more-num 選項(xiàng),指定你想在共同提交后看到多少個(gè)額外的提交。
revert
git revert 提交命令跟 git cherry-pick 提交命令大致是相同的,但有一個(gè)重要區(qū)別:它應(yīng)用給定提交的逆過程。因此,此命令用于引入一個(gè)新提交來抵消給定提交的影響。
跟 git cherry-pick 命令一樣, revert 命令不修改版本庫的現(xiàn)存歷史記錄。相反它往歷史記錄中添加新提交。
git revert 的常見用途是“撤銷”可能深埋在歷史記錄中的某個(gè)提交的影響。
-n, --no-commit
只還原到工作區(qū) 和 暫存區(qū), 特別是在 revert 多個(gè)提交記錄的時(shí)候有用。
git revert HEAD 進(jìn)行倒數(shù)第 1 次內(nèi)容逆轉(zhuǎn), 可以認(rèn)為是還原成 HEAD^ 的內(nèi)容。
git revert HEAD^ 進(jìn)行倒數(shù)第 2 次內(nèi)容逆轉(zhuǎn),
git revert HEAD~3 進(jìn)行倒數(shù)第 4 次內(nèi)容逆轉(zhuǎn),
git revert -n master~5..master~2 進(jìn)行倒數(shù)第 5 次內(nèi)容到倒數(shù)第 3 次逆轉(zhuǎn)?!咀箝_右閉】
refspec
refspec 把遠(yuǎn)程版本庫中的分支名映射到本地版本庫中的分支名。
因?yàn)?refspec 必須同時(shí)從本地版本庫和遠(yuǎn)程版本庫指定分支,所以完整的分支名在refspec中是很常見的,通常也是必需的。在 refspec 中,你通常會(huì)看到
開發(fā)分支名有 refs/heads/前綴, 遠(yuǎn)程追蹤分支名有 refs/remotes/ 前綴。
refspec語法:
[+] source: destination
它主要由源引用(source ref) 、冒號(hào)(:)和目標(biāo)引用(destination ref)組成。
完整的格式還可以在前面加上一個(gè)可選的加號(hào)(+) 。如果有加號(hào)則表示不會(huì)在傳輸過程中進(jìn)行正常的快進(jìn)安全檢查。此外,星號(hào)(*)允許用有限形式的通配符匹配分支名。
在某些應(yīng)用中,源引用是可選的;在另一些應(yīng)用中,冒號(hào)和目標(biāo)引用是可選的。 refspec 在 git fetch和git push 中都使用。使用 refspec 的竅門是要了解它指定的數(shù)據(jù)流。refspec 本身始終是“源:目標(biāo)”, 但源和目標(biāo)依賴于正在執(zhí)行的Git操作。此關(guān)系總結(jié)于表中。
操作 源 目標(biāo)
push 推送的本地引用 更新的遠(yuǎn)程引用
fetch 抓取的遠(yuǎn)程引用 更新的本地引用
典型的git fetch 命令會(huì)使用 refspec,如 +refs/heads/*:refs/remotes/remote/*
在 git push 操作中,你通常要提供并發(fā)布你在本地特性分支上的變更。在你上傳變更后,為了讓其他人在遠(yuǎn)程版本庫中找到你的變更,你所做的更改必須出現(xiàn)在該版本庫的特性分支中。因此,在典型的 git push 命令中,會(huì)把你的版本庫中的源分支發(fā)送到遠(yuǎn)程版本庫,方法是使用這樣一個(gè) refspec, 如 +refs/heads/*: refs/heads/*
應(yīng)用補(bǔ)丁 patches
有些情況下,無論是推送還是拉取, Git 原生協(xié)議和 HTTP 協(xié)議都不能用來在版本庫間交換數(shù)據(jù)。在類似情況下, email 就成為傳送補(bǔ)丁的最佳媒介。
對(duì)等開發(fā)模型的一個(gè)巨大優(yōu)勢就是合作。補(bǔ)丁(尤其是發(fā)送到公共郵件列表中的補(bǔ)丁)是一種向同行評(píng)審(peer review)公開分發(fā)修改建議的手段。
如果你想要一個(gè)特殊或明確的提交,比方說,一個(gè)單獨(dú)的 bug 修復(fù)或一個(gè)特定功能實(shí)現(xiàn),那么應(yīng)用補(bǔ)丁也許就是獲得該特定改進(jìn)最直接的方式了。
Git 實(shí)現(xiàn)三條特定的命令幫助交換補(bǔ)丁:
- git format-patch 會(huì)生成 email 形式的補(bǔ)丁;
- git send-email 會(huì)通過簡單郵件傳輸協(xié)議(Simple Mail Transfer Protocol, SMTP)來發(fā)送一個(gè)Git補(bǔ)丁;
- git am 會(huì)應(yīng)用郵件消息中的補(bǔ)丁。
常見的用例包括:
- 特定的提交數(shù),如
-2; - 提交范圍,如
master~4..master~2; - 單次提交, 通常是分支名
為最近n次提交生成補(bǔ)丁的最簡方式是使用-n選項(xiàng)
git format-patch -2
默認(rèn)情況下, Git 為每個(gè)補(bǔ)丁生成單獨(dú)的文件,用一序列數(shù)字加上提交日志消息為其命名。該命令在執(zhí)行時(shí)輸出文件名。
為最近 2 次提交生成補(bǔ)丁,也可以使用..圈定出范圍
git format-patch master^^..master
應(yīng)用補(bǔ)丁示例
導(dǎo)出補(bǔ)丁
git format-patch -o /tmp/patches master~3
應(yīng)用補(bǔ)丁
git am /tmp/patches/*
使用三路合并的方式
-3, --3way, --no-3way
When the patch does not apply cleanly, fall back on 3-way merge. 而非以失敗告終。
Git Describe
由于標(biāo)簽在代碼庫中起著“錨點(diǎn)”的作用,Git 還為此專門設(shè)計(jì)了一個(gè)命令用來描述離你最近的錨點(diǎn)(也就是標(biāo)簽),它就是 git describe
Git Describe 能幫你在提交歷史中移動(dòng)了多次以后找到方向;當(dāng)你用 git bisect(一個(gè)查找產(chǎn)生 Bug 的提交記錄的指令)找到某個(gè)提交記錄時(shí),或者是當(dāng)你坐在你那剛剛度假回來的同事的電腦前時(shí), 可能會(huì)用到這個(gè)命令。
git describe 的語法是:
`git describe <ref>`
<ref> 可以是任何能被 Git 識(shí)別成提交記錄的引用,如果你沒有指定的話,Git 會(huì)以你目前所檢出的位置(HEAD)。
它輸出的結(jié)果是這樣的:
<tag>_<numCommits>_g<hash>
tag 表示的是離 ref 最近的標(biāo)簽, numCommits 是表示這個(gè) ref 與 tag 相差有多少個(gè)提交記錄, hash 表示的是你所給定的 ref 所表示的提交記錄哈希值的前幾位。
當(dāng) ref 提交記錄上有某個(gè)標(biāo)簽時(shí),則只輸出標(biāo)簽名稱
鉤子
你可以使用 Git 鉤子(hook) ,任何時(shí)候當(dāng)版本庫中出現(xiàn)如提交或補(bǔ)丁這樣的特殊事件時(shí),都會(huì)觸發(fā)執(zhí)行一個(gè)或多個(gè)任意的腳本。通常情況下,一個(gè)事件會(huì)分解成多個(gè)規(guī)定好的步驟,可以為每個(gè)步驟綁定自定義腳本。當(dāng) Git 事件發(fā)生時(shí),每一步開始都會(huì)調(diào)用相應(yīng)的腳本。
撤銷修改 restore Git 【2.23 實(shí)驗(yàn)特性】
將已經(jīng) git add 到暫存區(qū)(staged) 中的內(nèi)容進(jìn)行撤銷。為了便于理解,可以認(rèn)為是 git add 的反動(dòng)作。
use "git restore --staged <file>..." to unstage)
git restore --staged
表示將當(dāng)前目錄所有暫存區(qū)文件恢復(fù)狀態(tài)
switch 命令【2.23 實(shí)驗(yàn)特性】
必知必會(huì)之 Git Windows credential.helper
安裝 Git 后,我們可以通過下面的指令查詢當(dāng)前憑證存儲(chǔ)模式 git config credential.helper
可選憑證存儲(chǔ)模式
- "cache" 模式
會(huì)將憑證存放在內(nèi)存中一段時(shí)間。 密碼永遠(yuǎn)不會(huì)被存儲(chǔ)在磁盤中,并且在15分鐘后從內(nèi)存中清除。 - "store" 模式
會(huì)將憑證用明文的形式存放在磁盤中,并且永不過期。 這意味著除非你修改了你在 Git 服務(wù)器上的密碼,否則你永遠(yuǎn)不需要再次輸入你的憑證信息。 這種方式的缺點(diǎn)是你的密碼是用明文的方式存放在你的 home 目錄下。 - "osxkeychain" 模式
如果你使用的是 Mac,Git 還有一種 “osxkeychain” 模式,它會(huì)將憑證緩存到你系統(tǒng)用戶的鑰匙串中。 這種方式將憑證存放在磁盤中,并且永不過期,但是是被加密的,這種加密方式與存放 HTTPS 憑證以及 Safari 的自動(dòng)填寫是相同的。 - "manager" 模式
如果你使用的是 Windows,你可以安裝一個(gè)叫做 “Git Credential Manager for Windows” 的輔助工具。 這和上面說的 “osxkeychain” 十分類似,但是是使用 Windows Credential Store 來控制敏感信息。
推薦使用憑證存儲(chǔ)模式 "manager"。
Git 憑據(jù)管理器設(shè)置
Git Credential Manager (GCM) 是在 .NET 上構(gòu)建的安全 Git 憑據(jù)幫助程序,可與 WSL1 和 WSL2 一起使用。 它為 GitHub 存儲(chǔ)庫、Azure DevOps、Azure DevOps Server和 Bitbucket 啟用多重身份驗(yàn)證支持。
Git 憑據(jù)管理器包含在 Git for Windows 中,最新版本包含在每個(gè)新的 Git for Windows 版本中。 在安裝期間,系統(tǒng)會(huì)要求你選擇憑據(jù)幫助程序,并將 GCM 設(shè)置為默認(rèn)值。
如果你有理由不安裝 Git for Windows,則可以將 GCM 作為 Linux 應(yīng)用程序直接安裝在 WSL 分發(fā)中,但請(qǐng)注意,這樣做意味著 GCM 作為 Linux 應(yīng)用程序運(yùn)行,并且不能利用主機(jī)Windows操作系統(tǒng)的身份驗(yàn)證或憑據(jù)存儲(chǔ)功能。 有關(guān)如何為 Windows 配置 WSL 的說明,請(qǐng)參閱 GCM 存儲(chǔ)庫。
若要設(shè)置 GCM 以用于 WSL 分發(fā)版,請(qǐng)打開分發(fā)并輸入以下命令:
git config --global credential.helper "/mnt/c/Program\ Files/Git/mingw64/libexec/git-core/git-credential-manager-core.exe"
Configuring WSL without Git for Windows
If you wish to use GCM inside of WSL without installing Git for Windows you must complete additional configuration so that GCM can callback to Git inside of your WSL installation.
git config --global credential.helper "/mnt/c/Users/<USERNAME>/AppData/Local/Programs/Git\ Credential\ Manager\ Core/git-credential-manager-core.exe"
安裝“Git Credential Manager for Windows” 的輔助工具
提示認(rèn)證失敗的解決辦法
進(jìn)入控制面板>>查看方式改為小圖標(biāo)>>憑據(jù)管理器>>windows憑據(jù)>>普通憑據(jù),在里面找到 git,點(diǎn)開編輯密碼,更新為最新密碼之后就可以正常操作了。
配置某個(gè)模式
git config --global credential.helper manager
手動(dòng)設(shè)置
git config --global credential.helper "/mnt/c/Program\ Files/Git/mingw64/libexec/git-core/git-credential-manager-core.exe"
重置指令
git config --global –unset credential.helper