问题是:如何更快地完成同样的事情?
我目前做什么(在脚本中自动化,但请耐心等待……):
>确定将新文件添加到存储库的所有提交(其中只有500个,fwiw):
git whatchanged --diff-filter=A --format=oneline
>将环境变量GIT_EDITOR定义为我自己的脚本,在文件的第一行只用一次编辑替换pick(你很快就会明白为什么).这是该操作的核心:
perl -pi -e 's/pick/edit/ if $. == 1' $1
>对于上面git以上输出的每个提交,在添加文件的提交之前调用交互式rebase:
git rebase -i decafbad001badc0da0000~1
我的自定义GIT_EDITOR(perl one-liner)更改选择进行编辑,我们将被删除到shell以更改新文件.另一个简单的header-inserter脚本在我试图插入的标题中查找已知的唯一模式(仅在已知文件类型中(*.[chS] for me)).如果它不存在,则插入它,然后git添加文件.这种天真的技术不知道在当前提交期间实际添加了哪些文件,但它最终做了正确的事情并且是幂等的(对同一文件多次运行是安全的),并且不是这整个过程瓶颈的地方无论如何.
在这一点上,我们很高兴我们已经更新了当前的提交,并调用:
git commit --amend git rebase --continue
反叛 – 继续是昂贵的部分.因为我们为whatchanged的输出中的每个修订调用一次git rebase -i,这就是很多重新定位.这个脚本运行的几乎所有时间都花在观看“Rebasing(2345/2733)”计数器增量上.
它也不仅仅是缓慢的.必须解决定期发生的冲突.至少在这些情况下(但可能更多)会发生这种情况:(1)当“新”文件实际上是现有文件的副本时,对其第一行(例如,#include语句)进行了一些更改.这是一个真正的冲突,但在大多数情况下可以自动解决(是的,有一个处理它的脚本). (2)删除文件时.通过确认我们想要用git rm删除它,这是可以轻易解决的. (3)有些地方似乎差异只是表现不好,例如,改变只是添加一个空行.其他更合理的冲突需要人工干预,但总的来说它们不是最大的瓶颈.最大的瓶颈绝对只是坐在那里盯着“Rebasing(xxxx / yyyy)”.
现在,单个rebase是从较新的提交启动到较旧的提交,即从git输出的顶部开始.这意味着第一个rebase影响了昨天的提交,最终我们将从3年前重新定位提交.从“较新”到“较旧”似乎是违反直觉的,但到目前为止,我并不认为这很重要,除非我们在调用rebase时将多个选项更改为编辑.我害怕这样做是因为冲突确实到来了,而且我不想处理冲突的浪潮,试图一次性改变一切.也许有人知道避免这种情况的方法吗?我无法想出一个.
我开始研究git对象1的内部工作原理!看起来似乎应该有一种更有效的方法来遍历对象图并只进行我想要进行的更改.
请注意,这个存储库来自一个SVN存储库,我们实际上没有使用标签或分支(我已经git过滤器将它们分开),所以我们确实有直线历史的便利.没有git分支或合并.
我确定我已经遗漏了一些关键信息,但是这个帖子似乎已经过了很长时间.我会尽力按要求提供更多信息.最后,我可能需要发布我的各种脚本,这是一种可能性.我的目标是弄清楚如何在git存储库中重写历史;不要讨论其他可行的许可和代码发布方法.
谢谢!
更新2012-06-17:Blog post以及所有血腥细节.
解决方法
git filter-branch -f --tree-filter '[[ -f README ]] && echo "---FOOTER---" >> README' HEAD
本质上会在README文件中添加一个页脚行,历史看起来就像文件创建后一直存在,我不确定它是否足够有效,但这是正确的方法.
制作一个自定义脚本,你可能最终得到一个好的项目历史,做太多“魔术”(rebase,perl,脚本编辑等)可能会以意想不到的方式丢失或改变项目历史.
jon(OP)使用这种基本模式来实现显着简化和加速的目标.
git filter-branch -d /dev/shm/git --tree-filter \ 'perl /path/to/find-add-license.pl' --prune-empty HEAD
一些性能关键的观察.
>使用-d<目录>指向ramdisk目录的参数(如/ dev / shm / foo)将显着提高速度.
>使用其内置语言功能从单个脚本执行所有更改,使用小实用程序(如查找)时完成的分支将使该过程多次减慢.避免这个:
git filter-branch -d /dev/shm/git --tree-filter \ 'find . -name "*.[chS]" -exec perl /path/to/just-add-license.pl \{\} \;' \ --prune-empty HEAD
这是OP使用的perl脚本的清理版本:
#!/usr/bin/perl -w use File::Slurp; use File::Find; my @dirs = qw(aDir anotherDir nested/DIR); my $header = "Please put me at the top of each file."; foreach my $dir(@dirs) { if (-d $dir) { find(\&Wanted,$dir); } } sub Wanted { /\.c$|\.h$|\.S$/ or return; # *.[chS] my $file = $_; my $contents = read_file($file); $contents =~ s/\r\n?/\n/g; # convert DOS or old-Mac line endings to Unix unless($contents =~ /Please put me at the top of each file\./) { write_file( $file,{atomic => 1},$header,$contents ); } }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。