【Git教程】(四)版本庫 —— 存儲系統,存儲目錄,提交對象及其命名、移動與復制~

Git教程 · 版本庫

  • 1?? 一種簡單而高效的存儲系統
  • 2?? 存儲目錄:Blob 與 Tree
  • 3?? 相同數據只存儲一次
  • 4?? 壓縮相似內容
  • 5?? 不同文件的散列值相同
  • 6?? 提交對象
  • 7?? 提交歷史中的對象重用
  • 8?? 重命名、移動與復制
  • 🌾 總結

事實上,我們即使不了解版本庫的具體工作方式,也一樣可以將 Git 用得風生水起。但 如果我們了解了 Git 存儲和組織數據的方式,就能對工作流有一個更好的理解。當然,如果你真的很討厭談理論,也可以選擇跳過本章的正文,只選擇性地讀一下部分內容即可。

Git 主要由兩個層面構成。其頂層結構就是我們所用的命令,例如 logresetcommit 等。這些命令使用起來很方便,并提供了許多可調用的選項。Git 的開發者們稱它們令為瓷質命令 (porcelain command)。
而對于其底層結構,我們則稱之為管道 (plumbing) 。 這里主要是一組帶有少量選項的簡 單命令,瓷質命令就是以此為基礎被構建出來的。管道命令很少被直接用到。本章將為你提供一些了解該系統管道層結構的機會。

在這里插入圖片描述


1?? 一種簡單而高效的存儲系統

Git 的核心是一個對象數據庫。該數據庫可用來存儲文本或二進制數據,例如對于某文件 的內容。我們可通過帶 -w 選項 (w 代表寫入)的 hash-object 命令將其作為一條記錄插入到該對象數據庫中。

> git hash-object -w hello.txt
28cf67640e502fe8e879a863bdlbbcd4366689e8

每當我們存儲了這樣一個對象, Git 就會返回一個40個字符的代碼,這是被存儲對象的 鍵值。請記住它,我們日后需要用該鍵值配合帶 -p 選項 (p代表打印)的cat-file 命令來訪問這個對象。

> git cat-file -p 28cf67640e
Hello World!

對象數據庫是一個非常高效的實現。即使對于一個有著非常長提交歷史的大型項目(例如Linux內核,這是一個擁有 200000次提交和近兩百萬個對象的項目)來說,訪問其版本庫 中對象的操作也幾乎可在瞬間完成。Git 非常適合用于那些擁有大量小型源文件的項目。其性能瓶頸只有在總數據量非常巨大的時候才能顯現出來。對于那些想要管理大量二進制文件的人來說,Git 版本庫顯然是不二的選擇。


2?? 存儲目錄:Blob 與 Tree

在文件和目錄的存儲上,Git 使用了一種包含兩種節點類型的簡單樹結構。其文件內容將 保持不變,并以blob 對象的形式按字節被存儲對象數據庫中。而目錄則將用tree 對象來表示, 它們看起來應該像如圖所示。

在這里插入圖片描述

> git cat-file -p 2790ef78
100644 blob 507d3a30ae9ed53bcf953744c5f5c9391a263356 README
040000 tree 91c7822ab43800b0e3c13049519587df4fd74591 src

正如你將如上看到的, tree 對象中包含了文件和子目錄。其中的每個條目都被分配了 相應的訪問權限(例如上面的100644)、類型(即 blob 還是 tree), 以及由該文件內容、該文
件或目錄名稱生成的散列值。


3?? 相同數據只存儲一次

為了節省內存空間, Git 對于相同數據將只存儲 一 次。例如在下面這個例子中,foo.txtcopy-of-foo.txt 將返回相同的散列值,因為它們的文件內容是相同的。

> git hash-object -w foo.txt
a42a0aba404c21le8fdf33d4edde67bb474368a7
> git hash-object -w copy-of-foo.txt
a42a0aba404c21le8fdf33d4edde67bb474368a7

通過這種方法, Git 不僅能夠節省內存,同時也能在性能上得到提升。許多Git 操作之所以快,就是因為它們的算法只比較相關的散列值,而不需要查看其實際數據。


4?? 壓縮相似內容

Git 不僅可以對相同的文件內容進行合并,每當程序員們所創建的新文件在內容上與前人 只有區區幾行的區別時,Git 可以采用增量方法來存儲這些文件,在這種情況下,包文件中將只存儲原始版本后來被改變的那一部分。

