Git入门与练习(二)

上回我们说到git log可以查看当前版本之前的所有提交信息,包括message和commit的id。版本回退还没有说。上次我们到了“append GPL”这个版本,这时我们觉得这个版本没有上个版本好,想回到上个版本,这时就用到了

$ git reset --hard HEAD^
HEAD is now at 1065292 insert a word control    细心的你会发现1065292就是第二个版本的commit id,而insert a word control是你在提交第二个版本时的-m参数的注释。这里reset表示版本回退,--hard我们以后再说,在Git中HEAD是一个指向当前版本的指针,HEAD^表示将指针倒退一位,你也许猜到了可以HEAD^^甚至HEAD^^^^^^^^,但是当你想回退100个版本可以用HEAD~100。

OK,这时我们再来log一下
$ git log
commit 10652926b09e0f9191db72cd5bad5cb84bf23dc3 (HEAD -> master)
Author: zaw <872852458@qq.com>
Date:   Wed Feb 7 23:05:49 2018 +0800

    insert a word control

commit 78d680c4b62d2e7d190c5ea820308e7297844410
Author: zaw <872852458@qq.com>
Date:   Wed Feb 7 22:52:38 2018 +0800

    create a file readme.txt:
你发现了什么?you are right!当你回退到某一个版本时你使用log查看提交历史,显示的提交历史只有当前版本(你回退到的那一个版本)之前的所有提交,之后的他就不知道了。

这时问题又来了,纠结的你又觉得第三个版本好,怎么回去啊?在Git中查找版本都是通过commit id的,于是你在命令行向上找,找啊找,找到了第三个版本的commit id:
commit 0c9d4ec59e2975a28d7178abf9862afa542d56d8 (HEAD -> master)
Author: zaw <872852458@qq.com>
Date:   Wed Feb 7 23:16:37 2018 +0800

    append GPL
这时你再使用  
$ git reset --hard 0c9d4ec
HEAD is now at 0c9d4ec append GPL   提示你HEAD指针已经指向了这个版本并显示了他的commit -m       
你不相信?那你再来git log一下
commit 0c9d4ec59e2975a28d7178abf9862afa542d56d8 (HEAD -> master)
Author: zaw <872852458@qq.com>
Date:   Wed Feb 7 23:16:37 2018 +0800

    append GPL

commit 10652926b09e0f9191db72cd5bad5cb84bf23dc3
Author: zaw <872852458@qq.com>
Date:   Wed Feb 7 23:05:49 2018 +0800

    insert a word control

commit 78d680c4b62d2e7d190c5ea820308e7297844410
Author: zaw <872852458@qq.com>
Date:   Wed Feb 7 22:52:38 2018 +0800

    create a file readme.txt:
果真回来了,是不是很神奇?

你会发现git reset不仅能回退版本,还能向前追溯版本。他在master分支(默认主分支,分支即版本链)上就像一个时光机,使用(--hard 参数)你可以根据HEAD~n或commit id会到指定的版本。

工作区和暂存区

上面谈到了工作区、暂存区、版本库、master分支、HEAD指针等,下面对这些名词进行详解。

  • 工作区(Repository)就是你磁盘上的目录,你使用git init命令纳入Git管理的目录,比如我们之前创建的learngit。
  • 在此目录下有一个隐藏目录.git,这不算我们的工作目录,这是使用git init时自动创建的对应这个工作目录的版本库,用来保存我们提交的不同版本。
  • 版本库又分为暂存区和分支,分支就是一条版本链,在初始化版本库时Git会默认帮我们建一条分支即master。后面会讲到,为了稳步开发,一般不直接在master分支上操作,而是在新建分支上操作成功后将其融合到master分支上。
  • 暂存区就是用来检测工作区文件是否有改动,有改动后是否git add。无论是文件是新建还是改动,要同步版本库就要先add到暂存区后commit才会一起更新到版本库中。否则暂存区没有add来的文件,即使你做了改动,commit会提示你文件没有任何改动。
  • HEAD指针,他总是指向分支中我们当前处于的版本。
光说不练假把式,下面我们来实践一下
在learngit中新建文件LICENSE.txt,随便写什么内容,然后git status一下
$ git status
On branch master    
Untracked files:    (没有踪迹的文件,LICENSE是新建的,并且从未被添加到版本库中)
  (use "git add <file>..." to include in what will be committed)

        LICENSE.txt

nothing added to commit but untracked files present (use "git add" to track)    (暂存区中没有add来的文件)
我们来add一下
zaw@DESKTOP-KSRUM81 MINGW64 /e/Repositories/learngit (master)
$ git add LICENSE.txt
提交之前status一下
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage) (提示我们可以使用git reset HEAD LICENSE.txt撤销add到暂存区这个操作,暗示我们LICENSE.txt已经被add到了stage)

        new file:   LICENSE.txt
