Git是怎樣控制版本的

2021-07-28 15:48:59 字數 4718 閱讀 9965

參考:

git暫存區的理解

git diff命令詳解

一些基本的git概念

git 內部原理

《git權威指南》

1.邏輯

git的控制原理邏輯上可以看作三個部分,工作區、暫存區和分支。

git add將工作區檔案儲存到暫存區(標記為tracked)

git commit將暫存區檔案儲存到分支

git push就是將乙個倉庫的分支推送到另乙個倉庫的分支

git diff 比較工作區tracked檔案和暫存區之間的差異

git diff --cached比較暫存區檔案和head的差異

git diff head比較工作區tracked檔案和head的差異

git diff test比較工作區tracked檔案和指定分支的差異

git status比較工作區所有檔案和暫存區之間的差異

2.物理

物理上.git檔案就是整個版本庫,包括了暫存區(/index)、引用命名空間(/refs/)(包含了分支(/refs/head))、head(/head)、物件庫(/objects/)。

暫存區中儲存了乙個目錄樹,樹中的檔案指向物件庫中乙個bolb物件,每個提交對應的目錄樹就是當時暫存區中的目錄樹。

命名空間中的分支指向該分支的最新提交,git reset可以改變指向的提交。

head可以理解為「頭指標」,是當前工作區的基礎版本,當提交時,head指向的提交將作為新提交的父提交。

git放在物件庫里的物件有4種型別:

①塊(blob):檔案的每乙個版本表示乙個blob。

git追蹤的是內容而不是檔案,git並不追蹤那些與檔案次相關的檔名或者是目錄名。如果兩個檔案的內容完全一樣,git在物件庫里只儲存乙份blob形式的內容副本,並且該檔案具有唯一的sha1值。檔案內容改變,則git會計算乙個新的sha1值,識別出它現在是乙個不同的blob物件並把這個blob物件新增到物件庫里。

②目錄樹(tree):乙個目錄樹物件表示一層目錄資訊,git通過目錄樹物件來追蹤檔案的路徑名。

可以自己建立 tree 。通常 git 根據你的暫存區域或 index 來建立並寫入乙個 tree 。因此要建立乙個 tree 物件的話首先要通過將一些檔案暫存從而建立乙個 index 。

③提交(commit):乙個提交(commit)物件儲存版本庫中每一次變化的元資料。

④標籤:乙個標籤物件分配乙個任意的且人類可讀的名字給乙個特定物件。

git cat-file -t 可以檢視某個物件的型別,id可以只寫開頭幾位。

3.命令

(1)git reset

git reset [-q] […]…

git reset [--soft | --mixed | --hard |--merge | --keep] [-q]

都是可選項,可以使用引用或提交id,如果省略,則相當於使用了head的指向作為提交id

第一種在命令中包含路徑,為了避免路徑和引用(或提交id)同名而發生衝突,可以在前用兩個連續的減號作為分隔,這種用法不會重置引用,更不會改變工作區,而是用指定提交狀態()下的檔案()替換掉暫存區中的檔案

git reset head 相當於取消之前執行的gitadd 命令時改變的暫存區

第二種則會重置引用

--hard,如git reset --hard會執行上圖的全部動作1、2、3

1.替換引用的指向,引用指向新的提交id

2.替換暫存區,替換後暫存區的內容和引用指向的目錄樹一致

3.替換工作區,替換後工作區的內容和暫存區一致也和head指向的目錄樹內容相同

--soft,如git reset --soft執行操作1,只更改引用的指向,不改變暫存區和工作區

--mixed或不用引數,如git reset 會執行操作1、2,只更改引用的指向及重置暫存區,不改變工作區

git reset或git reset head僅用head指向的目錄樹重置暫存區,工作區不會收到影響,相當於之前用git add命令更新到暫存區的內容撤出暫存區,引用也沒改變,因為重置到head相當於沒有重置

git reset --filename或git resethead filename僅將檔案filename的改動撤出暫存區,暫存區中其中檔案不改變,相當於git add filename的反向操作

git reset --soft head^工作區和暫存區不改變,但是引用向前回退一次,當對最新的提交說明或提交的更改不滿意時,撤銷最新的提交以便重新提交

git commit --amend用於對最新的提交進行重新提交以修補錯誤的提交說明或錯誤的提交檔案,相當於執行了git reset --soft head^和git commit -s -f .git/commit_editmsg

git reset head^或git reset--mixed head^工作區不改變,但是暫存區會回退到上一次提交之前,引用也會回退一次

git reset --hard head^徹底撤銷最近的提交,引用回退到前一次,而且工作區和暫存區都會回退到上一次提交的狀態,自上一次以來的提交全部丟失。

(2)git checkout

