GIT代码管理系统使用手册

版权说明:本文为博主原创,如果转载请注明来源。作为学习笔记,不能保证所有知识点是完全正确以及表达无误,用于生产环境配置时请斟酌。如有错误或建议请联系。侵删联系:linuxops@qq.com。感谢各位!

2018年10月29号更新

前言

在第一期的GIT培训中,整理了一些GIT常用的命令和开发的流程,但是培训只能针对在场的人进行传播,三三两两新人入职也没有办法实时开展培训,第一期的培训整理的PPT也不是太完善,所以写了这一份手册,以便于大家随时查阅。

从第一期培训到现在也已经过去了一年多,这份文档也更新到3.0版本,这个版本推翻了之前的结构,也更加丰富了内容。

福信富通代码管理系统使用规则

在开始学习git之前我们先了解以下福信富通代码管理系统的规则约定

福信富通代码管理系统地址为:https://git.fxft.net

代码托管系统仅限于福信富通内部的代码管理使用,为了代码的安全和规范开发的流程,我们做以下的规则约定:

关于帐号:

  • 各位无法创建帐号,需要使用代码托管系统需要联系运维创建。
  • 也无法修改帐号中的用户名自定义名称邮箱这三个个字段信息。
  • 帐号和企业邮箱一致,如果没有企业邮请找人资申请。

关于仓库:

  • 仅开放SSH的方式使用代码库。
  • 为了安全,已经对master分支进行了保护,只有授权人员才能对master进行push操作,各组小组长拥有master权限。
  • master分支对所有有仓库权限的人都有pull权限。

关于开发流程:

  • 开发者 checkout master到本地的新分支。
  • 在本地的新分支编写代码,编写好后推送到服务器保存。
  • 如果需要发布代码,通知小组长合并代码(不建议使用使用web管理页面发起合并请求)
  • 小组长合并开发者合并代码到master。
  • 如果需要发布版本,小组需要在master的commit上创建tag,并pish到git服务器

什么是GIT?

Git是一个开源的分布式版本控制系统,可以有效、高速的处理从很小到非常大的项目版本管理。

GIT在创建的初衷是为了管理Linux的内核代码,在2005年之前,Linux的内核代码被一款商业的版本控制系统BitKeeper管理着,BitKeep东家BitMover公司出于人道主义精神,授权Linux社区免费使用这个版本控制系统。

但是程序员圈就是一个江湖,都会有一些江湖习气,开发Samba的Andrew试图破解BitKeeper的协议,被BitMover公司发现了,于是BitMover公司怒了,要收回Linux社区的免费使用权。

Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!一个月之内,Linux系统的源码已经由Git管理了!

为什么要使用GIT?

目前市面上代码管理系统大概分为两类,一类是以git为代表的分布式代码管理系统,另一类是以SVN为代表的集中式代码管理系统。

GIT不仅仅是个版本控制系统,它也是个内容管理系统(CMS),工作管理系统等。

如果你是一个具有使用SVN背景的人,你需要做一定的思想转换,来适应GIT提供的一些概念和特征。

Git 与 SVN 区别点:

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

分布式代码管理系统无需实时联网、没有中央服务器、每个开发机(库)都是一个完整的库,这都是分布式的非常好的优点,但是相比SVN这些集中式代码管理系统在权限上就显得很弱,无法像SVN那样精确控制每一个文件的权限。

除了权限控制的弱点以外,GIT的强大的分支管理、灵活的Commit、TAG标签、灵活的撤销回退等等功能足够吸引我们了。

市面上基于GIT的代码托管服务

市面上有很多基于GIT的代码托管服务,其中最大最著名的当属GITHUB了,我们来看一下常见的几个服务提供商。

提供商 说明
GITHUB 私有仓库必须要付费
因为众所周知的原因,访问速度慢。
码云 免费有5个用户限制,总共5G容量。单项目1G空间。服务不稳定。
Coding 价格昂贵。
阿里云 完全免费。速度快。不限制团队人数、不限制项目数量。
当个项目上限1G。可以创建私有仓库,50G免费的空间。

我司之前使用的是阿里云的CODE,但是因为有50G和单个项目1G的限制,另外受阿里云可能商业收费的影响,我们现在已经将代码迁移到了自建的GOGS上。

