中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

Git內(nèi)部原理之Git引用

2018-10-31    來(lái)源:importnew

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬(wàn)Linux鏡像隨意使用

這篇文章本應(yīng)該在6月份就完成,拖了4個(gè)月之后,終于鼓起勇氣撿起來(lái),實(shí)在慚愧。堅(jiān)持寫(xiě)文章就像長(zhǎng)跑,途中跑起來(lái)基本是靠慣性,如果停下來(lái)再起跑就很累很困難。

閑話不多說(shuō),本篇繼續(xù)承接前文講一講Git內(nèi)部原理,本篇的主題是Git引用的原理。

首先來(lái)搞清楚什么是Git引用,前文講了Git提交對(duì)象的哈希、存儲(chǔ)原理,理論上我們只要知道該對(duì)象的hash值,就能往前推出整個(gè)提交歷史,例如:

$ git log --pretty=oneline 3ac728ac62f0a7b5ac201fd3ed1f69165df8be31
3ac728ac62f0a7b5ac201fd3ed1f69165df8be31 third commit
d4d2c6cffb408d978cb6f1eb6cfc70e977378a5c second commit
db1d6f137952f2b24e3c85724ebd7528587a067a first commit

現(xiàn)在問(wèn)題來(lái)了,提交對(duì)象的這40位hash值不好記憶,Git引用相當(dāng)于給40位hash值取一個(gè)別名,便于識(shí)別和讀取。Git引用對(duì)象都存儲(chǔ)在.git/refs目錄下,該目錄下有3個(gè)子文件夾heads、tagsremotes,分別對(duì)應(yīng)于HEAD引用、標(biāo)簽引用和遠(yuǎn)程引用,下面分別講一講每種引用的原理。

HEAD引用

HEAD引用是用來(lái)指向每個(gè)分支的最后一次提交對(duì)象,這樣切換到一個(gè)分支之后,才能知道分支的“尾巴”在哪里。HEAD引用存儲(chǔ)在.git/refs/heads目錄下,有多少個(gè)分支,就有相應(yīng)的同名HEAD引用對(duì)象。例如代碼庫(kù)里面有mastertest兩個(gè)分支,那么.git/refs/heads目錄下就存在mastertest兩個(gè)文件,分別記錄了分支的最后一次提交。

HEAD引用的內(nèi)容就是提交對(duì)象的hash值,理論上我們可以手動(dòng)地構(gòu)造一個(gè)HEAD引用:

$ echo "3ac728ac62f0a7b5ac201fd3ed1f69165df8be31" > .git/refs/heads/master

Git提供了一個(gè)專(zhuān)有命令update-ref,用來(lái)查看和修改Git引用對(duì)象,當(dāng)然也包括HEAD引用:

$ git update-ref refs/heads/master 3ac728ac62f0a7b5ac201fd3ed1f69165df8be31
$ git update-ref refs/heads/master
3ac728ac62f0a7b5ac201fd3ed1f69165df8be31

上面的命令我們將master分支的HEAD指向了3ac728ac62f0a7b5ac201fd3ed1f69165df8be31,現(xiàn)在用git log查看下master的提交歷史,可以發(fā)現(xiàn)最后一次提交就是所更新的hash值:

$ git log --pretty=oneline master
3ac728ac62f0a7b5ac201fd3ed1f69165df8be31 (HEAD -> master) third commit
d4d2c6cffb408d978cb6f1eb6cfc70e977378a5c second commit
db1d6f137952f2b24e3c85724ebd7528587a067a first commit

同理,可以使用同樣的方法更新test分支的HEAD:

$ git update-ref refs/heads/test d4d2c6cffb408d978cb6f1eb6cfc70e977378a5c
$ git log --pretty=oneline test
d4d2c6cffb408d978cb6f1eb6cfc70e977378a5c (test) second commit
db1d6f137952f2b24e3c85724ebd7528587a067a first commit

