Git
英文 ▾ 主題 ▾ 最新版本 ▾ git-push 最後更新於 2.45.0

名稱

git-push - 更新遠端參考以及相關物件

概要

git push [--all | --branches | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
	   [--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-q | --quiet] [-v | --verbose]
	   [-u | --set-upstream] [-o <string> | --push-option=<string>]
	   [--[no-]signed|--signed=(true|false|if-asked)]
	   [--force-with-lease[=<refname>[:<expect>]] [--force-if-includes]]
	   [--no-verify] [<repository> [<refspec>…​]]

描述

使用本機參考更新遠端參考,同時傳送完成給定參考所需的物件。

您可以透過在儲存庫中設定鉤子,每次將內容推送至儲存庫時,讓它發生有趣的事情。請參閱 git-receive-pack[1] 的文件。

當命令列未使用 <repository> 引數指定要推送的位置時,會查詢目前分支的 branch.*.remote 組態以判斷要推送的位置。如果缺少組態,則預設為 origin

當命令列未使用 <refspec>... 引數或 --all--mirror--tags 選項指定要推送的內容時,命令會透過查詢 remote.*.push 組態來找到預設的 <refspec>,如果找不到,則會採用 push.default 組態來決定要推送的內容 (請參閱 git-config[1] 以瞭解 push.default 的意義)。

當命令列和組態都沒有指定要推送的內容時,會使用預設行為,這對應於 push.defaultsimple 值:目前分支會推送至對應的上游分支,但為了安全起見,如果上游分支的名稱與本機分支的名稱不同,則推送會中止。

選項

<repository>

作為推送操作目的地的「遠端」儲存庫。此參數可以是 URL(請參閱下方的 GIT URLS 章節)或是遠端的名稱(請參閱下方的 REMOTES 章節)。

<refspec>…​

指定要使用哪個來源物件更新哪個目的地參考。<refspec> 參數的格式是選用的加號 +,後接來源物件 <src>,後接冒號 :,後接目的地參考 <dst>。

<src> 通常是您想要推送的分支名稱,但它可以是任何任意的「SHA-1 運算式」,例如 master~4HEAD (請參閱 gitrevisions[7])。

<dst> 會指出遠端上的哪個參考會透過此推送進行更新。這裡不能使用任意運算式,必須指定實際的參考。如果 git push [<repository>] 在沒有任何 <refspec> 引數的情況下設定為使用 remote.<repository>.push 組態變數,以 <src> 更新目的地的某個參考,則可以省略 :<dst> 部分,這類推送將更新 <src> 通常會更新的參考,而命令列上沒有任何 <refspec>。否則,遺失 :<dst> 表示更新與 <src> 相同的參考。

如果 <dst> 沒有以 refs/ 開頭 (例如 refs/heads/master),我們會嘗試根據所推送的 <src> 類型,以及 <dst> 是否不明確,來推斷其在目的地 <repository> 上 refs/* 中的位置。

  • 如果 <dst> 明確地指向 <repository> 遠端上的參考,則會推送至該參考。

  • 如果 <src> 解析為以 refs/heads/ 或 refs/tags/ 開頭的參考,則會在 <dst> 前面加上該參考。

  • 未來可能會新增其他不明確的解析,但目前其他任何情況都會發生錯誤,指出我們嘗試的操作,並且會根據 advice.pushUnqualifiedRefname 組態 (請參閱 git-config[1]) 建議您可能想要推送至哪個 refs/ 命名空間。

由 <src> 參考的物件會用於更新遠端上的 <dst> 參考。是否允許這樣做取決於 <dst> 參考所在 refs/* 中的位置,如下方的詳細說明,在這些章節中,「更新」是指任何修改,刪除除外,刪除會以不同的方式處理,如接下來的幾個章節所述。

refs/heads/* 命名空間只會接受 commit 物件,且只有在可以快速轉送時才會更新。

refs/tags/* 命名空間會接受任何類型的物件 (因為可以標記 commit、樹狀結構和 blob),並且任何對它們的更新都會遭到拒絕。

您可以將任何類型的物件推送至 refs/{tags,heads}/* 以外的任何命名空間。在標籤和 commit 的情況下,就允許更新而言,這些物件會被視為像是 refs/heads/* 內的 commit 一樣。

也就是說,允許快速轉送 refs/{tags,heads}/* 以外的 commit 和標籤,即使快速轉送的內容不是 commit,而是恰好指向新 commit 的標籤物件,而該新 commit 是上一個標籤 (或 commit) 所取代的 commit 的快速轉送。如果標籤指向相同的 commit,也允許以完全不同的標籤取代標籤,以及推送已拆封的標籤,也就是推送現有標籤物件指向的 commit,或現有 commit 指向的新標籤物件。

refs/{tags,heads}/* 以外的樹狀結構和 blob 物件會以與 refs/tags/* 內相同的方式處理,任何對它們的更新都會遭到拒絕。

上面描述的有關不允許作為更新的所有規則都可以透過在 refspec 中新增選用的前導 + (或使用 --force 命令列選項) 來覆寫。唯一的例外是,無論如何強制,refs/heads/* 命名空間都不會接受非 commit 物件。鉤子和組態也可以覆寫或修正這些規則,例如,請參閱 git-config[1] 中的 receive.denyNonFastForwards 以及 githooks[5] 中的 pre-receiveupdate

推送空的 <src> 可讓您從遠端儲存庫刪除 <dst> 參考。始終會接受刪除,而不會在 refspec (或 --force) 中使用前導 +,除非組態或鉤子禁止。請參閱 git-config[1] 中的 receive.denyDeletes 以及 githooks[5] 中的 pre-receiveupdate

特殊的 refspec : (或 +: 以允許非快速轉送更新) 指示 Git 推送「符合的」分支:對於本機端存在的每個分支,如果遠端端已存在同名的分支,則會更新遠端端。

tag <tag>refs/tags/<tag>:refs/tags/<tag> 具有相同的意義。

--all
--branches

推送所有分支 (也就是 refs/heads/ 下的參考);不能與其他 <refspec> 一起使用。

--prune

移除沒有本機對應項目的遠端分支。例如,如果不再存在具有相同名稱的本機分支,則會移除遠端分支 tmp。這也會遵循 refspec,例如,git push --prune remote refs/heads/*:refs/tmp/* 會確保在不存在 refs/heads/foo 的情況下,將會移除遠端 refs/tmp/foo

--mirror

此選項並非指定每個要推送的 ref,而是指定將 refs/ 下的所有 ref(包括但不限於 refs/heads/refs/remotes/refs/tags/)鏡像到遠端儲存庫。新建立的本機 ref 將被推送到遠端,本機更新的 ref 將在遠端強制更新,而刪除的 ref 將從遠端移除。如果設定了組態選項 remote.<remote>.mirror,則此為預設行為。

-n
--dry-run

執行所有操作,但不實際傳送更新。

--porcelain

產生機器可讀的輸出。每個 ref 的輸出狀態行將以 Tab 分隔,並傳送到 stdout 而不是 stderr。將會提供 ref 的完整符號名稱。

-d
--delete

從遠端儲存庫刪除所有列出的 ref。這與在所有 ref 前面加上冒號的效果相同。

--tags

除了在命令列上明確列出的 refspec 外,還會推送 refs/tags 下的所有 ref。

--follow-tags

推送所有在沒有此選項的情況下會推送的 ref,同時也推送 refs/tags 中缺少但指向可從正在推送的 ref 訪問的 commit-ish 的已註解標籤。也可以使用組態變數 push.followTags 指定。如需更多資訊,請參閱 git-config[1] 中的 push.followTags

--[no-]signed
--signed=(true|false|if-asked)

對推送請求進行 GPG 簽章,以更新接收端的 ref,以便允許由鉤子檢查和/或記錄。如果為 false--no-signed,則不會嘗試簽章。如果為 true--signed,如果伺服器不支援簽章推送,則推送將失敗。如果設定為 if-asked,則僅在伺服器支援簽章推送時才簽章。如果實際呼叫 gpg --sign 失敗,推送也會失敗。有關接收端的詳細資訊,請參閱 git-receive-pack[1]

--[no-]atomic

如果遠端可用,則在遠端使用原子交易。要麼更新所有 ref,要麼在發生錯誤時不更新任何 ref。如果伺服器不支援原子推送,則推送將失敗。

-o <option>
--push-option=<option>

將給定的字串傳輸到伺服器,伺服器會將其傳遞給 pre-receive 以及 post-receive 鉤子。給定的字串不得包含 NUL 或 LF 字元。當給定多個 --push-option=<option> 時,它們會按照命令列上列出的順序全部傳送到另一端。當命令列未給定 --push-option=<option> 時,則改為使用組態變數 push.pushOption 的值。

--receive-pack=<git-receive-pack>
--exec=<git-receive-pack>

遠端 git-receive-pack 程式的路徑。當通過 ssh 推送到遠端儲存庫,且您的預設 $PATH 中沒有該程式時,這有時會很有用。

--[no-]force-with-lease
--force-with-lease=<refname>
--force-with-lease=<refname>:<expect>

通常,"git push" 會拒絕更新不是用於覆寫它的本機 ref 之祖先的遠端 ref。

如果遠端 ref 的目前值為預期值,則此選項會覆寫此限制。否則 "git push" 會失敗。

假設您必須重新設定您已經發布的內容的基底。您將必須繞過「必須快速轉發」規則,才能將您最初發布的歷史記錄替換為重新設定基底的歷史記錄。如果在您重新設定基底時,其他人基於您原始的歷史記錄建置,則遠端分支的尖端可能會隨著他們的提交而前進,並且盲目使用 --force 進行推送將會遺失他們的工作。

此選項允許您表示您預期要更新的歷史記錄是您重新設定基底並想要替換的內容。如果遠端 ref 仍然指向您指定的 commit,您可以確定沒有其他人對該 ref 執行任何操作。這就像在沒有明確鎖定 ref 的情況下對 ref 進行「租借」,並且僅當「租借」仍然有效時才更新遠端 ref。

單獨使用 --force-with-lease,而不指定詳細資訊,將透過要求所有要更新的遠端 ref 的目前值與我們為它們擁有的遠端追蹤分支相同,來保護這些遠端 ref。

如果指定的 ref(單獨)將要更新,則 --force-with-lease=<refname> 在未指定預期值的情況下,將透過要求它的目前值與我們為它擁有的遠端追蹤分支相同來保護該 ref。

如果指定的 ref(單獨)將要更新,則 --force-with-lease=<refname>:<expect> 將透過要求它的目前值與指定值 <expect> 相同來保護該 ref(允許它與我們為 refname 擁有的遠端追蹤分支不同,或者當使用此格式時,我們甚至不必擁有這樣的遠端追蹤分支)。如果 <expect> 為空字串,則表示指定的 ref 必須尚不存在。

請注意,除了明確指定 ref 的預期目前值的 --force-with-lease=<refname>:<expect> 以外的所有其他格式仍然是實驗性的,並且隨著我們對此功能獲得更多經驗,它們的語意可能會發生變化。

"--no-force-with-lease" 將取消命令列上所有先前的 --force-with-lease。

關於安全性的通用注意事項:在沒有預期值的情況下提供此選項,也就是說,使用 --force-with-lease--force-with-lease=<refname> 與在背景中隱式執行 git fetch 到要推送到的遠端儲存庫的任何操作(例如 cronjob 中儲存庫的 git fetch origin)之間的互動非常糟糕。

它提供的對 --force 的保護是確保不會覆蓋您工作所基於的後續變更,但是如果某些背景程序在背景中更新 ref,則很容易被擊敗。我們除了遠端追蹤資訊之外,沒有任何東西可以作為您預期看到和願意覆蓋的 ref 的啟發法依據。

如果您的編輯器或其他一些系統在背景中為您執行 git fetch,則可以透過簡單地設定另一個遠端來減輕此問題

git remote add origin-push $(git config remote.origin.url)
git fetch origin-push

現在,當背景程序執行 git fetch origin 時,origin-push 上的參考將不會更新,因此諸如

git push --force-with-lease origin-push

除非您手動執行 git fetch origin-push,否則將會失敗。當然,如果某個東西執行 git fetch --all,此方法將完全被擊敗,在這種情況下,您需要禁用它或執行更繁瑣的操作,例如

git fetch              # update 'master' from remote
git tag base master    # mark our base point
git rebase -i master   # rewrite some commits
git push --force-with-lease=master:base master:master

也就是說,為您已看到且願意覆寫的上游程式碼版本建立 base 標籤,然後重寫歷史記錄,最後強制推送對 master 的變更,如果遠端版本仍在 base,無論您的本機 remotes/origin/master 在背景中已更新到什麼狀態。

或者,在「推送」時,將 --force-if-includes 指定為 --force-with-lease[=<refname>] 的輔助選項(也就是說,不說明遠端上的 ref 必須指向的確切 commit,或要保護的遠端上的哪些 ref),將驗證是否在允許強制更新之前,已在本機整合了可能在背景中隱式更新的遠端追蹤 ref 的更新。

-f
--force

通常,此命令會拒絕更新不是用於覆寫它的本機 ref 之祖先的遠端 ref。此外,當使用 --force-with-lease 選項時,此命令會拒絕更新目前值與預期值不符的遠端 ref。

此標籤會停用這些檢查,並且可能會導致遠端儲存庫遺失 commit;請小心使用。

請注意,--force 適用於推送的所有 ref,因此將它與設定為 matchingpush.default 或設定多個推送目的地的 remote.*.push 一起使用,可能會覆蓋目前分支以外的 ref(包括嚴格落後於其遠端對應項的本機 ref)。若要強制僅推送至一個分支,請在要推送的 refspec 前面使用 +(例如,git push origin +master 會強制推送至 master 分支)。有關詳細資訊,請參閱上述 <refspec>... 區段。

--[no-]force-if-includes

僅當在本機整合了遠端追蹤 ref 的尖端時才強制更新。

此選項啟用一項檢查,該檢查會驗證是否可從基於它的本機分支的「reflog」條目之一訪問遠端追蹤 ref 的尖端以進行重寫。該檢查可確保已在本機合併來自遠端的任何更新,如果情況並非如此,則拒絕強制更新。

如果傳遞此選項時未指定 --force-with-lease,或與 --force-with-lease=<refname>:<expect> 一起指定,則它是「空操作」。

指定 --no-force-if-includes 會停用此行為。

--repo=<repository>

此選項等同於 <repository> 引數。如果同時指定兩者,則命令列引數優先。

-u
--set-upstream

對於每個最新的或已成功推送的分支,新增上游(追蹤)參考,以供無引數的 git-pull[1] 和其他命令使用。如需更多資訊,請參閱 git-config[1] 中的 branch.<name>.merge

--[no-]thin

這些選項會傳遞至 git-send-pack[1]。當傳送者和接收者共用許多相同的物件時,精簡傳輸會顯著減少傳送的資料量。預設值為 --thin

-q
--quiet

隱藏所有輸出,包括更新的 ref 的清單,除非發生錯誤。進度不會報告給標準錯誤流。

-v
--verbose

詳細執行。

--progress

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

--no-recurse-submodules
--recurse-submodules=check|on-demand|only|no

可用於確保要推送的修訂版本使用的所有子模組 commit 都可在遠端追蹤分支上使用。如果使用 check,Git 將驗證在要推送的修訂版本中變更的所有子模組 commit 是否可在子模組的至少一個遠端上使用。如果遺失任何 commit,則會中止推送並以非零狀態退出。如果使用 on-demand,則會推送在要推送的修訂版本中變更的所有子模組。如果按需推送無法推送所有必要的修訂版本,也會中止並以非零狀態退出。如果使用 only,則會推送所有子模組,同時保留未推送的超級專案。當不需要子模組遞迴時,可以使用值 no 或使用 --no-recurse-submodules 來覆寫 push.recurseSubmodules 組態變數。

當使用 on-demandonly 時,如果子模組具有 "push.recurseSubmodules={on-demand,only}" 或 "submodule.recurse" 組態,則會發生進一步的遞迴。在這種情況下,"only" 被視為 "on-demand"。

--[no-]verify

切換 pre-push hook (請參閱 githooks[5])。預設為 --verify,讓 hook 有機會阻止推送。使用 --no-verify,hook 會被完全繞過。

-4
--ipv4

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

-6
--ipv6

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

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 本身也支援,可以使用以下語法

這兩種語法大多是等效的,但在複製時,前者表示 --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。

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,或如果未定義 pushurl,則會影響所有已定義的 url。但是,如果定義了多個 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 push" 的輸出取決於所使用的傳輸方法;本節說明透過 Git 協定推送時的輸出 (無論是本機還是透過 ssh)。

推送狀態以表格形式輸出,每行表示單一 ref 的狀態。每行的格式如下

 <flag> <summary> <from> -> <to> (<reason>)

如果使用 --porcelain,則輸出的每一行的格式如下

 <flag> \t <from>:<to> \t <summary> (<reason>)

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

flag

表示 ref 狀態的單一字元

(空格)

表示成功推送的快轉;

+

表示成功強制更新;

-

表示成功刪除的 ref;

*

表示成功推送的新 ref;

!

表示被拒絕或無法推送的 ref;以及

=

表示最新且不需要推送的 ref。

摘要

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

對於失敗的更新,會提供更多詳細資訊

rejected

Git 根本沒有嘗試發送 ref,通常是因為它不是快轉,而且您沒有強制更新。

remote rejected

遠端拒絕了更新。通常是由於遠端上的 hook 造成的,或是因為遠端儲存庫生效了以下安全選項之一:receive.denyCurrentBranch (用於推送至已檢出的分支)、receive.denyNonFastForwards (用於強制非快轉更新)、receive.denyDeletesreceive.denyDeleteCurrent。請參閱 git-config[1]

remote failure

遠端未報告 ref 的成功更新,可能是由於遠端上的暫時性錯誤、網路連線中斷或其他暫時性錯誤。

from

正在推送的本機 ref 的名稱,減去其 refs/<type>/ 前綴。在刪除的情況下,本機 ref 的名稱會被省略。

to

正在更新的遠端 ref 的名稱,減去其 refs/<type>/ 前綴。

reason

人類可讀的說明。在成功推送 ref 的情況下,不需要任何說明。對於失敗的 ref,會描述失敗的原因。

關於快轉的注意事項

當更新將原本指向提交 A 的分支 (或更廣泛地說,ref) 變更為指向另一個提交 B 時,如果 B 是 A 的後代,則稱為快轉更新。

在從 A 到 B 的快轉更新中,原始提交 A 建構的提交集合是新提交 B 建構的提交集合的子集。因此,它不會遺失任何歷史記錄。

相反地,非快轉更新將會遺失歷史記錄。例如,假設您和另一個人從相同的提交 X 開始,並且您建立了導致提交 B 的歷史記錄,而另一個人建立了導致提交 A 的歷史記錄。歷史記錄如下所示

      B
     /
 ---X---A

進一步假設另一個人已將導致 A 的變更推回您們兩者取得原始提交 X 的原始儲存庫。

另一個人進行的推送更新了原本指向提交 X 的分支,使其指向提交 A。這是一個快轉。

但是,如果您嘗試推送,您將嘗試使用提交 B 更新分支 (現在指向 A)。這 不是 快轉。如果您這樣做,提交 A 所引入的變更將會遺失,因為現在每個人都會開始在 B 的基礎上建構。

預設情況下,該命令不允許非快轉的更新,以防止這種歷史記錄遺失。

如果您不想遺失您的工作 (從 X 到 B 的歷史記錄) 或另一個人的工作 (從 X 到 A 的歷史記錄),您需要先從儲存庫提取歷史記錄,建立包含雙方所做變更的歷史記錄,然後將結果推回。

您可以執行 "git pull"、解決潛在的衝突,然後 "git push" 結果。"git pull" 將在提交 A 和 B 之間建立一個合併提交 C。

      B---C
     /   /
 ---X---A

使用產生的合併提交更新 A 將會快轉,您的推送將被接受。

或者,您可以使用 "git pull --rebase" 將您在 X 和 B 之間的變更基於 A 之上,然後將結果推回。重新變基將會建立一個新的提交 D,它在 A 的基礎上建構 X 和 B 之間的變更。

      B   D
     /   /
 ---X---A

同樣地,使用此提交更新 A 將會快轉,您的推送將被接受。

當您嘗試推送時,可能會遇到非快轉拒絕的另一種常見情況,即使您推送到的儲存庫沒有其他人推送,也可能發生這種情況。在您自己推送 commit A 之後(本節的第一張圖片),使用「git commit --amend」將其替換為 commit B,然後您嘗試將其推送出去,因為您忘記已經推送了 A。在這種情況下,並且只有在您確定在此期間沒有人提取您之前的 commit A(並開始在其之上建構)時,您才能執行「git push --force」來覆寫它。換句話說,「git push --force」是一種保留給您確實想丟失歷史記錄的情況的方法。

範例

git push

作用類似於 git push <remote>,其中 <remote> 是目前分支的遠端(如果目前分支沒有設定遠端,則為 origin)。

git push origin

在沒有其他設定的情況下,如果目前分支的名稱與其上游(branch.<name>.merge 設定變數)的名稱相同,則會將目前分支推送到已設定的上游,否則會發生錯誤且不會推送。

當沒有給定 <refspec> 時,此命令的預設行為可以透過設定遠端的 push 選項或 push.default 設定變數來設定。

例如,若要預設為僅將目前分支推送到 origin,請使用 git config remote.origin.push HEAD。任何有效的 <refspec>(例如以下範例中的那些)都可以設定為 git push origin 的預設值。

git push origin :

將「符合」的分支推送到 origin。請參閱上方 OPTIONS 章節中的 <refspec> 以了解「符合」分支的說明。

git push origin master

在來源儲存庫中尋找符合 master 的 ref(最有可能找到 refs/heads/master),並使用它更新 origin 儲存庫中相同的 ref(例如 refs/heads/master)。如果遠端不存在 master,則會建立它。

git push origin HEAD

這是一種將目前分支推送到遠端相同名稱的便捷方式。

git push mothership master:satellite/master dev:satellite/dev

使用符合 master 的來源 ref(例如 refs/heads/master)來更新符合 satellite/master 的 ref(很可能是 refs/remotes/satellite/master)在 mothership 儲存庫中;對 devsatellite/dev 執行相同的操作。

請參閱上方描述 <refspec>... 的章節,以了解有關符合語意的討論。

這是為了模擬在 mothership 上執行 git fetch,使用在相反方向上執行的 git push,以便整合在 satellite 上完成的工作,當您只能以單向方式建立連線時,通常是必要的(也就是說,satellite 可以 ssh 連線到 mothership,但 mothership 無法啟動與 satellite 的連線,因為後者位於防火牆後方或未執行 sshd)。

satellite 機器上執行此 git push 後,您將 ssh 連線到 mothership 並在那裡執行 git merge,以完成對 mothership 上執行的 git pull 的模擬,以提取在 satellite 上所做的變更。

git push origin HEAD:master

將目前分支推送到 origin 儲存庫中符合 master 的遠端 ref。此形式對於在不考慮其本地名稱的情況下推送目前分支很方便。

git push origin master:refs/heads/experimental

透過複製目前 master 分支,在 origin 儲存庫中建立分支 experimental。只有在本地名稱和遠端名稱不同時,才需要使用此形式在遠端儲存庫中建立新的分支或標籤;否則,ref 名稱本身即可運作。

git push origin :experimental

origin 儲存庫中尋找符合 experimental 的 ref(例如 refs/heads/experimental),並將其刪除。

git push origin +dev:master

使用 dev 分支更新 origin 儲存庫的 master 分支,允許非快轉更新。這可能會在 origin 儲存庫中留下懸空的未參考 commit。 考慮以下情況,其中無法進行快轉:

	    o---o---o---A---B  origin/master
		     \
		      X---Y---Z  dev

上面的命令會將 origin 儲存庫變更為:

		      A---B  (unnamed branch)
		     /
	    o---o---o---X---Y---Z  master

Commit A 和 B 將不再屬於具有符號名稱的分支,因此將無法存取。因此,這些 commit 將被 origin 儲存庫上的 git gc 命令刪除。

安全性

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

已知的攻擊向量如下:

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

  2. 如 #1 所示,攻擊者選擇要竊取的物件 ID X。受害者傳送攻擊者已經擁有的物件 Y,而攻擊者謊稱擁有 X 而沒有 Y,因此受害者將 Y 作為相對於 X 的增量傳送。該增量向攻擊者揭露與 Y 相似的 X 區域。

設定

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

push.autoSetupRemote

如果設定為「true」,則在目前分支不存在上游追蹤時,假設預設推送時使用 --set-upstream;此選項在 push.default 選項 *simple*、*upstream* 和 *current* 中生效。如果您預設希望將新分支推送到預設遠端(例如 *push.default=current* 的行為),並且也希望設定上游追蹤,則此選項很有用。最可能從此選項中受益的工作流程是 *simple* 中央工作流程,其中所有分支預期在遠端具有相同的名稱。

push.default

定義在未給定 refspec 時,git push 應採取的動作(無論是來自命令列、設定或任何其他地方)。不同的值非常適合特定的工作流程;例如,在純粹的中央工作流程中(也就是說,fetch 來源等於 push 目的地),您可能想要 upstream。可能的值為:

  • nothing - 除非給定 refspec,否則不推送任何內容(發生錯誤)。這主要是為那些想要避免錯誤並始終明確的人設計的。

  • current - 推送目前分支以更新接收端上具有相同名稱的分支。適用於中央和非中央工作流程。

  • upstream - 將目前分支推回通常將變更整合到目前分支的分支(稱為 @{upstream})。如果您要推送到通常會從中提取的相同儲存庫(也就是說,中央工作流程),則此模式才有意義。

  • tracking - 這是 upstream 的已棄用同義詞。

  • simple - 將目前分支以相同的名稱推送到遠端。

    如果您正在使用集中式工作流程(推送到您從中提取的相同儲存庫,通常是 origin),則需要設定具有相同名稱的上游分支。

    自 Git 2.0 以來,此模式為預設值,並且是最適合初學者最安全的選項。

  • matching - 推送兩端具有相同名稱的所有分支。這會讓您推送到的儲存庫記住將推送的分支集合(例如,如果您始終在那裡推送 *maint* 和 *master*,而沒有其他分支,則您推送到的儲存庫將擁有這兩個分支,並且您的本地 *maint* 和 *master* 將被推送到那裡)。

    為了有效地使用此模式,您必須確保您要推送的所有分支都已準備好在執行 *git push* 之前推送,因為此模式的重點是讓您一次推送所有分支。如果您通常只完成一個分支的工作並推送結果,而其他分支未完成,則此模式不適合您。此外,此模式不適合推送到共用的中央儲存庫,因為其他人可能會在那裡新增新的分支,或在您無法控制的情況下更新現有分支的頂端。

    這過去是預設值,但自 Git 2.0 以來已不是(simple 是新的預設值)。

push.followTags

如果設定為 true,則預設啟用 --follow-tags 選項。您可以透過指定 --no-follow-tags 在推送時覆寫此設定。

push.gpgSign

可以設定為布林值或字串 *if-asked*。true 值會導致所有推送都經過 GPG 簽名,就好像將 --signed 傳遞給 git-push[1] 一樣。字串 *if-asked* 會導致在伺服器支援的情況下對推送進行簽名,就好像將 --signed=if-asked 傳遞給 *git push* 一樣。false 值可能會覆寫優先順序較低的設定檔中的值。明確的命令列標誌始終會覆寫此設定選項。

push.pushOption

當未從命令列給定 --push-option=<option> 引數時,git push 的行為就好像此變數的每個 <value> 都被給定為 --push-option=<value> 一樣。

這是一個多值變數,並且可以在優先順序較高的設定檔中(例如儲存庫中的 .git/config)使用空值,以清除從優先順序較低的設定檔(例如 $HOME/.gitconfig)繼承的值。

Example:

/etc/gitconfig
  push.pushoption = a
  push.pushoption = b

~/.gitconfig
  push.pushoption = c

repo/.git/config
  push.pushoption =
  push.pushoption = b

This will result in only b (a and c are cleared).
push.recurseSubmodules

可以是「check」、「on-demand」、「only」或「no」,其行為與「push --recurse-submodules」的行為相同。如果未設定,則預設使用 *no*,除非設定了 *submodule.recurse*(在這種情況下,*true* 值表示 *on-demand*)。

push.useForceIfIncludes

如果設定為「true」,則等同於在命令列中使用 git-push[1] 時指定 --force-if-includes 選項。在推送時加入 --no-force-if-includes 會覆蓋此設定。

push.negotiate

如果設定為「true」,會嘗試透過多輪協商來縮減發送的 packfile 大小,在此協商過程中,客戶端和伺服器會嘗試找出共同的 commit。如果設定為「false」,Git 將僅依靠伺服器的 ref 宣告來找出共同的 commit。

push.useBitmaps

如果設定為「false」,則會停用 "git push" 使用 bitmap,即使 pack.useBitmaps 為「true」也一樣,但不會阻止其他 git 操作使用 bitmap。預設值為 true。

GIT

git[1] 套件的一部分

scroll-to-top