![](/img/trans.png)
[英]Git rebase remote branch that has merge commits from master - is this safe?
[英]Can you “rebase” commits from a remote branch?
我已經建立了一個存儲庫,並希望對其進行長期維護和更改。 這些更改將永遠不會合並回原始存儲庫(OR)中。 但是,我確實想從OR中引入任何新更改。 將這些提交添加到我的存儲庫時,我不需要很多合並提交。 如果有沖突,我知道它們是不可避免的。 但是大多數提交應該干凈合並。
有沒有一種方法可以從OR中“重新設置”這些提交?
我認為git cherry-pick
是做到這一點的一種方法,但是OR會對其進行很多更改,我不想每次都選擇進行Cherry-pick。
我考慮過簽出OR / master,將其重新部署到我的dev分支之上,然后ff將其合並回我的dev分支。
git checkout -b ORmaster OR/master
git rebase -i dev
git checkout dev
git merge --ff-only ORmaster
但這意味着每次我想從OR / master合並時,都必須簽出一個新分支並重復一次。
有更簡單的方法嗎?
PS:我也不知道標題的字眼。 如果有人能說得更好,請告訴我。
編輯:我已經添加了我想發生的事情。
A--B--C <-- OR/master, origin/master, master
我添加一些更改到我的分支
A--B--C <-- OR/master
\
D--E--F <-- master
其他人對OR / master進行更改。
A--B--C--G <-- OR/master
\
D--E--F <-- master
我想要這些更改,所以我想將它們應用於我的
A--B--C--G <-- OR/master
\
D--E--F--G' <-- master
我想進行其他更改,有人對OR進行更改
A--B--C--G--I <-- OR/master
\
D--E--F--G'-H <-- master
我想將OR更改應用於我的分支。
A--B--C--G--I <-- OR/master
\
D--E--F--G'-H--I' <-- master
據我了解,這將防止任何合並提交,同時保持我的倉庫最新。
我根據已修改的問題對此進行了修改。 當然可以這樣做,您可以使自動進行摘櫻桃變得容易一些,但偶爾會遇到絆腳石,合並會更好。
首先,讓我們看一下如何自動執行摘櫻桃的過程。 在OR
存儲庫僅添加提交的假設下(如更新問題中的圖紙所示),我們需要的是某種標記,以便我們知道哪個提交是我們前面挑選的最后一個提交。
該標記可以采用任何形式,並且可以使用內置標記,尤其是OR/master
本身的引用日志。 但是,為了說明起見,如果沒有其他要求(在存在reflog過期或可能導致問題的其他任何條件下獲得更大的靈活性),我們可以使用顯式分支或標記名稱。 分支名稱是最合適的,因為我們將按照Git期望分支名稱移動的通常方式來移動它。
讓我們以這個階段為例:
A--B--C--G <-- OR/master
\
D--E--F--G' <-- master
(摘櫻桃后)。 要記住我們已經專門離開了G
,我們應該設置一個分支名稱以指向G
:
A--B--C--G <-- marker, OR/master
\
D--E--F--G' <-- master
當我們下次進行一些更新時,我們將添加到自己的`master中的提交數量無關緊要,因為:
I <-- OR/master
/
A--B--C--G <-- marker
\
...
因此,要復制的提交只是marker..OR/master
,我們可以運行:
git checkout master # if needed
git cherry-pick marker..OR/master # copy the new commits
當此操作成功后,將marker
以任何我們喜歡的方式快速轉發到OR/master
,包括比較聰明的(如果有點嚇人):
git push . OR/master:marker
(除非對marker
的更新是快進操作,否則它將拒絕執行任何操作)。
因為當它出現問題的說明,考慮會發生什么,如果OR/master
漲幅一系列的提交,其中包括合並的:
...--L
\
I--M--N <-- OR/master
/
A--B--C--G <-- marker
\
...
現在,提交范圍marker..OR/master
包括提交M
及其第二個父級L
以及L
之前無法從G
到達的所有內容。 我們應該復制哪些提交? 只要我們使用-m
參數(實際上始終為-m 1
分別進行處理,我們就可以從字面上選擇M
,這可能適合您的情況。 但這是一個令人擔憂的問題,您應該意識到這一點(並知道您打算對此做些什么)。 如果您使用git merge
,就像下面我的原始建議一樣,那不是問題:一切都會按照應有的方式自動進行。
(原始答案在分界線下方。)
git rebase
所做的全部工作就是復制提交(就像git cherry-pick
有時是 git cherry-pick
),然后移動分支名稱。
您始終可以復制自己擁有的任何提交,因此,可以對從其他Git存儲庫中獲得的提交進行基准化。 但是,這並不能幫助您實現實際目標。 您應該做的是使用git merge
。
這樣看:您的fork只是一個克隆,而您的fork的克隆是您的克隆的克隆。 除了有一個始終在線的地方來存放您自己的克隆(您的叉子)之外,您實際上只是在克隆原始克隆。 因此,我們可以通過以下方式在您本地存儲庫中標記內容:
...--F--G--H <-- OR/master, origin/master, master
其中每個大寫字母代表一個唯一的提交哈希ID。 (我們將在26次提交后用完,因此您可以了解為什么Git的實際哈希ID如此之大又丑陋-在過去或將來在這些存儲庫中每個人所做的每個提交中,它們必須永遠唯一)。
現在,在某個時候,您已經進行了自己的提交,並將它們推到origin
(您自己的叉子),所以現在您有了:
...--F--G--H <-- OR/master
\
I--J <-- master, origin/master
在您git push origin master
之后,您的origin/master
總是會與您自己的master
匹配,因此我們在這里甚至不需要理會。
但是,與此同時,擁有OR存儲庫的人進行自己的提交,因此在git fetch OR
,您將擁有以下內容:
...--F--G--H--K--L <-- OR/master
\
I--J <-- master
您可以將他們的提交K
和L
復制到K'
和L'
以便:
...--F--G--H--K--L <-- OR/master
\
I--J <-- master
\
K'-L' <-- dev
然后您可以快進您的master
以便您擁有:
...--F--G--H--K--L <-- OR/master
\
I--J--K'-L' <-- dev, master
最終,他們將做出更多提交:
...--F--G--H--K--L--N--O <-- OR/master
\
I--J--K'-L' <-- dev, master
(我跳過了M
來保留它),也許您也有:
...--F--G--H--K--L--N--O <-- OR/master
\
I--J--K'-L' <-- dev
\
P--Q <-- master
但如果你現在git checkout dev
和git rebase OR/master
,這只是要你復制I
和J
給I'
和J'
,並復制你的K'
這是他們的一個副本K
到一個新的K"
等:
I'-J'-K"-L" <-- dev
/
...--F--G--H--K--L--N--O <-- OR/master
\
I--J--K'-L'
\
P--Q <-- master
這確實無法帶您到任何地方。
如果合並 ,則會得到以下信息:
...--F--G--H--K--L <-- OR/master
\ \
I--J--M <-- master
現在他們進行自己的提交,而您進行自己的提交:
...--F--G--H--K--L----N---O <-- OR/master
\ \
I--J--M--P--Q <-- master
再一次,您只需git merge OR/master
即可將其工作合並到您的工作中:
...--F--G--H--K--L----N---O <-- OR/master
\ \ \
I--J--M--P--Q--R <-- master
進行合並時,必須一次性解決所有合並沖突。 如果您重新設定基准,則必須再次重新解決所有過去的合並沖突 。 (使用git rerere
可以解決這個問題,但是這樣做有一定的局限性。)您只需解決一次的原因有兩個:
M
和之后的R
, 下一個合並將從公共合並基礎L
,然后是O
:您只需查看自上一次共享提交以來它們所做的事情。 合並提交本身將建立更新的共享提交合並基礎。 沒有合並提交,您將不會獲得更新的合並基礎。 合並提交很好; 擁抱他們。 :-)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.