版本管理
简介
- 版本控制系统
- 版本控制系统即VCS(version control system)是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。它帮助我们查阅或回到某个历史版本
- “人肉”VCS
- LVCS 本地版本控制系统(Local)
- 比如 RCS(Revision Control System)
- 缺点:管理困难;不利于多人协作
- CVCS 集中式版本控制系统
- 比如CVS(Concurrent Versions System)
- SVN(Subversion) (比较有名)
- Perforce
- DVCS 分布式版本控制系统(Distribution)
- 比如Git
- Mercurial
-
集中式版本控制系统(CVCS)对比分布式版本控制(DVCS):
- CVCS:
- 优点:因为管理的点只在中央服务器上,所以可控性比较高。共享性更高点,大家修改和使用公共池中的文件
- 缺点:容易发生单点故障,一旦服务器发生故障,有可能会导致无法进行相关操作,甚至会丢失历史消息。且每次操作都要经过网络请求,影响操作的流畅性,也就是必须要进行网络的连接
- 使用:比较适合项目中的文档的版本管理
- DVCS:
- 优点:适合多人团队协作开发。每个本地库都是一个完整的历史拷贝,即使中央服务器故障,也很容易从本地库将历史还原,即安全性比较高。若大部分相关操作不需要同步服务器,可直接在本地完成,也就是可以离线工作,不依赖网络请求,这样操作会更流畅
- 缺点:很容易出现代码冲突。两台电脑不能相互访问,只能访问中央库中的,这个比较适合代码文件的版本控制。
- CVCS:
分支模型
- 分支:从目标仓库获得一份项目拷贝,每条拷贝都有和原仓库一样的开发线
- 分支模型(branching moel)/工作流(workflow):一个围绕项目(开发/部署/测试)等工作流程的分支操作(创建/合并等)规范集合
Git
- Git是什么?
- git是一根免费开源的分布式版本控制系统(DVCS)
- git是一个基于内容寻址的存储系统
- 历史:git的出现离不开linux
- 1991-2002:几乎无版本控制(patch包)
- 2002-2005:BitKeeper
- 2005-至今:git
- 优势:
- 速度:快!不是直接对比文件的改变,而是给文件做一个快照(hash),通过比较 hash 值的变更来判断文件是否改变
- 完全的分布式,不怕断网
- 轻量级的分支操作,允许上千个并行分支
- Git已经成为现实意义上的标准(几乎所有的优秀前端的开源项目都是通过git来控制的)
- 社区成熟活跃(github,注意git并不等于github,当然git的流行离不开github)
Git 重要概念
在仓库中,任何文件都是下面三种状态之一:
- 已提交(committed):该文件已经被安全地保存在本地数据库中了
- 已修改(modified):修改了某个文件,但还没有提交保存
- 已暂存(staged):把已修改的文件放在下次提交时要保存的清单中
基本操作
起步
- 初次使用需要设置姓名和邮箱
- 我们将文件 push 到 github,会有一条记录,显示是谁提交了这份文件(姓名 + 邮箱),方便跟踪测试
# 添加 --global,设置一次,所有的仓库都能用了
git config --global user.name "你的姓名"
git config --global user.email johndoe@example.com
clone 项目
- 用于把一个 Github 上的项目 clone(下载)到本地变为本地仓库
# 这里使用的是 SSH 协议地址
git clone git@github.com:jirengu/blog.git
cd blog
# 通过命令 ls -al,可以看到在 blog 目录下存在 .git 文件夹的(隐藏),因为它,blog 才能被视为本地仓库
# 我们做的修改,其实都是 .git 文件夹记录操作的,如果删除它,blog 就是一个普通的文件夹,git 命令对其无作用
添加文件并提交
# 创建文件(这里是通过命令行的方式,也可以打开 blog 目录,自行添加、编辑)
touch a.md
# 在文件里写入一个字符串
echo "hello" > a.md
# 显示有变更的文件
git status
# 把当前目录下的所有新增和修改的文件添加到暂存区
git add .
git status
# 把暂存区的更新提交到本地库
# -a 代表将工作区自上次commit之后的变化,直接提交到仓库区
# -m 每次提交必须留点信息出来,加点备注,方便以后查询提交记录,所以 git 强制要求加这个参数,哪怕是空字符串
git commit -am "add file"
git status
# 把当前本地库里的改动推送到远程库(origin)的 master 分支
git push origin master
# 如果之前已经使用此命令推送过,那么直接使用命令 git push 即可
修改删除文件
# 把远程仓库的变动更新合并到本地仓库
git pull
# 修改文件
vim a.md
git add .
# 这里需要注意,如果提交消息包含大量字符串,提交参数不用加 m
# 此时会进入 vim 界面,按下i进入编辑状态,进行编辑
# 编辑完成后按下 esc 进入命令态, 输入 :wq 保存退出 vim
git commit -a
git push origin master
rm -rf a.md
git add .
git commit -am "删除a.md"
- git clone 是把整个 git 项目拷贝下来,包括里面的日志信息,git项目里的分支,我们也可以直接切换、使用里面的分支等
- git pull 相当于 git fetch(下载) 和 git merge(合并)。其意思是先从远程下载 git 项目里的文件,然后将文件与本地的分支进行 merge
[origin 代表什么?](Git 里面的 origin 到底代表啥意思?)
- origin 就是一个名字,它是我们 clone 一个托管在 Github 上代码库时,git 为我们默认创建的指向这个远程代码库的标签,origin 指向的是 repository,master 只是这个 repository 中默认创建的第一个 branch。当我们 git push 的时候因为 orgin 和 master 都是默认创建的,所以这样可以省略,但是这个是 bad practice,因为当我们换一个 branch 再 git push 的时候,有时候就纠结了
复杂使用
本地创建一个 git 项目推送到远程空仓库
mkdir newProject
cd new Project
# 把一个文件夹初始化成一个本地 git 仓库
# 注意 仓库和文件夹的区别在于仓库下有一个隐藏的 .git文件夹,里面有一些信息
# 对于一个仓库,删除.git文件夹,就变成一个普通文件夹了
git init
touch index.html
echo "hello" > index.html
git add .
git commit -am "init"
# 查看本地库里记录的远程库地址
git remote -v
# 这里把远程库的地址添加个标签叫origin
git remote add origin git@github.com:jirengu/blog2.git
# 推送到远程库地址
git push origin master
# 我们知道,当别人修改了文件并推送到了 github 上,我们 git push 的时候,会被拒绝,需要先 git pull
# 但是如果我们确信自己即将要做的操作,可以强制推送
# 慎用,这样会强制推送,会覆盖别人的代码
git push -f origin master
# 再添加一个远程库的标签
git remote add gitlab git@gitlab.com:abc/blog.git
# 推送到gitlab标签的地址上
git push gitlab master
# 删除gitlab 标签
git remote remove gitlab
# 修改origin标签对应的地址
git remote set-url origin git@github.com:jirengu/blog3.git
# 把 gitlab 标签改名为coding
git remote rename gitlab coding
分支操作
# 列出所有本地分支和远程分支
# 前面带 * 号的,是我们当前所处的本地分支
$ git branch -a
# 创建本地库 dev 分支
git branch dev
# 切换到 dev 分支
# 我们切换分支,就会展现不同分支的文件状态,我理解为不同分支之间是隔离的
git checkout dev
touch b.md
git add .
git commit -am "add b.md"
# 推送到 origin 地址的 dev 分支上
git push origin dev
# 把 dev 分支上的内容合并到当前分支(master) 上,注意要先切换到 master 分支上
# 此时本地仓库 master 里面的内容就和 dev 一样了,
# 再把当前本地库里的改动推送到远程库(origin)的 master 分支上
git checkout master
git merge dev
push origin master
当自己和别人改同一个文件的同一个地方,在执行 git pull 时更新本地合并时会出现冲突
- 修改冲突文件
- 重新提交