簡體   English   中英

Git:拉一個重新定位的分支

[英]Git: Pulling a rebased branch

讓我描述一下我的情況:

Blond 先生和 Orange 先生正在處理分支 A,該分支在提交 M1 時從主分支分支出來。 分支 A 有 2 個提交:A1 和 A2。

M1  
   \
    \
     A1 - A2

與此同時,Orange 先生在主分支 M2 和 M3 上提交並推送了另外 2 個提交。

M1  - M2 - M3
   \
    \
     A1 - A2

Blond 先生從遙控器中拉出,過了一會兒決定重新設置到 master 分支上:

M1  - M2 - M3
   \         \
    \         \
     A1 - A2   A1` - A2`

現在 A1` 和 A2` 是在 Mr blond's 本地存在的 rebase 提交,並且 A1 和 A2 遠程存在。 Blond 先生推動他的提交,使用-f強制他的更改和“重寫”歷史。 現在遠程存儲庫如下所示:

M1  - M2 - M3
             \
              \
               A1` - A2`

但奧蘭治先生也在 A 分公司工作。 他的本地存儲庫仍然如下所示:

M1  - M2 - M3
   \
    \
     A1 - A2

橙先生需要做什么才能與遠程倉庫的A分支同步?

正常的拉動是行不通的。 pull -f會在本地強制從遠程進行更改嗎? 我知道刪除 A 的本地版本並從遠程存儲庫中再次將其帶入可以解決問題,但這似乎不是實現這一目標的好方法。

如果 Orange 先生不介意丟失他的更改,他可以從服務器獲取,然后git checkout A進入他的本地A分支,然后(假設遠程被命名為“origin”) git reset --hard origin/A將他A重置為遙控器的A所在的位置。

如果他擔心丟失更改,他可以使用git merge origin/A合並服務器的更改以解決它們(從他自己的A分支,並再次假設遠程被命名為“origin”)。 這將在他的和遠程的A分支之上進行一個新的提交,並將兩者的更改合並在一起。 然后可以將其推回遙控器。

我的建議(或者,“如果我是 Orange 先生,我會怎么做”)是從git fetch開始。 現在我將在我的 repo 中有這個,這是 Blond 先生在他的 rebase 之后和他運行“git push -f”之前所擁有的。

M1  - M2 - M3
   \         \
    \         \
     A1 - A2   A1' - A2'

一個重要的區別是,我的本地標簽A指向 rev A2,遠程標簽remotes/origin/A指向 A2'(Blond 先生反過來說,本地標簽A指向 A2' 和remotes/origin/A指向 A2)。

如果我一直在處理名為“A”的分支副本,我將改為:

M1  ---- M2 ---- M3
   \               \
    \               \
     A1 - A2 - A3    A1' - A2'

(我的本地標簽指向 A3 而不是 A2;或 A4 或 A5 等,具體取決於我應用了多少更改。)現在我所要做的就是將我的 A3(如果需要,還有 A4 等)重新定位到 A2' . 一種明顯的直接方式:

$ git branch -a
  master
* A
  remotes/origin/master
  remotes/origin/A
$ git branch new_A remotes/origin/A
$ git rebase -i new_A

然后完全刪除 revs A1 和 A2,因為修改后的在 new_A 中作為 A1' 和 A2'。 或者:

$ git checkout -b new_A remotes/origin/A
$ git format-patch -k --stdout A3..A | git am -3 -k

git am -3 -k方法在git-format-patch手冊頁中有描述)。

這些確實需要弄清楚 Blond 先生在他做他的rebase之前沒有什么,即識別 A1、A2、A3 等。

如果第二種方法成功,我最終會得到:

M1  ---- M2 ---- M3
   \               \
    \               \
     A1 - A2 - A3    A1' - A2' - A3'

我的分支名稱new_A指向 A3'(我現有A分支仍然指向舊的 A3)。 如果我使用第一種方法並且它成功了,我最終會得到同樣的結果,只是我現有的分支名稱A現在將指向 A3'(而且我沒有 A1-A2-A3 的舊分支的名稱,甚至雖然它仍然在我的回購中;找到它需要通過 reflogs 或類似的)。