然后提交
zaw@DESKTOP-KSRUM81 MINGW64 /e/Repositories/learngit (master)
$ git commit -m "create a file LICENSE"
[master 485949b] create a file LICENSE
 1 file changed, 1 insertion(+)
 create mode 100644 LICENSE.txt

再来status一下
$ git status
On branch master
nothing to commit, working tree clean
由于之前add到stage的被commit了,所以提示stage是空的

我们来尝试一下另外一种情况:
改变LICENSE中的内容为twice add
然后add一下
再将内容改为once add then commit然后commit一下
这时status一下,你会发现:
$ git status
On branch master
Changes not staged for commit:  (提示,有修改的文件没有被add到stage中)
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   LICENSE.txt

no changes added to commit (use "git add" and/or "git commit -a")
你可能会问为什么会这样呢?我明明add了,也commit了呀!
我们来细分一下上述操作步骤:
1、修改-->2、add-->3、修改-->4、commit
知道暂存区(stage)的工作原理不难理解,你得add是将第一次修改后的内容add到了stage,之后的提交不管你工作区的变化而是提交stage中的内容,因此第一次的修改成功更新到了版本库中,而第二次修改只是让工作区中的内容发生了变化而并没有add到stage中,因此会有上述提示。
解决方案是,要么一次性修改完后add并commit,要么每修改一次就add到stage中最后一起commmit。后者把你每次的修改合并然后一起提交了。

撤销修改

人非圣贤孰能无过,一次修改时,你将你的抱怨写入了文件中:
Git is distributed version control system.
Git is a free software distributed under the GPL.
My stupid boss prefers SVN.
哇,你最后一行的不理智之举要是让boss看见了,说不定奖金就泡汤了。
自然,在add之前,理智的你可以手动即时将文件内容的最后一行删除掉。
当我们用命令行来status看一下
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "**git checkout -- <file>**..." to discard changes in working directory)

        modified:   readme.txt
回车键后的提示告诉我们可以使用**git checkout -- <file>**撤销工作区的修改。(其实就是工作区中的文件恢复到版本库中最新的版本,也叫从版本库中取出最新版本的文件来覆盖工作区的文件)
我们来试一下
$ git checkout -- readme.txt   
没有反应?OK,说明撤销成功,打开工作区中的readme,你会发现最后一行的stupid boss神奇的消失了。
命令中的--不能掉,否则就变成切换分支的命令了(稍后会谈到)。

OK,今天你的心情很不好,去他的boss,我爱咋地咋地。我就将“stupid boss”add到了stage中。这时还能反悔吗?
当然可以,我们还是status一下
$ git status
On branch master
Changes to be committed:
  (use "**git reset HEAD <file>**..." to unstage)

        modified:   readme.txt
readme只是被add到了stage中还没有被提交,提示信息告诉我们可以通过**git reset HEAD <file>**来清空stage中的文件
于是:
$ git reset HEAD readme.txt
Unstaged changes after reset:
M       readme.txt

我们发现会到之前的状态了,checkout -- file 一下就完事了
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   readme.txt

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


哇,有一哥们儿上了头,就是要让boss看到stupid,他不但add到了stage中还commit了一下
但冷静后又后悔了,谁喜欢跟奖金过不去啊,咱还能吃吃后悔药吗?
$ git status
On branch master
nothing to commit, working tree clean
git status也不管用了!怎么办啊?

机智如你,咱们之前不是学过版本回退吗?查看一下版本:
$ git log
commit a5093325ccb9ac7a603affdb93fddf7f46193fbf (HEAD -> master)
Author: zaw <872852458@qq.com>
Date:   Thu Feb 8 12:17:50 2018 +0800

    stupid boss

commit 3d8aa111933a8c871f46f2c29e700bfb3204397b
Author: zaw <872852458@qq.com>
Date:   Thu Feb 8 11:59:26 2018 +0800

    test stage

commit c768747927d6073e48c53c453262d9bac873ff55
Author: zaw <872852458@qq.com>
Date:   Thu Feb 8 11:43:36 2018 +0800

    test add

commit 6055d92946436ab9daf6fd0507ed855294252064
Author: zaw <872852458@qq.com>
Date:   Thu Feb 8 11:09:42 2018 +0800
咱们回退到一个版本不就完事了吗:
先按Q然后回车,终止git log命令,然后回退:
$ git reset --hard HEAD^
HEAD is now at 3d8aa11 test stage

$ git log
commit 3d8aa111933a8c871f46f2c29e700bfb3204397b (HEAD -> master)
Author: zaw <872852458@qq.com>
Date:   Thu Feb 8 11:59:26 2018 +0800

    test stage

commit c768747927d6073e48c53c453262d9bac873ff55
Author: zaw <872852458@qq.com>
Date:   Thu Feb 8 11:43:36 2018 +0800

    test add
问题终于解决了?这一招的前提是你没有将本地版本库推送到远程,否则,呵呵,你只能祈祷你的boss心胸宽广了!!!
后续笔记请关注后续更博。。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值