将git存储库历史记录的一部分移动到另一个存储库中

时间:2011-02-21 01:41:12

标签: git merge repository

这里有很多关于使用git filter-branch将文件夹从一个存储库移动到新存储库的帖子;我需要做的是将一个文件移动到一个新的存储库中。

我已经创建了新的存储库,并将文件系统中的旧存储库添加为“远程”,并创建了一个新的“根提交”(只为新的单文件项目添加了自述文件。)现在我需要将与此特定文件有关的提交移植到新的root-commit上。

(我应该提一下,这个文件在任何时候都没有像任何其他文件一样被修改;我怀疑这可能会让这个任务变得更容易。)

4 个答案:

答案 0 :(得分:5)

这基于filter-branch manpage

中的示例
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打印索引的当前内容,只显示要保留的文件(grep相当痴迷 - 字段是制表符分隔的,文件名是最后一个),然后使用该信息创建一个新索引,并将其移到旧索引之上。

--prune-empty选项导致filter-branch删除任何现在什么也不做的提交(即他们只触及其他文件),-- --all告诉它重写所有引用。

与filter-branch一样,最好在一个新的克隆中执行此操作,因此,如果您将任何内容搞砸了,那么即使filter-branch确实将备份保留在refs / originals中也是如此。您可能还想阅读联机帮助页中的checklist for shrinking a repository;结果是,一旦你完成了,真正摆脱你不再需要的所有东西的最好办法就是简单地克隆过滤后的存储库。

即使文件在与其他文件相同的提交中被修改,这实际上也会起作用,尽管我想你可以尝试偷偷摸摸并通过简单地为所做的所有提交生成补丁来利用这个事实触摸该文件,然后通过应用这些补丁来构建新的存储库......但为什么要这么麻烦?

(旁注:删除单个文件比保留单个文件更容易。在这种情况下,您只需要使用{{1}用于索引过滤器。)

答案 1 :(得分:2)

我最终使用此(否则无关)帖子的回复来构建解决方案。我没有使用新root重新绑定到树中,而是修改了旧根,--onto - 将内容重新绑定到新根:

Can I remove the initial commit from a Git repo?

答案 2 :(得分:2)

另一种解决方案 - 将旧的仓库添加为另一个遥控器,然后使用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

答案 3 :(得分:0)

尝试了将文件或文件夹从一个Git存储库移动到另一个存储库的各种方法,下面概述了唯一一个似乎可靠工作的方法。

它涉及克隆要从中移动文件或文件夹的存储库,将该文件或文件夹移动到根目录,重写Git历史记录,克隆目标存储库以及将具有历史记录的文件或文件夹直接拖到此目标存储库中。 / p>

第一阶段

  1. 制作存储库A的副本,因为以下步骤为major 对此副本的更改,您不应该推送!

    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进去吧

    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文件

  6. 第二阶段

    1. 清理步骤

      git reset --hard
      
    2. 清理步骤

      git gc --aggressive
      
    3. 清理步骤

      git prune
      
    4. 您可能希望将这些文件导入到不是根目录的目录中的存储库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
        
      5. 第三阶段

        1. 如果您还没有

          ,请复制存储库B.
          git clone <git repository B url>
          eg. git clone https://username@giturl/scm/projects/FOLDER_TO_KEEP.git
          

          (假设FOLDER_TO_KEEP是您要复制到的新存储库的名称)

        2. cd进去吧

          cd <git repository B directory>          eg. cd /c/Working/GIT/FOLDER_TO_KEEP
          
        3. 创建与存储库A的远程连接,作为存储库中的分支 乙

          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