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

名稱

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

概要

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

描述

將遠端儲存庫的變更整合到目前分支。如果目前分支落後於遠端分支,則預設會快速轉送目前分支以符合遠端分支。如果目前分支與遠端分支發生分歧,使用者需要指定如何使用 --rebase--no-rebase(或 pull.rebase 中的對應設定選項)來調和分歧的分支。

更精確地說,git pull 會使用指定的參數執行 git fetch,然後根據設定選項或命令列旗標,呼叫 git rebasegit merge 來調和分歧的分支。

<repository> 應該是傳遞給 git-fetch[1] 的遠端儲存庫名稱。<refspec> 可以命名任意遠端參考(例如,標籤名稱),甚至是具有對應遠端追蹤分支的參考集合(例如,refs/heads/*:refs/remotes/origin/*),但通常它是遠端儲存庫中分支的名稱。

<repository> 和 <branch> 的預設值是從目前分支的「remote」和「merge」設定中讀取,這是由 git-branch[1] --track 所設定的。

假設存在以下歷史記錄,且目前分支為「master

	  A---B---C master on origin
	 /
    D---E---F---G master
	^
	origin/master in your repository

然後,「git pull」會提取並重播自遠端 master 分支與本機 master(即 E)分歧以來的變更,直到其目前的提交 (C) 位於 master 之上,並將結果記錄在新的提交中,同時記錄兩個父提交的名稱,以及使用者描述變更的記錄訊息。

	  A---B---C origin/master
	 /         \
    D---E---F---G---H master

有關詳細資訊,包括如何顯示和處理衝突,請參閱 git-merge[1]

在 Git 1.7.0 或更新版本中,若要取消衝突的合併,請使用 git reset --merge警告:在較舊版本的 Git 中,不建議使用未提交的變更執行 git pull:雖然可行,但在發生衝突時,您可能會陷入難以回溯的狀態。

如果任何遠端變更與本機未提交的變更重疊,則合併會自動取消,且工作樹不會變動。一般來說,最好在提取之前將所有本機變更恢復正常工作狀態,或使用 git-stash[1] 將其隱藏起來。

選項

-q
--quiet

這會傳遞給底層的 git-fetch 以抑制傳輸期間的報告,並傳遞給底層的 git-merge 以抑制合併期間的輸出。

-v
--verbose

將 --verbose 傳遞給 git-fetch 和 git-merge。

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

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

如果透過變基完成結帳,則也會變基本機子模組提交。

如果透過合併完成更新,則會解析子模組衝突並簽出。

--commit
--no-commit

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

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

請注意,快速轉送更新不會建立合併提交,因此無法使用 --no-commit 停止這些合併。因此,如果您想要確保您的分支不會因合併命令而變更或更新,請搭配 --no-commit 使用 --no-ff。

--edit
-e
--no-edit

在提交成功的機械合併之前叫用編輯器,以進一步編輯自動產生的合併訊息,讓使用者可以說明和證明合併的合理性。--no-edit 選項可用於接受自動產生的訊息 (通常不建議這樣做)。

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

--cleanup=<mode>

此選項決定在提交之前如何清理合併訊息。如需詳細資訊,請參閱 git-commit[1]。此外,如果為 <mode> 指定值 scissors,則在發生合併衝突時,會在傳遞給提交機制之前,將 scissors 附加到 MERGE_MSG

--ff-only

如果沒有分歧的本機歷史記錄,則僅更新到新的歷史記錄。當未提供調和分歧歷史記錄的方法時 (透過 --rebase=* 旗標),這是預設行為。

--ff
--no-ff

在合併而非變基時,指定在合併歷史記錄已是目前歷史記錄的子代時如何處理合併。如果要求合併,則除非合併未儲存在 refs/tags/ 階層自然位置的已註釋 (且可能已簽署) 標籤,否則預設會使用 --ff,在此情況下會假設使用 --no-ff

使用 --ff 時,如果可能,請將合併解析為快速轉送 (僅更新分支指標以符合合併的分支;不要建立合併提交)。如果不可能 (當合併的歷史記錄不是目前歷史記錄的子代時),則建立合併提交。

使用 --no-ff 時,在所有情況下都建立合併提交,即使合併可以改為解析為快速轉送也是如此。

-S[<keyid>]
--gpg-sign[=<keyid>]
--no-gpg-sign

使用 GPG 簽署產生的合併提交。keyid 引數是選用的,預設為提交者身分;如果指定,則必須將其緊貼在選項後方,且沒有空格。--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 結尾。簽署的意義取決於您要提交的專案。例如,它可以證明提交者有權根據專案的授權提交作品,或同意某些貢獻者聲明,例如開發人員原產地證明。(請參閱 https://developercertificate.org,其中包含 Linux 核心和 Git 專案使用的證明)。請參閱您要貢獻的專案的文件或領導階層,以了解如何在該專案中使用簽署。

--no-signoff 選項可用於取消命令列上先前的 --signoff 選項。

--stat
-n
--no-stat

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

使用 -n 或 --no-stat 將不會在合併結束時顯示 diffstat。

--squash
--no-squash

產生工作樹和索引的狀態,如同真實的合併發生一樣 (除了合併資訊),但實際上不進行提交、移動 HEAD 或記錄 $GIT_DIR/MERGE_HEAD (以便讓下一個 git commit 命令建立合併提交)。這允許你在目前分支之上建立一個單一提交,其效果與合併另一個分支 (或在章魚式合併時的多個分支) 相同。

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

使用 --squash 時,不允許使用 --commit,且會失敗。

僅在合併時有用。

--[no-]verify

預設情況下,會執行 pre-merge 和 commit-msg hook。當給定 --no-verify 時,會略過這些 hook。另請參閱 githooks[5]。僅在合併時有用。

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

使用指定的合併策略;可以多次提供以指定它們應該嘗試的順序。如果沒有 -s 選項,則改為使用內建的策略列表 (合併單個 head 時使用 ort,否則使用 octopus)。

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

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

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

驗證要合併的 side branch 的頂端提交是否使用有效金鑰簽名,也就是說,在預設的信任模型中,此金鑰具有有效的 uid,這表示簽名金鑰已由受信任的金鑰簽名。如果 side branch 的頂端提交未使用有效金鑰簽名,則合併會中止。

僅在合併時有用。

--summary
--no-summary

與 --stat 和 --no-stat 同義;這些已被棄用,將在未來移除。

--autostash
--no-autostash

在操作開始之前,自動建立一個暫時的 stash 項目,將其記錄在 ref MERGE_AUTOSTASH 中,並在操作結束後應用它。這表示您可以在 dirty 的工作樹上執行操作。但是,請謹慎使用:成功合併後的最終 stash 應用可能會導致非預期的衝突。

--allow-unrelated-histories

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

僅在合併時有用。

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

當為 true 時,在提取後將目前分支 rebase 到上游分支之上。如果存在與上游分支對應的遠端追蹤分支,且上游分支自上次提取以來已重新 rebase,則 rebase 會使用該資訊以避免 rebase 非本機的變更。

當設定為 merges 時,使用 git rebase --rebase-merges 進行 rebase,以便將本機合併提交包含在 rebase 中 (有關詳細資訊,請參閱 git-rebase[1])。

當為 false 時,將上游分支合併到目前分支中。

當為 interactive 時,啟用 rebase 的互動模式。

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

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

這是 --rebase=false 的簡寫。

--[no-]all

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

-a
--append

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

--atomic

使用原子交易更新本機 ref。所有 ref 都會被更新,或者在發生錯誤時,沒有任何 ref 會被更新。

--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 的 ref。此選項會更新 .git/shallow 並接受此類 ref。

--negotiation-tip=<commit|glob>

預設情況下,Git 會向伺服器報告可從所有本機 ref 到達的提交,以尋找共同提交,以便嘗試減少要接收的封包檔案的大小。如果指定了此選項,則 Git 只會報告可從給定的提示到達的提交。當使用者知道哪個本機 ref 可能具有與正在提取的上游 ref 相同的提交時,這對於加速提取非常有用。

此選項可以多次指定;如果是這樣,Git 將報告可從任何給定提交到達的提交。

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

另請參閱 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 組態選項。

-f
--force

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

-k
--keep

保留下載的封包。

--prefetch

修改設定的 refspec,以將所有 ref 放入 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.*.fetch 配置變數值。為 --refmap 選項提供空的 <refspec> 會導致 Git 忽略已配置的 refspec,並完全依賴於作為命令列引數提供的 refspec。有關詳細資訊,請參閱「已配置的遠端追蹤分支」一節。

-t
--tags

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

-j
--jobs=<n>

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

如果指定了 --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 通訊時,將給定的字串傳送到伺服器。給定的字串不得包含 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 一節)。

<refspec>

指定要提取哪些參考,以及要更新哪些本地參考。當命令列上沒有出現 <refspec> 時,要提取的參考會從 remote.<repository>.fetch 變數中讀取(請參閱 git-fetch[1] 中的「已配置的遠端追蹤分支」一節)。

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

<refspec> 的 <src> 中可能包含 *,表示簡單的模式比對。此類 refspec 的作用類似於 glob,它會比對具有相同前置詞的任何參考。模式 <refspec> 的 <src> 和 <dst> 中都必須有 *。它會將參考對應到目標,方法是用從來源比對到的內容取代 *

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

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,還是將一個 commit 換成另一個沒有先前 commit 作為祖系的 commit 等。

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

與使用 git-push[1] 推送時一樣,可以使用在 refspec 中新增可選的開頭 +(或使用 --force 命令列選項)來覆寫上述有關不允許作為更新的所有規則。唯一的例外是,無論如何強制,refs/heads/* 命名空間都不會接受非 commit 物件。

注意
當您要提取的遠端分支已知會定期倒帶和 rebase 時,預期其新的尖端不會是其先前尖端的子系(如上次提取時儲存在遠端追蹤分支中的那樣)。您會想要使用 + 符號來表示此類分支需要非快速轉送更新。無法判斷或宣告將在此行為中在儲存庫中提供分支;提取的使用者必須知道這是分支的預期使用模式。
注意
git pull 命令列上直接列出多個 <refspec>,與在 <repository> 的配置中有多個 remote.<repository>.fetch 項目,並在沒有任何明確 <refspec> 參數的情況下執行 git pull 命令之間存在差異。命令列上明確列出的 <refspec> 始終會在提取後合併到目前分支中。換句話說,如果您列出多個遠端參考,git pull 將會建立章魚式合併。另一方面,如果您未在命令列上列出任何明確的 <refspec> 參數,則 git pull 會提取它在 remote.<repository>.fetch 配置中找到的所有 <refspec>,並且只將找到的第一個 <refspec> 合併到目前分支中。這是因為很少從遠端參考建立章魚式合併,而同時追蹤多個遠端標頭並提取多個標頭通常很有用。

GIT URLS

一般而言,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 原生也支援以下語法:

這兩種語法在大多數情況下是等效的,但當進行複製(clone)時,前者會隱含使用 --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"。

如果您只想為推送(push)操作改寫 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",但提取(pull)時仍會使用原始 URL。

REMOTES

可以使用以下其中一個名稱來代替 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 mergegit pull 命令)允許使用 -s 選項選擇後端的 _合併策略_。某些策略也可以使用自己的選項,這些選項可以透過將 -X<option> 引數傳遞給 git merge 和/或 git pull 來傳遞。

ort

這是提取或合併一個分支時的預設合併策略。此策略只能使用三向合併演算法解析兩個頭。當有多個可用於三向合併的共同祖先時,它會建立共同祖先的合併樹,並將其用作三向合併的參考樹。據報告,透過對取自 Linux 2.6 核心開發歷史的實際合併提交進行的測試,這樣做可以減少合併衝突,而不會導致錯誤合併。此外,此策略可以偵測並處理涉及更名的合併。它不使用偵測到的副本。此演算法的名稱是一個首字母縮寫字(「表面上遞迴的雙生子」),源於它被編寫為先前預設演算法 recursive 的替代品。

_ort_ 策略可以採用以下選項:

ours

此選項強制將衝突的區塊透過偏好_我們_的版本來自動乾淨地解析。來自另一個樹且與我們這一方沒有衝突的變更會反映在合併結果中。對於二進位制檔案,整個內容都取自我們這一方。

這不應與 _ours_ 合併策略混淆,後者甚至根本不看另一個樹包含的內容。它會捨棄另一個樹所做的所有事情,並宣告_我們_的歷史記錄包含其中發生的所有事情。

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

  • 如果_他們_的版本僅在行中引入空格變更,則使用_我們_的版本;

  • 如果_我們_的版本引入空格變更,但_他們_的版本包含實質性的變更,則使用_他們_的版本;

  • 否則,合併會以通常方式繼續。

renormalize

在解析三向合併時,這會對檔案的所有三個階段執行虛擬簽出和簽入。此選項旨在用於合併具有不同清除篩選器或行尾標準化規則的分支。有關詳細資訊,請參閱 gitattributes[5] 中的「合併具有不同簽入/簽出屬性的分支」。

no-renormalize

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

find-renames[=<n>]

開啟重新命名偵測,可選擇設定相似度臨界值。這是預設值。這會覆寫 _merge.renames_ 設定變數。另請參閱 git-diff[1] --find-renames

rename-threshold=<n>

已過時的 find-renames=<n> 同義詞。

subtree[=<path>]

此選項是 _subtree_ 策略的更進階形式,其中策略會猜測兩個樹在合併時必須如何移動才能相互匹配。相反地,指定的路徑會加上前置詞(或從開頭移除),以使兩個樹的形狀匹配。

recursive

這只能使用三向合併演算法解析兩個頭。當有多個可用於三向合併的共同祖先時,它會建立共同祖先的合併樹,並將其用作三向合併的參考樹。據報告,透過對取自 Linux 2.6 核心開發歷史的實際合併提交進行的測試,這樣做可以減少合併衝突,而不會導致錯誤合併。此外,這可以偵測並處理涉及更名的合併。它不使用偵測到的副本。這是從 Git v0.99.9k 到 v2.33.0 用於解析兩個頭的預設策略。

_recursive_ 策略採用與 _ort_ 相同的選項。但是,有三個 _ort_ 忽略(未在上面文件中說明)的額外選項,這些選項在使用 _recursive_ 策略時可能很有用:

patience

已過時的 diff-algorithm=patience 同義詞。

diff-algorithm=[patience|minimal|histogram|myers]

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

no-renames

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

resolve

這只能使用三向合併演算法解析兩個頭(即目前分支和您從中提取的另一個分支)。它會嘗試仔細偵測交叉合併歧義。它不處理重新命名。

octopus

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

ours

此策略會處理任意數量的分支頭部,但合併產生的樹狀結構始終是目前分支頭部的樹狀結構,實際上忽略了所有其他分支的變更。它旨在用於取代側分支的舊開發歷史。請注意,這與 *recursive* 合併策略的 -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。

如果命令列上沒有提供 refspec,則 git pull 會使用來自設定或 $GIT_DIR/remotes/<origin> 的 refspec。在這種情況下,適用下列規則

  1. 如果存在目前分支 <name>branch.<name>.merge 設定,則該設定是遠端站點要合併的分支名稱。

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

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

範例

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

    $ git pull
    $ git pull origin

    通常合併的分支是遠端儲存庫的 HEAD,但此選擇是由 branch.<name>.remote 和 branch.<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* 復原。

安全性

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

已知的攻擊向量如下

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

  2. 如同 #1 中,攻擊者選擇要竊取的物件 ID X。受害者傳送攻擊者已擁有的物件 Y,而攻擊者謊稱自己擁有 X 而沒有 Y,因此受害者會將 Y 作為相對於 X 的差異傳送。差異會向攻擊者顯示與 Y 相似的 X 區域。

錯誤

目前,使用 --recurse-submodules 只能擷取已簽出子模組中的新提交。例如,當上游在剛擷取的超專案提交中新增一個新的子模組時,無法擷取子模組本身,導致稍後無法簽出該子模組,而必須再次進行擷取。預期會在未來的 Git 版本中修正此問題。

GIT

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

scroll-to-top