簡體中文 ▾ 主題 ▾ 最新版本 ▾ git-pull 最後更新於 2.50.0

名稱

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> 的預設值是從透過 git-branch[1] --track 設定的當前分支的“remote”和“merge”配置中讀取的。

假設存在以下歷史記錄,並且當前分支是“master

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

然後“git pull”將從遠端 master 分支拉取並重放自本地 master 分支(即 E)分歧以來的更改,直到其當前提交(C),然後將其記錄在一個新提交中,並附帶兩個父提交的名稱以及使用者描述更改的日誌訊息。

	  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])。

如果檢出是透過 rebase 完成的,則本地子模組提交也會被 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 附註。簽名的含義取決於你所提交的專案。例如,它可能證明提交者有權在專案許可下提交作品,或者同意某些貢獻者宣告,例如開發者原創證明(Developer Certificate of Origin)。(請參閱 https://developercertificate.org 瞭解 Linux 核心和 Git 專案使用的證明。)請查閱你所貢獻的專案的文件或領導層,以瞭解該專案中籤名的用途。

可以使用 --no-signoff 選項來抵消命令列中較早的 --signoff 選項。

--stat
-n
--no-stat

在合併結束時顯示差異統計。差異統計也受配置選項 merge.stat 控制。

使用 -n--no-stat 時,不在合併結束時顯示差異統計。

--squash
--no-squash

生成工作樹和索引狀態,就像發生了實際合併一樣(除了合併資訊),但實際上不進行提交,不移動 HEAD,也不記錄 $GIT_DIR/MERGE_HEAD(以使下一個 git commit 命令建立合併提交)。這允許你在當前分支之上建立一個單獨的提交,其效果與合併另一個分支(或在八爪魚合併情況下合併更多分支)相同。

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

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

僅在合併時有用。

--[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

驗證正在合併的側分支的最新提交是否使用有效金鑰簽名,即在預設信任模型中,這意味著簽名金鑰已由受信任金鑰簽名。如果側分支的最新提交未用有效金鑰簽名,則合併中止。

僅在合併時有用。

--summary
--no-summary

--stat--no-stat 同義;這些已棄用,將來會移除。

--autostash
--no-autostash

在操作開始前自動建立一個臨時暫存條目,將其記錄在引用 MERGE_AUTOSTASH 中,並在操作結束後應用。這意味著你可以在髒工作樹上執行操作。但是,請謹慎使用:成功合併後的最終暫存應用可能會導致非平凡的衝突。

--allow-unrelated-histories

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

僅在合併時有用。

-r
--rebase[=(false|true|merges|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 的簡寫。

--[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=<ref>

深化或縮短淺克隆倉庫的歷史記錄,以排除從指定遠端分支或標籤可達的提交。此選項可以多次指定。

--unshallow

如果源倉庫是完整的,則將淺克隆倉庫轉換為完整的倉庫,移除淺克隆倉庫施加的所有限制。

如果源倉庫是淺克隆倉庫,則儘可能多地拉取,以便當前倉庫擁有與源倉庫相同的歷史記錄。

--update-shallow

預設情況下,當從淺克隆倉庫拉取時,git fetch 拒絕需要更新 .git/shallow 的引用。此選項會更新 .git/shallow 並接受此類引用。

--negotiation-tip=<commit|glob>

預設情況下,Git 會向伺服器報告所有本地引用可達的提交,以查詢共同提交,從而嘗試減小要接收的 packfile 的大小。如果指定此選項,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 配置選項。

-f
--force

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

-k
--keep

保留已下載的包。

--prefetch

修改配置的引用規範,將所有引用放置到 refs/prefetch/ 名稱空間中。請參閱 git-maintenance[1] 中的 prefetch 任務。

-p
--prune

在拉取之前,移除遠端倉庫上不再存在的任何遠端跟蹤引用。如果標籤僅因預設的標籤自動跟蹤或 --tags 選項而被拉取,則它們不受修剪。但是,如果標籤因顯式引用規範(無論是在命令列還是在遠端配置中,例如如果遠端倉庫是使用 --mirror 選項克隆的)而被拉取,則它們也受修剪。提供 --prune-tags 是提供標籤引用規範的簡寫。

--no-tags

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

--refmap=<refspec>

當拉取命令列中列出的引用時,使用指定的引用規範(可以多次給定)將引用對映到遠端跟蹤分支,而不是遠端倉庫的 remote.*.fetch 配置變數的值。向 --refmap 選項提供空 *<refspec>* 會導致 Git 忽略配置的引用規範,並完全依賴作為命令列引數提供的引用規範。有關詳細資訊,請參閱“配置的遠端跟蹤分支”部分。

-t
--tags

除了其他將被拉取的內容外,還從遠端拉取所有標籤(即,將遠端標籤 refs/tags/* 拉取到具有相同名稱的本地標籤中)。單獨使用此選項不會使標籤受到修剪,即使使用了 --prune 也是如此(儘管如果標籤也是顯式引用規範的目標,它們仍可能被修剪;請參閱 --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> 時,它們都會按照命令列中列出的順序傳送到對方。當命令列沒有提供 --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 URL 部分)或遠端名稱(請參閱下面的 遠端倉庫 部分)。

<refspec>

指定要拉取哪些引用以及要更新哪些本地引用。當命令列中沒有出現 <refspec> 時,要拉取的引用將從 remote.<repository>.fetch 變數中讀取(請參閱 git-fetch[1] 中“配置的遠端跟蹤分支”部分)。

<refspec> 引數的格式是可選的加號 +,後跟源 <src>,後跟冒號 :,再後跟目標 <dst>。當 <dst> 為空時,可以省略冒號。<src> 通常是一個引用,或者一個帶單個 * 的全域性模式,用於匹配一組引用,但它也可以是一個完整的十六進位制物件名稱。

一個 <refspec> 可以在其 <src> 中包含一個 * 來指示簡單的模式匹配。這樣的 refspec 像一個全域性模式,匹配任何符合該模式的引用。一個模式 <refspec> 在 <src> 和 <dst> 中都必須只有一個 *。它會透過將 * 替換為從源匹配到的內容來將引用對映到目標。

如果一個引用規範以 ^ 為字首,它將被解釋為負引用規範。這樣的引用規範不是指定要拉取哪些引用或要更新哪些本地引用,而是指定要排除的引用。如果一個引用至少匹配一個正引用規範,並且不匹配任何負引用規範,則它將被視為匹配。負引用規範對於限制模式引用規範的範圍很有用,使其不包含特定引用。負引用規範本身可以是模式引用規範。但是,它們只能包含 <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/* 的任何更新都可以在引用規範中沒有 +(或 --force)的情況下被接受。在拉取時,我們隨意地將遠端的所有標籤更新視為強制拉取。自 Git 2.20 版本以來,拉取以更新 refs/tags/* 的工作方式與推送時相同。也就是說,在引用規範中沒有 +(或 --force)的情況下,任何更新都將被拒絕。

與使用 git-push[1] 推送時不同,在引用規範中沒有 +(或 --force)的情況下,refs/{tags,heads}/* 之外的任何更新都將被接受,無論是例如用一個 blob 替換一個樹物件,還是用一個沒有前一個提交作為祖先的提交替換另一個提交等。

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

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

注意
當你希望拉取的遠端分支已知會定期回溯和變基時,其新提示預計不會是其先前提示(上次拉取時儲存在你遠端跟蹤分支中的提示)的後代。你將需要使用 + 符號來指示此類分支需要非快進更新。無法確定或宣告一個分支在倉庫中將以這種行為提供;拉取使用者只需知道這是該分支的預期使用模式。
注意
在 *git pull* 命令列上直接列出多個 <refspec>,與在配置中為某個 <repository> 擁有多個 remote.<repository>.fetch 條目並在不帶任何顯式 <refspec> 引數的情況下執行 *git pull* 命令之間存在差異。命令列上明確列出的 <refspec> 在拉取後總是合併到當前分支中。換句話說,如果你列出多個遠端引用,*git pull* 將建立一次“八爪魚合併”(Octopus merge)。另一方面,如果你在命令列上沒有列出任何顯式 <refspec> 引數,*git pull* 將拉取它在 remote.<repository>.fetch 配置中找到的所有 <refspec>,並且只將找到的第一個 <refspec> 合併到當前分支中。這是因為從遠端引用建立八爪魚合併的情況很少見,而透過一次拉取多個來跟蹤多個遠端頭部通常很有用。

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>

ssh 協議還可以使用另一種類似 scp 的語法:

  • [<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。

遠端倉庫

以下之一的名稱可以作為 <repository> 引數來代替 URL 使用:

  • Git 配置檔案中的遠端倉庫:$GIT_DIR/config

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

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

所有這些也允許你省略命令列中的引用規範,因為它們各自包含一個 Git 將預設使用的引用規範。

配置檔案中的命名遠端倉庫

你可以選擇提供之前使用 git-remote[1]git-config[1] 配置的遠端倉庫名稱,甚至可以透過手動編輯 $GIT_DIR/config 檔案來配置。此遠端倉庫的 URL 將用於訪問倉庫。當你未在命令列上提供引用規範時,此遠端倉庫的引用規範將作為預設值使用。配置檔案中的條目將如下所示:

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

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

$GIT_DIR/remotes 中的命名檔案

你可以選擇提供 $GIT_DIR/remotes 中的檔名稱。此檔案中的 URL 將用於訪問倉庫。當你未在命令列上提供引用規範時,此檔案中的引用規範將作為預設值使用。此檔案應具有以下格式:

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

Push: 行由 *git push* 使用,Pull: 行由 *git pull* 和 *git fetch* 使用。可以指定多行 Push:Pull: 以進行額外的分支對映。

$GIT_DIR/branches 中的命名檔案

你可以選擇提供 $GIT_DIR/branches 中的檔名稱。此檔案中的 URL 將用於訪問倉庫。此檔案應具有以下格式:

	<URL>#<head>

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

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

git fetch 使用

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

git push 使用

	HEAD:refs/heads/<head>

合併策略

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

ort

這是拉取或合併一個分支時的預設合併策略。此策略只能使用三向合併演算法解決兩個頭部。當存在多個可用於三向合併的共同祖先時,它會建立共同祖先的合併樹,並將其用作三向合併的參考樹。根據對 Linux 2.6 核心開發歷史中實際合併提交進行的測試報告,這會導致更少的合併衝突,而不會引起合併錯誤。此外,此策略可以檢測和處理涉及重新命名的合併。它不使用檢測到的複製。此演算法的名稱是一個縮寫(“表面上的遞迴的雙胞胎”),因為它被編寫為替代之前的預設演算法 recursive

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

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

ours

此選項強制透過偏向於*我們的*版本來乾淨地自動解決衝突的 hunk。來自另一個樹的更改(與我們這邊的更改不衝突)會反映在合併結果中。對於二進位制檔案,整個內容取自我們這邊。

這不應與 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> 同義詞。

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: 行的值。

為了確定在不帶任何引用規範引數的情況下執行命令時要拉取哪些遠端分支(並可選地儲存在遠端跟蹤分支中),會查詢配置變數 remote.<origin>.fetch 的值,如果不存在,則查詢 $GIT_DIR/remotes/<origin> 並使用其 Pull: 行。除了 OPTIONS 部分中描述的引用規範格式外,你還可以有類似這樣的全域性引用規範:

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

一個全域性引用規範必須有一個非空的 RHS(即,必須將拉取的內容儲存在遠端跟蹤分支中),並且其 LHS 和 RHS 都必須以 /* 結尾。上面指定了所有遠端分支都使用 refs/remotes/origin/ 層級結構中同名的遠端跟蹤分支進行跟蹤。

確定拉取後合併哪個遠端分支的規則有些複雜,以避免破壞向後相容性。

如果 git pull 命令列上給出了顯式引用規範,則它們都將被合併。

當命令列上未給出引用規範時,git pull 會使用配置或 $GIT_DIR/remotes/<origin> 中的引用規範。在這種情況下,適用以下規則:

  1. 如果當前分支 <name>branch.<name>.merge 配置存在,則這是遠端站點上要合併的分支名稱。

  2. 如果引用規範是全域性匹配的,則不進行合併。

  3. 否則,合併第一個引用規範的遠端分支。

示例

  • 更新你克隆倉庫的遠端跟蹤分支,然後將其中一個合併到你當前的分支中

    $ git pull
    $ git pull origin

    通常,合併的分支是遠端倉庫的 HEAD,但選擇由 branch.<name>.remotebranch.<name>.merge 選項決定;有關詳細資訊,請參閱 git-config[1]

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

    $ git pull origin next

    這會將 next 的副本暫時留在 FETCH_HEAD 中,並更新遠端跟蹤分支 origin/next。同樣的操作也可以透過呼叫 fetch 和 merge 來完成:

    $ git fetch origin
    $ git merge origin/next

如果你嘗試了一次拉取,導致了複雜的衝突,並且想要重新開始,可以使用 *git reset* 進行恢復。

安全性

拉取(fetch)和推送(push)協議並非旨在防止一方竊取另一方倉庫中不打算共享的資料。如果你有需要保護免受惡意對等方侵害的私有資料,最好的選擇是將其儲存在另一個倉庫中。這適用於客戶端和伺服器。特別是,伺服器上的名稱空間對於讀取訪問控制無效;你只應授予對整個倉庫具有讀取訪問許可權的客戶端讀取某個名稱空間的許可權。

已知的攻擊向量如下:

  1. 受害者傳送“have”行,宣傳它擁有的、並非明確打算共享但如果對等方也擁有則可用於最佳化傳輸的物件 ID。攻擊者選擇要竊取的物件 ID X,並向 X 傳送一個引用,但不需要傳送 X 的內容,因為受害者已經擁有它。現在受害者認為攻擊者擁有 X,並稍後將 X 的內容發回給攻擊者。(這種攻擊對於客戶端在伺服器上執行最直接,即在客戶端有權訪問的名稱空間中建立指向 X 的引用,然後拉取它。伺服器在客戶端上執行它的最可能方式是將 X “合併”到一個公共分支中,並希望使用者在此分支上進行額外工作並將其推回伺服器而沒有注意到合併。)

  2. 與 #1 中類似,攻擊者選擇要竊取的物件 ID X。受害者傳送攻擊者已有的物件 Y,攻擊者虛假地聲稱擁有 X 而不是 Y,因此受害者將 Y 作為針對 X 的增量傳送。此增量向攻擊者揭示了 X 中與 Y 相似的區域。

BUG

目前,使用 --recurse-submodules 只能拉取已檢出子模組中的新提交。例如,當上遊在剛剛拉取的超級專案提交中添加了一個新子模組時,該子模組本身無法被拉取,導致以後無法在不再次拉取的情況下檢出該子模組。預計這將在未來的 Git 版本中修復。

GIT

Git[1] 套件的一部分

scroll-to-top