安装GIT

在使用Git前我们需要先安装 Git。Git 目前支持 Linux/Unix、Solaris、Mac和 Windows 平台上运行。

Git 各平台安装包下载地址为:http://git-scm.com/downloads

Linux 平台上安装

Git 的工作需要调用 curl,zlib,openssl,expat,libiconv 等库的代码,所以需要先安装这些依赖工具。

在有 yum 的系统上(比如 Fedora)或者有 apt-get 的系统上(比如 Debian 体系),可以用下面的命令安装:

各 Linux 系统可以很简单多使用其安装包管理工具进行安装:

Debian/Ubuntu

$ apt-get install libcurl4-gnutls-dev libexpat1-dev gettext \
  libz-dev libssl-dev

$ apt-get install git-core

$ git --version
git version 1.8.3.1

Centos/RedHat

$ yum install curl-devel expat-devel gettext-devel \
  openssl-devel zlib-devel

$ yum -y install git-core

$ git --version
git version 1.8.3.1

Windows 平台上安装

在 Windows 平台上安装 Git 同样轻松,下载EXE安装包,点击运行一直下一步即可。点击下载2.19.1安装包

windows安装

安装完成后在任意一个文件夹空白处右击会出现一个 Git Bash Here 的选项,这个选项会快速打开GIT命令行,并且进入到当前目录.

windows安装

GIT的基本概念

在使用GIT之前,我们先来了解一下GIT再本地仓库中的三种状态的概念

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

下面这个图展示了工作区、版本库中的暂存区和版本库之间的关系:

GIT工作区、暂存区、版本库的关系

上图中左侧为工作区,右侧为版本库。在版本库中标记为 "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 " 命令时,会直接从暂存区删除文件,工作区则不做出改变。

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

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

简单理解为:

工作区是你编写代码操作的文件和文件夹的磁盘空间。

暂存区是暂时将工作区的文件保存起来的空间,这个空间位于./git的隐藏文件夹中

仓库是最终保存代码的地方,仓库的只能前进不能后退,比如你不能删除仓库中的某一个提交。

GIT的使用

无论是哪一个平台的客户端,GIT的命令都是一样的,操作也是一样的,windows客户端不仅仅提供了命令行,也提供了一个GUI界面,本手册只演示linux下的命令行使用方式。

全局配置

Git会查找三个地方的配置文件,分别为"/etc/gitconfig"(系统配置)、"~/.gitconfig"或者"~/.config/git/config"(用户全局配置)、".git/config"(本地仓库配置),这三处配置文件按照顺序查找,最新找的哪个配置会替换比较早查到的配置。

Git的配置文件均是文本,可以通过vim直接修改,只要配置项合法即可。当然Git也提供了一个命令来配置,我们来看一下修改全局配置中的邮箱和用户名:

git config --global user.name "Linux" #设置用户名
git config --global user.email linuxops@qq.com #设置邮箱

以上的全局配置会被写入到"~/.gitconfig" 文件中,我们来看一下这个文件:

linuxops@deepin:~$cat ~/.gitconfig 
[user]
    email = linuxops@qq.com
    name = Linux
[core]
    editor = vim
linuxops@deepin:~$

全局配置项中我们只介绍设置邮箱和用户名,其他诸如配置默认编辑器、代码着色等等不在这里介绍了,使用默认的即可。

配置邮箱和用户名是必须的,Git如果没有找到你的邮箱和用户名会出现提示,当然你也可以在本地仓库中配置不同的邮箱和用户名。不过为了管理方便,这个用户名要配置为分配给你的GOGS的用户名。

开始一个项目

对于一个新的项目,我们可以使用git init来初始化一个库,也可以使用git clone来克隆一个已经存在的库,因为我们的规定,再项目开始之前都会创建并初始化好了仓库,所以使用git clone即可。

git clone

我们使用 git clone 从现有 Git 仓库中拷贝项目。

克隆仓库的命令格式为:

git clone <repo>

如果我们需要克隆到指定的目录,可以使用以下命令格式:

git clone <repo> <directory>

参数说明:

  • repo:Git 仓库。
  • directory:本地目录。

比如,要克隆 Ruby 语言的 Git 代码仓库 Grit,可以用下面的命令:

$ git clone git://github.com/schacon/grit.git

执行该命令后,会在当前目录下创建一个名为grit的目录,其中包含一个.git 的目录,用于保存下载下来的所有版本记录。

如果要自己定义要新建的项目目录名称,可以在上面的命令末尾指定新的名字:

$ git clone git://github.com/schacon/grit.git mygrit

一般项目开始之前都会初始化好了仓库,我们使用clone即可,如果想学习git init的使用,请往下看

git init

Git 使用 git init 命令来初始化一个 Git 仓库,Git 的很多命令都需要在 Git 的仓库中运行,所以 git init 是使用 Git 的第一个命令。

在执行完成 git init 命令后,Git 仓库会生成一个 .git 目录,该目录包含了资源的所有元数据,其他的项目目录保持不变。

使用当前目录作为Git仓库,我们只需使它初始化。

git init

该命令执行完后会在当前目录生成一个 .git 目录。

使用我们指定目录作为Git仓库。

git init newrepo

初始化后,会在 newrepo 目录下会出现一个名为 .git 的目录,所有 Git 需要的数据和资源都存放在这个目录中。

如果当前目录下有几个文件想要纳入版本控制,需要先用 git add 命令告诉 Git 开始对这些文件进行跟踪,然后提交:

$ git add *.c
$ git add README
$ git commit -m '初始化项目版本'

以上命令将目录下以 .c 结尾及 README 文件提交到仓库中。

提交到暂存区

项目clone到本地,可以开始编写代码的工作了,在编写好代码后,我们要将代码保存到暂存区。

git add

git add 命令可将该文件添加到缓存,下面介绍一下git add的常用的三个参数:

  • git add .:他会监控工作区的状态树,使用它会把工作时的所有变化提交到暂存区,包括文件内容修改(modified)以及新文件(new),但不包括被删除的文件(注意git add后面有一个英文的点)。
  • git add -u:他仅监控已经被add的文件(即tracked file),他会将被修改的文件提交到暂存区。git add -u不会提交新文件(untracked file)。(git add --update的缩写)
  • git add -A:是上面两个功能的合集(git add --all的缩写)

GIT_ADD

如上图,git add命令并不会提示什么,如果需要查看暂存区的状态,需要用到git status命令,这个命令会给出git的状态信息。

git的命令提示和补全也是很强大的,当你在敲错命令或者有命令关联的时候会给出提示,例如上图给出了use "git reset HEAD <file>..." to unstage的提示

暂存区提交到本地仓库

代码编写到一定时候,修改了bug或者新增了功能,需要提交仓库的时候我们可以使用git commit -m messgae的命令。

git commit –m fix:修改了登录页面错误:Git commit 必须要指定一个message,messge可以看着是是一个说明。如果只运行 git commit 密令,会跳出窗口让你输入message信息,可以使用 –m 来直接输入message信息。 要养成良好的习惯,message的编写一定要简单易懂,不要使用无意义的字符,不如“kkk”之类的

如果直接使用git commit命令,会跳出编辑框,让你输入message信息才能提交,操作和vim的命令一样。 如果是通过 git commit -m messgae指定信息,那么message可以不用加引号。

GIT_ADD

git中只能将暂存区的内容提交到仓库,工作区的内容无法直接提交到仓库。

提交到远程仓库

通过commit提交的代码只是保存再本地的仓库中,因为git是分布式的,每一个本地库都是一个完整的仓库,而我们需要协同开发,所以要有一台服务器保存每一个开发者的代码,一来可以方便快捷实现协同开发,另一个统一管理代码,和GITHUB一样,GOGS也是这么一个系统。

commit以后,我们需要通过 git push 命令才能将代码推送到远程服务器上。

GIT_PUSH

如果只是运行git push,其实push的是默认的远程库,在git中默认的远程仓库名称是origin,所以git push命令等同于git push origin。如果你有多个远程仓库,也指定远程仓库的名称,一般再我们的开发中不会出现多个远程仓库的情况,所以不展开说明。

同步远程到本地

