一直以來對git push
與git pull
命令的預設行為感覺混亂,今天抽空總結下。
通常對於乙個本地的新建分支,例如git checkout -b develop
, 在develop分支commit了**之後,如果直接執行git push
命令,develop分支將不會被push到遠端倉庫(但此時git push
操作有可能會推送一些**到遠端倉庫,這取決於我們本地git config配置中的push.default
預設行為,下文將會逐一詳解)。
因此我們至少需要顯式指定將要推送的分支名,例如git push origin develop
,才能將本地新分支推送到遠端倉庫。
當我們通過顯式指定分支名進行初次push操作後,本地有了新的commit,此時執行git push
命令會有什麼效果呢?
如果你未曾改動過git config中的push.default
屬性,根據我們使用的git不同版本(git 2.0之前或之後),git push
通常會有兩種截然不同的行為:
develop分支中本地新增的commit被push到遠端倉庫
push失敗,並收到git如下的警告
fatal: the current branch new
hasno upstream branch.
to push the current branch and
set the remote as upstream, use
git push --set-upstream origin develop
為什麼git版本不同會有兩種不同的push行為?
因為在git的全域性配置中,有乙個push.default屬性,其決定了git push
操作的預設行為。在git 2.0之前,這個屬性的預設被設為'matching',2.0之後則被更改為了'******'。
我們可以通過git version
確定當前的git版本(如果小於2.0,更新是個更好的選擇),通過git config --global push.default 'option'
改變push.default的預設行為(或者也可直接編輯~/.gitconfig檔案)。
push.default 有以下幾個可選值:
nothing, current, upstream, ******, matching
其用途分別為:
因此如果我們使用了git2.0之前的版本,push.default = matching,git push後則會推送當前分支**到遠端分支,而2.0之後,push.default = ******,如果沒有指定當前分支的upstream分支,就會收到上文的fatal提示。
說到這裡,需要解釋一下git中的upstream到底是什麼:
git中存在upstream和downstream,簡言之,當我們把倉庫a中某分支x的**push到倉庫b分支y,此時倉庫b的這個分支y就叫做a中x分支的upstream,而x則被稱作y的downstream,這是乙個相對關係,每乙個本地分支都相對地可以有乙個遠端的upstream分支(注意這個upstream分支可以不同名,但通常我們都會使用同名分支作為upstream)。初次提交本地分支,例如
git push origin develop
操作,並不會定義當前本地分支的upstream分支,我們可以通過git push --set-upstream origin develop
,關聯本地develop分支的upstream分支,另乙個更為簡潔的方式是初次push時,加入-u引數,例如git push -u origin develop
,這個操作在push的同時會指定當前分支的upstream。
注意push.default = current可以在遠端同名分支不存在的情況下自動建立同名分支,有些時候這也是個極其方便的模式,比如初次push你可以直接輸入 git push 而不必顯示指定遠端分支。
弄清楚git push
的預設行為後,再來看看git pull
。
there is
no tracking information for the current branch.
please specify which branch you want to merge with.
see git-pull(1) for details
git pull
if you wish to
set tracking information for this branch you can do
so with:
git branch --set-upstream-to=origin/
new1
git pull
的預設行為和git push
完全不同。當我們執行git pull
的時候,實際上是做了git fetch + git merge
操作,fetch操作將會更新本地倉庫的remote tracking,也就是refs/remotes中的**,並不會對refs/heads中本地當前的**造成影響。
當我們進行pull的第二個行為merge時,對git來說,如果我們沒有設定當前分支的upstream,它並不知道我們要合併哪個分支到當前分支,所以我們需要通過下面的**指定當前分支的upstream:
git branch --set-upstream-to=origin/
develop
// 或者git push --set-upstream origin develop
實際上,如果我們沒有指定upstream,git在merge時會訪問git config中當前分支(develop)merge的預設配置,我們可以通過配置下面的內容指定某個分支的預設merge操作
[branch "develop"]
remote = origin
merge = refs/heads/develop // [1]為什麼不是refs/remotes/develop?
或者通過command-line直接設定:
git config branch.develop
.merge refs/heads/develop
這樣當我們在develop分支git pull時,如果沒有指定upstream分支,git將根據我們的config檔案去merge origin/develop
;如果指定了upstream分支,則會忽略config中的merge預設配置。
以上就是git push和git pull操作的全部預設行為,如有錯誤,歡迎斧正
[1] 為什麼merge = refs/heads/develop 而不是refs/remotes/develop?
因為這裡merge指代的是我們想要merge的遠端分支,是remote上的refs/heads/develop,文中即是origin上的refs/heads/develop,這和我們在本地直接執行git merge
是不同的(本地執行git merge origin/develop
則是直接merge refs/remotes/develop)。
refs:
by abruzzi's blog
git push和pull如何解決衝突!!!精品
多人合作完成專案時,git push 和 pull經常會發生衝突,根本原因就是遠端的東西和本地的東西長的不一樣,以下步驟能完美解決所有衝突!先檢視一下分支 git branch 確認沒錯再進行下面的操作 1.找到乙個最新可用的版本,並回退到那 先用 git log 找到乙個可行版本,如 abc.再用...
Git 遠端分支的pull與push
git branch r 檢視遠端分支 git branch a 檢視所有分支,本地和遠端 git remote show remote name 檢視遠端倉庫資訊其中git remote show remote name 展示的資訊包括 git checkout b local origin da...
activemq接收訊息pull與push模式
1。同步和非同步的方式 public static void main string args else 非同步的方式接收訊息 consumer.setmessagelistener new messagelistener catch exception e 非同步接收 catch exceptio...