English ▾ 主題 ▾ 最新版本 ▾ git-pull 最後更新於 2.55.0

名稱

git-pull - 從另一個儲存庫或本地分支獲取並整合

概要

git pull [<options>] [<repository> [<refspec>…​]]

描述

將遠端儲存庫的變更整合至目前分支。

首先,git pull 會執行與輸入參數相同(排除合併選項)的 git fetch 指令,以獲取遠端分支。接著,它會決定要整合哪個遠端分支:如果您在執行 git pull 時沒有輸入任何參數,預設會使用目前分支的 上游 (upstream) 分支。然後,它會將該分支整合至目前分支。

整合遠端分支主要有 4 種選項

  1. git pull --ff-only 將僅執行「快轉」(fast-forward) 更新:如果您的本地分支與遠端分支分歧,此操作將會失敗。這是預設行為。

  2. git pull --rebase 會執行 git rebase

  3. git pull --no-rebase 會執行 git merge

  4. git pull --squash 會執行 git merge --squash

您也可以透過設定組態選項 pull.rebasepull.squashpull.ff 來設定您偏好的行為。

如果在合併或重定基底 (rebase) 過程中發生您不想處理的合併衝突,您可以安全地使用 git merge --abortgit rebase --abort 來中止操作。

選項

<repository>

要拉取的「遠端」儲存庫。這可以是一個 URL(請參閱下方的 GIT URLS 章節)或是遠端名稱(請參閱下方的 REMOTES 章節)。

預設為目前分支所設定的上游 (upstream),或是 origin。請參閱下方的 UPSTREAM BRANCHES 以了解如何設定上游。

<refspec>

要獲取並整合至目前分支的分支或其他參照,例如在 git pull origin main 中的 main。預設為目前分支所設定的上游分支。

這可以是一個分支、標籤或其他參照集合。請參閱下方「與獲取相關的選項」中的 <refspec> 以了解完整語法,並參閱下方的 DEFAULT BEHAVIOUR 以了解 git pull 如何使用此參數來決定要整合哪個遠端分支。

-q
--quiet

此選項會傳遞給底層的 git-fetch 以在傳輸過程中靜默輸出,並傳遞給底層的 git-merge 以在合併過程中靜默輸出。

-v
--verbose

--verbose 傳遞給 git-fetch 與 git-merge。

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

此選項控制是否應獲取已部署子模組 (submodules) 的新提交,以及是否同時更新作用中子模組的工作樹(請參閱 git-fetch[1]git-config[1]gitmodules[5])。

如果透過重定基底 (rebase) 進行檢出,本地子模組的提交也會隨之重定基底。

如果透過合併進行更新,子模組的衝突會被解決並檢出。

--commit
--no-commit

執行合併並提交結果。此選項可用來覆寫 --no-commit。僅在合併時有效。

使用 --no-commit 執行合併並在建立合併提交之前停止,讓使用者有機會在提交前檢查並調整合併結果。

請注意,快轉更新不會建立合併提交,因此無法透過 --no-commit 來停止這類合併。因此,若您想確保您的分支不會被合併指令變更或更新,請使用 --no-ff 搭配 --no-commit

--edit
-e
--no-edit

在提交自動生成的合併訊息前呼叫編輯器,讓使用者進一步編輯訊息,說明並佐證該合併。使用 --no-edit 選項則可接受自動生成的訊息(一般不建議如此做)。

較舊的腳本可能依賴於不允許使用者編輯合併日誌訊息的歷史行為。當執行 git merge 時,他們會看到編輯器開啟。為了更容易將這類腳本調整為符合更新後的行為,可在腳本開頭將環境變數 GIT_MERGE_AUTOEDIT 設為 no

--cleanup=<mode>

此選項決定合併訊息在提交前如何進行清理。詳情請參閱 git-commit[1]。此外,若 <mode> 的值設為 scissors,則在合併衝突時,剪刀符號將被附加至 MERGE_MSG,之後再傳遞給提交機制。

--ff-only

