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