成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Git歷險記(4):索引與提交的那些事

系統 Linux
本文是《Git歷險記》的第四篇,前三篇文章從初識、安裝、設置Git談起,并介紹了git add,git commit這兩個命令。但是對這兩個命令幕后還有很多有趣的細節,本文將一一介紹。以下是原文。

編者按:本文是《Git歷險記》的第四篇,前三篇文章從初識、安裝、設置Git談起,并介紹了git add,git commit這兩個命令。但是對這兩個命令幕后還有很多有趣的細節,本文將一一介紹。以下是原文。

 不一樣的索引

我想如果看過《Git歷險記》的前面三篇文章的朋友可能已經知道怎么用git add,git commit這兩個命令了;知道它們一個是把文件暫存到索引中為下一次提交做準備,一個創建新的提交(commit)。但是它們臺前幕后的一些有趣的細節大家不一定知曉,請允許我一一道來。

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

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

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

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

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

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

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

看到上面的這么多的規則,大家早就頭大了吧。老辦法,我們建一個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/

我們還創建一個內容是“hello, world”的文件:

$echo "hello,world" > readme.txt

現在來看一下當前工作目錄的狀態,大家可以看到“readme.txt”處于未被跟蹤的狀態(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"加到暫存區: $git add readme.txt

現在再看一下當前工作目錄的狀態:

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

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

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

但是我不想馬上就把文件提交,我想看一下暫存區(staging area)里的內容,我們執行git ls-files命令看一下:

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

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

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

現在我們先在"readme.txt"文件上做一些修改后:

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

再來看一下暫存區的變化:

$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
#

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

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

我現在對于“hello,world2"的這個修改不是很滿意,想要撤消這個修改,可以執行git checkout這個命令:

$git checkout -- readme.txt

現在再來看一下倉庫里工作目錄的狀態:

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

好的,現在項目恢復到我想要的狀態了,下面我就用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

現在我們再來看一下工作目錄的狀態:

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

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

SHA1值內容尋址

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

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

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

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

我們通過下面的例子,來驗證上面所說的是否屬實。現在創建一個和“readme.txt“內容完全相同的文件”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 與大部分你熟悉的版本控制系統,如Subversion、CVS、Perforce 之間的差別是很大的。傳統系統使用的是: “增量文件系統” (Delta Storage systems),它們存儲是每次提交之間的差異。而Git正好與之相反,它是保存的是每次提交的完整內容(snapshot);它會在提交前根據要提交 的內容求SHA1哈希串值作為對象名,看倉庫內是否有相同的對象,如果沒有就將在“.git/objects"目錄創建對應的對象,如果有就會重用已有的 對象,以節約空間。

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

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

$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(-)

我們現在看看當前版本所包含的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"已經對應了一個新的blob對象:“2e4e85a”,而之前版本的"readme.txt“對應的blob對象是:“2d832d9”。下面我們再來看一看這兩個”blob“里面的內容和我們的預期是否相同:

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

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

小結

Git內在機制和其它傳統的版本控制系統(VCS)間存在本質的差異,所以Git的里"add"操作的含義和其它VCS存在差別也不足為奇,“git add“不但能把未跟蹤的文件(untracked file)添加到版本控制之下,也可以把修改了的文章暫存到索引中。

同時,由于采用“SHA1哈希串值內容尋值“和”快照存儲(snapshot)“,讓Git成為一個速度非常非常快的版本控制系統(VCS)。

原文連接:http://www.infoq.com/cn/news/2011/03/git-adventures-index-submit

【編輯推薦】

  1. Git歷險記(3):創建一個自己的本地倉庫
  2. Git歷險記(2):Git的安裝和配置
  3. Git歷險記(1):初識版本控制系統Git
責任編輯:黃丹 來源: InfoQ
相關推薦

2011-03-30 10:50:55

GitLinux 版本控制

2011-01-26 10:05:36

Git安裝配置

2009-10-15 09:21:00

CCNA考試歷險記CCNA

2022-05-05 19:26:17

Druid分布式存儲

2022-05-26 21:38:02

開源分布式Hadoop

2011-01-26 09:09:06

版本控制系統GitLinux

2021-02-22 08:20:32

Activity動畫界面

2011-02-28 14:37:43

GitLinux版本控制

2011-09-16 16:05:10

MySQL

2014-04-01 09:13:23

程序員招聘

2017-03-08 08:53:44

Git命令 GitHub

2017-06-30 17:54:04

2016-10-27 14:28:59

Hadoop系統大數據

2021-10-19 21:39:51

Unsafe構造器內存

2021-04-22 05:43:22

索引設計SET

2013-04-12 09:41:52

MySQL 5.6

2017-12-08 10:20:45

FedoraLinux

2019-07-15 15:37:31

頁面緩存內存

2022-06-05 13:51:47

SentinelOpenFeign服務熔斷

2014-06-06 16:08:17

初志科技
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 午夜激情一区 | 欧美福利在线 | 黄免费观看视频 | 九九九视频在线 | 亚洲精品自拍 | 国产精品综合视频 | 阿v视频在线观看 | 中文字幕av一区二区三区 | 日日摸夜夜添夜夜添精品视频 | 一级黄色片毛片 | 免费1区2区3区| 毛片站 | 午夜成人在线视频 | 久草在线高清 | 成人午夜免费在线视频 | 亚洲视频在线一区 | 亚洲免费观看 | 亚洲精品日韩在线 | 亚洲成年影院 | 国产精品久久久久久久久久软件 | 欧美激情一区二区三级高清视频 | 亚洲视频中文字幕 | 日本精品在线播放 | 91精品中文字幕一区二区三区 | 国产成人99久久亚洲综合精品 | 国产精品九九九 | 欧美激情在线一区二区三区 | 九九在线视频 | 久久精品一区二区三区四区 | 国产二区精品视频 | 国产美女自拍视频 | 亚洲精品在线看 | 国产a爽一区二区久久久 | 日韩福利在线观看 | 91av在线免费看 | 久久久网 | 久久99精品久久久久久琪琪 | 国产成人福利在线观看 | 久久久久久国产精品久久 | 国产亚洲一区二区三区在线观看 | 亚洲一区 |