Git的缔造者(father)javascript
第一代版本控制系统被称为本地版本控制系统。经过加锁将并发执行转换成顺序执行。 一次只能有一我的处理文件。具体流程以下:首先,应该把文件放在一个服务器上,方便使用者上传或下载文件;其次,任何人想对文件修改时,须要先把这个文件加锁,经过checkout指令,使得其余人没法修改;最后,当修改完成以后,须要释放锁,经过checkin指令,造成一个新的版本,存放到服务器端。第一代版本控制系统主要有 RCS( Revision Control System )、SCCS。html
在硬盘上(本地,local computer)保存补丁集(文件修订先后的变化),经过全部的补丁,能够计算出各个版本的文件内容,大多都是采用某种简单的数据库来记录文件的历次更新差别。前端
第二代版本控制系统被称为集中式版本控制系统(Centralized Version Control Systems,CVCS),其对同步修改更加宽容,但有一个明显的限制,用户必须在容许提交以前将当前修订合并到他们的工做中。不便之处就是要联网,若中央服务器发生单机故障,宕机了,那么在这宕机期间谁都没法提交更新,也就没法协同工做,还有中央服务器丢失数据的可能等。java
由下图可看到,在集中式版本控制系统中,若是服务器嗝屁了,那么全部的开发者就只能干瞪眼了!由于,SVN 对于项目的管理是依赖于服务器中的中心仓库的!咱们的更改必需要提交到服务器中的中心仓库。第二代版本控制系统主要有 CVS、Subversion、SourceSafe、Team Foundation Server、SVK。git
第三代版本控制系统被称为分布式式版本控制系统(Distributed Version Control Systems,DVCS),其容许合并和提交分开。在每一个使用者电脑上就有一个完整的数据仓库,没有网络依然可使用。程序员
由下图可看到,分布式版本控制系统也能够有个服务器端的仓库,用来同步各开发者的私有仓库。在分布式版本控制系统中,每一个参与者的本地也会有一个完整的仓库。及时服务器端崩溃,咱们仍然可使用 Git(仅在本地仓库管理咱们的代码),在网络具有时,再和服务器进行同步便可!第三代版本控制系统主要有 Bazaar、Git、Mercurial、BitKeeper、Monotone。github
思考:web
- 怎么理解分布式与集中式?(廖雪峰老师给出的理解)
- 集中式:版本库是集中存放在中央服务器的,而干活的时候,用的都是本身的电脑,因此要先从中央服务器取得最新的版本,而后开始干活,干完活了,再把本身的活推送给中央服务器。中央服务器就比如是一个图书馆,你要改一本书,必须先从图书馆借出来,而后回到家本身改,改完了,再放回图书馆。
- 分布式:分布式版本控制系统根本没有“中央服务器”,每一个人的电脑上都是一个完整的版本库,这样,你工做的时候,就不须要联网了,由于版本库就在你本身的电脑上。
特性 | SVN | GIT |
---|---|---|
架构模式 | 集中式 | 分布式 |
安全性 | 较差,按期备份 | 高,开发者本地电脑就是一个完整的版本库 |
适用性 | 文档管理, | 代码管理, |
易用性 | 简单上手,对新手友好 | 上手困难,学习成本高但效率搞 |
灵活性 | 较低,易发生单点故障,拉取分支 | 高,单机本地操做,多个备份,本地新建分支 |
权限管理 | 拥有严格的权限管理 | 尚无严格权限管理,有帐号角色划分 |
咱们使用Git来记录每一次文件内容的变动,版本的更新,清晰地比较出不一样版本的内容差别;可使用Git在项目的历史版本自如地进行切换;还可使用Git从当前项目的更改中撤销一些操做,能够新建分支,合并分支甚相当联远程服务器仓库等,这一切的背后都是怎么实现的?了解Git的思想以及基本原理这些操做也就略知一二了。算法
.git下的文件夹数据库
.git下的文件
HEAD 文件指向当前分支, 包含了一个分支的引用,经过这个文件Git能够获得下一次commit的parent,能够理解为指针
index 文件存储着暂存区的内容信息
config 文件包含项目的配置信息
description 存储着仓库的描述信息,主要给gitweb等git托管系统使用
packed-refs 打包标头和标签以便高效的存储库访问
FETCH_HEAD 是一个版本连接,指向着目前已经从远程仓库取下来的分支的末端版本
ORIG_HEAD 记录的是在进行危险(drastic)操做(如合并merge,回退reset等)时,此操做以前HEAD所指向的位置,便于咱们在发生毁灭性失误时进行回退
COMMIT_EDITMSG 保存最新的commit message,Git系统不会用到这个文件,只是给用户一个参考
Git本质上是一个内容寻址文件系统(就是根据文件内容的hash码来定位文件。 这就意味着一样内容的文件,在这个文件系统中会指向同一个位置,不会重复存储。)Git 的核心部分是一个简单的键值对数据库,能够向该数据库插入任意类型的内容,它会返回一个键值,经过该键值能够在任意时刻再次检索(retrieve)该内容
Git 保存的不是文件的变化或者差别,而是一系列不一样时刻的文件快照。在进行提交操做时,Git 会保存一个提交对象(commit object)。该提交对象会包含一个指向暂存内容快照的指针。 但不只仅是这样,该提交对象还包含了做者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。
git经过一种安全散列算法1(SHA-1)能够获得任意文件的SHA-1哈希值(40位的字符),也就是commit ID,而后经过文件哈希值存取数据,存取的数据都位于objects目录,SHA-1哈希值的前两个字符做为子目录名称,后 38 个字符则做为子目录内文件的名称。
Git经常使用命令共有30多个,可运行git help
查看;但Git总共有130多个命令,能够经过git help -a
查看,这些命令能够分为高层命令和底层命令,底层命令被设计成unix风格,不经常使用
浏览完整的提交历史,但为了能遍历那段历史从而找到全部相关对象,须要记住最后提交的SHA-1值。咱们须要一个文件来保存 SHA-1 值,并给文件起一个简单的名字,而后用这个名字指针来替代原始的 SHA-1 值。文件被称为“引用(references,或缩写为 refs)”,使用git branch (branchname)
这样的命令时,Git 实际上会运行 update-ref
命令,取得当前所在分支最新提交对应的 SHA-1 值,并将其加入你想要建立的任何新引用中。
git/refs/heads
目录下,每个分支对应一个文件refs/remotes
目录下master分支为项目的核心分支,也是最终对外发布的分支,惟一且稳定。仅提供可读,不可在该分支上直接修改代
develop分支是项目的开发主干分支,惟一。仅提供可读,不可在该分支上直接修改代码。新功能的开发需从该分支拉取新的分支展开。develop分支应该包含项目完整的所有历史记录。
featrue分支项是目的需求开发分支,可多个,从develop分支或其余featrue分支拉取。程序员的多人分工协做即经过featrue来实现,是代码具体实现的一线程序员接触最多的分支。需求开发完成后,要合并回develop分支。
release分支为预发布分支,一般被叫作测试分支,主要用于开发阶段的测试及bug修复。当feature分支开发完毕后会合并回develop分支,而后再从develop分支拉取release分支提测。测试并修复后的release分支要合并回develop分支以及master分支,并打上合适的tag标记(包含必要的releaseNote)。
hotfix分支为紧急线上修复分支,即当对外发布的master分支出现重大bug,影响线上使用时,从master分支拉取hotfix分支进行紧急修复。修复后的hotfix分支要合并回master分支和develop分支。
而后,开发团队中的其余人克隆中央仓库的develop分支到本地,造成全体成员统一的惟一的develop分支轨迹。以后,按照需求及成员各自的分工,各个成员能够从develop分支拉取出各自的featrue分支(步骤②)进行独立的开发;若涉及到多人合做开发同一分支,拉取的分支要及时推送至服务器,便于各成员共享。
当各成员完成各自的功能开发后,需将完成后的代码提交到featrue分支,而后合并到develop分支(步骤③)。代码合并后,featrue分支能够再也不保留。
功能累积足够且稳定或到达约定的提测周期时,项目负责人应当从develop分支拉取出release分支(步骤④),打包提交相应的版本给测试人员进行部署测试,测试中提交的bug所有在该release分支完成修改。
测试结束并完成bug修复后,release分支应该合并回develop分支和master分支(步骤⑤),代码合并后,release分支能够再也不保留。合并后的master分支,应由项目负责人及时推送到中央仓库(步骤⑥)。同时全体成员要及时同步本身develop分支。
有上线需求时,直接从master分支打包提交应用版本进行部署。当线上版本出现重大bug,项目负责人需从master分支拉取hotfix分支(步骤⑦),进行线上的紧急修复。
最后,修复后的hotfix分支要合并回develop分支和master分支(步骤⑧)。并推送到中央仓库(步骤⑨)。
git config --global user.name 'your name'
git config --global user.email 'your email'
$ ssh-keygen -t rsa -C "your email"
复制代码
打开在windows(c盘)/用户/xxx/.ssh文件夹下的id_rsa.pub文件,复制里面的内容;粘贴在GitHub或Gitlab的setting的ssh key
HEAD
commit
branch
merge 合并指定分支
git merge branch 合并其余分支到当前分支
rebase 衍合指定分支
reset 重置
revert 撤销,回滚到指定的特定版本
cherry-pick 选择合并某次提交的commit到当前分支
reflog 查看HEAD的全部移动轨迹
思考:
git merge 与 git rebase 的区别是?
- rebase会合并该分支与其余分支的commit history,可能会获得一个新的commit history
- rebase获得更简洁的项目历史,去掉了merge commi,若是合并出现代码问题不容易定位,由于re-write了commit history
- merge会建立新的commit,包括每一个分支的commit 详情
- 每次merge会自动产生一个merge commit,特别是commit比较频繁时,看到分支很杂乱。
- 想要获得一个干净的,没有merge commit的线性commit历史记录,选择git rebase
- 想要获得一个完整的commit历史记录,且想避重写commit历史记录的风险,选择git merge
git reset 与 git rebase的区别?
- git revert会生成一个新的提交来撤销某次提交,这次提交以前的commit都会被保留,也就是说对于项目的版本历史来讲是往前走的。
- git reset 则是回到某次提交,相似于穿越时空。
附前端全站书籍PDF文档下载连接:juejin.im/post/5d7216… (要书籍资源的请在下面留言,网盘收集了先后端时髦的书籍电子版)