asen's Blog

Happy coding

git reset 的用法

  git reset 的用法

  这两天开始学git了,老师给了一份资料让看看,总体看着还不太难,可是在学到git reset的时

候,却发现老师说的太过笼统和概括了,没法理解!在终端上怎么运行也看不出个所以然。从网

上找了些资料都是太简约了,没有反应出最直接的东西,不过这里我要特别说一下

《看日记学git》之二十五  http://roclinux.cn/?p=622     这篇文章还是不错的很是适合初学

者理解git reset的工作原理。但是我在操作的过程中,还是发现有些话说的不够明白,自己又

结合了Git 版本控制系統 (1)by ihower ihower.idv.tw/blog/archives/2591 

的文章中关于“git diff的进行比较的作用”。终于理解了git reset的用法。在说git reset 之前我感

觉有必要先弄清楚git diff的作用,在此分享!希望大家给予支持!

1. git diff 的用法和作用

2. git reset的用法和作用

 


1 git diff 有三个命令,git diff  ,git diff --cached,git diff HEAD.

这里我有比要 说明一下,cached 是有缓存的意思。HEAD 是工作树的最新的一次提交

$ git show HEAD^  # 查看HEAD 的父版本更新细节
$ git show HEAD^^ # 查看HEAD 的祖父版本更新细节
$ git show HEAD~4 # 查看HEAD 的祖父之祖父的版本更新细节

结合一个图会更容易理解一点:

这个图很清楚的说明了映像,和提交的步骤,git add 命令是首先映像到staging area 阶

段,但这时只是将工作树的改变先缓存在一个地方,真正的文件还没有改变。只有git commit

后工作树中的文件才改变。

git diff 比较的是前两个阶段即working directory(一下称1段) 和staging area(一下称2段).

git diff --cached 比较的是第二个阶段staging area 和 repository(一下称3段).

git diff HEAD 比较的是repository 和 working directory.

好这里git diff 就说到这。言归正传,请读者按下面的步骤操作,你很快就会对git reset有

深刻的认识了!


2.git reset

happyasen@asen-desktop:~
>$ mkdir git25
happyasen@asen-desktop:~
>$ cd git25
happyasen@asen-desktop:~/git25
>$ vi roc.c   /*按照下面的内容建立roc.c*/
happyasen@asen-desktop:~/git25
>$ cat -n roc.c /*查看roc.c的内容*/
     1    /*
     2     * ================================================         

    4     *       Filename:  roc.c
     5     *
     6     *    Description:  
     7     *
     8     *        Version:  1.0
     9     *        Created:  2009年08月22日 11时28分17秒 CST
    10     *       Revision:  none
    11     *       Compiler:  gcc
    12     *
    13     *         Author:   (),
    14     *        Company:  
    15     *
    16     * =============================================
    17     */
    18    
    19    #include <stdio.h>
    20    int
    21    main()
    22    {
    23            printf("He is a young man.\n");
    24            return 0;
    25    }
happyasen@asen-desktop:~/git25
>$ git init
Initialized empty Git repository in /home/happyasen/git25/.git/
happyasen@asen-desktop:~/git25
>$ git add .
happyasen@asen-desktop:~/git25
>$ git commit -m "1"
Created initial commit 98d8694: 1
 1 files changed, 25 insertions(+), 0 deletions(-)
 create mode 100644 roc.c
happyasen@asen-desktop:~/git25
>$ git log  /*利用git log 我们可以清楚的看到roc.c的变更历史*/
commit 98d86943e91a48a87c4d6c51f3b8273229bbfefe
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 11:30:52 2009 +0800

    1
happyasen@asen-desktop:~/git25
>$ vi roc.c  /*向roc.c 中加入内容,第一次修改*/
happyasen@asen-desktop:~/git25
>$ git diff   /*比较你会发现工作树中的内容还没有映像到2段阶段。所以2,3段

中实际上还是第一次提交的内容,所以git diff 和git diff HEAD有输出。

而git diff --cached没有输出*/
diff --git a/roc.c b/roc.c
index c9e2e4e..4fc1b3e 100644
--- a/roc.c
+++ b/roc.c
@@ -21,5 +21,6 @@ int
 main()
 {
         printf("He is a young man.\n");
+        printf("He is 24 years old.\n");
         return 0;
 }

