背景
公司内部从方案商拿到的是repo管理的源码,迁移到内部后改成了单个的git仓库。后续方案商会更新源码,有的时候大的版本变动会产生非常多的提交更新。如果全部人工对比更新,费时费力,而且方案商的commit记录也是没有了。所以就研究了下怎么去自动生成patch然后去打补丁,这样既能更高效同步也可以同步更新commit记录。
更新repo到git仓库
repo是Google用python脚本写的调用Git的脚本,主要用来下载、管理android项目的工具。内部也是一个git仓库,在.repo/manifests/ 目录下。查看本地版本更新的记录,可以看到是哪些路径和git模块更新了。
生成patch
首先需要对比之前的xml文件,通过diff生成一份改动了的模块记录文件,然后通过git format-patch生成补丁
#!/bin/bash diff_file=/tmp/manifest.diff patchs_path=/tmp/allpatchs sdk_dir=$1 old_manifest_file=$2 new_manifest_file=$3 if [ ! -d "$sdk_dir" ];then echo "No such $sdk_dir directory!" exit -1 elif [ ! -f "$old_manifest_file" ];then echo "No such $old_manifest_file file!" exit -1 elif [ ! -f "$new_manifest_file" ];then echo "No such $new_manifest_file file!" exit -1 else echo "Usage: manifest_patch sdk_dir old_manifest_file new_manifest_file" fi diff -u $old_manifest_file $new_manifest_file > $diff_file while read LINE do # echo $LINE | grep "\- <" each_update=`echo $LINE | grep "\- <"` # echo $test if [ -n "$each_update" ];then path=${each_update#*path=\"} path=${path%\" remote*} path=${path%\" name*} echo "mypath = $path" revision=${each_update#*revision=\"refs\/tags\/} echo "myrevision1 = $revision" revision=${revision%\"*} echo "myrevision = $revision" mkdir -p $patchs_path/$path echo sdk_dir:$sdk_dir echo path:$path cd $sdk_dir/$path git format-patch --src-prefix="a/$path/" --dst-prefix="b/$path/" -o $patchs_path/$path $revision fi done < $diff_file
里面注意几点:将manifest.xml注释行删除掉,另外脚本里面的$path 和 $revision 截取方式可能不太完善,如果有问题可以调试着去修改。
参考脚本执行
./manifest_patch_tool /opt/aosp/ /opt/aosp/lastreop/.repo/manifests/include/rk_modules_repository.xml /opt/aosp/.repo/manifests/include/rk_modules_repository.xml
执行成功会生成对应目录结构的patch文件在/tmp/allpatchs/
更新patch到本地git仓库
这个过程还是有点痛苦,因为补丁太多的话,很可能打patch的时候有冲突,需要处理冲突。(我更新了将近500个patch,花了我一下午时间才更新完毕) ORZ...
更新补丁的一些心得也分享下:
1.尽量按照目录文件夹来操作,比如: git am /tmp/allpatchs/device/rockchip/common/*.patch --reject
这个命令的好处,一次性更新一个目录的patch文件,如果有冲突会提示:
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
此时 可以
git status [报冲突的文件目录]
查看报冲突的目录文件更新情况,一般会有个.rej文件,这个就是提示的冲突异常,手动处理修改完冲突——一般也就是对比工具对比手动更新
处理完再把修改的文件git add 后继续执行 git am --continue 继续打补丁
2. 然后就是一直 git am [patches] 和 处理 rej异常,然后git am --continue
大概就是过程就是这样的了。
大家有什么好的建议也可以一起分享交流。