溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Git索引如何創(chuàng)建與提交

發(fā)布時間:2022-01-10 17:29:10 來源:億速云 閱讀:132 作者:iii 欄目:系統(tǒng)運維

這篇“Git索引如何創(chuàng)建與提交”文章的知識點大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Git索引如何創(chuàng)建與提交”文章吧。

 不一樣的索引

Git 索引是一個在你的工作目錄(working tree)和項目倉庫間的暫存區(qū)域(staging area)。有了它,  你可以把許多內(nèi)容的修改一起提交(commit)。 如果你創(chuàng)建了一個提交(commit),那么提交的一般是暫存區(qū)里的內(nèi)容, 而不是工作目錄中的內(nèi)容。

一個Git項目中文件的狀態(tài)大概分成下面的兩大類,而第二大類又分為三小類:

1、未被跟蹤的文件(untracked file)

2、已被跟蹤的文件(tracked file)

          1、被修改但未被暫存的文件(changed but not updated或modified)

          2、已暫存可以被提交的文件(changes to be committed 或staged)

          3、自上次提交以來,未修改的文件(clean 或 unmodified)

看到上面的這么多的規(guī)則,大家早就頭大了吧。老辦法,我們建一個Git測試項目來試驗一下:

我們先來建一個空的項目:

$rm -rf stage_proj
$mkdir stage_proj
$cd stage_proj
$git init
Initialized empty Git repository in /home/test/work/test_stage_proj/.git/

我們還創(chuàng)建一個內(nèi)容是“hello, world”的文件:

$echo "hello,world" > readme.txt

現(xiàn)在來看一下當前工作目錄的狀態(tài),大家可以看到“readme.txt”處于未被跟蹤的狀態(tài)(untracked file):

$git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add ..." to include in what will be committed)
#
# readme.txt
nothing added to commit but untracked files present (use "git add" to track)

把“readme.txt"加到暫存區(qū): $git add readme.txt

現(xiàn)在再看一下當前工作目錄的狀態(tài):

$git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached ..." to unstage)
#
# new file: readme.txt
#

可以看到現(xiàn)在"readme.txt"的狀態(tài)變成了已暫存可以被提交(changes to be committed),這意味著我們下一步可以直接執(zhí)行“git  commit“把這個文件提交到本地的倉庫里去了。

暫存區(qū)(staging  area)一般存放在“git目錄“下的index文件(.git/index)中,所以我們把暫存區(qū)有時也叫作索引(index)。索引是一個二進制格式的文件,里面存放了與當前暫存內(nèi)容相關(guān)的信息,包括暫存的文件名、文件內(nèi)容的SHA1哈希串值和文件訪問權(quán)限,整個索引文件的內(nèi)容以暫存的文件名進行排  序保存的。

但是我不想馬上就把文件提交,我想看一下暫存區(qū)(staging area)里的內(nèi)容,我們執(zhí)行g(shù)it ls-files命令看一下:

$git ls-files --stage
100644 2d832d9044c698081e59c322d5a2a459da546469 0 readme.txt

我們?nèi)绻锌催^上一篇文章里 的"庖丁解牛",  你會發(fā)現(xiàn)“git目錄“里多出了”.git/objects/2d/832d9044c698081e59c322d5a2a459da546469”這么一個文件,再執(zhí)行“git  cat-file -p 2d832d”  的話,就可以看到里面的內(nèi)容正是“hello,world"。Git在把一個文件添加暫存區(qū)時,不但把它在索引文件(.git/index)里掛了號,而且把它的內(nèi)容先保存到了“git目錄“里面去了。

如果我們執(zhí)行”git add“命令時不小心把不需要的文件也加入到暫存區(qū)中話,可以執(zhí)行“git rm --cached filename"  來把誤添加的文件從暫存區(qū)中移除。

現(xiàn)在我們先在"readme.txt"文件上做一些修改后:

$echo "hello,world2" >> readme.txt

再來看一下暫存區(qū)的變化:

$git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached ..." to unstage)
#
# new file: readme.txt
#
# Changed but not updated:
# (use "git add ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory)
#
# modified: readme.txt
#

大家可以看到命令輸出里多了一塊內(nèi)容:“changed but not updated ...... modified:  readme.txt”。大家可能會覺得很奇怪,我前面不是把"readme.txt"這個文件給添加到暫存區(qū)里去了嗎,這里怎么又提示我未添加到暫存區(qū)  (changed but not updated)呢,是不是Git搞錯了呀。

Git 沒有錯,每次執(zhí)行“git  add”添加文件到暫存區(qū)時,它都會把文件內(nèi)容進行SHA1哈希運算,在索引文件中新加一項,再把文件內(nèi)容存放到本地的“git目錄“里。如果在上次執(zhí)行 “git  add”之后再對文件的內(nèi)容進行了修改,那么在執(zhí)行“git  status”命令時,Git會對文件內(nèi)容進行SHA1哈希運算就會發(fā)現(xiàn)文件又被修改了,這時“readme.txt“就同時呈現(xiàn)了兩個狀態(tài):被修改但未被暫存的文件(changed  but not updated),已暫存可以被提交的文件(changes to be committed)。如果我們這時提交的話,就是只會提交***次“git  add"所以暫存的文件內(nèi)容。

