日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 综合教程 >内容正文

综合教程

【原创】关于Git暂存区的理解

發(fā)布時(shí)間:2023/12/31 综合教程 35 生活家
生活随笔 收集整理的這篇文章主要介紹了 【原创】关于Git暂存区的理解 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

關(guān)于Git暫存區(qū)的理解

暫存區(qū)可以說(shuō)是Git的三大重要的區(qū)域之一,另外兩個(gè)分別是工作目錄和Git倉(cāng)庫(kù),所以說(shuō)對(duì)暫存區(qū)的深入理解可以幫助我們理解很多Git命令背后隱藏的工作原理。今天,本文將以一名初學(xué)者的角度詳細(xì)講解Git暫存區(qū),涉及到的Git命令也會(huì)作簡(jiǎn)單的介紹但不會(huì)深入。
在這里,我們先拋出Git暫存區(qū)的概念和相關(guān)理解,后面會(huì)一一說(shuō)明。
(1)所謂的暫存區(qū)只是一個(gè)簡(jiǎn)單的索引文件而已。
(2)暫存區(qū)這個(gè)索引文件里面包含的是文件的目錄樹,像一個(gè)虛擬的工作區(qū),在這個(gè)虛擬工作區(qū)的目錄樹中,記錄了文件名、文件的時(shí)間戳、文件長(zhǎng)度、文件類型以及最重要的SHA-1值,文件的內(nèi)容并沒有存儲(chǔ)在其中,所以說(shuō) 它像一個(gè)虛擬的工作區(qū)。
(3)索引指向的是.Git/objects下的文件。

(4)暫存區(qū)的作用:除非是繞過(guò)暫存區(qū)直接提交,否則Git想把修改提交上去,就必須將修改存入暫存區(qū)最后才能commit。每次提交的是暫存區(qū)所對(duì)應(yīng)的文件快照。
好了結(jié)論說(shuō)到這,上面的結(jié)論開始接觸時(shí)你不一定都能理解,下面開始進(jìn)行詳細(xì)說(shuō)明。

當(dāng)我們?cè)谀硞€(gè)目錄下運(yùn)行g(shù)it init命令后,在該目錄下便會(huì)生成一個(gè).git的子目錄,這個(gè)目錄是隱藏的。它是用來(lái)保存元數(shù)據(jù)以及對(duì)象數(shù)據(jù)庫(kù)的地方,這個(gè)目錄可以說(shuō)是Git的核心,每次克隆鏡像倉(cāng)庫(kù)時(shí),實(shí)際上拷貝的這個(gè)目錄里的內(nèi)容而已,然后再根據(jù)這個(gè)目錄恢復(fù)工作目錄(工作目錄:你所git init的目錄,但不包含.git這個(gè)隱藏的目錄),即在工作目錄下生成相應(yīng)的項(xiàng)目文件和目錄。而我們的暫存區(qū)也位于這個(gè).git目錄之下,名為index,它一般很小,一般不超過(guò)1KB左右,這和它存儲(chǔ)的內(nèi)容是有關(guān)系的。
在這個(gè)目錄下,除了index這個(gè)暫存區(qū)索引文件,還有其他重要的文件和目錄,其中有存放數(shù)據(jù)對(duì)象的objects目錄(這可以說(shuō)是我們Git的一個(gè)倉(cāng)庫(kù)了)、存放引用文件的refs目錄以及存放指向當(dāng)前分支的HEAD文件。

和暫存區(qū)極其相關(guān)的一條命令是

git add <文件名>//將一個(gè)文件添加進(jìn)暫存區(qū)

git add可以分兩條底層命令實(shí)現(xiàn):

1 git hash-object <文件名>
2 git update-index <文件名>

運(yùn)行第一條命令,Git將會(huì)根據(jù)新生成的文件產(chǎn)生一個(gè)長(zhǎng)度為40的SHA-1哈希字符串,并在.git/objects目錄下生成一個(gè)以該SHA-1的前兩個(gè)字符命名的子目錄,然后在該子目錄下,存儲(chǔ)剛剛生成的一個(gè)新文件,新文件名稱是SHA-1的剩下的38個(gè)字符。
第二條命令將會(huì)更新.git/index索引,使它指向新生成的objects目錄下的文件。
在objects目錄下新生成的文件是什么文件呢?

在這個(gè)目錄下,Git將其下文件分為四種類型,其中有兩種是tree類型和blob類型,blob類型文件存儲(chǔ)的就是我們運(yùn)行命令增加的文件加上一個(gè)特定的文件頭,而tree類型文件就相當(dāng)于我們系統(tǒng)下的目錄了,里面存儲(chǔ)的是多條記錄,每一條記錄含有一個(gè)指向 blob 或子 tree 對(duì)象的 SHA-1 指針,并附有該對(duì)象的權(quán)限模式 (mode)、類型和文件名信息,它和blob類型對(duì)象不一樣,存儲(chǔ)的并非文件的內(nèi)容。

