Git
英文 ▾ 主題 ▾ 最新版本 ▾ git-fetch 最後更新於 2.46.2

名稱

git-fetch - 從另一個儲存庫下載物件與參考

概要

git fetch [<options>] [<repository> [<refspec>…​]]
git fetch [<options>] <group>
git fetch --multiple [<options>] [(<repository> | <group>)…​]
git fetch --all [<options>]

描述

從一個或多個其他儲存庫提取分支和/或標籤(統稱為「參考」),以及完成其歷史記錄所需的物件。遠端追蹤分支會被更新(請參閱下方 <refspec> 的說明,了解控制此行為的方式)。

預設情況下,任何指向提取歷史記錄中的標籤也會被提取;效果是提取指向您感興趣的分支的標籤。可以使用 --tags 或 --no-tags 選項或設定 remote.<name>.tagOpt 來變更此預設行為。透過使用明確提取標籤的 refspec,您也可以提取未指向您感興趣的分支的標籤。

如果給定 <group> 且設定檔中有 remotes.<group> 項目,git fetch 可以從單一具名儲存庫或 URL,或同時從多個儲存庫提取。(請參閱 git-config[1])。

當未指定遠端時,預設會使用 origin 遠端,除非目前分支設定了上游分支。

提取的參考名稱,以及它們指向的物件名稱,會被寫入 .git/FETCH_HEAD。指令碼或其他 git 指令 (例如 git-pull[1]) 可以使用此資訊。

選項

--[no-]all

