git重置
refs/heads/master 是一个游标,当有新的提交发生时,master分支会指向新的commit,使用git reset
将master(游标)指向任意一个commit id
git reset --hard HEAD^ # --hard参数会破坏工作区未提交的改动。
git重置到任意一次提交
(1)通过git log --graph --oneline
来查看所有提交的ID
(2)git reset --hard a810291
执行命令将git重置到这一次提交
(3)重置后发现工作区文件也变成了这次提交的状态
注意
使用git reset
命令会彻底的丢弃重置点之后的所有提交。
只能通过commit ID来恢复这些提交
通过reflog挽回错误的重置
带有工作区的版本库都提供分支日志功能。
用以下命令查看该参数
git config core.logallrefupdates #执行后会显示true
用tail命令查看master分支日志
tail 5 .git/logs/refs/heads/master
会发现logs下的这个master文件记录了master分支的变迁,最新的改变会追加在这个文件的末尾,通过git reset –hard恢复重置以后,通过git log --oneline
来查看提交历史,会发现通过reset丢失的commit历史也回来了。
通过git reflog的子命令show也可以查看logs中的master文件
git reflog show master
,git reflog会给每个commit id提供一个好记得名称,格式为<ref>@<number>
,可以用git reset到这一名称直接重置到这一个commit。
深入理解git reset
git reset有两种形式
1.git reset [-q] [<commit>] [--] <paths>
这一种commit不会改变master指向,也不会改变工作区,而是用指定commit的文件paths来替换暂存区的文件
2.git reset [--soft|--mixed|--hard|--merge|--keep] [-q] [<commit>]
这一种用法会重置引用,根据参数不同,可以对暂存区或工作区进行重置。
使用git reset --hard <commit>
1.改变master指向。将完整的commit id赋予master游标
2.改变暂存区。master游标用该commit id指向的内容改变暂存区
3.改变工作区。用objects中的文件覆盖工作区文件。操作后,工作区与暂存区与HEAD指向的目录树相同。
使用git reset --soft <commit>
执行--hard
参数的第一步,而不改变暂存区和工作区
使用mixed(默认)
执行--hard
参数的1、2步,而不改变工作区。
git reset示例
git reset
:相当于git reset --mixed
或git reset --mixed HEAD
,用HEAD指向的目录重置暂存区。
git reset --soft HEAD^
:不改变工作区与暂存区,maser的引用回滚一次。
git commit --amend
与git reset --soft
此前用 git commit --amend
修改过用户名和email,相当于执行了如下命令
git reset --soft HEAD^
git commit -e -F .git/COMMIT_EDITING
git checkout
术语:detatched HEAD(分离头指针)
原本指向.git/refs/head/master的.git/HEAD文件内容变成了一个具体的commit,此时可以
执行git checkout HEAD^
此时,git会进入分离头指针状态,在此之后的提交不会并入master分支。除非执行git checkout master.
在执行git checkout master后,分离头指针模式下的提交和工作区都会变为master分区的内容。可以通过git merge命令合并master和HEAD
git merge
执行git merge的具体操作如下
(1)执行git branch -v ,查看输出,确认处于master分支。
(2)执行合并操作,将“分离头指针”状态下的提交合并到当前分支
git merge ac818291c
此时工作区会发生改变。
(3)查看日志git log --graph --pretty=oneline
会发现日志中间出现开发分支,并在最终进行了合并。最新提交将有两个父提交