簡體中文 ▾ 主題 ▾ 最新版本 ▾ git-update-index 最後更新於 2.45.3

名稱

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

從標準輸入讀取索引資訊。

--chmod=(+|-)x

設定更新檔案的執行許可權。

--[no-]assume-unchanged

當指定此標誌時,路徑記錄的物件名稱不會更新。相反,此選項會設定/取消設定路徑的“假定未修改”位。當“假定未修改”位開啟時,使用者承諾不更改檔案,並允許 Git 假定工作區檔案與索引中記錄的內容匹配。如果你想更改工作區檔案,你需要取消設定該位以通知 Git。當在具有非常慢的 lstat(2) 系統呼叫(例如 cifs)的檔案系統上處理大型專案時,這有時會很有幫助。

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

--really-refresh

類似於 --refresh,但無條件檢查 stat 資訊,不考慮“假定未修改”設定。

--[no-]skip-worktree

當指定這些標誌之一時,路徑記錄的物件名稱不會更新。相反,這些選項會設定和取消設定路徑的“跳過工作區”位。有關更多資訊,請參閱下面的“跳過工作區位”部分。

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

即使指定了 --remove 選項,也不移除跳過工作區(又名“僅索引”)條目。

--[no-]fsmonitor-valid

當指定這些標誌之一時,路徑記錄的物件名稱不會更新。相反,這些選項會設定和取消設定路徑的“檔案系統監視器有效”位。有關更多資訊,請參閱下面的“檔案系統監視器”部分。

-g
--again

在索引條目與 HEAD 提交不同的路徑上執行 git update-index 本身。

--unresolve

如果檔案在合併期間意外被清除,則恢復其未合併需要更新的狀態。

--info-only

對於此標誌後所有 <file> 引數,不要在物件資料庫中建立物件;只需將其物件 ID 插入到索引中。

--force-remove

即使工作目錄中仍存在此檔案,也將其從索引中移除。(隱含 --remove。)

--replace

預設情況下,當檔案 path 存在於索引中時,git 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 版本開始支援它,libgit2 在 2016 年添加了對其的支援,JGit 在 2020 年添加了對其的支援。本手冊頁的舊版本稱其為“相對年輕”,但如今它應被視為成熟技術。

--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,在舊版本中 --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. mode SP type SP sha1 TAB path

    此格式用於將 git ls-tree 輸出填充到索引中。

  2. mode SP sha1 SP stage TAB path

    此格式用於將高階階段放入索引檔案,並與 git ls-files --stage 的輸出匹配。

  3. mode SP sha1 TAB path

    此格式不再由任何 Git 命令生成,但 update-index --index-info 仍然並將繼續支援它。

要將更高階段的條目放置到索引中,首先應透過為路徑提供 mode=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)來工作,然後省略讀取那些修改時間未更改的目錄以及對其中檔案的 stat 呼叫。為此,底層作業系統和檔案系統必須在目錄中新增、修改或刪除檔案時更改目錄的 st_mtime 欄位。

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

如果你想啟用(或停用)此功能,使用 core.untrackedCache 配置變數(參見 git-config[1])比在每個倉庫中使用 git update-index--untracked-cache 選項更容易,特別是如果你想在你使用的所有倉庫中這樣做,因為你可以在你的 $HOME/.gitconfig 中只設置一次此配置變數為 true(或 false),它就會影響你操作的所有倉庫。

core.untrackedCache 配置變數更改時,未跟蹤快取將在下次命令讀取索引時新增到索引或從索引中移除;而當使用 --[no-|force-]untracked-cache 時,未跟蹤快取會立即新增到索引或從索引中移除。

在 2.17 版本之前,未跟蹤快取有一個 bug,將目錄替換為指向另一個目錄的符號連結可能導致它錯誤地將 Git 跟蹤的檔案顯示為未跟蹤。參見 git.git 中的“status: add a failing test showing a core.untrackedCache bug”提交。解決此問題的方法是(這可能也適用於未來未發現的其他 bug):

$ git -c core.untrackedCache=false status

當涉及未跟蹤快取的內部結構時,此 bug 也已被證明會影響非符號連結情況下用檔案替換目錄的情況,但尚未報告因此導致錯誤的“git status”輸出的案例。

還有一些情況,由 2.17 之前 Git 版本寫入的現有索引會引用不再存在的目錄,這可能導致在“git status”上列印許多“無法開啟目錄”警告。這些是針對現有問題的新警告,這些問題以前被靜默丟棄了。

與上述 bug 一樣,解決方案是臨時執行一次 core.untrackedCache=false 的“git status”以清除殘留的錯誤資料。

檔案系統監視器

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

它使 Git 能夠與檔案系統監視器(參見 git-fsmonitor--daemon[1]githooks[5] 的“fsmonitor-watchman”部分)協同工作,檔案系統監視器可以告知 Git 哪些檔案已修改。這使得 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 配置變數。當 inode 更改時間經常被 Git 外部的東西修改時(檔案系統爬蟲和備份系統使用 ctime 來標記已處理的檔案),這會很有用(參見 git-config[1])。

未跟蹤快取擴充套件可以透過 core.untrackedCache 配置變數啟用(參見 git-config[1])。

注意事項

使用者經常嘗試使用 assume-unchanged 和 skip-worktree 位來告訴 Git 忽略已跟蹤檔案的更改。但這並不能按預期工作,因為 Git 在執行某些操作時仍然可能根據索引檢查工作區檔案。通常,Git 不提供忽略已跟蹤檔案更改的方法,因此建議採用替代解決方案。

例如,如果你想更改的檔案是某種配置檔案,倉庫可以包含一個示例配置檔案,然後可以將其複製到被忽略的名稱並進行修改。倉庫甚至可以包含一個指令碼,將示例檔案視為模板,自動修改和複製它。

GIT

Git[1] 套件的一部分

scroll-to-top