簡體   English   中英

git pull *after* git rebase?

[英]git pull *after* git rebase?

我有一個功能分支和一個主分支。

主分支已經發展,我的意思是讓這些更新盡可能少地從主分支中分離出來。

所以我git pull兩個分支, git checkout feature/branch和最后git rebase master

現在在這里,我要么期望一切順利進行,要么希望在繼續 rebase 之前解決我需要解決的沖突,直到所有主提交都成功地重新應用到功能分支上。

現在,在我的案例中真正發生的事情是我不明白的:

$>git rebase master
First, rewinding head to replay your work on top of it...
Applying: myFirstCommitDoneOnTheBranch
Applying: myOtherCommitDoneOnTheBranch
$>git status
On branch feature/branch
Your branch and 'origin/feature/feature' have diverged,
and have 27 and 2 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)
nothing to commit, working tree clean
$>git pull
*load of conflicts*

現在,據我所知,他在拉動后會發生大量沖突; 我不明白拉動的必要性。 從邏輯上講,它應該在分支時回滾到 master,保存在分支上所做的提交,轉發到 master 上的最新提交,然后應用保存的提交。

我不明白Applying消息指的是什么:什么是在哪個版本上應用提交?

tl;博士您應該使用git pullgit pull --rebase更新masterfeature然后再將feature重新設置在master之上。 feature分支重新設置在master之上,無需執行git pull

使用您當前的工作流程, git status告訴您的原因是:

您的分支和“起源/特征”已經分歧,分別有 27 個和 2 個不同的提交。

是因為您的 rebase feature分支現在有25 個新提交無法從origin/feature訪問(因為它們來自master上的 rebase)加上2 個origin/feature訪問但具有不同提交 ID 的提交。 這些提交包含相同的更改(即它們是等效的補丁),但它們具有不同的 SHA-1 哈希,因為它們基於origin/feature中的不同提交,而不是您在本地存儲庫中重新基於它們的提交。

這是一個例子。 讓我們假設這是您在執行git pull on master之前的歷史:

A - B - C (master)
         \
          D - E (feature)

git pull之后, master得到了提交F

A - B - C - F (master, origin/master)
         \
          D - E (feature)

此時,您在master之上重新設置feature ,該功能適用DE

A - B - C - F (master, origin/master)
             \
              D - E (feature)

與此同時,遠程分支origin/feature仍然基於提交C

A - B - C - F (master, origin/master)
         \   \
          \   D' - E' (feature)
           \
             D - E (origin/feature)

如果你對feature執行git status ,Git 會告訴你你的feature分支已經與origin/feature不同,分別有3 個FD'E' )和2 個DE )提交。

請注意, D'E'包含與DE相同的更改,但具有不同的提交 ID,因為它們已重新基於F之上。

解決方案featuremaster上 rebase之前masterfeature執行git pull 但是,由於您可能已經提交了尚未推送到originfeature ,因此您需要執行以下操作:

git checkout feature && git pull --rebase

避免在origin/feature和您的本地feature之間創建合並提交

關於變基的后果的更新:

鑒於此評論,我擴展了不同的分支。 git status在 rebase 后報告featureorigin/feature分歧的原因是因為 rebase 為feature帶來了新的提交,而且它重寫了之前推送到origin/feature的提交。

考慮 pull之后,rebase之前的情況:

A - B - C - F (master)
         \
          D - E (feature, origin/feature)

此時, featureorigin/feature指向同一個提交E換句話說,它們處於“同步”狀態。 master之上 rebase feature后,歷史將如下所示:

A - B - C - F (master)
         \   \
          \   D' - E' (feature)
           \
             D - E (origin/feature)

如您所見, featureorigin/feature已經分歧,它們的共同祖先是提交C 這是因為feature現在包含來自master的新提交F加上D'E' (讀作“ D prime ”和“ E prime ”),它們是在F之上應用的提交DE 即使它們包含相同的更改,Git 仍認為它們是不同的,因為它們具有不同的提交 ID。 同時, origin/feature仍然引用DE

至此,您已經改寫了歷史:您通過變基修改了現有提交,有效地創建了“新”提交。

現在,如果您要在feature上運行git pull ,將會發生以下情況:

A - B - C - F (master)
         \   \
          \   D' - E'- M (feature)
           \         /
             D - E - (origin/feature)

由於git pull確實git fetch + git merge ,這將導致創建合並提交M ,其父級是E'E

相反,如果您運行git pull --rebase (即git fetch + git rebase ),那么 Git 會:

  1. feature移動到提交Cfeatureorigin/feature的共同祖先)
  2. origin/feature應用DE
  3. 應用FD'E'

然而,注意到D'E'包含與DE相同的更改,Git 會丟棄它們,導致歷史看起來像這樣:

A - B - C - F (master)
         \   
          D - E - F' (feature)
              ^
             (origin/feature)

請注意以前可從feature訪問的 commit F是如何應用在origin/feature之上的,從而導致F' 此時, git status會告訴你:

您的分支領先於 'origin/feature' 1 次提交。

該提交當然是F'

如果masterfeature/branch的遠程版本分別是最新的,那么只需重置您的本地功能分支

git checkout feature/branch
git fetch origin feature/branch
git reset --hard origin/feature/branch

那么如果你想在master分支中引入變化,

git rebase origin/master

當你在 master 之上重新定義你的特性分支時,你創建了一堆新的提交。 但是,您的origin/feature分支仍指向舊分支。 這是rebase后的情況:

C' (feature)
B'
A'
* (master, origin/master)
*
*
| C (origin/feature)
| B
| A
|/
* some base commit

雖然提交A'包含與提交A類似的更改集,但它絕不是相同的提交。 它包含不同的樹,並具有不同的父級。

現在,當您再次嘗試提取feature時,您會嘗試創建此歷史記錄:

* (feature)
|\
C'|
B'|
A'|
* | (master, origin/master)
* |
* |
| C (origin/feature)
| B
| A
|/
* some base commit

您正在合並兩個引入了非常相似、不同的變化的分支。 除了完全沒有意義之外,這必然會產生大量沖突。

您需要做的是使用git push -f通知您的上游倉庫有關變基的信息。 這將丟失舊的歷史,並用重寫的歷史代替它

另一種方法是避免在您已經推送到任何其他存儲庫的分支上使用git rebase ,或者完全避免使用git rebase 這是更簡潔的方法:它會按照已經發生的方式生成歷史,而不是像git rebase那樣對歷史撒謊。 這至少是我更喜歡的。

have 27 and 2 different commits each告訴您,您現在有 27 個來自master的新提交和 2 個在您的分支中不存在於origin/<yourbranch>的新提交。

由於 rebase 已對origin/<yourbranch>進行了大規模更改,因此它不再具有與origin/<yourbranch>的共同基礎。 因此,您不想在 rebase 之后從origin/<yourbranch>中提取更改,因為如您所見,所有 H*** 都會松動。

如果您知道在本地分支中需要更改origin/<yourbranch> ,請在 rebase 之前拉取這些更改。

如果您確定自上次推送后沒有人更改origin/<yourbranch> (如果這是您自己的功能分支,這是一個安全的選擇),您可以使用push --force再次將它們同步。 然后origin/<yourbranch>將再次與您的本地分支具有相同的基礎,並且該基礎將包含所有最新的master更改。

出現此錯誤是因為在調用git checkout feature/branch后未調用git fetch origin 為避免以后出現此錯誤,您可以按順序執行以下命令:

git checkout feature/branch
git fetch origin
git rebase master

暫無
暫無

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

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