
上圖讓我們對 git pull 和 git pull --rebase 有一個很好的了解。我對這里的一件事感到困惑。讓我詳細說明——
1. 案例1 -> git pull --rebase origin master
命令后我的本地主分支 - ABCXYD' E'
命令后我的遠程主分支 - ABCXY
如果我現在執行 git push origin master:master,我的遠程 master 分支看起來像 - ABCXYD' E'
2. 案例2 -> git pull origin master
命令后我的本地主分支 - ABCDEF
命令后我的遠程主分支 - ABCXY
在這種情況下 git push origin master:master 將如何表現?我無法理解為什么在任何情況下我們都希望在沒有 --rebase 的情況下使用 git pull?
uj5u.com熱心網友回復:
你缺少的是,我認為,最好通過避免 git pull. 不過,讓我們假設git pull有一個假設--merge選項,以便我們可以說您正在運行git pull --merge origin master. (您已經在進行合并;如果它是顯式選項,則此選項將是默認選項。)也就是說,您的git pull origin master運行相當于:
git fetch origin; 然后git merge -m "merge branch master of <url>" origin/master.
這產生了圖表,他們將其繪制為:
A--B--C--D--E--F <-- master
\ /
X----Y
(我把它橫著這里。90?旋轉CCW相匹配。)
我現在想建議像這樣重新繪制它:
D--E
/ \
A--B--C F <-- master
\ /
X--Y
現在我已經以這種方式繪制了圖形,哪些提交是“在”分支上的master?如果你選擇了A-B-C-D-E-F,你為什么不也選擇X-Y?如果你選擇了A-B-C-X-Y-F,你為什么不也選擇D-E?
事實是,所有八次提交,包括D-E 和 X-Y,都在“on”分支上master。該名稱 master標識提交F,但承諾F是一個合并提交。它可以追溯到兩個不同的提交:E和Y. 這兩個不同的提交分別回傳到D和X,并且這兩個不同的提交回傳到一個共同的共享起點C。
CommitC是兩個提示提交的合并基礎,在您運行 Git 時,通過. 所以Git的發現你做了什么,上至-腿,通過運行在提交的快照之間的差異和。然后Git的發現,他們做了什么,上至-腿,通過之間運行DIFF和。然后 Git 獲取兩個差異并將它們組合起來,將組合結果應用到來自 commit 的共享快照,并使用它來進行新的合并提交。git mergegit pullCECECYCYCF
合并提交F有一個快照,就像其他所有提交一樣。它與其他提交的不同之處在于它有兩個父級,E并且Y. 所以你可以問 Git:*從EtoF的變化以及你將得到的是由于合并的較低(在我的圖中)腿而帶來的變化;或者您可以詢問從YtoF發生了什么變化,您會看到由于合并的上段而帶來了哪些變化。
無論如何,這就是合并的作業(和要點):合并作業,記錄合并作業的事實。你現在可以確切地看到發生了什么:你在他們作業的時候做了一些事情,他們在你作業的時候做了一些事情,然后你一下子把它們結合起來。
使用 rebase 可以創建“更清晰”的歷史記錄:看起來他們做了一些事情,你等待他們完成,然后你開始你的任務,知道他們做了什么,完成了你的作業并提交了它。這并不是真正發生的事情,但也許它也一樣好。也許這更好,因為對于未來的你,或他們,或任何人,它更簡單:它不需要弄清楚在作業組合程序中是否出了問題。但是,如果確實出了問題,它可能會隱藏那件事是什么,使您/他們/任何人的未來變得更糟。
這就是為什么你有一個選擇:一個可能比另一個更好,或者不是。
[編輯:]有什么git push作用
當你運行時:
git push origin master
或其等效但更明確的變體:
git push origin master:master
你的 Git 將:
- 使用名稱
origin查找此git push操作的 URL (git config --get remote.origin.pushurl; 如果未設定,git config --get remote.origin.url); - 呼叫回應此 URL 的任何內容:這應該是連接到另一個存盤庫的另一個 Git 軟體;
- 提議
master通過其哈希 ID向他們發送您的最新提交;和 - 從那里繼續。
Let's suppose first that you used rebase, so that your latest master commit hash ID is the hash ID of commit E'. Your Git offers to send this commit to their Git. They have never heard of this hash ID, so they say yes please, send that one, and tell me about its parent(s). Your Git then tells them the hash ID of commit D'; they haven't heard of that one either, so your Git tells them about D's parent Y. At this point they say to your Git: Ah, I have commit Y, you can stop sending things now; package up what I'll need for the commits I asked for, knowing that I have commit Y and every earlier commit.
Alternatively, let's suppose for the moment that you used git merge. Your Git will offer to send commit F (by hash ID). Their Git will say yes to that one, so your Git will now offer to send both parents, E and Y. They will say no thanks to Y because they already have that one, but yes please to E, so your Git will then offer D; they will say yes to that one as well, and your Git will then either offer C, or realize that they have C because they have Y: if your Git does offer C they'll say they don't need it, so this works out the same either way (it's just more efficient if your Git is smarter).
Now that your Git knows which commits to send, and which commits they already have, your Git makes a reasonably minimal thin pack—this technically depends on the chosen push protocol but everyone should be using the "smart" protocol these days—containing the necessary commits and objects, knowing that the other Git repository already has all the objects that go with all the commits they already have. Your Git then sends over this "thin pack" to them, which they save away for further use if all goes well.
Finally, your Git sends a polite request of the form: Please, if it's OK, set your branch name master to ________. Let me know if it was OK. Your Git fills in the blank with the hash ID from your own master. Their Git then checks to see if the new commits add on to their own master branch, without dropping from their master any commits they had before.
Both scenarios—where you ask them to add F, or where you ask them to add E'—do add on, keeping their existing commit Y in their branch, so they probably accept your polite request.
請注意,他們從不知道或關心您用于查找這些提交的分支名稱。他們只關心他們被要求設定的分支名稱、哈希 ID 以及涉及的各種提交。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/391828.html
上一篇:如何在linux中將終端結果放入一個檔案全名的檔案中
下一篇:獲取遠程和本地分支的差異
