reset和checkout的重置作用
- HEAD当前检出记录的符号引用,就是指向正在其基础上进行工作的提交记录,总是指向当前分支上最近一次提交记录,通常情况下是指向分支名的。
HEAD
的内容可以通过cat .git/HEAD
查看, 如果HEAD
指向的是一个引用,还可以用git symbolic-ref HEAD
查看它的指向。 - reset移动
HEAD
指向,即修改引用(如master)的游标 - checkout改变
HEAD
的自身,即HEAD
的内容ref: refs/heads/master
,.git/HEAD
当前所处分支
当检出一个分支时,它会修改HEAD指向新的分支引用,将暂存区填充为该分支上的最后一次提交的快照, 然后将暂存区的内容复制到工作区
reset用法:
git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
git reset [-q] [<tree-ish>] [--] <pathspec>…
第一种用法会移动HEAD
分支的指向,然后更据选项参数(-q
参数保持安静,只报告错误)决定是否更新暂存区和工作区。
第二种用法,带路径,--
是为了避免路径和引用(提交ID)同名而冲突,这种用法不会改变HEAD
的指向,更不会改变工作区,而是从<tree-ish>
指定提交状态下的文件替换掉暂存区中的文件,即只会用某个指定提交的文件去更新暂存区。例如:git reset test.c
相当于取消git add test.c
命令添加到暂存区。
checkout的用法:
git checkout [<branch>]
git checkout [-q] [<commit>] [--] <paths>...
git checkout [-m] [[-b|--orphan] <new_branch>] [<start_point>]
第一种用法git checkout branch
虽然也会更改暂存区和工作区的内容,但相对比较安全,首先它在更改时会检查确保已经修改的文件被弄丢,然后checkout不会移动HEAD
分支的指向,只会修改HEAD
自身来指向另一个分支。
第二种用法,带路径,<commit>
是可选项,如果省略则相当于从暂存区(index)进行检出。这和上
reset命令大不相同:reset的默认值是HEAD
,而检出的默认值是暂存区。因此reset一般用于重置暂存区(除非使用–hard参数,否则不重置工作区),而检出命令主要是覆盖工作区(如果<commit>
不省略,也会替换暂存区中相应的文件)。这种用法不会改变HEAD
头指针,主要是用于指定版本的文件覆盖工作区中对应的文件。如果省略<commit>
,会拿暂存区的文件覆盖工作区的文件,否则用指定提交中的文件覆盖暂存区和工作区中对应的文件。
第三种用法主要是创建和切换到新的分支(<new_branch>
),新的分支从<start_point>
指定的提交开始创建。
下面的速查表列出了命令对树的影响。“HEAD” 一列中的 “REF” 表示该命令移动了 HEAD 指向的分支引用,而 “HEAD” 则表示只移动了 HEAD 自身。
HEAD | Index | Workdir | WD Safe? | |
---|---|---|---|---|
Commit Level | ||||
reset --soft [commit] | REF | NO | NO | YES |
reset [commit] | REF | YES | NO | YES |
reset --hard [commit] | REF | YES | YES | NO |
checkout <commit> | HEAD | YES | YES | YES |
File Level | ||||
reset [commit] <paths> | NO | YES | NO | YES |
checkout [commit] <paths> | NO | YES | YES | NO |
HEAD
文件通常是一个符号引用(symbolic reference),指向目前所在的分支。所谓符号引用,表示它是一个指向其他引用的指针。
当你在检出一个标签、提交或远程分支,让你的仓库变成 “分离 HEAD”状态时(DETACHED HEAD),
分离的HEAD就是让其指向了某个具体的提交记录而不是分支名,HEAD
文件可能会包含一个git对象的SHA-1值。