2016-07-04 71 views
2

我的需求:將一個git倉庫分解爲多個git倉庫,保留與原始倉庫相同的目錄結構,並保存提交歷史記錄被複制到新回購的文件。 我曾嘗試已經:將多個文件和目錄從一個git倉庫複製到另一個倉庫,同時保留其原始歷史

  1. 首先我想基於在http://gbayer.com/development/moving-files-from-one-git-repository-to-another-preserving-history/ 結果的建議git的過濾分支--subdirectory過濾:歷史保留,但可運行 只觀察git log - follow 此外,原始的提交歷史記錄無法在Github上看到。它只顯示我的合併提交作爲該文件的唯一提交,並且不顯示任何以前的提交。我仍然可以忍受這種限制,並接受它作爲解決方案。但我對這種方法的另一個擔憂是,對於每個文件夾和我想要複製的每個文件,我需要多次克隆原始回購,並且每次都重複所有12或13個步驟。我想知道是否有更簡單的方法,因爲我正在移動大量文件。此外,由於該帖子已有5年曆史,只是想知道是否有更新的更簡單的解決方案? (令人驚訝的谷歌主要是顯示了這個博客作爲第一搜索結果)

  2. 我想是在較早的格雷格·拜爾的信息發表評論http://gbayer.com/development/moving-files-from-one-git-repository-to-another-preserving-history/#comment-2685894846 該解決方案通過使用git的子樹做的事情簡單一點接下來的事情分裂但結果與第一種情況相同。

  3. 然後我嘗試了git的日誌--patch-與-STATgit的是在此基礎上回答https://stackoverflow.com/a/11426261/5497551 結果選項:這通常給出了遇到的合併錯誤,而應用補丁。 我嘗試了使用這個答案的建議之一-m --first-parent這解決了錯誤,但沒有將任何合併擴展到它們的提交中,只是將合併列爲單個提交。因此,大部分提交歷史都會丟失。 所以我增加了另一個選項--3way。這一直反覆通過承諾,並沒有導致任何可接受的解決方案。

總之,我寧願使用第三種解決方案,如果只有一個選項可以將合併中的所有提交列入新回購的歷史記錄中。否則,我必須堅持第一個解決方案,這在我的情況下有點不方便和乏味。任何建議,幫助將不勝感激。

謝謝。

+0

