簡體   English   中英

了解git reset對索引的影響

[英]understanding git reset effect on index

在閱讀有關git reset的文檔/教程時,我遇到了一個小沖突:例如,對於git reset --mixed ,文檔說:

重置的下一步是使用HEAD現在指向的快照快照的內容更新Index

引起沖突的原因是我期望清除索引而不是更新索引 是否使用HEAD現在指向的快照清除或更新了索引?

TL; DR

索引總是更新的。 索引保存您打算進行的下一次提交 ,因此它永遠不會為空。 (什么,從來沒有?嗯,幾乎從來沒有:它在您剛剛創建的存儲庫中為空,沒有文件,並且如果您現在運行git commit ,則不會提交任何內容 。如果您對所有內容進行 git rm也為空。)

您在這里的困惑幾乎可以肯定與PetSerAl的評論有關 Git的新手經常被告知或顯示,或者至少導致他們相信commit和/或Git的索引包含更改 ,但這是錯誤的! 一旦擺脫了這種錯誤的信念,Git的一些奧秘就變得更加有意義。 (並不是所有的Git都對任何人都有意義,甚至我也沒有。😀因此,如果花很長時間來操縱 Git,請不要擔心。)

在Git中, 提交包含所有文件的完整快照 它還包含一些元數據- 有關提交本身的信息,例如您的姓名,電子郵件地址和時間戳。 元數據中包括提交的提交(或對於合並提交,多個父,復數)的哈希ID,通過比較提交與其父提交,Git會顯示出您的更改。 每個提交都有其自己唯一的哈希ID,例如8858448bb49332d353febc078ce4a3abcc962efe (這是Git的Git存儲庫中的提交ID)。 這犯是一個快照,但犯有父母(在這種情況下, 67f673aa4a... ),這樣的Git可以告訴8858448bb4...通過提取兩者較早67f673aa4a 8858448bb4 ,然后比較這兩個。 git show命令做到了這一點,所以你看到的是什么改變 8858448bb4 ,而不是什么 8858448bb4

(這就像告訴您今天的溫度比昨天的溫度高或低5,風或多或少,而不是一堆數字來表示天氣。數據庫存儲絕對值,但是大多數情況下我們想知道它是否更好。)

索引存儲您可以進行的下一次提交

您可以通過各種方式查看Git的提交,當然也可以通過它們的哈希ID對其進行命名,就像我之前所做的那樣。 您可以直接看到您的工作樹 -這是Git允許您查看和編輯文件的地方-它們在計算機上以正常的日常形式存在。 但是您不能很好地看到索引。 這是一種看不見的東西。 這是一個問題,因為它也很關鍵。

大多數版本控制系統根本沒有索引,或者如果它們有類似的索引,請將其隱藏如此之好 ,以至於您無需了解它。 但是,Git所做的事情很奇怪,它迫使您了解Git的索引,同時又將其隱藏了一點。

如果您真的想立即查看索引中的文件列表,則可以使用git ls-files

$ git ls-files | head
.clang-format
.editorconfig
.gitattributes
.github/CONTRIBUTING.md
.github/PULL_REQUEST_TEMPLATE.md
.gitignore
.gitmodules
.mailmap
.travis.yml
.tsan-suppressions
$ git ls-files | wc -l
    3454

在此Git的Git存儲庫中,索引中幾乎有3500個文件。 有很多文件! 就是 Git使其大部分都隱藏的原因:那里有太多東西無法理解。

但這也是Git通過與父母比較來向我們展示承諾的原因 顯示的全部內容8858448bb4是太多了,所以git show 8858448bb4為我們展示了什么改變 8858448bb4 ,VS其父。 Git與索引保持一致,向我們展示了我們已更改的內容 ,而不是傾倒整個內容。

我認為,這就是使人們認為Git正在存儲更改的原因。 Git會顯示更改,因此Git必須存儲它們……但是事實並非如此! Git存儲整個快照。 每當您要求Git向您展示一些東西時,Git都會找出變化。

考慮到這一點,讓我們一下如何看待索引。

該指數位於當前提交和工作樹之間

現在我們知道每個提交都是完整的快照。 如果Git在每次提交時都為每個文件都制作了一個新副本,則存儲庫將變得非常大。 因此,它不這樣做,並且不這樣做的一部分方法非常簡單。 雖然每個提交的是一個完整的快照, 里面每一個文件提交完全,完全,只讀100%。 沒有人能夠永遠改變。 這意味着每個提交都可以與較早的提交共享其部分或全部文件!

Git只需要確保每次我們運行git commit ,它就會永久凍結所有文件內容,或者至少在此新提交繼續存在的前提下永久凍結該文件內容。 因此,每次提交中的文件都被凍結。 它們也被壓縮成一種特殊的僅Git格式(對於文本文件確實很好用,但對於圖像之類的二進制文件通常效果不佳)。 這種壓縮需要時間,有時會花費很多時間,但是會使存儲庫變小。

