W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
Git 允許你通過幾種方法來(lái)指明特定的或者一定范圍內(nèi)的提交。 了解它們并不是必需的,但是了解一下總沒壞處。
你可以通過 Git 給出的 SHA-1 值來(lái)獲取一次提交,不過還有很多更人性化的方式來(lái)做同樣的事情。 本節(jié)將會(huì)介紹獲取單個(gè)提交的多種方法。
Git 十分智能,你只需要提供 SHA-1 的前幾個(gè)字符就可以獲得對(duì)應(yīng)的那次提交,當(dāng)然你提供的 SHA-1 字符數(shù)量不得少于 4 個(gè),并且沒有歧義——也就是說,當(dāng)前倉(cāng)庫(kù)中只有一個(gè)對(duì)象以這段 SHA-1 開頭。
例如查看一次指定的提交,假設(shè)你執(zhí)行?git log
?命令來(lái)查看之前新增一個(gè)功能的那次提交:
$ git log
commit 734713bc047d87bf7eac9674765ae793478c50d3
Author: Scott Chacon <schacon@gmail.com>
Date: Fri Jan 2 18:32:33 2009 -0800
fixed refs handling, added gc auto, updated tests
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Merge: 1c002dd... 35cfb2b...
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 15:08:43 2008 -0800
Merge commit 'phedders/rdocs'
commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 14:58:32 2008 -0800
added some blame and merge stuff
假設(shè)這個(gè)提交是?1c002dd....
,如果你想?git show
?這個(gè)提交,下面的命令是等價(jià)的(假設(shè)簡(jiǎn)短的版本沒有歧義):
$ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b
$ git show 1c002dd4b536e7479f
$ git show 1c002d
Git 可以為 SHA-1 值生成出簡(jiǎn)短且唯一的縮寫。 如果你在?git log
?后加上?--abbrev-commit
?參數(shù),輸出結(jié)果里就會(huì)顯示簡(jiǎn)短且唯一的值;默認(rèn)使用七個(gè)字符,不過有時(shí)為了避免 SHA-1 的歧義,會(huì)增加字符數(shù):
$ git log --abbrev-commit --pretty=oneline
ca82a6d changed the version number
085bb3b removed unnecessary test code
a11bef0 first commit
通常 8 到 10 個(gè)字符就已經(jīng)足夠在一個(gè)項(xiàng)目中避免 SHA-1 的歧義。
比如 Linux 內(nèi)核這個(gè)相當(dāng)大的 Git 項(xiàng)目,目前有超過 45 萬(wàn)個(gè)提交,包含 360 萬(wàn)個(gè)對(duì)象,也只需要前 11 個(gè)字符就能保證唯一性。
NOTE
關(guān)于 SHA-1 的簡(jiǎn)短說明
許多人覺得他們的倉(cāng)庫(kù)里有可能出現(xiàn)兩個(gè) SHA-1 值相同的對(duì)象。 然后呢?
如果你真的向倉(cāng)庫(kù)里提交了一個(gè)跟之前的某個(gè)對(duì)象具有相同 SHA-1 值的對(duì)象,Git 發(fā)現(xiàn)倉(cāng)庫(kù)里已經(jīng)存在了擁有相同 HASH 值的對(duì)象,就會(huì)認(rèn)為這個(gè)新的提交是已經(jīng)被寫入倉(cāng)庫(kù)的。 如果之后你想檢出那個(gè)對(duì)象時(shí),你將得到先前那個(gè)對(duì)象的數(shù)據(jù)。
但是這種情況發(fā)生的概率十分渺小。 SHA-1 摘要長(zhǎng)度是 20 字節(jié),也就是 160 位。 280 個(gè)隨機(jī)哈希對(duì)象才有 50% 的概率出現(xiàn)一次沖突 (計(jì)算沖突機(jī)率的公式是?
p = (n(n-1)/2) * (1/2^160))
?)。280 是 1.2 x 10^24 也就是一億億億。 那是地球上沙??倲?shù)的 1200 倍。舉例說一下怎樣才能產(chǎn)生一次 SHA-1 沖突。 如果地球上 65 億個(gè)人類都在編程,每人每秒都在產(chǎn)生等價(jià)于整個(gè) Linux 內(nèi)核歷史(360 萬(wàn)個(gè) Git 對(duì)象)的代碼,并將之提交到一個(gè)巨大的 Git 倉(cāng)庫(kù)里面,這樣持續(xù)兩年的時(shí)間才會(huì)產(chǎn)生足夠的對(duì)象,使其擁有 50% 的概率產(chǎn)生一次 SHA-1 對(duì)象沖突。 這要比你編程團(tuán)隊(duì)的成員同一個(gè)晚上在互不相干的意外中被狼襲擊并殺死的機(jī)率還要小。
指明一次提交最直接的方法是有一個(gè)指向它的分支引用。 這樣你就可以在任意一個(gè) Git 命令中使用這個(gè)分支名來(lái)代替對(duì)應(yīng)的提交對(duì)象或者 SHA-1 值。 例如,你想要查看一個(gè)分支的最后一次提交的對(duì)象,假設(shè)?topic1
?分支指向?ca82a6d
?,那么以下的命令是等價(jià)的:
$ git show ca82a6dff817ec66f44342007202690a93763949
$ git show topic1
如果你想知道某個(gè)分支指向哪個(gè)特定的 SHA-1,或者想看任何一個(gè)例子中被簡(jiǎn)寫的 SHA-1 ,你可以使用一個(gè)叫做?rev-parse
?的 Git 探測(cè)工具。 你可以在?Git 內(nèi)部原理?中查看更多關(guān)于探測(cè)工具的信息。簡(jiǎn)單來(lái)說,rev-parse
?是為了底層操作而不是日常操作設(shè)計(jì)的。 不過,有時(shí)你想看 Git 現(xiàn)在到底處于什么狀態(tài)時(shí),它可能會(huì)很有用。 你可以在你的分支上執(zhí)行?rev-parse
$ git rev-parse topic1
ca82a6dff817ec66f44342007202690a93763949
當(dāng)你在工作時(shí), Git 會(huì)在后臺(tái)保存一個(gè)引用日志(reflog),引用日志記錄了最近幾個(gè)月你的 HEAD 和分支引用所指向的歷史。
你可以使用?git reflog
?來(lái)查看引用日志
$ git reflog
734713b HEAD@{0}: commit: fixed refs handling, added gc auto, updated
d921970 HEAD@{1}: merge phedders/rdocs: Merge made by recursive.
1c002dd HEAD@{2}: commit: added some blame and merge stuff
1c36188 HEAD@{3}: rebase -i (squash): updating HEAD
95df984 HEAD@{4}: commit: # This is a combination of two commits.
1c36188 HEAD@{5}: rebase -i (squash): updating HEAD
7e05da5 HEAD@{6}: rebase -i (pick): updating HEAD
每當(dāng)你的 HEAD 所指向的位置發(fā)生了變化,Git 就會(huì)將這個(gè)信息存儲(chǔ)到引用日志這個(gè)歷史記錄里。 通過這些數(shù)據(jù),你可以很方便地獲取之前的提交歷史。 如果你想查看倉(cāng)庫(kù)中 HEAD 在五次前的所指向的提交,你可以使用?@{n}
?來(lái)引用 reflog 中輸出的提交記錄。
$ git show HEAD@{5}
你同樣可以使用這個(gè)語(yǔ)法來(lái)查看某個(gè)分支在一定時(shí)間前的位置。 例如,查看你的?master
?分支在昨天的時(shí)候指向了哪個(gè)提交,你可以輸入
$ git show master@{yesterday}
就會(huì)顯示昨天該分支的頂端指向了哪個(gè)提交。 這個(gè)方法只對(duì)還在你引用日志里的數(shù)據(jù)有用,所以不能用來(lái)查好幾個(gè)月之前的提交。
可以運(yùn)行?git log -g
?來(lái)查看類似于?git log
?輸出格式的引用日志信息:
$ git log -g master
commit 734713bc047d87bf7eac9674765ae793478c50d3
Reflog: master@{0} (Scott Chacon <schacon@gmail.com>)
Reflog message: commit: fixed refs handling, added gc auto, updated
Author: Scott Chacon <schacon@gmail.com>
Date: Fri Jan 2 18:32:33 2009 -0800
fixed refs handling, added gc auto, updated tests
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Reflog: master@{1} (Scott Chacon <schacon@gmail.com>)
Reflog message: merge phedders/rdocs: Merge made by recursive.
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 15:08:43 2008 -0800
Merge commit 'phedders/rdocs'
值得注意的是,引用日志只存在于本地倉(cāng)庫(kù),一個(gè)記錄你在你自己的倉(cāng)庫(kù)里做過什么的日志。 其他人拷貝的倉(cāng)庫(kù)里的引用日志不會(huì)和你的相同;而你新克隆一個(gè)倉(cāng)庫(kù)的時(shí)候,引用日志是空的,因?yàn)槟阍趥}(cāng)庫(kù)里還沒有操作。?git show HEAD@{2.months.ago}
?這條命令只有在你克隆了一個(gè)項(xiàng)目至少兩個(gè)月時(shí)才會(huì)有用——如果你是五分鐘前克隆的倉(cāng)庫(kù),那么它將不會(huì)有結(jié)果返回。
祖先引用是另一種指明一個(gè)提交的方式。 如果你在引用的尾部加上一個(gè)?^
, Git 會(huì)將其解析為該引用的上一個(gè)提交。 假設(shè)你的提交歷史是:
$ git log --pretty=format:'%h %s' --graph
* 734713b fixed refs handling, added gc auto, updated tests
* d921970 Merge commit 'phedders/rdocs'
|\
| * 35cfb2b Some rdoc changes
* | 1c002dd added some blame and merge stuff
|/
* 1c36188 ignore *.gem
* 9b29157 add open3_detach to gemspec file list
你可以使用?HEAD^
?來(lái)查看上一個(gè)提交,也就是 “HEAD 的父提交”:
$ git show HEAD^
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Merge: 1c002dd... 35cfb2b...
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 15:08:43 2008 -0800
Merge commit 'phedders/rdocs'
你也可以在?^
?后面添加一個(gè)數(shù)字——例如?d921970^2
?代表 “d921970 的第二父提交” 這個(gè)語(yǔ)法只適用于合并(merge)的提交,因?yàn)楹喜⑻峤粫?huì)有多個(gè)父提交。 第一父提交是你合并時(shí)所在分支,而第二父提交是你所合并的分支:
$ git show d921970^
commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
Author: Scott Chacon <schacon@gmail.com>
Date: Thu Dec 11 14:58:32 2008 -0800
added some blame and merge stuff
$ git show d921970^2
commit 35cfb2b795a55793d7cc56a6cc2060b4bb732548
Author: Paul Hedderly <paul+git@mjr.org>
Date: Wed Dec 10 22:22:03 2008 +0000
Some rdoc changes
另一種指明祖先提交的方法是?~
。 同樣是指向第一父提交,因此?HEAD~
?和?HEAD^
?是等價(jià)的。 而區(qū)別在于你在后面加數(shù)字的時(shí)候。?HEAD~2
?代表 “第一父提交的第一父提交”,也就是 “祖父提交” —— Git 會(huì)根據(jù)你指定的次數(shù)獲取對(duì)應(yīng)的第一父提交。 例如,在之前的列出的提交歷史中,HEAD~3
?就是
$ git show HEAD~3
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
Author: Tom Preston-Werner <tom@mojombo.com>
Date: Fri Nov 7 13:47:59 2008 -0500
ignore *.gem
也可以寫成?HEAD^^^
,也是第一父提交的第一父提交的第一父提交:
$ git show HEAD^^^
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
Author: Tom Preston-Werner <tom@mojombo.com>
Date: Fri Nov 7 13:47:59 2008 -0500
ignore *.gem
你也可以組合使用這兩個(gè)語(yǔ)法 —— 你可以通過?HEAD~3^2
?來(lái)取得之前引用的第二父提交(假設(shè)它是一個(gè)合并提交)。
你已經(jīng)學(xué)會(huì)如何單次的提交,現(xiàn)在來(lái)看看如何指明一定區(qū)間的提交。 當(dāng)你有很多分支時(shí),這對(duì)管理你的分支時(shí)十分有用,你可以用提交區(qū)間來(lái)解決 “這個(gè)分支還有哪些提交尚未合并到主分支?” 的問題
最常用的指明提交區(qū)間語(yǔ)法是雙點(diǎn)。 這種語(yǔ)法可以讓 Git 選出在一個(gè)分支中而不在另一個(gè)分支中的提交。 例如,你有如下的提交歷史?Figure?7-1
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: