【问题标题】:How to move a subdirectory from a branch in one git repository to a branch in a different repository, preserving history?如何将子目录从一个 git 存储库中的分支移动到另一个存储库中的分支,保留历史记录?
【发布时间】:2011-09-15 16:30:46
【问题描述】:

我有一个目录,其中包含在一个 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 命令有问题,但我对它还不够熟悉,无法弄清楚是什么。

我们将非常感谢任何建议,因为我们正在对我们的代码库进行一些根本性的更改,因此我需要在一段时间内相对频繁地执行此操作(但我们希望保留历史记录)。

更新: 正如我提到的 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 但这也与“master”分支混为一谈,而且似乎没有必要......结果相同)。也就是说,在运行git filter-branch 之后,提交历史就在那里,我可以用git log master.. 看到它,它似乎不再与目录或文件有关。有什么想法吗?

【问题讨论】:

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


    【解决方案1】:

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

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

    git log --follow -- DirectoryName
    

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

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

    【讨论】:

    • 是的,就是这样!我只是错过了git log 不会自动跟随重命名之类的事实(并且使用git filter-branch 需要重命名,因为文件最终会出现在树的根目录中)。
    【解决方案2】:

    我会这样做:

    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 之外的两个文件,则补丁还将包含另一个文件上的差异,因此您必须修剪这些大块,或执行过滤器分支以删除完成以下第二步后,这些文件:

    2. 使用 git am 将补丁应用到另一个 repo 的分支上:

      $ git am *.patch
      

    【讨论】:

      猜你喜欢
      • 2019-10-13
      • 2011-06-30
      • 2013-06-26
      • 2014-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多