簡體中文 ▾ 主題 ▾ 最新版本 ▾ git-update-index 最後更新於 2.52.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 <模式>,<物件>,<路徑>
--cacheinfo <模式> <物件> <路徑>

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

--index-info

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

--chmod=(+|-)x

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

--assume-unchanged
--no-assume-unchanged

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

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

--really-refresh

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

--skip-worktree
--no-skip-worktree

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

--ignore-skip-worktree-entries
--no-ignore-skip-worktree-entries

即使指定了 --remove 選項,也不會刪除 skip-worktree(又名“僅索引”)條目。

--fsmonitor-valid
--no-fsmonitor-valid

指定這些標誌之一時,不會更新為路徑記錄的物件名稱。相反,這些選項會設定和取消設定這些路徑的“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])。但是,當更改與配置值相反時會發出警告,因為配置值將在下次讀取索引時生效,這將消除該選項的預期效果。

--

不再將任何後續引數解釋為選項。

<檔案>

要操作的檔案。請注意,以 . 開頭的檔案會被丟棄。這包括 ./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. 模式 空格 型別 空格 sha1 製表符 路徑

    此格式用於將 git ls-tree 的輸出存入索引。

  2. 模式 空格 sha1 空格 階段 製表符 路徑

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

  3. 模式 空格 sha1 製表符 路徑

    此格式不再由任何 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)。

有時使用者會混淆 assume-unchanged 位和 skip-worktree 位。請參閱下面的“Skip-worktree 位”部分的最後一段,瞭解它們之間的區別。

示例

僅更新和重新整理已簽出檔案的操作

$ 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) 進行檢查,發現它已被更改。

跳過工作樹位

Skip-worktree 位可以用一個(長)句子來定義:告訴 git 在合理可能的情況下避免將檔案寫入工作目錄,並在檔案不在工作目錄中時將其視為未更改。

請注意,並非所有 git 命令都會關注此位,有些命令僅部分支援它。

update-index 標誌和與 skip-worktree 位相關的 read-tree 功能在 git-sparse-checkout[1] 命令引入之前就已存在,該命令提供了一種更簡便的方法來配置和處理 skip-worktree 位。如果您想將工作目錄限制為只處理儲存庫中的部分檔案,我們強烈建議優先使用 git-sparse-checkout[1] 而不是底層的 update-index 和 read-tree 原語。

skip-worktree 位的主要目的是啟用稀疏簽出,即擁有隻有部分路徑存在的工作目錄。當設定 skip-worktree 位時,Git 命令(例如 switchpullmerge)將避免寫入這些檔案。但是,在發生重要情況(例如合併或 rebase 期間的衝突)時,這些命令有時仍會寫入這些檔案。Git 命令還將避免將這些檔案的缺失視為有意刪除;例如 git add -u 不會為這些檔案暫存刪除,git commit -a 也不會透過提交來刪除它們。

儘管此位看起來與 assume-unchanged 位相似,但其目標不同。assume-unchanged 位用於保留工作樹中的檔案,但讓 Git 忽略對其的更改檢查,並假定檔案未被更改(儘管如果 Git 在不 stat 檔案的情況下就能確定它已更改,則它可以記錄更改)。skip-worktree 告訴 Git 忽略檔案的缺失,在可能的情況下避免使用通常會更新大部分工作目錄的命令(例如 checkoutswitchpull 等)來更新它,並且不將其缺失記錄在提交中。請注意,在稀疏簽出(由 git sparse-checkout 設定或透過將 core.sparseCheckout 配置為 true)中,如果索引中標記了 skip-worktree 的檔案在工作樹中找到,Git 將清除該檔案的 skip-worktree 位。

拆分索引

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

在此模式下,索引被分成兩個檔案:$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 選項測試檔案系統是否支援此功能。在較舊版本的 Git 中,--untracked-cache 選項會隱式執行此測試,但現在已不再如此。

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

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”時列印大量“無法開啟目錄”警告。這些是先前被靜默忽略的現有問題的新的警告。

與上述錯誤一樣,解決方案是執行一次“git status”執行,並將 core.untrackedCache 設定為 false,以清除殘留的壞資料。

檔案系統監視器

此功能旨在加快具有大型工作目錄的儲存庫的 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 配置變數。當 inode 更改時間經常被 Git 之外的某些東西修改時(檔案系統爬蟲和備份系統使用 ctime 來標記已處理的檔案),這可能很有用(請參閱 git-config[1])。

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

注意事項

使用者經常嘗試使用 assume-unchanged 和 skip-worktree 位來告訴 Git 忽略已跟蹤檔案的更改。這並不能按預期工作,因為 Git 在執行某些操作時仍可能將工作樹檔案與索引進行比較。總的來說,Git 無法提供忽略已跟蹤檔案更改的方法,因此建議採用其他解決方案。

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

GIT

Git[1] 套件的一部分