.git/refs/heads目錄下存儲(chǔ)了每個(gè)分支的HEAD,那怎么知道代碼庫(kù)當(dāng)前處于哪個(gè)分支呢?這就需要一個(gè)代碼庫(kù)級(jí)別的HEAD引用。.git/HEAD這個(gè)文件就是整個(gè)代碼庫(kù)級(jí)別的HEAD引用。我們先查看一下.git/HEAD文件的內(nèi)容:

$ cat .git/HEAD
ref: refs/heads/master

我們發(fā)現(xiàn).git/HEAD文件的內(nèi)容不是40位hash值,而像是指向.git/refs/heads/master。嘗試切換到test

$ git checkout test
$ cat .git/HEAD
ref: refs/heads/test

切換分支后,.git/HEAD文件的內(nèi)容也跟著指向.git/refs/heads/test。.git/HEAD也是HEAD引用對(duì)象,與一般引用不同的是,它是“符號(hào)引用”。符號(hào)引用類(lèi)似于文件的快捷方式,鏈接到要引用的對(duì)象上。

Git提供專(zhuān)門(mén)的命令git symbolic-ref,用來(lái)查看和更新符號(hào)引用:

$ git symbolic-ref HEAD refs/heads/master
$ git symbolic-ref HEAD refs/heads/test

至此,我們分析了兩種HEAD引用,一種是分支級(jí)別的HEAD引用,用來(lái)記錄各分支的最后一次提交,存儲(chǔ)在.git/refs/heads目錄下,使用git update-ref來(lái)維護(hù);一種是代碼庫(kù)級(jí)別的HEAD引用,用來(lái)記錄代碼庫(kù)所處的分支,存儲(chǔ)在.git/HEAD文件,使用git symbolic-ref來(lái)維護(hù)。

標(biāo)簽引用

標(biāo)簽引用,顧名思義就是給Git對(duì)象打標(biāo)簽,便于記憶。例如,我們可以將某個(gè)提交對(duì)象打v1.0標(biāo)簽,表示是1.0版本。標(biāo)簽引用都存儲(chǔ)在.git/refs/tags里面。

標(biāo)簽引用和HEAD引用本質(zhì)是Git引用對(duì)象,同樣使用git update-ref來(lái)查看和修改:

$ git update-ref refs/tags/v1.0 d4d2c6cffb408d978cb6f1eb6cfc70e977378a5c
$ cat .git/refs/tags/v1.0
d4d2c6cffb408d978cb6f1eb6cfc70e977378a5c

還有一種標(biāo)簽引用稱(chēng)為“附注引用”,可以為標(biāo)簽添加說(shuō)明信息。上面的標(biāo)簽引用打了一個(gè)v1.0的標(biāo)簽表示發(fā)布1.0版本,有時(shí)候發(fā)布軟件的時(shí)候除了版本號(hào)信息,還要寫(xiě)更新說(shuō)明。附注引用就是用來(lái)實(shí)現(xiàn)打標(biāo)簽的同時(shí),也可以附帶說(shuō)明信息。

附注引用是怎么實(shí)現(xiàn)的呢?與常規(guī)標(biāo)簽引用不同的是,它不直接指向提交對(duì)象,而是新建一個(gè)Git對(duì)象存儲(chǔ)到.git/objects中,用來(lái)記錄附注信息,然后附注標(biāo)簽指向這個(gè)Git對(duì)象。

使用git tag建立一個(gè)附注標(biāo)簽:

$ git tag -a v1.1 3ac728ac62f0a7b5ac201fd3ed1f69165df8be31 -m "test tag"
$ cat .git/refs/tags/v1.1
8be4d8e4e8e80711dd7bae304ccfa63b35a6eb8c

使用git cat-file來(lái)查看附注標(biāo)簽所指向的Git對(duì)象:

$ git cat-file -p 8be4d8e4e8e80711dd7bae304ccfa63b35a6eb8c
object 3ac728ac62f0a7b5ac201fd3ed1f69165df8be31
type commit
tag v1.1
tagger jingsam <jing-sam@qq.com> 1529481368 +0800

test tag

