git reset hard,mixed,soft

首先,我们得了解git reset命令的形式之一:

git reset [<mode>] [<commit>]

此命令的作用是恢复HEAD分支到<commit>位置,并根据<mode>决定是否恢复index file和working tree。恢复是指将staging area和working tree的状态还原到commit的状态(如果不指定commit,则默认为last commit)。如果没有pick哪个mode,即omitted mode,则mode默认为--mixed。<commit>可以为commit的hash id或引用值。

此外,mode还有两个值:--soft和--hard。

--soft不会改动(touch) index file和working tree,但是会撤销head到commit之间的all history,这是三个模式所共有的作用。

bash 复制代码
$ git status

On branch main

Changes not staged for commit:

 (use "git add <file>..." to update what will be committed)

 (use "git restore <file>..." to discard changes in working directory)

​    modified:  README.md

no changes added to commit (use "git add" and/or "git commit -a")

$ git add README.md

$ git status

On branch main

Changes to be committed:

 (use "git restore --staged <file>..." to unstage)

​    modified:  README.md

$ git log --graph --oneline

\* 0a071ac (HEAD -> main) A

\* 0c888f4 Initial Commit

$ git reset --soft 0c888f4

$ git status

On branch main

Changes to be committed:

 (use "git restore --staged <file>..." to unstage)

​    modified:  README.md

$ git log --graph --oneline

\* 0c888f4 (HEAD -> main) Initial Commit

可以观察到commit A的committed changes都reset为staged changes to be committed。原本已经stage等待commit的changes不会被reset。HEAD指向<commit>,HEAD到<commit>的提交都会被undo。

--mixed在--soft的基础上,进一步reset,它会恢复index到<commit>时的状态。已经在index中的changes会reset回working tree,note that modify working tree≠reset working tree。

bash 复制代码
$ git reset 0c888f4

Unstaged changes after reset:

M    README.md

git reset会报告影响到的changes。

--hard会在--mixed的基础上恢复working tree的状态。被跟踪的changes会被丢弃。

Any untracked files or directories in the way of writing any tracked files are simply deleted.

Git文档中的这句话我不是太理解,通过询问ChatGPT,翻译为:任何阻碍跟踪文件的写入的未跟踪文件或目录将被删除。

下面是一个Stack Overflow对该疑问的解释代码例子:

bash 复制代码
There is a case in which git reset --hard has effects on untracked files.

$ touch a.txt

$ git add .

$ git commit -m'A'

$ echo hello >> a.txt

$ git add .

$ git commit -m'B'

$ git rm a.txt

$ echo world > a.txt

$ git status -s

The status output is

D  a.txt

?? a.txt

The a.txt in the index is removed and the one in the work tree is untracked.

$ cat a.txt

world

Reset in the mode of --hard,

$ git reset --hard

$ cat a.txt

hello

$ git status

On branch master

nothing to commit, working tree clean

The untracked a.txt in the work tree is deleted. But we could also say it's been overwritten with the tracked a.txt in HEAD.

相关推荐
YoungHong199211 小时前
Git删除本地已经merge到远程的分支
git
内核程序员kevin16 小时前
GitHub新手入门 - 从创建仓库到协作管理
git·github
南城巷陌19 小时前
node.js实现批量修改git项目的数据源
git·node.js·修改git项目数据源
动不了一点1 天前
关于git使用的图文教程(包括基本使用,处理冲突问题等等)超详细
git
joan_851 天前
git提交顺序为什么是:add,conmmit,pull,push
git
yangmc042 天前
二维前缀和 子矩阵的和
c语言·数据结构·c++·git·算法·矩阵·图论
W、明义2 天前
IDEA git提交时如何忽略某个文件或文件夹
java·git·intellij-idea
我是哈哈hh2 天前
Linux环境基础开发工具的使用_yum源_vim_Git控制器
linux·运维·c++·git·vim·1024程序员节
待磨的钝刨2 天前
四期书生大模型实战营(【基础岛】- 第1关 | 书生·浦语大模型开源开放体系)
linux·服务器·git·python
single5942 天前
c++学习:封装继承多态
开发语言·c++·git·vscode·学习