我的要求:将一个git repo分解为多个git repos,保留与原始repo中相同的目录结构,并保留复制到新repo的文件的提交历史记录。 我已经尝试过了:
首先,我根据http://gbayer.com/development/moving-files-from-one-git-repository-to-another-preserving-history/中的建议尝试了 git filter-branch --subdirectory-filter 结果:历史记录已维护,但只能在运行时查看 git log - 关注 此外,在Github上无法看到原始提交历史记录。它只显示我的合并提交作为该文件的唯一提交,并且不显示任何先前的提交。我仍然可以忍受这种限制并接受它作为解决方案。但我对这种方法的另一个担忧是,对于我要复制的每个文件夹和每个文件,我需要多次克隆原始repo并且每次都重复所有这12或13个步骤。我想知道是否有更简单的方法,因为我移动了很多文件。此外,由于该职位已有5年历史,只是想知道是否有更新的更简单的解决方案? (令人惊讶的是,Google主要将此博客显示为第一个搜索结果)
我接下来尝试的是对早期Greg Bayer的帖子http://gbayer.com/development/moving-files-from-one-git-repository-to-another-preserving-history/#comment-2685894846的评论 这个解决方案通过使用 git子树分割使事情变得更简单,但结果与第一种情况中列出的结果相同。
然后我根据这个答案尝试了 git log --patch-with-stat 和 git am 选项https://stackoverflow.com/a/11426261/5497551 结果:在应用修补程序时,这通常会在遇到合并时出错。 我尝试了使用 -m --first-parent 这个答案的建议之一。这解决了错误,但没有将任何合并扩展到它们的提交中,只是将合并列为单个提交。因此大多数提交历史都丢失了。 所以我添加了 - 3way 的另一个选项。这在提交过程中反复出现,并没有带来任何可接受的解决方案。
总之,我更倾向于使用第三种解决方案,如果只有一个选项让合并中的所有提交都列在新回购的历史中。否则我必须坚持第一个解决方案,这在我的情况下有点不方便和乏味。任何建议,帮助将不胜感激。
感谢。
答案 0 :(得分:4)
这对我有用(结合@ 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
在此之后,我可以使用new-repo1
git log
以及命令行中查看文件的历史记录
答案 1 :(得分: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
并删除您不想保留的文件。
答案 2 :(得分:0)
对于这种情况,人们可能想尝试source。
它基本上从一个仓库的给定文件或目录($object
)创建补丁,并在保留历史记录的同时将它们应用于另一个仓库。
cd old_repo
git format-patch --thread -o "$temp" --root -- "$object"
然后将这些补丁应用于新的存储库:
cd new_repo
git am "$temp"/*.patch
(如果需要,可以对旧存储库的不同部分重复此过程。)
详情请查询: