Git
English ▾ 主題 ▾ 最新版本 ▾ git-update-index 最後更新於 2.46.0

名稱

git-update-index - 將工作目錄中的檔案內容註冊到索引

概要

git update-index
	     [--add] [--remove | --force-remove] [--replace]
	     [--refresh] [-q] [--unmerged] [--ignore-missing]
	     [(--cacheinfo <mode>,<object>,<file>)…​]
	     [--chmod=(+|-)x]
	     [--[no-]assume-unchanged]
	     [--[no-]skip-worktree]
	     [--[no-]ignore-skip-worktree-entries]
	     [--[no-]fsmonitor-valid]
	     [--ignore-submodules]
	     [--[no-]split-index]
	     [--[no-|test-|force-]untracked-cache]
	     [--[no-]fsmonitor]
	     [--really-refresh] [--unresolve] [--again | -g]
	     [--info-only] [--index-info]
	     [-z] [--stdin] [--index-version <n>]
	     [--show-index-version]
	     [--verbose]
	     [--] [<file>…​]

描述

修改索引。每個提到的檔案都會更新到索引中,並且任何未合併需要更新的狀態都會被清除。

另請參閱 git-add[1],以更使用者友善的方式對索引執行一些最常見的操作。

可以使用各種選項修改git update-index處理檔案的方式

選項

--add

如果指定的檔案尚未在索引中,則會新增它。預設行為是忽略新檔案。

--remove

如果指定的檔案在索引中但遺失了,則會移除它。預設行為是忽略已移除的檔案。

--refresh

查看目前的索引,並透過檢查 stat() 資訊來檢查是否需要合併或更新。

-q

安靜。如果 --refresh 發現索引需要更新,預設行為是錯誤退出。此選項會讓 git update-index 繼續執行。

--ignore-submodules

不要嘗試更新子模組。只有在 --refresh 之前傳遞此選項時,才會考慮此選項。

--unmerged

如果 --refresh 在索引中發現未合併的變更,預設行為是錯誤退出。此選項會讓 git update-index 繼續執行。

--ignore-missing

在 --refresh 期間忽略遺失的檔案

--cacheinfo <mode>,<object>,<path>
--cacheinfo <mode> <object> <path>

直接將指定的資訊插入索引。為了向後相容,您也可以將這三個引數作為三個單獨的參數提供,但建議新使用者使用單一參數形式。

--index-info

從 stdin 讀取索引資訊。

--chmod=(+|-)x

設定更新檔案的執行權限。

--[no-]assume-unchanged

指定此旗標時,不會更新為路徑記錄的物件名稱。相反地,此選項會為路徑設定/取消設定「假設未變更」位元。當「假設未變更」位元開啟時,使用者承諾不會變更檔案,並允許 Git 假設工作目錄檔案與索引中記錄的內容相符。如果您想要變更工作目錄檔案,您需要取消設定位元以告知 Git。在處理具有非常慢的 lstat(2) 系統呼叫 (例如 cifs) 的檔案系統上的大型專案時,這有時很有幫助。

如果需要在索引中修改此檔案 (例如在合併提交時),Git 將會 (優雅地) 失敗;因此,如果假設未追蹤的檔案在上游變更,您需要手動處理這種情況。

--really-refresh

--refresh 類似,但不考慮「假設未變更」設定,無條件地檢查 stat 資訊。

--[no-]skip-worktree

指定其中一個旗標時,不會更新為路徑記錄的物件名稱。相反地,這些選項會為路徑設定和取消設定「跳過工作目錄」位元。請參閱下方的「跳過工作目錄位元」章節以取得更多資訊。

--[no-]ignore-skip-worktree-entries

即使指定了 --remove 選項,也不會移除 skip-worktree (又名「僅限索引」) 項目。

--[no-]fsmonitor-valid

指定其中一個旗標時,不會更新為路徑記錄的物件名稱。相反地,這些選項會為路徑設定和取消設定「檔案系統監視器有效」位元。請參閱下方的「檔案系統監視器」章節以取得更多資訊。

-g
--again

針對索引項目與 HEAD 提交的項目不同的路徑,執行 git update-index 本身。

--unresolve

如果檔案在合併期間不小心被清除,則會還原檔案的未合併需要更新狀態。

--info-only

