【学了就忘】Git后悔药 — 36.通过路径进行重置

1、通过路径来重置修改说明

前面讲述了 git reset 命令的基本用法,不过你还可以给它提供一个作用路径(路径+目录/文件)。

若指定了一个路径,git reset命令将会跳过第 1 步,并且将它的作用范围限定为指定的文件或文件集合。

这样做自然有它的道理,因为 HEAD 只是一个指针,你无法让它同时指向两个提交中各自的一部分。

不过索引和工作目录 可以部分更新,所以回退会继续进行第 2、3 步。

现在,假如我们运行 git reset file.txt ,这其实是 git reset --mixed HEAD file.txt 的简写形式。

他会做如下操作:

  1. 移动 HEAD 分支的指向 (已跳过):实际上命令中写的是HEAD,就是当前commit,所以显示的效果是跳过了这一步。(我的理解)
  2. 让暂存区中的file.txt文件进行撤销。
  3. 而工作区中的file.txt文件的修改,保持不变。

大家想一下这个场景:我在工作区修改完文件,然后添加到了暂存区中,但是我还没有提交到本地版本库中。这个时候我发现有内容写错了,我此时执行 git reset file.txt命令,即git reset --mixed HEAD file.txt 命令。

就会发生表面现象,只是从暂存区中把file.txt文件,撤回到工作区了,且工作区中的修改保持不变,同时暂存区中其它文件不改变。

这样的效果,也就相当于是git add filename命令和git reset filename命令,是相互的反操作。

2、图解说明

1)步骤1:

现在有一个V1版本的file.txt文件,进行修改后,变成V2版本,添加到暂存区中。

就是如下图所示的状态:

2)步骤2:

我发现刚刚修改file.txt文件有错误,需要从暂存去中撤回到工作区中,进行重新修改。

执行命令:git add filename

如下图所示:


说明:

它本质做的是,是将 file.txt 文件从 HEAD 复制到暂存区中,进行单文件的覆盖。

这样就有了"取消暂存文件"的实际效果。 然后再想想 git add 命令所做的事,就会发现它们正好相反。

这就是为什么 git status 命令的输出提示中,会建议运行此命令来取消暂存一个文件。

3、拓展

我们可以不让 Git 从 HEAD 拉取数据,而是通过具体指定的某一个提交,来拉取该文件的对应版本。

如下:现在Git的工作目录中,工作区、暂存区和本地版本库中的file.txt文件都是V3版本,我需要把暂存区中的file.txt文件恢复成V1版本。

只需执行命令:git reset eb43bf -- file.txt 即可。

即执行了git reset --mixed eb43bf -- file.txt命令。

如下图所示:

(到这里我也没有,没有具体的底层操作流程是什么。我只知道,只要这样执行命令,工作区和本地版本库中的文件都不会改变,只有暂存区中的文件会回退到指定的版本。)

下面我们通过命令行演示:

# 1.查看历史提交信息
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git log --oneline
e72b30f (HEAD -> master) 第4次提交,新增内容:readme.txt file v4
529ad74 第3次提交,新增内容:readme.txt file v3
1b23cae 第2次提交,新增内容:readme.txt file v2
2612adf 第1次提交,创建readme.txt文件

# 2.查看可回退的历史提交信息
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git reflog
e72b30f (HEAD -> master) HEAD@{0}: reset: moving to e72b30f
529ad74 HEAD@{1}: reset: moving to HEAD^
e72b30f (HEAD -> master) HEAD@{2}: commit: 第4次提交,新增内容:readme.txt file v4
529ad74 HEAD@{3}: commit: 第3次提交,新增内容:readme.txt file v3
1b23cae HEAD@{4}: commit: 第2次提交,新增内容:readme.txt file v2
2612adf HEAD@{5}: commit (initial): 第1次提交,创建readme.txt文件

# 3.查看工作目录中文件状态,很干净
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git status
On branch master
nothing to commit, working tree clean

# 4.查看readme.txt文件内容
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ cat readme.txt
readme.txt file v1
readme.txt file v2
readme.txt file v3
readme.txt file v4

# 5.把暂存区中的readme.txt文件回退到V1版本。
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git reset 2612adf -- readme.txt
Unstaged changes after reset:
M       readme.txt

