Git 实用操作:撤销 Commit 提交
有的时候,改完代码提交 commit 后发现写得实在太烂了,连自己的都看不下去,与其修改它还不如丢弃重写。怎么操作呢?
使用 reset 撤销
如果是最近提交的 commit 要丢弃重写可以用 reset
来操作。比如你刚写了一个 commit:
写完回头看了看,你觉得不行这得重新写。那么你可以用 reset --hard
来撤销这条 commit。
git reset --hard HEAD^
HEAD^ 表示往回数一个位置的 commit`,上篇刚说过。
因为你要撤销最新的一个 commit,所以你需要恢复到它的父 commit ,也就是 HEAD^
。那么在这行之后,你要丢弃的最新一条就被撤销了:
不过,就像图上显示的,你被撤销的那条提交并没有消失,只是你不再用到它了。如果你在撤销它之前记下了它的 SHA-1 码,那么你还可以通过 SHA-1 来找到他它。
使用 rebase -i 撤销
假如有一个 commit,你在刚把它写完的时候并没有觉得它不好,可是在之后又写了几个提交以后,你突然灵光一现:哎呀,那个 commit 不该写,我要撤销!
不是最新的提交,就不能用 reset --hard
来撤销了。这种情况的撤销,就要用之前介绍过的一个指令交互式变基:rebase -i
。
之前介绍过,交互式变基可以用来修改某些旧的 commit。其实除了修改提交,它还可以用于撤销提交。比如下面这种情况:
你想撤销倒数第二条 commit,那么可以使用 rebase -i
:
git rebase -i HEAD^^
Git 引导到选择要操作的 commit 页面:
pick 310154e 第 N-2 次提交
pick a5f4a0d 第 N-1 次提交
# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
...
在上篇中,讲到要修改哪个 commit 就把哪个 commit 前面的 pick
改成 edit
。而如果你要撤销某个 commit ,做法就更加简单粗暴一点:直接删掉这一行就好(使用 d
命令)。
pick a5f4a0d 第 N-1 次提交
# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
...
把这一行删掉就相当于在 rebase 的过程中跳过了这个 commit,从而也就把这个 commit 丢弃了。
如果你通过 git log
查看,就会发现之前的倒数第二条 commit 已经不在了。
使用用 rebase --onto 撤销
除了用交互式 rebase,你还可以用 rebase --onto
来更简便地撤销提交。
rebase 加上 --onto
选项之后,可以指定 rebase 的「起点」。一般的 rebase, 的「起点」是自动选取的,选取的是当前 commit 和目标 commit 在历史上的交叉点。
例如下面这种情况:
如果在这里执行:
git rebase 第3个commit
那么 Git 会自动选取 3
和 5
的历史交叉点 2
作为 rebase 的起点,依次将 4
和 5
重新提交到 3
的路径上去。
而 --onto
参数,就可以额外给 rebase 指定它的起点。例如同样以上图为例,如果我只想把 5
提交到 3
上,不想附带上 4
,那么我可以执行:
git rebase --onto 第3个commit 第4个commit branch1
选项 --onto
参数后面有三个附加参数:目标 commit、起点 commit(注意:rebase 的时候会把起点排除在外)、终点 commit。所以上面这行指令就会从 4
往下数,拿到 branch1
所指向的 5
,然后把 5
重新提交到 3
上去。
同样的,你也可以用 rebase --onto
来撤销提交:
git rebase --onto HEAD^^ HEAD^ branch1
上面这行代码的意思是:以倒数第二个 commit 为起点(起点不包含在 rebase 序列里),branch1
为终点,rebase 到倒数第三个 commit 上。
也就是这样:
总结
撤销最近一次的 commit 直接使用 reset --hard
,撤销过往历史提交。方法有两种:
- 用
git rebase -i
在编辑界面中删除想撤销的 commit - 用
git rebase --onto
在 rebase 命令中直接剔除想撤销的 commit
这有两种理念是一样的,即在 rebase 的过程中去掉想撤销的 commit,让它消失在历史中。
Git 实用操作:撤销 Commit 提交的更多相关文章
- Git 实用操作:重写 Commit 历史
当我们修改完代码,提交了一个 commit,然后发现改错了,怎么修正?下面分两种情况来讨论:修正最近一次提交,和修正历史多个提交. 修正最近一次提交 如果发现刚刚提交的内容有错误,当场再修改一下再提交 ...
- git rebase 操作撤销
git rebase可以更改提交历史,在不影响别人的情况下,能够重整git树. 但如果git rebase操作失误,却在push后才发现,怎么撤销rebase操作呢? 使用git reflog + g ...
- git实用操作21条
1.建空目录 mkdir e:\gg 2.把该目录变成仓库 git init //发现当前目录下多了一个.git 3.新建文件readme.txt 4.添加文件到仓库 git add readm ...
- GIT实用操作指令(更新中)
提取多次提交的文件 git archive --format=zip HEAD `git diff --name-only 较早的提交ID 较晚的提交ID` > diff.zip
- git 实用操作
查看某文件的某些行的变化历史: $ git log --pretty=short -u -L 2003,2005:Executor.cpp http://stackoverflow.com/quest ...
- Git撤销对远程仓库的push&commit提交
撤销push 1. 执行 git log查看日志,获取需要回退的版本号 2. 执行 git reset –soft <版本号> ,如 git reset -soft 4f5e9a90ed ...
- 使用git命令修改commit提交信息
很多时候我们在提交代码时可能会把commit提交信息写错了,这个时候我们就可以用到下面的git命令来修改commit提交信息 git commit --amend 输入"i"之后进 ...
- Eclipse IDE 使用指南:Git失误提交代码,撤销commit操作
在Eclipse IDE使用Git Commit提交代码时把不需要的文件失误Commit了,比如.settings..classpath..project等文件. 如果是Commit提交代码到本地仓库 ...
- 【原】git如何撤销已提交的commit(未push)
输入git log,我们可以看到最近的3次提交,最近一次提交是test3,最早的一次是test1,其中一大串类似黄色的字母是commit id(版本号) 如果嫌输出信息太多,可加上--pretty=o ...
随机推荐
- JDK 1.8 中文 API CHM
链接: https://pan.baidu.com/s/1AiJn6RM1KoEL1n_96qoQhQ 提取码: n2ya
- 漫画 | 到底是什么让IT人如此苦逼???
写在最后 漫画是有点夸张,不过多少还是有点现实开发过程的影子! 老板很乐观,核心就是三个月上线,至于怎么办那是底下人的事. 产品很无奈,心里盘算着,万万不可在他这一环节耽误了进度,时间这么赶,先出个壳 ...
- python新添加excel数据
相关库 import os import xlwt from xlrd import open_workbook from xlutils.copy import copy 1.判断是否存在xls文件 ...
- 设计模式:桥接模式及代码示例、桥接模式在jdbc中的体现、注意事项
0.背景 加入一个手机分为多种款式,不同款式分为不同品牌.这些详细分类下分别进行操作. 如果传统做法,需要将手机,分为不同的子类,再继续分,基本属于一个庞大的多叉树,然后每个叶子节点进行相同名称.但是 ...
- Salesforce学习笔记之Actions and Recommendations
设置Actions and Recommendations(Salesforce提供的标准元素),Salesforce上的文档说有两种方法,即Deployment和Process Builder(通过 ...
- OAuth2.0分布式系统环境搭建
好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 介绍 OAuth(开放授权)是一 ...
- Nginx同时支持Http和Https
现在的网站支持Https几乎是标配功能,Nginx能很好的支持Https功能.下面列举一个配置同时支持Http和Https的功能. 需要注意的是:既然选择使用Https,就是为了保证通信安全,那么就没 ...
- java基础-04:标识符与关键字
在Java中,标识符是代表你对程序中某个方法或变量赋予的一个名称,而这个名称不能是关键字 关键字:
- 为什么 max() 应该写成 b < a ? a : b 呢?
在 < C++ Templates 2nd Edition >Chapter 1 中,作者将 max() 模板定义如下: template <typename T> T max ...
- 使用 gopacket 进行数据包捕获,注入和分析
原文链接:https://www.devdungeon.com/content/packet-capture-injection-and-analysis-gopacket 接口文档:https:// ...