git:将某些文件的历史记录拆分为单独的分支

时间:2010-11-25 14:44:20

标签: git branch rebase

说我介绍了< feature.c>前一段时间,现在注意到它不应该是我的main分支的一部分,而是分支feature。有可能使用例如git-filter-branch自动将所有< feature.c>的历史记录从main分支移出到feature分支?

2 个答案:

答案 0 :(得分:6)

听起来你正在做一些相当疯狂的事情! :)

那就是说,我看到了一些选项,其中没有一个是特别自动化的。

  1. 如果您对该文件提交了大量提交,只需承认错误,从HEAD创建一个新分支,并将该功能的进一步提交放入该分支,直到它们稳定为止。如果你是repo的共享,这将成为唯一真正的选择。没有人想要有不同的历史,特别是如果这个特征在历史深处都有。

  2. 如果您只是在谈论实际触及该文件的大约10个提交,并且它们最近提交而没有交错的许多其他提交,您可以在HEAD上检出新分支,并还原在添加功能之前,您不希望使用此功能,然后在功能分支中提取您需要的提交,直到您准备好以后再提交它们为止。

  3. 如果你正在处理大量的历史记录,大量的交错提交,而你真的不想让这个功能出现,你可以写一点获取git log输出的shell脚本,并将其选入新分支。有点像:

    $ cd git-repo
    $ git checkout -b feature-x
    $ the-perfect-shell-script `git log --pretty=format:"%H" path/to/feature.c`
    

    一旦你拥有了所有提交的功能分支,你可以使用git filter-branch过滤掉引用该文件的所有提交。 man page有一个简单的例子,就是这样。

    一旦你有了这个,你就可以git rebase feature-x --onto <filtered-branch>,你应该好好去。

    当然应该非常气馁,特别是如果发布任何的话。

答案 1 :(得分:1)

好的,这是我的去处:

如果我没有提交操作&lt; feature.c&gt;,我可以从&lt; feature.c&gt;的第一次提交中分支,然后在循环中使用git cherry-pickgit logsuggested Tim Visher。从大师开始,我想这应该有效:

#!/bin/bash
# create the feature branch starting from feature.c's first commit
FIRSTCOMMIT=$(git log --pretty=format:"%H" feature.c | tail -n1)
git checkout -b feature $FIRSTCOMMIT

# find all commits concerning feature.c...
for i in $(git log feature..master --reverse --pretty=format:"%H" feature.c)
do
  # ... cherry-pick them ...
  git cherry-pick $i
  # ... and copy ONE modified tag of it if existing
  git describe --tags --exact-match $i && xargs taghelperscript
done
# now eliminate feature.c from master
git filter-branch --prune-empty --tag-name-filter "cat" --index-filter 'git rm --cached --ignore-unmatch feature.c' $FIRSTCOMMIT..master

taghelperscript类似于git tag prefix.$1(也许这可以做得更好?)。标记部分可能仅适用于我使用的轻量级标签。另请注意,如果&lt; feature.c&gt;已经在某个时候被重命名,如果它已经存在于初始提交中,这可能会导致两个单独的历史记录,或者(我的猜测)master中的提交,其中包含删除&lt; feature.c&gt;这可能会导致合并冲突或混乱。


问题是,我的一些提交会修改其他文件,从而导致git cherry-pick触发未解析的合并,或者引入这些其他文件。相反,我会尝试一些git filter-branch魔法。 <子>后来。请继续关注...