簡體   English   中英

如何還原更改所有文件的特定提交,從而在還原過程中引起很多沖突?

[英]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 rebasegit filter-branch ,使用BFG Repo Cleaner或您自己想出的東西)實際上是重寫的存儲庫新的存儲庫。 至少,新鏈是新的:從重寫點開始的舊內容是相同的。 您必須讓擁有舊存儲庫副本的每個人都可以從內容切換到內容。 如果甚至只有一個人保留了舊提交,並使用Gi​​t將舊提交與新提交融合在一起(Git很高興這樣做),那么所有舊提交都會馬上回來 現在,您將舊的和新的都壓縮到一個大的快樂(?)存儲庫中,而您的問題變得越來越糟!

將您的提交(部分或全部)重寫為新的歷史記錄從根本上沒有錯,您只需要(a)知道如何做,以及(b)注意這種“每個人都必須切換”的后果。 如果沒有其他人擁有您要替換的提交,則這種重寫是完全安全的-沒有其他人其他Git存儲庫可以使舊提交重新發揮作用。 如果確實有舊承諾的每個人都知道這是如何工作並計划進行合作的,則這種歷史改寫在大多數情況下都是安全的:只有在有人犯錯的情況下它才會出錯(然后,取決於您自己的謹慎和/或謹慎程度)偏執狂,也許只為他們!)。 當您只有天真的用戶時,他們只是讓Git 像Borg這樣的默認行為來集成所遇到的每一個技術,這種重寫就變得一團糟。

暫無
暫無

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

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