顯然,僅Git的凍結文件僅對Git本身有用,因此我們需要從當前提交中取出,解凍,解壓縮並使其有用的每個文件的副本。 這些有用的副本進入工作樹 ,我們在其中進行工作。

其他版本控制系統也做同樣的事情。 在假設的XYZ版本控制系統中,您運行xyz checkout commit ,它將提交從深度凍結倉庫中復制出來,將其解凍,解壓縮並將其存儲在工作樹中。 您做了一些工作,最后運行xyz commit 現在,它會掃描整個工作樹,重新壓縮每個文件,將其凍結,然后檢查是否已在倉庫中獲得該凍結版本,或者也需要將該文件放入其中。 您去喝咖啡或其他任何東西時,每個步驟都需要花費幾秒鍾或幾分鍾。

Git的工作及其索引非常聰明:索引是臨時存儲區 ,位於深凍倉庫(充滿提交的存儲庫)和有用的表單(工作樹中已解凍的文件)之間。 最初,它包含深度凍結相同的文件。 它們已解凍(某種),但仍處於僅Git的特殊形式,並且與工作樹中已完全解凍的解壓縮版本配對。

當您更改工作樹中的文件或添加和/或刪除文件時,索引副本將與工作樹不同步。 現在,Git可以索引副本與工作樹副本進行比較,並告訴您所做的更改但尚未登台

一旦有了所需的文件,就可以運行git add file 這樣就可以立即將文件重新壓縮為特殊的僅Git格式,並將該副本放入索引中。 現在,索引副本(它是一個完整的副本,只是經過壓縮)與工作樹副本匹配,但與提交的副本不同。

您可以隨時讓Git將每個文件的提交HEAD )副本與索引副本進行比較:

git diff --cached

對於相同的文件,Git什么也沒說。 對於不同的文件,Git會列出文件並顯示差異。

同樣,您可以隨時讓Git將每個文件的索引副本與工作樹副本進行比較:

git diff

對於相同的文件,Git什么也沒說。 對於不同的文件,Git會列出文件並顯示差異。

(注意:如果添加了--name-statusgit diff顯示文件名,如果文件名被修改,則以M為前綴。Git使用A表示新添加的文件, D表示刪除的文件,依此類推。上。一個文件,通過簡單地從完全索引中刪除它在索引中刪除 。一個文件中的索引添加的 ,如果它是在索引中而不是在HEAD )。

git status命令使用--name-status限制器運行這兩個比較 對於HEAD和索引之間不同的文件,這些文件已暫存為commit 對於索引和工作樹之間不同的文件,它們不會暫存為commit


形象地:

   HEAD         index        work-tree
----------    ----------    ----------
README.txt    README.txt    README.txt
main.py       main.py       main.py

HEAD副本被凍結,因為它處於提交狀態。 索引和工作樹副本可以更改,但最初三個都匹配 你改變工作樹副本和使用git add到后面將其復制索引,壓縮和連接的Git-ING(如果“EN-的Git-ING”是一個詞,它不是)。 如果您不打算在索引中進行任何更改,則可以使用git reset (具有默認的--mixed操作,或它在任何單個文件上的工作方式)將凍結的一個復制回索引中。

這也是為什么git commit相比xyz commit這么快的原因

當您運行git commit ,Git已經以正確的格式包含了所有將在新提交中使用的文件。 它不必重新壓縮所有工作樹文件,並查看它們是否與凍結的提交版本匹配。 索引已准備就緒:它要做的就是凍結索引副本,如果與先前的提交相同,則與先前的提交共享文件。

此外,由於索引“知道”哪些文件與工作樹匹配而哪些不匹配,因此索引1還具有有關存儲庫中內容的額外信息,因此這也使git checkout更快。 假設您master了大約3500個文件,並且git checkout了其他分支,其中大約3300個文件完全相同。 兩次提交之間大約有200個文件不同(也許是一些新文件或刪除了文件)。 Git可以使用索引來知道在工作樹中可能需要觸摸的內容 ,並且完全避免觸摸那些約3300個文件。

因此,Git掃描並可能觸摸200個文件,而不是XYZ系統掃描並可能觸摸3500個文件,從而節省了94%以上的工作。


1這通常需要掃描工作樹。 索引保留有關工作樹的( 緩存 )數據的副本,以加快此速度。 這就是為什么有時將索引稱為緩存的原因 其他VCS(例如Mercurial)具有工作樹緩存(Mercurial將其稱為dirstate ),但是與Git的索引不同,它已正確隱藏:您不必了解它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM