糟糕,我写错了!Git 花式撤销大法

糟糕,我写错了!Git 花式撤销大法
Photo by Randy Laybourne / Unsplash

作为一个版本管理系统,撤销是一个非常重要的功能。特别是在 Vibe Coding 的时候,保不齐会出一些乱子。那么都有 Git 哪些撤销的办法呢?

核心概念速览

在深入场景之前,先理解 Git 的三个主要区域:

  1. 工作区 (Working Directory): 你在电脑上能看到的文件,可以直接编辑。
  2. 暂存区 (Staging Area/Index): 使用 git add 命令后,文件的快照被添加到的地方,准备下次提交。
  3. 版本库 (Repository): 使用 git commit 命令后,暂存区的文件快照被永久存入 .git 目录的地方,形成了历史记录。

工作区和暂存区的内容容易被误操作,需要小心。

尚未 commit

这是最常见的情况。如果使用 VSCode 等 GUI,可以直接在 Git 的插件里面点撤销,如果是命令行,则:

  1. 如果没有 git add

    # 撤销对单个文件的修改
    git checkout -- main.py
    
    # 或者使用新版的 git restore
    git restore main.py
    
    # 撤销对所有文件的修改
    git restore . 
    # 或者
    git checkout -- .
    

    以上操作将会把指定文件或者所有文件恢复到最近一次 commit 的状态,此操作不可逆,谨慎使用。

  2. 修改已经 git add,可以先移出暂存区

    # 将文件从暂存区撤出,但保留工作区的修改
    git reset HEAD main.py
    
    # 或者使用新版的 git restore
    git restore --staged main.py
    

    然后,可以根据情况继续按照上面没有 git add 的方法继续重置。

    此操作只是把暂存区的文件放回工作区,不会丢失修改。

已经 commit

  1. 刚才的提交有问题,想要修改,比如修改文件或者 commit message。这一步也可以用 VSCode 的 git 插件完成。

    # 先添加修改的文件。如果只是想修改信息,则忽略这一步。
    git add modified.py
    # 然后再使用 --amend 提交
    git commit --amend
    

    执行完毕之后,刚才的提交会被重写。旧的提交会被丢弃,以本次提交为准。

    Commit ID 会改变,因此如果已经 Push,则需要谨慎使用这一个命令。

  2. 想要彻底撤销最近的一次或者多次提交。

    由于 VSCode 的 git 插件没有提供 git reset 的选项,因此只能在命令行中完成。

    下面三种模式本质上是HEAD指针的移动,commit 并不会真的消失,git reflog 仍然可以看到,也可以恢复。

    1. 温柔模式:soft

      仅仅撤销提交的动作,工作区和暂存区里面的文件不会有任何变化。

      git reset --soft HEAD~1
      
    2. 默认模式:mixed

      不加额外参数,默认就是 mixed 模式,工作区里面的文件不会变化。

      执行下面的命令,刚才的提交,连同已经提交在暂存区里面的内容,都会返回到工作区中。

      相当于先 --soft,再执行 git reset 把暂存区的文件重置。

      git reset HEAD~1 
      # 相当于
      git reset --mixed HEAD~1
      
    3. 完全重置:hard

      暂存区和工作目录里面的文件全部都会变成目标提交的样子,也就是说,新的修改会完全丢失。

      这个选项是最危险的,需要谨慎使用。

      git reset --hard HEAD~1
      

如何修改分支指针?

运行下面的命令,即可把分支的头指向指定的 commit。

git branch -f <branch-name> <commit-hash>

这个命令不会影响工作区和暂存区,但是移动的分支不能是当前分支。

如果是当前分支,则需要先 detach,或者先切换到其他分支,此时需要先commit 或者 stash 来保存修改,然后再修改分支指针。

更多阅读

Git reset三种常用模式区别和用法
主要介绍git reset三种常用模式(soft、mixed、hard)的用法,不同的重置模式,对工作目录和暂存区的影响不同,课程通过一个示例对比了它们的区别。
Git的各种Undo技巧
GitHub的How to undo (almost) anything with Git这篇文章介绍了Git使用中的各种Undo技巧。 任何版本控制系统中最有用的功能之一就是能够**”撤销(undo)”你之前的错误。在Git中“undo”**功能可能因为场景的不同而有些许的差异。 当你进行一个新的提交时,Git会保存你在这个特定时间点的快照到本地的仓库中,之后,你可以通过Git来回到你早期的某
Git的10种撤销操作详解 - 蓝桥云课
蓝桥云课是国内领先的IT在线编程及在线实训学习平台,专业导师提供精选的实践项目,创新的技术使得学习者无需配置繁琐的本地环境,随时在线流畅使用。以就业为导向, 提供编程、运维、测试、云计算、大数据、数据库等全面的IT技术动手实践环境, 提供Linux、Python、Java、C语言、Node.js、Hadoop、PHP、Docker、Git、 R、SQL、MongoDB、Redis、Swift、Spark等千门热门课程。