'還保存提交歷史所有files' - 所以只是刪除你不希望保留的位?您可能會發現這很有用:[帶有僅當前跟蹤文件的歷史記錄複製的新回購](http://stackoverflow.com/a/17909526/761202)。 – AD7six

+0

謝謝。當你說'刪除所有內容並恢復你想保留的文件:'你能幫我理解我們要恢復哪些文件嗎?因爲keep-these.txt將包含當前回購權限中存在的所有文件的列表?或者我應該先刪除不需要的文件,然後執行'git ls-files> keep-these.txt'?我對git很新,所以對它的所有概念都不太熟悉。 – neel

+0

請編輯您的問題以便清楚。從問題描述中不清楚爲什麼'git rm somefolder; git commit -m「刪除一些文件夾」不會做你想做的事 - 你特別要求保留_all_文件的提交歷史;也要具體說明你擁有什麼,以及你期望的結果;將頂級文件夾/文件放在問題中 - 以及您想實現的目標。 – AD7six

回答

3

下面是我的工作(結合來自@ AD7six和@Olivier的答案)將我的orig-repo分成多個新的回購。我在此列出僅創建一個新回購的步驟new-repo1。但是同樣也被用來創建其他人。

首先在Github上創建新的空回購名爲new-repo1

git clone [Github url of orig-repo] 

git clone --no-hardlinks orig-repo new-repo1 
cd new-repo1 
git remote rm origin 
git checkout -b master //This step can be skipped. I had to do it since the default branch on my orig-repo was `develop`, but on the new-repo1 I wanted to create it as `master` 

//I used a script here to delete files and directories not required in the new-repo1. 
//But if you have very few files/dirs to be deleted then you can do the below. 
git rm <path of file 1 to be deleted> 
git rm <path of file 2 to be deleted> 
git rm -rf <path of dir 1 to be deleted> 

git commit -m "Deleted non-new-repo1 code" 

git ls-files > keep-these.txt 
git filter-branch --force --index-filter "git rm --ignore-unmatch --cached -qr . ; cat $PWD/keep-these.txt | xargs git reset -q \$GIT_COMMIT --" --prune-empty --tag-name-filter cat -- --all 

rm -rf .git/refs/original/ 
git reflog expire --expire=now --all 
git gc --prune=now 

git init 
git remote add origin [Github url of new-repo1] 
git push -u origin master 

在此之後,我可以用git log

0

使用方法1,您是從本地目錄或URL進行克隆嗎?如果從本地目錄克隆,則應使用--no-hardlinks選項。否則,你在一個克隆中執行的操作可能會影響其他目錄的.git目錄,因爲git硬鏈接文件。

這裏是我如何做到這一點:

  • 克隆的本地資源庫:

    git clone --no-hardlinks source_repo detached_repo 
    
  • detached_repo,刪除原點(更多信息here保持比當前的其他分支):

    git remote rm origin 
    
  • 刪除您不想保留的標籤。要刪除所有標籤,請使用git tag -l | xargs git tag -d

  • 使用filter-branch排除其他文件,以便它們可以被修剪。讓我們也加入--tag-name-filter cat --prune-empty刪除空提交和重寫標籤(更多信息here,如果你有幾個分支,以保持):

    git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter folder/to/keep HEAD 
    
  • 然後刪除備份reflogs這樣的空間,才能真正收回(即現在的操作破壞性的):

    git reset --hard 
    git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d 
    git reflog expire --expire=now --all 
    git gc --aggressive --prune=now 
    

    ,現在你有folder/to/keep子目錄及其所有歷史保存的本地的Git倉庫。

編輯

因爲你需要保持一個以上的子目錄,我會假設你有文件的列表,以保持在一個名爲files_to_keep文件。然後改變git filter-branch步驟:

git filter-branch --tag-name-filter cat --prune-empty \ 
    --index-filter 'git ls-tree -z -r --name-only --full-tree $GIT_COMMIT \ 
    | grep -z -v -F -f /absolute/path/to/files_to_keep \ 
    | xargs -0 -r git rm --cached -r' HEAD 

您可以生成文件的列表,以保持運行以下命令:

git log --pretty=format: --name-status | cut -f2- | sort -u > all_files 

和刪除文件,你不想保留。

+0

感謝您的回答。但我的要求是保持新的回購中的多個文件夾和文件,而不是一個'文件夾/到/保持'。你的解決方案可以修改來做到這一點? – neel

+0

另外,最終如何從'detached_repo'創建一個新的Github回購?將使用'--no-hardlinks'選項和清理步驟使我能夠在'detached_repo'上執行'git init',並將它作爲Github上的新回購?另外我想澄清的是,這些步驟不會以任何方式修改原始回購,即其文件和歷史記錄不受影響? – neel

+0

好吧,我得到了我的第二個評論的答案。我做了一個'git init',然後'remote add origin ''git push -u origin develop'。 – neel

0

對於這樣的查看文件的歷史在new-repo1在Github上以及通過命令行一個可能想要嘗試git-import的場景。

它基本上從一個回購的給定文件或目錄($object)創建補丁,並在保留歷史的同時將它們應用到另一個。

cd old_repo 
git format-patch --thread -o "$temp" --root -- "$object" 

這些補丁然後得到應用到新的存儲庫:

cd new_repo 
git am "$temp"/*.patch 

(如果需要,這個過程可以重複舊倉庫的不同部分)

詳情請查詢:

相關問題