1、什么是版本控制
版本控制(Version control),是维护工程蓝图的标准做法,能追踪工程蓝图从诞生一直到定案的过程。此外,版本控制也是一种软件工程技巧,借此能在软件开发的过程中,确保由不同人所编辑的同一程序文件都得到同步。并且可以实现记录文件所有历史变化,做到可追溯、随时恢复。
2、常见的版本控制工具
1)集中式版本控制系统
适合多人团队协作开发;代码集中化管理。单点故障、必须联网,无法单机工作。
代表:SVN。
2)分布式版本控制系统
适合多人团队协作开发;代码集中化管理;可以离线工作、每个计算机都是一个完整仓库。
代表:Git。
3、Git
git,是一个分布式版本控制软件。分布式版本控制系统的客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。
1)工作原理
当我们通过git init创建或者git clone一个项目的时候,项目目录会隐藏一个.git子目录,其作用是用来跟踪管理版本库的。
Git 中所有数据在存储前都计算校验和,然后以校验和来引用,所以在我们修改或者删除文件的时候,git能够知道。Git用以计算校验和的机制叫做 SHA-1 散列(hash,哈希), 这是一个由 40 个十六进制字符(0-9 和 a-f)组成字符串,基于 Git 中文件的内容或目录结构计算出来。
通过git status进行查询,状态情况如下:
a、已修改(modified):表示修改了文件,但还没保存到数据库中。
b、已暂存(staged):表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
c、已提交(committed):表示数据已经安全的保存在本地数据库中。
文件状态对应的,不同状态的文件在Git中处于不同的工作区域,主要分成了四部分:
a、工作区:相当于本地写代码的区域,如 git clone 一个项目到本地,相当于本地克隆了远程仓库项目的一个副本
b、暂存区:暂存区是一个文件,保存了下次将提交的文件列表信息,一般在 Git 仓库目录中
c、本地仓库:提交更新,找到暂存区域的文件,将快照永久性存储到 Git 本地仓库
d、远程仓库:远程的仓库,如 github、阿里code。
2)常见命令
git config --global user.name "xxx" 配置用户名
git config --global user.email "xxx@xxx.com" 配置邮件
git init [project-name]:创建或在当前目录初始化一个git代码库
git clone url:下载一个项目和它的整个代码历史
git add README 添加文件,添加至暂存区
git branch 查看本地所有分支
git status 查看当前状态
git commit 提交
git commit -am "init" 提交并且加注释
git push origin master 将文件给推到服务器上
git checkout -b dev 建立一个新的本地分支dev
git checkout dev 切换到本地dev分支
git checkout --track origin/dev 切换到远程dev分支
git pull 本地与服务器端同步
git push (远程仓库名) (分支名) 将本地分支推送到服务器上去。
git fetch 相当于是从远程获取最新版本到本地,不会自动merge
git status 查看当前版本状态(是否修改)
4、Git中 fork, clone,branch的区别
1)fork
fork则可以代表分叉、克隆 出一个(仓库的)新拷贝。包含了原来的仓库(即upstream repository,上游仓库)所有内容,如分支、Tag、提交。如果想将你的修改合并到原项目中时,可以通过的 Pull Request 把你的提交贡献回原仓库。
当你在github发现感兴趣开源项目的时候,可以通过点击github仓库中右上角fork标识的按钮;
点击这个操作后会将这个仓库的文件、提交历史、issues和其余东西的仓库复制到自己的github仓库中,而你本地仓库是不会存在任何更改;
然后你就可以通过git clone对你这个复制的远程仓库进行克隆;
后续更改任何东西都可以在本地完成,如git add、git commit一系列的操作,然后通过push命令推到自己的远程仓库;
如果希望对方接受你的修改,可以通过发送pull requests给对方,如果对方接受。则会将你的修改内容更新到仓库中;
2)clone
clone,译为克隆,它的作用是将文件从远程代码仓下载到本地,从而形成一个本地代码仓。执行clone命令后,会在当前目录下创建一个名为xxx的目录,并在这个目录下初始化一个 .git 文件夹,然后从中读取最新版本的文件的拷贝。
3)branch
branch,译为分支,其作用简单而言就是开启另一个分支, 使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线。
通过git branch可以创建一个分支,但并不会自动切换到新分支中去;
通过git checkout可以切换到另一个testing分支。
总结
fork 只能对代码仓进行操作,且 fork 不属于 git 的命令,通常用于代码仓托管平台的一种“操作”;
clone 是 git 的一种命令,它的作用是将文件从远程代码仓下载到本地,从而形成一个本地代码仓;
branch 特征与 fork 很类似,fork 得到的是一个新的、自己的代码仓,而 branch 得到的是一个代码仓的一个新分支。
5、git pull 和 git fetch 的理解
git fetch 命令用于从另一个存储库下载对象和引用;是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中
git pull 命令用于从另一个存储库或本地分支获取并集成(整合)。则是将远程主机的最新内容拉下来后直接合并,即:git pull = git fetch + git merge,这样可能会产生冲突,需要手动解决。
6、git rebase 和 git merge的理解
当完成一个特性的开发并将其合并到 master 分支时,会有两种方式:git merge 和 git rebase。它们都是将一个分支的提交合并到另一分支上,但是在原理上却不相同。
1)git merge XXX 将当前分支合并到指定分支
例如:bugfix分支是从master分支分叉出来的,我们需要合并bugfix分支到master分支时:
a、如果master分支的状态没有被更改过,即 bugfix分支的历史记录包含master分支所有的历史记录。所以通过把master分支的位置移动到bugfix的最新分支上,就完成合并。
b、如果master分支的历史记录在创建bugfix分支后又有新的提交。使用git merge的时候,会生成一个新的提交,并且master分支的HEAD会移动到新的分支上。
总结:git merge 会把两个分支的最新快照以及二者最近的共同祖先进行三方合并,合并的结果是生成一个新的快照(commit)。是一种非破坏性的操作,对现有分支不会以任何方式被更改,但是会导致历史记录相对复杂。
2)git rebase -i <commit> 将当前分支移植到指定分支或指定commit之上
常见的参数有--continue,git rebase --continue 用于解决冲突之后,继续执行rebase。
a、master分支的历史记录在创建bugfix分支后又有新的提交,通过git rebase,会bugfix分支生成的记录加在主分支之后。
b、在移交过程中,如果发生冲突,需要修改各自的冲突。
总结:git rebase 会找到不同的分支的最近共同祖先,如上图的B。然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件X',Y'(老的提交X和Y也没有被销毁,只是简单地不能再被访问或者使用)。然后在当前分支指向目标最新位置D后,将之前另存为临时文件的修改依序应用。rebase会将整个分支移动到另一个分支上,有效地整合了所有分支上的提交,好处是历史记录更加清晰,是在原有提交的基础上将差异内容反映进去,消除了 git merge所需的不必要的合并提交。
7、git reset 和 git revert 的区别
git reset是直接删除指定的commit,可以遗弃不再使用的提交,即HEAD向后移动;
git revert是用一次新的commit来回滚之前的commit,不会改变过去的历史,主要是用于安全地取消过去发布的提交,即HEAD继续前进