簡體   English   中英

您可以從遠程分支“重新設置”提交嗎?

[英]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

可以將他們的提交KL復制到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 devgit rebase OR/master ,這只是要你復制IJI'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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM