我有一个约3500提交,并在最新版本30000个不同文件的Git仓库。 它代表了大约3年,由多个人的工作,我们已获得相关许可,使这一切开源。 我努力地释放整个历史,而不只是最新版本。 要做到这一点,我很感兴趣,“时光倒流”,并在创建时,在文件的顶部插入许可证标头。 其实,我有这个工作,但它需要3天左右全部用完一个ramdisk的,并且仍然需要人工干预的一点点。 我知道这可能是快了很多,但我的git-FU是没有达到的任务。
问题:我怎么能完成同样的事情快了很多?
我现在做什么(自动化的脚本,但是请多多包涵...):
确定所有地方的新文件添加到资料库中提交的(有略低于这些500,FWIW):
git whatchanged --diff-filter=A --format=oneline
定义环境变量GIT_EDITOR是我自己的脚本,取代
pick
与edit
只在文件的第一行包含一个时间(你会发现为什么不久)。 这是操作的核心:perl -pi -e 's/pick/edit/ if $. == 1' $1
对于每一个从输出提交
git whatchanged
以上,调用交互式变基刚开始在提交之前添加的文件:git rebase -i decafbad001badc0da0000~1
我的自定义GIT_EDITOR(Perl的一个班轮)改变pick
到edit
,我们下降到外壳进行修改,新的文件。 另一个简单的header-inserter
脚本会在我试图插入(只在已知文件类型(*。[CHS]对我来说))的头一个已知的唯一模式。 如果它不存在,它插入它, git add
的文件。 这种天真的技术并不知道它的存在过程中实际上添加的文件提交,但它结束了做正确的事,并为幂(安全运行针对同一文件多次),而不是在那里这整个过程反正瓶颈。
在这一点上,我们很高兴,我们已经更新了当前提交,并调用:
git commit --amend
git rebase --continue
该rebase --continue
是昂贵的部分。 因为我们调用git rebase -i
一次在输出每一个版本whatchanged
,这是一个很大的重定基。 几乎所有的在此期间,该脚本运行的时间都花在看“衍合(2733分之2345)”计数器增量。
它也不仅仅是慢。 有周期性必须解决的冲突。 这至少在这些情况下(但可能更多)发生:(1)当一个“新”的文件实际上是它的第一个线(例如,做了一些改变现有的文件的副本#include
语句)。 这是一个真正的冲突,但可以在大多数情况下(是的,有一个脚本,与交易)自动解决。 (2)当一个文件被删除。 这是刚刚确认,我们想删除它平凡解析git rm
。 (3)有些地方好像diff
只是表现不好,例如,其中的变化仅仅是增加了一个空行。 其他更合理的冲突需要人工干预,但是,整体而言,他们并不是最大的瓶颈。 最大的瓶颈是绝对只是坐在那里,在“衍合(XXXX / YYYY)”盯着。
眼下各底垫是由较新提交发起的旧的承诺,即从输出的顶部开始git whatchanged
。 这意味着第一个底垫影响昨日提交,并从3年前,最终我们将基础重建的提交。 从正在进行的“新”,以“老”,似乎违反直觉的,但到目前为止,我不相信它的问题,除非我们改变不止一个pick
一个edit
调用重订时。 恐怕这样做,因为矛盾就来了,我不想处理来自试图要一次重订的一切冲突的涟漪浪潮。 也许有人知道的方式,以避免? 我一直没能拿出一个。
我开始寻找Git对象的内部工作1 ! 它似乎是应该有一个更有效的方式来走的对象图,只是让我想要做的改变。
请注意,这个仓库从SVN仓库,我们有效地使没有用的标签或分支出来(我已经git filter-branch
编他们离开),所以我们有一个直线的历史的便利。 没有的Git分支或合并。
我敢肯定,我已经离开了一些重要的信息,但这个职位似乎已经过长。 我会尽我所能,以提供所要求的更多信息。 最后,我需要只发表我的各种脚本,这是一种可能性。 这是我的目标是找出如何改写历史正是如此在一个Git仓库; 不是辩论许可和代码发布的其他可行的方法。
谢谢!
更新2012-06-17: 博客文章的所有血淋淋的细节。