# 6.比较工作区和暂存区中readme.txt文件的差别
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index 0d065f4..47b238c 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1,4 @@
 readme.txt file v1
+readme.txt file v2
+readme.txt file v3
+readme.txt file v4

# 7.比较暂存区与本地版本库中readme.txt文件的差别
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git diff --cached readme.txt
diff --git a/readme.txt b/readme.txt
index 47b238c..0d065f4 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,4 +1 @@
 readme.txt file v1
-readme.txt file v2
-readme.txt file v3
-readme.txt file v4

# 8.查看暂存区readme.txt文件的内容如下:
# 查看暂存区中文件的信息
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git ls-files -s
100644 0d065f480e5ac0200f678ff99a206729d47d808f 0       readme.txt

# 查看tree对象的内容
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git cat-file -p 0d065f480e5ac0200f678ff99a206729d47d808f
readme.txt file v1

如上已确认,工作区和本地版本库中都是V4版本,而暂存区回退到V1版本。(这个示例比图片中多一个提交)

那我们查看一下,当前工作目录中文件的状态,还有历史提交信息。

# 1.查看当前工作目录中文件的状态
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   readme.txt

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.txt

# 2.再次查看历史提交版本
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git log --oneline
e72b30f (HEAD -> master) 第4次提交,新增内容:readme.txt file v4
529ad74 第3次提交,新增内容:readme.txt file v3
1b23cae 第2次提交,新增内容:readme.txt file v2
2612adf 第1次提交,创建readme.txt文件

L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git reflog
e72b30f (HEAD -> master) HEAD@{0}: reset: moving to e72b30f
529ad74 HEAD@{1}: reset: moving to HEAD^
e72b30f (HEAD -> master) HEAD@{2}: commit: 第4次提交,新增内容:readme.txt file v4
529ad74 HEAD@{3}: commit: 第3次提交,新增内容:readme.txt file v3
1b23cae HEAD@{4}: commit: 第2次提交,新增内容:readme.txt file v2
2612adf HEAD@{5}: commit (initial): 第1次提交,创建readme.txt文件
# 发现日志信息和最开始一样,没有变动。

我们可以看到,暂存区中有一个已修改状态的readme.txt文件,工作区中有一个未被追踪的readme.txt文件。

同是也还发现了一个现象,就是这样操作不会生成新的commit。不像之前使用git reset命令后,会自动生成一个commit提交。

看到这里我就大概明白了,git reset --mixed eb43bf -- readme.txt命令,它其实做了同样的事情:

  1. 因为--mixed后边加了路径(包括文件和目录),所以会跳过第1步,也就是HEAD指针不进行移动。
  2. 然后继续执行第2步,把暂存区中的readme.txt文件回退到V1版本。
  3. 然后工作区中的readme.txt文件,在使用--mixed参数进行回退的时候,内容不会变动。

所以工作区和暂存区中的readme.txt文件内容不一样,才会出现暂存区中有已修改状态的readme.txt文件,和工作区中有一个未被追踪的readme.txt文件。

这时如果我们直接执行git commit命令进行提交,暂存区中V1版本的readme.txt文件就会被提交到本地版本库中,会新生成一个commit提交,它就会记录一条“将该文件恢复到 v1 版本”的更改。

提示:在这种情况下,如果把工作区的readme.txt文件,先添加到暂存区中,然后在提交,当前版本库的历史提交信息,是不会有任何变化的。(你可以试试)

分析原因:

我之前一直以为只要有git commit提交操作,就应该有一个commit提交生成。我是这样想的,当我把工作区的readme.txt文件,添加到暂存区后。这个时候工作区,暂存区和本地版本库中readme.txt文件都是一样的,等于我没有做任何的修改。然后我直接提交新的commit,应该这个操作会被Git忽略把。Git也给你提示nothing to commit, working tree clean:没有可提交的内容,暂存区中的树对象没改变。

说明:还有一点同 git add 一样,就是 reset 命令也可以接受一个 --patch 选项,来一块一块地取消暂存的内容。 这样你就可以根据选择,来取消暂存或恢复内容了。

参考:https://git-scm.com/book/zh/v2/

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容