三分鐘帶你玩轉GIT底層原理與核心命令

一、GIT體系概述:

大家公司是用什麼工具來管理程式碼版本?SVN、CVS、GIT

GIT和SVN有什麼區別呢?

GIT 與 svn 主要區別:

儲存方式不一樣

使用方式不一樣

管理方式不一樣

儲存方式區別:

GIT把內容按元資料方式儲存類似k/v資料庫,而SVN是按檔案儲存的(新版SVN已改成元資料儲存)GIT內部是有一個key/value的資料庫,可以理解為一個Map,內容提交到資料庫中時就會返回一個key,key是唯一的。

git init demo 建立一個git專案

cd demo 進入專案

echo “test demo” >> README。MF

git hash-object -w README。MF 把檔案提交到資料庫中

會返回一個key

git cat-file -p [key] 檢視檔案的內容回滾的話就可以透過key把值取出來進行回滾

使用方式區別:

從本地把檔案推送遠端服務,SVN只需要commit,而GIT需要add,commit,push三個步驟SVN基本使用過程

三分鐘帶你玩轉GIT底層原理與核心命令

從圖中可以看出無論是誰開發的程式碼都是直接commit就提交到了SVN

GIT基本使用過程

三分鐘帶你玩轉GIT底層原理與核心命令

git要提交內容的話,先要把修改的程式碼add進暫存區,然後commit到本地倉庫,然後在push到遠端倉庫

版本管理模式區別

git是一個分散式的版本管理系統,而SVN是一個遠端集中式的版本管理系統

集中式:

三分鐘帶你玩轉GIT底層原理與核心命令

當遠端倉庫服務掛掉了之後,本地專案就不能做任何操作了

分散式:

三分鐘帶你玩轉GIT底層原理與核心命令

從圖片中可以看出每個專案裡都有一個本地的git倉庫,因此當遠端git服務掛掉之後,不會影響到本地的專案,仍然可以提交建立切換分支

本地倉庫很明顯是可以和我們的遠端倉庫做關聯的,有四種傳輸協議支援與遠端倉庫進行連線(傳輸協議會在下一篇文章進行詳細的講解),如果網路和服務是正常的,本地倉庫就可以推送拉取程式碼,並且git還支援本地倉庫關聯多個遠端倉庫現在大家可以思考一下,為什麼要關聯多個遠端倉庫呢?

現在假設我們的團隊有100人,而一個倉庫的人員最多隻能有50人,因此需要分兩個倉庫去供開發人員使用,如果git只能關聯一個倉庫,那麼推送的時候就只有一個倉庫開發人員能夠拉取到程式碼

Richard Clayderman - 夢中的婚禮

Richard Clayderman - 夢中的婚禮

02:43

來自程式設計階級III

二、GIT核心命令使用

安裝git 客戶端安裝

官方客戶端:

httpsd://git-scm。com/downloads

其它客戶端:

https://tortoisegit。org/download/

認識git的基本使用

git專案建立與克隆

檔案提交與推送

完整模擬從專案新增到push的過程

建立專案

初始化git倉庫

提交檔案

遠端關聯

push至遠端倉庫

本地初始化GIT倉庫:

git clone 從遠端倉庫克隆到本地git init 在本地建立裸專案mvn archetype:generate 基於mvn 模板建立專案

本地新增

git add 新增指定檔案至暫存區git add 新增指定目錄至暫存區git add -a 或者git add 。 新增所有git rm ——cached target -r 將指定目錄及子目錄移除暫存區。gitignore 新增忽略配置檔案

本地提交

git commit -m ‘提交評論’ 提交至本地倉庫git commit -am ‘快新增與提交’ 快捷提交至本地倉庫

推送至遠端

git push origin <分支名稱>

分支管理

git branch [-avv] 檢視本地分支

git branch 基於當前分支建立分支

git branch 基於提交新建分支

git checkout 切換分支

git merge 合併指定分支

如果因衝突導致自動合併失敗,此時status為mergeing狀態需要手動修改後重新commit

遠端倉庫管理

git remote [-v] 檢視遠端配置

git remote add origin http:xxx。xxx 新增遠端地址

git remote remove origin http:xxx。xxx 刪除遠端地址

git branch ——track ——set-upstream-to = origin/test test 本地分支與遠端分支建立關聯

tag管理

git tag 檢視當前

git tag 建立分支

git tag -d 刪除分支

日誌管理

git log 檢視當前分支下所有提交日誌

git log 檢視指定分支下所有提交日誌

git log ——oneline 單行顯示日誌

git log master。。experiment 比較兩個版本的區別

三、git底層原理

GIT儲存物件

GIT樹物件

GIT提交物件

GIT引用

GIT儲存物件(HashMap)

Git 是一個內容定址檔案系統,其核心部分是一個簡單的鍵值對資料庫(key-value data store),你可以向資料庫中插入任意內容,它會返回一個用於取回該值的hash 鍵。

三分鐘帶你玩轉GIT底層原理與核心命令

echo ‘luban is good man’ | git hash-object -w ——stdin

GIT鍵值庫中插入資料

git cat-file -p 79362d07cf264f8078b489a47132afbc73f87b9a

