GIT实战

作者: 阿辉_2186 | 来源:发表于2020-09-16 22:07 被阅读0次

    git实战

    • git与svn的区别
    • git核心命令使用
    • git底层实现原理剖析
    • 基于git通信协议搭建git私服
    • 基于gogs搭建企业git私服

    git基础概念

    git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。git 是 Linus Torvalds为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

    image-20191212195307999.png

    git与svn的区别

    • 存储方式不同
    • 使用方式不同
    • 管理模式不同
    存储方式不同

    git把内容按元数据方式存储,类似k/v数据库,而svn是按文件存储

    git存储过程演示

    $ git init fox
    Initialized empty git repository in D:/git/fox/.git/
    $ cd fox
    $ echo 'hello world' >> README.MF
    
    $ git hash-object -w README.MF
    warning: LF will be replaced by CRLF in README.MF.
    The file will have its original line endings in your working directory.
    3b18e512dba79e4c8300dd08aeb37f8e728b8dad
    
    $ git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad
    hello world
    
    使用方式不同

    从本地把文件推送远程服务,svn只需要commit,而git需要 add、commit、push 三个步骤

    • svn使用过程
    image-20191203160140984.png
    • git使用过程
    image-20191203162120940.png
    管理模式不同

    git 是一个分布式的版本管理系统,而要svn是一个远程集中式的管理系统

    • 集中式
    image-20191203162616231.png
    • 分布式
    image-20191203192803969.png

    git核心命令

    git 客户端安装

    官方客户端: https://git-scm.com/downloads

    其它客户端:https://tortoisegit.org/download/

    文档: https://www.git-scm.com/docs

    centos7 安装git

    # yum安装
    yum install -y git
    

    源码编译安装

    # 1.安装依赖环境
    yum -y install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker
    
    # 2.下载并解压源码
    $ wget https://github.com/git/git/archive/v2.3.0.zip
    $ unzip v2.3.0.zip
    $ cd git-2.3.0
    
    #3 编译 安装(如果没有权限就加上sudo)
    make prefix=/usr/local/git all
    make prefix=/usr/local/git install
    
    #4、添加环境变量
    vim /etc/profile
    export PATH=/usr/local/git/bin:$PATH
    source /etc/profile
    
    #如果成功显示版本号表示添加成功
    git --version
    git version 2.3.0
    

    Git配置

    #Git安装完之后,需做最后一步配置。打开git bash,分别执行以下两句命令
    git config --global user.name "username"
    git config --global user.email "xxxx@163.com"
    #git 自动记住用户和密码操作
    git config --global credential.helper store
    #查看配置信息
    git config -l
    
    cat ~/.gitconfig
    

    git的基本使用

    完整模拟从项目添加到push 过程

    • 创建项目

    • 初始化git仓库

    • 提交文件

    • 远程关联

    • push 至远程仓库

    初始化git仓库
    #基于远程仓库克隆至本地
    $ git clone <remote_url>
    
    # 将指定目录初始化为git本地仓库
    $ git init <directory>
    
    查看仓库状态
    # 查看本地仓库的状态
    $ git status
    # 以简短模式查看本地仓库的状态
    # 会显示两列,第一列是文件的状态,第二列是对应的文件
    # 文件状态:A 新增,M 修改,D 删除,?? 未添加到git中
    $ git status -s
    

    文件的状态变化周期

    工作目录下的每一个文件都有两种状态:已跟踪或未跟踪。 已跟踪的文件是指那些被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后,它们的状态可能处于未修改,已修改或已放入暂存区。 工作目录中除已跟踪文件以外的所有其它文件都属于未跟踪文件,它们既不存在于上次快照的记录中,也没有放入暂存区。 初次克隆某个仓库的时候,工作目录中的所有文件都属于已跟踪文件,并处于未修改状态。

    image-20191209141635967.png
    本地添加
    #添加指定文件至暂存区
    $ git add <fileName>
    # 添加所有修改、已删除的文件到暂存区中
    $ git add -u <directory>
    #添加所有修改、已删除、新增的文件到暂存区中,省略 <文件路径> 即为当前目录
    $ git add -A <directory>
    
    # 当需要删除暂存区或分支上的文件,同时工作区不需要这个文件
    $ git rm <directory>
    # 当需要删除暂存区或分支上的文件,同时工作区需要这个文件,但是不需要被版本控制
    $ git rm --cached <file>
    
    
    本地提交
    # 把暂存区中的文件提交到本地仓库中并添加描述信息
    $ git commit <file> -m '提交的描述信息'
    # 把所有修改、已删除的文件提交到本地仓库中
    # 不包括未被版本库跟踪的文件,等同于先调用了 "git add -u"
    $ git commit -am '提交的描述信息'
    
    
    远程仓库管理
    # 列出已经存在的远程仓库
    $ git remote
    # 列出远程仓库的详细信息,在别名后面列出URL地址
    $ git remote -v
    #添加远程仓库地址
    $ git remote add origin http:xxx.xxx
    #删除指定名称的远程仓库origin
    $ git remote remove origin 
    
    #把本地仓库的提交推送到远程仓库
    #上传新分支至远程
    $ git push --set-upstream origin master 
    $ git push -u origin master
    
    #将本地分支与远程建立关联
    $ git branch --track --set-upstream-to=origin/test test
    
    分支管理
    #查看本地分支,当前所在分支以 "*" 标出
    $ git branch
    #查看所有分支
    $ git branch -avv
    #基于当前分支创建一个新分支
    $ git branch <branch name>
    #基于存在的分支创建一个新分支
    $ git branch <branch name> <exist branch>
    #基于远程分支创建一个新分支
    git branch <branch name> origin/master
    #基于提交创建一个新分支
    $ git branch <branch name> <commit id>
    #基于标签创建一个新分支
    $ git branch <branch name> <tag name>
    
    #删除分支
    $ git branch -d {dev}
    #切换分支
    $ git checkout <branch name>
    #合并分支
    $ git merge <merge target>
    #解决冲突,如果因冲突导致自动合并失败,此时 status 为mergeing 状态.
    #需要手动修改后重新提交(commit) 
    
    
    tag管理
    #查看当前
    $ git tag
    #基于分区创建tag
    $ git tag <tag name> <branch name>
    
    # 基于提交创建tag
    $ git tag <tag name> [<commit ID>]
    # 可以指定标签信息
    $ git tag -a <tagname> -m "..."
    
    # 查看标签信息
    $ git show <tagname>
    # 推送一个标签到远程
    $ git push origin <tagname>
    # 删除标签
    $ git tag -d <tagname>
    
    
    日志管理
    #查看当前分支下所有提交日志
    $ git log
    #查看当前分支下所有提交日志
    $ git log {branch}
    # 单行显示日志
    $ git log <dev> --oneline
    # 比较两个版本的区别   master比dev多提交了什么内容
    $ git log dev..master
    
    #以图表的方式显示提交合并网络
    $ git log --pretty=format:'%h %s' --graph
    $ git log --graph --pretty=oneline --abbrev-commit
    
    # 可以查看所有分支的所有操作记录(包括已经被删除的 commit 记录和 reset 的操作)
    $ git reflog
    
    #还原提交记录
    # 回退到某个版本   慎用,之后版本会丢失,借助reflog找回
    # 会将工作区、暂存区、本地仓库的所有提交的文件全都撤销(包括工作区文件,会删除)
    $ git reset --hard <commit ID>
    # 用于将本地仓库文件撤回至工作区 
    $ git reset --mixed <commit ID> 
    
    #反做,如果想撤销之前的某一版本,但是又想保留该目标版本后面的版本,可以使用revert  
    #注意:反做后还需要commit提交
    $ git revert -n  <commit ID>
    $ git commit -am 'revert xxx'
    
    # 撤回revert操作
    $ git revert --abort
    

    git底层原理

    • git存储对象

    • git树对象

    • git提交对象

    • git引用

    git存储对象

    git 是一个内容寻址文件系统,其核心部分是一个简单的键值对数据库(key-value data store),你可以向数据库中插入任意内容,它会返回一个用于取回该值的hash 键。

    # git 键值库中插入数据
    $ echo 'hello world version 1.0' | git hash-object -w --stdin
    e4dc2ded6eb80dbbe38375acd0b409c81e98277d
    
    #基于键获取指定内容
    $ git cat-file -p e4dc2ded6eb80dbbe38375acd0b409c81e98277d
    hello world version 1.0
    
    #相当于 git hash-object -w hello.md
    $ git add hello.md
    
    
    

    git基于该功能 把每个文件的版本中内容都保存在数据库中,当要进行版本回滚的时候就通过其中一个键将其取回并替换。

    模拟演示git 版本写入与回滚过程

    
    # 查找所有的git对象
    $ find .git/objects/ -type f
    # 写入版本1
    $ echo 'hello world version 1.0' > README.MF;git hash-object -w README.MF
    warning: LF will be replaced by CRLF in README.MF.
    The file will have its original line endings in your working directory.
    e4dc2ded6eb80dbbe38375acd0b409c81e98277d
    
    # 写入版本2
    $ echo 'hello world version 2.0' > README.MF;git hash-object -w README.MF
    warning: LF will be replaced by CRLF in README.MF.
    The file will have its original line endings in your working directory.
    a984c1ed3f9a3eceaf4043c5a3b227954621b5ea
    
    # 写入版本3
    $ echo 'hello world version 3.0' > README.MF;git hash-object -w README.MF
    warning: LF will be replaced by CRLF in README.MF.
    The file will have its original line endings in your working directory.
    14f5521ac31e82f0b51ba2d278c6ce185e4a7a9a
    
    # 回滚指定版本
    $ git cat-file -p e4dc2ded6eb80dbbe38375acd0b409c81e98277d > README.MF
    

    git add 其实就是把修改之后的内容 插入到键值库中。当执行 git add README.MF 等同于执行了 git hash-object -w README.MF 把文件写到数据库中。

    git树对象

    树对象解决了文件名存储的问题,它的目的是将多个文件名组织在一起,其内包含多个文件名称与其对应的Key和其它树对象的引用,可以理解成操作系统当中的文件夹,一个文件夹包含多个文件和多个其它文件夹。

    [图片上传失败...(image-be0dc9-1600265206653)]

    每一个分支当中都关联了一个树对像,他存储了当前分支下所有的文件名及对应的 key.

    通过以下命令即可查看

    # 查看commit对象
    $ git cat-file -p 263d8a9463a5be9c8cb6973464fd7408945e20ac
    tree 7ca5aba06a1d353f082de003afb6aec2a334bc2a
    author fox <2763800211@qq.com> 1575524733 +0800
    committer fox <2763800211@qq.com> 1575524733 +0800
    
    commit 1
    
    #查看对象类型
    $ git cat-file -t 263d8a9463a5be9c8cb6973464fd7408945e20ac
    commit
    
    
    #查看tree对象
    $ git cat-file -p master^{tree}
    100644 blob e4dc2ded6eb80dbbe38375acd0b409c81e98277d    README.MF
    100644 blob f2f901d721b1819be1b9874952245ed6d2523d1d    fox.md
    
    

    git提交对象

    一次提交即为当前版本的一个快照,该快照就是通过提交对象保存,其存储的内容为:一个顶级树对象、上一次提交的对象哈希、提交者用户名及邮箱、提交时间戳、提交评论。

    # 查看提交日志
    $ git log master
    commit c631696a799a04dc04187b01a89854cef285b85e (HEAD -> master)
    Author: fox <2763800211@qq.com>
    Date:   Thu Dec 5 14:01:21 2019 +0800
    
        2 commit
    
    commit 263d8a9463a5be9c8cb6973464fd7408945e20ac
    Author: fox <2763800211@qq.com>
    Date:   Thu Dec 5 13:45:33 2019 +0800
    
        commit 1
    
    #查看提交对象信息
    $ git cat-file -p  c631696a799a04dc04187b01a89854cef285b85e
    tree cc0850e551b41927c7aa88e1273bf4cedde9f63e
    parent 263d8a9463a5be9c8cb6973464fd7408945e20ac
    author fox <2763800211@qq.com> 1575525681 +0800
    committer fox <2763800211@qq.com> 1575525681 +0800
    
    2 commit
    
    

    从修改一个文件到提交的过程中会生成三类对象:

    一个内容对象 ==> 存储了文件内容

    树对象(至少一个) ==> 存储了文件名及内容对象的key

    一个提交对象 ==> 存储了树对象的key 及提交评论。

    git引用

    当执行 git branch {branchName} 时创建了一个分支,其本质就是在git 基于指定提交创建了一个引用文件,保存在 .git\refs\heads\ 下。

    # 创建分支
    $ git branch dev 
    # 查看分支引用文件
    $ cat .git\refs\heads\dev
    # 查看分支差异
    git diff dev..master
     
    

    git通信协议

    分布式通信需要有应用协议,应用协议的实现包含编码,解码和远程传输的实现,git支持四种应用协议,分别是Local,http,git,ssh。通过四种协议都可以手动搭建简单的git仓库私服。

    Local(本地协议)

    本地协议可以基于本地文件系统,或者共享(NFS)文件系统进行访问,来实现源码的一个共享,使用Local协议搭建git私服是最轻松的,也是最简单的。

    优点:简单,直接使用了现有的文件权限和网络访问权限,小团队小项目建立一个这样的版本管理系统是非常轻松的一件事。

    缺点:这种协议缺陷就是本身共享文件系统的局限,只能在局域网,而且速度也慢。

    适应场景:小团队,小项目临时搭建版本服务。

    演示本地协议使用方式:

    # 使用目录 /d/git/local 作为git公共仓库,在仓库中创建一个裸项目
    # 祼项目一般用做git服务、非裸项目也可做远程服务,二者区别在于祼项目录中文件无法查看和修改。
    $ git init --bare hello.git
    
    # 克隆项目
    $ git clone /d/git/local/hello.git
    
    # 基于file 协议克隆本地项目
    $ git clone file:///d/git/local/hello.git
    
    

    如果在 URL 开头明确的指定 file://,那么 git 的行为会略有不同。 如果仅是指定路径,git 会尝试使用硬链接(hard link)或直接复制所需要的文件。 如果指定 file://,git 会触发平时用于网路传输资料的进程,传输过来的是打包好的文件,更节约硬盘空间。

    ssh协议

    在Linux中,ssh协议是我们经常用到的。ssh属于Linux里面的一个通信协议,基于ssh在Linux中搭建私服,访问git仓库是不需要做额外的配置的。只需要基于ssh的用户名密码即可。git 支持利用ssh 协议进行通信,这是绝大部分linux、uninx系统都支持的,所以利用该协议架设git版本服务是非常方便的。

    优点:首先ssh 架设相对简单、其次通过 ssh 访问是安全的,另外ssh 协议很高效,在传输前也会尽量压缩数据。

    缺点:权限体系不灵活,必须提供操作系统的帐户密码,哪怕是只需要读取版本。

    适用场景:团队、小项目、临时项目

    演示ssh 协议使用方式:

    git 服务必须先安装到linux 系统上,然后才能使用ssh协议跟git服务进行通信

    # /data/git下创建一个祼项目
    git --bare init hello.git
    
    # 本地基于远程克隆仓库
    git clone root@192.168.3.14:/data/git/hello.git
    cd hello/
    # 添加文件
    echo 'hello world version 1.0' >> README.MF
    # 本地添加、提交、并推送至远程
    git add -A; git commit -am 'commit 1'; git push;
    

    免密码登录配置

    # 开发机器上生成公钥  
    ssh-keygen -t rsa 
    #查看公钥内容
    cat ~/.ssh/id_rsa.pub
    
    #拷贝公钥内容到git服务器的用户目录的.ssh下的authorized_keys文件中
    cd ~/.ssh/
    vim authorized_keys
    

    可能的错误:

    git-upload-pack: command not found

    原因是 ssh 协议下只能访问/usr/bin 下的目录,解决办法如下

    ln -s /usr/local/git/bin/git-upload-pack /usr/bin/git-upload-pack
    ln -s /usr/local/git/bin/git-receive-pack /usr/bin/git-receive-pack
    

    http协议

    git http 协议实现是依懒WEB容器(apache、nginx)及cgi 组件进行通信交互,并利用WEB容器本身权限体系进行授权验证。在git 1.6.6 前只支持http Dumb(哑)协议,该协议只能下载不能提交,通常会配合ssh 协议一起使用,ssh 分配提交帐号,http dumb提供只读帐号。1.6.6 之后git 提供了git-http-backend 的 CGI 用于实现接收远程推送等功能。

    优点:解决了local 与ssh权限验证单一的问题、可基于http url 提供匿名服务,从而可以放到公网上去。而local 与ssh 是很难做到这一点,比如实现一个类似github 这样的网站。

    缺点:架设复杂一些需要部署 WEB服务器,和https 证书之类的配置

    适用场景:大型团队、需要对权限精准控制、需要把服务部署到公网上去

    演示http Dumb 配置与使用

    # /data/git下创建一个祼项目
    git --bare init hello.git
    # 在仓库中加一个钩子,首先进入目录:
    cd  /data/git/hello.git/hooks
    # 修改文件,post-update 当有项目修改的时候,就会触发这个钩子
    # 钩子参考: https://www.git-scm.com/book/zh/v2/%E8%87%AA%E5%AE%9A%E4%B9%89-Git-Git-%E9%92%A9%E5%AD%90
    mv post-update.sample post-udpate
    
    #打包,然后生成web端能够访问的静态文件
    #进入hello.git目录
    git update-server-info
    
    #配置nginx
     server {
            listen       80;
            server_name  localhost git.bat.com;
    
            location / {
                root   /data/git;
            }
     }
     
    #C:\Windows\System32\drivers\etc配置
    192.168.3.14     git.bat.com 
    
    # 本地克隆远程服务
    git clone http://git.bat.com/hello.git 
    
    # 哑协议只能拉取,无法提交
    $ git push
    error: Cannot access URL http://git.bat.com/hello.git/, return code 22
    fatal: git-http-push failed
    error: failed to push some refs to 'http://git.bat.com/hello.git'
    
    

    哑协议只能拉取代码,但是http智能协议可以同时实现拉取和推送。 设置 Smart HTTP 一般只需要在服务器上启用一个 git 自带的名为 git-http-backend 的 CGI 脚本。 该 CGI 脚本将会读取由 git fetch 或 git push 命令向 HTTP URL 发送的请求路径和头部信息,来判断该客户端是否支持 HTTP 通信(不低于 1.6.6 版本的客户端支持此特性)。 如果 CGI 发现该客户端支持智能(Smart)模式,它将会以智能模式与它进行通信,否则它将会回落到哑(Dumb)模式下(因此它可以对某些老的客户端实现向下兼容)。Smart 协议 是基于CGI 配合git git-http-backend 脚本进行使用,配置较复杂,现在一般不会这么去做,而是采用gitlab 、gogs 之类的web管理进行代替

    git协议

    git 协议是包含在 git 里的一个特殊的守护进程,它会监听一个特定的端口(9418),类似于 SSH 服务,但是访问无需任何授权。

    优点:目前,git 协议是 git 使用的网络传输协议里最快的。 如果你的项目有很大的访问量,或者你的项目很庞大并且不需要为写进行用户授权,架设 git 守护进程来提供服务是不错的选择。 它使用与 SSH 相同的数据传输机制,但是省去了加密和授权的开销。

    缺点:git 协议缺点是缺乏授权机制。 而且9418是一个非标准端口,一般防火墙不会开放

    演示git协议的使用:

    yum install -y git-daemon
    # 启动守护进程 ,配置git协议
    nohup git daemon --reuseaddr --base-path=/data/git/ /data/git/ &
    
    # /data/git下创建一个祼项目
    git --bare init hello3.git
    cd hello3.git/
    # 创建一个空文件,表示开放该项目,允许非授权访问
    touch git-daemon-export-ok
    
    #本地克隆远程项目
    git clone git://192.168.3.14:9418/hello3.git
    
    

    git私服搭建

    基于gogs快速搭建企业私有git服务

    gogs 介绍安装

    Gogs 是一款开源的轻量级git web服务,其特点是简单易用完档齐全、国际化做的相当不错。其主要功能如下:

      1. 提供Http 与ssh 两种协议访问源码服务
      1. 提供WEB界面可查看修改源码代码
      1. 提供较完善的权限管理功能、其中包括组织、团队、个人等仓库权限
      1. 提供简单的项目wiki功能
      1. 提供工单管理与里程碑管理。

    下载安装

    官网:https://gogs.io

    下载:https://gogs.io/docs/installation 选择Linux amd64 下载安装

    文档:https://gogs.io/docs/installation/install_from_binary

    wget https://dl.gogs.io/0.11.91/gogs_0.11.91_linux_amd64.tar.gz
    #后台运行
    nohup ./gogs web &
    

    默认端口:3000,初次访问http://<host>:3000 会进到初始化页,进行引导配置。

    数据库类型可以选择SQLite3 ,选择mysql需要mysql5.7以上

    gogs基础配置

    配置手册 https://gogs.io/docs/advanced/configuration_cheat_sheet

    gogs 定时备份与恢复

    备份与恢复
    #查看备份相关参数
    ./gogs backup -h
    
    #默认备份,备份在当前目录
    ./gogs backup 
    
    #参数化备份  --target 输出目录 --database-only 只备份db 
    ./gogs backup --target=./backups --database-only --exclude-repos
    #恢复。执行该命令前要先删除 custom.bak
    ./gogs restore --from=gogs-backup-20191208192026.zip
    
    ./gogs restore --database-only  --from=./backups/gogs-backup-20191208221323.zip --config custom/conf/app.ini
    
    自动备份脚本

    backup.sh内容如下:

    #!/bin/sh -e
    
    gogs_home="/usr/local/soft/gogs/"
    backup_dir="$gogs_home/backups"
    cd `dirname $0`
    
    # 执行备份命令
    ./gogs backup --target=$backup_dir
    echo 'backup sucess'
    
    day=7
    #查找并删除 7天前的备份  
    find $backup_dir -name '*.zip' -mtime +7 -type f |xargs rm -f;
    echo 'delete expire back data!'
    
    添加定时任务

    每天2:00执行备份

    #列出当前用户的crontab
    crontab ‐l
    
    # 打开任务编辑器
    crontab -e
    
    # 输入如下命令 00 02 * * * 每天凌晨2点执行 backup.sh 并输出日志至 backup.log
    #分 时 日 月 星期 command
    00 04 * * * /usr/local/soft/gogs/backup.sh >> /usr/local/soft/gogs/backup.log 2>&1
    
    # 重启crontab
    systemctl restart crond.service
    #查看状态
    systemctl status crond.service
    

    相关文章

      网友评论

          本文标题:GIT实战

          本文链接:https://www.haomeiwen.com/subject/gczhyktx.html