Git系列常用命令之放弃修改

Git 是一种流行的分布式版本控制系统,它允许开发者在不同的分支上进行工作,同时保持代码的完整性和历史记录。在使用 Git 进行版本控制的过程中,我们可能会遇到需要放弃当前工作进度的情况,例如,当发现当前分支的修改与主分支的代码不兼容,或者需要切换到另一个分支继续工作时。

概述

这篇文章会介绍如何在 Git 中放弃对文件的修改,包括以下几个方面:

  • 放弃对单个文件/文件夹的修改:如果只想放弃对某个特定文件的修改,可以使用 git checkout 命令。
  • 放弃所有未提交的修改:如果需要放弃对所有未提交文件的修改,可以使用 git reset 命令。
  • 撤销已经提交的更改:如果需要撤销已经提交但尚未推送到远程仓库的更改,可以使用 git revert 命令。
  • 清理未跟踪的文件:有时候,你可能想要删除那些被错误添加到工作目录中但未被 Git 跟踪的文件,可以使用 git clean 命令。

文章可能会通过具体的命令示例和场景,帮助读者理解在不同情况下如何使用 Git 命令来放弃修改,以保持工作流程的流畅和代码的整洁。

两个概念

在 Git 中,indexcommit 是两个核心概念,它们在版本控制过程中扮演着不同的角色,理解这两个概念有助于加深对git工作原理的理解:

Index(索引)

  • Index 是 Git 用来准备下一次提交的暂存区。你可以将其视为一个准备提交的文件列表,这些文件已经被审查和选择,准备成为下一次提交的一部分。
  • 当你对工作目录中的文件进行更改并希望将这些更改包含在下一次提交中时,你需要使用 git add 命令将它们添加到 index 中。
  • Index 允许你在提交之前进行多次修改,并且可以对这些修改进行排序和组织,以确保提交是有意义的。
  • Index 是一个文件,位于 .git/index 文件中。

Commit(提交)

  • Commit 是项目快照的记录,它包含了项目的某个特定版本。当你执行 git commit 命令时,Git 会将当前 index 中的内容以及一些附加的元数据(如提交信息、作者、时间戳等)打包成一个提交对象,并存储在本地仓库中。

  • 提交是不可变的,意味着一旦创建,其内容就不能被更改。这保证了项目历史的完整性和一致性。

  • 提交可以看作是项目的版本号,每个提交都有一个唯一的哈希值,用于标识和引用特定的项目状态。

  • 提交是 Git 分布式特性的基础,因为它允许开发者在本地进行提交,而不必立即与远程仓库同步。

两者之间的关系可以这样理解:

  • 你首先对文件进行修改。
  • 使用 git add 将这些修改的文件添加到 index 中,这时候修改被暂存,准备提交。
  • 使用 git commit 将 index 中的内容以及提交信息一起打包,创建一个新的提交对象。

简而言之,index 是准备提交的暂存区,而 commit 是已经提交的快照记录。在进行提交之前,你可以多次修改 index,但是一旦执行了 commit,那么这个提交就是最终的,不可更改的。

请深刻理解这两个概念,有助于帮助您理解后面的内容

命令

Git Checkout - 切换分支或恢复工作目录树文件

更新工作区中的文件,使其与索引或指定的树中的版本一致。 如果没有给出pathspec,’git checkout’也将更新HEAD,将指定的分支设为当前分支

使用git checkout来切换分支用的很多,但是没想到还可以用来恢复工作目录,可以理解为:
将一个文件从另一个提交中取出,从索引中恢复,所以它不会影响到git add及之后的内容。

具体用法如下:

1
git checkout -- <filename>

注意这里的filename是支持通配符匹配的,比如

1
2
3
4
5
6
7
8
# 恢复hello.html
git checkout -- hello.html

# 恢复hello.开头的文件
git checkout -- "hello.*"

# 恢复.html结尾的文件
git checkout -- *.html

注意此方法只是将本地文件恢复了,没有对git add 和git commit 产生影响

Git-reset - 重置当前HEAD到指定的状态

复制条目到索索引或者将当前的分支头(HEAD)设置为某个commit

Git-revert - 还原某些现有提交

给定一个或多个现有提交,还原相关补丁引入的更改,并记录一些新提交来记录这些更改。 这要求你的工作区是干净的(没有对 HEAD 提交的修改)。

Git-clean - 删除工作目录树中未跟踪的文件

从当前目录开始,通过递归删除不在版本控制之下的文件来清理工作区。
通常情况下,只有 Git 未知的文件会被删除,但如果指定了 -x 选项,被忽略的文件也会被删除。例如,这对删除所有构建产品很有用。
如果给出任何可选的<路径规范>…​参数,只有那些与路径规范相匹配的路径会受到影响

一些常见场景

本地修改了一些文件 (并没有使用 Git Add 到暂存区),想放弃修改

  •   单个文件/文件夹:
1
git checkout -- <filename>
  •   所有文件/文件夹:
1
git checkout .

本地新增了一些文件 (并没有 Git Add 到暂存区),想放弃修改

  •   单个文件/文件夹:
1
rm  -rf <filename>
  •   所有文件
1
git clean -xdf

删除新增的文件,如果文件已经已经 git add 到暂存区,并不会删除!

  •   所有文件和文件夹:
1
git clean -xdff

ps:谨慎操作: 本命令删除新增的文件和文件夹,如果文件已经已经 git add 到暂存区,并不会删除!

本地修改/新增了一些文件,已经 Git Add 到暂存区,想放弃修改

  •   单个文件/文件夹:
1
git reset HEAD <filename>
  •   所有文件/文件夹:
1
git reset HEAD .

本地通过 Git Add 和 Git Commit 后,想要撤销此次 Commit

  • 撤销 commit, 同时保留该 commit 修改:
1
git reset <commit_id>

这个 commit_id 是你想要回到的那个节点,可以通过 git log 查看,可以只选前 6 位。

撤销之后,你所做的已经 commit 的修改还在工作区!

  •   撤销 commit, 同时本地删除该 commit 修改:
1
git reset --hard <commit_id>

这个 commit_id 是你想要回到的那个节点,可以通过 git log 查看,可以只选前6位

ps:谨慎操作: 撤销之后,你所做的已经 commit 的修改将会清除,仍在工作区/暂存区的代码也将会清除!

参考

1.Git - git-checkout Documentation
2.Git - git-reset Documentation
3.Git - git-revert Documentation
4.Git - git-clean Documentation