×

实战Git

96
布朗XD
2018.02.08 15:13* 字数 4479

实战Git

作者:BrianXia
转载请注明 https://www.jianshu.com/p/ed034b004255

1、Git 介绍

Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。
Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。

1.1 、Git 与 SVN 区别

GIT不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等。
如果你是一个具有使用SVN背景的人,你需要做一定的思想转换,来适应GIT提供的一些概念和特征。

Git 与 SVN 区别点:
1、GIT是分布式的,SVN不是:这是GIT和其它非分布式的版本控制系统,例如SVN,CVS等,最核心的区别。
2、GIT把内容按元数据方式存储,而SVN是按文件:所有的资源控制系统都是把文件的元信息隐藏在一个类似.svn,.cvs等的文件夹里。
3、GIT分支和SVN的分支不同:分支在SVN中一点不特别,就是版本库中的另外的一个目录。
4、GIT没有一个全局的版本号,而SVN有:目前为止这是跟SVN相比GIT缺少的最大的一个特征。
5、GIT的内容完整性要优于SVN:GIT的内容存储使用的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。

1.2、Git 安装配置

在使用Git前我们需要先安装 Git。Git 目前支持 Linux/Unix、Solaris、Mac和 Windows 平台上运行。
Git 各平台安装包下载地址为:http://git-scm.com/downloads

Windows 平台上安装
在 Windows 平台上安装 Git 同样轻松,有个叫做 msysGit 的项目提供了安装包,可以到 GitHub 的页面上下载 exe 安装文件并运行:

安装包下载地址:http://msysgit.github.io/

Windows 上安装 Git

完成安装之后,就可以使用命令行的 git 工具(已经自带了 ssh 客户端)了,另外还有一个图形界面的 Git 项目管理工具。

在开始菜单里找到"Git"->"Git Bash",会弹出 Git 命令窗口,你可以在该窗口进行 Git 操作。

用户信息
配置个人的用户名称和电子邮件地址:

$ git config --global user.name "runoob"
$ git config --global user.email test@runoob.com

如果用了 --global 选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的项目都会默认使用这里配置的用户信息。

如果要在某个特定的项目中使用其他名字或者电邮,只要去掉 --global 选项重新配置即可,新的设定保存在当前项目的 .git/config 文件里。

1.3、Git 基本原理

GIT有以下
工作区:就是你在电脑里能看到的目录。
暂存区:英文叫stage, 或index。一般存放在 ".git目录下" 下的index文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
版本库:工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。


1352126739_7909.jpg

图中左侧为工作区,右侧为版本库。在版本库中标记为 "index" 的区域是暂存区(stage, index),标记为 "master" 的是 master 分支所代表的目录树。

图中我们可以看出此时 "HEAD" 实际是指向 master 分支的一个"游标"。所以图示的命令中出现 HEAD 的地方可以用 master 来替换。

图中的 objects 标识的区域为 Git 的对象库,实际位于 ".git/objects" 目录下,里面包含了创建的各种对象及内容。

当对工作区修改(或新增)的文件执行 "git add" 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。

当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。

当执行 "git reset HEAD" 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。

当执行 "git rm --cached <file>" 命令时,会直接从暂存区删除文件,工作区则不做出改变。

当执行 "git checkout ." 或者 "git checkout -- <file>" 命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动。

当执行 "git checkout HEAD ." 或者 "git checkout HEAD <file>" 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。

2、Git 基本操作

2.1 、创建新仓库

创建新文件夹,打开,然后执行

    git init

以创建新的 git 仓库。

2.2 、检出仓库

执行如下命令以创建一个本地仓库的克隆版本:

    git clone /path/to/repository 

如果是远端服务器上的仓库,你的命令会是这个样子:

    git clone username@host:/path/to/repository
2.3 、添加和提交

你可以提出更改(把它们添加到暂存区),使用如下命令:

    git add <filename>
    git add *

这是 git 基本工作流程的第一步;使用如下命令以实际提交改动:

    git commit -m "代码提交信息"

现在,你的改动已经提交到了 HEAD,但是还没到你的远端仓库

2.4 、推送改动

你的改动现在已经在本地仓库的 HEAD 中了。执行如下命令以将这些改动提交到远端仓库:

    git push origin master

可以把 master 换成你想要推送的任何分支。

如果你还没有克隆现有仓库,并欲将你的仓库连接到某个远程服务器,你可以使用如下命令添加:

    git remote add origin <server>

如此你就能够将你的改动推送到所添加的服务器上去了。

2.5 、分支

分支是用来将特性开发绝缘开来的。在你创建仓库的时候,master 是“默认的”分支。在其他分支上进行开发,完成后再将它们合并到主分支上。

创建一个叫做“feature_x”的分支,并切换过去:

    git checkout -b feature_x

切换回主分支:

    git checkout master

再把新建的分支删掉:

    git branch -d feature_x

除非你将分支推送到远端仓库,不然该分支就是 不为他人所见的:

    git push origin <branch>
2.5 、分支

分支是用来将特性开发绝缘开来的。在你创建仓库的时候,master 是“默认的”分支。在其他分支上进行开发,完成后再将它们合并到主分支上。

