git版本回退, github版本回退
上周提交了更改,过了周末回来说要撤销上个story。于是,需要找到上周提交的版本,rollback回来。
git版本管理命令,自从习惯使用管理工具之后就很少接触了,当突然寻找其他指令的时候就成浆糊了,ctrl+k只能顺利的提交而无关管理。因此,工具简化操作却弱化了技能。就像前几天听到的BBC 6分钟英语的一段对话。
Rob说他当年在酒吧实习,对钱的加减算法很熟悉很强,因为那时候计算机还没有推广。
计算器的出现使人们放弃了自己计算的本领。有时候即便仅仅是简单的加减法也不愿用自己的脑袋计算了。不说好坏,自己的感觉非常糟糕,因为觉得自己曾经拥有的技能消退了而难过。所以说,加强自身而不完全依赖于外物还是很重要的。
# Attention
更多Git以及Github的用法,参阅[Github工作流的正确打开方式](http://www.cnblogs.com/woshimrf/p/git-workflow.html)
# 结论放开头
- 不要在公共分支做reset, 不要修改公共分支的历史
- 使用revert不会改变历史,只是增加一个版本
1.reset
几个月前,我提交了一次更改,这个更改涉及几十个文件,提交到github,Jenkins build,然后health check 503 error。看着报错我毫无头绪,不明白health check究竟是因为代码的哪部分造成的,这提醒我以后的错误日志一定要详细。但有一点是肯定的,这次提交的更改有问题。既然上一次的代码没问题,那就回退吧。
我在本地,使用git reset current branch to here. 这是Intelij自带的git管理工具,可以指定版本后,然后回退到指定版本。本质上就是 git reset 版本号。
显然,这个指令就是将head指针后退了一下,也就是说,当前版本是落后的。而我从master的最新一次提交reset到倒数第二个,那么我的当前的版本比maser落后一次提交。
既然回退好了,需要merge到master上面。对应到github上就是pull request.然而,当我选择pull request的时候显示nothing.说本次更改不用merge。也就是说master的历史中已经包含了这个版本,所以不用merge。
因此,如果想要合并分支,那么要合并的分支必须比当前分支的版本先进。显然,reset只能重置本地或者说本分支的更改。那么,我如果想要mater回退,我必须提交一个比mater先进而且内容正好的是上一次提交的相反的修改。这就是revert干的事情。
2.revert
revert指定版本可以实现版本回退。这个不是像reset一样指针回退,而是会创建一个新的提交,而且将指定版本的修改逆过来。这样,我们想回退的内容被逆反修改过来了,而且我们的版本比master先进。这样就可以直接提交了。
具体做法:
假设当前git log为:
G1 - G2 - G3 - B1 - B2 - B3
G1-G3 正确的,好的,但 B1-B3 需要丢弃。
如果这些log都是在本地分支,那么可以使用reset:
$ git reset --hard HEAD~3
注释: B3 as HEAD, B2 is HEAD~1, B1 is HEAD~2. 好的 G3 is HEAD~3:
G1 - G2 - G3 - B1 - B2 - B3
-- HEAD
------ HEAD~1
---------- HEAD~2
-------------- HEAD~3
但是如果这些log提交已经在远程分支了,那就只能使用 revert:
$ git revert --no-commit HEAD~2^..HEAD
Or:
$ git revert --no-commit HEAD~3..HEAD
注释:
--no-commit是说虽然HEAD~2到HEAD的提交已经被回滚了,但回滚的内容会放在缓存区,需要stage后commit才能生效。
这里,"start..end"的意思是不包含start,包含end。
注意:
1. Merge操作不能revert
2. 对于使用IDEA做开发的,推荐使用IDEA自带的回退。查看log,然后点击需要回退的文件,右键revert。
3. 回退要慎重,很容产生冲突。
参考
git代码回滚:Reset、Checkout、Revert的选择
Git - how to revert multiple recent commits
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 七日Python之路--第十天
- 初学Vue.js,用 vue ui 创建项目会不会被鄙视
- 十三、jQuery过时的今天,你还会使用它吗
- 0005 Java 包扫描实现和应用(Jar篇)
- python基础 -- acm
- 十四、深入核心,详解事件循环机制
- python基本 -- threading多线程模块的使用
- python基本 -- mysql 的使用
- python爬虫----(6. scrapy框架,抓取亚马逊数据)
- 十五、这一次,彻底弄懂Promise的使用
- python爬虫----(5. scrapy框架,综合应用及其他)
- 十六、半小时掌握ES6常用知识,覆盖80%实践场景
- python爬虫----(4. scrapy框架,官方文档以及例子)
- python爬虫----(3. scrapy框架,简单应用)
- python爬虫----(2. scrapy框架)