操作的回撤

本文演示了下列命令的常见使用方式:

git clean
git checkout
git reset

1. git clean

清除工作区所有未纳入版本管理的目录、文件。
git clean -f:强制清除工作区根目录下未纳入版本管理的文件。
git clean -d -f:强制清除未纳入版本管理的目录和文件,会从根目录递归所有子目录。

2. git checkout

git checkout <file>:撤销工作区指定文件的修改。用该文件暂存区的快照替换(如果该文件是untracked的,此命令不会处理)。
git checkout HEAD <file>:撤销指定文件在工作区和暂存区的所有修改,用版本库最近一次提交的版本来替换。

以gitsample的README.md文件为例。当前此文件的内容:

# gitsample

This line is the first time modified.

This line is the second time modified.

我们在文件中新加入一行文字,内容变成:

# gitsample

This line is the first time modified.

This line is the second time modified.
demo for checkout file.

此时在Git bash命令行中使用git diff比较下工作区和暂存区文件的差异:

$ git diff
diff --git a/README.md b/README.md
index 8d42e6b..cde90e6 100644
--- a/README.md
+++ b/README.md
@@ -2,4 +2,6 @@

 This line is the first time modified.

-This line is the second time modified.
\ No newline at end of file
+This line is the second time modified.
+
+demo for checkout.
\ No newline at end of file

接下来撤销工作区的修改:

$ git checkout README.md

再来查看差异:

$ git diff

工作区和暂存区没有差异了,README.md文件也变回最初的内容,刚才对工作区README.md文件的操作成功的被撤回了。

3. git reset

git reset HEAD [--] <paths>...:撤销指定路径在暂存区的尚未提交到版本库的内容。如果指定的路径从未提交到版本库,那么就直接将该路径从暂存区撤销;否则会用该路径在版本库中最近一次的提交来覆盖该路径的暂存区。
git reset --soft [<commit>]:撤销版本库到指定的commit id。可以用HEAD来代替commit id:HEAD^代表回撤最近一次的提交(和HEAD~1等效),HEAD^^表示回撤最近两次(和HEAD~2等效),以此类推;
git reset --mixed [<commit>]:撤销版本库提交和暂存区到指定的commit id。--mixed是默认参数,git reset --mixed HEAD^git reset HEAD^等效;
git reset --hard [<commit>]:撤销版本库、暂存区和工作区到指定的commit id。注意:此命令会直接撤销工作区的修改,这个操作是不可逆的!使用之前最好用git status来比较下确认工作区的修改可以放弃。

我们先在gitsample仓库中准备一下数据:
在文件夹内新建一个demo_reset.txt文件;
在文件内增加一行“Rev. 1”保存、在Git bash中运行git add .git commit -m "demo reset Rev. 1"将文件提交到版本库;
在文件内增加一行“Rev. 2”保存、git add .git commit -m "demo reset Rev. 2"将文件提交到版本库;
在文件内增加一行“Rev. 3”保存、git add .git commit -m "demo reset Rev. 3"将文件提交到版本库。

然后再文件内增加一行文字“Rev. 4”、然后git add .添加到暂存区。此时使用git diff demo_reset.txt查看状态:

$ git diff demo_reset.txt

从diff信息可以看到工作区的文件和暂存区的比较起来没有不同。此时回撤暂存区的操作:

$ git reset HEAD demo_reset.txt

然后再执行git diff查看:

$ git diff demo_reset.txt
diff --git a/demo_reset.txt b/demo_reset.txt
index 9820ed9..22aeec4 100644
--- a/demo_reset.txt
+++ b/demo_reset.txt
@@ -1,3 +1,4 @@
 Rev. 1
 Rev. 2
-Rev. 3
\ No newline at end of file
+Rev. 3
+Rev. 4
\ No newline at end of file

从diff的结果来看暂存区的内容已经回撤了,和工作区的文件已经不一样了。

接下来通过练习看下下git reset --hard [<commit>]的效果:

$ git reset --hard HEAD^
HEAD is now at 97bd7c9 demo reset Rev. 2

