Git 常用操作 | 重写 commit 历史
当我们修改完代码,提交了一个 commit,然后发现改错了,怎么修正?这种情况分为两种:修正最近一次提交,和修正历史多个提交。
修正最近一次提交
如果发现刚刚提交的内容有错误,当场再修改一下再提交一个新 commit
不就可以么?可以是可以,不过还有一个更加优雅和简单的解决方法:
git commit --amend
"amend" 是“修正”的意思。在提交时,如果加上 --amend
参数,Git 不会在当前 commit
上增加 commit
,而是会把当前 commit
的内容和暂存区(stageing area)里的最近一次 commit 的内容合并起来后创建一个新的 commit
,用这个新的 commit
把之前最新的 commit
替换掉。所以 commit --amend
做的事就是它的字面意思:对最新一条 commit
进行修正。
具体地,比如你发现刚刚的提交中 foo.txt 文件有错别字,你就可以把文件中的错别字修改好之后,输入以下命令:
git add foo.txt
git commit --amend
此时 Git 会把你带到提交信息编辑界面。提交信息默认是最近那次提交时填的信息。你可以修改或者保留它,然后保存退出。然后,你的最新 commit
就被更新了。
需要注意的有一点:commit --amend
并不是直接修改原 commit
的内容,而是如上面动图所示生成一条新的 commit
。
修正历史多个提交
commit --amend
可以修正最新 commit
的错误,但如果是倒数第二个、第三个 commit
写错了,怎么办?
如果不是最新的 commit
写错,就不能用 commit --amend
来修复了,而是要用 rebase
。不过需要给 rebase
也加一个参数:-i
。
rebase -i
是 rebase --interactive
的缩写形式,意为“交互式变基”。
所谓交互式 rebase,就是在 rebase
的操作执行之前,你可以指定要 rebase
的 commit
链中的哪一个 commit
是否需要进一步修改。
那么你就可以利用这个特点,进行一次原地 rebase。
例如你是在写错了 commit
之后,又提交了一次才发现之前写错了。现在再用 commit --amend
已经晚了,此时就要用 rebase -i
命令了:
git rebase -i HEAD^^
在 Git 中,有两个「偏移符号」:^
和 ~
。
^
的用法:在 commit
的后面加一个或多个 ^
号,可以把 commit
往回偏移,偏移的数量是 ^
的数量。例如:master^
表示 master
指向的 commit
之前的那个 commit
;HEAD^^
表示 HEAD
所指向的 commit
往前数两个 commit
。
~
的用法:在 commit
的后面加上 ~
号和一个数,可以把 commit
往回偏移,偏移的数量是 ~
号后面的数。例如:HEAD~5
表示 HEAD
指向的 commit
往前数 5 个 commit
。
上面这行代码表示,把当前 commit
( HEAD
所指向的 commit
) rebase
到 HEAD
向前两个的 commit
上:
如果没有 -i
参数的话,这种原地 rebase 相当于空操作,会直接结束。而在加了 -i
后,就会跳到一个新的界面:
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
...
这个编辑界面的最顶部,列出了将要被 rebase 的所有 commit
s,也就是倒数第二个 commit
“第 N-2 次提交”和最近的 commit
“第 N-1 次提交”。需要注意,这个排列是正序的,旧的 commit
会排在上面,新的排在下面。
这两行指示了两个信息:需要处理哪些 commit
和如何处理它们。
你需要修改这两行的内容来指定你需要的操作。每个 commit
默认的操作都是 pick
,表示直接应用这个 commit
。所以如果你现在直接退出编辑界面,那么结果仍然是空操作。
但你的目标是修改倒数第二个 commit
,也就是上面的那个“第 N-2 次提交”,所以你需要把它的操作指令从 pick
改成 edit
。edit
的意思是应用这个 commit,然后停下来等待继续修正。其他的操作指令,在这个界面里都已经列举了出来(下面的 "Commands…" 部分文字),你可以自己研究一下。
edit 310154e 第 N-2 次提交
pick a5f4a0d 第 N-1 次提交...
把 pick
修改成 edit
后,就可以退出编辑界面了,并输出以下信息:
$ git rebase -i HEAD^^
Stopped at 310154e... 第 N-2 次提交
You can amend the commit now, withgit commit --amendOnce you're satisfied with your changes, rungit rebase --continue
上图的提示信息说明,rebase
过程已经停在“第 N-2 次提交”的 commit
的位置,那么现在你就可以去修改你想修改的内容了。
修改完成后,和前文修改最近提交的方法一样,用 commit --amend
把修改原地应用到一个新的 commit
:
git add foo.txt
git commit --amend
这样你的倒数第二个错误的 commit
就被修正了。在此过程中,把原来倒数第二个 commit 的内容和当前修改的内容合并在一起创建了一个新的 commit,并用此 commit 原地替换了原来的原来倒数第二个 commit:
然后,你可以用 rebase --continue
来继续上述 rebase
过程。
git rebase --continue
所有需要重写的 commit 都修改完成后,这次交互式 rebase
的过程就完美结束了。
总结
只修正最近的错误提交,使用简单的 commit --amend
即可。若修改历史多个提交用交互式变基 rebase -i
,它可以在 rebase
开始之前指定一些额外操作。通过交互式变基还可以实现其它历史重写操作,如“重新排序提交”、“压缩提交”、“拆分提交”等,这些历史重写操作不常用,我个人从来没用过,所以就不讲了,你可以在实际有需要的时候自己再去研究一下。
-
精致码农
带你洞悉编程与架构
↑长按图片识别二维码关注,不要错过网海相遇的缘分
Git 常用操作 | 重写 commit 历史相关推荐
- git常用操作以及码云Gitee连接git
文章目录 1 git简介 1.1 工作区.暂存区.版本库 1.2 工作区状态保存 2 和gitee连接 2.1 创建git仓库 2.2 通过ssh公钥连接 2.2.1 获取公钥 2.2.2 gitee ...
- Node.js Git Server搭建及Git常用操作笔记
Node.js Git Server搭建及Git常用操作笔记 安装Git工具即可在本地进行Git仓库的管理,如果要实现远程仓库则需要搭建Git Server.通过Node.js搭建Git Server ...
- git 常用操作总结——基于Gitlab
博主目前在蚂蚁集团-体验技术部,AntV/S2 是博主所在团队的开源项目--多维交叉分析表格,欢迎使用,感谢到 S2 github 仓库点赞 star,有任何关于前端面试.就业.技术问题都可给在文章后 ...
- git报错:‘fatal:remote origin already exists‘怎么处理?附上git常用操作以及说明。
git添加远程库的时候有可能出现如下的错误, 怎么解决? 只要两步: 1.先删除 $ git remote rm origin 2.再次执行添加就可以了. ---------------------- ...
- 版本控制工具——Git常用操作(下)
本文由云+社区发表 作者:工程师小熊 摘要:上一集我们一起入门学习了git的基本概念和git常用的操作,包括提交和同步代码.使用分支.出现代码冲突的解决办法.紧急保存现场和恢复现场的操作.学会以后已经 ...
- Git 实用操作 | 撤销 Commit 提交
有的时候,改完代码提交 commit 后发现写得实在太烂了,连自己的都看不下去,与其修改它还不如丢弃重写.怎么操作呢? 使用 reset 撤销 如果是最近提交的 commit 要丢弃重写可以用 res ...
- Git学习总结(22)——Git 常用操作再总结
一.前言 每一个项目,我们都把他变成一个git仓库.一个git仓库包含无数分支,默认分支为master,每个分支都包含无数个版本库,每个版本库都包含无数个文件. 二.常用操作 $ git co(che ...
- Git常用操作速查,没有人比我更简单!!
目录 Git初始化 Git配置 init clone commit branch push pull checkout merge log rm reset --hard rebase 应用场景 其他 ...
- git常用操作及原理--本地
工欲善其事,必先利其器 git是跨平台的,在linux.windows.mac上都能使用的优秀的版本管理工具. git干啥的? 为什么要用git?话不多说,看图: 你是否也有这样的遭遇,文件有很多个 ...
最新文章
- ubuntu 启动器
- 优化JS加载时间过长的一种思路
- Tomcat一步步实现反向代理、负载均衡、内存复制
- pat 乙级 1023 组个最小数(C++)
- CentOS 7 firewalld使用简介
- 【Web】WEB项目初启动的那些糟心事
- 栈溢出笔记1.12 栈Cookie
- ORA-00054:资源正忙,但指定以nowait方式
- Ubuntu 18.04上使用snort3搭建NIDS(一)| 安装篇
- Qt对图像的二值化处理
- 基于Ubuntu虚拟机的Linux驱动开发入门
- python add sheet_Python系列(6)——使用openpyxl将三种类型的数据添加进新sheet及已有的sheet中且不覆盖原数据...
- 光电信息科学与工程学c语言吗,光电信息工程专业排名_光电信息科学与工程专业可以考什么专业的研究生...
- 服务器怒稳定进不了某个网址,登录服务器的一瞬间,让我感觉自己再也不是“菊外人”...
- 2022腾讯云服务器租用费用价格表(轻量和CVM精准报价)
- 小程序 设置小程序打开聊天中的素材
- 处理txt文件下载下来以后,排版格式不对的问题
- 《财务自由之路III》阅读笔记2021-03-18
- excel标题行列浮动显示/冻结窗口
- 在idea配置虚拟机参数与虚拟机内存溢出