happyasen@asen-desktop:~/git25
>$ git diff --cached
happyasen@asen-desktop:~/git25
>$ git diff HEAD
diff --git a/roc.c b/roc.c
index c9e2e4e..4fc1b3e 100644
--- a/roc.c
+++ b/roc.c
@@ -21,5 +21,6 @@ int
 main()
 {
         printf("He is a young man.\n");
+        printf("He is 24 years old.\n");
         return 0;
 }
happyasen@asen-desktop:~/git25
>$ git add ./*将1段的内容映像到2段,2段中的内容更新成了1段的内容。

这时候在用diff 就会发现 git diff已经没有输出了,而git diff --cached

和git diff HEAD 有输出*/
happyasen@asen-desktop:~/git25
>$ git diff
happyasen@asen-desktop:~/git25
>$ git diff --cached
diff --git a/roc.c b/roc.c
index c9e2e4e..4fc1b3e 100644
--- a/roc.c
+++ b/roc.c
@@ -21,5 +21,6 @@ int
 main()
 {
         printf("He is a young man.\n");
+        printf("He is 24 years old.\n");
         return 0;
 }
happyasen@asen-desktop:~/git25
>$ git diff HEAD
diff --git a/roc.c b/roc.c
index c9e2e4e..4fc1b3e 100644
--- a/roc.c
+++ b/roc.c
@@ -21,5 +21,6 @@ int
 main()
 {
         printf("He is a young man.\n");
+        printf("He is 24 years old.\n");
         return 0;
 }
happyasen@asen-desktop:~/git25
>$ git commit -m "2"/*提交! 这时 2段的内容提交到3段。

这时候在diff 我想你应该知道会出现什么样的结果了吧*/
Created commit 09161f5: 2
 1 files changed, 1 insertions(+), 0 deletions(-)
happyasen@asen-desktop:~/git25
>$ git diff
happyasen@asen-desktop:~/git25
>$ git diff --cached
happyasen@asen-desktop:~/git25
>$ git diff HEAD
/*为了加深理解我们在改变一次roc.c的内容,即进行第二次修改文件*/
happyasen@asen-desktop:~/git25
>$ vi roc.c /*第二次修改为如下cat -n roc.c内容*/
happyasen@asen-desktop:~/git25
>$ git log/*查看文件更改日志可以看到第三次修改还没有加入到git仓库中*/
commit 09161f59270d9e5ac828926fe1f23bd6941bf468
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 15:03:13 2009 +0800

    2

commit 98d86943e91a48a87c4d6c51f3b8273229bbfefe
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 11:30:52 2009 +0800

    1
happyasen@asen-desktop:~/git25
>$ cat -n roc.c
     1    /*
     2     * ===================================

     3     *
     4     *       Filename:  roc.c
     5     *
     6     *    Description:  
     7     *
     8     *        Version:  1.0
     9     *        Created:  2009年08月22日 11时28分17秒 CST
    10     *       Revision:  none
    11     *       Compiler:  gcc
    12     *
    13     *         Author:   (),
    14     *        Company:  
    15     *
    16     * ===================================

    17     */
    18    
    19    #include <stdio.h>
    20    int
    21    main()
    22    {
    23            printf("He is a young man.\n");
    24            printf("He is 24 years old.\n");
    25            printf("He is very handsome.\n");
    26            return 0;
    27    }
happyasen@asen-desktop:~/git25
>$ git diff/*再次用diff进行比较一下,加深diff的使用*/
diff --git a/roc.c b/roc.c
index 4fc1b3e..314a544 100644
--- a/roc.c
+++ b/roc.c
@@ -22,5 +22,6 @@ main()
 {
         printf("He is a young man.\n");
         printf("He is 24 years old.\n");
+        printf("He is very handsome.\n");
         return 0;
 }
happyasen@asen-desktop:~/git25
>$ git diff --cached
happyasen@asen-desktop:~/git25
>$ git diff HEAD
diff --git a/roc.c b/roc.c
index 4fc1b3e..314a544 100644
--- a/roc.c
+++ b/roc.c
@@ -22,5 +22,6 @@ main()
 {
         printf("He is a young man.\n");
         printf("He is 24 years old.\n");
+        printf("He is very handsome.\n");
         return 0;
 }