僅在沒有分歧的本地歷史紀錄時才更新至新歷史紀錄。若未提供協調分歧歷史紀錄的方法(透過 --rebase 旗標),這是預設行為。

--ff
--no-ff

當進行合併而非重定基底時,指定當合併入的歷史紀錄已是目前歷史紀錄的後代時,應如何處理合併。如果請求合併,--ff 是預設值,除非合併的是一個未儲存在 refs/tags/ 層級自然位置的附註(且可能已簽署)標籤,在這種情況下會假定為 --no-ff

使用 --ff 時,盡可能以快轉方式解決合併(僅更新分支指標以符合已合併的分支;不建立合併提交)。如果不可能(當合併入的歷史紀錄不是目前歷史紀錄的後代時),則建立一個合併提交。

使用 --no-ff 時,在所有情況下均建立合併提交,即使該合併原本可以以快轉方式解決。

-S[<key-id>]
--gpg-sign[=<key-id>]
--no-gpg-sign

對產生的合併提交進行 GPG 簽署。<key-id> 參數是選填的,預設為提交者身分;如果指定了該參數,它必須緊接在選項後,且不得有空格。--no-gpg-sign 可用來撤銷組態變數 commit.gpgSign 或先前的 --gpg-sign 設定。

--log[=<n>]
--no-log

除了分支名稱外,將最多 <n> 個實際被合併的提交之單行描述填入日誌訊息中。亦請參閱 git-fmt-merge-msg[1]。僅在合併時有效。

使用 --no-log 則不列出實際被合併提交的單行描述。

--signoff
--no-signoff

