將git工作目錄的改動應用到svn

之前在維護自己寫的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分支的提交一一對應。這個過程如下圖所示:


目錄結構如下所示:

$ 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://stackoverflow.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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章