[英]Git rebase removed lines added by another PR
我遇到了一個奇怪的問題,我想了解發生了什么:
我們有一個develop
分支,我和一位同事建立了一個新功能分支: feature-a
和feature-b
。
在他的分支( feature-a
)中,他為foo.js
添加了行(比如:行100-120)。 在我的分支( feature-b
)中,我刪除了foo.js
行(比如:第90-110行)。
他的特點得到了合並到develop
和我重訂我岔開develop
之后。
沒有合並沖突,但當所有事情都說完了,他的台詞就不再存在了。
我懷疑發生的事情是:
feature-a
-a添加了100-120行feature-a
進行develop
feature-b
中刪除 我實際上期望git足夠聰明,不能這樣做並留下“新”線。這不是正確的假設嗎?
有沒有一個好方法來檢查發生了什么?
你是正確的,根據你的描述,你應該在變基期間遇到合並沖突。 要找出你是否沒有以及為什么不這樣做,你可以重復rebase,或者將其分解為commit-by-commit副本。
運行git rebase
運行重復的git cherry-pick
操作序列,或運行git format-patch
生成的補丁郵箱文件的一個大git am --3way
。 無論哪種方式,這將原始提交復制到更新的,據稱更好的提交。
請注意,所有提交都是只讀的。 這意味着沒有什么可以改變現有的提交 。 您現有的提交,預先變基,不受反彈的影響! 訣竅是找到原始提交。 沒有明顯的名稱可以找到它們,Git最終會(默認30天后) 刪除它們。
讓我們看一個典型的例子,繪制一些提交,其哈希ID由各種分支名稱記錄。 我們不知道提交的哈希ID,但無論如何它們都太笨重了,所以我們只使用大寫字母:
...--D--E <-- master
\
F--G <-- develop
|\
| H--I <-- feature-a
\
J--K <-- feature-b (HEAD)
在這里,你在feature-b
,你有兩個J
和K
提交,這些提交對你的工作是獨一無二的。 你的同事在feature-a
也有兩個提交。 你們兩個共享提交G
作為你們兩個開始的基礎; commit G
在分支develop
以及兩個功能分支上。 Commit G
特別是此時develop
的提示 。 提交F
也在所有三個分支上; F
指回(記錄散列ID) E
,這是master
的提示。 E
指向D
,依此類推到存儲庫中的第一個提交。 提交E
和更早的時候在所有四個分支上。
讓我們說在提交中I
將這些行添加到foo.js
,以便快照H
沒有行,而快照I
沒有。 他的功能現已獲得批准,因此某些存儲庫中的某些人具有非常相似且指向相同提交的分支名稱,它們執行以下兩個命令:
git checkout develop
git merge feature-a # or maybe git merge --no-ff feature-a
第一個將他們的HEAD
附加到他們的名稱develop
,以便合並結果將被添加或保存在那里。 如果指定了--no-ff
或者需要真正的合並,或者如果可能而且不禁止進行快進操作,則第二次執行真正的合並。 為簡單起見,我假設快進,結果是:
...--D--E <-- master
\
F--G
\
H--I <-- develop (HEAD), feature-a
(我已經把你的提交完全留在這里,假設它們沒有被推動;它不會影響結果。)
在他們的存儲庫中 如果你現在運行git fetch origin
來獲取它們的狀態,你可以在自己的存儲庫中找到它:
...--D--E <-- master, origin/master
\
F--G <-- develop
|\
| H--I <-- origin/develop, feature-a, origin/feature-a
\
J--K <-- feature-b (HEAD)
請注意,您的origin/*
名稱是其名稱的副本,更改為遠程跟蹤名稱而不是分支名稱。 就像你的分支名稱,這些遠程跟蹤名稱指向小費提交。 您的git fetch
步驟執行此操作以確保您自己的分支名稱不受影響。
您現在可以運行git rebase origin/develop
或git rebase origin/feature-a
或甚至(在這種特殊情況下) git rebase feature-a
,因為我們關心的只是選擇正確的提交 。 這將:
HEAD
可以從目標提交無法訪問的所有(非合並)提交:即J
和K
; I
; 要復制提交,Git實際上通過將提交與其父級進行比較將其轉換為一組更改。 因此,對於J
,Git將G
中的快照與J
的快照進行比較。 無論你在那里做了什么改變,Git都會對當前的提交做同樣的事情,然后進行新的提交。 讓我們調用新的提交J'
:
...--D--E <-- master, origin/master
\
F--G <-- develop
|\
| H--I <-- origin/develop, feature-a, origin/feature-a
| \
| J' <-- temporary HEAD
\
J--K <-- feature-b
Git通過比較J
與K
並對J'
應用相同的更改來重復K
的副本:
...--D--E <-- master, origin/master
\
F--G <-- develop
|\
| H--I <-- origin/develop, feature-a, origin/feature-a
| \
| J'-K' <-- temporary HEAD
\
J--K <-- feature-b
現在所有的提交都被復制了,rebase通過“剝離標簽” feature-b
關閉提交K
並使其指向提交K'
:
...--D--E <-- master, origin/master
\
F--G <-- develop
|\
| H--I <-- origin/develop, feature-a, origin/feature-a
| \
| J'-K' <-- feature-b (HEAD)
\
J--K [abandoned]
既然你的提交K
沒有名字 ,你很難找到它。
你的一個提交刪除了一些行。 您認為復制該提交刪除了太多行。 現在您可以看到每個提交的復制方式,您可以:
查找原始提交的哈希ID。
這可能有點棘手。 它們的名稱feature-b
不再指向它們。 它指向副本。 但有幾種選擇:
ORIG_HEAD
: git rebase
將此名稱設置為指向原始的最終提交(上圖中的K
)。 但是,此名稱也會被其他操作重用,因此它可能不再指向您的原始鏈。 你可以檢查一下。
Reflogs:每個分支都有一個reflog ,還有一個用於HEAD
。 運行git reflog
會顯示HEAD
那個; 運行git reflog feature-b
會告訴你一個feature-b
reflog會記住用於指向分支名稱的提交,並記住至少30天。 查看feature-b
的reflog,找到rebase復制它們之前的提交。
重復復制操作,以便您可以看到發生了什么。
既然您擁有原始文件並且知道您的分支名稱用於指向的位置(使用各種reflog),您就可以找到所有原始提交,這些提交仍處於其原始狀態。
然后你可以在出現錯誤之前將git checkout
(作為一個獨立的HEAD)提交,然后使用git cherry-pick
或git format-patch -1 <hash> --stdout | git am --3way
git format-patch -1 <hash> --stdout | git am --3way
來復制它,就像git rebase
那樣。
雖然這應該只是做與以前相同(錯誤)的事情,但您現在有足夠的細節來提出更具體的問題: 為什么在此特定快照上復制此提交會導致此特定破損?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.