不要為此旗標後的所有 <file> 引數在物件資料庫中建立物件;只需將它們的物件 ID 插入索引。

--force-remove

即使工作目錄仍然有此類檔案,也從索引中移除該檔案。(暗示 --remove。)

--replace

預設情況下,如果索引中存在檔案 pathgit update-index 會拒絕新增 path/file 的嘗試。同樣地,如果存在檔案 path/file,則無法新增檔案 path。使用 --replace 旗標時,會自動移除與新增項目衝突的現有項目,並顯示警告訊息。

--stdin

不要從命令列取得路徑清單,而是從標準輸入讀取路徑清單。預設情況下,路徑以 LF 分隔 (即每行一個路徑)。

--verbose

報告正在新增和從索引中移除的內容。

--index-version <n>

以具名的磁碟格式版本寫出產生的索引。支援的版本有 2、3 和 4。目前的預設版本為 2 或 3,具體取決於是否使用額外功能,例如 git add -N。使用 --verbose 時,也會報告此命令之前和之後索引檔案使用的版本。

版本 4 執行簡單的路徑名稱壓縮,可將大型存放庫上的索引大小減少 30%-50%,從而加快載入時間。Git 從 2012 年 10 月發行的 1.8.0 版本開始支援它,並在 2016 年將其新增至 libgit2,並在 2020 年將其新增至 JGit。此手冊頁面的舊版本稱其為「相對較新」,但現在應將其視為成熟的技術。

--show-index-version

報告磁碟索引檔案使用的索引格式版本。請參閱上方的 --index-version

-z

僅在使用 --stdin--index-info 時才有意義;路徑以 NUL 字元而不是 LF 分隔。

--split-index
--no-split-index

啟用或停用分割索引模式。如果已啟用分割索引模式,且再次給定 --split-index,則 $GIT_DIR/index 中的所有變更都會推回共用索引檔案。

無論 core.splitIndex 組態變數 (請參閱 git-config[1]) 的值為何,這些選項都會生效。但是,當變更與設定的值不符時,會發出警告,因為設定的值會在下次讀取索引時生效,這會消除選項的預期效果。

--untracked-cache
--no-untracked-cache

啟用或停用未追蹤快取功能。請在啟用之前使用 --test-untracked-cache

無論 core.untrackedCache 組態變數的值為何(請參閱 git-config[1]),這些選項都會生效。但是,當變更與組態值相反時,會發出警告,因為組態值將在下次讀取索引時生效,並且會移除選項的預期效果。

--test-untracked-cache

僅對工作目錄執行測試,以確保可以使用未追蹤快取。如果您真的想使用它,您必須之後使用 --untracked-cache--force-untracked-cachecore.untrackedCache 組態變數手動啟用未追蹤快取。如果測試失敗,則結束代碼為 1,並會顯示訊息說明哪些地方無法正常運作。否則,結束代碼為 0,並印出 OK。

--force-untracked-cache

--untracked-cache 相同。為了與舊版 Git 的回溯相容性而提供,在舊版 Git 中 --untracked-cache 曾經暗示 --test-untracked-cache,但此選項會無條件啟用擴充功能。

--fsmonitor
--no-fsmonitor

啟用或停用檔案系統監視器功能。無論 core.fsmonitor 組態變數的值為何(請參閱 git-config[1]),這些選項都會生效。但是,當變更與組態值相反時,會發出警告,因為組態值將在下次讀取索引時生效,並且會移除選項的預期效果。

--

不再將任何其他引數解讀為選項。

<file>

要作用的檔案。請注意,開頭為 . 的檔案會被捨棄。這包括 ./filedir/./file。如果您不想要這樣,請使用較乾淨的名稱。同樣地,結尾為 / 的目錄和包含 // 的路徑也適用。

使用 --REFRESH

--refresh 不會計算新的 sha1 檔案,也不會更新索引以反映模式/內容變更。但它**確實**會做的是將檔案的 stat 資訊與索引「重新比對」,讓您可以重新整理尚未變更,但 stat 項目已過期的檔案索引。

例如,您會在執行 git read-tree 之後執行此操作,以將 stat 索引詳細資料與正確的檔案連結起來。

使用 --CACHEINFO 或 --INFO-ONLY

--cacheinfo 用於註冊目前工作目錄中不存在的檔案。這對於最小簽出合併很有用。

