深入了解git的checkout命令
检出命令(git checkout)是Git最常用的命令之一,同时也是一个很危险的命令.
因为这条命令会重写工作区.检出命令的用法如下:
用法一: git checkout [-q] [<commit>] [--] <path>...
用法二: git checkout [<branch>]
用法三: git checkout [-m] [[-b|--orphan] <new_branch>] [<start_point>>]
第一种用法的<commit>是可选项,如果省略则相当于从暂存区(index)进行检出.
这和之前的重置命令大不相同:重置的默认值是HEAD,而检出的默认值是暂存区.
因此重置一般用于重置暂存区(除非使用--hard参数,否则不重置工作区)
而检出命令主要是覆盖工作区(如果<commit>不省略,也会替换暂存区中相应的文件).
第一种用法:
先来合个影:
在Git中,"留影"用的命令是叫做tag,更加专业的术语叫做"里程碑"(打tag,或者打标签)
"留影"的命令如下:
$ git tag -m "say bye to previous" old_practice
只需要知道里程碑也无非是一个引用.通过记录提交ID(或者创建Tag对象)来为当前版本库的状态进行"留影"
$ ls .git/refs/tags/old_practice
留影之后,可以执行git describe命令将最新提交显示为一个容易记忆的名字.
显示的时候会选取离该提交最近的里程碑作为"基础版本号",后面附加标识距离"基础版本"
的数字,以及该提交的SHA1哈希值的缩写.因为最新的提交上恰好被打了一个"里程碑".
所以直接显示"里程碑"的名称.这个技术会在后面的示例代码中经常用到.
删除文件:(这个时候工作区只有一个test1.txt文件是已经commit结束,又增加了新的东西,处于modify状态)
在这个暂存区和工作区都包含文件修改的情况下,使用删除命令更具有挑战性.
删除命令有很多种使用方法,有的方法很巧妙,而有的方法则需要更多的输入.
为了分别介绍不同的删除方法.还要使用之前使用过的保存进度的git stash 命令.
保存进度:
在恢复进度.注意不要使用git stash pop ,而是使用git stash apply,因为这个保存的进度要被多次用到.
本地删除不是真的删除.
$ls是看工作区中有哪些文件.
$rm test1.txt 命令执行之后,工作区中处于修改Modified状态的test1.txt文件被删除了.
但是执行$ git ls-files 之后还是可以看出有文件的.
从文件的状态来看,文件只是在本地进行了删除,尚未添加到暂存区(提交任务)中.
也就是说:直接在工作区删除,对暂存区和版本库没有任何影响.
从Git的状态中可以看出,本地删除如果要反应在暂存区中应该用git rm命令,对不向删除的文件执行
git checkout -- <file>,可以让文件在工作区中重现.
这个时候如果用checkout命令的话,刚才已经"被删除"的test1.txt就会恢复在工作区了.
不过这个文件是没有修改之前的状态.上面的图中我也已经$git status 了.
执行git rm命令删除文件
$ git rm test1.txt
这样删除的动作加入了暂存区,这时执行提交动作,就从真正意义上执行了文件删除.
$ git commit -m "delete files(using:git rm)"
不过不要担心,文件只是在版本库的最新提交中被删除了,在历史提交中尚在.可以通过下面的命令查看历史版本的文件列表.
$ git ls-files --with-tree=HEAD^
也可以查看在历史版本中尚在的删除文件的内容.
$git cat-file -p HEAD^:test1.txt
命令git add -u 快速标记删除
在前面执行git rm命令时,写下了所有要删除的文件名,很长.能不能简化些?
实际上git add就可以.即使用-u参数调用git add命令.含义是将本地有改动(包括修改和删除)的文件标记到暂存区.
为了重现刚才的场景,先使用重置命令抛弃最新的提交,再使用进度回复到之前的状态.
文件的整个过程操作:
上图中$git stash apply -q 恢复保存的进度(参数-q 使得命令进入安静模式)
执行完上面这个命令恢复到了在test1.txt的modified状态.
执行 git add -u 命令可以将(被版本库追踪的)本地文件的变更(修改,删除)全部记录到暂存区中.