Git版本控制(2)

来源:互联网 发布:时间安排手机软件 知乎 编辑:程序博客网 时间:2024/05/18 18:01

版本回退
现在,我们最次修改readme的文件,并再次提交文件:

$ git add readme.txt$ git commit -m "append GPL"[master 3628164] append GPL 1 file changed, 1 insertion(+), 1 deletion(-)

有些时候,在打Boss之前,你会手动存盘,以便万一打Boss失败了,可以从最近的地方重新开始。Git也是一样,每当你觉得文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit恢复,然后继续工作,而不是把几个月的工作成果全部丢失。

git log命令显示从最近到最远的提交日志,我们可以看到3次提交,最近的一次是append GPL,上一次是add distributed,最早的一次是wrote a readme file。
如果嫌输出信息太多,看得眼花缭乱的,可以试试加上–pretty=oneline参数:

$ git log --pretty=oneline3628164fb26d48395383f8f31179f24e0882e1e0 append GPLea34578d5496d7dd233c827ed32a8cd576c5ee85 add distributedcb926e7ea50ad11b8f9e909c05226233bf755030 wrote a readme file

需要友情提示的是,你看到的一大串类似3628164…882e1e0的是commit id(版本号)。
在Git中,用HEAD表示当前版本,也就是最新的提交3628164…882e1e0,上一个版本就是HEAD^,上上一个版本就是HEAD^^,往上的地一百个版本可以表示为HEAD~100

如果我们要把当前版本“append GPL”回退到上一个版本“add distributed”,就可以使用git reset命令:

$ git reset --hard HEAD^HEAD is now at ea34578 add distributed

如果我们想回到未来,如果命令窗口还没有关掉,我们可以找到 append GPL的commit id,乘坐时光机回到未来,在下面的指令中,版本号不需要写全,写前几位就可以了:

$ git reset --hard 3628164HEAD is now at 3628164 append GPL

Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD从指向append GPL:

这里写图片描述

这里写图片描述
在Git中,总是有后悔药可以吃的。当你用$ git reset –hard HEAD^回退到add distributed版本时,再想恢复到append GPL,就必须找到append GPL的commit id。Git提供了一个命令git reflog用来记录你的每一次命令:

$ git reflogea34578 HEAD@{0}: reset: moving to HEAD^3628164 HEAD@{1}: commit: append GPLea34578 HEAD@{2}: commit: add distributedcb926e7 HEAD@{3}: commit (initial): wrote a readme file

工作区和暂存区
接下来的环节,我们要看看git版本控制系统的工作区和暂存区:
工作区(Working Directory):就是你在电脑里能看到的目录,比如我的learngit文件夹就是一个工作区。
版本库(Repository):*工作区*有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区(我们执行添加(add)指令之后,就把文件添加修改到暂存区),还有Git为我们自动创建的第一个分支master(就是把暂存区的所有内容提交到当前分支),以及指向master的一个指针叫HEAD,看图:

这里写图片描述

从工作区add文件到暂存区需要逐个文件添加,如果从暂存区commit到分支上则只需提交一次。

管理修改
假如说你修改了两次文件,把第一次修改的文件add到暂存区,而第二次的没有add,然后我们commit到master里面。理解了工作区和版本库的知识后,这个管理的修改就特别容易理解。
提交后,用git diff HEAD – readme.txt命令可以查看工作区和版本库里面最新版本的区别:

$ git diff HEAD -- readme.txt diff --git a/readme.txt b/readme.txtindex 76d770f..a9c5755 100644--- a/readme.txt+++ b/readme.txt@@ -1,4 +1,4 @@ Git is a distributed version control system. Git is free software distributed under the GPL. Git has a mutable index called stage.-Git tracks changes.           /*版本库*/+Git tracks changes of files.  /*工作区*/ 

撤销修改
你在readme.txt中添加了一行:My stupid boss still prefers SVN.这一个可能会令你的boss很生气的句子。首先,如果你及时发现,你可以手动删除这一行。其次,如果我们查看git 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#no changes added to commit (use "git add" and/or "git commit -a")

我们会发现,git checkout – file可以丢弃工作区的修改,把readme.txt文件在工作区的修改全部撤销。
1:如果你还没有把文件add到暂存区,这个撤销指令会把文件恢复到很版本库里面的一样。
2:如果你已经把文件add到暂存区,然后再修改文件,这个撤销指令会会把文件恢复到添加到暂存区后的状态。

用命令git reset HEAD file可以把暂存区的修改撤销掉(unstage),重新放回工作区:

$ git reset HEAD readme.txtUnstaged changes after reset:M       readme.txt

删除文件
我们可以直接用rm指令把工作区的文件删除掉:

$ rm test.txt

Git知道你删除了文件,工作区和版本库不一致了,git status命令会立刻告诉你哪些文件被删除了:

$ git status# On branch master# Changes not staged for commit:#   (use "git add/rm <file>..." to update what will be committed)#   (use "git checkout -- <file>..." to discard changes in working directory)##       deleted:    test.txt#no changes added to commit (use "git add" and/or "git commit -a")

现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit:

$ git rm test.txtrm 'test.txt'$ git commit -m "remove test.txt"[master d17efd8] remove test.txt 1 file changed, 1 deletion(-) delete mode 100644 test.txt

另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:

$ git checkout -- test.txt
0 0