若要假裝您在路徑上有一個具有模式和 sha1 的檔案,請說

$ git update-index --add --cacheinfo <mode>,<sha1>,<path>

--info-only 用於註冊檔案,而不會將它們放置在物件資料庫中。這對於僅限狀態的儲存庫很有用。

--cacheinfo--info-only 的行為類似:索引會更新,但物件資料庫不會。當物件在資料庫中但檔案在本地不可用時,--cacheinfo 很有用。當檔案可用,但您不希望更新物件資料庫時,--info-only 很有用。

使用 --INDEX-INFO

--index-info 是一種更強大的機制,可讓您從標準輸入饋送多個條目定義,並且專為腳本設計。它可以採用三種格式的輸入

  1. 模式 SP 類型 SP sha1 TAB 路徑

    此格式是將 git ls-tree 輸出放入索引中。

  2. 模式 SP sha1 SP 階段 TAB 路徑

    此格式是將較高階的階段放入索引檔中,並與 git ls-files --stage 輸出相符。

  3. 模式 SP sha1 TAB 路徑

    此格式不再由任何 Git 命令產生,但 update-index --index-info 會繼續支援此格式。

若要將較高階段的條目放入索引中,應先透過饋送路徑的模式 = 0 條目來移除路徑,然後再以第三種格式饋送必要的輸入行。

例如,從這個索引開始

$ git ls-files -s
100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0       frotz

您可以將下列輸入饋送給 --index-info

$ git update-index --index-info
0 0000000000000000000000000000000000000000	frotz
100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1	frotz
100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2	frotz

輸入的第一行饋送 0 作為模式以移除路徑;只要格式正確,SHA-1 並不重要。然後,第二行和第三行會饋送該路徑的階段 1 和階段 2 條目。完成上述步驟後,我們會得到這個結果

$ git ls-files -s
100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1	frotz
100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2	frotz

使用「假設未變更」位元

Git 中的許多操作都依賴您的檔案系統具有有效的 lstat(2) 實作,以便可以便宜地檢查工作樹檔案的 st_mtime 資訊,以查看檔案內容是否已從索引檔中記錄的版本變更。遺憾的是,某些檔案系統的 lstat(2) 效率不高。如果您的檔案系統是其中之一,您可以將「假設未變更」位元設定為您尚未變更的路徑,以使 Git 不執行此檢查。請注意,在路徑上設定此位元並不表示 Git 會檢查檔案的內容以查看它是否已變更,而是會讓 Git 省略任何檢查,並假設它**未**變更。當您對工作樹檔案進行變更時,您必須在修改它們之前或之後明確告知 Git,方法是移除「假設未變更」位元。

若要設定「假設未變更」位元,請使用 --assume-unchanged 選項。若要取消設定,請使用 --no-assume-unchanged。若要查看哪些檔案已設定「假設未變更」位元,請使用 git ls-files -v(請參閱 git-ls-files[1])。

此命令會查看 core.ignorestat 組態變數。當此值為 true 時,使用 git update-index paths... 更新的路徑,以及使用其他同時更新索引和工作樹的 Git 命令(例如 git apply --indexgit checkout-index -ugit read-tree -u)更新的路徑,會自動標記為「假設未變更」。請注意,如果 git update-index --refresh 發現工作樹檔案與索引相符,則**不會**設定「假設未變更」位元(如果您想要將它們標記為「假設未變更」,請使用 git update-index --really-refresh)。

有時使用者會將假設未變更的位元與跳過工作樹位元混淆。請參閱下方「跳過工作樹位元」區段的最後一段,以取得差異說明。

範例

若要僅更新和重新整理已簽出的檔案

$ git checkout-index -n -f -a && git update-index --ignore-missing --refresh
在設定了 core.ignorestat 的效率不高的檔案系統上
$ git update-index --really-refresh              (1)
$ git update-index --no-assume-unchanged foo.c   (2)
$ git diff --name-only                           (3)
$ edit foo.c
$ git diff --name-only                           (4)
M foo.c
$ git update-index foo.c                         (5)
$ git diff --name-only                           (6)
$ edit foo.c
$ git diff --name-only                           (7)
$ git update-index --no-assume-unchanged foo.c   (8)
$ git diff --name-only                           (9)
M foo.c
  1. 強制 lstat(2) 為與索引相符的路徑設定「假設未變更」位元。

  2. 標記要編輯的路徑。

  3. 這會執行 lstat(2) 並找到索引與路徑相符。

  4. 這會執行 lstat(2) 並找到索引與路徑**不**相符。

  5. 將新版本註冊到索引會設定「假設未變更」位元。

  6. 並假設未變更。

  7. 即使在您編輯它之後。

  8. 您可以在事後告知變更。

  9. 現在它會使用 lstat(2) 檢查,並發現它已變更。