可以看到,上面的Git對(duì)象存儲(chǔ)了我們填寫(xiě)的附注信息。

總之,普通的標(biāo)簽引用和附注引用同樣都是存儲(chǔ)的是40位hash值,指向一個(gè)Git對(duì)象,所不同的是普通的標(biāo)簽引用是直接指向提交對(duì)象,而附注標(biāo)簽是指向一個(gè)附注對(duì)象,附注對(duì)象再指向具體的提交對(duì)象。

另外,本質(zhì)上標(biāo)簽引用并不是只可以指向提交對(duì)象,實(shí)際上可以指向任何Git對(duì)象,即可以給任何Git對(duì)象打標(biāo)簽。

遠(yuǎn)程引用

遠(yuǎn)程引用,類(lèi)似于.git/refs/heads中存儲(chǔ)的本地倉(cāng)庫(kù)各分支的最后一次提交,在.git/refs/remotes是用來(lái)記錄多個(gè)遠(yuǎn)程倉(cāng)庫(kù)各分支的最后一次提交。

我們可以使用git remote來(lái)管理遠(yuǎn)程分支:

$ git remote add origin git@github.com:jingsam/git-test.git

上面添加了一個(gè)origin遠(yuǎn)程分支,接下來(lái)我們把本地倉(cāng)庫(kù)的master推送到遠(yuǎn)程倉(cāng)庫(kù)上:

$ git push origin master
Counting objects: 9, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (9/9), 720 bytes | 360.00 KiB/s, done.
Total 9 (delta 0), reused 0 (delta 0)
To github.com:jingsam/git-test.git
 * [new branch]      master -> master

這時(shí)候在.git/refs/remotes中的遠(yuǎn)程引用就會(huì)更新:

$ cat .git/refs/remotes/origin/master
3ac728ac62f0a7b5ac201fd3ed1f69165df8be31

和本地倉(cāng)庫(kù)的master比較一下,發(fā)現(xiàn)是一模一樣的,表示遠(yuǎn)程分支和本地分支是同步的:

$ cat .git/refs/heads/master
3ac728ac62f0a7b5ac201fd3ed1f69165df8be31

由于遠(yuǎn)程引用也是Git引用對(duì)象,所以理論上也可以使用git update-ref來(lái)手動(dòng)維護(hù)。但是,我們需要先把代碼與遠(yuǎn)程倉(cāng)庫(kù)進(jìn)行同步,在遠(yuǎn)程倉(cāng)庫(kù)中找到對(duì)應(yīng)分支的HEAD,然后使用git update-ref進(jìn)行更新,過(guò)程比較麻煩。而我們?cè)趫?zhí)行git pullgit push這樣的高層命令的時(shí)候,遠(yuǎn)程引用會(huì)自動(dòng)更新。

總結(jié)

到這里,三種Git引用都已分析完畢?偟膩(lái)說(shuō),三種Git引用都統(tǒng)一存儲(chǔ)到.git/refs目錄下,Git引用中的內(nèi)容都是40位的hash值,指向某個(gè)Git對(duì)象,這個(gè)對(duì)象可以是任意的Git對(duì)象,可以是數(shù)據(jù)對(duì)象、樹(shù)對(duì)象、提交對(duì)象。三種Git引用都可以使用git update-ref來(lái)手動(dòng)維護(hù)。

三種Git引用對(duì)象所不同的是,分別存儲(chǔ)于.git/refs/heads.git/refs/tags、.git/refs/remotes,存儲(chǔ)的文件夾不同,賦予了引用對(duì)象不同的功能。HEAD引用用來(lái)記錄本地分支的最后一次提交,標(biāo)簽引用用來(lái)給任意Git對(duì)象打標(biāo)簽,遠(yuǎn)程引用正式用來(lái)記錄遠(yuǎn)程分支的最后一次提交。

標(biāo)簽: 代碼

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:Android開(kāi)發(fā)技術(shù)周報(bào) Issue#179

下一篇:說(shuō)說(shuō) MQ 之 Kafka(三)