(如果我的 A3 需要修改為 A3',當然,交互式變基和“git am”方法都需要我的工作。)

當然也可以只git merge (如 Gary Fixler 的回答),但這將創建一個合並提交(“M”,沒有數字,如下)並保持 A1 和 A2 的轉速可見,給出:

M1  ---- M2 ---- M3
   \               \
    \               \
     A1 - A2 - A3    A1' - A2' -- M
                 \_______________/

如果要保留原來的A1和A2,這是好事; 如果你想擺脫它們,那是一件壞事。 所以“做什么”取決於“你想要的結果是什么”。

編輯添加:我更喜歡 format-patch 方法,因為它保留了我的舊 A 分支名稱,同時我確保一切都很好。 假設一切正常並且很好,這最后幾個步驟:

$ git branch -m A old_A
$ git branch -m new_A A

然后,如果 old_A 可以完全放棄:

$ git branch -D old_A

或者,等效地,從分支刪除開始,然后將 new_A 重命名為 A。

(編輯:另見git rebase --onto文檔,以將 A3 等重新定位到 new_A 分支上。)

出於配置目的,我在兩個虛擬機上同時開發。 結果,我經常在一台機器上進行 rebase,並且需要將更改毫無困難地出現在另一台機器上。

假設我的分支名為feature/my-feature-branch 在第一個 VM 上完成 rebase 后,我在第二個 VM 上執行 git fetch。 出現以下消息:

$ git status
On branch feature/my-feature-branch
Your branch and 'origin/feature/my-feature-branch' have diverged,
and have 21 and 24 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

好吧,不要執行 git pull,因為在經過一番大驚小怪之后,您最終會得到一個毫無意義的合並提交。

相反,運行

git rebase -i origin/feature/my-feature-branch

一旦文本編輯器彈出,刪除所有提交,並將其替換為以下內容(這使得 rebase 完成而不保留任何提交)。

exec echo test

如果您確實有需要保留的提交,那么可以在此處應用這些提交。 在任何一種情況下,rebase 都會完成,現在兩台機器再次同步,如下所示:

$ git pull
Already up-to-date.
$ git push
Everything up-to-date

TLDR

除非我誤解了這個問題,否則奧蘭治先生的答案是git pull --rebase

更長的閱讀時間

簡單案例

如果我們假設 A1 和 A2 所做的更改與 A1' 和 A2' 相同(即使它們的提交哈希值不同),那么 Orange 先生可以不再擁有

M1  - M2 - M3
   \
    \
     A1 - A2

本地擁有

M1  - M2 - M3
             \
              \
               A1` - A2`

通過要么做

git pull --rebase

或者

git branch -d A
git checkout A

一個更有趣的案例

如果我們假設,如上所述,A1 和 A2 所做的更改是相同的,並且 Orange 先生進行了額外的提交,那么他將在本地擁有

M1  - M2 - M3
   \
    \
     A1 - A2 - A3O

和起源將是

M1  - M2 - M3
             \
              \
               A1` - A2`

再說一次,奧蘭治先生可以到達

M1  - M2 - M3
             \
              \
               A1` - A2` - A3O

git pull --rebase

一個更現實的案例

如果我們假設,如上所述,A1 和 A2 所做的更改是相同的,Orange 先生做了一個額外的提交,而 Blonde 先生做了一個額外的提交,那么 Orange 先生將在本地擁有這個

M1  - M2 - M3
   \
    \
     A1 - A2 - A3O

並且,假設 Blonde 先生已經推動,起源將是

M1  - M2 - M3
             \
              \
               A1` - A2` - A3B

奧蘭治先生可以到達

M1  - M2 - M3
             \
              \
               A1` - A2` - A3B - A3O

通過做

git pull --rebase

不過,這一次,他可能需要解決沖突。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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