搜尋
首頁電腦教學電腦知識Git 提交是差異、快照還是歷史記錄?

Git 提交是差異、快照還是歷史記錄?

Feb 19, 2024 am 11:39 AM
git提交快招

Git 提交是差异、快照还是历史记录?

#

理解Git提交實作方式對我來說很簡單,但理解他人對提交的看法卻有難度。因此,我在Mastodon上向他人提出了一些問題。

大家是怎麼看待 Git 提交的?

#我進行了 非常不科學的調查,詢問大家是怎麼看待 Git 提交的:是快照、差異,還是所有之前提交的清單? (當然,把它看作這三者都是合理的,但我很好奇人們的 主要

結果是:

  • 51% 差異
  • 42% 快照
  • 4% 所有先前的提交的歷史記錄
  • 3% “其他”

我很驚訝差異和快照兩個選項的比例如此接近。人們也提出了一些有趣但相互矛盾的觀點,例如
「在我看來,提交是一個差異,但我認為它實際上是以快照的形式實現的」 和
「在我看來,提交是一個快照,但我認為它實際上是以差異的形式實現的」。關於提交的實際實現方式,我們稍後再詳談。

在我們進一步討論之前:我們的說 「一個差異」 或 「一個快照」 都是什麼意思?

什麼是差異?

#我說的「差異」可能相當明顯:差異就是你在執行 git show COMMIT_ID 時所得到的。例如,這是一個 rbspy 專案中的拼字錯誤修復:

diff --git a/src/ui/summary.rs b/src/ui/summary.rs
index 5c4ff9c..3ce9b3b 100644
--- a/src/ui/summary.rs
+++ b/src/ui/summary.rs
@@ -160,7 +160,7 @@ mod tests {
";
let mut buf: Vec = Vec::new();
-stats.write(&mut buf).expect("Callgrind write failed");
+stats.write(&mut buf).expect("summary write failed");
let actual = String::from_utf8(buf).expect("summary output not utf8");
assert_eq!(actual, expected, "Unexpected summary output");
}

你可以在 GitHub 上看到它: https://github.com/rbspy/rbspy/commit/24ad81d2439f9e63dd91cc1126ca1bb5d3a4da5b

什麼是快照?

#我說的 「快照」 是指 「當你執行 git checkout COMMIT_ID 時得到的所有檔案」。

Git 通常將提交的檔案清單稱為 「樹」(如「目錄樹」),你可以在 GitHub 上看到上述提交的所有檔案:

https://github.com/rbspy/rbspy/tree/24ad81d2439f9e63dd91cc1126ca1bb5d3a4da5b(它是 /tree/ 而不是 /commit/

#「Git 是如何實現的」真的是正確的解釋方式嗎?

#我最常聽到的關於學習 Git 的建議大概是 「只要學會 Git 在內部是如何表示事物的,一切都會變得清晰明了」。我顯然非常喜歡這種觀點(如果你花了一些時間閱讀這個博客,你就會知道我 喜歡

但是作為一個學習 Git 的方法,它並沒有我希望的那麼成功!通常我會興奮地開始解釋“好的,所以Git
提交是一個快照,它有一個指向它的父提交的指針,然後一個分支是一個指向提交的指針,然後……”,但是我試圖幫助的人會告訴我,他們並沒有真正發現這個解釋有多有用,他們仍然不明白。所以我一直在考慮其他方案。

但是讓我們還是先談談內部實作吧。

Git 是如何在內部表示提交的 —— 快照

#在內部,Git 將提交表示為快照(它儲存每個檔案目前版本的 「樹」)。我在 在一個 Git 倉庫中,你的文件在哪裡? 中寫過這個,但下面是一個非常快速的內部格式概述。

這是一個提交的表示方式:

$ git cat-file -p 24ad81d2439f9e63dd91cc1126ca1bb5d3a4da5b
tree e197a79bef523842c91ee06fa19a51446975ec35
parent 26707359cdf0c2db66eb1216bf7ff00eac782f65
author Adam Jensen1672104452 -0500
committer Adam Jensen1672104890 -0500
Fix typo in expectation message

以及,當我們查看這個樹物件時,我們會看到這個提交中倉庫根目錄下每個檔案/子目錄的清單:

$ git cat-file -p e197a79bef523842c91ee06fa19a51446975ec35
040000 tree 2fcc102acd27df8f24ddc3867b6756ac554b33ef.cargo
040000 tree 7714769e97c483edb052ea14e7500735c04713eb.github
100644 blob ebb410eb8266a8d6fbde8a9ffaf5db54a5fc979a.gitignore
100644 blob fa1edfb73ce93054fe32d4eb35a5c4bee68c5bf5ARCHITECTURE.md
100644 blob 9c1883ee31f4fa8b6546a7226754cfc84ada5726CODE_OF_CONDUCT.md
100644 blob 9fac1017cb65883554f821914fac3fb713008a34CONTRIBUTORS.md
100644 blob b009175dbcbc186fb8066344c0e899c3104f43e5Cargo.lock
100644 blob 94b87cd2940697288e4f18530c5933f3110b405bCargo.toml

這意味著檢出一個 Git 提交總是很快的:對 Git 來說,檢出昨天的提交和檢出 100 萬個提交之前的提交一樣容易。 Git 永遠不需要重新應用 10000 個差異來確定當前狀態,因為提交根本就不是以差異的形式儲存的。

快照使用 packfile 進行壓縮

我剛剛提到了Git 提交是一個快照,但是,當有人說「在我看來,提交是一個快照,但我認為它在實現上是一個差異」
時,這其實也是正確的! Git
提交並不是以你可能習慣的差異的形式表示的(它們不是以與上一個提交的差異的形式存儲在磁碟上的),但基本的直覺是,如果你要對一個10,000
行的文件編輯500 次,那麼儲存500 份文件的效率會很低。

Git 有一個將檔案以差異的形式儲存的方法。這稱為 “packfile”,Git 會定期進行垃圾回收,將你的資料壓縮成 packfile 以節省磁碟空間。當你 git clone 一個倉庫時,Git 也會壓縮資料。

這裡,我沒有足夠的篇幅來完整地解釋 packfile 是如何運作的(Aditya Mukerjee 的 《解壓縮 Git packfile》是我最喜歡的解釋它們是如何運作的文章)。不過,我可以在這裡簡單總結一下我對 deltas 工作原理的理解,以及它們與 diff 的區別:

  • 物件儲存為 「原始檔案」 和一個 “變化量delta” 的引用
  • 變化量是一系列例如 “讀取第 0 到 100 字節,然後插入字節 ‘hello there’,然後讀取第 120 到 200 字節” 的指令。它從原始文件中拼湊出新的文字。所以沒有 “刪除” 的概念,只有複製和添加。
  • 我認為變化量的層次較少:我不知道如何檢查 Git 究竟要經過多少層變化量才能得到一個給定的對象,但我的印像是通常不會很多。可能少於 10 層?不過,我很想知道如何才能真正查出來。
  • 原始文件不一定來自上一個提交,它可以是任何東西。也許它甚至可以來自一個更晚的提交?我不確定。
  • 沒有一個 “正確的” 演算法來計算變化量,Git 只是有一些近似的啟發式演算法

當你查看差異時,實際上發生了一些奇怪的事情

