一次git事故

在开发过程中,我们的版本管理方式是,一版本一分支。之所以这样,是因为随着开发的进行,版本随时会分叉(这里分叉是指,两个版本都需要后续开发,但是对同一模块的功能需要不一样的微调)。

随着分叉之后的持续开发,就会导致多个分支之间差别越来越大。因此,如果所有版本都添加同样功能或修改同一个Bug时,是不可以采用git merge的方式来进行的。因为很难找到他相同的父节点。这时patch会是一个很好的工具。

而这次事故正是git patch功能使用不当引起的,下面来模拟出一个完整的事故现场。

在最开始我们有一段原始代码如下,可以明显看到,在第18行代码中,将dst错打成了src。

void foo(std::vector<int> &src, std::vector<int> &dst, int id)
{
        for (auto iter = src.begin(); iter != src.end(); )
        {
                if (*iter == id)
                {
                        iter = src.erase(iter);
                }
                else
                {
                        ++iter;
                }
        }
        for (auto iter = dst.begin(); iter != dst.end(); )
        {
                if (*iter == id)
                {
                        iter = src.erase(iter);
                }
                else
                {
                        ++iter;
                }
        }
        dst.push_back(id);
        return ;
}

以此次commit为节点,分切出分支ver1和ver2。

然后在ver1分支上修改上述错误并使用git commit提交,由于也许有很多并行版本都有这个问题,一个一个去改很消耗时间还容易错。因此可以使用`git formatch-patch HEAD~1`来制作一个patch文件,我们得到的patch文件内容如下:

From 3c3a434d131c8cea38eb77b7b0f4681b78ae4172 Mon Sep 17 00:00:00 2001
From: findstr <findstr@sina.com>
Date: Sun, 4 Mar 2018 15:43:43 +0800
Subject: [PATCH] bugfix
 
---
 a.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
 
diff --git a/a.c b/a.c
index 241c07f..1157ab4 100644
--- a/a.c
+++ b/a.c
@@ -15,7 +15,7 @@ void foo(std::vector<int> &src, std::vector<int> &dst, int id)
        {
                if (*iter == id)
                {
-                       iter = src.erase(iter);
+                       iter = dst.erase(iter);
                }
                else
                {
--
2.4.6

切到ver2分支后,先手动将18行修改提交一次,再使用`git am 0001-bugfix.patch`来重复修复这个Bug。

预期中,执行完git am之后,只有两种情况。一是这个文件完全没有变化,二是会出现conflict。

然而,事实并没有想象中的那么美好,执行完git am之后,第7行的src被改成了dst。

以上基本就是整个事故的全部还原过程。

这种事故很难发现,一旦发现却很容易就知道原因。

分析一下patch文件,就会立即发现,整个patch行为是靠以下7行代码来定位的。

{
                if (*iter == id)
                {
-                       iter = src.erase(iter);
+                       iter = dst.erase(iter);
                }
                else
                {

恰巧,由于在git am之前,我手动修改了这一行,导致在执行git am时,不可能会匹配到这一块出错的代码。更巧的是,git可以使用个patch中的代码块匹配到第4行的代码,即然匹配成功了,git自然就会将修改应用。

从这个事故中,可以得到几点启示。

  1. patch并不是100%可靠的,执行之后最好查看一下结果

2. 大扩号另起一行,对版本管理工具不友好:D

3. DRY原则 不但对人适用,对版本管理工具同样适用

ps. 如果实在没有办法,就尽量扩大git diff输出的代码块大小,`git config –global diff.context 30`即可把代码块增加致30行

本文分享自微信公众号 - 重归混沌(findstrx),作者:重归混沌

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-07-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 从CPU层面谈谈优化

    大多数时间,大家都在从设计和算法上优化效率(这类优化往往效果比较明显,比如一个二分查找可以轻易将时间复杂度降低为lg(n))。但是在实现上,却很少有人注重实现效...

    重归混沌
  • 再学计算机图形学入门

    在网上查资料时,无意间发现了一门课叫《现代计算机图形学入门》。于是事隔将近3年后,我再一次尝试图形学入门。这次学习从8月20号开始,一直到10月11日,约持续了...

    重归混沌
  • 三角形光栅化时遇到的坑

    前一段时间打算写一个完整的游戏, 客户采用Unity3D引擎, 服务端则采用我自己的Silly网络框架。

    重归混沌
  • Vapor奇幻之旅(06 PostgreSQL)

    用Vapor连接数据库是一件令人兴奋的事,本篇就来介绍如何使用Vapor来连接PostgreSQL数据库,将数据持久化。

    Leacode
  • 沟通可视化、服务外网化与 SaaS 化

    2020 年的工作正式开启,大多数开发者的开工方式是云办公。对开发者来说,云办公意味着什么?如何开始云办公?云办公的发展趋势会怎样?基于此,云加社区联手知乎科技...

    云加社区
  • 会员定价-三个学了就能用的大招

    | 导语 在会员服务的极简公式:收入=付费用户数*客单价,上面玩来玩去也绕不开客单价的问题。今天就近期的有效实战经验来分享下调整会员定价提高客单价的几个关键作...

    腾讯大讲堂
  • Python大神教你打造自己的个性签名!

    点击链接加入群【python┮】:https://jq.qq.com/?_wv=1027&k=5w7Rllc

    云飞
  • 尼尔森AI助手报告出炉,如何用语音唤醒下一个商业时代?

    前几天,抖音上一支关于智能音箱的视频火了。视频里这位“孟同学”家中有五台不同品牌的智能音箱,当他说“屋里太黑了,想要开灯”时,五个音箱间进行了一番精彩的对话——...

    罗超频道
  • Pycharm配置PyQt5环境的教程

    使用镜像源快速安装PyQt5方法:pip install PyQt5 -i https://pypi.tuna.tsinghua.edu.cn/simple

    砸漏
  • 访问者模式

    一、简介 1、访问者模式表示一个作用于某对象结构中各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 2、模式中的成员角色 访问者(...

    用户1215536

扫码关注云+社区

领取腾讯云代金券