跳過工作樹位元

跳過工作樹位元可以用一句(長)句子定義:告知 Git 在合理的情況下避免將檔案寫入工作目錄,並且當檔案不存在於工作目錄中時,將其視為未變更。

請注意,並非所有 Git 命令都會注意此位元,而且有些命令僅部分支援它。

與跳過工作樹位元相關的 update-index 旗標和 read-tree 功能早於 git-sparse-checkout[1] 命令的引入,後者提供了一種更簡單的方式來組態和處理跳過工作樹位元。如果您想要將工作樹縮減為僅處理儲存庫中的檔案子集,我們強烈建議您使用 git-sparse-checkout[1],而不是底層的 update-index 和 read-tree 基本功能。

跳過工作樹位元的主要目的是啟用稀疏簽出,也就是說,工作目錄中僅存在路徑的子集。設定跳過工作樹位元時,Git 命令(例如 switchpullmerge)會避免寫入這些檔案。但是,這些命令有時仍然會在重要情況下寫入這些檔案,例如合併或變基期間發生衝突。Git 命令也會避免將缺少這些檔案視為有意的刪除。例如,git add -u 不會為這些檔案暫存刪除,而 git commit -a 也不會建立刪除這些檔案的提交。

雖然此位元看起來與假設未變更的位元類似,但其目標不同。假設未變更的位元是為了將檔案保留在工作樹中,但讓 Git 省略檢查其變更,並假設檔案未變更(不過,如果可以在不使用 stat 的情況下確定檔案已變更,則可以自由記錄變更)。跳過工作樹會告知 Git 忽略缺少檔案、盡可能避免使用通常更新大部分工作目錄的命令(例如 checkoutswitchpull 等)來更新它,並且不要在提交中記錄其缺失。請注意,在稀疏簽出中(由 git sparse-checkout 設定,或將 core.sparseCheckout 組態為 true 設定),如果檔案在索引中標記為跳過工作樹,但在工作樹中找到,Git 會清除該檔案的跳過工作樹位元。

分割索引

此模式專為具有非常大索引的儲存庫設計,旨在減少重複寫入這些索引所需的時間。

在此模式下,索引會分割成兩個檔案,$GIT_DIR/index 和 $GIT_DIR/sharedindex.<SHA-1>。變更會累積在 $GIT_DIR/index 中,即分割索引,而共用索引檔包含所有索引條目,並且保持不變。

當分割索引中的條目數達到 splitIndex.maxPercentChange 組態變數指定的層級時(請參閱 git-config[1]),分割索引中的所有變更都會推回共用索引檔。

每次建立新的共用索引檔時,如果舊共用索引檔的修改時間早於 splitIndex.sharedIndexExpire 組態變數指定的時間(請參閱 git-config[1]),則會刪除舊的共用索引檔。

為了避免刪除仍在使用中的共用索引檔,每次建立或從共用索引檔讀取基於共用索引檔的新分割索引時,其修改時間都會更新為目前時間。

未追蹤快取

此快取旨在加速涉及判斷未追蹤檔案的命令,例如 git status

此功能的工作方式是記錄工作樹目錄的 mtime,然後省略讀取目錄和針對 mtime 未變更的目錄中的檔案執行 stat 呼叫。為了使此功能正常運作,如果目錄中的檔案已新增、修改或刪除,則底層作業系統和檔案系統必須變更目錄的 st_mtime 欄位。

您可以使用 --test-untracked-cache 選項測試檔案系統是否支援此功能。--untracked-cache 選項曾經在舊版 Git 中隱含執行該測試,但現在已不再如此。

如果您想要啟用(或停用)此功能,使用 core.untrackedCache 組態變數(請參閱 git-config[1])會比在每個儲存庫中使用 git update-index--untracked-cache 選項更容易,特別是當您想要在您使用的所有儲存庫中執行此操作時,因為您可以在 $HOME/.gitconfig 中將組態變數設定為 true(或 false)一次,即可影響您所接觸的所有儲存庫。

