如何将子目录从一个git存储库中的分支移动到另一个存储库中的分支,保留历史记录?

时间:2011-09-15 16:30:46

标签: git git-branch git-merge git-filter-branch

我有一个包含在一个git存储库中的分支中开发的实用程序库的目录,但事实证明它们确实属于不同项目中的不同目录。我已经多次阅读并尝试过Greg Bayer Moving Files from one Git Repository to Another, Preserving History,但我无法保留历史。我试图在非主分支下完成这一切,以便更安全,因为项目还没有准备好合并回主人。

这是我到目前为止所做的事情:

准备从“Repo1”存储库的分支“SomeBranch”移动“DirectoryName”目录:

cd ~/Desktop
git clone git@github.com:username/Repo1.git
cd Repo1
git checkout -b SomeBranch origin/SomeBranch
git remote rm origin
git filter-branch --subdirectory-filter DirectoryName
mkdir DirectoryName
git mv *.php *.txt DirectoryName
git add DirectoryName
git commit -m "Stripped everything down to just DirectoryName."

将“DirectoryName”目录合并到“Repo2”存储库的“SomeBranch”分支中:

cd ~/Desktop
git clone git@github.com:username/Repo2.git
cd Repo2
git checkout -b SomeBranch origin/SomeBranch
git remote rm origin
git remote add Repo1 ../Repo1/
git pull Repo1 SomeBranch
git remote rm Repo1

当我这样做时,我可以成功地将所有内容都删除到Repo1中的“DirectoryName”(我也可以将其拉到Repo2),但历史记录丢失了。如果我执行git log -- DirectoryNamegit log -- DirectoryName/SomeFile.php,我只会看到“将所有内容删除到只有DirectoryName”。承诺)。所以,我的git filter-branch命令显然有问题,但我对它的了解还不够熟悉。

任何建议都会受到高度赞赏,因为我们正在对代码库进行一些根本性的更改,因此我需要相对频繁地执行此操作一段时间(因为我们希望保留历史记录)。 / p>

更新:正如我所提到的git log -- DirectoryName(或git log -- DirectoryName/SomeFile.php;无论是在Repo1还是Repo2中)都没有显示任何其他提交“将所有内容删除到只有DirectoryName。 “提交,但如果我git log,我会看到正确的提交历史记录。我只是错误地使用git log还是有一些腐败导致提交无法正确显示?

另一个更新: git log -- DirectoryName 在原始未经修改的Repo1中显示正确的提交,但显示git filter-branch之后的正确提交(我已经尝试了git filter-branch --subdirectory-filter DirectoryName -- --all但是那个“主”分支也是如此,并且似乎没有必要......同样的结果)。也就是说,在运行git filter-branch之后,提交历史就在那里,我可以用git log master..看到它,它似乎不再与目录或文件有关。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

听起来好像你所做的一切都很好,这只是对导致问题的git log的误解。

git只是在每次提交时存储树的状态,而不是记录在一次提交中将树从状态转移到下一次提交的更改。但是,如果您使用git log查找特定文件或目录的历史记录,则可以告诉它在文件的历史记录用完时尝试查找重命名。你可以用:

来做到这一点
git log --follow -- DirectoryName

或者,如果这不起作用,请仅针对单个文件进行尝试,例如

git log --follow -- DirectoryName/whatever.txt

答案 1 :(得分:0)

我是这样做的:

  1. 为触及子目录中文件的所有提交创建补丁:

    $ c=1; git log --format=%h -- subdir/*|tac|while read commit; do 
    git format-patch --stdout -1 $commit > $(printf '%04d' $c).patch
    c=$((c+1))
    done
    

    请注意,如果有单个提交触及subdir和subdir之外的两个文件,那么补丁也会在另一个文件中包含diff,因此您必须修剪这些文件,或者执行过滤分支以删除完成以下第二步后的那些文件:

  2. 使用git am在其他repo中的分支上应用补丁:

    $ git am *.patch