版本控制系统
集中式版本控制系统(Centralized Version Control Systems,简称 CVCS):have a single server that contains all the versioned files, and a number of clients that check out files from that central place.
集中式版本控制系统的缺点是中央服务器的单点故障。
分布式版本控制系统(Distributed Version Control System,简称 DVCS):clients don’t just check out the latest snapshot of the files; rather, they fully mirror the repository, including its full history.
分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。
集中式版本控制:CVS、SVN、ClearCase、VSS
分布式版本控制:Git、BitKeeper、Mercurial、Bazaar
git和其他版本控制工具存储数据的方式不同:
- 其他版本控制工具存储一组文件以及基于这些文件随时间推移产生的差异
- git存储更像快照,对当时的全部文件制作一个快照并保存这个快照的索引,如果没有修改则只保留一个指向之前存储文件的链接
在 Git 中的绝大多数操作都只需要访问本地文件和资源,一般不需要来自网络上其它计算机的信息
SVN 中可以修改文件,但是无法向数据库提交修改
Git 中所有数据在存储前都计算校验和,然后以校验和来引用,
校验和由 40 个十六进制字符组成,通过SHA1计算得出。Git 数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。
Git的作用
- 备份文件
- 记录历史
- 回到过去
- 多端共享
- 团队协作
安装Git
|
|
帮助信息
|
|
配置
|
|
配置文件
/etc/gitconfig
,系统配置,git config --system
~/.gitconfig
或~/.config/git/config
,当前用户,git config --global
- 项目目录下的
.git/config
,当前仓库
当前仓库会覆盖当前用户配置,当前用户配置会覆盖系统配置
用户信息
|
|
全局配置只需设置一次
当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 --global
选项的命令来配置
列出所有配置
|
|
配置别名
|
|
初始化
在现有目录中初始化仓库
|
|
克隆现有的仓库
|
|
检查当前文件状态
|
|
tracked:已跟踪,那些被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后,它们的状态可能处于未修改,已修改或已放入暂存区
untracked:未跟踪,其他文件,使用git add <file-name>
变为跟踪状态
三种状态和三个工作区域
状态 | 工作区域 | 命令 |
---|---|---|
已修改modifed | Workspace | |
已暂存staged | Stage/Index | git add <file-name> |
已提交commited | Local Repository/.git目录 | git commit |
git add
既可以用该命令开始跟踪新文件,也可以把已跟踪的文件放到暂存区
查看修改
|
|
添加和提交
|
|
忽略特殊文件
忽略某些文件时,需要编写.gitignore
.gitignore
文件本身要放到版本库里,并且可以对.gitignore
做版本管理
参考模版:https://github.com/github/gitignore
文件 .gitignore
的格式规范如下:
• 所有空行或者以 #
开头的行都会被 Git 忽略。
• 可以使用标准的 glob
模式(通配符模式)匹配。
• 以 /
开头防止递归。
• 以 /
结尾表示目录。
• 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。
查看提交历史
|
|
撤消操作
|
|
如果用–hard选项,那么工作目录也更新,如果用–soft选项,那么都不变
删除文件
|
|
如果误删除了文件且没有git add
,需要撤消
远程仓库
查看远程仓库
|
|
origin是远程仓库的默认名字
添加远程库
|
|
从远程库克隆
|
|
Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快。
自动设置本地 master 分支跟踪克隆的远程仓库的 master 分支
从远程仓库中抓取与拉取
|
|
推送到远程仓库
|
|
远程仓库的重命名
|
|
远程仓库的删除
|
|
一个本地库关联多个远程库
|
|
标签管理
发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。
查看标签
|
|
创建标签
轻量标签
只是特定提交的引用
附注标签
存储在 Git 数据库中的一个完整对象。它们是可以被校验的;其中包含打标签者的名字、电子邮件地址、日期时间;还有一个标签信息;并且可以使用 GNU Privacy Guard (GPG)签名与验证
|
|
-a 表示是附注标签
-m 表示存储在标签中的信息
后期打标签
|
|
推送标签
推送标签到远程服务器
|
|
分支管理
Git的分支,本质上仅仅是指向提交对象的可变指针master
:Git的默认分支名HEAD
是一个指针,指向当前所在的本地分支
一开始的时候,master
分支是一条线,Git用master
指向最新的提交,再用HEAD
指向master
,就能确定当前分支,以及当前分支的提交点
每次提交,master
分支都会向前移动一步,这样,随着你不断提交,master
分支的线也越来越长
当我们创建新的分支,例如dev
时,Git新建了一个指针叫dev
,指向master
相同的提交,再把HEAD
指向dev
,就表示当前分支在dev
上
创建分支
|
|
分支切换
|
|
在 testing
分支提交文件之后的变化
切换回 master
分支后的变化,工作目录的内容会变成 master
最全后一次提交的情况
在 master
分支提交文件
查看分支
|
|
合并分支
|
|
fast-forward
:没有需要解决的冲突,直接将HEAD
指向分支- 一次合并提交:三方合并,你的开发历史从一个更早的地方开始分叉开来
non-fast-forward
:存在需要解决的冲突,需要先拉取到本地并进行合并才能推送
删除分支
删除不再需要的分支
分支开发工作流
长期分支
在整个项目开发周期的不同阶段,你可以同时拥有多个开放的分支;你可以定期地把某些特性分支合并入其他分支中
比如只在 master
分支上保留完全稳定的代码
特性分支
短期分支,它被用来实现单一特性或其相关工作
Bug分支
每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
假定需要在master分支上修复,就从master创建临时分支
Feature分支
添加一个新功能
|
|
远程分支
之前的分支操作都是在本地执行的。
远程跟踪分支是远程分支状态的引用。以 (remote)/(branch)
形式命名,比如 origin/master
表示远程的master分支
|
|
推送
|
|
其他协作者通过 git fetch origin
会下载新的分支,但不能修改
跟踪分支
跟踪分支是与远程分支有直接关系的本地分支
当克隆一个仓库时,它通常会自动地创建一个跟踪 origin/master 的 master 分支
|
|
拉取
|
|
也就是 git fetch
和 git merge
,建议显示使用 git fetch
和 git merge
删除远程分支
|
|
变基
变基是另一种合并方式
不要对在你的仓库外有副本的分支执行变基
变基使得提交历史更加整洁,提交历史是一条直线没有分叉
首先找到这两个分支(即当前分支 experiment、变基操作的目标基底分支 master)的最近共同祖先 C2,然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件,然后将当前分支指向目标基底 C3, 最后以此将之前另存为临时文件的修改依序应用
|
|
解决冲突
不同的分支各自都分别有新的提交,当进行合并时就会发生冲突,必须手动解决冲突后再提交。git status
也可以告诉我们冲突的文件
修改文件中的冲突后可以再次提交
用git log --graph
命令可以看到分支合并图产品
git有个最佳实践,master是主分支,用来做正式发布版之后的保留历史,其他分支包括dev用来做正常开发,多个feature用来做某些特性功能,release用来做发布版历史,每次发布都是用release打包,hotfix用来做发布版之后的一些及时迭代修复bug的工作。
合并分支时,加上--no-ff
参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward
合并就看不出来曾经做过合并
多人协作
|
|
工作流
私有小型团队
有一两个其他开发者的私有项目
私有管理团队
独立小组的工作只能被特定的工程师整合,主仓库的master 分支只能被那些工程师更新
假设 John 与 Jessica 在一个特性上工作,同时 Jessica 与 Josie 在第二个特性上工作
git flow
- master分支,即主分支。任何项目都必须有个这个分支。对项目进行tag或发布版本等操作,都必须在该分支上进行。
- develop分支,即开发分支,从master分支上检出。团队成员一般不会直接更改该分支,而是分别从该分支检出自己的feature分支,开发完成后将feature分支上的改动merge回develop分支。同时release分支由此分支检出。
- release分支,即发布分支,从develop分支上检出。该分支用作发版前的测试,可进行简单的bug修复。如果bug修复比较复杂,可merge回develop分支后由其他分支进行bug修复。此分支测试完成后,需要同时merge到master和develop分支上。
- feature分支,即功能分支,从develop分支上检出。团队成员中每个人都维护一个自己的feature分支,并进行开发工作,开发完成后将此分支merge回develop分支。此分支一般用来开发新功能或进行项目维护等。
- fix分支,即补丁分支,由develop分支检出,用作bug修复,bug修复完成需merge回develop分支,并将其删除。所以该分支属于临时性分支。
- hotfix分支,即热补丁分支。和fix分支的区别在于,该分支由master分支检出,进行线上版本的bug修复,修复完成后merge回master分支,并merge到develop分支上,merge完成后也可以将其删除,也属于临时性分支。
参考:
- git-flow 备忘清单
- Git 在团队中的最佳实践–如何正确使用Git Flow
- 大话 Git 工作流
- 图文详解如何利用Git+Github进行团队协作开发
- 深入理解学习Git工作流(git-workflow-tutorial)
- Learn Version Control with Git
搭建Git服务器
以下方式为通过ssh协议搭建的Git服务器,添加了公钥的用户可以进行读写操作
1.安装git
2.创建用户
3.管理公钥
收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub
文件,把所有公钥导入到/home/git/.ssh/authorized_keys
文件里,一行一个
人多可以用Gitosis
来管理公钥
注意权限
4.初始化Git仓库
选定一个目录作为Git仓库
需要有一个人推送第一个版本
5.克隆远程仓库
在各自的电脑上克隆远程仓库
Git不支持权限控制。不过,因为Git支持钩子(hook),所以,可以在服务器端编写一系列脚本来控制提交等操作,达到权限控制的目的。Gitolite
就是这个工具。
还有其他方式,比如适合快速只读访问的Git守护进程,既可以进行授权访问又可以进行无授权访问的Smart HTTP,使用GitWeb搭建网页展示,参考Pro-git
利用工具提升工作效率,而不是去学习工具本身
- 多用客户端和工具,少用命令行,除非在linux服务器上直接开发
- 每次提交前,diff自己的代码,以免提交错误的代码
- 下班回家前,整理好自己的工作区
- 并行的项目,使用分支开发
- 遇到冲突时,搞明白冲突的原因,千万不要随意丢弃别人的代码
参考: