git和svn比较
| git | svn |
架构 | 分布式 所有的teammates本地可以clone一份独立完整的仓库,而不仅仅是某一个版本的镜像拷贝;开发者可以在本地clone仓库中完成所有vcs的操作,只有当需要协同工作提交代码到远程仓库的时候,才需要联上网络。 | 中央集中式 所有的teammates都面向同样一个远程仓库工作;checkout出来的本地工作区代码只是远程仓库某一版本的一份镜像拷贝。 |
仓库结构与URL |
|
|
分支管理 | Git分支相对于其他的vcs是非常不一样的设计理念,一个Git分支仅仅指的是指向某一确定版本的简单指针,因此,Git的分支是无拷贝、无新建目录、几乎无开销的。 | SVN中的分支仅仅是项目的一份拷贝,是一个具有特殊含义的普通文件夹;多分支则是多文件夹的形式。 |
提交操作 |
|
|
撤消操作 | 代码库是属于个人,允许任意修改。Git通过对提交建立数字摘要来保证提交的唯一性和不可更改性,通过版本库在多人之间的多份拷贝来保障数据的安全性。Git可以丢弃最新的一个或几个提交,使用 git reset –hard命令可以永远丢弃最新的一个或者几个提交。 | 一旦完成向服务器的数据提交,你就没有办法再从客户端追回,只能在后续的提交中修正(回退或者修改)等。因为Subversion作为集中式的版本控制,不能允许个人对已提交的数据进行篡改。Subversion具有一个非常重要的特性就是它的信息从不丢失,即使当你删除了文件或目录,它也许从最新版本中消失了 ,但这个对象依然存在于历史的早期版本中。 |
协同工作 | Git不会为你作任何的自动上传的操作,需要决定何时将本地仓库的内容同步上传到远端仓库分享出来,分享过程相对于其他的中央仓库式的vcs系统来说是更加安全的,所发生的冲突也只会发生于你的本地(仓库)而非远端服务器的仓库,这将更能帮助你规避打乱teammates工作内容冲突的风险。 | 将本地分支内容作commit操作之时,你的内容便会分享到远端中央仓库中,其他teammates也都能同步到你所提交的内容 |
权限管理 | 只能实现非零即壹式的授权,要么拥有全部的写权限,要么没有写权限,要么拥有整个版本库的读权限,要么禁用。 | 通过对文件目录授权来实现权限管理,子目录默认继承父目录的权限。但是也有缺憾,即权限不能在分支中继承,不能对单个文件授权。 |
优缺点 |
|
|
工作区域
- 本地:
Working directory:工作区
Index directory:暂存区
Local repository:本地仓库
- 远程:
Remote repository:远端仓库
常用的Git操作
- clone:克隆项目到本地工作区
- branch:创建分支
注:git branch -f master HEAD~3:将 master 分支强制指向 HEAD 的第 3 级父提交
- checkout:创建/切换本地仓库的指定分支到工作区中
注:git checkout bugfix:HEAD迁出某个分支
git checkout -b bugfix:创建bugFix分支并迁出
git checkout C1:HEAD迁到hash值某个版本
git checkout HEAD^/ git checkout master^:迁出到head/master的上一个版本
git checkout HEAD~4/ git checkout master~4:迁出到head/master的上4个版本
- commit:将本地工作区代码提交到本地仓库
- merge / rebase:从指定分支中获取更新并合并到当前分支
注:merge:将bugFix分支合并到master,保留分支的提交内容
在master分支执行:$git merge bugfix
rebase: 把 bugFix 分支里的工作直接移到 master 分支上。移动以后会使得两个分支的功能看起来像是按顺序开发,但实际上它们是并行开发的。
在bugFix分支执行:$git rebase master
- reset/revert:撤销变更
注:reset通过把分支记录回退几个提交记录来实现撤销改动,你可以将这想象成“改写历史”。reset操作不可以推送到远程。
执行:$git reset HEAD~1
revert在要撤销的提交记录后面多了一个新提交,新提交记录 C2' 引入了更改 —— 这些更改刚好是用来撤销 C2 这个提交的。可以把更改推送到远程仓库与别人分享。
执行:$git revert HEAD
- push:将本地仓库代码同步到远端仓库
- pull / fetch:将远端仓库的代码同步到本地仓库/工作区
注:fetch:从远端仓库获取并更新到本地仓库中,不影响工作区
pull:fetch + merge(默认方式,可以用 —rebase 参数指定成rebase合并方式),该操作会影响工作区
- stash:备份/唤出当前的现场状态(包含工作区和暂存区)
- cheery-pick/rebase -i 自由修改提交树
执行:git cherry-pick C2 C4
当你你知道你所需要的提交记录(并且还知道这些提交记录的哈希值)时, 用 cherry-pick 再好不过了,但是如果你不清楚你想要的提交记录的哈希值,我们可以利用交互式的 rebase -i
执行:git rebase -I HEAD~4,并对提交记录进行调整或删除
Flow比较
GitFlow
优点:
- 并行开发:GitFlow可以很方便的实现并行开发。每个新功能都会建立一个新的 feature分支,从而和已经完成的功能隔离开来,而且只有在新功能完成开发的情况下,其对应的 feature分支才会合并到主开发分支上(也就是我们经常说的develop分支)。另外,如果你正在开发某个功能,同时又有一个新的功能需要开发,你只需要提交当前 feature 的代码,然后创建另外一个feature 分支并完成新功能开发。然后再切回之前的 feature 分支即可继续完成之前功能的开发。
- 协作开发:GitFlow 还支持多人协同开发,因为每个 feature 分支上改动的代码都只是为了让某个新的 feature 可以独立运行。同时我们也很容易知道每个人都在干啥。
- 发布阶段:当一个新 feature 开发完成的时候,它会被合并到 develop 分支,这个分支主要用来暂时保存那些还没有发布的内容,所以如果需要再开发新的 feature,我们只需要从 develop 分支创建新分支,即可包含所有已经完成的 feature 。
- 支持紧急修复:GitFlow 还包含了 hotfix 分支。这种类型的分支是从某个已经发布的 tag 上创建出来并做一个紧急的修复,而且这个紧急修复只影响这个已经发布的 tag,而不会影响到你正在开发的新 feature。
缺点:
- 第一个问题是开发人员必须使用development分支而不是master, master是为发布到生产环境中的代码预留的。由于大多数工具会自动将主分支设置为默认分支并显示默认分支,因此切换到另一个分支非常烦人。
- 默认的 master 分支只是用于发布,开发都在其他分支上。对于多数应用来说过于复杂,特别是 release 和 hotfix 分支的不可部署导致使用上的复杂。
Github flow
优点:
只有特性分支和主分支,非常简单和干净的,将所有内容合并到主分支中并进行部署通常意味着最小化“库存”中的代码量,这符合精益和持续交付的最佳实践。
缺点:
没有对于常见的工作场景中的问题,比如部署、环境、发布和集成方面提出解决办法。
Gitlab Flow
Gitlab flow 的最大原则叫做"上游优先"(upsteam first),即只存在一个主分支master,它是所有其他分支的"上游"。只有上游分支采纳的代码变化,才能应用到其他分支。
对于"持续发布"的项目,它建议在master分支以外,再建立不同的环境分支。比如,"开发环境"的分支是master,"预发环境"的分支是pre-production,"生产环境"的分支是production。
开发分支是预发分支的"上游",预发分支又是生产分支的"上游"。代码的变化,必须由"上游"向"下游"发展。比如,生产环境出现了bug,这时就要新建一个功能分支,先把它合并到master,确认没有问题,再cherry-pick到pre-production,这一步也没有问题,才进入production。
只有紧急情况,才允许跳过上游,直接合并到下游分支。
对于"版本发布"的项目,建议的做法是每一个稳定版本,都要从master分支拉出一个分支,比如2-3-stable、2-4-stable等等。以后,只有修补bug,才允许将代码合并到这些分支,并且此时要更新小版本号。