在远程服务器有修改的时候,我们可能需要同步远程的服务器,否则无法GIT认为版本有差异,拒绝PUSH

git pull:无论本地仓库处于哪一种状态,都可以通过git pull 命令拉取服务器的一切信息。包括 分支信息、tag信息等等所有的信息。 假如,你在A电脑上操作,然后同步到了远程服务器,然后需要在B电脑上编辑代码,就需要先pull代码到B电脑,以保持本地仓库信息和远程仓库信息的一致。

GIT_PULL

回滚和重置

GIT是一款版本控制软件,既然有版本,那么肯定是可以做回滚的。人生总有个别时候会后悔嘛,GIT为你实现了后悔药的功能。

无论处于哪一个版本,均可以恢复到指定的状态。

git checkout 常用命令如下:

  • git checkout -- hello.txt 将最近的一次commit或者add的版本覆盖到工作目录。
  • git checkout . 检出当前目录下所有的tree,修改文件名的文件将会保存已经修改的,检出的时候创建原来的文件。
  • git checkout branchName 切换到本地存在的分支
  • git checkout tag_name 检出指定tag,检出指定tag,指针将会偏离分支,tag不属于任何分支,也不允许修改(检出的文件修改后不允许push的)
  • git checkout -b newbranch tagname 以tag为基础创建新分支

git reset 常用命令如下:

  • git reset --hard [commit hash]此命令将回退到买一个commit的状态,回退完毕以后,在此commit之后的所有的状态都将被删除。
  • git reset --soft [commit hash]此命令将本地仓库中的某次提交恢复到暂存区,其他的所有的信息将会被保留。
  • git reset --mixed [commit hash]此命令将本地仓库中的某次提交直接恢复到工作区,其他的所有的信息将会被保留

按照几种reset使用方式,无疑--hard是危险的。但是即便是这样,远程的仓库信息是不会改变的,如果操作失误,可以通过git pull来同步服务器的信息,但是之前所有还没有提交的更改将会永远找不到。

分支查看

  • git branch #查看本地分支
  • git branch -r #查看远端分支
  • git branch -a #查看所有分支,包括本地和远程的
  • git branch –D #删除本地分支

任何查看分支的命令打印出来的结果都有一个加*的分支,这个分支就是当前分支。

GIT_PULL

分支创建删除

  • git branch <user_branch_name> #在本地创建一个新分支,但是并没有切换到此分支上
  • git checkout -b <user_branch_name> #在本地创建一个新分支,并且立即切换到这个分支,分支并没有提交,可以直接将工作空间的文件提交到此分支
  • git checkout -b newLocalBranch origin/branchName #创建本地分支、切换到此分支并且拉取远程分支代码(这种方式是我们经常用到的)
  • git branck –d branck_name 删除本地的分支,强制删除没有被合并过的分支,可以使用-D
  • git push origin :remote_branch 删除远程分支

GIT_PULL

分支合并

合并本地分支: 合并分支的思想是:将指定分支合并至当前分支。 例如:将dev分支合并到master分支 1、git checkout master #切换到master分支 2、git merge dev –m m1 #将dev分支合并至master分支

GIT_PULL

合并分支这个功能非常重要,在我们协同开发的过程需要经常使用分支合并。 分支合并的过程可能会产生冲突,这些冲突需要手动区解决,然后才能提交。 关于冲突解决下面会介绍。

推送分支到远程

推送本地分支到远端:

  • git push #远程已经有了分支并且建立了关联,将当前分支推送到已经关联的分支。如果没有此远程分支或者没有关联的远程分支,那么会报错,可以通过 git push --set-upstream origin remote_branch_name 命令来关联(远程没有分支会自动创建)。
  • git push origin remote_branch_nam #当前分支推送到远程分支,如果远程没有此分支,那么将创建,创建分支后并不会关联到本地,请使用git push --set-upstream origin remote_branch_name 关联

git报错一般都会给出相应的提示,还有给出相应的操作命令。

tag管理

tag也是我们经常使用的功能,对于一个版本的迭代,我们可以使用tag来管理。 tag只是一个独立于分支的一个指针,它必须要指向某一个commit

