关注:CodingTechWork
引言
Git 是一款非常流行的分布式版本控制工具,它帮助开发者有效地管理代码历史,支持多种功能来帮助团队协作、追踪修改和维护代码质量。git reset
是 Git 中最强大、最复杂的命令之一,它的主要作用是重置当前分支到某个特定的提交状态。git reset
被用来修改提交历史、撤销某些操作,甚至回退到之前的某个阶段。
由于经常遇到需要撤销某些操作,本文详细总结和探讨git reset
的各个用法、原理以及一些实战示例,帮助你更好地理解这个命令如何工作,并展示如何在实际开发中灵活运用它。
git reset命令介绍
git reset
是 Git 中用来撤销更改 的一个命令,它能够修改当前分支的指针(HEAD)
。根据不同的参数,git reset
可以撤销工作区、暂存区和提交历史中的更改。
基本作用
- 重置当前分支的指针 :将分支的指针
(HEAD)
移动到指定的提交。 - 调整暂存区的状态:可以选择是否将更改从暂存区中移除。
- 修改工作区的状态:可以选择是否将更改从工作区中撤销。
区域简介
工作区(Working Directory)
工作区,也叫工作目录 ,是你本地计算机上存放项目文件的地方。它是你实际
编辑代码、添加新文件、修改现有文件的地方。
- 文件状态 :在工作区中,文件可以是未跟踪(untracked)、已修改(modified)或者已暂存(staged)等状态。
-** 操作**:你在工作区执行git add
命令时,会将文件从工作区移到暂存区;通过编辑和保存文件,会修改工作区的内容。
简单来说,工作区就是你本地存放项目文件的文件夹
,你在其中做出代码变动。
暂存区(Staging Area)
暂存区,也叫索引区(index) ,是一个介于工作区和本地仓库之间
的区域。它用于暂时存放你打算提交的文件变更。你在暂存区做的任何更改,都会在下一次提交时被记录到版本历史中。
- 文件状态 :当你使用
git add
命令将文件从工作区添加到暂存区时,文件的状态会变成"已暂存"
。 - 操作 :你在暂存区添加或删除文件时,不会立即影响版本历史,只有当你执行
git commit
时,暂存区中的所有更改才会被提交到本地仓库
。
暂存区是一个缓存区
,你可以在其中选择哪些更改会被提交,这样你可以按需整理提交的内容。
本地仓库(Local Repository)
本地仓库是 Git 存储所有版本历史和配置的地方,它包含了所有的提交记录(commit)
。在本地仓库中,Git 会保存所有提交的信息,并允许你查看项目的历史。
- 文件状态:文件在本地仓库中是已提交(committed)的状态,意味着它已经被永久记录在版本历史中。
- 操作 :你通过
git commit
命令将暂存区中的变更提交到本地仓库,之后这些变更就成为项目的历史记录,可以随时查看和回溯。
本地仓库是你项目的"历史档案馆"
,存放着项目的所有版本,允许你进行版本回溯、查看历史提交、创建分支等操作。
git reset的三种模式
在了解了三区的含义后,我们来看看git reset
提供了三种不同的模式,每种模式对 Git 仓库中不同区域(暂存区、工作区、提交历史)的影响不同。分别是:
--soft
:仅重置HEAD
(当前分支指针),不影响暂存区和工作区。--mixed(默认)
:重置HEAD
和暂存区,但不修改工作区。--hard
:重置HEAD
、暂存区和工作区,彻底丢弃所有修改。
假设你有以下的提交历史:
a1b2c3d Commit 3
d4e5f6g Commit 2
h7i8j9k Commit 1
git reset --soft
使用 git reset --soft
时,Git 只会移动当前分支的 HEAD
指针,而不会更改暂存区和工作区
的内容。这意味着,你可以"撤销"提交,但保留所有更改
。
用法示例:
bash
git reset --soft <commit-hash>
如果你想将当前分支回退到 Commit 2,但保留 Commit 3 中的所有修改,并将它们放回暂存区,可以执行:
bash
git reset --soft d4e5f6g
此时,HEAD 会指向 Commit 2,而 Commit 3 的修改会出现在暂存区,等待提交。
git reset --mixed(默认)
git reset --mixed
是 git reset
的默认行为,它不仅会将 HEAD 指针重置到指定的提交,还会将暂存区重置
为该提交的内容,但不会修改工作区的文件。因此,它的作用是将文件从暂存区移除
,但不会丢失工作区的修改
。
用法示例:
bash
git reset --mixed <commit-hash>
继续以相同的提交历史为例,如果你执行:
bash
git reset --mixed d4e5f6g
Git 会将 HEAD 指针重置到 Commit 2,并将暂存区重置为 Commit 2 的状态,但是 Commit 3 中的修改仍然存在于工作区。你可以通过 git status
查看哪些文件被修改,但尚未暂存。
git reset --hard
git reset --hard
是最强力的版本,它不仅会重置 HEAD 和暂存区,还会把工作区的所有更改丢弃
。使用此命令会清除所有未提交的修改
,恢复到指定提交的状态。
用法示例:
bash
git reset --hard <commit-hash>
假设你执行:
bash
git reset --hard d4e5f6g
Git 会重置 HEAD 到 Commit 2,暂存区也会恢复到该提交的状态,并且所有未提交的修改都将丢失。谨慎
使用--hard
选项,因为它会删除所有本地修改,无法恢复
。
git reset 的常见应用场景
撤销最近的提交
如果你想撤销最近的一次提交,可以使用 git reset
将 HEAD 重置到上一个提交。假设你想撤销最近的提交,但保留代码修改在工作区和暂存区 ,你可以使用 --soft
或 --mixed
选项。
示例:
bash
git reset --mixed HEAD~1
这将撤销最近的提交,并将更改保留在工作区。
撤销暂存区的更改
有时我们将一些修改错误地添加到暂存区,但不想撤销修改本身。这时可以使用 git reset
只从暂存区中移除这些修改,保留工作区的修改。
示例:
bash
git reset HEAD <file>
这将把指定文件从暂存区中移除,但不修改工作区的文件内容。
恢复到某个历史提交
如果你希望将当前分支恢复到某个历史提交,可以使用 git reset --hard
来彻底回退到那个提交并删除所有后续的提交记录。
示例:
bash
git reset --hard d4e5f6g
这将使当前分支指向 Commit 2,并删除 Commit 3 之后的所有更改。
使用 Git Reset 时的注意事项
严格避免在公共分支上使用 git reset --hard
git reset --hard
会永久删除
提交历史中的内容,如果你在公共分支(例如 master
或 main
)上使用它,可能会导致其他开发人员的工作丢失。尤其是当你已将更改推送到远程仓库时,避免使用 git reset --hard
。
恢复丢失的修改
如果你不小心丢失了修改,可以使用 Git 的 reflog
命令来查找并恢复丢失的提交。git reflog
会记录所有 HEAD 的变动历史,即使你使用了 git reset --hard
,也有可能通过 reflog 找回丢失的提交。
bash
git reflog
git reset --hard <commit-hash>
使用 git reset 修改提交历史
git reset
允许你修改历史,但要小心,如果你已经将修改推送到远程仓库,执行 git reset
后需要使用git push -f
强制推送,这可能会导致其他团队成员的本地仓库与远程仓库不同步,影响协作。这个在团队开发过程中就遇到过,某位小伙伴把代码给合并错了,已经推送到了远程仓库,这个时候需要回滚到他合并的上次,从本地git reset
到上次的commit后,怎么也推不到远程,后来查了一下,原来是需要加-f
来强推。
git reset 与 git revert 的区别
虽然git reset
和git revert
都是用来撤销更改的,但它们有很大的区别:
git reset
会修改提交历史,适用于本地操作,可以撤销提交并将工作区或暂存区恢复到某个状态。使用 git reset 时,特别是在公共分支中,要小心影响其他开发者的工作。git revert
会创建一个新的提交,撤销指定提交的更改,适用于公共分支,保证历史记录不被修改。在需要恢复提交历史时,使用 git revert 是更为安全的选择。
总结
git reset
是一个非常强大的命令,它能够帮助开发者灵活地调整代码历史、撤销提交、更改暂存区或工作区的内容。掌握 git reset
的不同选项(--soft
、--mixed
和 --hard
)以及其适用场景,可以让你在面对复杂的开发问题时游刃有余。
然而,git reset
也需要小心使用,尤其是在团队协作中,避免误操作导致代码丢失。