要想做到這一點,我們就要在想節省空間時使用 gc 命令。這樣一來,Git 就會刪除所有多余的、不再接受任何分支頭訪問的提交,并將剩下的提交存儲到包文件中。對于那些源代碼占絕大多數的項目來說,這就等于實現了某種令人驚嘆的高壓縮處理。通常情況下,當前版本未壓縮的工作區內容大小往往要比包含多年項目歷史并打包的Git 版本庫還要大得多。


5?? 不同文件的散列值相同

當不同文件的散列值相同時,情況會很糟糕,因為 Git 是通過散列值來識別內容的。因此, 一 旦內容各不相同的文件出現散列值相同的情況,Git 就無法提供正確的數據了,我們稱這種情況為敬列沖突(hash collision)。

好消息是,敬列沖突是一種非常罕見的事件。其原因在于,散列值的可能取值至少有2160 種。而即使是Linux 內核項目在運作5年之后,版本庫中也就“僅有”大約221個對象。

當然從理論上而言,SHA1 敬列算法是有缺陷的,你可以在 SHA1 算法中找到251 中會 引起敬列沖突的操作。然而,格拉茨科技大學 (Graz University of Technology) 的一個研究項目曾從2007年嘗試到2009年,目的是想找出一個(!) 這樣的散列沖突,結果以失敗告終。

總而言之,在當今版本控制所在的環境下,我們可以認為它是安全的。

6?? 提交對象

我們所做的歷次提交也被存儲在對象數據庫中,它們的格式很簡單。

> git cat-file -p 64b98df0
tree 319c67d41a0b3f7464550b41db4bb1584939ad2a
parent 6c7f1ba0828a5b595026e08d2476808105a6b815
author Bjorn Stachmann <bs@test123.de>1295906997  +0100
committer Bjorn Stachmann <bs@test123.de>1295906997  +0100
Section on trees & blobs.

除了作者、提交者、日期以及注釋這些元數據外,每個提交對象還在對象數據庫中放入 了一些其他對象的散列值。例如: tree 對象負責描述該提交的內容。它還包含了該項目的根目錄信息,并且與上文提到的一樣,它也將以tree 和 blob 對象的方式呈現。而 parent 對象則指的是它的上一次提交。


7?? 提交歷史中的對象重用

除了最初的那次提交外,版本庫中的每個提交對象上面都至少會存在一個前提交對象(即 父對象)。通常來說, 一次提交往往只涉及項目中少數文件的修改,其他大部分文件和目錄不會發生變化。所以,我們會希望 Git 盡可能多地重用前次提交中的相關對象。

下面我們來看一個具體的例子(見下圖)。某一提交(即自頂向下第二排中第二個被 實線箭頭所指向的那個標題為 “commit” 的方框)中包含了一個README 文件,以及一個 用于包含其他文件的 src 目錄。然后,如果在新建的提交(即圖中第一行用虛線箭頭所指向 的那個標題為 “commit” 的方框)中,被修改的只有 README 文件, Git 就會專門為該 README 文件創建一個新的blob對象。而對于src 目錄,則繼續沿用現有的tree對象與相應的 blob 對象。

在這里插入圖片描述


8?? 重命名、移動與復制

在許多版本控制系統中,我們都可以對文件的重命名及其修改時間的歷史進行跟蹤監視。
它們大多數通常是通過某個特定的文件移動或重命名命令來實現的。例如在 Subversion 中,我們可以用 svn move 來移動文件。但是如果用戶想要將文件在圖形界面中拖放到某一新的位置的話, Subversion 就無能為力了。對于這種情況, Subversion 不會認為這是個移動操作,而會將其記錄為先刪除,再另行新建該文件的操作過程。

對此,Git 采用了不同的方法:它沒有選擇去存儲與文件移動操作相關的信息,而是采用 了重命名檢測算法。在該算法中,如果一個文件在某一次提交中消失了,它依然會存在于其 前次提交中。而如果某個擁有相同名字或相似內容的文件出現在了另一個位置, Git 就會自動檢測到。如果是這種情況, Git 就會假定該文件被移動過了。下面我們以下圖中的情況為例 來演示一下。你可以看到:第二次提交中已經沒有了 foo.txt 文件,它可能被移動了。隨后,Git 又自動檢測到新增文件中有一個與之內容相似的文件,位于src/foo-moved.txt, 這一過程就成為了重命名操作。