提取所有遠端,除了設定 remote.<name>.skipFetchAll 設定變數的遠端。這會覆寫設定變數 fetch.all`。

-a
--append

將提取的參考的參考名稱和物件名稱附加到現有的 .git/FETCH_HEAD 內容。如果沒有此選項,.git/FETCH_HEAD 中的舊資料將被覆寫。

--atomic

使用原子交易來更新本機參考。要麼更新所有參考,要麼在發生錯誤時,不更新任何參考。

--depth=<depth>

將提取限制為每個遠端分支歷史記錄頂端指定數量的提交。如果提取到使用 git clone--depth=<depth> 選項建立的淺層儲存庫(請參閱 git-clone[1]),則將歷史記錄加深或縮短為指定數量的提交。不提取加深提交的標籤。

--deepen=<depth>

與 --depth 類似,但它指定從目前淺層邊界開始的提交數量,而不是從每個遠端分支歷史記錄頂端開始的提交數量。

--shallow-since=<date>

加深或縮短淺層儲存庫的歷史記錄,以包含 <date> 之後所有可連線的提交。

--shallow-exclude=<revision>

加深或縮短淺層儲存庫的歷史記錄,以排除可從指定的遠端分支或標籤連線的提交。可以多次指定此選項。

--unshallow

如果來源儲存庫完整,則將淺層儲存庫轉換為完整儲存庫,移除淺層儲存庫施加的所有限制。

如果來源儲存庫為淺層,則盡可能提取,使目前儲存庫具有與來源儲存庫相同的歷史記錄。

--update-shallow

預設情況下,當從淺層儲存庫提取時,git fetch 會拒絕需要更新 .git/shallow 的參考。此選項會更新 .git/shallow 並接受此類參考。

--negotiation-tip=<commit|glob>

預設情況下,Git 會向伺服器報告可從所有本機參考連線的提交,以尋找通用提交,以便嘗試減少要接收的封裝檔案大小。如果指定,Git 將僅報告可從指定提示連線的提交。當使用者知道哪個本機參考可能與正在提取的上游參考有共同的提交時,這對於加速提取很有用。

可以多次指定此選項;如果這樣,Git 會報告可從任何給定提交連線的提交。

此選項的引數可以是參考名稱的 glob、參考或提交的(可能縮寫的)SHA-1。指定 glob 相當於多次指定此選項,每個符合的參考名稱一次。

另請參閱 git-config[1] 中說明的 fetch.negotiationAlgorithmpush.negotiate 設定變數,以及下方的 --negotiate-only 選項。

--negotiate-only

不從伺服器提取任何內容,而是列印我們與伺服器共用的所提供 --negotiation-tip=* 引數的祖先。

這與 --recurse-submodules=[yes|on-demand] 不相容。在內部,這用於實作 push.negotiate 選項,請參閱 git-config[1]

--dry-run

顯示將執行的動作,而不進行任何變更。

--porcelain

以易於指令碼剖析的格式將輸出列印到標準輸出。請參閱 git-fetch[1] 中的 OUTPUT 區段,了解詳細資訊。

這與 --recurse-submodules=[yes|on-demand] 不相容,且優先於 fetch.output 設定選項。

--[no-]write-fetch-head

將提取的遠端參考清單直接寫入 $GIT_DIR 下的 FETCH_HEAD 檔案。這是預設值。從命令列傳遞 --no-write-fetch-head 會告知 Git 不要寫入檔案。在 --dry-run 選項下,永遠不會寫入檔案。

-f
--force

git fetch<src>:<dst> refspec 一起使用時,它可能會拒絕更新本機分支,如以下 <refspec> 部分所述。此選項會覆寫該檢查。

-k
--keep

保留下載的封裝。

--multiple

允許指定多個 <repository> 和 <group> 引數。不得指定 <refspec>。

--[no-]auto-maintenance
--[no-]auto-gc

在結尾執行 git maintenance run --auto,以便在需要時執行自動儲存庫維護。(--[no-]auto-gc 是同義詞。)預設啟用此功能。

--[no-]write-commit-graph

提取後寫入提交圖表。這會覆寫設定值 fetch.writeCommitGraph

--prefetch

修改已設定的 refspec,將所有參考放置到 refs/prefetch/ 命名空間。請參閱 git-maintenance[1] 中的 prefetch 工作。

-p
--prune

在提取之前,移除遠端上已不存在的任何遠端追蹤參照。如果標籤僅因預設的標籤自動追蹤或由於 --tags 選項而被提取,則標籤不會被修剪。但是,如果標籤是因明確的 refspec 而被提取(無論是在命令列上或是在遠端設定中,例如,如果遠端是用 --mirror 選項複製的),則它們也會被修剪。提供 --prune-tags 是提供標籤 refspec 的簡寫。

請參閱下方的「修剪」章節以取得更多詳細資訊。

-P
--prune-tags

如果啟用 --prune,在提取之前,移除遠端上已不存在的任何本機標籤。這個選項應該謹慎使用,不像 --prune,它會移除任何已建立的本機參照(本機標籤)。這個選項是提供明確標籤 refspec 和 --prune 的簡寫,請參閱其說明文件中關於此的討論。

請參閱下方的「修剪」章節以取得更多詳細資訊。

-n
--no-tags

預設情況下,指向從遠端儲存庫下載的物件的標籤會被提取並儲存在本機。此選項會停用此自動追蹤標籤。遠端的預設行為可以使用 remote.<name>.tagOpt 設定來指定。請參閱 git-config[1]

--refetch

這個選項不會與伺服器協商以避免傳輸已在本機存在的提交和相關物件,而是會像全新複製一樣提取所有物件。當篩選定義已變更時,可以使用此選項來重新套用來自設定的局部複製篩選或使用 --filter=。自動提取後維護將執行物件資料庫封裝整合,以移除任何重複物件。

--refmap=<refspec>

當提取命令列上列出的 refs 時,使用指定的 refspec(可以多次給定)將 refs 對應到遠端追蹤分支,而不是遠端儲存庫的 remote.*.fetch 設定變數的值。為 --refmap 選項提供一個空的 <refspec> 會使 Git 忽略已設定的 refspecs,並完全依賴作為命令列引數提供的 refspecs。請參閱「已設定的遠端追蹤分支」部分以取得詳細資訊。

-t
--tags

從遠端提取所有標籤(即,將遠端標籤 refs/tags/* 提取到具有相同名稱的本機標籤),除了其他任何會被提取的內容之外。單獨使用此選項不會使標籤受到修剪,即使使用了 --prune(儘管如果標籤也是明確 refspec 的目的地,則標籤仍然可能會被修剪;請參閱 --prune)。

--recurse-submodules[=(yes|on-demand|no)]

此選項控制是否以及在何種條件下也應該提取子模組的新提交。當遞迴處理子模組時,git fetch 始終會嘗試提取「已變更」的子模組,也就是說,具有新提取的超級專案提交所參照,但在本機子模組複製中遺失的提交的子模組。只要變更的子模組在本機存在,例如在 $GIT_DIR/modules/ 中(請參閱 gitsubmodules[7]),就可以提取變更的子模組;如果上游新增了一個新的子模組,則該子模組必須先複製,例如通過 git submodule update,才能被提取。

當設定為 *on-demand* 時,僅提取已變更的子模組。當設定為 *yes* 時,會提取所有已填充的子模組,並且會提取未填充和已變更的子模組。當設定為 *no* 時,永遠不會提取子模組。

如果未指定,則會使用 fetch.recurseSubmodules 的值(如果已設定)(請參閱 git-config[1]),如果未設定,則預設為 *on-demand*。當此選項在不帶任何值的情況下使用時,它會預設為 *yes*。

-j
--jobs=<n>

用於所有形式提取的平行子程序數量。

如果指定了 --multiple 選項,則會平行提取不同的遠端。如果提取多個子模組,它們將平行提取。要獨立控制它們,請使用設定 fetch.parallelsubmodule.fetchJobs(請參閱 git-config[1])。

通常,平行的遞迴和多遠端提取會更快。預設情況下,提取會循序執行,而不是平行執行。

--no-recurse-submodules

停用子模組的遞迴提取(這與使用 --recurse-submodules=no 選項的效果相同)。

--set-upstream

如果成功提取遠端,則新增上游(追蹤)參照,供無引數的 git-pull[1] 和其他命令使用。如需更多資訊,請參閱 git-config[1] 中的 branch.<name>.mergebranch.<name>.remote

--submodule-prefix=<path>

在資訊訊息(例如「正在提取子模組 foo」)中列印的路徑前加上 <path>。當遞迴處理子模組時,會在內部使用此選項。

--recurse-submodules-default=[yes|on-demand]

此選項在內部用於暫時為 --recurse-submodules 選項提供一個非負的預設值。所有其他設定 fetch 的子模組遞迴的方法(例如 gitmodules[5]git-config[1] 中的設定)都會覆寫此選項,直接指定 --[no-]recurse-submodules 也是如此。

-u
--update-head-ok

預設情況下,*git fetch* 會拒絕更新對應於目前分支的 head。此旗標會停用檢查。這純粹是為了 *git pull* 的內部使用,以便與 *git fetch* 通訊,除非您正在實作自己的 Porcelain,否則您不應該使用它。

--upload-pack <upload-pack>

當給定,且要從中提取的儲存庫由 *git fetch-pack* 處理時,--exec=<upload-pack> 會傳遞給命令,以指定在另一端執行的命令的非預設路徑。

-q
--quiet

將 --quiet 傳遞給 git-fetch-pack 並使任何其他內部使用的 git 命令保持靜默。進度不會報告到標準錯誤串流。

-v
--verbose

顯示詳細資訊。

--progress

預設情況下,當進度狀態連接到終端機時,進度狀態會報告到標準錯誤串流,除非指定了 -q。即使標準錯誤串流未定向到終端機,此旗標也會強制執行進度狀態。

-o <option>
--server-option=<option>

在使用協定版本 2 通訊時,將給定的字串傳輸到伺服器。給定的字串不得包含 NUL 或 LF 字元。伺服器對伺服器選項(包括未知選項)的處理是伺服器特定的。當給定多個 --server-option=<option> 時,它們會按照命令列上列出的順序全部傳送到另一端。

--show-forced-updates

預設情況下,git 會檢查在提取期間是否強制更新了分支。這可以通過 fetch.showForcedUpdates 來停用,但 --show-forced-updates 選項可保證會執行此檢查。請參閱 git-config[1]

--no-show-forced-updates

預設情況下,git 會檢查在提取期間是否強制更新了分支。傳遞 --no-show-forced-updates 或將 fetch.showForcedUpdates 設定為 false 可跳過此檢查以提高效能。如果在 *git-pull* 期間使用,--ff-only 選項仍然會在嘗試快轉更新之前檢查強制更新。請參閱 git-config[1]

-4
--ipv4

僅使用 IPv4 位址,忽略 IPv6 位址。

-6
--ipv6

僅使用 IPv6 位址,忽略 IPv4 位址。

<repository>

作為提取或拉取作業來源的「遠端」儲存庫。此參數可以是 URL(請參閱下方「GIT URLS」章節)或遠端的名稱(請參閱下方「REMOTES」章節)。

<group>

在設定檔案中,指的是儲存庫清單的名稱,該清單作為 remotes.<group> 的值。(請參閱 git-config[1])。

<refspec>

指定要提取哪些 refs 以及要更新哪些本機 refs。當命令列上沒有出現 <refspec> 時,要提取的 refs 會改為從 remote.<repository>.fetch 變數讀取(請參閱下方「已設定的遠端追蹤分支」)。

<refspec> 參數的格式是一個可選的加號 +,後接來源 <src>,後接冒號 :,後接目的地 ref <dst>。當 <dst> 為空時,可以省略冒號。<src> 通常是一個 ref,但它也可以是完全拼寫的十六進位物件名稱。

<refspec> 的 <src> 中可以包含 *,以表示簡單的模式比對。此類 refspec 的功能類似於一個 glob,它會比對具有相同字首的任何 ref。模式 <refspec> 的 <src> 和 <dst> 中都必須有 *。它會透過將 * 替換為從來源比對的內容,將 refs 對應到目的地。

如果 refspec 以 ^ 為字首,則會將其解譯為負 refspec。此類 refspec 不會指定要提取哪些 refs 或要更新哪些本機 refs,而是指定要排除的 refs。如果 ref 符合至少一個正 refspec,且不符合任何負 refspec,則會將其視為符合。負 refspec 可以用來限制模式 refspec 的範圍,使其不包含特定的 refs。負 refspec 本身可以是模式 refspec。但是,它們可能只包含 <src>,而不指定 <dst>。也不支援完全拼寫的十六進位物件名稱。

tag <tag> 的含義與 refs/tags/<tag>:refs/tags/<tag> 相同;它會請求提取直到給定標籤的所有內容。

提取符合 <src> 的遠端 ref,如果 <dst> 不是空字串,則會嘗試更新符合它的本機 ref。

是否允許在沒有 --force 的情況下進行該更新取決於它要提取到的 ref 命名空間、要提取的物件類型,以及更新是否被視為快轉。一般而言,提取的規則與推送時的規則相同,請參閱 git-push[1]<refspec>... 章節以了解這些規則。下面列出了 *git fetch* 特有的規則例外情況。

在 Git 2.20 版之前,與使用 git-push[1] 進行推送不同,任何對 refs/tags/* 的更新都會被接受,而不需要 refspec 中的 +(或 --force)。在提取時,我們會任意地將來自遠端的所有標籤更新視為強制提取。自 Git 2.20 版以來,提取以更新 refs/tags/* 的工作方式與推送時相同。也就是說,任何更新都會在沒有 refspec 中的 +(或 --force)的情況下被拒絕。

與使用 git-push[1] 進行推送不同,在 refs/{tags,heads}/* 之外的任何更新都會被接受,而不需要 refspec 中的 +(或 --force),無論是將樹狀物件交換為 blob,還是將提交交換為不以前一個提交作為祖先的另一個提交等等。

與使用 git-push[1] 進行推送不同,沒有任何設定可以修改這些規則,也沒有任何類似於 pre-receive 掛鉤的 pre-fetch 掛鉤。

如同使用 git-push[1] 推送一樣,所有上述關於不允許更新的規則,都可以透過在 refspec 前面加上可選的 + 符號(或使用 --force 命令列選項)來覆蓋。唯一的例外是,無論如何強制,refs/heads/* 命名空間都不會接受非 commit 物件。

注意
當您要提取的遠端分支已知會定期回溯和變基時,預期其新的頂端將不會是其先前頂端(上次提取時儲存在您的遠端追蹤分支中)的後代。您應該使用 + 符號來表示此類分支將需要非快速轉發的更新。無法判斷或宣告某個分支將以此行為在儲存庫中提供;提取的使用者必須知道這是分支的預期使用模式。
--stdin

除了作為參數提供的 refspec 外,還從 stdin 讀取 refspec,每行一個。"tag <name>" 格式不支援。

GIT URL

一般來說,URL 包含有關傳輸協定、遠端伺服器的位址和儲存庫路徑的資訊。根據傳輸協定,其中一些資訊可能會不存在。

Git 支援 ssh、git、http 和 https 協定(此外,ftp 和 ftps 可用於提取,但效率不高且已棄用;請勿使用)。

原生傳輸(即 git:// URL)不進行身分驗證,應在不安全的網路上謹慎使用。

以下語法可用於它們

  • ssh://[<user>@]<host>[:<port>]/<path-to-git-repo>

  • git://<host>[:<port>]/<path-to-git-repo>

  • http[s]://<host>[:<port>]/<path-to-git-repo>

  • ftp[s]://<host>[:<port>]/<path-to-git-repo>

另一種類似 scp 的語法也可以與 ssh 協定一起使用

  • [<user>@]<host>:/<path-to-git-repo>

只有在第一個冒號之前沒有斜線時,才會識別此語法。這有助於區分包含冒號的本機路徑。例如,本機路徑 foo:bar 可以指定為絕對路徑或 ./foo:bar,以避免被誤解為 ssh URL。

ssh 和 git 協定還支援 ~<username> 展開

  • ssh://[<user>@]<host>[:<port>]/~<user>/<path-to-git-repo>

  • git://<host>[:<port>]/~<user>/<path-to-git-repo>

  • [<user>@]<host>:~<user>/<path-to-git-repo>

對於本機儲存庫,Git 原生也支援以下語法

這兩種語法大致相同,但克隆時除外,前者表示 --local 選項。詳情請參閱 git-clone[1]

git clonegit fetchgit pull,但不包括 git push,也會接受合適的捆綁檔案。請參閱 git-bundle[1]

當 Git 不知道如何處理某個傳輸協定時,它會嘗試使用 remote-<transport> 遠端協助程式(如果存在)。若要明確請求遠端協助程式,可以使用以下語法

  • <transport>::<address>

其中 <address> 可以是路徑、伺服器和路徑,或是正在呼叫的特定遠端協助程式所識別的任意類 URL 字串。詳情請參閱 gitremote-helpers[7]

如果有大量名稱相似的遠端儲存庫,並且您想要對它們使用不同的格式(以便您使用的 URL 將被重寫為可用的 URL),您可以建立以下形式的設定區段

	[url "<actual-url-base>"]
		insteadOf = <other-url-base>

例如,使用此設定

	[url "git://git.host.xz/"]
		insteadOf = host.xz:/path/to/
		insteadOf = work:

類似 "work:repo.git" 或 "host.xz:/path/to/repo.git" 的 URL,在任何接受 URL 的上下文中都會被重寫為 "git://git.host.xz/repo.git"。

如果您只想為推送重寫 URL,可以建立以下形式的設定區段

	[url "<actual-url-base>"]
		pushInsteadOf = <other-url-base>

例如,使用此設定

	[url "ssh://example.org/"]
		pushInsteadOf = git://example.org/

類似 "git://example.org/path/to/repo.git" 的 URL,在推送時會被重寫為 "ssh://example.org/path/to/repo.git",但提取仍會使用原始 URL。

遠端

可以使用以下其中一項的名稱來代替 URL 作為 <repository> 參數

  • Git 設定檔案中的遠端:$GIT_DIR/config

  • $GIT_DIR/remotes 目錄中的檔案,或

  • $GIT_DIR/branches 目錄中的檔案。

所有這些也允許您從命令列中省略 refspec,因為它們每個都包含 git 預設使用的 refspec。

設定檔中具名的遠端

您可以選擇提供先前使用 git-remote[1]git-config[1] 或甚至是手動編輯 $GIT_DIR/config 檔案設定的遠端名稱。此遠端的 URL 將用於存取儲存庫。當您未在命令列上提供 refspec 時,此遠端的 refspec 將預設使用。設定檔案中的條目如下所示

	[remote "<name>"]
		url = <URL>
		pushurl = <pushurl>
		push = <refspec>
		fetch = <refspec>

<pushurl> 僅用於推送。它是可選的,預設值為 <URL>。推送到遠端會影響所有定義的 pushurl 或所有定義的 url(如果未定義 pushurl)。但是,如果定義了多個 url,提取將僅從第一個定義的 url 中提取。

$GIT_DIR/remotes 中具名的檔案

您可以選擇提供 $GIT_DIR/remotes 中檔案的名稱。此檔案中的 URL 將用於存取儲存庫。當您未在命令列上提供 refspec 時,此檔案中的 refspec 將用作預設值。此檔案應具有以下格式

	URL: one of the above URL formats
	Push: <refspec>
	Pull: <refspec>

Push: 行由 git push 使用,而 Pull: 行由 git pullgit fetch 使用。可以為其他分支對應指定多個 Push:Pull: 行。

$GIT_DIR/branches 中具名的檔案

您可以選擇提供 $GIT_DIR/branches 中檔案的名稱。此檔案中的 URL 將用於存取儲存庫。此檔案應具有以下格式

	<URL>#<head>

<URL> 是必需的;#<head> 是可選的。

根據操作,如果您未在命令列上提供 refspec,git 將使用以下 refspec 之一。<branch> 是此檔案在 $GIT_DIR/branches 中的名稱,而 <head> 預設為 master

git fetch 使用

	refs/heads/<head>:refs/heads/<branch>

git push 使用

	HEAD:refs/heads/<head>

已設定的遠端追蹤分支

您通常會透過定期且重複地從同一個遠端儲存庫提取來與之互動。為了追蹤此類遠端儲存庫的進度,git fetch 允許您設定 remote.<repository>.fetch 設定變數。

通常,此類變數可能如下所示

[remote "origin"]
	fetch = +refs/heads/*:refs/remotes/origin/*

此設定以兩種方式使用

  • git fetch 執行時未在命令列上指定要提取的分支和/或標籤時,例如 git fetch origingit fetch,則 remote.<repository>.fetch 值將用作 refspec — 它們指定要提取哪些 refs 以及要更新哪些本機 refs。上面的範例將提取 origin 中存在的所有分支(即任何符合值左側的 ref,refs/heads/*),並更新 refs/remotes/origin/* 階層中的相應遠端追蹤分支。

  • git fetch 執行時在命令列上明確指定要提取的分支和/或標籤時,例如 git fetch origin master,則命令列上給定的 <refspec>s 會決定要提取的內容(例如範例中的 master,它是 master: 的簡寫,而 master: 又表示「提取 master 分支,但我未在命令列中明確說明要使用它更新哪個遠端追蹤分支」),並且範例命令將僅提取 master 分支。remote.<repository>.fetch 值決定要更新哪些遠端追蹤分支(如果有的話)。以這種方式使用時,remote.<repository>.fetch 值在決定提取什麼方面沒有任何影響(即當命令列列出 refspec 時,這些值不用作 refspec);它們僅用於決定透過作為對應來提取的 refs 儲存在哪裡

可以透過在命令列上給定 --refmap=<refspec> 參數來覆蓋 remote.<repository>.fetch 值的後一種使用方式。

修剪

Git 的預設處理方式是保留資料,除非明確捨棄資料;這也擴展到保留對已在其遠端刪除這些分支的本機分支引用。

如果任其累積,這些過時的引用可能會降低具有大量分支變更的大型且繁忙儲存庫的效能,並且例如,使諸如 git branch -a --contains <commit> 之類的命令的輸出變得不必要地冗長,並且會影響任何使用已知完整引用集的其他內容。

這些遠端追蹤引用可以使用以下任一方法一次性刪除

# While fetching
$ git fetch --prune <name>

# Only prune, don't fetch
$ git remote prune <name>

若要在正常工作流程中修剪引用,而無需記住執行此操作,請在設定中全域設定 fetch.prune 或針對每個遠端設定 remote.<name>.prune。請參閱 git-config[1]

以下是事情變得棘手和更具體的地方。修剪功能實際上並不關心分支,而是根據遠端的 refspec(請參閱 <refspec> 和上面的 已設定的遠端追蹤分支)修剪本機 ←→ 遠端引用。

因此,如果遠端倉庫的 refspec 包含例如 refs/tags/*:refs/tags/*,或者您手動執行例如 git fetch --prune <名稱> "refs/tags/*:refs/tags/*",則被刪除的將不會是過時的遠端追蹤分支,而是任何遠端倉庫上不存在的本地標籤。

這可能不是您所預期的,也就是說,您想要修剪遠端 <名稱>,但也明確地從該遠端提取標籤,因此當您從該遠端提取時,您會刪除所有本地標籤,其中大多數可能一開始就不是來自 <名稱> 遠端倉庫。

因此,當使用像 refs/tags/*:refs/tags/* 這樣的 refspec,或任何其他可能將多個遠端倉庫的引用對應到同一個本機命名空間的 refspec 時,請務必小心。

由於保持與遠端倉庫上的分支和標籤同步是一種常見的使用情境,因此可以同時提供 --prune-tags 選項和 --prune 來修剪遠端倉庫上不存在的本地標籤,並強制更新那些不同的標籤。也可以在組態中使用 fetch.pruneTagsremote.<名稱>.pruneTags 來啟用標籤修剪。請參閱 git-config[1]

--prune-tags 選項等同於在遠端倉庫的 refspec 中宣告了 refs/tags/*:refs/tags/*。這可能會導致一些看似奇怪的互動。

# These both fetch tags
$ git fetch --no-tags origin 'refs/tags/*:refs/tags/*'
$ git fetch --no-tags --prune-tags origin

當在沒有 --prune 或其組態版本的情況下提供時,它不會產生錯誤的原因是為了組態版本的彈性,並保持命令列標誌的功能與組態版本的功能之間的一對一映射。

例如,在 ~/.gitconfig 中組態 fetch.pruneTags=true 是合理的,以便在執行 git fetch --prune 時修剪標籤,而不會使每次在沒有 --prune 的情況下調用 git fetch 都變成錯誤。

當提取 URL 而不是具名的遠端倉庫時,使用 --prune-tags 修剪標籤也有效。這些都將修剪 origin 上找不到的標籤。

$ git fetch origin --prune --prune-tags
$ git fetch origin --prune 'refs/tags/*:refs/tags/*'
$ git fetch <url-of-origin> --prune --prune-tags
$ git fetch <url-of-origin> --prune 'refs/tags/*:refs/tags/*'

輸出

"git fetch" 的輸出取決於使用的傳輸方法;本節描述了通過 Git 協議(本地或通過 ssh)和智慧 HTTP 協議進行提取時的輸出。

提取的狀態以表格形式輸出,每一行代表單個引用的狀態。每一行的格式如下

 <flag> <summary> <from> -> <to> [<reason>]

當使用 --porcelain 時,輸出格式旨在可由機器解析。與人類可讀的輸出格式不同,它會將內容列印到標準輸出,而不是標準錯誤。每一行的格式如下

<flag> <old-object-id> <new-object-id> <local-reference>

只有在使用 --verbose 選項時,才會顯示最新引用的狀態。

在緊湊輸出模式下,由組態變數 fetch.output 指定,如果整個 <from><to> 在另一個字串中找到,它將在另一個字串中被替換為 *。例如,master -> origin/master 變為 master -> origin/*

旗標

一個單一字元,表示引用的狀態

(空格)

表示成功提取的快速轉發;

+

表示成功的強制更新;

-

表示成功修剪的引用;

t

表示成功標籤更新;

*

表示成功提取的新引用;

!

表示被拒絕或未能更新的引用;以及

=

表示最新的且不需要提取的引用。

摘要

對於成功提取的引用,摘要以適合用作 git log 引數的形式顯示引用的舊值和新值(在大多數情況下為 <舊值>..<新值>,對於強制非快速轉發更新則為 <舊值>...<新值>)。

正在提取的遠端引用的名稱,減去其 refs/<類型>/ 字首。在刪除的情況下,遠端引用的名稱為 "(none)"。

正在更新的本地引用的名稱,減去其 refs/<類型>/ 字首。

原因

人類可讀的解釋。對於成功提取的引用,不需要解釋。對於失敗的引用,將描述失敗的原因。

範例

  • 更新遠端追蹤分支

    $ git fetch origin

    除非使用 remote.<儲存庫>.fetch 選項來指定非預設的 refspec,否則上述命令會從遠端 refs/heads/ 命名空間複製所有分支,並將其儲存到本地 refs/remotes/origin/ 命名空間。

  • 明確使用 refspec

    $ git fetch origin +seen:seen maint:tmp

    這會通過從遠端儲存庫中的 seenmaint 分支提取,更新(或在必要時建立)本地儲存庫中的 seentmp 分支。

    即使 seen 分支沒有快速轉發,也會更新該分支,因為它帶有加號字首;tmp 則不會。

  • 查看遠端倉庫的分支,而無需在本機儲存庫中組態遠端倉庫

    $ git fetch git://git.kernel.org/pub/scm/git/git.git maint
    $ git log FETCH_HEAD

    第一個命令從 git://git.kernel.org/pub/scm/git/git.git 的儲存庫中提取 maint 分支,第二個命令使用 FETCH_HEAD 來使用 git-log[1] 檢查分支。提取的物件最終將被 Git 的內建家務管理移除(請參閱 git-gc[1])。

安全性

提取和推送協議並非旨在防止一方從另一方儲存庫中竊取不打算共享的資料。如果您有需要保護免受惡意對等方侵害的私人資料,最好的選擇是將其儲存在另一個儲存庫中。這適用於客戶端和伺服器。特別是,伺服器上的命名空間對於讀取存取控制無效;您應該只授予對命名空間的讀取存取權給您信任其讀取整個儲存庫存取權的客戶端。

已知的攻擊媒介如下

  1. 受害者傳送「have」行,宣告它擁有的物件 ID,這些物件 ID 並非明確打算共享,但如果對等方也擁有它們,則可用於優化傳輸。攻擊者選擇要竊取的物件 ID X 並傳送對 X 的引用,但不需要傳送 X 的內容,因為受害者已經擁有它。現在受害者認為攻擊者擁有 X,並在稍後將 X 的內容傳送回攻擊者。(此攻擊最簡單的方法是客戶端在伺服器上執行,方法是在客戶端有權存取的命名空間中建立對 X 的引用,然後提取它。伺服器在客戶端上執行此操作最有可能的方式是將 X「合併」到公用分支中,並希望使用者在此分支上執行其他工作,然後在沒有注意到合併的情況下將其推送回伺服器。)

  2. 如同 #1,攻擊者選擇要竊取的物件 ID X。受害者傳送攻擊者已經擁有的物件 Y,而攻擊者錯誤地聲稱擁有 X 而沒有 Y,因此受害者傳送 Y 作為針對 X 的 delta。delta 向攻擊者揭示了與 Y 相似的 X 區域。

組態

本節中此行以下的所有內容都是從 git-config[1] 文件中有選擇地包含的。這些內容與在那裡找到的內容相同

fetch.recurseSubmodules

此選項控制 git fetch(以及 git pull 中的基礎提取)是否會遞迴提取到已填入的子模組中。此選項可以設定為布林值或按需。將其設定為布林值會變更 fetch 和 pull 的行為,當設定為 true 時,會無條件地遞迴進入子模組,或者當設定為 false 時,根本不會遞迴。當設定為按需時,fetch 和 pull 只有在其超專案擷取更新子模組參考的提交時,才會遞迴進入已填入的子模組。預設為按需,或者如果已設定,則為 *submodule.recurse* 的值。

fetch.fsckObjects

如果設定為 true,則 git-fetch-pack 將檢查所有提取的物件。請參閱 transfer.fsckObjects 以瞭解檢查的內容。預設值為 false。如果未設定,則改為使用 transfer.fsckObjects 的值。

fetch.fsck.<msg-id>

行為類似於 fsck.<msg-id>,但由 git-fetch-pack[1] 而非 git-fsck[1] 使用。請參閱 fsck.<msg-id> 文件以瞭解詳細資訊。

fetch.fsck.skipList

行為類似於 fsck.skipList,但由 git-fetch-pack[1] 而非 git-fsck[1] 使用。請參閱 fsck.skipList 文件以瞭解詳細資訊。

fetch.unpackLimit

如果通過 Git 原生傳輸提取的物件數量低於此限制,則物件將解壓縮為鬆散物件檔案。但是,如果接收的物件數量等於或超過此限制,則在新增任何遺失的 delta 基底之後,接收的封包將儲存為封包。從推送儲存封包可以使推送操作更快地完成,尤其是在慢速檔案系統上。如果未設定,則改為使用 transfer.unpackLimit 的值。

fetch.prune

如果為 true,則 fetch 會自動表現得好像在命令列上給定了 --prune 選項一樣。另請參閱 remote.<名稱>.prunegit-fetch[1] 的修剪章節。

fetch.pruneTags

如果為 true,則在修剪時,fetch 會自動表現得好像已提供 refs/tags/*:refs/tags/* refspec,如果尚未設定。這允許同時設定此選項和 fetch.prune,以維持與上游引用的一對一映射。另請參閱 remote.<名稱>.pruneTagsgit-fetch[1] 的修剪章節。

fetch.all

如果為 true,則 fetch 將嘗試更新所有可用的遠端倉庫。可以通過傳遞 --no-all 或明確指定一個或多個要從中提取的遠端倉庫來覆寫此行為。預設值為 false。

fetch.output

控制如何列印引用更新狀態。有效值為 fullcompact。預設值為 full。請參閱 git-fetch[1] 中的輸出章節以瞭解詳細資訊。

fetch.negotiationAlgorithm

控制在協商要由伺服器傳送的封包檔案的內容時,如何傳送有關本機儲存庫中提交的資訊。設定為 "consecutive" 以使用一種遍歷連續提交並檢查每個提交的演算法。設定為 "skipping" 以使用一種跳過提交的演算法,以加快收斂速度,但可能會導致大於必要的封包檔案;或者設定為 "noop" 以完全不傳送任何資訊,這幾乎肯定會導致大於必要的封包檔案,但會跳過協商步驟。設定為 "default" 以覆寫先前所做的設定並使用預設行為。預設通常為 "consecutive",但如果 feature.experimental 為 true,則預設為 "skipping"。未知的值將導致 git fetch 發生錯誤。

另請參閱 git-fetch[1]--negotiate-only--negotiation-tip 選項。

fetch.showForcedUpdates

設定為 false 以在 git-fetch[1]git-pull[1] 命令中啟用 --no-show-forced-updates。預設值為 true。

fetch.parallel

指定一次並行執行的提取操作的最大數量(子模組,或當 git-fetch[1]--multiple 選項生效時的遠端倉庫)。

若設定為 0,將會使用一些合理的預設值。若未設定,則預設為 1。

對於子模組,此設定可以使用 submodule.fetchJobs 設定覆寫。

fetch.writeCommitGraph

設定為 true 可在每次 git fetch 命令從遠端下載 pack-file 後寫入 commit-graph。使用 --split 選項,大多數執行會於現有的 commit-graph 檔案之上建立一個非常小的 commit-graph 檔案。偶爾,這些檔案會合併,寫入時間可能會較長。擁有更新的 commit-graph 檔案有助於許多 Git 命令的效能,包括 git merge-basegit push -fgit log --graph。預設為 false。

fetch.bundleURI

此值儲存一個 URI,用於在從原始 Git 伺服器執行增量提取之前,從 bundle URI 下載 Git 物件資料。這類似於 git-clone[1]--bundle-uri 選項的行為。如果提供的 bundle URI 包含為增量提取而組織的 bundle 列表,則 git clone --bundle-uri 將設定 fetch.bundleURI 值。

如果您修改此值,並且您的儲存庫具有 fetch.bundleCreationToken 值,請在從新的 bundle URI 提取之前移除該 fetch.bundleCreationToken 值。

fetch.bundleCreationToken

當使用 fetch.bundleURI 從使用 "creationToken" 啟發式方法的 bundle 列表進行增量提取時,此設定值會儲存已下載 bundle 的最大 creationToken 值。此值用於防止在未來下載宣告的 creationToken 並非嚴格大於此值的 bundle。

creation token 值由提供特定 bundle URI 的提供者選擇。如果您修改 fetch.bundleURI 上的 URI,請務必在提取之前移除 fetch.bundleCreationToken 值。

錯誤

使用 --recurse-submodules 只能提取本地存在的子模組中的新 commit,例如在 $GIT_DIR/modules/ 中。如果上游新增了新的子模組,則必須先克隆該子模組(例如使用 git submodule update)才能提取它。預計將在未來的 Git 版本中修復此問題。

另請參閱

GIT

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

scroll-to-top