git:复制/移动提交范围到单独的存储库

时间:2016-05-04 14:34:50

标签: git

我创建了一个新的功能分支并在那里添加了一个文件。创建该分支后的每次提交仅针对此文件 现在我想将这些提交移动到一个仅用于此新文件的新存储库 我如何实现这一目标?我尝试将旧存储库作为远程分支添加到新存储库并挑选所有提交但我也从功能分支之前和其他文件中获取较旧的提交消息,并且我丢失了原始提交日期。

所以这就是我需要的:

  • 将一系列提交从一个仓库复制/移动到另一个仓库
  • 只有该文件的提交从创建该文件开始到今天(两者之间没有涉及其他文件,但在创建旧功能分支之前)
  • 保留原创作者和提交日期

我也尝试过:

# git rebase --onto develop oldRepo/feature/issue#14 c7bc952

其中c7bc952是当前的HEAD。

我得到了什么:

First, rewinding head to replay your work on top of it...

# git status
HEAD detached from 4ae31a1
nothing to commit, working directory clean

2 个答案:

答案 0 :(得分:2)

这样的大手术最好通过直接构建新的历史来完成。我喜欢在临时克隆中做这样的工作:

git clone -s . $TMPDIR/wip         # scratch clone
cd !$

现在重写所有历史记录,只包含影响该文件的提交,并且只包含那些提交的文件:

git filter-branch --index-filter '
                        git read-tree --empty
                        git reset $GIT_COMMIT -- that/file
                ' \
        -- --all -- that/file

如果您只想要一个分支,请使用例如master代替--all以上。

现在,您可以将重写的分支推送到任何您想要的位置。请记住"起源"在这个回购中是你克隆的回购。

快速回顾一下:

  • 一个工作存储库分为四个部分:对象db,refs,index,worktree。 HEAD ref通常标识生成当前索引和工作树的提交; git commit将其用作新提交的第一个父级,git checkout将其切换到新分支,依此类推。

  • 索引只是一个列表:路径名,内容ID,有关inflight操作的元数据。例如,Git状态检查HEAD ref以查看在路径上提交的内容,查看上次添加或检出的内容的索引,以及查找任何未分级的未添加的未加密的又名未编入索引的内容的工作树

  • refs只是对象db的大拇指。

因此,git read-tree是从对象db加载索引的(如果你问的话,是工作树)。这是你用git做的大部分工作的基本操作。

所以filter-branch调用你提供的所有过滤器,你的arg产生的所有过滤器(第一个--之后的东西)。在这里,我提供--all -- that/file,因此rev-list会提供触及that/file的每个提交。当您提供索引过滤器时,filter-branch从提交中加载索引,设置GIT_COMMIT,运行过滤器,并使用生成的索引状态重写提交。

此处,git read-tree --empty; git reset $GIT_COMMIT -- that/file清空索引,然后仅加载当前提交的that/file条目。泡沫,冲洗,重复。

答案 1 :(得分:1)

我回答我的问题,因为这是我找到的第一个解决方案,也许对其他人有帮助:

git rebase hash_of_parent_of_first-commit hash_of_last_commit --onto develop --committer-date-is-author-date

将所有提交从我当前的功能分支重新绑定到我之前的空开发分支。