happyasen@asen-desktop:~/git25
>$ git add roc.c
happyasen@asen-desktop:~/git25
>$ git log /*从这可以看出,没有提交是不生成变更日志的*/
commit 09161f59270d9e5ac828926fe1f23bd6941bf468
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 15:03:13 2009 +0800

    2

commit 98d86943e91a48a87c4d6c51f3b8273229bbfefe
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 11:30:52 2009 +0800

    1

happyasen@asen-desktop:~/git25
>$ git diff
happyasen@asen-desktop:~/git25
>$ git diff --cached
diff --git a/roc.c b/roc.c
index 4fc1b3e..314a544 100644
--- a/roc.c
+++ b/roc.c
@@ -22,5 +22,6 @@ main()
 {
         printf("He is a young man.\n");
         printf("He is 24 years old.\n");
+        printf("He is very handsome.\n");
         return 0;
 }
happyasen@asen-desktop:~/git25
>$ git diff HEAD
diff --git a/roc.c b/roc.c
index 4fc1b3e..314a544 100644
--- a/roc.c
+++ b/roc.c
@@ -22,5 +22,6 @@ main()
 {
         printf("He is a young man.\n");
         printf("He is 24 years old.\n");
+        printf("He is very handsome.\n");
         return 0;
 }

happyasen@asen-desktop:~/git25
>$ git add roc.c
happyasen@asen-desktop:~/git25
>$ git commit -m "3"
Created commit 49e90bf: 3
 1 files changed, 1 insertions(+), 0 deletions(-)
happyasen@asen-desktop:~/git25
>$ git log /*提交后变更日志有了第二次修改*/
commit 49e90bf24881a4c5fe18e903daca0d52ef361623
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 15:24:17 2009 +0800

    3

commit 09161f59270d9e5ac828926fe1f23bd6941bf468
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 15:03:13 2009 +0800

    2

commit 98d86943e91a48a87c4d6c51f3b8273229bbfefe
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 11:30:52 2009 +0800

    1

/*下面就让我们进入reset 阶段,看一看reset的功能*/

git reset 有三个常用命令:

   git-reset 命令有三个选项:--mixed 、 --soft 和 --hard 。我们在日常使用

中仅使用前两个选项; 第三个选项由于杀伤力太大, 容易损坏项目仓库,需谨慎使
用。
   --mixed 是 git-reset 的默认选项,它的作用是重置索引内容, 将其定位到指定
的项目版本, 而不改变你的工作树中的所有内容, 只是提示你有哪些文件还未更
新。
   --soft 选项既不触动索引的位置, 也不改变工作树中的任何内容,但是会要
求它们处于一个良好的次序之内。该选项会保留你在工作树中的所有更新并使之
处于待提交状态。

看到上面给出的标准定义。我想你肯定是一头雾水了吧?!

没关系下面跟我一块去探探到底这是什么东东?

happyasen@asen-desktop:~/git25
>$ git reset HEAD^/*利用默认选项回到第二次修改的地方,然后看看

发生了什么*/
roc.c: locally modified
happyasen@asen-desktop:~/git25
>$ git diff
diff --git a/roc.c b/roc.c
index 4fc1b3e..314a544 100644
--- a/roc.c
+++ b/roc.c
@@ -22,5 +22,6 @@ main()
 {
         printf("He is a young man.\n");
         printf("He is 24 years old.\n");
+        printf("He is very handsome.\n");
         return 0;
 }
happyasen@asen-desktop:~/git25
>$ git diff --cached
happyasen@asen-desktop:~/git25
>$ git diff HEAD
diff --git a/roc.c b/roc.c
index 4fc1b3e..314a544 100644
--- a/roc.c
+++ b/roc.c
@@ -22,5 +22,6 @@ main()
 {
         printf("He is a young man.\n");
         printf("He is 24 years old.\n");
+        printf("He is very handsome.\n");
         return 0;
 }
happyasen@asen-desktop:~/git25
>$ git log
commit 09161f59270d9e5ac828926fe1f23bd6941bf468
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 15:03:13 2009 +0800

    2

commit 98d86943e91a48a87c4d6c51f3b8273229bbfefe
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 11:30:52 2009 +0800

    1
