簡體   English   中英

修復 git 存儲庫中的連接並與舊存儲庫合並以保留歷史記錄

[英]repair connection in git repo and merge with old repo to preserve history

問題

我有兩個屬於同一個項目的代碼庫“REPO A”和“REPO B”。 事實上,REPO B 是 REPO A 的延續,因此應該包括 REPO A。我無法從本地存儲庫 REPO B 推送回我的原始(裸)存儲庫 REPO A,因為似乎存在結構錯誤。 當調用git log REPO B 時,我得到:

error: Could not read 3c4168d
fatal: Failed to traverse parents of commit 3d8c67a

背景

2016 年,我開始推送“REPO A”,它位於 Raspberry Pi Linux 計算機上作為裸存儲庫。 自 2018 年以來,我不再推動 REPO A,因為我是該項目中唯一的開發人員,並且更喜歡只提交我的本地克隆“REPO B”。 現在,三年后,我想繼續推REPO A,但是嘗試這樣做時遇到了問題。 這是兩個 REPO 的結構

                                                        +-----  HEAD -> master of REPO B
                                                        |
                                                        |
                                                        v
                                                    +---------+
                                           d784821  |         |  latest commit
                                                    +---------+  20 Mar 2021
                                                         |
                                                    +---------+
                                           bcc1186  |         |  commit
                                                    +---------+  14 Dec 2020
                                                         |

                                                        ...

                                                         |
                                                    +---------+
REPO A                                     86dea25  |         |  commit
                                                    +---------+  8 Nov 2018
HEAD -> master                                           |
origin/master   -----+                              +---------+
origin/HEAD          |                     f5ea2e3  |         |  commit
                     |                              +---------+  7 Apr 2018
                     |                                   |
                     |                              +~~~~~~~~~+
                     |                              |    ?    |  -> error: Could not read 3c4168d
                     |                              +~~~~~~~~~+  -> fatal: Failed to traverse
                     v                                   |                 parents of commit 3d8c67a
                +---------+                         +~~~~~~~~~+
        commit  |         |  3c4168d       =        |         |
   13 Mar 2018  +---------+                         +~~~~~~~~~+
                     |                                   |

                    ...                    =            ...

                     |                                   |
                +---------+                         +~~~~~~~~~+
        commit  |         |  7ad262b       =        |         |
    2 Aug 2016  +---------+                         +~~~~~~~~~+
                     |                                   |
                +---------+                         +~~~~~~~~~+
initial commit  |         |  09b9c4d       =        |         |
    2 Aug 2016  +---------+                         +~~~~~~~~~+

                   REPO A                              REPO B

推理

兩個 REPO 的下半部分應該相同,因為 REPO B 包括 REPO A 的延續。 3c4168d 的3c4168d值,屬於 REPO A 的最新提交,與 HASH 值相同,在嘗試時會出現錯誤git log REPO B。因此,不知何故,在 REPO B 的最舊有效提交f5ea2e3之后的向下連接丟失了。

嘗試使用 SourceTree 打開 REPO B 時,它拒絕設置顯示錯誤消息的項目:

error code 128: refs/remotes/GitPi/master does not point to a valid object!
error: Could not read 3c4168d...
fatal: revision walk setup failed

但是對 REPO B 的提交仍在使用命令行進行。

問題

我如何“修復” REPO B 以便找回我當前丟失的提交歷史記錄(它仍然有效地位於 REPO A 中?我怎樣才能再次恢復我的log和從 REPO B push送到 REPO A 的能力?

我明白了,有很多關於粘合兩個 repos 和修復提交歷史的帖子,但是經過幾個小時的閱讀,我無法為我的具體情況弄清楚。

感謝您的任何提示。

經過一整天的閱讀和嘗試,問題可以解決;-)。 這是,它是如何執行的。 希望對某人有所幫助:

概念

  1. 通過在 REPO A 的尖端創建一個新的“恢復提交”來修復提交鏈中缺失的鏈接,然后
  2. 創建 REPO B 的每個有效提交的補丁,然后
  3. 將補丁應用於 REPO A。補丁不查看 blob,而僅包含更改的代碼片段。 從而使“重放”提交變得容易。

修復回購 A 和 B 之間的缺失鏈接

找到兩個有效提交f5ea2e3 (Repo B) 和3c4168d之間的鏈接

cd RepoB
git show <sha-of-broken-commit>
  • 提交3d8c67a已損壞且未找到其父級
  • 但對象可能沒問題

上面的命令給出了樹 object(參見文件夾)的 sha,以查找更多的 blob 對象(文件)。 有了這個,嘗試從損壞的提交3d8c67a中恢復盡可能多的信息,以便在 REPO A 之上創建一個有效的提交3c4168d ,它可以平滑地適應由 REPO B 的提交f5ea2e3施加的更改。

git cat-file -p <sha-of-tree-object>
  • 相應的樹 object 確實存在並且有效
  • f5ea2e3中更改的文件的相應 blob 對象存在並且有效

現在,使用 Python 和zlib package 恢復屬於損壞的提交3d8c67a的文件

import zlib
fname = r'<path-to-object-within-object-folder-below-git-management-folder>'
compressed = open(fname, 'rb').read()
decompressed=zlib.decompress(compressed)
fh = open("./<filename>",'w')
fh.write(decompressed.decode('utf-8'))
fh.close()

從回購 B 創建補丁

從提交f5ea2e3到 repo 的提示,在 REPO B 中創建補丁。

cd ../RepoB
git format-patch f5ea2e3 -o _patches/

在回購 A 中應用補丁

將所有補丁應用到 REPO A 的尖端(在新的“恢復提交”之上)

cd ../RepoA
cat ../RepoB/_patches/*.patch | git am

暫無
暫無

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

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