簡體   English   中英

將git存儲庫歷史記錄的一部分移動到另一個存儲庫中

[英]Moving part of a git repository’s history into another repository

這里有很多關於使用git filter-branch將文件夾從一個存儲庫移動到新存儲庫的帖子; 我需要做的是將單個文件移動到新的存儲庫中。

我已經創建了新的存儲庫,並將文件系統中的舊存儲庫添加為“遠程”,並創建了一個新的“根提交”(只需為新的單文件項目添加自述文件)。現在我需要移植與此特定文件有關的提交到新的root-commit上。

(我應該提一下,這個文件在任何時候都沒有像任何其他文件一樣被修改;我懷疑這可能會讓這個任務變得更容易。)

這基於filter-branch手冊頁中的示例:

git filter-branch --index-filter 'git ls-files -s | grep $'\t'<file-to-keep>$ | \
    GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && \
    mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' --prune-empty -- --all

索引過濾器使用git ls-files -s打印索引的當前內容,greps只輸出要保留的文件(grep相當痴迷 - 字段是制表符分隔的,文件名是最后一個),然后創建使用該信息的新索引,並將其移到舊索引之上。

--prune-empty選項導致filter-branch刪除任何現在什么都不做的提交(即它們只觸及其他文件), -- --all告訴它重寫所有引用。

與使用filter-branch一樣,最好在一個新的克隆中執行此操作,因此如果您將任何內容搞砸了,那么即使filter-branch確實將備份保留在refs / originals中也是如此。 您可能還想閱讀用於縮小聯機幫助頁中存儲庫核對表 ; 結果是,一旦你完成了,真正擺脫你不再需要的所有東西的最好方法就是簡單地克隆過濾后的存儲庫。

這實際上即使該文件是在同一提交的其他文件修改工作,雖然我想你可以嘗試偷偷摸摸,並通過簡單地生成補丁這確實觸及該文件的所有提交,然后去和建設充分利用這一事實應用這些補丁的新存儲庫......但為什么要這么麻煩?

(旁注: 刪除單個文件比保留單個文件更容易。在這種情況下,您只需使用git rm --cached --ignore-unmatch <filename>作為索引過濾器。)

一個不同的解決方案 - 將舊的repo添加為另一個遙控器,然后rebase和cherry-pick可以工作。

git clone old_repo
git clone new_repo
cd new_repo
git remote add temp_repo old_repo
git fetch temp_repo

# bring the changed from old_repo into new_repo
git rebase --onto <...> temp_repo/master
OR
git cherry-pick [list of relevant commits]

git remote rm temp_repo
git push origin HEAD

我最終使用這個(否則無關的)帖子的回答來構建解決方案。 我沒有使用新root --onto綁定到樹中,而是修改了舊根, --onto內容重新設置為新根:

我可以從Git倉庫中刪除初始提交嗎?

嘗試了各種方法將文件或文件夾從一個Git存儲庫移動到另一個存儲庫,唯一一個似乎可靠工作的方法概述如下。

它涉及克隆要從中移動文件或文件夾的存儲庫,將該文件或文件夾移動到根目錄,重寫Git歷史記錄,克隆目標存儲庫以及將具有歷史記錄的文件或文件夾直接拖到此目標存儲庫中。

第一階段

  1. 制作存儲庫A的副本,因為以下步驟對此副本進行了重大更改,您不應該推送!

     git clone --branch <branch> --origin origin --progress -v <git repository A url> eg. git clone --branch master --origin origin --progress -v https://username@giturl/scm/projects/myprojects.git 

    (假設myprojects是您要復制的存儲庫)

  2. 進入它

     cd <git repository A directory> eg. cd /c/Working/GIT/myprojects 
  3. 刪除原始存儲庫的鏈接,以避免意外進行任何遠程更改(例如,通過推送)

     git remote rm origin 
  4. 瀏覽歷史記錄和文件,刪除目錄1中沒有的任何內容。結果是目錄1的內容擴展到存儲庫A的基礎。

     git filter-branch --subdirectory-filter <directory> -- --all eg. git filter-branch --subdirectory-filter subfolder1/subfolder2/FOLDER_TO_KEEP -- --all 
  5. 僅適用於單個文件移動:瀏覽左側的內容並刪除除所需文件之外的所有內容。 (您可能需要使用相同的名稱刪除不需要的文件並提交。)

     git filter-branch -f --index-filter \\ 'git ls-files -s | grep $'\\t'FILE_TO_KEEP$ | GIT_INDEX_FILE=$GIT_INDEX_FILE.new \\ git update-index --index-info && \\ mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE || echo "Nothing to do"' --prune-empty -- --all 

    例如。 FILE_TO_KEEP = pom.xml只保留FOLDER_TO_KEEP中的pom.xml文件

第二階段

  1. 清理步驟

     git reset --hard 
  2. 清理步驟

     git gc --aggressive 
  3. 清理步驟

     git prune 

您可能希望將這些文件導入到不是根目錄的目錄中的存儲庫B中:

  1. 制作該目錄

     mkdir <base directory> eg. mkdir FOLDER_TO_KEEP 
  2. 將文件移動到該目錄中

     git mv * <base directory> eg. git mv * FOLDER_TO_KEEP 
  3. 將文件添加到該目錄

     git add . 
  4. 提交您的更改,我們已准備好將這些文件合並到新存儲庫中

     git commit 

第三階段

  1. 如果您還沒有存儲庫B,請復制存儲庫B.

     git clone <git repository B url> eg. git clone https://username@giturl/scm/projects/FOLDER_TO_KEEP.git 

    (假設FOLDER_TO_KEEP是您要復制到的新存儲庫的名稱)

  2. 進入它

     cd <git repository B directory> eg. cd /c/Working/GIT/FOLDER_TO_KEEP 
  3. 創建與存儲庫A的遠程連接作為存儲庫B中的分支

     git remote add repo-A-branch <git repository A directory> 

    (repo-A-branch可以是任何東西 - 它只是一個任意名稱)

     eg. git remote add repo-A-branch /c/Working/GIT/myprojects 
  4. 從此分支(僅包含您要移動的目錄)拉入存儲庫B.

     git pull repo-A-branch master 

    pull會復制文件和歷史記錄。 注意:您可以使用合並而不是拉動,但拉動效果更好。

  5. 最后,您可能希望通過刪除與存儲庫A的遠程連接來清理一下

     git remote rm repo-A-branch 
  6. 推,你一切都准備好了。

     git push 

暫無
暫無

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

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