(读书) 版本控制之道--试用Git
Git的优势:
1,分布式体系结构,完全断网操作;
2,分布与合作操作很容易,创建分支,合并分支简单快捷;
git通过对提交内容进行SHA1 Hash计算,得到他们的SHA1串值,作为每个提交的唯一标识。 使用版本库中的元数据产生提交名称。这些元数据包括提交者的个人信息及提交的时间戳。当然,产生相同哈希码的可能性也是存在的,但是这种可能性非常的低,可以忽略。从数学的角度考虑,可能性是2的63次方分之一。
ls| more 查看当前git目录的结构:
FETCH_HEAD #
HEAD #
ORIG_HEAD #
description #项目的描述信息
hooks #默认的hooks脚本文件
index #索引文件,git add后要把添加的项暂存到这里。(是工作目录树和版本库之间的缓冲区。)
info #里面有一个exclude文件,制定本项目要忽略的文件
logs #各个ref的历史信息
objects #这个目录非常重要,里面存储的都是git的数据对象
#包括 ,commits(提交),tree(树对象),blobs(二进制对象),tags(标签对象)
packed-refs #
refs #标识着你的每个分支指向那个提交(commit)
每个提交都是一个树对象。一个树对象可以引用一个或多个二进制对象。每个二进制对象都对应一个文件。更进一步,树对象也可以引用其他的树对象,从而构成一个目录层次结构。
如果通过git,ssh协议传输,服务器端会在传输前是把需要传输的各种对象先打好包再进行传输,而http(s)协议则会反复请求要传输的不同对象。
git把它所管理的所有对象,全部根据内容生成SHA1哈希串值作为对象名。这样的好处是:
1,git只要比较对象名,就可以很快的判断出两个对象的内容是否相同。
2,因为在每个仓库的“对象名“的计算犯法都完全一样,如果同样的内容存在两个不同的仓库中,就会存在相同的”对象名“。
3,git还可以通过检查对象内容的SHA1的哈希值和”对象名“是否匹配,来判断对象内容是否正确。
No delta, just snapshot
传统系统使用的是: 增量文件系统,(delta storge systems)
他们存储的是每次提交之间的差异。git正好相反,保存的是每次提交的完整内容(SNAPSHOT)。会在提交前根据要提交的内容求SHA1哈希串值作为对象名,看仓库内是否有相同的对象,如果没有就将“.git/objects”目录创建对应的对象,如果有就重用已有的对象,以节约空间。
SHA使用git hash-object来计算的。commit object内容是tree SHA,commiter/时间戳,author/时间戳。即使是tree SHA一致,后面两部分不同,最后的SHA就不同。
相关命令:
git init 初始化版本库
git add fileName 将文件加入版本库的索引(index),然后提交。
git commit -m "commit message" 提交文件,其中commit message作为注释。
git log 显示提交名称。git用来跟踪提交。
git status 显示工作目录树的状态,类似于SVN的工作拷贝。
git branch 创建分支,该命令需要2个参数:新分支名称和父分支名称。
git branch -d 删除分支,只是删除了分支的名字,并不会删除分支上的任何内容。
git tag 给Git中的代码打标签,该命令需要2个参数:标签名称和对应的分支。 标签以一个简单的名称(即标签名)来标记版本库历史中某个特定的点。
git checkout master 切换回主分支(切换分支)
git rebase (变基命令) 转换到那个分支的末端。把一条分支上的修改在另一条分支的末端重现。
git branck -d branchName 删除分支,只是删除了分支的名称,并不会删除分支上任何实际内容。只要标签还在,从标签到版本树起点的一连串提交记录就都在。
git archive 将标签对应的版本内容打包。
git mv srcName newName 移动文件
在文件.gitignore中设定本地忽略的文件名称
合并分支间的操作:
直接合并(straight merge):把两条分支上的历史轨迹合并,交汇到一起。
git merge alternate
压合合并(squashed commits):将一条分支上的若干个提交条目呀合成一个提交条目,提交到另一个分支的末端。 git merge --squash branchName
挑拣合并(cherry-picking):挑选另一条分支上的某个提交条目的改动到当前分支上。
git cherry-pick SHA1 ID -n 参数标明创建提交前需要连续进行合并操作。
git blame fileName 查看特定代码块的历史信息
git revert 反转提交
git reset --hard HEAD^(复位2个提交) –hard 会从版本库和工作目录树中同时删除提交。好像版本库中的删除键,并且不可以恢复。
改写历史: 1,重新排序提交: git rebase -i HEAD~3 排列最新3个提交
2,将多个提交合并成一个提交: git rebase -i versionID 调整好次序,将需要合并的pick修改为squash。
3,将一个大的提交分解为多个提交: 运行 git rebase -i HEAD~4 将需要修改需要分拆的提交 pick修改为edit
运行 git log -1 显示最后一个提交。也就是需要编辑的内容。 git reset HEAD~ 撤销本次调教
git diff 显示等待提交的变更。 修改文件后单独提交。
然后运行 git rebase --continue 继续进行其他提交。
git branch -r 查看远程版本库的变动。
与远程版本库协作:
Git与网络上的远程版本库通信,这里所说的网络可以是内部局域网,虚拟专用网或者是因特网。Git提供了三种与远程版本库通信的协议:
1,Git: 优势在于速度,在Git中是最快的网络协议。但比较麻烦的是它必须试用9418端口,而这个端口的通信一般会受到防火墙的限制。git与ssh的区别是,git协议无需加密,且是匿名的。
一种常见的方式是,开发人员使用git协议将远程版本库中的更新拖入本地版本库,而使用SSH协议将本地版本库中的更新推入远程版本库中。
2,SSH: 通过SSH访问,与直接通过文件系统访问非常相似。唯一不同的是,在指定远程版本库路径前,还必须为它制定域名服务器和用户名。
3,HTTP/HTTPS: 在Git中使用HTTP协议通信协议效率最低。但是它的好处在于,能通过严格的防火墙,且易于架设。
管理本地版本库
1,用标签标记项目里程碑
版本库里的标签就像书签,使用它们可以方便回到版本库上打了标签的点。在Git中,可以随心所愿地给任意打标签。标签最常用于给项目代码的发布版本做标识,以便以后在需要修正或功能变更时,可以通过标签或到该发布代码上。
Git标签是只读的,在Git中不能像修改分支的内容一样修改标签内容。
在代码发布过程中处理好发布分支,以便集中经历做好开发
2,发布分支的处理
发布分支通常只需要少许改动,往往侧重于Bug或逻辑修正, 很少会添加新功能。发布分支通常以RB_作为前缀并包含版本号。发布分支持续时间不长,通常只用于发布代码时的最终测试起家你,一旦该版本发布,应该使用标签标记项目,然后就可以删除该发布分支了。
高阶功能
压缩版本库 git gc
导出版本库 git archive
分支变基到新的基点
重现版本库中隐藏的历史 git reflog
使用二分法在版本库中查找引入Bug时间点 git bisect start, git bisect bad
PS: git不会跟踪空目录。
本地仓库由git维护的三棵”树”组成,第一个是的工作目录,它持有实际文件,第二个是缓存区(Index),它像个缓存区域,临时保存你的改动;最后是HEAD,指向你最近一次提交后的结果。
blog comments powered by Disqus