2017-07-13 33 views
1

(我在下面所描述的本地git倉庫的實驗都發生了什麼。無遠程回購參與。)爲什麼git pull提供了合併的機會,但git push沒有?

我創建2個地方分支機構lb1lb2。它們從相同的提交節點開始。

git branch lb1 
git branch lb2 

我讓它們相互上游。如下:

$ git checkout lb2 
Switched to branch 'lb2' 

$ git branch -u lb1 
Branch lb2 set up to track local branch lb1. 

$ git checkout lb1 
Switched to branch 'lb1' 

$ git branch -u lb2 
Branch lb1 set up to track local branch lb2. 

然後我通過對它們進行不同的改變使它們發散。如下圖所示:

enter image description here

$ git branch -vv 
* lb1 6774aa6 [lb2: ahead 1, behind 1] lb1 change 
    lb2 cdd1247 [lb1: ahead 1, behind 1] lb2 change 

我目前lb1。然後我試圖一個分支(LB1)推到其他(LB2),看看會發生什麼:

$ git push . lb1:lb2 
To . 
! [rejected]  lb1 -> lb2 (non-fast-forward) 
error: failed to push some refs to '.' 
hint: Updates were rejected because a pushed branch tip is behind its remote 
hint: counterpart. Check out this branch and integrate the remote changes 
hint: (e.g. 'git pull ...') before pushing again. 
hint: See the 'Note about fast-forwards' in 'git push --help' for details. 

所以,如果我的理解是正確的,它說,推分支的頂端lb1)的背後是其遠程對方lb2)。我必須先結帳lb1並從lb2拉到整合lb2的變化。

所以我這樣做:(請注意,我在lb1分支現在)

$ git pull 
From . 
* branch   lb2  -> FETCH_HEAD 
Auto-merging file1.txt 
CONFLICT (content): Merge conflict in file1.txt 
Automatic merge failed; fix conflicts and then commit the result. 

所以git pull使我有機會合並。

後,我合併,我可以推lb1lb2

$ git push . lb1:lb2 
Total 0 (delta 0), reused 0 (delta 0) 
To . 
    cdd1247..2dfb555 lb1 -> lb2 

和版本圖是這樣的:

enter image description here

而且lb2的變化是加入lb1的日誌歷史:

enter image description here

總結:

  • LB1 - 推 - > LB2:失敗
  • LB1 < - 拉 - LB2:有機會合並

我的問題是:

爲什麼git push不提供合併的機會?從英語的角度來看,我認爲pushpull是對稱的。所以我期望他們有同樣的結果。

+0

一個失敗的推動意味着分支不是快進,你會重寫一些歷史記錄(或重新編入死亡歷史記錄) –

+1

git pull是git fetch和git merge命令的組合。這就是它提供合併的原因。 git push是一個獨立的命令。 – dunni

+0

@AnthonySottile通過「分支」,我猜你是指推送的目標分支,在我的場景中爲'lb2'。 – smwikipedia

回答

4

我認爲@dunni在評論中指出頭部(即釘入釘板)時,他們提到git pull實際上是兩種不同操作的便利標記。我想挑戰你的問題的斷言是git-pull是對稱的git-push。指出git-fetchgit-push對稱可能更準確。當然,正如你所說的,英語的推拉是非常對立的,然而,這並不一定意味着在其他領域的使用上是對稱的。

至於爲什麼git的實現者決定嘗試一個automerge,我只能推測。我的理論是,因爲工作回購有跟蹤分支這樣的概念,所以自動合併遠程跟蹤分支到本地分支來執行pull操作是有意義的。這是因爲您必須執行合併/快進才能使用處於未分離HEAD狀態的更新。存儲庫必須保持這種分離狀態,以便知道遙控器提供的內容與本地提供的內容。然而,遠程倉庫沒有跟蹤分支這樣的概念:它只是在後臺運行git-receive-pack時更新它的參考。它並不在乎提交什麼提交;這就是爲什麼力推(git push -f)存在。實際上,力推並不是git-pack-protocol中的構造,而只是一個客戶端選項,可以忽略保持歷史記錄完整性的正常檢查。推送時,並不意味着需要合併/快進:您只暗示遠程及其參考列表上的對象數據庫的更新。在客戶端,只需更新遠程跟蹤分支以匹配您成功推送的內容(無論是否強制)。

總結:獲取需要合併,因爲獲取的遠程跟蹤分支必須合併到相應的本地分支中供您在工作存儲庫中使用。然而,推動你可能不一定需要合併;你只是更新遠程分支。

+1

Upvote for「merge the nail into the board」 –

1

你可能應該更好地在git maiilist中提問,但有一個重要的區別:由pull執行的合併仍然是你的個人歷史的一部分。您可以測試它,或者更新合併信息,或者改變主意並重置爲在合併之前提交。你可以花時間解決衝突。

如果git push合併,這個自動合併提交會立即成爲公共歷史的一部分。這也會導致同步問題,以防有人在同一時間推送,合併需要解決衝突或編寫提交消息。

其實,我有一個script試圖實現它,但我不能說我已經看到很多關於它的反饋。現在人們習慣使用大多數個人功能分支,並且只在服務器合併請求時才合併。

相關問題