在這里插入圖片描述Git 會自行顯示出被重命名或移動的文件。

  1. 先獲取一份摘要
    我們可以用 log 命令的-M 選項 ( 即“move”) 來激活重命名的檢測算法。如果想要格式化輸出的信息,我們可以對其使用–summary 選項來顯示文件修改的相關信息。但這段輸 出很長也是個問題。如果我們想要簡短一些,也可以用grep命令來對輸出進行篩選。另外,百分比顯示了源文件和目標文件的相似度。

    > git log --summary -M90% | grep -e "^ rename"
    rename foo.txt => foo-renamed.txt(90%)
    rename src/{before =>after}/bar.txt(100%)
    
  2. 跟蹤被移動文件的歷史
    我們可以用 log 命令的–follow 選項來連續取出文件被重命名之后的歷史記錄(當然,該做法僅適用于單文件操作)。如果不使用該選項,日志就會在該文件被重命名的那一刻停止。

    > git log --follow  foo-renamed.txt
    

我們還可以透過-C 選項來跟蹤被復制的數據。

> git log --summary -C90% | grep -e "^copy"

如果有必要的話,我們也可以用 --find-copies-harder選項來使Git 做一個更長的計算操作。只要該選項被激活,Git 就會去檢查相關提交中的所有文件,并不僅僅是那些已更改的文件。

我們也可以將重命名檢測配制成 Git 的默認選項。這樣一來,我們就無需在每次使用 log
命令時為其指定-M--follow 選項了。

> git config diff.renames true

我們可以按照以下步驟找出誰最后修改了那幾行代碼,以及修改的時間。

  1. 逐行打印源頭信息
    當我們將某些較大的代碼塊復制或移動到其他文件中時,Git 甚至可以確定其中某幾行 代碼的來源。而且, blame 命令還可以顯示出最后一次修改這幾行代碼的人及其修改時間。

    > git blame -M -C -C -C copied-together.txt 
    f5fdbad0 foo.txt (Rene  2010-11-1418:30:42  +0100  1)One
    a5b80903 bar.txt (Bjorn  2011-01-3121:32:49 +0100  2)Two or
    f5fdbad0 foo.txt (Rene  2010-11-1418:30:42  +0100  3)Three
    

其中的 -M 選項(M 代表“move”) 暗示的是文件的復制和移動操作。 -C 選項也可用于 檢測相同提交中的文件副本。但我們還可以用多個-C 選項來搜索該文件在更多提交中的副本。對于大型的版本庫來說,這種操作有時候會需要較長的時間。

🌾 總結

  • 對象數據庫:所有提交中的文件、目錄以及相關的元數據都將被存儲在該數據庫中。
  • SHA1 散列值:我們可以通過一個SHA1 散列值從對象數據庫中撿取相關對象。SHA1 散列值是一種針對文件內容的加密校驗值。
  • 相同數據只存儲一次:內容相同的對象擁有相同的 SHA1 散列值,并且只存儲一次。
  • 相似的數據會被壓縮:對于內容相似的數據, Git 會針對其被修改的部分采取增量存儲的方法。
  • Blob對象:文件的內容將會被存儲在相應的blob對象中。
  • Tree 對象:目錄會被存儲在相應的 tree對象中。 一個 tree 對象中通常會包含一份文件 名列表,包含這些文件名和儲存在blob 或 tree 對象中內容的 SHA1 散列值。
  • 提交圖:我們的提交對象會沿著各自的 tree 和 blob對象,形成一個提交圖。
  • 重命名檢測:文件的重命名和移動操作在提交之前無需報備。Git 可以自動根據文件 內容的相似度來識別操作。例如:git log-follow 命令。
  • 廬山真面目:我們可以通過blame 命令來確定某幾行代碼的來源,即使這些代碼們已 被移動或復制到了別處。


? 溫習回顧上一篇(點擊跳轉)
《【Git教程】(三)提交詳解 —— add、commit、status、stach命令的說明,提交散列值與歷史,多次提交及忽略 ~》