tag查看:

  • 通过 git tag 可以查看本地所有tag标签
  • 通过 git show tag_name 查看指定tag信息

tag创建:

  • git tag -a v0.1.2 -m “0.1.2版本” #在当前分支的最新的commit上创建tag
  • git tag -a v0.1.1 –m “0.1.1版本” 9fbc3d0#在指定的commit上创建标签
  • git tag -d v0.1.2 # 删除标签

tag发布: 通常的git push不会将标签对象提交到git服务器,我们需要进行显式的操作:

  • git push origin v0.1.2 # 将v0.1.2标签提交到git服务器
  • git push origin –tags # 将本地所有标签一次性提交到git服务器

.gitignore文件的使用

在git中如果想忽略掉某个文件,不让这个文件提交到版本库中,可以使用修改根目录中 .gitignore 文件的方法(如无,则需自己手工建立此文件)。这个文件每一行保存了一个匹配的规则例如:

# 此为注释 – 将被 Git 忽略
*.a       # 忽略所有 .a 结尾的文件
!lib.a    # 但 lib.a 除外
/TODO     # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
build/    # 忽略 build/ 目录下的所有文件
doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt

.gitignore文件可以在git的任何一级目录中,只对当前目录以及子目录生效。

.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。那么解决方法就是先把本地缓存删除(改变成未track状态),然后再提交:

git rm -r --cached 。
git add 。
git commit -m 'update .gitignore'

通常,需要忽略日志文件等等无用的信息,以防止仓库过大。在必要的时候也需要忽略配置文件,通常在发布正式环境的时候配置是不允许放在git仓库中的。

git信息查看

  • git log 可以查看log、每次的提交hash和提交说明
  • git status:可以列出当前目录所有还没有被git管理的文件和被git管理且被修改但还未提交(git commit)的文件
  • git config –local -l:查看仓库级的config:
  • git config –global -l:查看全局级的config:
  • git config –system -:查看系统级的config:

冲突解决

无论是在pull或者merge,都有可能造成冲突。 在冲突产生后,可以通过git status查看冲突的文件。 再冲突文件中,git会标注冲突的行,例如:

<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
 please contact us at support@github.com
</div>
>>>>>>> iss53:index.html

冲突的代码会以<<<<<<< HEAD ======= >>>>>>>标注,我们需要手动选择保留哪一段代码,删除不需要代码即可。

GOGS的使用

说到自建代码管理系统,首先想到的是gitlab,gitlab是基于ruby开发的一套功能丰富的代码管理系统,但是gitlab资源消耗异常大,在低配置的服务器中无法支撑大用户量的使用,安装维护也异常麻烦。

Gogs是基于go语言开发的开源代码管理系统,go语言有其天生的高并发高性能的特点,在低配置的服务器中也能支持大用户量愉快的玩耍,Gogs起步晚,功能没有gitlab丰富,但是提供了基本的功能,并且安装维护比gitlab更为简单方便,在我们的评估了gogs的功能以后得出结论完全符合我司的需要。

代码管理系统地址:https://git.fxft.net 通过分配你给帐号密码即可登录。

其他的功能不在这里展开,我们主要讲一下SSH的使用。

在众多的代码托管系统中,都提供了两种连接方式,一种是HTTPS的,一种是SSH的。 HTTPS每次的连接都需要鉴权,而SSH不需要,另外HTTPS有上传大小和超时的限制,SSH没有上传大小的限制。 所以在实际的使用中,我们更建议大家使用SSH连接。

配置SSH

配置SSH很简单,只要再开发机上生成SSHKEY,然后将公钥复制到GOGS的SSH密钥配置中即可。

1、生成SSHKEY

在windows中,通过$ ssh-keygen.exe 一路回车即可生产,密钥文件保存在用户目录下的.ssh文件夹中。

例如下图:

GIT_PULL

用文本编辑器打开id_rsa.pub文件,将内容完整复制下来。

2、gogs设置SSH公钥

登录GOGS,点击头像->用户设置—>SSH密钥->增加密钥

GIT_PULL

标记一个名称,将复制好的id_rsa.pub内容粘帖到密钥内容上,确定即可。

添加好了,你的开发机就可以使用SSH连接了。