?
本文檔使用 php中文網(wǎng)手冊 發(fā)布
git-push - 更新遠(yuǎn)程引用以及關(guān)聯(lián)的對象
git push [--all | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-v | --verbose] [-u | --set-upstream] [--push-option=<string>] [--[no-]signed|--sign=(true|false|if-asked)] [--force-with-lease[=<refname>[:<expect>]]] [--no-verify] [<repository> [<refspec>…]]
使用本地引用更新遠(yuǎn)程引用,同時發(fā)送完成給定引用所需的對象。
您可以在每次進(jìn)入存儲庫時通過在存儲庫中設(shè)置有趣的事情hooks
。請參閱 git-receive-pack [1] 的文檔。
當(dāng)命令行未指定將<repository>
參數(shù)推branch.*.remote
送到何處時,將查閱當(dāng)前分支的配置以確定推送的位置。如果配置丟失,則默認(rèn)為origin
。
當(dāng)在命令行中沒有指定,可以把什么<refspec>...
參數(shù)或--all
,--mirror
,--tags
選項,該命令將查找默認(rèn)<refspec>
通過咨詢remote.*.push
配置,如果沒有找到它,榮譽(yù)push.default
配置來決定推什么(請查看 git-config[1]為)push.default
的意思。
如果命令行和配置均未指定要推送的內(nèi)容,則使用默認(rèn)行為,該行為對應(yīng)于以下simple
值push.default
:當(dāng)前分支被推送到相應(yīng)的上游分支,但作為安全措施,如果上游分公司不具有與本地名稱相同的名稱。
<repository>
作為推送操作目標(biāo)的“遠(yuǎn)程”存儲庫。此參數(shù)可以是 URL(請參閱下面的 GIT URLS 部分)或遠(yuǎn)程名稱(請參閱下面的 REMOTES 部分)。
<refspec>…
指定源對象要更新的目標(biāo)引用。一個 <refspec> 參數(shù)的格式是一個可選的 plus +
,后面是源對象 <src> ,后面是一個冒號:
,后面是目標(biāo) ref <dst> 。
<src> 通常是您想要推送的分支的名稱,但它可以是任意的“SHA-1表達(dá)式”,例如master~4
或
HEAD
(請參閱
gitrevisions [7] )。
<dst> 通過這個推送來告訴遠(yuǎn)程端的哪個 ref 被更新。任意表達(dá)式不能在這里使用,必須命名實(shí)際的引用。如果git push [<repository>]
沒有任何<refspec>
參數(shù)設(shè)置為<src>
使用remote.<repository>.push
配置變量更新目標(biāo)中的某個 ref ,:<dst>
則可以省略部分 - 這樣的推送將更新<src>
通常<refspec>
在命令行上沒有任何更新的 ref 。否則,缺少:<dst>
意味著更新相同的參考作為<src>
。
由 <src> 引用的對象用于更新遠(yuǎn)程端的 <dst> 引用。默認(rèn)情況下,只有當(dāng) <dst> 不是標(biāo)簽(帶注釋或輕量級標(biāo)簽)時才允許使用,并且只有在它可以快速轉(zhuǎn)發(fā) <dst> 時才允許使用。通過具有可選的領(lǐng)導(dǎo)+
,你可以讓 Git 更新 <DST> REF 即使是默認(rèn)不允許的(比如,它不是一個快進(jìn)。)這并不會試圖合并<來源>為
<DST> 。有關(guān)詳細(xì)信息,請參閱下面的示例。
tag <tag>
means the same as refs/tags/<tag>:refs/tags/<tag>
.
推送一個空的 <src>允許你從遠(yuǎn)程倉庫中刪除 <dst> ref 。
特殊 refspec :
(或+:
允許非快進(jìn)更新)指示 Git 推送“匹配”分支:對于本地存在的每個分支,如果遠(yuǎn)程已存在的同名分支已經(jīng)存在,則更新遠(yuǎn)程端側(cè)。
--all
推送所有分支(即參考下refs/heads/
); 不能與其他
<refspec> 一起使用。
--prune
刪除沒有本地副本的遠(yuǎn)程分支。例如,tmp
如果具有相同名稱的本地分支不再存在,則遠(yuǎn)程分支將被刪除。這也尊重
refspecs ,例如git push --prune remote refs/heads/*:refs/tmp/*
,refs/tmp/foo
如果refs/heads/foo
不存在,將確保遠(yuǎn)程將被刪除。
--mirror
代替命名每個裁判推的,指定了下的所有參考文獻(xiàn)refs/
(包括但不限于refs/heads/
,refs/remotes/
和refs/tags/
)被鏡像到遠(yuǎn)程存儲庫。新創(chuàng)建的本地參考將被推送到遠(yuǎn)端,本地更新的參考將在遠(yuǎn)端強(qiáng)制更新,刪除的參考將從遠(yuǎn)端移除。如果remote.<remote>.mirror
設(shè)置了配置選項,這是默認(rèn)值。
-n --dry-run
做除了實(shí)際發(fā)送更新之外的其他事
--porcelain
生成機(jī)器可讀的輸出。每個 ref 的輸出狀態(tài)行將被制表符分隔并發(fā)送到 stdout 而不是 stderr 。將給出參考文獻(xiàn)的完整符號名稱。
--delete
所有列出的 ref 都從遠(yuǎn)程存儲庫中刪除。這與用冒號前綴所有引用相同。
--tags
refs/tags
除了在命令行中明確列出的 refspecs 之外,所有
refs 都將被推送。
--follow-tags
推送所有沒有此選項時將被推送的引用,并且推送refs/tags
遠(yuǎn)程引用中缺少的帶注釋的標(biāo)簽,但指向可從所推送的引用訪問的提交標(biāo)識。這也可以通過配置變量來指定push.followTags
。有關(guān)更多信息,請參閱push.followTags
git-config [1]。
--no-signed --sign=(true|false|if-asked)
GPG - 簽署推送請求以更新接收端的 refs,以便通過鉤子檢查和/或記錄。如果false
或者--no-signed
,不會嘗試簽名。如果true
或者--signed
,如果服務(wù)器不支持簽名推送,推送將失敗。如果設(shè)置為if-asked
,則當(dāng)且僅當(dāng)服務(wù)器支持簽名推送時簽名。如果實(shí)際的呼叫gpg --sign
失敗,推送也會失敗。有關(guān)接收端的詳細(xì)信息,請參閱 git-receive-pack [1]。
--no-atomic
如果可用,請在遠(yuǎn)程端使用原子事務(wù)。要么所有的參考文獻(xiàn)都被更新,要么出錯,沒有參考文獻(xiàn)被更新。如果服務(wù)器不支持原子推送,推送將失敗。
-o --push-option
將給定的字符串傳送給服務(wù)器,服務(wù)器將它們傳遞給預(yù)接收以及接收后掛接。給定的字符串不能包含 NUL 或 LF 字符。
--receive-pack=<git-receive-pack> --exec=<git-receive-pack>
git-receive-pack
遠(yuǎn)程端程序的路徑。通過 ssh 推送到遠(yuǎn)程存儲庫時有用,而且您沒有默認(rèn) $ PATH 目錄中的程序。
--no-force-with-lease --force-with-lease=<refname> --force-with-lease=<refname>:<expect>
通常,“git push”拒絕更新一個不是本地 ref 的祖先的遠(yuǎn)程 ref ,用于覆蓋它。
如果遠(yuǎn)程 ref 的當(dāng)前值是期望值,則此選項將覆蓋此限制。否則,“git push”會失敗。
想象一下,你必須重新發(fā)布你已經(jīng)發(fā)布的內(nèi)容。您將不得不繞過“必須快進(jìn)”規(guī)則,以便用最新發(fā)布的歷史記錄替換您最初發(fā)布的歷史記錄。如果其他人在重新裝修時建立在原始?xì)v史的基礎(chǔ)上,則遙控器分支的尖端可能會隨著承諾而前進(jìn),而盲目推動--force
則會失去她的工作。
這個選項允許你說你期望你正在更新的歷史是你重新設(shè)計和想要取代的。如果遠(yuǎn)程引用仍然指向你指定的提交,你可以確定沒有其他人對引用做任何事情。這就像在 ref 上“租賃”而不顯式鎖定它,只有當(dāng)“租約”仍然有效時才更新遠(yuǎn)程參考。
--force-with-lease
單獨(dú)的,沒有指定細(xì)節(jié),將通過要求它們的當(dāng)前值與我們對它們的遠(yuǎn)程跟蹤分支相同來保護(hù)將被更新的所有遠(yuǎn)程參考。
--force-with-lease=<refname>
,而不指定期望值,如果它將要更新,將通過要求它的當(dāng)前值與我們?yōu)樗倪h(yuǎn)程跟蹤分支相同來保護(hù)指定的 ref(單獨(dú))。
--force-with-lease=<refname>:<expect>
將保護(hù)指定的
ref(單獨(dú)),如果它將被更新,則通過要求其當(dāng)前值與指定值相同<expect>
(其可以不同于我們針對 refname 的遠(yuǎn)程跟蹤分支),或者當(dāng)使用這種形式時,我們甚至不需要有這樣的遠(yuǎn)程追蹤分支)。如果<expect>
是空字符串,那么命名的 ref 必須不存在。
請注意,除此之外的所有形式--force-with-lease=<refname>:<expect>
明確指定 ref 的預(yù)期當(dāng)前值仍然是實(shí)驗性的,并且隨著我們獲得此功能的經(jīng)驗,它們的語義可能會改變。
“--no-force-with-lease”將在命令行中取消之前的所有--force-with-lease。
安全的一般注意事項:無預(yù)期值提供這個選項,即作為--force-with-lease
或--force-with-lease=<refname>
任何事情非常糟糕交互隱含運(yùn)行git fetch
遙控器上的在后臺推到,例如git fetch origin
在一個你存儲庫的 cronjob 。
它提供的保護(hù)措施--force
是確保您的工作不基于的后續(xù)更改不會被破壞,但如果某些后臺進(jìn)程正在更新后臺中的 refs ,則會被輕微擊敗。除了遠(yuǎn)程追蹤信息外,我們沒有任何東西可以作為啟發(fā)式參考,您預(yù)計會看到并愿意詆毀。
如果您的編輯器或其他系統(tǒng)正在git fetch
后臺運(yùn)行,則可以采取以下措施來簡化此操作:只需設(shè)置另一個遠(yuǎn)程設(shè)備:
git remote add origin-push $(git config remote.origin.url)git fetch origin-push
現(xiàn)在當(dāng)后臺進(jìn)程運(yùn)行時git fetch origin
,引用origin-push
將不會被更新,因此命令如下所示:
git push --force-with-lease origin-push
除非您手動運(yùn)行,否則會失敗git fetch origin-push
。這種方法當(dāng)然完全被運(yùn)行的東西擊敗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
即為上游代碼的版本創(chuàng)建一個標(biāo)簽,這些代碼是您已經(jīng)看到并愿意覆蓋的版本,然后重寫歷史記錄,最后master
在遠(yuǎn)程版本仍在時強(qiáng)制推送更改base
,無論您的本地remotes/origin/master
更新為背景。
-f --force
通常,該命令拒絕更新遠(yuǎn)程 ref ,該遠(yuǎn)程 ref 不是用于覆蓋它的本地 ref 的祖先。另外,當(dāng)使用--force-with-lease
選項時,該命令拒絕更新當(dāng)前值與預(yù)期值不匹配的遠(yuǎn)程參考。
該標(biāo)志會禁用這些檢查,并可能導(dǎo)致遠(yuǎn)程存儲庫丟失提交; 小心使用它。
請注意,--force
適用于所有推入的 ref,因此使用它push.default
設(shè)置為matching
或配置有多個推送目標(biāo),remote.*.push
可能會覆蓋當(dāng)前分支以外的引用(包括嚴(yán)格位于其遠(yuǎn)程對象之后的本地引用)。要強(qiáng)制只推送一個分支,可以使用+
refspec前面的一個按鈕(例如git push origin +master
強(qiáng)制推送master
分支)。有關(guān)<refspec>...
詳情,請參閱上面的部分。
--repo=<repository>
該選項等同于 <repository> 參數(shù)。如果兩者都指定,則命令行參數(shù)優(yōu)先。
-u --set-upstream
對于最新或成功推送的每個分支,添加無參數(shù) git-pull [1] 和其他命令使用的上游(跟蹤)引用。有關(guān)更多信息,請參閱branch.<name>.merge
git-config [1]。
--no-thin
這些選項被傳遞給 git-send-pack [1]。當(dāng)發(fā)送方和接收方共享許多相同的對象時,精簡傳輸可顯著減少發(fā)送的數(shù)據(jù)量。默認(rèn)值是 --thin 。
-q --quiet
抑制所有輸出,包括更新的引用列表,除非發(fā)生錯誤。進(jìn)度未報告給標(biāo)準(zhǔn)錯誤流。
-v --verbose
運(yùn)行詳細(xì)。
--progress
當(dāng)連接到終端時,默認(rèn)情況下,標(biāo)準(zhǔn)錯誤流中會報告進(jìn)度狀態(tài),除非指定了 -q 。即使標(biāo)準(zhǔn)錯誤流未定向到終端,此標(biāo)志也會強(qiáng)制進(jìn)度狀態(tài)。
- no-recurse-submodules --recurse-submodules = check | on-demand | only | no
可用于確保所推送的版本所使用的所有子模塊提交在遠(yuǎn)程跟蹤分支上可用。如果check
使用,Git 將驗證子模塊的至少一個遠(yuǎn)程模塊上是否有可供推送中修改的所有子模塊提交。如果缺少任何提交,推送將被中止并以非零狀態(tài)退出。如果on-demand
使用了所有在修訂中被更改的子模塊將被推送。如果按需無法推送所有必需的修訂,它也會被中止并以非零狀態(tài)退出。如果only
使用了所有子模塊,則在超級項目處于未放置狀態(tài)時將遞歸推送所有子模塊。值no
或使用--no-recurse-submodules
可用于在不需要子模塊遞歸時覆蓋 push.recurseSubmodules 配置變量。
--no-verify
切換預(yù)推鉤(見 githooks [5])。默認(rèn)值是 - 驗證,使鉤子有機(jī)會阻止推送。使用 --no-verify ,掛鉤完全被旁路。
-4 --ipv4
僅使用 IPv4 地址,忽略 IPv6 地址。
-6 --ipv6
僅使用 IPv6 地址,忽略 IPv4 地址。
通常,URL 包含有關(guān)傳輸協(xié)議,遠(yuǎn)程服務(wù)器地址和存儲庫路徑的信息。根據(jù)傳輸協(xié)議,這些信息可能不存在。
Git 支持 ssh,git,http 和 https 協(xié)議(另外,ftp 和 ftps 可用于提取,但效率低下,不推薦使用;不要使用它)。
本地傳輸(即 git:// URL)不進(jìn)行身份驗證,因此在不安全的網(wǎng)絡(luò)上應(yīng)謹(jǐn)慎使用。
以下語法可以與它們一起使用:
ssh://user@host.xz:port/path/to/repo.git/
git://host.xz:port/path/to/repo.git/
https://host.xz:port/path/to/repo.git/
ftps://host.xz:port/path/to/repo.git/
ssh 協(xié)議也可以使用另一種類似 scp 的語法:
user@host.xz:path / to / repo.git /只有在第一個冒號前沒有斜線時才能識別此語法。這有助于區(qū)分包含冒號的本地路徑。例如,本地路徑foo:bar
可以被指定為絕對路徑或./foo:bar
避免被誤解為 ssh url 。ssh 和 git 協(xié)議還支持用戶名擴(kuò)展:
ssh://user@host.xz:port/~user/path/to/repo.git/
git://host.xz:port/~user/path/to/repo.git/
user@host.xz:/~user/path/to/repo.git/
對于本地支持的本地存儲庫,可以使用以下語法:
/path/to/repo.git/
file:///path/to/repo.git/
這兩種語法大多是相同的,除了克隆時,前者意味著 --local 選項。有關(guān)詳細(xì)信息,請參閱 git-clone [1]。
當(dāng) Git 不知道如何處理某個傳輸協(xié)議時,它會嘗試使用remote-<transport>
遠(yuǎn)程助手(如果存在)。要顯式請求遠(yuǎn)程助手,可以使用以下語法:
<transport>::<address>where <address> may be a path, a server and path, or an arbitrary URL-like string recognized by the specific remote helper being invoked. See gitremote-helpers[1] for details.If there are a large number of similarly-named remote repositories and you want to use a different format for them (such that the URLs you use will be rewritten into URLs that work), you can create a configuration section of the form: [url "<actual url base>"]
insteadOf = <other url base>For example, with this: [url "git://git.host.xz/"]
insteadOf = host.xz:/path/to/
insteadOf = work:a URL like "work:repo.git" or like "host.xz:/path/to/repo.git" will be rewritten in any context that takes a URL to be "git://git.host.xz/repo.git".If you want to rewrite URLs for push only, you can create a configuration section of the form: [url "<actual url base>"]
pushInsteadOf = <other url base>For example, with this: [url "ssh://example.org/"]
pushInsteadOf = git://example.org/a URL like "git://example.org/path/to/repo.git" will be rewritten to "ssh://example.org/path/to/repo.git" for pushes, but pulls will still use the original URL.RemotesThe name of one of the following can be used instead of a URL as <repository>
argument:
a remote in the Git configuration file: $GIT_DIR/config
,
a file in the $GIT_DIR/remotes
directory, or
a file in the $GIT_DIR/branches
directory.
All of these also allow you to omit the refspec from the command line because they each contain a refspec which git will use by default.
You can choose to provide the name of a remote which you had previously configured using git-remote[1], git-config[1] or even by a manual edit to the $GIT_DIR/config
file. The URL of this remote will be used to access the repository. The refspec of this remote will be used by default when you do not provide a refspec on the command line. The entry in the config file would appear like this:
[remote "<name>"] url = <url> pushurl = <pushurl> push = <refspec> fetch = <refspec>
The <pushurl>
is used for pushes only. It is optional and defaults to <url>
.
$GIT_DIR/remotes
You can choose to provide the name of a file in $GIT_DIR/remotes
. The URL in this file will be used to access the repository. The refspec in this file will be used as default when you do not provide a refspec on the command line. This file should have the following format:
URL: one of the above URL format Push: <refspec> Pull: <refspec>
Push:
lines are used by git push
and Pull:
lines are used by git pull
and git fetch
. Multiple Push:
and Pull:
lines may be specified for additional branch mappings.
$GIT_DIR/branches
You can choose to provide the name of a file in $GIT_DIR/branches
. The URL in this file will be used to access the repository. This file should have the following format:
<url>#<head>
<url>
is required; #<head>
is optional.
Depending on the operation, git will use one of the following refspecs, if you don’t provide one on the command line. <branch>
is the name of this file in $GIT_DIR/branches
and <head>
defaults to master
.
git fetch uses:
refs/heads/<head>:refs/heads/<branch>
git push uses:
HEAD:refs/heads/<head>
The output of "git push" depends on the transport method used; this section describes the output when pushing over the Git protocol (either locally or via ssh).
The status of the push is output in tabular form, with each line representing the status of a single ref. Each line is of the form:
<flag> <summary> <from> -> <to> (<reason>)
If --porcelain is used, then each line of the output is of the form:
<flag> \t <from>:<to> \t <summary> (<reason>)
The status of up-to-date refs is shown only if --porcelain or --verbose option is used.
flag
A single character indicating the status of the ref:
(space)
for a successfully pushed fast-forward;
+
for a successful forced update;
-
for a successfully deleted ref;
*
for a successfully pushed new ref;
!
for a ref that was rejected or failed to push; and
=
for a ref that was up to date and did not need pushing.
summary
For a successfully pushed ref, the summary shows the old and new values of the ref in a form suitable for using as an argument to git log
(this is <old>..<new>
in most cases, and <old>...<new>
for forced non-fast-forward updates).
For a failed update, more details are given:
rejected
Git did not try to send the ref at all, typically because it is not a fast-forward and you did not force the update.
remote rejected
The remote end refused the update. Usually caused by a hook on the remote side, or because the remote repository has one of the following safety options in effect: receive.denyCurrentBranch
(for pushes to the checked out branch), receive.denyNonFastForwards
(for forced non-fast-forward updates), receive.denyDeletes
or receive.denyDeleteCurrent
. See git-config[1].
remote failure
The remote end did not report the successful update of the ref, perhaps because of a temporary error on the remote side, a break in the network connection, or other transient error.
from
The name of the local ref being pushed, minus its refs/<type>/
prefix. In the case of deletion, the name of the local ref is omitted.
to
The name of the remote ref being updated, minus its refs/<type>/
prefix.
reason
A human-readable explanation. In the case of successfully pushed refs, no explanation is needed. For a failed ref, the reason for failure is described.
When an update changes a branch (or more in general, a ref) that used to point at commit A to point at another commit B, it is called a fast-forward update if and only if B is a descendant of A.
In a fast-forward update from A to B, the set of commits that the original commit A built on top of is a subset of the commits the new commit B builds on top of. Hence, it does not lose any history.
In contrast, a non-fast-forward update will lose history. For example, suppose you and somebody else started at the same commit X, and you built a history leading to commit B while the other person built a history leading to commit A. The history looks like this:
B / ---X---A
Further suppose that the other person already pushed changes leading to A back to the original repository from which you two obtained the original commit X.
The push done by the other person updated the branch that used to point at commit X to point at commit A. It is a fast-forward.
But if you try to push, you will attempt to update the branch (that now points at A) with commit B. This does not
fast-forward. If you did so, the changes introduced by commit A will be lost, because everybody will now start building on top of B.
The command by default does not allow an update that is not a fast-forward to prevent such loss of history.
If you do not want to lose your work (history from X to B) or the work by the other person (history from X to A), you would need to first fetch the history from the repository, create a history that contains changes done by both parties, and push the result back.
You can perform "git pull", resolve potential conflicts, and "git push" the result. A "git pull" will create a merge commit C between commits A and B.
B---C / / ---X---A
Updating A with the resulting merge commit will fast-forward and your push will be accepted.
Alternatively, you can rebase your change between X and B on top of A, with "git pull --rebase", and push the result back. The rebase will create a new commit D that builds the change between X and B on top of A.
B D / / ---X---A
Again, updating A with this commit will fast-forward and your push will be accepted.
There is another common situation where you may encounter non-fast-forward rejection when you try to push, and it is possible even when you are pushing into a repository nobody else pushes into. After you push commit A yourself (in the first picture in this section), replace it with "git commit --amend" to produce commit B, and you try to push it out, because forgot that you have pushed A out already. In such a case, and only if you are certain that nobody in the meantime fetched your earlier commit A (and started building on top of it), you can run "git push --force" to overwrite it. In other words, "git push --force" is a method reserved for a case where you do mean to lose history.
git push
Works like git push <remote>
, where <remote> is the current branch’s remote (or origin
, if no remote is configured for the current branch).
git push origin
Without additional configuration, pushes the current branch to the configured upstream (remote.origin.merge
configuration variable) if it has the same name as the current branch, and errors out without pushing otherwise.
The default behavior of this command when no <refspec> is given can be configured by setting the push
option of the remote, or the push.default
configuration variable.
For example, to default to pushing only the current branch to origin
use git config remote.origin.push HEAD
. Any valid <refspec> (like the ones in the examples below) can be configured as the default for git push origin
.
git push origin :
Push "matching" branches to origin
. See <refspec> in the OPTIONS section above for a description of "matching" branches.
git push origin master
Find a ref that matches master
in the source repository (most likely, it would find refs/heads/master
), and update the same ref (e.g. refs/heads/master
) in origin
repository with it. If master
did not exist remotely, it would be created.
git push origin HEAD
A handy way to push the current branch to the same name on the remote.
git push mothership master:satellite/master dev:satellite/dev
Use the source ref that matches master
(e.g. refs/heads/master
) to update the ref that matches satellite/master
(most probably refs/remotes/satellite/master
) in the mothership
repository; do the same for dev
and satellite/dev
.
This is to emulate git fetch
run on the mothership
using git push
that is run in the opposite direction in order to integrate the work done on satellite
, and is often necessary when you can only make connection in one way (i.e. satellite can ssh into mothership but mothership cannot initiate connection to satellite because the latter is behind a firewall or does not run sshd).
After running this git push
on the satellite
machine, you would ssh into the mothership
and run git merge
there to complete the emulation of git pull
that were run on mothership
to pull changes made on satellite
.
git push origin HEAD:master
Push the current branch to the remote ref matching master
in the origin
repository. This form is convenient to push the current branch without thinking about its local name.
git push origin master:refs/heads/experimental
Create the branch experimental
in the origin
repository by copying the current master
branch. This form is only needed to create a new branch or tag in the remote repository when the local name and the remote name are different; otherwise, the ref name on its own will work.
git push origin :experimental
Find a ref that matches experimental
in the origin
repository (e.g. refs/heads/experimental
), and delete it.
git push origin +dev:master
Update the origin repository’s master branch with the dev branch, allowing non-fast-forward updates. This can leave unreferenced commits dangling in the origin repository. Consider the following situation, where a fast-forward is not possible:
o---o---o---A---B origin/master \ X---Y---Z dev
The above command would change the origin repository to
A---B (unnamed branch) / o---o---o---X---Y---Z master
Commits A and B would no longer belong to a branch with a symbolic name, and so would be unreachable. As such, these commits would be removed by a git gc
command on the origin repository.
The fetch and push protocols are not designed to prevent one side from stealing data from the other repository that was not intended to be shared. If you have private data that you need to protect from a malicious peer, your best option is to store it in another repository. This applies to both clients and servers. In particular, namespaces on a server are not effective for read access control; you should only grant read access to a namespace to clients that you would trust with read access to the entire repository.
The known attack vectors are as follows:
The victim sends "have" lines advertising the IDs of objects it has that are not explicitly intended to be shared but can be used to optimize the transfer if the peer also has them. The attacker chooses an object ID X to steal and sends a ref to X, but isn’t required to send the content of X because the victim already has it. Now the victim believes that the attacker has X, and it sends the content of X back to the attacker later. (This attack is most straightforward for a client to perform on a server, by creating a ref to X in the namespace the client has access to and then fetching it. The most likely way for a server to perform it on a client is to "merge" X into a public branch and hope that the user does additional work on this branch and pushes it back to the server without noticing the merge.)
As in #1, the attacker chooses an object ID X to steal. The victim sends an object Y that the attacker already has, and the attacker falsely claims to have X and not Y, so the victim sends Y as a delta against X. The delta reveals regions of X that are similar to Y to the attacker.