[英]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 pull
和git pull --rebase
更新master
和feature
,然后再將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
,該功能適用D
和E
:
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 個( F
, D'
, E'
)和2 個( D
, E
)提交。
請注意,
D'
和E'
包含與D
和E
相同的更改,但具有不同的提交 ID,因為它們已重新基於F
之上。
解決方案feature
在master
上 rebase之前對master
和feature
執行git pull
。 但是,由於您可能已經提交了尚未推送到origin
的feature
,因此您需要執行以下操作:
git checkout feature && git pull --rebase
避免在origin/feature
和您的本地feature
之間創建合並提交。
鑒於此評論,我擴展了不同的分支。 git status
在 rebase 后報告feature
和origin/feature
分歧的原因是因為 rebase 為feature
帶來了新的提交,而且它重寫了之前推送到origin/feature
的提交。
考慮 pull之后,rebase之前的情況:
A - B - C - F (master)
\
D - E (feature, origin/feature)
此時, feature
和origin/feature
指向同一個提交E
換句話說,它們處於“同步”狀態。 在master
之上 rebase feature
后,歷史將如下所示:
A - B - C - F (master)
\ \
\ D' - E' (feature)
\
D - E (origin/feature)
如您所見, feature
和origin/feature
已經分歧,它們的共同祖先是提交C
。 這是因為feature
現在包含來自master
的新提交F
加上D'
和E'
(讀作“ D prime ”和“ E prime ”),它們是在F
之上應用的提交D
和E
即使它們包含相同的更改,Git 仍認為它們是不同的,因為它們具有不同的提交 ID。 同時, origin/feature
仍然引用D
和E
。
至此,您已經改寫了歷史:您通過變基修改了現有提交,有效地創建了“新”提交。
現在,如果您要在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 會:
feature
移動到提交C
( feature
和origin/feature
的共同祖先)origin/feature
應用D
和E
F
、 D'
和E'
然而,注意到D'
和E'
包含與D
和E
相同的更改,Git 會丟棄它們,導致歷史看起來像這樣:
A - B - C - F (master)
\
D - E - F' (feature)
^
(origin/feature)
請注意以前可從feature
訪問的 commit F
是如何應用在origin/feature
之上的,從而導致F'
。 此時, git status
會告訴你:
您的分支領先於 'origin/feature' 1 次提交。
該提交當然是F'
。
如果master
和feature/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.