创建一个叫做“feature_x”的分支,并切换过去:

    git checkout -b feature_x

切换回主分支:

    git checkout master

再把新建的分支删掉:

    git branch -d feature_x

除非你将分支推送到远端仓库,不然该分支就是 不为他人所见的:

    git push origin <branch>
2.6、分支更新与合并

要更新你的本地仓库至最新改动,执行:

    git pull

以在你的工作目录中 获取(fetch) 并 合并(merge) 远端的改动。
要合并其他分支到你的当前分支(例如 master),执行:

    git merge <branch>

在这两种情况下,git 都会尝试去自动合并改动。遗憾的是,这可能并非每次都成功,并可能出现冲突(conflicts)。 这时候就需要你修改这些文件来手动合并这些冲突(conflicts)。改完之后,你需要执行如下命令以将它们标记为合并成功:

    git add <filename>

在合并改动之前,你可以使用如下命令预览差异:

    git diff <source_branch> <target_branch>
2.7、标签

通常我们在发布版本的时候会打上标签。这个概念早已存在,在 SVN 中也有。你可以执行如下命令创建一个叫做 1.0.0 的标签:

    git tag 1.0.0 1b2e1d63ff

1b2e1d63ff 是你想要标记的提交 ID 的前 10 位字符。可以使用下列命令获取提交 ID:

    git log

你也可以使用少一点的提交 ID 前几位,只要它的指向具有唯一性。

2.8、替换本地改动

假如你操作失误(当然,这最好永远不要发生),你可以使用如下命令替换掉本地改动:

    git checkout -- <filename>

此命令会使用 HEAD 中的最新内容替换掉你的工作目录中的文件。已添加到暂存区的改动以及新文件都不会受到影响。

假如你想丢弃你在本地的所有改动与提交,可以到服务器上获取最新的版本历史,并将你本地主分支指向它:

    git fetch origin
    git reset --hard origin/master

3、Git 权限控制介绍

3.1、Git角色介绍

首先来了解下,Git 中的五种角色:

角色 解释
Owner Git 系统管理员
Master Git 项目管理员
Developer Git 项目开发人员
Reporter Git 项目测试人员
Guest 访客

相关权限如下:


80458056_1.png

可以将特定branch,例如master、develop等设为保护分支,由代码管理员进行维护,合并开发人员提交的代码。

4、Git 版本管理

4.1、建立项目

Git对于权限控制分为三种级别:私有、内部、公开。
私有:项目访问权限必须明确授权给每个用户,未授权的用户无法访问。
内部:该项目允许已登录的用户访问。
公开:该项目允许任何人访问。

为了保证代码的安全性,所有项目的建立均为私有,同时在管理员面板中关闭内部和公开项目的建立(Restricted visibility levels)。

Git中支持将项目按照group进行划分,例如我们可以建立如下group:
车联网(一级group)\项目A(二级group)

从而将不同的人员分配到不同的group级别,实现不同级别的权限配置。

4.2、分支管理

GIT在技术层面上是一个无中心的分布式版本控制系统,但在管理层面上,保持一个中心版本库(Gitlab)。

一个中心版本库(我们叫它origin)至少包括两个分支,即“主分支(master)”和“开发分支(develop)”

团队成员从主分支(master)获得的都是处于可发布状态的代码,而从开发分支(develop)应该总能够获得最新开发进展的代码。

在一个团队开发协作中有“辅助分支”的概念。“辅助分支”,大体包括如下几类:“管理功能开发”的分支、“帮助构建可发布代码”的分支、“可以便捷的修复发布版本关键BUG”的分支,等等。“辅助分支”的最大特点就是“生命周期十分有限”,完成使命后即可被清除。

“辅助分支”分为三类,我们称之为“Feature branches”,“Release branches”,“Hotfix branches”。

下图就是整个版本管理的生命周期:

4.2.1、 Feature branches

“Feature branches”,起源于develop分支,最终也会归于develop分支。

“Feature branches”常用于开发一个独立的新功能,且其最终的结局必然只有两个,其一是合并入“develop”分支,其二是被抛弃。最典型的“Fearture branches”一定是存在于团队开发者那里,而不应该是“中心版本库”中。

“Feature branches”起源于“develop”分支,实现方法是:

git checkout -b myfeature develop

“Feature branches”最终将在开发完成后合并到“develop”分支,实现方式是:

git checkout devleop

git merge --no-ff myfeature

(--no-ff,即not fast forward,其作用是:要求git merge即使在fast forward条件下也要产生一个新的merge commit)

(此处,要求采用--no-ff的方式进行分支合并,其目的在于,希望保持原有“Feature branches”整个提交链的完整性)

git branch -d myfeature

git push origin develop

4.2.2、 Release branch

“Release branch”,起源于develop分支,最终归于“develop”或“master”分支。这类分支建议命名为“release-*”

“Relase branch”通常负责“短期的发布前准备工作”、“小bug的修复工作”、“版本号等元信息的准备工作”。与此同时,“develop”分支又可以承接下一个新功能的开发工作了。

