【git重案组】如何逃避git blame的追踪?
导语:程序员的血腥复仇——论如何偷偷修改代码而不被别人发现...
背景介绍
上周笔者在工作中发现git仓库出现了一个奇怪的问题,master分支中某文件的一次commit丢失掉了,但diff中没有任何记录,这让笔者一度怀疑是git或者code平台自己出了问题。
通过查询该文件的commit记录,可以看到最近的一次SHA为49c1a的commit确实丢掉了。
先明确前提,这是在一次merge中丢失的,而非经历了rebase或者reset操作,并没有对历史记录进行修改。
这里回顾下整个过程中的git 操作流,先从master checkout一个feature分支,在该分支提交了几次commit,merge master 到 feature,然后在master再次merge feature。
应该说这里虽然有不规范之处(没有提交merge request而是本地直接在master上merge然后push),但整体还算常规操作,即使是在merge中发生了冲突,不小心操作失误,按道理也不会没有diff记录。
merge的parent-1和parent-2
google一下找到了一篇相似的文章https://blog.laisky.com/p/git-merge/
该文章是在master分支上git pull,由于pull 的默认行为是 pull —merge,所以其实也是在merge中丢失的。
原文作者给出了一个比较清晰的解释:
众所周知,merge 是将两个 branch 合并为一个,所以每一个 merge commit 拥有两个 parents。当我们在 gitlab 或者 source tree 查看一个提交的具体修改时,其实就是将本次提交和其 parent 做 diff。而由于 merge commit 有两个 parent,并会将其排序为 1 和 2,当你试图查看一个 merge commit 的修改时,其实显示的是相对于 parent-1 的 diff。这样的一个问题是,如果 remote 不幸成为了 parent-2,那么你就可以通过巧妙的构造 parent-1 来实现一次“隐身”的代码修改。
我们提取原文核心,重点在于merge时的diff记录是相对于当前分支,假如当前分支是两周前的版本,而外来分支是一周前的版本,当merge时放弃掉一周前的版本,对原分支来说这次merge之后与之前并未发生改变,所以diff中自然也没有记录。
merge request 的不同之处
这个解释似乎也说的过去,不过在合并到master分支之前必然要本地merge一下master才可以快速合并,这个操作是逃避不了的,如果在本地merge时错误解决冲突会被隐藏下来,这岂不是git一个很大的缺陷吗?那code平台的merge request后的code review还有意义吗?
笔者自己搭建了一个测试仓库发现如果提交merge request,在code review的diff界面是看得到这次修改的,在提交之后也能在history中看到diff。难道gitlab(code平台应该是基于gitlab开发的)平台自己的diff算法更高级,所以才能发现这次错误?
笔者到这里产生了一个猜测,在本地操作的时候git 的diff算法有缺陷,它简单地把每一次commit的diff patch在一起,而code平台是老老实实做了两个文件夹的diff。
git diff的差异
在google之后,果然发现了不同(其实并不然…)!
在几个stackoverflow的问答和github的issue中笔者发现 github平台的pull request(虽然gitlab是merge request,实际上差不多)是使用了git diff的三点操作,而直接diff是两点操作,区别如下:
笔者一度以为突破口就在这里,但是仔细分析了git log —graph之后发现在merge request之前本地feature分支就已经merge了一次master,在这个情形下git diff的两点操作和三点操作根本没什么不同。
链接:What are the differences between double-dot “..” and triple-dot “…” in Git diff commit ranges? - Stack Overflow
https://github.community/t5/How-to-use-Git-and-GitHub/GitHub-pull-requests-showing-invalid-diff-for-already-merged/td-p/3000
merge的原理和fast-forward
Git merge采取三路合并策略,三路分别是基准分支(分叉的节点)、mine、theirs。
一次普通的merge会新建一个commit节点(7号节点)。
而如果在feature分支从master checkout之后,master并未出现新的commit,就会出现三种策略。
默认git merge会采取第三种策略,直接将master指针移到feature的头上即可,这里不会出现一个message为“merge xxx into xxx”的commit。
回到问题发生的场景上,在feature分支上执行git merge master的时候发生了一次普通的合并,生成一个“merge xxx into xxx”的commit,由于上文说到的原因,这个commit节点没有记录diff。当checkout回master再从master merge feature分支的时候,满足了fast-forward的条件,所以没有再次进行diff操作,没有对上次失误进行再次检查。
而code平台merge request默认的操作是—no-ff(这里补充一下,github是有squash选项的,但是code平台不支持),所以会强制再次进行一次diff,这时候上次merge中隐藏的错误得到了一个再次暴露出来的机会,在code review中就可以发现了。
解决方案
浅层原因:merge时错误处理了冲突
- 深层原因:没有走code平台merge request,没有禁止master分支直接pull
【git重案组】如何逃避git blame的追踪?相关推荐
- Git详解之六 Git工具(转)
Git 工具 现在,你已经学习了管理或者维护 Git 仓库,实现代码控制所需的大多数日常命令和工作流程.你已经完成了跟踪和提交文件的基本任务,并且发挥了暂存区和轻量级的特性分支及合并的威力. 接下来你 ...
- Git学习5:Git常用命令简明用法
不要使用git commit -a 该命令可以对本地所有的变更文件(包括对本地修改和删除的文件)执行提交操作,但是不包括未被版本库跟踪的文件. git命令补充说明 显示.git目录所在的位置 git ...
- Git详解之六 Git工具
Git详解之六 Git工具 Git工具 现在,你已经学习了管理或者维护 Git仓库,实现代码控制所需的大多数日常命令和工作流程.你已经完成了跟踪和提交文件的基本任务,并且发挥了暂存区和轻量级的特性分支 ...
- 你什么时候使用git rebase而不是git merge?
什么时候建议使用git rebase与git merge ? 成功改造后我还需要合并吗? #1楼 在合并/ rebase之前: A <- B <- C [master] ^\D <- ...
- 【代码管理】GitHub超详细图文攻略 - Git客户端下载安装 GitHub提交修改源码工作流程 Git分支 标签 过滤 Git版本工作流
GitHub操作总结 : 总结看不明白就看下面的详细讲解. . 作者 :万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details ...
- 【git学习二】git基础之git管理本地项目
1.背景 git基础打算分两部分来说,一部分是对于本地项目的管理,第二部分是对于远程代码仓库的操作.git执行本地项目管理包括对于相关文件的追踪,暂存区的比较分析,提交,撤销等功能. 2.本地项目管理 ...
- 一个 .git 目录,领悟 Git 的强大!
Git 是一个强大的工具,但是使用起来却不是很友好.如果程序员们能够真正花时间去理解 Git 的构成,将会避免很多不必要的麻烦. 以下为译文: 初学 Git 就像一个不懂当地语言的人来到一个陌生的国家 ...
- Git知识总览(六) Git分支中的远程操作实践
前几篇博客陆陆续续的讲了好多关于Git操作的内容, 其中在上篇博客聊了<Git中的merge.rebase.cherry-pick以及交互式rebase>,本篇博客仍然也不例外,不过本篇博 ...
- springboot去掉git版本控制_关于 Git 提交这些规范,你都遵守了吗?
来源:人人贷大前端技术中心http://juejin.im/post/5d0b3f8c6fb9a07ec07fc5d0 git是现在市面上最流行的版本控制工具,书写良好的commit message能 ...
- 【git学习】统计git项目某user的代码量
查看自己的代码量:(直接awk编程) git log --author="username" --pretty=tformat: --numstat | awk '{ add += ...
最新文章
- 动态规划:求最大公共子串
- 饿了么风神登录_海底捞首度登陆第三方外卖!联手饿了么全国配送“小火锅”...
- 8.Using Categorical Data with One Hot Encoding
- jsp网页实现自动刷新和自动跳转页面
- python 连接MYSQL数据库(入门帖)
- 遵义 计算机应用能力,遵义市人力资源和社会保障局
- java.sql.SQLException: Field 'id' doesn't have a default value解决方法
- XLSTransformer 导出Excel数据
- 计算机专业笔记本需要小键盘吗,笔记本小键盘数字键不能用 并点击解除锁定...
- weblogic部署war包
- OSChina 周四乱弹 —— 人类首张黑洞照片
- php正则表达式在线测试工具,在线测试正则表达式工具:适合asp.net vb.net cs.net等Web或者Windows程序,便于你快速编写正确正则表达式,提供正则表达式模板供参考。...
- Java ffmpeg视频压缩IOS播放没有声音问题解决(超级简单)
- 计算机科学的顶级会议期刊,一些计算机领域的顶级会议和期刊
- 【电气专业知识问答】问:什么叫组合电器?什么是GIS?
- 西南科技大学计算机考研好考吗,西南科技大学考研难吗?一般要什么水平才可以进入?...
- 百度图片推广广告位怎么做,图片广告位如何投放
- MindFusion教程:Charting for Java Swing中的FunctionSeries
- Linux定时运行Python脚本
- JDK源码阅读之路【不断更新】
热门文章
- Cool!15个创意的 CSS3 文本效果【下篇】
- 软引用、弱引用、 java
- [转]C#中多路IP摄像机的视频监控系统
- PHP 解析xml(包含非英文字符)
- 牛客多校2 - All with Pairs(字符串哈希+next数组)
- CH - 0502 七夕祭(思维+中位数优化+前缀和优化)
- 皇牌空战无限服务器,《皇牌空战:无限》正式停服 一个搏击长空的时代终结[多图]...
- edit plus 中文插件_iMindMap手绘思维导图软件中文版
- linux排序语言,Go语言排序sort的使用
- ESP8266开发笔记