? 繼續閱讀下一篇(點擊跳轉)
《【Git教程】(五)分支 —— 并行式開發,分支相關操作(創建、切換、刪除)~》

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/714564.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/714564.shtml
英文地址,請注明出處:http://en.pswp.cn/news/714564.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

keil MDK安裝armcc V5編譯器

不知道從什么時候開始&#xff0c;Keil MDK默認不支持V5的編譯器了&#xff0c;里面默認只有V6的編譯器&#xff0c;設置界面跟V5有很大的差異不太熟悉。最可怕的是&#xff0c;之前使用V5編譯的工程&#xff0c;換成V6編譯器后居然報錯...雖然修改一下應該也可以正常編譯&…

神經網絡基礎知識:LeNet的搭建-訓練-預測

1.參考視頻&#xff1a; 2.1 pytorch官方demo(Lenet)_嗶哩嗶哩_bilibili 2.總結&#xff1a; &#xff08;1&#xff09;LeNet網絡就是 我最開始用來預測mnist數據集的那個網絡&#xff0c;簡單的2個conv2個maxpool3個linear層 &#xff08;2&#xff09;up主整理的train.py…

SQL面試題(2)

第一題 創建trade_orders表: create table `trade_orders`( `trade_id` varchar(255) NULL DEFAULT NULL, `uers_id` varchar(255), `trade_fee` int(20), `product_id` varchar(255), `time` varchar(255) )ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_…

web自動化筆記九:驗證碼的處理方式

一、驗證碼常用的處理方式 ①、說明&#xff1a;Selenium中并沒有對驗證碼處理的方法&#xff0c;在這里我們介紹一下針對驗證碼的幾種常用處理方式 ②、方式&#xff1a; 1&#xff09;、去掉驗證碼&#xff08;測試環境下采用&#xff09; …

RDD算子介紹

1. RDD算子 RDD算子也叫RDD方法&#xff0c;主要分為兩大類&#xff1a;轉換和行動。轉換&#xff0c;即一個RDD轉換為另一個RDD&#xff0c;是功能的轉換與補充&#xff0c;比如map&#xff0c;flatMap。行動&#xff0c;則是觸發任務的執行&#xff0c;比如collect。所謂算子…

LeetCode 1551.是數組中所有元素相等的最小操作數

存在一個長度為 n 的數組 arr &#xff0c;其中 arr[i] (2 * i) 1 &#xff08; 0 < i < n &#xff09;。 一次操作中&#xff0c;你可以選出兩個下標&#xff0c;記作 x 和 y &#xff08; 0 < x, y < n &#xff09;并使 arr[x] 減去 1 、arr[y] 加上 1 &…

Mac專用投屏工具AirServer 7.27 for Mac中文版2024最新圖文教程

Mac專用投屏工具AirServer 7.27 for Mac中文版是一款適用于Mac的投屏工具&#xff0c;可以將Mac屏幕快速投影到其他設備上&#xff0c;如電視、投影儀、平板等。 Mac專用投屏工具AirServer 7.27 for Mac中文版具有優秀的兼容性&#xff0c;可以與各種設備配合使用。無論是iPhon…

基于springboot+vue的在線考試系統(源碼+論文)

文章目錄 目錄 文章目錄 前言 一、功能設計 二、功能頁面 三、論文 前言 現在我國關于在線考試系統的發展以及專注于對無紙化考試的完善程度普遍不高&#xff0c;關于對考試的模式還大部分還停留在紙介質使用的基礎上&#xff0c;這種教學模式已不能解決現在的時代所產生的考試…

【MySQL】數據庫的操作

【MySQL】數據庫的操作 目錄 【MySQL】數據庫的操作創建數據庫數據庫的編碼集和校驗集查看系統默認字符集以及校驗規則查看數據庫支持的字符集查看數據庫支持的字符集校驗規則校驗規則對數據庫的影響數據庫的刪除 數據庫的備份和恢復備份還原不備份整個數據庫&#xff0c;而是備…

YOLOv9改進|增加SPD-Conv無卷積步長或池化:用于低分辨率圖像和小物體的新 CNN 模塊

專欄介紹&#xff1a;YOLOv9改進系列 | 包含深度學習最新創新&#xff0c;主力高效漲點&#xff01;&#xff01;&#xff01; 一、文章摘要 卷積神經網絡(CNNs)在計算即使覺任務中如圖像分類和目標檢測等取得了顯著的成功。然而&#xff0c;當圖像分辨率較低或物體較小時&…

