[英]How do I revert a specific commit that changed all files, causing lots of conflicts during revert?
在協作存儲庫中,有人進行了提交,使其以某種方式出現,就像它再次重新添加了存儲庫中的所有文件一樣。
這是使用--date-order
打印時的部分歷史記錄:
* 28cbf861 - (65 minutes ago) update logs and metadata (HEAD -> master, origin/master, origin/HEAD)
* e589776e - (18 hours ago) P2LTR15 update
...
* d4c61147 - (5 days ago) Delete P2STR03_SRC00150_Q0448_0000_0-7.log
* fa837509 - (5 days ago) Delete P2STR03_SRC00150_Q0427_0000_0-7.log
* 9a5e2300 - (5 days ago) git pull at 20180421 10am.
|\
* | 6567df4b - (5 days ago) add md5 3min
* | 6f7c80f7 - (5 days ago) Added md5sum files for all 3min SRCs
/
* b97e834f - (6 days ago) Delete P2STR13_SRC00605_Q0325_0000_0-9.log
* 5cd9989b - (6 days ago) Delete P2STR13_SRC00605_Q0129_0000_0-9.log
* 769ae25d - (6 days ago) Delete P2STR13_SRC00605_Q0209_0000_0-9.log
...
錯誤的提交是6f7c80f7
,我想將其刪除,但保留6567df4b
。 git pull
commit( 9a5e2300
)是一個簡單的合並提交。
當我打印不帶--date-order
的歷史記錄時,突然在6f7c80f7
顯示了6f7c80f7
提交,即好像是第一次提交。
* 28cbf861 - (70 minutes ago) update logs and metadata
* e589776e - (18 hours ago) P2LTR15 update
...
* fa837509 - (5 days ago) Delete P2STR03_SRC00150_Q0427_0000_0-7.log
* 9a5e2300 - (5 days ago) git pull at 20180421 10am.
|\
| * b97e834f - (6 days ago) Delete P2STR13_SRC00605_Q0325_0000_0-9.log
...
| * 697a103c - (7 months ago) initial commit
* 6567df4b - (5 days ago) add md5 3min
* 6f7c80f7 - (5 days ago) Added md5sum files for all 3min SRCs
我嘗試執行git revert 6f7c80f7
,但是它顯示了很多我不知道如何解決的沖突,也就是說,當我執行git status
:
On branch master
Your branch is up to date with 'origin/master'.
You are currently reverting commit 6f7c80f7.
(fix conflicts and run "git revert --continue")
(use "git revert --abort" to cancel the revert operation)
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: P2LTR15/.gitkeep
deleted: P2LTR15/MOS_P2LTR15_MO.csv
... (this is basically a list of almost all the files in the repository)
Unmerged paths:
(use "git reset HEAD <file>..." to unstage)
(use "git add/rm <file>..." as appropriate to mark resolution)
deleted by them: P2LTR15/P2LTR15.yaml
deleted by them: P2LTR15/audioFrameInformation/P2LTR15_SRC00712_HRC021.afi
... (this is another list of files, I don't know why it is there, possibly those were actually changed)
我還有其他方法可以重寫Git歷史記錄,以至於這種錯誤的提交從未發生嗎?
我看過本指南,但它僅告訴我進行還原。 我是否應該嘗試在此之前返回到提交,然后選擇Cherry-pick提交 ,然后強制重寫存儲庫? 我也不認為這是一個不錯的選擇。
您說您的git log
輸出引用只是歷史記錄的一部分 ,但您也說了commit 6f7c80f7
會添加所有文件,並且在引用的文本中6f7c80f7
永遠不會顯示其連接的任何父提交。
這表明6f7c80f7
是根提交:實際上,它會添加它顯示的每個文件的初始提交,因為“先前”提交不存在,因此根據定義,每個文件在該提交中必須是新的。
一幅圖可以有多個根。 在Git提交圖中這有點不尋常,因為我們通常通過首先檢出一些現有提交,然后進行更改,然后運行git commit
來保存新的完整快照來進行新git commit
。 但是還有其他方法:
我們可以使用git fetch
獲取不相關的存儲庫,然后git merge
與--allow-unrelated-histories
git merge
。 如果Git版本足夠老,則git merge
總是允許不相關的歷史記錄,並且沒有--allow-unrelated-histories
標志:它只是合並這些文件而不會發出警告。 (您可能會在這里看到很多add/add conflict
錯誤,並且必須做很多手工操作!)
這會將它們(另一個存儲庫的)根提交添加到我們自己的提交圖中,該提交圖已經具有我們的根提交,因此現在我們有了兩個根提交。
我們可以使用git checkout --orphan
來設置自己的存儲庫狀態,以便我們進行的下一個提交將是根提交。
(如果當我們做作出這樣的承諾根,我們將有相同的合並問題作為與“取無關庫”的情況。)
我們可以不經意地或故意地使用git commit-tree
等管道命令來修飾Git內部,或者只是在.git
內部的文件中創建一個新的root提交。
無論如何,一旦處於這種狀態,即存在多個根,並且合並提交合並了多余的根,然后在合並之上構建了更多提交,我們就陷入了這種局面。 合並提交(在您的情況下為9a5e2300
具有一個哈希ID,該ID 取決於 兩個提交鏈的存在:一個返回到原始根提交,一個返回到新的根提交。 任何散列ID犯有9a5e2300
作為父母,你的情況,這僅僅是一個承諾fa837509
上存在-depends 9a5e2300
,因為它從字面上結合了哈希ID為自己的ID。 fa837509
的孩子的哈希ID(同樣,在您的圖形中只有一個提交)則取決於fa837509
的存在; 如果圖的其余部分是線性的,依次在每個子取決於它的父ID,一路到底。
因此,如果你以某種方式擺脫多余的根的承諾,您的合並提交需要有不同的哈希ID,這意味着以后每犯也將需要有不同的哈希ID。 此外,如果您確實擺脫了6f7c80f7
,則您必須為其當前子級6567df4b
制作的6567df4b
將是另一個root提交! 您也必須擺脫那一個,這意味着將沒有任何合並提交9a5e2300
進行合並,因此您可能也希望放棄它-除了要以某種方式保留其源快照 。 那么你就需要把所有剩余的(大概是線性)鏈,從fa837509
到尖端,並復制每個這些提交新提交的是不依賴於存在的9a5e2300
,但不要提交你所做的任何使用具有來自合並提交的更新的源快照。
因此,這將導致您必須避免使用兩次根提交的過程:
將合並9a5e2300
的快照復制到新的非合並提交中。 這將獲得一個新的哈希ID(因為這是一個新的唯一提交)。 將該ID保存在某處。
將fa837509
的快照復制到新提交,該提交同樣會獲得新的哈希ID。 新提交的父級將是您剛剛保存的ID。 將此ID保存在某處。
使用以前的副本作為新的父代,將fa837509
的子代中的快照復制到新提交。
對每次提交重復一次,直到達到提示。
一旦有了不依賴於要刪除的提交的線性提交鏈,那么您就可以簡單地停止使用 不依賴於要刪除的提交的原始提交鏈。 如果您和其他所有人都這樣做了,並且您刪除了Git 查找舊鏈的名稱,那么好像該舊鏈就不存在了。 隨着名稱的消失,最終舊的提交確實被刪除了。 (這種情況發生在所有安全檢查計時器中的內容都到期時。這些安全檢查存在,因此,如果您犯了一個錯誤,則可以找回舊的提交,但要盡快(通常為30天)捕獲它,以便Git可以制作不是尚未連接到提交圖,但將在14天之內。正常的Git命令在最差的幾毫秒內將它們連接起來,因此14天實際上是幾千年。)
上面的內容表明可以按照您的建議進行操作(盡管您可能希望構建與我描述的替換歷史略有不同的替換歷史)。 這是一個好主意,完全是另一個問題。 但是,重寫歷史記錄的主要缺點(使用git rebase
, git filter-branch
,使用BFG Repo Cleaner或您自己想出的東西)實際上是重寫的存儲庫新的存儲庫。 至少,新鏈是新的:從重寫點開始的舊內容是相同的。 您必須讓擁有舊存儲庫副本的每個人都可以從舊內容切換到新內容。 如果甚至只有一個人保留了舊提交,並使用Git將舊提交與新提交融合在一起(Git很高興這樣做),那么所有舊提交都會馬上回來 。 現在,您將舊的和新的都壓縮到一個大的快樂(?)存儲庫中,而您的問題變得越來越糟!
將您的提交(部分或全部)重寫為新的歷史記錄從根本上沒有錯,您只需要(a)知道如何做,以及(b)注意這種“每個人都必須切換”的后果。 如果沒有其他人擁有您要替換的提交,則這種重寫是完全安全的-沒有其他人或其他Git存儲庫可以使舊提交重新發揮作用。 如果確實有舊承諾的每個人都知道這是如何工作並計划進行合作的,則這種歷史改寫在大多數情況下都是安全的:只有在有人犯錯的情況下它才會出錯(然后,取決於您自己的謹慎和/或謹慎程度)偏執狂,也許只為他們!)。 當您只有天真的用戶時,他們只是讓Git 像Borg這樣的默認行為來集成所遇到的每一個技術,這種重寫就變得一團糟。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.