在Git中,如何『删除』commit?

本文详细介绍了在Git版本控制系统中,如何根据不同的需求选择正确的命令来删除或撤销提交,包括恢复到旧版本、撤销特定提交以及从提交历史中完全删除提交。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Git中,如何『删除』commit?

本文主要参考 How can I delete a commit in Git? 以及文中的链接 翻译、整理而来。

在Git中,如何『删除』commit?
首先,要搞清楚你是哪种情况,因为『删除』commit 有3种方法,但是每种方法的适用情况不一样。
需要注意的是,这里的『删除』的意思是泛泛的,最终的效果像是『删除』了commit,而commit是否真的从提交的历史记录里删掉,则取决于采用的 git 命令。

顺便说一下,Git-Tower的教程还是不错的,在线教程免费,主题清晰,文章简练,有中英文两个版本,英文不错的,建议读读英文版。教程覆盖不到的地方,可以参考他们提供的FAQ

注:本文中 『commit』和『提交』的概念一样,但是由于中文『提交』的动词含义较重,所以在『提交』后面有其他描述的,则使用『commit』来代替『提交』。

★ 情况1:恢复到某个旧版本

在这里插入图片描述
直接采用Git-Tower网站中的原图。这种情况是说,你想要将项目的版本恢复到C2版本,在效果上等同于将后面的C3和C4 commit『删除』了。在这种情况下,git reset命令适合你。

$ git reset --hard 0ad5a7a6

此命令是将HEAD分支回退到指定的版本(0ad5a7a6),所有在这个版本(0ad5a7a6)之后的commit都删掉了。使用这个命令(带--hard参数)要慎重,因为如果你的改动从没有提交到仓库中,那么你的改动将无法恢复了。--hard参数是git reset命令的唯一的危险的参数。如果你删除错了,本地未提交的数据就彻底丢失了。如果已经提交到本地仓库中,则可以参考这个链接来恢复数据

$ git reset --soft 0ad5a7a6

使用--soft参数,会把 0ad5a7a6 之后所有的commit的改动保留在工作目录(Working copy)中,留给你做进一步处理。

git reset命令还是有些危险的,所以需要搞清楚git reset的原理之后再使用。更多git reset的原理介绍,请参考 git官方文档 重置解密

还有一种更安全的方式,可以保持HEAD分支不动,就是使用git checkout命令将某个旧版本拉到一个新分支中。

$ git checkout -b old-project-state 0ad5a7a6

-b参数用来创建一个新分支old-project-state。git checkout切换到old-project-state分之后,就恢复到了旧版本。

注1:HEAD是指向当前所在的分支的最后一次提交,也是下一次提交的父节点。可以看做是当前分支的别名,例如HEAD指向master分支,则也可以用『HEAD分支』来指代master分支。
注2:『HEAD分支』在Git-Tower中的原文为『HEAD branch』。

★ 情况2:撤销某一个commit

在这里插入图片描述

如上图所示,撤销 C2 这个commit,但是保留C3、C4的改动。在这种情况下,可以使用git revert命令。
git revert命令并不会删除C2,而是创建一个新的commit,将C2中的改动再改回去。如下图所示。

在这个例子中,在revert之前是没有C4 commit的,假设C2的commit id为 0ad5a7a6,执行git revert 0ad5a7a6则会创建C4 commit。

在这里插入图片描述

★ 情况3:从提交历史中删掉一个commit

如下图所示,从提交历史中删除C2 commit,而保留C3、C4的改动。

在这里插入图片描述
出现这种情况的时候,可能是因为我不小心提交了关键的、不应该公开的信息(例如密码、私钥),我需要从历史中把commit删掉。此时,就需要用到最强大也最危险的工具git rebase -i

例如,我有3次提交,使用git log命令显示如下:

$ git log --pretty=format:"%h %s" HEAD~3..HEAD
a5f4a0d added cat-file
310154e updated README formatting and added blame
f7f3f6d changed my name a bit

我想删除『a5f4a0d added cat-file』这个提交。

执行git rebase -i HEAD~3命令,结果如下:

$ git rebase -i HEAD~3
pick f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame
pick a5f4a0d added cat-file

删除commit a5f4a0d,就是把『pick a5f4a0d added cat-file』这一行删掉。如下,

pick f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame

保存并退出编辑器,git就把 commit a5f4a0d删掉了。

需要说明的是,如果只是删掉『a5f4a0d added cat-file』,不需要使用HEAD~3,使用HEAD~1就行,因为commit a5f4a0d是最后一个提交,是HEAD指向的提交。

  • 扩展:

如果只是想修改历史记录里的邮箱、名字,则可以用git filter-branch并配合--commit-filter来使用。例如,修改邮箱和名字的命令,将所有原来邮箱是schacon@localhost的commit,都把邮箱改为schacon@example.com,名字改为Scott Chacon。邮箱不是schacon@localhost的commit则邮箱保持不变。但是,所有受影响的commit的SHA-1校验都会变化。命令如下:

$ git filter-branch --commit-filter '
        if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
        then
                GIT_AUTHOR_NAME="Scott Chacon";
                GIT_AUTHOR_EMAIL="schacon@example.com";
                git commit-tree "$@";
        else
                git commit-tree "$@";
        fi' HEAD

★ 参考

<think>嗯,用户问的是如何在Git中撤销操作。这个问题挺常见的,毕竟在版本控制过程中难免会出错,需要回退。我得先理清楚常见的撤销场景,然后针对每个场景给出相应的命令和解释。 首先,用户可能想撤销工作区的修改,也就是还没添加到暂存区的文件。这时候应该用git checkout -- <file>或者git restore <file>。不过要注意,这个操作是不可逆的,会直接覆盖工作区的文件。 然后是已经添加到暂存区(git add之后)的文件,需要撤销暂存。这时候可以用git reset HEAD <file>或者git restore --staged <file>。这样文件会回到工作区,但修改还在,用户还可以继续修改或者再次暂存。 接下来是撤销提交,也就是git commit之后。如果要修改最后一次提交,可以用git commit --amend。这个命令会修改提交信息或者添加漏掉的文件。不过如果已经推送到远程仓库,就要小心了,因为这样会改变历史,可能需要强制推送。 如果要回退到之前的某个提交,可以用git reset。这里分三种模式:--soft保留工作区和暂存区,--mixed(默认)保留工作区但重置暂存区,--hard彻底丢弃所有修改。用户需要注意,使用--hard会丢失所有未提交的更改,必须确认是否需要这样做。 另一种情况是已经推送到远程仓库的提交需要撤销。这时候可能需要用git revert,因为它会创建一个新的提交来撤销之前的更改,避免历史重写的问题。不过如果有冲突的话,用户需要解决冲突后再提交。 另外,可能用户还会遇到需要找回被删除的提交的情况,这时候用git reflog查找之前的HEAD指针,然后reset回去。这个挺有用的,特别是误操作后恢复。 最后,总结一下各个场景和对应的命令,确保用户能一目了然。还要提醒用户谨慎使用--hard和强制推送,避免数据丢失。可能还需要强调不同命令的影响范围,比如工作区、暂存区、仓库和远程仓库的区别,帮助用户理解每个步骤的作用。</think>在 Git 中撤销操作需要根据具体场景选择不同策略。以下是常见场景的解决方案,按操作风险由低到高排列: 1. **撤销未暂存的本地修改** ```bash git checkout -- <文件名> # 传统命令 git restore <文件名> # Git 2.23+ 推荐 ``` $$注意:这会永久丢弃工作目录中的修改$$ 2. **撤销已暂存但未提交的修改** ```bash git reset HEAD <文件名> # 传统命令 git restore --staged <文件名> # Git 2.23+ 推荐 ``` 文件会保留在工作目录,但退出暂存状态 3. **修改最后一次提交** ```bash git commit --amend # 修改提交信息 git commit --amend --no-edit # 追加文件到最近提交 ``` $$警告:已推送到远程仓库时慎用$$ 4. **回退到历史提交(本地仓库操作)** ```bash git reset --soft HEAD~1 # 保留修改到暂存区 git reset --mixed HEAD~1 # 保留修改到工作区(默认) git reset --hard HEAD~1 # 彻底丢弃修改 ``` $$注意:--hard 操作不可逆$$ 5. **撤销已推送的提交** ```bash git revert <提交哈希> # 创建逆向提交 git push origin <分支名> # 推送撤销操作 ``` 这是最安全的远程仓库撤销方式 6. **找回误删的提交** ```bash git reflog # 查看操作历史 git reset --hard HEAD@{n} # 恢复到指定操作点 ``` **注意事项**: 1. 使用 `--hard` 前务必确认已保存重要修改 2. 强制推送 (`git push -f`) 可能破坏团队协作 3. 重要操作前建议创建临时分支备份当前状态 建议通过 `git status` 查看当前状态,根据提示选择合适方案。复杂场景可使用 `git add -p` 进行精细控制。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值