在提交日誌訊息末尾由提交者新增一個 Signed-off-by 結尾。簽署的含義取決於您提交的專案。例如,它可以證明提交者有權在專案許可證下提交作品,或者同意某些貢獻者聲明,例如開發者來源證明 (DCO)。(有關 Linux 核心和 Git 專案使用的證明,請參閱 https://developercertificate.org。)請查閱您貢獻的專案的說明文件或領導層,以瞭解在該專案中如何使用簽署。

--no-signoff 選項可用於撤銷指令列中先前的 --signoff 選項。

Git 沒有(且將不會有)設定變數來預設啟用 --signoff 命令列選項;詳情請參閱 gitfaq[7] 中的 commit.signoff 條目。

--stat
-n
--no-stat

在合併結束時顯示 diffstat。diffstat 也受組態選項 merge.stat 控制。

使用 -n--no-stat 時,不顯示合併結束時的 diffstat。

--compact-summary

在合併結束時顯示精簡摘要 (compact-summary)。

--squash
--no-squash

產生工作樹與索引狀態,就如同真正進行了一次合併(除了合併資訊外),但實際上不進行提交、不移動 HEAD,也不記錄 $GIT_DIR/MERGE_HEAD(這會導致下一次 git commit 指令建立一個合併提交)。這讓您能夠在目前分支上建立單一提交,其效果等於合併了另一個分支(如果是 Octopus 合併則為多個)。

使用 --no-squash 則執行合併並提交結果。此選項可用來覆寫 --squash

使用 --squash 時,不允許同時使用 --commit,否則會失敗。

僅在合併時有效。

--verify
--no-verify

預設會執行 pre-merge 與 commit-msg 鉤子。當給定 --no-verify 時,這些鉤子會被繞過。亦請參閱 githooks[5]。僅在合併時有效。

-s <strategy>
--strategy=<strategy>

使用指定的合併策略;可多次提供以指定嘗試順序。如果沒有 -s 選項,則使用內建的策略清單(合併單一頭部時使用 ort,否則使用 octopus)。

-X <option>
--strategy-option=<option>

將特定合併策略的選項傳遞給合併策略。

--verify-signatures
--no-verify-signatures

驗證被合併分支的尖端提交是否以有效的金鑰簽署,即一個具有有效 uid 的金鑰:在預設信任模型中,這意味著簽署金鑰已被受信任的金鑰所簽署。如果被合併分支的尖端提交未以有效金鑰簽署,合併將被中止。

僅在合併時有效。

--summary
--no-summary

--stat--no-stat 的同義詞;這些已被棄用,將在未來版本中移除。

--autostash
--no-autostash

在操作開始前自動建立一個臨時 stash 條目,記錄在參照 MERGE_AUTOSTASH 中,並在操作結束後套用。這意味著您可以在髒污的工作樹上執行此操作。然而,請小心使用:成功合併後最終的 stash 套用可能會導致非平庸的衝突。

--allow-unrelated-histories

預設情況下,git merge 指令會拒絕合併沒有共同祖先的歷史紀錄。此選項可用於合併兩個獨立啟動的專案歷史紀錄時,覆寫此安全措施。由於這種情況非常罕見,因此沒有也不會新增任何組態變數來預設啟用此功能。

僅在合併時有效。

-r
--rebase[=(true|merges|false|interactive)]
true

獲取後,將目前分支重定基底至上游分支之上。如果存在對應於上游分支的遠端追蹤分支,且上游分支自上次獲取後已被重定基底,則重定基底過程會使用該資訊以避免對非本地變更進行重定基底。這是預設行為。

merges

使用 git rebase --rebase-merges 進行重定基底,以便將本地合併提交包含在重定基底中(詳情請參閱 git-rebase[1])。

false

將上游分支合併至目前分支。

interactive

啟用互動式重定基底模式。

如果您希望使 git pull 總是使用 --rebase 而非合併,請參閱 git-config[1] 中的 pull.rebasebranch.<name>.rebasebranch.autoSetupRebase

+

注意
這是一種具有潛在危險的操作模式。它會重寫歷史紀錄,如果您已經發布了該歷史紀錄,這並不是個好主意。除非您已仔細閱讀 git-rebase[1],否則請使用此選項。
--no-rebase

這是 --rebase=false 的簡寫。

--all
--no-all

獲取所有遠端儲存庫,但已設定 remote.<name>.skipFetchAll 組態變數的除外。此選項會覆寫 fetch.all 組態變數。

-a
--append

將已獲取的參照名稱與物件名稱附加至 .git/FETCH_HEAD 的現有內容中。若無此選項,.git/FETCH_HEAD 中的舊資料將會被覆寫。

--atomic

使用原子交易來更新本地參照。要麼所有參照都成功更新,要麼在出錯時一個參照也不會更新。

--depth=<depth>

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

--deepen=<depth>

--depth 類似,只是它指定的是從目前的淺層邊界起算的提交數量,而非從每個遠端分支歷史紀錄的頂端起算。

--shallow-since=<date>

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

--shallow-exclude=<ref>

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

--unshallow

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

如果來源儲存庫是淺層的,則盡可能獲取更多資料,以使目前儲存庫擁有與來源儲存庫相同的歷史紀錄。

--update-shallow

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

--negotiation-restrict=(<commit>|<glob>)
--negotiation-tip=(<commit>|<glob>)

預設情況下,Git 會向伺服器報告所有可從本地參照到達的提交,以尋找共同的提交,進而嘗試縮減即將接收的 packfile 大小。若有指定,Git 將僅報告可從給定尖端到達的提交。當使用者知道哪個本地參照可能與即將獲取的上游參照有共同提交時,這對於加速獲取非常有用。

--negotiation-restrict 是此選項的首選名稱;--negotiation-tip 也被視為同義詞。

此選項可指定多次;若是如此,Git 將報告可從給定提交中任一者到達的提交。

此選項的參數可以是參照名稱的 glob 模式、參照,或是提交的(可能經簡寫的)SHA-1。指定一個 glob 等同於多次指定此選項,每個匹配的參照名稱一次。

另請參閱 git-config[1] 中記錄的 fetch.negotiationAlgorithmpush.negotiate 組態變數,以及下方的 --negotiate-only 選項。

--negotiation-include=(<commit>|<glob>)

確保給定尖端的提交在獲取協商期間總是作為「have」行發送,無論協商演算法選擇了什麼。這對於保證可從特定參照到達的共同歷史紀錄總是被考慮是非常有用的,即使當 --negotiation-restrict 限制了尖端集合,或當協商演算法本來會跳過它們時。

此選項可指定多次;若是如此,每個提交都會被無條件發送。

參數可以是確切的參照名稱(例如 refs/heads/release)、物件雜湊值,或是 glob 模式(例如 refs/heads/release/{asterisk})。模式語法與 --negotiation-restrict 相同。

如果使用了 --negotiation-restrict,have 集合會先被該選項限制,然後再擴充以包含由 --negotiation-include 指定的尖端。

如果在命令列中未指定此選項,則使用目前遠端的任何 remote.<name>.negotiationInclude 組態值。

--negotiate-only

不從伺服器獲取任何東西,而是列印所提供 --negotiation-restrict= 參數的祖先,這些是我們與伺服器共有的。

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

--dry-run

顯示將會進行的操作,但不實際執行任何變更。

--porcelain

以易於腳本解析的格式將輸出列印至標準輸出。詳情請參閱 git-fetch[1] 中的 OUTPUT 章節。

這與 --recurse-submodules=(yes|on-demand) 不相容,且優先於 fetch.output 組態選項。

--filter=<filter-spec>

使用部分複製 (partial clone) 功能,並要求伺服器根據給定的物件過濾器發送可達物件的子集。當使用 --filter 時,所提供的 <filter-spec> 用於部分獲取。

如果使用了 --filter=auto,過濾規格會透過結合伺服器針對客戶端接受的 promisor 遠端所宣告的過濾規格來自動決定(請參閱 gitprotocol-v2[5] 以及 git-config[1] 中的 promisor.acceptFromServer 組態選項)。

有關所有其他可用過濾規格的詳細資訊,請參閱 git-rev-list[1] 中的 --filter=<filter-spec> 選項。

例如,--filter=blob:none 將過濾掉所有大型二進位物件 (blobs,即檔案內容),直到 Git 需要時為止。此外,--filter=blob:limit=<size> 將過濾掉所有大小至少為 <size> 的 blob。

-f
--force

git fetch<src>:<dst> refspec 一起使用時,它可能會拒絕更新本地分支,如 git-fetch[1] 文件中 <refspec> 部分所討論。此選項會覆寫該檢查。

-k
--keep

保留已下載的封裝檔。

--prefetch

修改已設定的 refspec,將所有參照放入 refs/prefetch/ 命名空間。請參閱 git-maintenance[1] 中的 prefetch 任務。

-p
--prune

在獲取之前,移除所有在遠端上已不存在的遠端追蹤參照。如果標籤僅因為預設的標籤自動追蹤或由於 --tags 選項而被獲取,它們不受修剪影響。然而,如果標籤是由於顯式的 refspec 而被獲取(無論是在命令列還是在遠端組態中,例如如果遠端是使用 --mirror 選項複製的),那麼它們也受修剪影響。提供 --prune-tags 是提供標籤 refspec 的簡寫。

--no-tags

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

--refmap=<refspec>

當獲取命令列上列出的參照時,使用指定的 refspec(可多次給定)將參照映射到遠端追蹤分支,而不是使用遠端儲存庫的 remote.<name>.fetch 組態變數的值。向 --refmap 選項提供空的 <refspec> 會導致 Git 忽略已組態的 refspec,並完全依賴作為命令列參數提供的 refspec。詳情請參閱「已組態的遠端追蹤分支」章節。

-t
--tags

獲取遠端的所有標籤(即將遠端標籤 refs/tags/* 獲取為具有相同名稱的本地標籤),除了原本就會被獲取的內容之外。僅使用此選項不會使標籤受到修剪影響,即使使用了 --prune 也是如此(儘管如果標籤同時是顯式 refspec 的目的地,它們仍可能被修剪;請參閱 --prune)。

-j <n>
--jobs=<n>

並行執行所有形式的獲取,每次最多 <n> 個作業。

值為 0 將使用合理的預設值。

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

通常,並行的遞迴獲取與多遠端獲取會更快。預設情況下,獲取是循序進行的,而非並行。

--set-upstream

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

--upload-pack <upload-pack>

當給定該選項,且要獲取的儲存庫是由 git fetch-pack 處理時,--exec=<upload-pack> 會被傳遞給指令,以指定在遠端執行之指令的非預設路徑。

--progress

當標準錯誤串流連接到終端時,預設會報告進度狀態,除非指定了 -q。即使標準錯誤串流未導向終端,此標記也會強制顯示進度狀態。

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

使用協定第 2 版通訊時,將給定的字串傳輸到伺服器。給定的字串不得包含 NULLF 字元。伺服器對伺服器選項(包括未知選項)的處理是特定於伺服器的。當提供多個 --server-option=<option> 時,它們會按照在命令列上列出的順序全部發送到另一端。當命令列未提供 --server-option=<option> 時,將改用設定變數 remote.<name>.serverOption 的值。

--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 章節)。

<refspec>

指定要獲取的參照以及要更新的本地參照。當命令列上未出現 <refspec> 時,要獲取的參照會改為從 remote.<repository>.fetch 變數讀取(請參閱 git-fetch[1] 中的「已組態的遠端追蹤分支」章節)。

<refspec> 參數的格式為選填的加號 +,後接來源 <src>,後接冒號 :,後接目的地 <dst>。當 <dst> 為空時,可以省略冒號。<src> 通常是一個參照,或是帶有單一 * 的 glob 模式,用來匹配一組參照,但也可以是完整拼寫的 hex 物件名稱。

<refspec><src> 中可包含一個 * 以表示簡單的模式匹配。此類 refspec 的功能類似於 glob,可匹配任何符合模式的參照。模式化的 <refspec> 必須在 <src><dst> 中都有且僅有一個 *。它會透過將 <src> 匹配到的內容替換掉 * 來將參照映射至目的地。

如果 refspec 以 ^ 為前綴,它將被解釋為負向 refspec。與指定要獲取哪些參照或更新哪些本地參照不同,此類 refspec 將指定要排除的參照。如果一個參照至少匹配一個正向 refspec 且不匹配任何負向 refspec,則視為匹配。負向 refspec 可用於限制模式 refspec 的範圍,使其不包含特定參照。負向 refspec 本身也可以是模式 refspec。然而,它們只能包含 <src>,且不能指定 <dst>。完整拼寫的 hex 物件名稱也不支援。

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

會獲取符合 <src> 的遠端參照,如果 <dst> 不是空字串,則會嘗試更新符合它的本地參照。

是否在沒有 --force 的情況下允許此類更新,取決於其獲取到的參照命名空間、獲取的物件類型,以及該更新是否被視為快轉。通常,獲取的規則與推送時相同,詳情請參閱 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/* 命名空間都不會接受非提交物件。

注意
當您想要獲取的遠端分支已知會定期倒回並重定基底時,其新尖端預計不會成為其先前尖端(即您上次獲取時儲存在遠端追蹤分支中的尖端)的後代。您會希望使用 + 號來表示此類分支需要非快轉的更新。沒有方法可以確定或宣告一個分支將以這種行為在儲存庫中提供;拉取的使用者必須單純知道這就是該分支預期的使用模式。
注意
git pull 命令列上直接列出多個 <refspec> 與為一個 <repository> 在組態中有多個 remote.<repository>.fetch 項目並執行不帶任何顯式 <refspec> 參數的 git pull 指令之間是有區別的。明確列在命令列上的 <refspec> 在獲取後總是會合併到目前分支。換句話說,如果您列出多於一個遠端參照,git pull 將建立一個 Octopus 合併。另一方面,如果您在命令列上沒有列出任何顯式的 <refspec> 參數,git pull 將獲取它在 remote.<repository>.fetch 組態中找到的所有 <refspec>,並僅將找到的第一個 <refspec> 合併到目前分支。這是因為從遠端參照製作 Octopus 合併的情況很少見,而透過一次獲取多個參照來追蹤多個遠端頭部則通常很有用。

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 原生支援的本地儲存庫,可以使用以下語法:

  • /path/to/repo.git/

  • file:///path/to/repo.git/

這兩種語法基本等價,除了在複製時,前者隱含了 --local 選項。詳情請參閱 git-clone[1]

git clonegit fetchgit pull(但不是 git push)也接受適當的 bundle 檔案。請參閱 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。

遠端 (REMOTES)

下列各項之一的名稱可用於代替 <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,如果沒有定義 pushurl,則影響所有定義的 url。然而,如果定義了多個 url,擷取 (fetch) 僅會從第一個定義的 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 中的分支可以選擇性地擁有一個上游遠端分支。Git 預設在遠端操作中使用上游分支,例如:

  • 它是無參數 git pullgit fetch 的預設值。

  • 它是無參數 git push 的預設值(有一些例外)。例如,您可以使用 branch.<name>.pushRemote 選項推送到與拉取來源不同的遠端,而且預設情況下在 push.default=simple 時,您設定的上游分支必須具有相同名稱。

  • 各種命令(包括 git checkoutgit status)將顯示自從您分叉以來,目前分支和上游分支各自增加了多少個提交,例如 "Your branch and origin/main have diverged, and have 2 and 3 different commits each respectively"(您的分支與 origin/main 已分叉,且分別有 2 個和 3 個不同的提交)。

上游儲存在 .git/config 的 "remote" 和 "merge" 欄位中。例如,如果 main 的上游是 origin/main

[branch "main"]
   remote = origin
   merge = refs/heads/main

您可以透過 git push --set-upstream <remote> <branch> 顯式設定上游分支,但 Git 通常會自動為您設定上游,例如:

  • 當您複製儲存庫時,Git 會自動為預設分支設定上游。

  • 如果您設定了 push.autoSetupRemote 設定選項,git push 會在您第一次推送分支時自動設定上游。

  • 使用 git checkout <branch> 切換到一個遠端追蹤分支,會自動建立一個同名的本地分支並將其上游設定為該遠端分支。

注意
上游分支有時被稱為「追蹤資訊」,如「設定分支的追蹤資訊」。

合併策略

合併機制(git mergegit pull 命令)允許透過 -s 選項選擇後端 合併策略。某些策略還可以接受自己的選項,這些選項可以透過向 git merge 和/或 git pull 提供 -X<option> 參數來傳遞。

ort

這是拉取 (pull) 或合併單一分支時的預設合併策略。此策略僅能使用三方合併演算法解決兩個分支頭 (heads)。當有多個可用於三方合併的共同祖先時,它會建立一個共同祖先的合併樹,並將其用作三方合併的參考樹。根據在 Linux 2.6 核心開發歷史中的實際合併提交進行的測試,據報此方法產生的合併衝突較少,且不會導致錯誤合併。此外,此策略可以偵測並處理涉及重新命名的合併。它不使用偵測到的複製。此演算法的名稱是一個縮寫(「Ostensibly Recursive’s Twin」,意為表面上是遞迴策略的孿生兄弟),因為它是作為先前預設演算法 recursive 的替代方案而編寫的。

在路徑為子模組的情況下,如果合併的一側所使用的子模組提交是另一側所使用提交的後代,Git 會嘗試快速前進到該後代。否則,Git 會將此情況視為衝突,並建議使用一個同時是衝突提交之後代的子模組提交(如果存在)作為解決方案。

ort 策略可以接受以下選項:

ours

此選項強制偏向 our (我方) 版本以自動乾淨地解決衝突區塊。來自另一棵樹但不與我方衝突的更改會反映在合併結果中。對於二進位檔案,整個內容都取自我方。

這不應與 ours 合併策略混淆,後者甚至根本不查看另一棵樹的內容。它會丟棄另一棵樹所做的所有事情,宣稱 our 歷史已包含其中發生的所有事情。

theirs

這與 ours 相對;請注意,與 ours 不同,沒有 theirs 合併策略會與此合併選項混淆。

ignore-space-change
ignore-all-space
ignore-space-at-eol
ignore-cr-at-eol

為了進行三方合併,將具有指定類型空白變更的行視為未更改。混合有其他更改的空白變更不會被忽略。另請參閱 git-diff[1] -b-w--ignore-space-at-eol--ignore-cr-at-eol

  • 如果 their 版本僅在行中引入空白變更,則使用 our 版本;

  • 如果 our 版本引入空白變更,但 their 版本包含實質性更改,則使用 their 版本;

  • 否則,合併將以通常的方式進行。

renormalize

這會對需要三方合併的任何檔案的所有三個階段進行虛擬檢出和檢入。此選項旨在於合併具有不同 clean 過濾器或行尾標準化規則的分支時使用。詳情請參閱 gitattributes[5] 中的「合併具有不同檢入/檢出屬性的分支」。

no-renormalize

停用 renormalize 選項。這會覆蓋 merge.renormalize 設定變數。

find-renames[=<n>]

開啟重新命名偵測,並可選擇設定相似度閾值。這是預設行為。這會覆蓋 merge.renames 設定變數。另請參閱 git-diff[1] --find-renames

rename-threshold=<n>

find-renames=<n> 的已棄用同義詞。

no-renames

關閉重新命名偵測。這會覆蓋 merge.renames 設定變數。另請參閱 git-diff[1] --no-renames

histogram

diff-algorithm=histogram 的已棄用同義詞。

patience

diff-algorithm=patience 的已棄用同義詞。

diff-algorithm=(histogram|minimal|myers|patience)

合併時使用不同的差異演算法,這有助於避免因不重要的匹配行(如來自不同函式的大括號)而發生的錯誤合併。另請參閱 git-diff[1] --diff-algorithm。請注意,ort 預設為 diff-algorithm=histogram,而一般的差異比較目前預設為 diff.algorithm 設定。

subtree[=<path>]

此選項是 subtree 策略的一種進階形式,該策略會猜測合併時兩棵樹必須如何移動才能相互匹配。相反,指定的路徑會被加上前綴(或從開頭去除),以使兩棵樹的形狀匹配。

recursive

這現在是 ort 的同義詞。在 v2.49.0 之前,它是一個替代實作,但在 v2.50.0 中被重新導向為 ort。先前的遞迴 (recursive) 策略是從 Git v0.99.9k 到 v2.33.0 解決兩個分支頭的預設策略。

resolve

此策略僅能使用三方合併演算法解決兩個分支頭(即目前分支和您拉取的另一個分支)。它嘗試仔細偵測交叉合併的歧義。它不處理重新命名。

octopus

這可以解決兩個以上分支頭的情況,但拒絕執行需要手動解決的複雜合併。它主要用於將多個主題分支頭捆綁在一起。這是拉取或合併多個分支時的預設合併策略。

ours

這可以解決任意數量的分支頭,但合併後產生的樹始終是目前分支頭的樹,實際上忽略了來自所有其他分支的所有更改。它旨在用於取代舊的側支開發歷史。請注意,這與 ort 合併策略的 -Xours 選項不同。

subtree

這是一個修改後的 ort 策略。合併樹 A 和 B 時,如果 B 對應於 A 的子樹,則首先調整 B 以匹配 A 的樹結構,而不是在同一層級讀取樹。這種調整也會對共同祖先樹進行。

對於使用三方合併的策略(包括預設的 ort),如果在兩個分支上都做了更改,但後來在其中一個分支上還原了該更改,則合併結果中將存在該更改;有些人覺得這種行為很令人困惑。這是因為執行合併時只考慮分支頭和合併基底,而不考慮單個提交。因此,合併演算法將還原的更改視為完全沒有更改,並代之以更改後的版本。

預設行為

人們經常在不給予任何參數的情況下使用 git pull。傳統上,這等同於說 git pull origin。然而,當在分支 <name> 上時,如果存在組態 branch.<name>.remote,則使用該值而非 origin

為了決定要使用什麼 URL 來進行獲取,會查閱組態 remote.<origin>.url 的值;如果沒有這樣的變數,則使用 $GIT_DIR/remotes/<origin>URL: 行上的值。

為了決定當指令在沒有任何 refspec 參數的情況下執行時要獲取哪些遠端分支(並選擇性地儲存在遠端追蹤分支中),會查閱組態變數 remote.<origin>.fetch 的值;如果沒有,則查閱 $GIT_DIR/remotes/<origin> 並使用其 Pull: 行。除了 OPTIONS 章節中描述的 refspec 格式外,您也可以使用類似這樣的 globbing refspec

refs/heads/*:refs/remotes/origin/*

Globbing refspec 必須具有非空的 RHS(即必須將獲取的內容儲存在遠端追蹤分支中),且其 LHS 與 RHS 必須以 /* 結尾。上述指定了所有遠端分支皆使用 refs/remotes/origin/ 層級下相同名稱的遠端追蹤分支進行追蹤。

為了不破壞向後相容性,決定獲取後要合併哪個遠端分支的規則有點複雜。

如果在 git pull 的命令列上給定了顯式的 refspec,則全部都會被合併。

當命令列上未給定 refspec 時,git pull 會使用來自組態或 $GIT_DIR/remotes/<origin> 的 refspec。在這種情況下,適用下列規則

  1. 如果目前分支 <name> 存在 branch.<name>.merge 組態,這就是遠端站點上被合併的分支名稱。

  2. 如果 refspec 是 globbing 的,則不會合併任何內容。

  3. 否則,合併第一個 refspec 的遠端分支。

範例

  • 更新您所複製儲存庫的遠端追蹤分支,然後將其中一個合併到您的目前分支

    $ git pull
    $ git pull origin

    通常合併進來的是遠端儲存庫的 HEAD,但選擇是由 branch.<name>.remotebranch.<name>.merge 選項決定的;詳情請參閱 git-config[1]

  • 將遠端分支 next 合併到目前分支

    $ git pull origin next

    這會在 FETCH_HEAD 中暫時留下一份 next 的副本,並更新遠端追蹤分支 origin/next。透過呼叫 fetch 與 merge 也可以完成相同的操作

    $ git fetch origin
    $ git merge origin/next

如果您嘗試的拉取導致了複雜的衝突並希望重新開始,可以使用 git reset 來恢復。

安全性

擷取 (fetch) 和推送協並非設計用於防止一側從另一儲存庫竊取不打算共享的數據。如果您有需要保護免受惡意同行侵害的私有數據,最好的選擇是將其儲存在另一個儲存庫中。這適用於客戶端和伺服器。特別是,伺服器上的命名空間對於讀取存取控制無效;您只應向信任其具有整個儲存庫讀取權限的客戶端授予對命名空間的讀取權限。

已知的攻擊向量如下:

  1. 受害者發送 "have" 行,宣傳其擁有的、並非明確打算共享但如果同行也擁有則可用於優化傳輸的物件 ID。攻擊者選擇一個要竊取的物件 ID X 並發送一個指向 X 的參照,但不需要發送 X 的內容,因為受害者已經擁有它。現在受害者相信攻擊者擁有 X,稍後它會將 X 的內容發送回給攻擊者。(這種攻擊對於客戶端在伺服器上執行最為直接,即在客戶端有權存取的命名空間中建立一個指向 X 的參照,然後擷取它。伺服器在客戶端上執行此操作的最可能方式是將 X「合併」到公共分支中,並希望使用者在該分支上進行額外工作並將其推回伺服器而未察覺合併。)

  2. 與第 1 點相同,攻擊者選擇一個要竊取的物件 ID X。受害者發送一個攻擊者已經擁有的物件 Y,而攻擊者虛假聲稱擁有 X 而不擁有 Y,因此受害者將 Y 作為針對 X 的差異 (delta) 發送。該差異向攻擊者揭示了 X 中與 Y 相似的區域。

錯誤 (BUGS)

目前使用 --recurse-submodules 只能獲取已檢出子模組中的新提交。例如,當上游在剛獲取的超級專案提交中新增了一個新的子模組時,子模組本身無法被獲取,使得之後無法在不重新執行 fetch 的情況下檢出該子模組。此問題預計在未來的 Git 版本中修復。

GIT

git[1] 套件的一部分