“Release branch”产生新提交的最好时机是“develop”分支已经基本到达预期的状态,至少希望新功能已经完全从“Feature branches”合并到“develop”分支了。

创建“Release branches”,方法是:

git checkout -b release-1.2 develop

./bump-version.sh 1.2 (这个脚本用于将代码所有涉及版本信息的地方都统一修改到1.2,另外,需要用户根据自己的项目去编写适合的bump-version.sh)

git commit -a -m "Bumped version number to 1.2"

在一段短时间内,在“Release branches”上,我们可以继续修复bug。在此阶段,严禁新功能的并入,新功能应该是被合并到“develop”分支的。

经过若干bug修复后,“Release branches”上的代码已经达到可发布状态,此时,需要完成三个动作:第一是将“Release branches”合并到“master”分支,第二是一定要为master上的这个新提交打TAG(记录里程碑),第三是要将“Release branches”合并回“develop”分支。

git checkout master

git merge --no-ff release-1.2

git tag -a 1.2 (使用-u/-s/-a参数会创建tag对象,而非软tag)

git checkout develop

git merge --no-ff release-1.2

git branch -d release-1.2
4.2.3、 Hotfix branches

“Hotfix branches”源于“master”,归于“develop”或“master”,通常命名为“hotfix-*”

“Hotfix branches”类似于“Release branch”,但产生此分支总是非预期的关键BUG。

建议设立“Hotfix branches”的原因是:希望避免“develop分支”新功能的开发必须为BUG修复让路的情况。

建立“Hotfix branches”,方法是:

git checkout -b hotfix-1.2.1 master

./bump-version.sh 1.2.1

git commit -a -m "Bumpt version to 1.2.1" (然后可以开始问题修复工作)

git commit -m "Fixed severe production problem" (在问题修复后,进行第二次提交)

BUG修复后,需要将“Hotfix branches”合并回“master”分支,同时也需要合并回“develop”分支,方法是:

git checkout master

git merge --no-ff hotfix-1.2.1

git tag -a 1.2.1

git checkout develop

git merge --no-ff hotfix-1.2.1

git branch -d hotfix-1.2.1

5、操作流程

角色 权限 解释
项目经理 Owner 分支管理
开发人员 Developer feature、hotfix、release代码开发
代码管理员 Master 代码merge
测试人员 Reporter 测试

下面我们就在测试环境,进行一次实战演练。
如下是涉及到的角色和权限:

角色 权限 解释
项目经理 Owner 分支管理
开发人员 Developer feature、hotfix、release代码开发
代码管理员 Master 代码merge
测试人员 Reporter 测试

首先项目经理新建group和子group,接着在group下新建了一个项目project

新建projcet.png

项目经理 给开发人员分配权限。
添加权限.png

为了测试我们通过控制台,由项目经理上传一个文件方便创建分支。

默认分支.png

可以看到,默认会有一个master分支。由项目经理生成develop分支。

拉取master分支.png

将这两个分支设置为只能由项目经理(或者由其他专人进行,后续称为代码管理员)merge。

只能由master管理权限.png

然后项目经理生成两个新分支feature1,feature2,由两个开发人员进行开发。

生成feature1.png

两个开发人员各自对自己的feature进行修改后,提交merge request。

提交merge申请.png

代码管理员进行两个feature源码merge,如果有冲突代码,需要进行冲突解决之后才能merge成功。

feature均开发完成之后项目经理从develop中拉出release进行测试。测试过程中release分支如果有bug产生,开发人员进行修复之后,代码管理员将修改的代码merge回develop。

release版本在测试完毕后,代码管理员将release代码merge到master,同时打上tag1.0。

1.0tag.png

tag1.0可用来进行生产发布。如果生产版本有问题,从对应版本的tag上拉出hotfix分支进行修复之后在hotfix分支上进行测试,完毕之后merge回develop和master。

6、配置SSH免密登陆

为了防止所有人或者是登陆用户能获取到源码,目前的项目都设置为private,这样只有经过授权的用户(项目小组成员)才能clone代码,下面介绍如何使用ssh进行免密登陆。

6.1 、生成免密文件

确保本机已经安装了Git,右键鼠标,选中 “Git Bash here”,当然你也可以在windows的 “开始”--->“所以程序”,或者安装目录、快速搜索打开它。

windows下需要在用户目录下创建.ssh文件夹, mkdir .ssh。

cd .ssh
git config --global user.name "name" 
git config --global user.email "email"  

ssh-keygen -t rsa -C "username"

username是git账号,同时设置全局名字和邮箱。
连续三次回车之后,在.ssh文件夹下会生成ssh秘钥文件。

最后得到了两个文件:id_rsa和id_rsa.pub

打开id_rsa.pub,复制里面的文字。

6.2 、git网站上配置秘钥

选择个人设置。


设置免密1.png
设置免密2.png

点击add key,即可设置成功。

6.3 、测试
ssh git@gitlab.com 

将gitlab.com替换成你所用git的host。
看到welcome to gitlab等字样就显示成功了。

参考资料
GIT分支管理是一门艺术 http://roclinux.cn/?p=2129#comments
Git 教程 http://www.runoob.com/git/git-tutorial.html

技术管理
Web note ad 1