欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

将git工作目录的改动应用到svn

程序员文章站 2022-07-15 15:25:28
...

之前在维护自己写的WordPress插件时,为了能够方便地同时向GitHub仓库和WordPress官方的svn仓库提交,我只在本地维护了一个git工作目录,然后用git svn dcommit向svn仓库提交,用git push向GitHub提交。(详见我之前写的日志。)

但可能是因为WordPress官方的svn仓库太大,历史记录太多,而git-svn的内部实现又有点问题,所以最近几次我用git svn rebase和git svn dcommit都毫无反应。思来想去,为了不耽误时间,我还是决定老老实实用svn客户端了。

于是现在我本地就有了两个目录:一个git工作目录,用于向GitHub提交;一个svn工作目录,用于向svn提交。由于svn里的分支和标签实际上就是目录,因此svn工作目录下还有trunk、branches和tags子目录。trunk子目录里的内容才和git工作目录里的内容相同。

一般我是在git工作目录下写代码,因此思路是在git工作目录commit之后,用git diff生成patch文件, git log输出提交日志到另外一个文件。然后用patch命令将git diff应用到svn工作目录。最后svn commit的时候利用git log的输出,这样就可以做svn trunk分支的提交和git master分支的提交一一对应。这个过程如下图所示:

将git工作目录的改动应用到svn

目录结构如下所示:

$ pwd
/Users/zhixiangzhu/emwi
$ ls -R
git		svn
 
./git:
README.md				license.txt
external-media-without-import.css	readme.txt
external-media-without-import.js	screenshots
external-media-without-import.php
 
./git/screenshots:
screenshot-1.png	screenshot-2.png
 
./svn:
assets		branches	tags		trunk
 
./svn/assets:
banner-1544x500.jpg	icon-128x128.jpg	screenshot-1.png
banner-772x250.jpg	icon-256x256.jpg	screenshot-2.png
 
./svn/branches:
 
./svn/tags:
1.0	1.0.1	1.0.2	1.0.2.1
 
./svn/tags/1.0:
external-media-without-import.css	license.txt
external-media-without-import.js	readme.txt
external-media-without-import.php
 
...
 
./svn/trunk:
README.md				license.txt
external-media-without-import.css	readme.txt
external-media-without-import.js	screenshots
external-media-without-import.php
 
./svn/trunk/screenshots:
screenshot-1.png	screenshot-2.png

显然我在其中一个工作目录下做出改动后,还要将改动同步到另一个工作目录并提交。人工同步改动显然繁琐耗时又容易出错,需要自动化。我写了一个脚本git2svn.sh,用于将git工作目录中最新提交所做的改动应用到svn工作目录并自动提交到svn仓库。这个脚本就放在与git工作目录和svn工作目录同级的地方。可以在git工作目录中执行,也可以在父目录中执行:

$ pwd
/Users/zhixiangzhu/emwi
$ ls -R
git		svn		git2svn.sh

脚本内容如下:

# 如果当前是在父目录,则进入git工作目录
if [ $PWD != *git ]
then
	cd git/
	echo $PWD
fi
 
# 将git工作目录最新提交的改动输出到git.diff
git diff --no-prefix HEAD^ HEAD > ../git.diff
 
# 将git最新提交的提交日志输出到git_n.log
git log -1 --format="%B" HEAD > ../git_n.log
 
cd ..
 
# git_n.log的最后一行是空行,要将其删掉
perl -pe 'chomp if eof' git_n.log > git.log
rm git_n.log
 
# 更新svn工作目录
cd svn
svn update
 
# 将改动应用到svn/trunk目录
cd trunk
patch -p0 < ../../git.diff
 
# 提交到svn仓库,提交日志与git相同
cd ..
svn commit -F ../git.log
 
cd ..
rm git.diff git.log

脚本第17行的perl命令的作用是将git log -1 --format命令输出的git_n.log文件末尾的空行删掉,见https://*.com/a/1654042。其中-p的作用是打印输入文件git_n.log的每一行, -e作用是执行-e后面的perl代码。详见这篇Perl命令行参数的说明。 chomp用于去除空行。

不过这个脚本没有文件的添加和删除。对这两个情况还需要分别调用svn add和svn delete,等以后遇到这个需求再改进吧。

本文在我的独立博客上的地址:http://zxtechart.com/2018/03/20/apply-git-diff-to-svn

相关标签: git svn