烦恼一般都是想太多了。

0%

Git使用patch来提取变更到其他分支

事情的缘由在于,我们的服务端用的是 svn 进行管理,而我在本地用的是 git ,采用主干 master 同步 svn trunk 的形式,然后我自己的功能代码是在本地分支 dev 进行的。
然后,一个猥琐的事情发生了,我在 dev 分支下执行了 git svn dcommit ,将分支代码提交到了 svn 上这一下就悲剧了。

事实上我一直有保证我的修改发生了 master,也就是 svn 代码库之后。每次 svn 代码有更新,我都会用 git rebase master 命令,将变更应用到外 dev 分支。实际上这样提交上去也没有什么问题,但是我的代码是没有开发完成了,有可能对线上代码造成破坏,所以将 svn 代码库回滚到了我提交前的代码库。

但这个时候,我已经无法用 rebase 命令,再把新信息给同步过来,即使可以,有可能会 rebase 的时候丢失东西,如删除了文件等。

所以我现在只有一条路,将我上一次 rebase 代码后的变更,都提交到一个新的,基于当前的,回滚过版本的 master 分支上,理论上是这样非常美好的。事实上也确实能执行。

git patch 文件的生成

我们可以用 git format-patch 来生成补丁文件。

git format-patch commitid -o ../patch

指定我上一次 commitId 后就会 生成很多个 patch 文件给我。

git patch 文件的应用

我们可以使用 git apply 或者 git am 命令来应用补丁,这两者的区别是,am 命令会进行提交,提交信息不会改变,而 apply 则不会进行提交,需要手动进行提交。如:

git am -s ../patch/0001-.patch

或者

git apply ../patch/0001-.patch

如果一切工作得好,那就没有问题了。

但如果出现冲突,那就是会是悲剧了。

冲突的解决

git am -s ../patch/0001-.patch # 这一步出现了冲突
git apply --reject ../patch/0001-.patch # 会将出现冲突的地方生成 .rej 文件,然后我们根据 .rej 文件手动进行解决
git add files # 添加我们修改后的文件。
git am --resolved # 继续被中止的打补丁
git log # 确认一下结果

脚本

我自己写了个脚本来完成这个事情:

for f in ../patch/*; do 
git am -s $f;
if [ $? -ne 0 ]; then
git apply --reject $f
exit;
fi
rm -f $f;
done

逻辑很简单,一旦补丁应用完成一个,就删除一个,如果失败,那么就用 apply 命令来检查一下,手动解决后继续执行。

patch 文件的格式

---
.../main/NewDataAnalysisFragment.java | 4 +--
.../main/DataAnalysisListMainActivity.java | 31 +++++++++++++++++++
2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/app/src/main/java/cn/nanming/smartsupervision/ui/activity/main/NewDataAnalysisFragment.java b/app/src/main/java/cn/nanming/smartsupervision/ui/activity/main/NewDataAnalysisFragment.java
index 0aad785..ccb80b5 100644
--- a/app/src/main/java/cn/nanming/smartsupervision/ui/activity/main/NewDataAnalysisFragment.java
+++ b/app/src/main/java/cn/nanming/smartsupervision/ui/activity/main/NewDataAnalysisFragment.java
@@ -29,7 +29,7 @@ import cn.nanming.smartsupervision.utils.CommonUtils;
* Date:2018/9/27
* Desc:数据分析新界面
*/
-@AppMenuView(value = "数据分析",ids = {R.id.iv_work_load_analysis,R.id.iv_work_data_analysis},names = {"工作量分析","数据分析"})
+@AppMenuView(value = "数据分析",ids = {R.id.iv_work_load_analysis,R.id.iv_work_data_analysis},names = {"工作量分析","数据分析M"})
public class NewDataAnalysisFragment extends BaseFragment {

其中:

  • a:源文件,b:变更的文件
  • index 0aad785..ccb80b5 100644 文件的索引变更,也就是git index的变更
  • @@ -29,7 +29,7 @@ import cn.nanming.smartsupervision.utils.CommonUtils; 29,7 表示 29行开始后的7行中的内容变更情况(忽略空行)
    看起来就像一个 diff 文件

apply 成功而 am 失败

这个问题的原因我一直没有找到。

避免将分支直接提交到 svn

提交代码之前用

git svn dcommit --dry-run

因为我们的 dev 实际上是没有跟踪分支信息,所以说直接就提交到 master 上去了。