我現(xiàn)在對于“hello,world2"的這個修改不是很滿意,想要撤消這個修改,可以執(zhí)行g(shù)it checkout這個命令:

$git checkout -- readme.txt

現(xiàn)在再來看一下倉庫里工作目錄的狀態(tài):

$git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached ..." to unstage)
#
# new file: readme.txt
#

好的,現(xiàn)在項目恢復到我想要的狀態(tài)了,下面我就用git commit 命令把這個修改提交了吧:

$git commit -m "project init"
[master (root-commit) 6cdae57] project init 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 readme.txt

現(xiàn)在我們再來看一下工作目錄的狀態(tài):

$git status
# On branch master
nothing to commit (working directory clean)

大家可以看到“nothing to commit (working directory clean)”;如果一個工作樹(working  tree)中所有的修改都已提交到了當前分支里(current head),那么就說它是干凈的(clean),反之它就是臟的(dirty)。

SHA1值內(nèi)容尋址

正如Git is the next Unix 一文中所說的一樣,Git是一種全新的使用數(shù)據(jù)的方式(Git is a totally new way to  operate on  data)。Git把它所管理的所有對象(blob,tree,commit,tag……),全部根據(jù)它們的內(nèi)容生成SHA1哈希串值作為對象名;根據(jù)目前的數(shù)學知識,如果兩塊數(shù)據(jù)的SHA1哈希串值相等,那么我們就可以認為這兩塊數(shù)據(jù)是相同  的。這樣會帶來的幾個好處:

Git只要比較對象名,就可以很快的判斷兩個對象的內(nèi)容是否相同。

因為在每個倉庫(repository)的“對象名”的計算方法都完全一樣,如果同樣的內(nèi)容存在兩個不同的倉庫中,就會存在相同的“對象名”。

Git還可以通過檢查對象內(nèi)容的SHA1的哈希值和“對象名”是否匹配,來判斷對象內(nèi)容是否正確。

我們通過下面的例子,來驗證上面所說的是否屬實?,F(xiàn)在創(chuàng)建一個和“readme.txt“內(nèi)容完全相同的文件”readme2.txt“,然后再把它提交到本地倉庫中:

$echo "hello,world" > readme2.txt
$git add readme2.txt
$git commit -m "add new file: readme2.txt"
[master 6200c2c] add new file: readme2.txt
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 readme2.txt

下面的這條很復雜的命令是查看當前的提交(HEAD)所包含的blob對象:

$git cat-file -p HEAD | head -n 1 | cut -b6-15 | xargs git cat-file -p
100644 blob 2d832d9044c698081e59c322d5a2a459da546469 readme.txt
100644 blob 2d832d9044c698081e59c322d5a2a459da546469 readme2.txt

我們再來看看上一次提交(HEAD^)所包含的blob對象:

$git cat-file -p HEAD^ | head -n 1 | cut -b6-15 | xargs git cat-file -p
100644 blob 2d832d9044c698081e59c322d5a2a459da546469 readme.txt

很明顯大家看到盡管當前的提交比前一次多了一個文件,但是它們之間卻是在共用同一個blob對象:“2d832d9”。

No delta, just snapshot

Git 與大部分你熟悉的版本控制系統(tǒng),如Subversion、CVS、Perforce 之間的差別是很大的。傳統(tǒng)系統(tǒng)使用的是: “增量文件系統(tǒng)”  (Delta Storage  systems),它們存儲是每次提交之間的差異。而Git正好與之相反,它是保存的是每次提交的完整內(nèi)容(snapshot);它會在提交前根據(jù)要提交  的內(nèi)容求SHA1哈希串值作為對象名,看倉庫內(nèi)是否有相同的對象,如果沒有就將在“.git/objects"目錄創(chuàng)建對應的對象,如果有就會重用已有的  對象,以節(jié)約空間。

下面我們來試驗一下Git是否真的是以“snapshot”方式保存提交的內(nèi)容。

先修改一下"readme.txt",給里面加點內(nèi)容,再把它暫存,***提交到本地倉庫中:

$echo "hello,world2" >> readme.txt
$git add readme.txt
$git commit -m "add new content for readme.txt"
[master c26c2e7] add new content for readme.txt 1 files changed, 1 insertions(+), 0 deletions(-)

我們現(xiàn)在看看當前版本所包含的blob對象有哪些:

$git cat-file -p HEAD | head -n 1 | cut -b6-15 | xargs git cat-file -p
100644 blob 2e4e85a61968db0c9ac294f76de70575a62822e1 readme.txt
100644 blob 2d832d9044c698081e59c322d5a2a459da546469 readme2.txt

從上面的命令輸出,我們可以看到"readme.txt"已經(jīng)對應了一個新的blob對象:“2e4e85a”,而之前版本的"readme.txt“對應的blob對象是:“2d832d9”。下面我們再來看一看這兩個”blob“里面的內(nèi)容和我們的預期是否相同:

$git cat-file -p 2e4e85a
hello,world
hello,world2
$git cat-file -p 2d832d9
hello,world

大家可以看到,每一次提交的文件內(nèi)容還是全部保存的(snapshot)。

以上就是關(guān)于“Git索引如何創(chuàng)建與提交”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關(guān)的知識內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

git
AI