基於鍵獲取指定內容

find 。git/objects/ -type f

查詢資料夾下所有的檔案 在。git/objects資料夾下就是查詢所有的git物件向資料庫中提交同樣的程式碼返回的key是相同的

三分鐘帶你玩轉GIT底層原理與核心命令

從圖片可以看出插入到鍵值庫的程式碼最後會變為git物件儲存在。git/objects資料夾下

模擬演示git 版寫入與回滾過程

查詢所有的git 對像

echo ‘version1’ > README。MF; git hash-object -w README。MF;

寫入版本

echo ‘version2’ > README。MF; git hash-object -w README。MF;

寫入版本

echo ‘version3’ > README。MF; git hash-object -w README。MF;

寫入版本

git cat-file -p c11e96db44f7f3bc4c608aa7d7cd9ba4ab25066e > README。MF

回滾指定版本

Git基於該功能 把每個檔案的版本中內容都儲存在資料庫中,當要進行版本回滾的時候就透過其中一個鍵將期取回並替換我們平常用的

git add

其實就是把修改之後的內容 插入到鍵值庫中。當我們執行

git add README。MF

等同於執行了

git hash-object -w README。MF

把檔案寫到資料庫中。我們解決了儲存的問題,但其只能儲存內容卻並沒有儲存檔名,如果要進行回滾 怎麼知道哪個內容對應哪個檔案呢?接下來我們要說的就是樹物件,它解決了檔名儲存的問題 ,使我們知道儲存的物件對應的是哪個檔案的內容。

GIT樹物件

樹對像解決了檔名的問題,它的目的是將多個檔名組織在一起,其內包含多個檔名稱與其對應的Key和其它樹對像的引用,可以理解成作業系統當中的資料夾,一個資料夾包含多個檔案和多個其它資料夾。

git add 。

把所有修改的檔案插入到鍵值庫內,每個檔案生成一個git物件儲存在。git/objects下

git commit -m ‘first commit’

在。git/objects下會生成兩個物件,一個提交物件,一個樹物件

git cat-file -p master^{tree}

檢視樹物件內容

三分鐘帶你玩轉GIT底層原理與核心命令

前兩個欄位是檔案的型別,第三個欄位是key,第四個欄位是生成這個git物件的檔名

提交後如果要回滾的話就是根據樹物件中的檔名找到對應的key,在根據key找到對應的內容,進行回滾

上面只在專案根目錄下建立了兩個檔案,沒有資料夾包裹,所以樹物件內型別只有blob,如果有資料夾包裹的話,提交之後會有一個頂級樹物件,裡面會包含檔名與對應的key,還會包含資料夾名與對應的子樹物件的key,類似於一個連結串列,不過儲存的並不是物件,而是物件的key與對應的檔名或資料夾名

三分鐘帶你玩轉GIT底層原理與核心命令

還記得之前說的,commit之後會生成兩個物件嗎,一個樹物件,一個提交物件,接下來我們就來看一下提交物件

GIT提交物件

一次提交即為當前版本的一個快照,該快照就是透過提交對像儲存,其儲存的內容為:一個頂級樹物件、上一次提交的對像啥希、提交者使用者名稱及郵箱、提交時間戳、提交評論。怎麼檢視提交物件的key是哪個呢?

git log master

檢視提交日誌

三分鐘帶你玩轉GIT底層原理與核心命令

第一個就是最近一次提交物件的key

三分鐘帶你玩轉GIT底層原理與核心命令

裡面的內容有頂級樹物件的key,以及parent物件的key,也就是上一個提交物件的key

透過上面的知識,我們可以推測出從修改一個檔案到提交的過程總共生成了三個對像:一個內容物件 ==> 儲存了檔案內容一個樹對像 ==> 儲存了檔名及內容對像的key

一個提交對像 ==> 儲存了樹對像的key 及提交評論。

下面請大家思考一個問題:

三分鐘帶你玩轉GIT底層原理與核心命令

三分鐘帶你玩轉GIT底層原理與核心命令

當我們在main資料夾下新增一個檔案並提交,會生成幾個物件,都有哪些物件會重新生成?首先提交一定會生成一個commit物件,新增的檔案物件,由於main樹物件的內容裡會引用新生成檔案的key等資訊,所以main物件也會重新生成,導致main樹物件的key改變,那麼引用了這個key的src樹物件也會改變,同理頂級樹物件也會改變。總共生成五個物件。現在這種專案回滾就不像單檔案回滾看起來那麼簡單了,想要回滾到指定版本時,會先和當前版本比較頂級樹物件,如果key改變了就會往下遍歷,查詢具體改變的檔案,如上面兩張圖,luban。txt和README。MF沒有改變所以不會回滾這兩個檔案,找到改變的檔案,替換內容就回滾完成了

GIT引用

其實像分支和tag就是git引用,當建立一個分支或者tag,就是在。git/refs/heads和tags資料夾下建立了一個檔案,裡面包含的是最近一次提交key,回滾操作就是把裡面的key換成回滾到的版本的提交物件的key

git 總共有三種類型的引用:

分支引用

遠端分支引用

標籤引用