github 进阶说明
前言
我们可以什么都不管,照搬命令来完成我们大部分git工作,但是如果想要进一步,就要深入理解git的实现原理,和底层机制。
三个目录树
- HEAD 仓库指针
- index file 暂存区
- Working Directory 工作目录
默认情况,头指针会指向当前分支,当前分支指向当前目录树。所谓目录树简而言之就是一个commit对象,保存了某个提交时刻的工作目录内容的镜像。而工作目录就是当前文件内容。
状态一:初始情况是三者相同。
状态二:当你编辑了工作目录下的内容,工作目录和暂存区就不同。git status
会提示你git add
相关文件。
状态三:git add
之后,暂存区和仓库又不相同了,git status
提示你git commit
,当你git commit
之后,回到状态一,仓库就增加了一个新的版本,当前分支指针移动到新版本之上。
周而复始。
重置 git reset
但总有需要重置的时候:
git reset
移动当前分支指针(即间接改变HEAD)。
手段一:git reset --soft HEAD~
移动HEAD指针到HEAD~,这时仓库和暂存区不同,暂存区和工作目录相同,即状态三。简而言之,就是“撤销”了上次的提交。
手段二:git reset --mixed HEAD~
移动HEAD指针到HEAD~,并重置暂存区。这时仓库和暂存区相同,工作区和暂存区不同,即进入状态二。--mixed是默认参数。
手段三:git reset --hard HEAD~
移动HEAD指针到HEAD~,并重置暂存区和工作区到当前HEAD版本。即状态一。这是一条危险操作,因为你可能会丢失当前正在编辑而没提交的所有内容。但这条命令也是真正完全的实现了跳跃版本,不会残留任何一点当前版本的信息。
增加路径的reset
reset可以增加路径,这时的表现就是重置某个文件而已。并不会改动HEAD指针。
git reset -- file.txt
重置暂存区file.txt文件状态。简而言之,就是git add
的反向操作。
你还能指定暂存区重置到哪个版本git reset 234b file.txt
。
检出 checkout
checkout和reset命令很相似,也是操控三个目录树。差别是checkout 改变HEAD本身,reset是改变当前被HEAD指向的分支。务必理解这个二重指针的结构。
比如HEAD 指向master,reset 会改变master,HEAD不变。而checkout 会直接改变HEAD,master不变。虽然表面现象上来说很多时候表现是差不多的,因为当前用户可能只会观察到三棵树的变化,而没有留意指针的变化。
git checkout develop
从master分支切换到develop分支,并重置工作区和暂存区,进入状态一。
带路径的checkout
类似带路径的reset,并不会改变HEAD,不同点它重置暂存区,同时也重置工作区。
git checkout -- file.txt
用当前HEAD指向的目录树中的file.txt镜像重置暂存区和工作区。
仓库
- 纯仓库。
git init --bare
创建一个纯仓库,只是用来存储仓库数据而不是用来工作的。比如用来做服务器远端仓库,本地仓库的备份。 - 空仓库。
git init
创建一个空仓库
仓库内容:ls -F1 .git
branches/ #分支
COMMIT_EDITMSG
COMMIT_EDITMSG.save
config #设置
description #GitWeb使用
FETCH_HEAD
gitk.cache
HEAD #头指针
hooks/ #钩子
index #暂存区
info/ #全局排除模式,类似.gitignore
logs/
objects/ #数据
ORIG_HEAD
refs/ #各种commit 指针
数据对象
-
git hash-object
任何对象都可以用哈希值加入仓库索引 -
git cat-file
用哈希值搜索仓库内对象 -
git update-index --add --cachinfo 100644
更新暂存区对象 -
git write-tree
将暂存区写入树对象 -
git read-tree --prefix=dir
加入子树,前缀dir -
git commit-tree c03ca4
用树对象生成提交对象 -
git log --stat
查看提交对象历史信息 -
git fsck --full
查看没有引用的对象 -
git gc
压缩对象库 -
git count-objects -v
查看空间暂用统计 -
git prune --expire now
立即清除所有不被引用的对象(因为试验,生成了错误的对象,但是要清理非常非常麻烦,最后靠这条命令成功清理了) -
git reflog expire --expire-unreachable=0 --all
清理操作记录,这是对象有可能被引用的地方
其他
-
git config core.autocrlf true
自动转换换行格式。
资料
git社区参考书:http://gitbook.liuhui998.com/