如果生成一個(gè)新的文件存入Git倉(cāng)庫(kù)中而沒有第二步的更新.git/index索引,那么將會(huì)發(fā)生兩種情況:

(1)如果該文件從未添加進(jìn)暫存區(qū),也就是將該文件從未更新到index索引中,那么Git是會(huì)一直顯示未跟蹤的文件。
模擬一下該情況,可以選擇一個(gè)無(wú)用的目錄進(jìn)行g(shù)it init,然后在運(yùn)行g(shù)it status,在目錄下新建一個(gè)test.txt文件并增加內(nèi)容,運(yùn)行g(shù)it status,運(yùn)行g(shù)it hash-object d.txt,再運(yùn)行g(shù)it status。

 1     #初始化倉(cāng)庫(kù)
 2     $git init
 3     Initialized empty Git repository in E:/t/test/.git/
 4     #查看Git當(dāng)前狀態(tài)
 5     $git status
 6     On branch master
 7     Initial commit
 8     nothing to commit (create/copy files and use "git add" to track)
 9     #在當(dāng)前目錄下新建一個(gè)內(nèi)容為"this is a test file"的test.txt
10     $echo 'this is a test file ,version 1'> test.txt
11     #再次查看Git的狀態(tài),Git會(huì)提示工作目錄下有一個(gè)未跟蹤的文件
12     $git status
13     On branch master
14     Initial commit
15     Untracked files:
16     (use "git add <file>..." to include in what will be committed)
17     test.txt
18     nothing added to commit but untracked files present (use "git add" to track)
19     #此時(shí)查看.git/objects目錄,只有兩個(gè)文件夾info和pack
20     $git hash-object -w test.txt
21     4617a36485976a90eb72e7020911dea0c892956b
22     #此時(shí).git/objects目錄下有了46子目錄以及該子目錄下17a36485976a90eb72e7020911dea0c892956b文件
23     #Git仍然顯示test.txt為未跟蹤文件
24     $git status
25     On branch master
26     Initial commit
27     Untracked files:
28     (use "git add <file>..." to include in what will be committed)
29     test.txt
30     nothing added to commit but untracked files present (use "git add" to track)

(2)如果文件曾經(jīng)添加進(jìn)暫存區(qū),那么結(jié)果會(huì)是怎樣?那么結(jié)果顯示的是修改結(jié)果未放入暫存區(qū)。
模擬下情況:git add,git status ,git commit -m "add test.txt file ,version 1",git status,修改文件,git status

 1     #將我們上次的test.txt添加進(jìn)暫存區(qū)
 2     $git add test.txt
 3     #查看狀態(tài)
 4     $git status
 5     On branch master
 6     Initial commit
 7     Changes to be committed:
 8     (use "git rm --cached <file>..." to unstage)
 9     new file: test.txt
10     #提交
11     git commit -m "add test.txt file ,version 1"
12     #查看當(dāng)前狀態(tài),當(dāng)前工作目錄是干凈的,沒有什么要提交的了
13     #此時(shí)查看.git/objects目錄,多了兩個(gè)子目錄,一個(gè)是tree對(duì)象,一個(gè)是commit對(duì)象暫時(shí)忽略它
14     $git status
15     On branch master
16     nothing to commit, working directory clean
17     #繼續(xù)修改
18     $echo 'this is a test file ,version 2'> test.txt
19     #Git顯示有一個(gè)修改文件未放入暫存區(qū)
20     On branch master
21     Changes not staged for commit:
22     (use "git add <file>..." to update what will be committed)
23     (use "git checkout -- <file>..." to discard changes in working directory)
24     modified: test.txt
25     no changes added to commit (use "git add" and/or "git commit -a")
26     $git hash-object -w test.txt
27     1ed62f7cc06e6a57cdbaf9a5a5023aa93bd1ffb1
28     $git status
29     On branch master
30     Changes not staged for commit:
31     (use "git add <file>..." to update what will be committed)
32     (use "git checkout -- <file>..." to discard changes in working directory)
33     modified: test.txt
34     no changes added to commit (use "git add" and/or "git commit -a")

前后兩次,一次顯示未跟蹤,一次顯示未放入暫存區(qū),我們可以得出一個(gè)結(jié)論:即使在.git的倉(cāng)庫(kù)中生成了相應(yīng)的數(shù)據(jù)對(duì)象文件,如果沒有update index更新索引,索引還是指向.git/objects下舊版本的文件或者文件在index中沒根本有索引,Git也無(wú)法commit。如果我們?cè)诘诙N情況下,更新索引同時(shí)提交,那么提交的test.txt版本是最近的一次add的版本。另外,我們可以看到git add 后更新的暫存區(qū)只是一些文件索引,而文件的快照是保存在.git/objects目錄下。