命令的返回信息提示版本库已经回撤到“demo reset Rev. 2”这一次的提交了,看下git status的结果:

$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

工作区和暂存区、暂存区和版本库都是一致的。说明暂存区和工作区的操作也都回撤了。用记事本打开文件会发现内容也只有Rev. 1和Rev. 2两行了。

接下来在Git bash中运行$ git reset --soft HEAD^,然后用git status看下效果:

$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   demo_reset.txt

可以看到,暂存区的demo_reset.txt有待提交的内容了。此时暂存区和工作区的文件内容都有Rev.1和Rev.2,而版本库已经回撤到Rev. 1这个版本了。如果现在又想将版本库回到最初的提交(或者过程中的某次提交),应该怎么办呢?还是使用reset命令,只要直到目的版本的commit id就能够返回。可以通过git log --reflog -3(只返回最近3次的提交操作)查看commit id:

$ git log --reflog -3 --pretty=oneline
df531846649c39baa68784ee40c907dd58e5c7da demo reset Rev. 3
97bd7c98ec0c0c8944dbd22c0711770564a7a762 demo reset Rev. 2
02e093b6513651c0e6e41d0710280a14e30b1d7c (HEAD -> master) demo reset Rev. 1

可以看到Rev. 3版本的commit id是df531846649c39baa68784ee40c907dd58e5c7da。现在将版本库的提交返回到这里:

$ git reset --hard df5318
HEAD is now at df53184 demo reset Rev. 3

从返回的结果可以看到,版本库的最近一次提交已经返回到Rev. 3了。

4. git commit --amend

有时候我们提交完了才发现有几个文件应该一起提交但是忘记添加,或者有的文件不应该提交,又或者提交的信息写的有问题。此时想修正这个问题,不想将原本应该在一起提交的变成两次提交,可以使用git commit -amend命令。

先要将需要一起提交的文件加入到暂存区,将不应该提交的文件撤回到原先的状态。然后在Git bash中运行命令:

git commit --amend

命令运行后会启动文本编辑器,提示修改commit message:

demo reset Rev. 3

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Mon Aug 19 00:04:47 2019 +0800
#
# On branch master
# Your branch is ahead of 'origin/master' by 3 commits.
#   (use "git push" to publish your local commits)
#
# Changes to be committed:
#   modified:   demo_reset.txt
#

将原来的message”demo reset Rev. 3“修改为“demo reset Rev. 3 --amend”。然后退出文本编辑器。

$ git commit --amend
hint: Waiting for your editor to close the file...
[main 2019-08-18T16:40:46.426Z] update#setState idle
[master ca497af] demo reset Rev. 3 --amend
 Date: Mon Aug 19 00:04:47 2019 +0800
 1 file changed, 2 insertions(+), 1 deletion(-)

从命令行返回结果可以看到,提交已经覆盖。我们再用git log --reflog验证下:

$ git log --reflog -3 --pretty=oneline
ca497afbba7b6eaefea0d96827875ddae4cb0791 (HEAD -> master) demo reset Rev. 3 --amend
df531846649c39baa68784ee40c907dd58e5c7da demo reset Rev. 3
97bd7c98ec0c0c8944dbd22c0711770564a7a762 demo reset Rev. 2

对比下之前的log:

$ git log --reflog -3 --pretty=oneline
df531846649c39baa68784ee40c907dd58e5c7da demo reset Rev. 3
97bd7c98ec0c0c8944dbd22c0711770564a7a762 demo reset Rev. 2
02e093b6513651c0e6e41d0710280a14e30b1d7c (HEAD -> master) demo reset Rev. 1

可以明显的看到,git commit --amend命令运行后,并没有新增一条提交操作,而是覆盖了最近一次的提交:commit id和message都被替换了。

需要注意的是git commit --amend命令会改变最近一次提交的commit id,所以当最近一次的提价已经推送到远程仓库之后,要特别谨慎的使用这个命令,否则容易引起同其它开发人员的版本冲突。

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