git checkout [-g] [--]…

在命令中包含路徑,為了避免路徑和引用(或提交id)同名而發生衝突,可以在前面用兩個連續的減號作為分隔;是可選項,如果省略則相當於從暫存區(index)進行檢出,重置的預設值是head,而檢出的預設值是暫存區,所以重置一般用於重置暫存區(除非使用--hard,否則不重置工作區),而檢出命令主要覆蓋工作區(如果不省略,也會替換暫存區中相應的檔案)。這種用法不會改變head頭指標,主要用於指定版本的檔案覆蓋工作區中對應的檔案,如果省略則會用暫存區的檔案覆蓋工作區的檔案,否則用指定提交中的檔案覆蓋暫存區和工作區中對應的檔案。

git checkout [

]不使用路徑,會改變head頭指標,之所以後面的引數寫為

是因為只有head切換到乙個分支才可以對提交進行跟蹤,否則仍然會進入「分離頭指標」的狀態,在該狀態下的提交不能被引用關聯到,可能丟失。主要作用是切換到分支,如果省略

則相當於對工作區進行狀態檢查。

gitcheckout [-m] [[-b] --orphan ] [start_point]

用於建立和切換到新的分支,新的分支從指向的提交開始建立。新分支和master分支一樣,都是在refs/heads命名空間下的引用。

git checkout branch檢出branch分支,要完成三個步驟,更新head以指向branch分支,以及用branch指向的樹更新暫存區和工作區

git checkout或git checkout head彙總顯示工作區、暫存區和head的差異

git checkout -- filename用暫存區中的filename檔案來覆蓋工作區中的filename檔案,相當於取消自上次執行gitadd filename以來的本地修改

git check branch --filename維持head的指向不變,用branch所指向的提交中的filename替換暫存區和工作區中相應的檔案(會將暫存區和工作區中的filename檔案直接覆蓋)

git checkout -- .或git checkout.取消所有本地的修改(相對於暫存區),相當於用暫存區的所有檔案直接覆蓋本地檔案,並且不會再次確認。

(3)更多命令

git branch -v 檢視當前的分支

git branch -a檢視所有分支(包括遠端)

git status -s -b顯示工作區狀態-s顯示精簡輸出,-b同時顯示當前工作分支的名稱

git rev-parse

顯示應用對應的提交id

git log --graph --online檢視提交日誌,通過對父提交的關聯實現對提交歷史的追溯

git log -l head檢視head的指向

git log -l master檢視master的指向

git log -l refs/heads/master檢視refs/heads/master的指向

git stash儲存當前工作進度,工作區尚未提交的改動(包括暫存區的改動)全都不見了

git clean -fd清除當前工作區中沒有加入版本庫的檔案和目錄(未跟蹤的)

git rm --cached a.txt從暫存區刪除檔案,工作區不做改變

4.遠端倉庫

git init

建立工作區(在當前路徑下新增.git資料夾)

(手動建立readme.md檔案)

git addreadme.md

將readme.md檔案新增到暫存區

git commit -m "first commit"

將暫存區中修改的提交到head指向的master,message為"first commit"

git remote addorigin

新增遠端倉庫,名字為origin,位址為...

git push -u orgin master

指定master分支提交到origin倉庫的對應分支(origin/master),同時指定origin為預設倉庫,以後就可以不加任何引數

(在github上手動建立d.txt並commit到dev分支)

fetch可以用status比較檔案差異(fetch實際將遠端檔案版本下到本機,不做fetch看不到差異)

merge將新檔案合併到本地

(pull直接將檔案合併到本地)

Git的使用和GitHub控制版本

首先,介紹下git,git是由linus開發的分布式版本控制器,用於分布式團隊合作開發版本控制。倉庫建立流程 1.建立遠端倉庫,如github,建立賬戶,建立倉庫 2.建立本地ssh金鑰,ssh keygen t rsa c youremail example.com 3.建立github倉庫使用者...

C 批量處理檔案(SVN版本控制版)

最近公司有個批量壓縮的任務交給我。對於io的是操作,我不是很擅長,自己比較shui 不管怎麼樣,經過的不懈的努力 所以打算分享一下。任務要求 給你乙個資料夾,把該資料夾下的所有.png檔案進行壓縮,然後儲存到相對資料夾的映象對應子資料夾目錄下,解決方案 網上有很多壓縮的方式,也很繁雜,我也嘗試過很多...

git版本控制

1.git 是乙個開源的分布式版本控制系統,可以有效 高速的處理從很小到非常大的專案版本 管理。2.git配置管理 一般,有乙個 集中庫,包含4個分支 qa才能merge production 發布生產,出現生產問題,轉hotfix 研發經理 hotfix 解決緊急生產問題,測試後轉producti...