【LeetCode刷題】146. LRU 緩存

請你設計并實現一個滿足 LRU (最近最少使用) 緩存 約束的數據結構。 實現 LRUCache 類&#xff1a; LRUCache(int capacity) 以 正整數 作為容量 capacity 初始化 LRU 緩存int get(int key) 如果關鍵字 key 存在于緩存中&#xff0c;則返回關鍵字的值&#xff0c;否則返回 -…

全量知識系統問題及SmartChat給出的答復 之9 三套工具之4語法解析器 之2

Q23. 一個語言的語法簡約規則 這些規則顯示show 在一個給定單詞&#xff08;a given word&#xff09;的右邊或左邊可能出現的單詞的類別。句型的多樣性variety不是復雜文法&#xff08;a complex grammar&#xff09;的結果&#xff0c;而是簡單語法&#xff08;a simple gra…

【InternLM 實戰營筆記】浦語·靈筆的圖文理解及創作部署、 Lagent 工具調用 Demo

浦語靈筆的圖文理解及創作部署 浦語靈筆是基于書生浦語大語言模型研發的視覺-語言大模型&#xff0c;提供出色的圖文理解和創作能力&#xff0c;結合了視覺和語言的先進技術&#xff0c;能夠實現圖像到文本、文本到圖像的雙向轉換。使用浦語靈筆大模型可以輕松的創作一篇圖文推…

進程間的通信 -- 共享內存

一 共享內存的概念 1. 1 共享內存的原理 之前我們學過管道通信&#xff0c;分為匿名管道和命名管道&#xff0c;匿名管道通過父子進程的屬性繼承原理來完成父子進程看到同一份資源的目的&#xff0c;而命名管道則是通過路徑與文件名來唯一標識管道文件&#xff0c;來讓不同的進…

學習Android的第二十一天

目錄 Android ProgressDialog (進度條對話框) 例子 Android DatePickerDialog 日期選擇對話框 例子 Android TimePickerDialog 時間選擇對話框 Android PopupWindow 懸浮框 構造函數 方法 例子 官方文檔 Android OptionMenu 選項菜單 例子 官方文檔 Android Progr…

Java實戰:Spring Boot中各類參數校驗機制

引言 在開發Web應用程序時&#xff0c;對客戶端傳入的參數進行有效校驗是保證系統安全性和穩定性的重要環節。Spring Boot作為一個現代化的Java開發框架&#xff0c;提供了多種參數校驗的方法和工具&#xff0c;以滿足不同場景下的需求。本文將深入探討Spring Boot中實現各種參…

typescript 的常用方式

文章目錄 前言一、綁定props 默認值的方式&#xff1a;withDefaults1.vue2 的props設置默認值2.vue3 的props設置默認值(1) 不設置默認值的寫法(2) 設置默認值的寫法&#xff08;分離模式&#xff09;(3) 設置默認值的寫法&#xff08;組合模式&#xff09; 二、定義一個二維數…

Matlab在同一張圖中如何加入多個圖例

根據代碼最終畫出的圖片如下&#xff1a; 其實原理很簡單&#xff0c;就是在一張figure中畫多個坐標軸&#xff0c;每個坐標軸都有對應的圖例&#xff0c;之后再將多余坐標軸隱藏&#xff0c;只保留一個即可。 代碼如下&#xff1a; clear all; close all;dd_linewidth 1;a …

maven archetype 項目原型

拓展閱讀 maven 包管理平臺-01-maven 入門介紹 Maven、Gradle、Ant、Ivy、Bazel 和 SBT 的詳細對比表格 maven 包管理平臺-02-windows 安裝配置 mac 安裝配置 maven 包管理平臺-03-maven project maven 項目的創建入門 maven 包管理平臺-04-maven archetype 項目原型 ma…

Spring學習筆記(六)利用Spring的jdbc實現學生管理系統的用戶登錄功能

一、案例分析 本案例要求學生在控制臺輸入用戶名密碼&#xff0c;如果用戶賬號密碼正確則顯示用戶所屬班級&#xff0c;如果登錄失敗則顯示登錄失敗。 &#xff08;1&#xff09;為了存儲學生信息&#xff0c;需要創建一個數據庫。 &#xff08;2&#xff09;為了程序連接數…