如果你在工作目錄下再新建一個(gè)文件,查看Git狀態(tài),Git只顯示剛剛新建的文件為未跟蹤文件,而Git對(duì)我們那個(gè)test.txt沒有提示,這時(shí)我們add新建的文件然后提交,提交的文件包括了剛剛新建的文件和test.txt,我們每一次提交時(shí),都無(wú)需對(duì)曾經(jīng)git add 的文件再進(jìn)行一次git add 操作,說(shuō)明每次add后,Git都會(huì)在index下更新文件索引,而且該索引是一直存在的,除非使用git rm刪除。


 1     #創(chuàng)建一個(gè)new.txt新文件
 2     $echo 'this is a new.txt file'> new.txt
 3     #添加到暫存區(qū)并提交,此時(shí)可以看到提示信息中有master b5e4b5c,該數(shù)值為commit對(duì)象的SHA-1值
 4     $git add new.txt
 5     $git commit -m "add new.txt file"
 6     [master b5e4b5c] add new.txt file
 7     1 file changed,1 file insertion(+)
 8     create mode 100644 new.txt
 9     #通過(guò)cat-file命令可以查看對(duì)象中存儲(chǔ)的內(nèi)容,可以看到master commit對(duì)象指向的是一棵樹對(duì)象,即代表根目錄
10     $git cat-file -p b5e4b5c
11     tree 019ab86ed8f73265378a25dc00bff6c085f35cb0
12     parent 8d50d0c061da5104551bdbaa060e0d4c916411c1
13     author cposture <cposture@126.com>1418539116+0800
14     committer cposture <cposture@126.com>1418539116+0800
15     add new.txt file
16     #查看樹對(duì)象根目錄的存儲(chǔ)內(nèi)容,可以發(fā)現(xiàn)tree對(duì)象存儲(chǔ)的是指向兩個(gè)我們創(chuàng)建的文件SHA-1值和其他相關(guān)信息,而不是數(shù)據(jù)本省內(nèi)容
17     $git cat-file -p 019ab86
18     100644 blob 3e1267f7b311e69a691cf2ff5b90b46afaa1a359    new.txt
19     100644 blob d5210ccb24bd6e8bbc994ade3be3b48a9001f3b7 test.txt

理解暫存區(qū),還要弄清楚我們到底提交上去的是什么?這和暫存區(qū)有什么聯(lián)系?
回答這個(gè)問題前,我們先回想一下,上文說(shuō)的.git/objects下文件有四種類型,其中第三種是commit對(duì)象。
commit對(duì)象指明了該時(shí)間點(diǎn)項(xiàng)目快照的頂層樹對(duì)象、作者/提交者信息(從 Git的user.nameuser.email中獲得)以及當(dāng)前時(shí)間戳、一個(gè)空行,以及提交注釋信息。
簡(jiǎn)單地增添一個(gè)文件后,我們每次執(zhí)行g(shù)it commit操作,一般都會(huì)在.git/objects目錄下生成另外兩個(gè)文件(這在上文模擬的第二種情況的命令行的第13行注釋中也提到過(guò)),一個(gè)是tree對(duì)象類型文件,另一個(gè)便是commit類型文件,為什么會(huì)生成兩個(gè)文件而不是一個(gè)。

這個(gè)commit對(duì)象中包含的tree對(duì)象SHA-1值指向了最新版本的根目錄樹對(duì)象。這個(gè)tree對(duì)象是根據(jù)你的暫存區(qū)而創(chuàng)建的,每個(gè)tree都是這樣,所以創(chuàng)建tree前都需將文件或目錄添加進(jìn)暫存區(qū)。如果是添加的是目錄則會(huì)再生成一個(gè)子tree對(duì)象,再根據(jù)目錄下的文件分別生成相應(yīng)的blob普通文件和子tree對(duì)象。這個(gè)根tree對(duì)象中包含的多條記錄,簡(jiǎn)單的概括,分別是修改后添加進(jìn)暫存區(qū)SHA-1改變了的文件或目錄(上文說(shuō)過(guò)的git add 分為的兩步,其中最后一步是更新修改文件在暫存區(qū)的SHA-1值)或者是沒修改但曾添加進(jìn)暫存區(qū),SHA-1值仍不變的文件或目錄。Git正是拷貝暫存區(qū)的這些目錄樹和文件的SHA-1等信息到commit對(duì)象而生成Git的一個(gè)提交,即commit對(duì)象,commit對(duì)象保存的提交完整的記錄了當(dāng)前所有已跟蹤文件的快照。所以你所提交的項(xiàng)目來(lái)自于暫存區(qū)!


簡(jiǎn)而言之,文件索引即暫存區(qū),建立了文件和.git/objects目錄下的對(duì)象實(shí)體之間的映射關(guān)系,如下圖:



本文鏈接:http://www.cnblogs.com/cposture/p/4178003.html

總結(jié)

以上是生活随笔為你收集整理的【原创】关于Git暂存区的理解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。