happyasen@asen-desktop:~/git25
>$ cat -n roc.c
     1    /*
     2     * ============================
     3     *
     4     *       Filename:  roc.c
     5     *
     6     *    Description:  
     7     *
     8     *        Version:  1.0
     9     *        Created:  2009年08月22日 11时28分17秒 CST
    10     *       Revision:  none
    11     *       Compiler:  gcc
    12     *
    13     *         Author:   (),
    14     *        Company:  
    15     *
    16     * ============================
    17     */
    18    
    19    #include <stdio.h>
    20    int
    21    main()
    22    {
    23            printf("He is a young man.\n");
    24            printf("He is 24 years old.\n");
    25            printf("He is very handsome.\n");
    26            return 0;
    27    }

/*看到了吗,发生了什么?默认选项回到的是父版修改后但还没有映像的状态,

也就是相当于,第二次刚刚修改好,但还没有add 到2段。默认选项就是实现的 这个

功能,明白了吧?*/
happyasen@asen-desktop:~/git25
>$ git commit -a -m "3"/*让我们把第二次修改提交了,回到没有

git reset 的时候*/
Created commit 8554dd1: 3
 1 files changed, 1 insertions(+), 0 deletions(-)
happyasen@asen-desktop:~/git25
>$ git log
commit 8554dd1247166e67a3603987832efbba4220dd99
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 15:29:08 2009 +0800

    3

commit 09161f59270d9e5ac828926fe1f23bd6941bf468
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 15:03:13 2009 +0800

    2

commit 98d86943e91a48a87c4d6c51f3b8273229bbfefe
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 11:30:52 2009 +0800

    1

/*看看第二个选项soft的作用*/
happyasen@asen-desktop:~/git25
>$ git reset --soft HEAD^
happyasen@asen-desktop:~/git25
>$ git log
commit 09161f59270d9e5ac828926fe1f23bd6941bf468
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 15:03:13 2009 +0800

    2

commit 98d86943e91a48a87c4d6c51f3b8273229bbfefe
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 11:30:52 2009 +0800

    1
happyasen@asen-desktop:~/git25
>$ git diff
happyasen@asen-desktop:~/git25
>$ git diff --cached
diff --git a/roc.c b/roc.c
index 4fc1b3e..314a544 100644
--- a/roc.c
+++ b/roc.c
@@ -22,5 +22,6 @@ main()
 {
         printf("He is a young man.\n");
         printf("He is 24 years old.\n");
+        printf("He is very handsome.\n");
         return 0;
 }
happyasen@asen-desktop:~/git25
>$ git diff HEAD
diff --git a/roc.c b/roc.c
index 4fc1b3e..314a544 100644
--- a/roc.c
+++ b/roc.c
@@ -22,5 +22,6 @@ main()
 {
         printf("He is a young man.\n");
         printf("He is 24 years old.\n");
+        printf("He is very handsome.\n");
         return 0;
 }
/*看到了把,soft是回到了第二次已经修改了,

也add 了,但是没有提交的那步*/


happyasen@asen-desktop:~/git25
>$ git commit -m "3"/*再次还原*/
Created commit 34b07aa: 3
 1 files changed, 1 insertions(+), 0 deletions(-)
happyasen@asen-desktop:~/git25
>$ git log
commit 34b07aa80945b8b8b05f7bdc7617cf5923c01f41
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 15:32:04 2009 +0800

    3

commit 09161f59270d9e5ac828926fe1f23bd6941bf468
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 15:03:13 2009 +0800

    2

commit 98d86943e91a48a87c4d6c51f3b8273229bbfefe
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 11:30:52 2009 +0800

    1

/*来看看hard 的作用*/

happyasen@asen-desktop:~/git25
>$ git reset --hard HEAD^
HEAD is now at 09161f5 2
happyasen@asen-desktop:~/git25
>$ git log
commit 09161f59270d9e5ac828926fe1f23bd6941bf468
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 15:03:13 2009 +0800

    2

commit 98d86943e91a48a87c4d6c51f3b8273229bbfefe
Author: happyasen <happyasen@asen-desktop.(none)>
Date:   Sat Aug 22 11:30:52 2009 +0800

    1
happyasen@asen-desktop:~/git25
>$ git diff
happyasen@asen-desktop:~/git25
>$ git cached
git: 'cached' is not a git-command. See 'git --help'.
happyasen@asen-desktop:~/git25
>$ git diff --cached
happyasen@asen-desktop:~/git25
>$ git diff HEAD
/*看到了吧。直接把第二次修改完全删除了*/

看了这些我想你对git reset 应该有透彻的认识了吧!