core.untrackedCache 組態變數變更時,未追蹤快取會在下次指令讀取索引時新增至索引或從索引中移除;而當使用 --[no-|force-]untracked-cache 時,未追蹤快取會立即新增至索引或從索引中移除。

在 2.17 版本之前,未追蹤快取有一個錯誤,當用指向另一個目錄的符號連結取代目錄時,可能會錯誤地將 Git 追蹤的檔案顯示為未追蹤。請參閱 git.git 的「status: add a failing test showing a core.untrackedCache bug」提交。一個解決方法是(這可能對未來其他未被發現的錯誤有效)

$ git -c core.untrackedCache=false status

此錯誤也顯示在以檔案取代目錄的非符號連結案例中,會影響未追蹤快取的內部結構,但沒有案例報告顯示這會導致錯誤的「git status」輸出。

還有一些情況是,2.17 之前的 Git 版本寫入的現有索引會參考不再存在的目錄,可能會導致在「git status」時印出許多「could not open directory」警告。這些是針對先前被靜默丟棄的現有問題的新警告。

如同上述錯誤,解決方法是使用 core.untrackedCache=false 執行一次「git status」以清除剩餘的錯誤資料。

檔案系統監控器

此功能旨在加速具有大型工作目錄的儲存庫的 Git 操作。

它使 Git 可以與檔案系統監控器(請參閱 git-fsmonitor--daemon[1]githooks[5] 的「fsmonitor-watchman」章節)協同工作,該監控器可以告知它哪些檔案已被修改。這使 Git 可以避免必須對每個檔案執行 lstat() 來查找已修改的檔案。

當與未追蹤快取結合使用時,它可以通過避免掃描整個工作目錄以查找新檔案的成本來進一步提高效能。

如果您想要啟用(或停用)此功能,使用 core.fsmonitor 組態變數(請參閱 git-config[1])會比在每個儲存庫中使用 git update-index--fsmonitor 選項更容易,特別是當您想要在您使用的所有儲存庫中執行此操作時,因為您可以在 $HOME/.gitconfig 中將組態變數設定一次,即可影響您所接觸的所有儲存庫。

core.fsmonitor 組態變數變更時,檔案系統監控器會在下次指令讀取索引時新增至索引或從索引中移除。當使用 --[no-]fsmonitor 時,檔案系統監控器會立即新增至索引或從索引中移除。

組態

此指令會遵守 core.filemode 組態變數。如果您的儲存庫位於執行位元不可靠的檔案系統上,則應將此設定為 *false*(請參閱 git-config[1])。如果索引中記錄的檔案模式與檔案系統上的檔案模式僅在執行位元上有所不同,這會導致指令忽略它們之間的差異。在這樣不幸的檔案系統上,您可能需要使用 *git update-index --chmod= *。

同樣地,如果 core.symlinks 組態變數設定為 *false*(請參閱 git-config[1]),符號連結會以純文字檔案的形式檢出,並且此指令不會將記錄的檔案模式從符號連結修改為常規檔案。

此指令會查看 core.ignorestat 組態變數。請參閱上面的「使用“假設未變更”位元」章節。

此指令也會查看 core.trustctime 組態變數。當節點變更時間經常被 Git 外部的東西修改時(檔案系統爬蟲和備份系統使用 ctime 來標記已處理的檔案),這會很有用(請參閱 git-config[1])。

未追蹤快取擴展可以由 core.untrackedCache 組態變數啟用(請參閱 git-config[1])。

注意事項

使用者經常嘗試使用 assume-unchanged 和 skip-worktree 位元來告訴 Git 忽略對已追蹤檔案的變更。這無法按預期工作,因為 Git 在執行某些操作時仍可能檢查工作樹檔案是否與索引一致。一般而言,Git 不提供忽略對已追蹤檔案變更的方法,因此建議使用替代解決方案。

例如,如果您想要變更的檔案是某種組態檔,儲存庫可以包含一個範例組態檔,然後可以將其複製到忽略的名稱中並進行修改。儲存庫甚至可以包含一個腳本,將範例檔案視為範本,自動修改和複製它。

GIT

屬於 git[1] 套件的一部分

scroll-to-top