#當我們執行 git show SOME_COMMIT 來查看某個提交的差異時,實際上發生的事情有點反直覺。我的理解是:

  • Git 會在 packfile 中尋找並套用變化量來重建該提交和其父提交的樹。
  • Git 會對兩個目錄樹(目前提交的目錄樹和父親提交的目錄樹)進行差異比較。通常這很快,因為幾乎所有的檔案都是完全一樣的,所以 git 只需比較相同檔案的雜湊值就可以了,幾乎所有時候都不用做什麼。
  • 最後 Git 會顯示差異
  • 所以,Git 會將變化量轉換為快照,然後計算差異。它感覺有點奇怪,因為它從一個類似差異的東西開始,最終得到另一個類似差異的東西,但是變化量和差異實際上是完全不同的,所以這是說得通的。

    也就是說,我認為 Git 將提交儲存為快照,而 packfile 只是實作細節,目的是節省磁碟空間並加快克隆速度。我其實從來沒必要知道 packfile 是如何運作的,但它確實能幫助我理解 Git 是如何在不佔用太多磁碟空間的情況下將提交快照化的。

    一個 “錯誤的” Git 理解:提交是差異

    #我認為一個相當常見的,對 Git 的 “錯誤” 的理解是:

    • 提交是以基於上一個提交的差異的形式儲存的(加上指向父提交的指標和作者和訊息)。
    • 要取得提交的目前狀態,Git 需要從頭開始重新套用所有先前的提交。

    這個理解當然是錯誤的(在現實中,提交是以快照的形式存儲的,差異是從這些快照計算出來的),但是對我來說它似乎非常有用而且有意義!在考慮合併提交時會有一點奇怪,但是或許我們可以說這只是基於合併提交的第一個父親提交的差異。

    我認為這個錯誤的理解有的時候非常有用,而且對於日常 Git 使用來說它似乎並沒有什麼問題。我真的很喜歡它將我們最常使用的東西(差異)作為最基本的元素——它對我來說非常直觀。

    我也一直在思考一些其他有用但 「錯誤」 的 Git 理解,例如:

    • 提交資訊可以被編輯(實際上不能,你只是複製了一個相同的提交然後給了它一個新的信息,舊的提交仍然存在)
    • 提交可以被移動到一個不同的基礎上(類似地,它們是被複製了)

    我認為有一系列非常有意義的、 “錯誤” 的對 Git 的理解,它們在很大程度上都受到 Git 用戶界面的支持,並且在大多數情況下都不會產生什麼問題。但是當你想要撤銷一個更改或出現問題時,它可能會變得混亂。

    將提交視為差異的一些優勢

    就算我知道在 Git 中提交是快照,我可能大部分時間也都將它們視為差異,因為:

    • 大多時候我都在關注我正在做的 更改 —— 如果我只是改變了一行程式碼,顯然我主要是在考慮那一行程式碼而不是整個程式碼庫的當前狀態
    • 點擊 GitHub 上的 Git 提交或使用 git show 時,你會看到差異,所以這只是我習慣看到的東西
    • 我經常使用變基,它是關於重新應用差異的

    將提交視為快照的一些優勢

    #但我有時也會將提交視為快照,因為:

    • Git 經常對檔案的移動感到困惑:有時我移動了一個檔案並編輯了它,Git 無法識別它是否被移動過,而是顯示為
      「刪除了 old.py,新增了 new.py」。這是因為 Git 只儲存快照,所以當它顯示 “移動 old.py -> new.py”
      時,只是猜測,因為 old.py 和 new.py 的內容相似。
    • 這種方式更容易理解 git checkout COMMIT_ID 在做什麼(重新應用 10000 個提交的想法讓我感到很有壓力)
    • 合併提交在我看來更像是快照,因為合併的提交實際上可以是任何東西(它只是一個新的快照!)。它幫助我理解為什麼在解決合併衝突時可以進行任意更改,以及為什麼在解決衝突時要小心。

    其他一些關於提交的理解

    #Mastodon 的一些回覆中也提到了:

    • 有關提交的 「額外的」 帶外信息,例如電子郵件、GitHub 拉取請求或你和同事的對話
    • 將「差異」視為一個「之前的狀態 之後的狀態」
    • 以及,當然,許多人根據情況的不同以不同的方式看待提交

    人們在談論提交時使用的其他一些單字可能不那麼含糊:

    • 「修訂」(似乎更像是快照)
    • 「補丁」(看起來更像是差異)

    就到這裡吧!

    #我很難了解人們對 Git 有哪些不同的理解。尤其棘手的是,儘管「錯誤」 的理解往往非常有用,但人們卻非常熱衷於警惕「錯誤」
    的心智模式,所以人們不願意分享他們「錯誤」 的想法,生怕有什麼Git 解釋者會站出來向他們解釋為什麼他們是錯的。 (這些 Git
    解釋者通常是出於善意的,但是無論如何它都會產生一種負面影響)

    但是我學到了很多!我仍然不完全清楚該如何談論提交,但是我們最終會弄清楚的。

    感謝 Marco Rogers、Marie Flanagan 以及 Mastodon 上的所有人和我討論 Git 提交。

    以上是Git 提交是差異、快照還是歷史記錄?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    陳述
    本文轉載於:每日运维。如有侵權,請聯絡admin@php.cn刪除
    Zlib1.dll缺少或找不到錯誤?用簡單的動作修復 -  MinitoolZlib1.dll缺少或找不到錯誤?用簡單的動作修復 - MinitoolApr 16, 2025 am 12:52 AM

    什麼是zlib1.dll?有些人遇到“ zlib1.dll丟失”錯誤或zlib1.dll試圖打開包含zlib1.dll的應用程序時找不到錯誤。為了解決這些相關錯誤,PHP.CN網站上的這篇文章可以為您提供一些我

    Autofill在Excel中不起作用嗎?這是修復程序! -  MinitoolAutofill在Excel中不起作用嗎?這是修復程序! - MinitoolApr 16, 2025 am 12:51 AM

    你們中有些人可能會發現自動填充沒有在Excel中工作。您能提出任何解決方案嗎?如果沒有,那麼您就會到達正確的位置。 PHP.CN網站上的這篇文章將為您提供6種方法來解決Excel Autofill無法正常工作的方法。

    Windows 7 Starter Edition:這是什麼?如何下載? -  MinitoolWindows 7 Starter Edition:這是什麼?如何下載? - MinitoolApr 16, 2025 am 12:50 AM

    什麼是Windows 7 Starter版本? Windows 7 Starter版的局限性是什麼?如何獲得Windows 7首發版ISO?來自PHP.CN的這篇文章為您提供了有關Windows 7 Starter Edition的詳細信息。

    使用此頂部指南在Windows中以其他用戶的方式運行應用程序使用此頂部指南在Windows中以其他用戶的方式運行應用程序Apr 16, 2025 am 12:49 AM

    運行應用程序時,您是否通過登錄目前然後登錄另一個應用程序來更改帳戶感到困擾? PHP.CN收集了一些有效的方法來幫助您在Windows 10和Windows 11中作為其他用戶運行應用程序。

    修復:Dropbox下載您的文件有錯誤修復:Dropbox下載您的文件有錯誤Apr 16, 2025 am 12:48 AM

    您是否患有“ Dropbox下載文件的錯誤下載您的文件”錯誤?現在閱讀PHP.CN發表的這篇文章,以獲取有關此問題的一些有用解決方案。

    修復所選文件的5種方法未在文件資源管理器中突出顯示-Minitool修復所選文件的5種方法未在文件資源管理器中突出顯示-MinitoolApr 16, 2025 am 12:47 AM

    您是否對“所選文件在文件資源管理器中未突出顯示”的問題感到困擾?您知道如何解決嗎?如果沒有,您可以在PHP.CN上閱讀此帖子,以獲取幾個可行解決方案,以使所選文件在文件資源管理器中可見。

    修復任務欄中缺少語言欄 - 經過驗證的指南修復任務欄中缺少語言欄 - 經過驗證的指南Apr 16, 2025 am 12:46 AM

    如果您使用多語言,語言欄是必不可少的。您可以通過從任務欄調整設置來更改輸入語言。但是,當您打開計算機時,語言條可能有一天會消失。如何修復語言欄丟失

    如何將外部驅動器連接到Android手機或平板電腦? -  Minitool如何將外部驅動器連接到Android手機或平板電腦? - MinitoolApr 16, 2025 am 12:45 AM

    是否想使用外部驅動器來擴展手機的存儲空間?可以這樣做。此php.cn帖子向您展示瞭如何將外部驅動器連接到手機的指南。此外,如果您需要從外部驅動器中恢復數據,則可以嘗試PHP

    See all articles

    熱AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智慧驅動的應用程序,用於創建逼真的裸體照片

    AI Clothes Remover

    AI Clothes Remover

    用於從照片中去除衣服的線上人工智慧工具。

    Undress AI Tool

    Undress AI Tool

    免費脫衣圖片

    Clothoff.io

    Clothoff.io

    AI脫衣器

    AI Hentai Generator

    AI Hentai Generator

    免費產生 AI 無盡。

    熱門文章

    R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
    4 週前By尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.最佳圖形設置
    4 週前By尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.如果您聽不到任何人,如何修復音頻
    1 個月前By尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.聊天命令以及如何使用它們
    1 個月前By尊渡假赌尊渡假赌尊渡假赌

    熱工具

    ZendStudio 13.5.1 Mac

    ZendStudio 13.5.1 Mac

    強大的PHP整合開發環境

    PhpStorm Mac 版本

    PhpStorm Mac 版本

    最新(2018.2.1 )專業的PHP整合開發工具

    SecLists

    SecLists

    SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

    DVWA

    DVWA

    Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

    VSCode Windows 64位元 下載

    VSCode Windows 64位元 下載

    微軟推出的免費、功能強大的一款IDE編輯器