2014-09-20 180 views
0

我想非交互式从我的历史记录中移除包含主题关键字的unpushed提交(类似于包含关键字的行被移除的交互式转化)。git非交互式地删除提交

以下nocommit在〜/ .gitconfig中的函数实现了我想要的功能,只是创建了一个新的结果分支。

nocommit = "!f() { \ 
    for i in `git log --oneline FETCH_HEAD.. |grep NOCOMMIT | awk '{ print $1 }'`; \ 
    do \ 
     git log -n1 --oneline $i; \ 
     git rebase --onto $i^ $i HEAD; \ 
    done; \ 
}; f" 

也应该可以用git push hook做到这一点,但我们已经有了三个挂钩,我不想修改。

编辑:使用此命令(由安德鲁·C中的答案启发)解决:

GIT_EDITOR="sed -i '/NOCOMMIT/d'" git rebase -i @{upstream} 
+0

可能重复[使用git filter-branch删除提交消息提交](http://stackoverflow.com/questions/4558162/using-git-filter-branch-to-remove-commits-by-their -commit-message) – Jubobs 2014-09-20 16:30:15

+0

恐怕这不能保证是非交互式的。无论何时从历史记录中删除提交,都有发生冲突的风险,并且必须以交互方式解决。 – 2014-09-21 07:00:34

回答

1

几点意见。

您正在通过提交'backwards',从最新到最旧。 rebase从最旧到最新的原因是你只处理每个提交一次。

脚本的第一行可能会更好写成

for i in `git rev-list --grep=NOCOMMIT @{u}..HEAD` 

使用FETCH_HEAD不限制提交一个很好的方式,并具有管道grep和不需要的awk。

为了使它更像rebase,你必须跟踪ORIG_HEAD,从git merge-base ORIG_HEAD ${u}结帐一个新的分支,然后运行从最旧到最新(--reverse)的提交,挑选任何没有的NOCOMMIT,然后在最后更新分支。

另一种选择是通过保存编辑器设置并将其替换为只删除包含NOCOMMIT的脚本的脚本来将交互式底图诱骗成您想要的内容。所以你可以正常的拨打git rebase -i,但是不用编辑窗口sed就可以删除你不想要的提交,然后继续。

+0

为rebase -i指定一个替代编辑器似乎很有吸引力,但由于某种原因,我无法使其工作: GIT_EDITOR =“grep -v NOCOMMIT”git rebase -i HEAD〜5 – badeip 2014-09-20 20:42:45

+2

grep不会保存生成的文件。尝试'sed -i'/ NOCOMMIT/d'' – 2014-09-20 22:16:29

+0

啊,当然。 sed -i完美地工作。 – badeip 2014-09-21 05:24:47