簡體中文 ▾ 主題 ▾ 最新版本 ▾ git-push 最後更新於 2.48.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 配置來決定推送內容(有關 push.default 的含義,請參閱 git-config[1])。

當命令列和配置均未指定推送內容時,將使用預設行為,這對應於 push.defaultsimple 值:當前分支被推送到相應的上游分支,但作為一項安全措施,如果上游分支與本地分支名稱不同,則推送會被中止。

選項

<倉庫>

作為推送操作目的地的“遠端”倉庫。此引數可以是 URL(參見下面的 GIT URL 部分)或遠端名稱(參見下面的 遠端 部分)。

<引用規範>…​

指定用哪個源物件更新哪個目標引用。<引用規範> 引數的格式是可選的加號 +,後跟源物件 <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> 是否模稜兩可,嘗試推斷它在目標 <倉庫> 的 refs/* 中的位置。

  • 如果 <dst> 明確地指向 <倉庫> 遠端上的一個引用,則推送到該引用。

  • 如果 <src> 解析為以 refs/heads/ 或 refs/tags/ 開頭的引用,則將其前置到 <dst>。

  • 未來可能會增加其他歧義解析,但目前任何其他情況都會報錯,指出我們嘗試過什麼,並根據 advice.pushUnqualifiedRefname 配置(參見 git-config[1])建議您可能希望推送到哪個 refs/ 名稱空間。

<src> 引用的物件用於更新遠端端的 <dst> 引用。這是否允許取決於 <dst> 引用在 refs/* 中的位置,具體描述如下,在這些部分中,“更新”意味著除刪除之外的任何修改,刪除將在接下來的幾節中單獨處理。

refs/heads/* 名稱空間只接受提交物件,並且只有在可以快進的情況下才允許更新。

refs/tags/* 名稱空間接受任何型別的物件(因為提交、樹和 blob 都可以被標記),並且對它們的任何更新都將被拒絕。

可以將任何型別的物件推送到 refs/{tags,heads}/* 之外的任何名稱空間。對於標籤和提交,它們將被視為 refs/heads/* 內部的提交,以決定是否允許更新。

即,允許對 refs/{tags,heads}/* 之外的提交和標籤進行快進,即使在快進的物件不是提交,而是一個標籤物件,並且該標籤物件恰好指向一個新提交,而這個新提交是其替換的最後一個標籤(或提交)的快進時,也允許這樣做。用一個完全不同的標籤替換現有標籤也允許,如果它指向相同的提交,以及推送剝離標籤,即推送現有標籤物件指向的提交,或一個現有提交指向的新標籤物件。

refs/{tags,heads}/* 之外的樹和 blob 物件將被視為與在 refs/tags/* 內部一樣對待,對它們的任何更新都將被拒絕。

上述所有關於不允許更新的規則都可以透過在引用規範前新增可選的 + 號(或使用 --force 命令列選項)來覆蓋。唯一的例外是,無論如何強制,refs/heads/* 名稱空間都不會接受非提交物件。鉤子和配置也可以覆蓋或修改這些規則,例如參見 git-config[1] 中的 receive.denyNonFastForwards 以及 githooks[5] 中的 pre-receiveupdate

推送空的 <src> 允許您從遠端倉庫中刪除 <dst> 引用。除非被配置或鉤子禁止,否則刪除操作總是被接受的,即使引用規範中沒有前導 +(或 --force)。參見 git-config[1] 中的 receive.denyDeletes 以及 githooks[5] 中的 pre-receiveupdate

特殊的引用規範 :(或 +: 以允許非快進更新)指示 Git 推送“匹配”分支:對於本地存在的每個分支,如果遠端端已存在同名分支,則更新遠端端的分支。

tag <tag> 的含義與 refs/tags/<tag>:refs/tags/<tag> 相同。

--all
--branches

推送所有分支(即 refs/heads/ 下的引用);不能與其他 <引用規範> 一起使用。

--prune

刪除沒有本地對應分支的遠端分支。例如,如果同名的本地分支不再存在,則遠端分支 tmp 將被刪除。這也遵循引用規範,例如 git push --prune remote refs/heads/*:refs/tmp/* 將確保如果 refs/heads/foo 不存在,則遠端 refs/tmp/foo 將被刪除。

--mirror

不指定要推送的每個引用,而是指定將 refs/ 下的所有引用(包括但不限於 refs/heads/refs/remotes/refs/tags/)映象到遠端倉庫。新建立的本地引用將被推送到遠端端,本地更新的引用將被強制更新到遠端端,已刪除的引用將從遠端端移除。如果配置選項 remote.<remote>.mirror 已設定,則這是預設行為。

-n
--dry-run

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

--porcelain

生成機器可讀的輸出。每個引用的輸出狀態行將以製表符分隔,併發送到標準輸出而非標準錯誤。將給出引用的完整符號名稱。

-d
--delete

所有列出的引用都將從遠端倉庫中刪除。這與在所有引用前加上冒號的效果相同。

--tags

除了命令列中明確列出的引用規範外,refs/tags 下的所有引用都將被推送。

--follow-tags

推送所有在沒有此選項時會被推送的引用,並且還推送遠端端缺失但指向從被推送引用可達的提交物件的 refs/tags 中的附註標籤。這也可以透過配置變數 push.followTags 指定。欲瞭解更多資訊,請參見 git-config[1] 中的 push.followTags

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

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

--[no-]atomic

如果可用,在遠端端使用原子事務。要麼所有引用都被更新,要麼在發生錯誤時,沒有引用被更新。如果伺服器不支援原子推送,則推送將失敗。

-o <選項>
--push-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=<引用名>
--force-with-lease=<引用名>:<期望值>

通常,“git push”會拒絕更新不是用於覆蓋它的本地引用的祖先的遠端引用。

如果遠端引用的當前值是期望值,此選項將覆蓋此限制。“git push”否則將失敗。

想象一下,您需要變基您已經發布的內容。您將不得不繞過“必須快進”規則,以用變基後的歷史替換您最初發布的歷史。如果您在變基時其他人基於您的原始歷史進行了開發,遠端分支的尖端可能會因他們的提交而前進,盲目地使用 --force 推送將丟失他們的工作。

此選項允許您宣告您期望正在更新的歷史是您已變基並希望替換的內容。如果遠端引用仍然指向您指定的提交,您可以確信沒有其他人對該引用做過任何更改。這就像在引用上“租賃”,而無需顯式鎖定它,並且只有當“租賃”仍然有效時,遠端引用才會被更新。

單獨使用 --force-with-lease,不指定細節時,將透過要求所有將被更新的遠端引用的當前值與其對應的遠端跟蹤分支值相同來保護它們。

單獨使用 --force-with-lease=<refname>,不指定期望值時,將透過要求其當前值與其對應的遠端跟蹤分支值相同來保護指定的引用(單獨),如果它將被更新。

--force-with-lease=<refname>:<expect> 將保護指定的引用(單獨),如果它將被更新,透過要求其當前值與指定值 <expect> 相同(該值可以與我們擁有的該引用名的遠端跟蹤分支不同,或者在使用此形式時我們甚至不必擁有這樣的遠端跟蹤分支)。如果 <expect> 是空字串,則指定的引用不得已存在。

請注意,除明確指定引用期望當前值的 --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 提供的保護是確保您的工作所基於的後續更改不會被覆蓋,但如果某些後臺程序在後臺更新引用,則這種保護很容易失效。除了遠端跟蹤資訊,我們沒有其他任何東西可以作為啟發式地判斷您預期已見過並願意覆蓋的引用。

如果您的編輯器或某些其他系統在後臺為您執行 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 標籤,然後重寫歷史,最後在遠端版本仍處於 base 時強制推送更改到 master,無論您的本地 remotes/origin/master 在後臺更新到了什麼。

或者,在“推送”時將 --force-if-includes 作為輔助選項與 --force-with-lease[=<refname>](即,不說明遠端端引用必須指向哪個確切提交,或遠端端哪些引用受到保護)一起指定,將驗證遠端跟蹤引用(可能已在後臺隱式更新)的更新是否已在本地整合,然後才允許強制更新。

-f
--force

通常,該命令會拒絕更新不是用於覆蓋它的本地引用的祖先的遠端引用。此外,當使用 --force-with-lease 選項時,如果遠端引用的當前值與期望值不匹配,則該命令會拒絕更新該遠端引用。

此標誌停用這些檢查,並可能導致遠端倉庫丟失提交;請謹慎使用。

請注意,--force 適用於所有被推送的引用,因此,將其與設定為 matchingpush.default 或配置了多個推送目標(透過 remote.*.push)一起使用時,可能會覆蓋當前分支以外的引用(包括嚴格落後於其遠端對應項的本地引用)。要強制推送到單個分支,請在推送的引用規範前使用 +(例如 git push origin +master 以強制推送到 master 分支)。有關詳細資訊,請參見上面的 <refspec>... 部分。

--[no-]force-if-includes

僅當遠端跟蹤引用的尖端已在本地整合時才強制更新。

此選項啟用一個檢查,驗證遠端跟蹤引用的尖端是否可從用於重寫的本地分支的“reflog”條目之一到達。該檢查透過在未合併遠端更新時拒絕強制更新,確保任何來自遠端的更新已在本地合併。

如果傳遞該選項而未指定 --force-with-lease,或與 --force-with-lease=<refname>:<expect> 一起指定,則它是一個“無操作”(no-op)。

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

--repo=<倉庫>

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

-u
--set-upstream

對於每個已是最新或已成功推送的分支,新增上游(跟蹤)引用,該引用被無引數的 git-pull[1] 和其他命令使用。有關詳細資訊,請參見 git-config[1] 中的 branch.<name>.merge

--[no-]thin

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

-q
--quiet

抑制所有輸出,包括更新的引用列表,除非發生錯誤。進度不會報告到標準錯誤流。

-v
--verbose

執行詳細模式。

--progress

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

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

可用於確保要推送的修訂版所使用的所有子模組提交都在遠端跟蹤分支上可用。如果使用 *check*,Git 將驗證要推送的修訂版中更改的所有子模組提交在子模組的至少一個遠端上可用。如果缺少任何提交,推送將中止並以非零狀態退出。如果使用 *on-demand*,則將推送要推送的修訂版中更改的所有子模組。如果按需推送未能推送所有必要的修訂版,它也將中止並以非零狀態退出。如果使用 *only*,則所有子模組都將被推送,而超專案則保持未推送狀態。當不需要子模組遞迴時,可以使用值 *no* 或使用 --no-recurse-submodules 來覆蓋 push.recurseSubmodules 配置變數。

當使用 *on-demand* 或 *only* 時,如果子模組有 "push.recurseSubmodules={on-demand,only}" 或 "submodule.recurse" 配置,將發生進一步遞迴。在這種情況下,“only”被視為“on-demand”。

--[no-]verify

切換 pre-push 鉤子(參見 githooks[5])。預設是 --verify,這給鉤子一個阻止推送的機會。使用 --no-verify,鉤子將被完全繞過。

-4
--ipv4

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

-6
--ipv6

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

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,也會接受合適的捆綁檔案。參見 git-bundle[1]

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

  • <傳輸方式>::<地址>

其中 <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>。推送到遠端會影響所有已定義的推送 URL,如果沒有定義推送 URL,則影響所有已定義的 URL。但是,如果定義了多個 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 pullgit 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 push”的輸出取決於所使用的傳輸方法;本節描述透過 Git 協議(本地或透過 ssh)推送時的輸出。

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

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

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

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

僅在使用 --porcelain 或 --verbose 選項時顯示最新引用的狀態。

標誌

一個字元指示引用的狀態

(空格)

表示成功推送的快進;

+

表示成功的強制更新;

-

表示成功刪除的引用;

*

表示成功推送的新引用;

!

表示被拒絕或推送失敗的引用;以及

=

表示最新且無需推送的引用。

摘要

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

對於失敗的更新,將給出更多詳情

被拒絕

Git 根本沒有嘗試傳送該引用,通常是因為它不是快進,並且您沒有強制更新。

遠端拒絕

遠端端拒絕了更新。通常是由於遠端端的鉤子,或者因為遠端倉庫啟用了以下安全選項之一:receive.denyCurrentBranch(用於推送到已檢出分支)、receive.denyNonFastForwards(用於強制非快進更新)、receive.denyDeletesreceive.denyDeleteCurrent。參見 git-config[1]

遠端失敗

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

被推送的本地引用名稱,不包括其 refs/<type>/ 字首。在刪除的情況下,省略本地引用名稱。

目標

被更新的遠端引用名稱,不包括其 refs/<type>/ 字首。

原因

人類可讀的解釋。對於成功推送的引用,無需解釋。對於失敗的引用,將描述失敗原因。

關於快進的說明

當一次更新將一個分支(或更普遍地,一個引用)從指向提交 A 變為指向另一個提交 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,該提交將 X 和 B 之間的更改構建在 A 的頂部。

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

同樣,用此提交更新 A 將進行快進,您的推送將被接受。

還有另一種常見情況,您在嘗試推送時可能會遇到非快進拒絕,即使您推送到沒有人推送的倉庫中也可能發生。在您自己推送提交 A(本節第一張圖片中)之後,用“git commit --amend”將其替換以生成提交 B,然後您嘗試將其推出,因為您忘記了您已經推送了 A。在這種情況下,並且只有在您確定在此期間沒有人抓取您的早期提交 A(並開始在此之上進行構建)時,您才可以執行“git push --force”來覆蓋它。換句話說,“git push --force”是一種僅用於您確實打算丟失歷史記錄的情況的方法。

示例

git push

工作方式類似於 git push <遠端倉庫>,其中 <遠端倉庫> 是當前分支的遠端倉庫(如果當前分支未配置遠端倉庫,則為 origin)。

git push origin

如果沒有額外的配置,如果當前分支的名稱與配置的上游分支(branch.<name>.merge 配置變數)相同,則將當前分支推送到配置的上游分支,否則會報錯而不進行推送。

當未給定 <引用規範> 時,此命令的預設行為可以透過設定遠端的 push 選項或 push.default 配置變數來配置。

例如,要將僅推送當前分支到 origin 設定為預設行為,請使用 git config remote.origin.push HEAD。任何有效的 <引用規範>(如下例所示)都可以配置為 git push origin 的預設值。

git push origin :

推送“匹配”分支到 origin。有關“匹配”分支的描述,請參見上面 選項 部分中的 <引用規範>。

git push origin master

在源倉庫中找到與 master 匹配的引用(很可能找到 refs/heads/master),並用它來更新 origin 倉庫中的相同引用(例如 refs/heads/master)。如果 master 在遠端不存在,則會建立它。

git push origin HEAD

將當前分支推送到遠端同名分支的便捷方式。

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

使用與 master 匹配的源引用(例如 refs/heads/master)來更新 mothership 倉庫中與 satellite/master 匹配的引用(最可能是 refs/remotes/satellite/master);對 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 匹配的遠端引用。這種形式方便在不考慮本地名稱的情況下推送當前分支。

git push origin master:refs/heads/experimental

透過複製當前的 master 分支,在 origin 倉庫中建立分支 experimental。當本地名稱與遠端名稱不同時,才需要此形式在遠端倉庫中建立新分支或標籤;否則,單獨的引用名稱即可。

git push origin :experimental

origin 倉庫中找到與 experimental 匹配的引用(例如 refs/heads/experimental),並刪除它。

git push origin +dev:master

用 dev 分支更新 origin 倉庫的 master 分支,允許非快進更新。**這可能在 origin 倉庫中留下未引用的懸空提交。**

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

考慮以下情況,其中快進不可能發生

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

上述命令將把 origin 倉庫更改為

安全性

提交 A 和 B 將不再屬於具有符號名稱的分支,因此將無法訪問。因此,這些提交將透過在 origin 倉庫上執行 git gc 命令而被刪除。

已知的攻擊向量如下:

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

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

配置

本節中以下所有內容均從 git-config[1] 文件中選擇性地包含。內容與彼處相同:

push.autoSetupRemote

如果設定為“true”,則在當前分支不存在上游跟蹤時,預設推送時假定使用 --set-upstream;此選項對 push.default 選項 *simple*、*upstream* 和 *current* 生效。如果您預設希望將新分支推送到預設遠端倉庫(如同 *push.default=current* 的行為),並且還希望設定上游跟蹤,則此功能很有用。最可能受益於此選項的工作流程是所有分支都預期在遠端上具有相同名稱的*簡單*集中式工作流程。

push.default

定義了在未給定引用規範(無論是來自命令列、配置或其他地方)時 git push 應採取的操作。不同的值適用於特定的工作流程;例如,在純粹的集中式工作流程中(即抓取源等於推送目的地),upstream 可能就是您想要的。可能的值有

  • nothing - 除非給定引用規範,否則不推送任何內容(並報錯)。這主要是為了那些希望透過始終明確來避免錯誤的人。

  • current - 推送當前分支以更新接收端同名的分支。適用於集中式和非集中式工作流程。

  • upstream - 將當前分支推送回通常整合到當前分支的那個分支(即 @{upstream})。僅當您推送到通常從中拉取的同一個倉庫時(即集中式工作流程),此模式才有意義。

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

  • simple - 將當前分支推送到遠端同名分支。

    如果您在集中式工作流程中工作(推送到與您拉取相同的倉庫,通常是 origin),那麼您需要配置一個同名的上游分支。

    自 Git 2.0 起,此模式為預設模式,是最適合初學者的安全選項。

  • matching - 推送兩端同名的所有分支。這使得您要推送到的倉庫會記住將要推送出去的分支集(例如,如果您總是將 maintmaster 推送到那裡,而沒有其他分支,那麼您要推送到的倉庫將擁有這兩個分支,並且您的本地 maintmaster 將被推送到那裡)。

    要有效使用此模式,您必須確保在執行 *git push* 之前,所有要推送的分支都已準備好被推送,因為此模式的全部目的就是讓您一次性推送所有分支。如果您通常只在一個分支上完成工作並推送結果,而其他分支未完成,則此模式不適合您。此外,此模式不適合推送到共享的中心倉庫,因為其他人可能會在那裡新增新分支,或在您控制之外更新現有分支的尖端。

    這曾是預設值,但自 Git 2.0 以來不再是(simple 是新的預設值)。

push.followTags

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

push.gpgSign

可以設定為布林值,或字串 if-asked。true 值會導致所有推送都進行 GPG 簽名,如同向 git-push[1] 傳遞了 --signed。字串 if-asked 會導致推送在伺服器支援時進行簽名,如同向 git push 傳遞了 --signed=if-asked。false 值可以覆蓋來自較低優先順序配置檔案的值。顯式命令列標誌始終會覆蓋此配置選項。

push.pushOption

當命令列中沒有給出 --push-option=<option> 引數時,git push 的行為如同此變數的每個 <值> 都被作為 --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”,則等同於在命令列中將 --force-if-includes 指定為 git-push[1] 的一個選項。在推送時新增 --no-force-if-includes 將覆蓋此配置設定。

push.negotiate

如果設定為“true”,則嘗試透過客戶端和伺服器試圖尋找共同提交的多輪協商來減小發送的 packfile 大小。如果為“false”,Git 將僅依賴伺服器的引用通告來尋找共同提交。

push.useBitmaps

如果設定為“false”,則即使 pack.useBitmaps 為“true”,也會停用“git push”使用點陣圖,但不阻止其他 Git 操作使用點陣圖。預設值為 true。

GIT

Git[1] 套件的一部分

scroll-to-top