Git分布式版本控制系统

一,企业高效持续集成平台场景介绍

二,GIT分布式版本控制系统

2.1 Git简介

2.1.1 git是什么?

  • Git在Wikipedia上的定义:它是一个免费的、分布式的版本控制工具,或是一个强调了速度快的源代码管理工具。Git最初被Linus Torvalds开发出来用于管理Linux内核的开发。每一个Git的工作目录都是一个完全独立的代码库,并拥有完整的历史记录和版本追踪能力,不依赖 于网络和中心服务器。
  • Git的出现减轻了许多开发者和开源项目对于管理分支代码的压力,由于对分支的良好控制,更鼓励开发者对自己感兴趣的项目做出贡献。其实许多开源项目 包括Linux kernel, Samba, X.org Server, Ruby on Rails,都已经过渡到使用Git作为自己的版本控制工具。可以在任何地点(在上班的地铁 上)提交自己的代码和查看代码版本;可以开许许多多个分支来实践自己的想法,而合并这些分支的开销几乎可以忽略不计。

2.1.2 什么是版本控制呢?

本地版本控制系统:

  • 许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。这么做唯一的好处就是简单。不过坏处也不少:有时候会混淆所在的工作目录,一旦弄错文件丢了数据就没法撤销恢复。
  • 为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异

 

  • 其中最流行的一种叫做 rcs,现今许多计算机系统上都还看得到它的踪影。甚至在流行的 Mac OS X 系统上安装了开发者工具包之后,也可以使用 rcs 命令。它的工作原理基本上就是保存并管理文件补丁(patch)。文件补丁是一种特定格式的文本文件,记录着对应文件修订前后的内容变化。所以,根据每次 修订后的补丁,rcs 可以通过不断打补丁,计算出各个版本的文件内容。

 

集中化的版本控制系统:

  • 接下来人们又遇到一个问题,如何让在不同系统上的开发者协同工作?于是,集中化的版本控制系统( Centralized Version Control Systems,简称 CVCS )应运而生。这类系统,诸如 CVS,Subversion 以及 Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这 已成为版本控制系统的标准做法

 

  • 这种做法带来了许多好处,特别是相较于老式的本地 VCS来说。现在,每个人都可以在一定程度上看到项目中的其他人正在做些什么。而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。

事分两面,有好有坏。这么做最显而易见的缺点是中央服务器的单点故障。如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。要 是中央服务器的磁盘发生故障,碰巧没做备份,或者备份不够及时,就还是会有丢失数据的风险。最坏的情况是彻底丢失整个项目的所有历史更改记录,而被客户端 提取出来的某些快照数据除外,但这样的话依然是个问题,你不能保证所有的数据都已经有人事先完整提取出来过。本地版本控制系统也存在类似问题,只要整个项 目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。

分布式版本控制系统:

  • 于是分布式版本控制系统( Distributed Version Control System,简称 DVCS )面世了。在这类系统中,像 Git,Mercurial,Bazaar 以及 Darcs 等,客户端并不只提取最新版本的文件快照,而是把原始的代码仓库完整地镜像下来。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜 像出来的本地仓库恢复。因为每一次的提取操作,实际上都是一次对代码仓库的完整备份

 

  • 更进一步,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。

 

2.1.3 git的优势在哪?

与同类型版本控制软件:svn,cvs 
SVN===>集中式版本控制系统 
GIT===>分布式版本控制系统

 

实际的例子:

  • 以前我所 在的小组使用SVN作为版本控制工具,当我正在试图增强一个模块,工作做到一半,由于会改变原模块的行为导致代码服务器上许多测试的失败,所以并没有提交 代码。这时候上级对我说,现在有一个很紧急的Bug需要处理, 必须在两个小时内完成。我只好将本地的所有修改diff,并输出成为一个patch文件,然后回滚有关当前任务的所有代码,再开始修改Bug的任务,等到 修改好后,在将patch应用回来。前前后后要完成多个繁琐的步骤,这还不计中间代码发生冲突所要进行的工作量。
  • 可是如果使用Git, 我们只需要开一个分支或者转回到主分支上,就可以随时开始Bug修改的任务,完成之后,只要切换到原来的分支就可以优雅的继续以前的任务。只要你愿意,每 一个新的任务都可以开一个分支,完成后,再将它合并到主分支上,轻松而优雅。
  • 因此,分布式的版本控制系统,在每个使用者电脑上就有一个完整的数据仓库,没有网络依然可以使用Git。当然为了习惯及团队协作,会将本地数据同步到Git服务器或者GitHub等远程代码仓库

 

2.2 Git的安装

2.2.1 Windows安装git客户端

客户端下载地址:https://www.git-scm.com/downloads

 

双击安装包一路下一步即可。

在桌面上创建一个空目录,右键点击目录

 

选择Git Bash Here,进入git命令界面

到此windows的git客户端就安装好了

2.2.2 Linux利用yum安装git客户端

安装环境查看

安装git客户端   yum安装的git版本都是比较低的,想要高版本可以源码安装。

 

Git全局配置

配置git使用用户  配置git使用邮箱    语法高亮      查看全局配置

说明:

如果没有提前设置Git的全局配置,那么在第一次进行代码提交的时候,会要求输入使用者的邮箱和姓名

到此利用Yum安装Linux操作系统的git客户端就安装好了

2.2.3 Linux源码安装git客户端

如果我们想要安装最新版本的git,那么就只能源码包安装了。

回退之前的yum安装

源码安装git-2.9.5.tar.gz

源码编译需要链接git的命令库

至此,利用源码包安装Linux操作系统的git客户端就安装好了

 

2.3 Git的命令入门

  • 工作区 
    • 你建立的本地git项目目录
  • 暂存区 
    • 将工作区里的变更部分(与上一版本不同的部分)暂时存储起来的地方
  • 本地仓库 
    • 在本地创建的git版本仓库,用于提交工作区的变更。
  • 远程仓库 
    • githab,gitlab或者队友机器上所建立的一个仓库

 

主机名

IP

备注

Git01

10.1.1.128

git测试客户端一

Git02

10.1.1.129

git测试客户端二

 

2.3.1 git帮助文档

输入git查看

2.3.2 git init初始化GIT工作目录

 

2.3.3 git add将变更添加进入暂存区

 

git status      查看git工作目录的暂存区状态

2.3.4 git commit将变更从暂存区提交到本地仓库

 

2.3.5 创建github账号,并创建个人github远程仓库

创建完github账号后,我们就可以创建远程仓库了,如下图所示:

2.3.6 git remote用于管理远程仓库

 

1git remote add

添加一个远程仓库的URL 
命令格式:git remote add <仓库的名字> <仓库的URL>

2.3.7 git push将本地仓库的变更推送到远程仓库的某个分支

命令格式: 
git push -u <远程仓库的名字> <远程仓库的某一分支名字>

在Linux上推送本地仓库变更到远程仓库的master分支

 

再次在浏览器进行访问查看你的github地址

 

git remote -v 查看仓库  前一列仓库代号,自己起的,fetch拉取代码,push推送

2.3.8 git clone克隆一个现有仓库到本地

在另一台Git02上来模拟其他客户端进行对远程仓库克隆到本地仓库的操作

 

初始化GIT工作目录并将已有远程仓库克隆到本地

 

修改仓库里的文件内容,并提交变更到本地,推送变更到远程仓库

浏览器打开github查看变更提交情况

2.3.9 git fetch 将远程仓库的变更拉取到本地仓库

在Git01上

查看文件是否修改     没有被修改

 说明:

应用git fetch拉取到本地仓库时,并不修改本地工作目录中的代码

如果要修改,那么需要进行git merge变更合并

 

2.3.10 get checkout检查工作目录代码与本地仓库中的代码的差异

 检查本地工作目录与本地仓库的差异

2.3.11 git merge 将远程仓库的变更,更新到本地工作目录中

2.3.12 git pull 将远程仓库的变更拉取到本地仓库,并更新本地工作目录。

git pull ====> git fetch + git merge

在Git01上对文件进行改动,并推送到github远程仓库 

在Git02上,拉取远程仓库的变更后直接合并进本地仓库的master分支

没有进行分布式更新,一旦产生冲突是修改不了的,所以一般来说,开发都是分两部分进行合并,除非断定没有冲突就会用pull

2.3.13 git mv && git reset 暂存区文件的修改和撤销

 如果文件还没有被添加到暂存区,那么Linux命令直接改名即可

 

变动文件已经添加到了暂存区

 

通过git mv 来给已经添加到暂存区的文件改名     本地文件同时改名了

 

通过git reset 来给已经添加到暂存区的文件撤销掉

2.3.14 git rm 提交文件的删除变更到暂存区

 git add 可以提交新增文件,修改文件的变更到暂存区;

 git rm 则是提交删除文件的变更到暂存区

 

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")

 

2.3.15 git diff 文件对比利器

git diff命令可以将本地工作目录中的文件与本地仓库中的文件进行对比

 

2.3.16 git log 查看git提交历史纪录

  • git log:查看提交历史记录 
    • git log -2 :查看最近几条记录
    • git log -p -1 : -p显示每次提交的内容差异
    • git log --stat -2 : stat简要显示数据增改行数,这样就能看到提交中修改过的内容
    • git log --pretty=oneline :一行显示提交的历史记录

查看最近两条记录

 

显示最近一次提交的内容差异

 

显示提交内容的修改概要

 

用一行显示提交的历史记录

 

2.4 追根溯源-git log

2.4.1 Git还原历史数据

Git服务程序中有一个叫做HEAD的版本指针,当用户申请还原数据时,其实就是将HEAD指针指向到某个特定的提交版本,但是因为Git是分布式版本控制系统,为了避免历史记录冲突,故使用了SHA-1计算出十六进制的哈西字符串来区分每个提交版本,另外默认的HEAD版本指针会指向到最近的一次提交版本记录,而上一个提交版本会叫HEAD^,上上一个版本则会叫做HEAD^^,当然一般会用HEAD~5来表示往上数第五个提交版本。

  • git reset --hard HEAD^ #-->还原历史提交版本上一次
  • git reset --hard 3de15d4 #-->找到历史还原点的SHA-1值后,就可以还原(值不写全,系统会自动匹配)

2.4.2 Git还原未来数据

当我们回滚到历史某个提交版本了以后; 
我们发现我们已经没有在那个版本之后的提交记录了; 
也就是说,我们一旦还原了历史版本,想要再次还原回去,那么就回不去了。 
如此一来,一旦错了。我们怎么办呢?

    • git reflog:查看未来历史更新点

2.4.3 Git的标签使用

前面回滚使用的是一串字符串,又长又难记 
git tag <标签> -m "描述" 
每次提交都可以打一个标签

    • git tag v1.0 : 给当前提交内容打一个标签(方便回滚) 
      • git tag : 查看当前所有的标签
      • git show v1.0 :查看当前1.0版本的详细信息
      • git tag v1.2 -m "描述"
      • git tag -d v1.0 :删除之前的v1.0标签

2.5 gitignore文件

  • 为什么使用.gitignore文件 
    • 大量与项目无关的文件全推到远程仓库上,同步的时候会非常慢,且跟编辑器相关的一些配置推上去之后,别人更新也会受到影响。所以,我们使用该文件,对不必要的文件进行忽略,使其不被git追踪。
    • 一般情况下, .gitignore文件,在项目一开始创建的时候就创建,并推送到远程服务器上。这样大家初次同步项目的时候,就是用到该文件,避免以后,团队成员把与项目无关的文件,传到远程服务器上。
  • gitignore文件匹配规则
    • *.log 表示忽略项目中所有以.log结尾的文件
    • 123?.log 表示忽略项目中所有以123加任意一个字符的文件
    • /error.log 表示忽略根目录下的error.log文件
    • **/java/ 匹配所有java目录下的所有文件
    • !/error.log 表示在前面的匹配规则中,被忽略了的文件,你不想它被忽略,那么就可以在文件前加叹号
     

 

三,GIT分支管理

3.1 分支的结构概述

在实际的项目开发中,尽量保证master分支稳定,仅用于发布新版本,平时不要随便直接修改里面的数据文件。 
那在哪干活呢?干活都在dev分支上。每个人从dev分支创建自己个人分支,开发完合并到dev分支,最后dev分支合并到master分支。 
所以,团队的合作分支看起来会像下图那样。

 

分支管理工作流程: 
在工作中,为了保证master分支稳定,产品经理通常会从master分支上复制一份代码作为dev分支; 
然后成员开发A在从dev分支上复制一份代码叫做michael; 
然后成员开发B再从dev分支上复制一份代码叫做bob; 
平时开发A和开发B推送和拉取代码都在自己的个人分支michael和bob上。 
当一个新功能开发完毕,或者一个bug修改完毕以后。开发人员会先将代码变更推送到自己的个人分支,然后再把个人分支的变更合并到dev分支里; 
当开发经理和测试人员拉取dev分支的代码进行测试以后,如果没问题,那么开发经理会把dev分支的变更合并进master版本; 
最后,由于master版本新增了测试过的新功能,那么就需要进行项目发布或者代码上线了。

3.2 GIT本地分支管理

3.2.1 本地分支的创建与切换

  • git branch : 查看当前分支情况,当前分支前有*号
  • git branch linux : 创建分支
  • git checkout: 检查本地分支与远程分支的变更差异
  • git checkout linux:切换分支

3.2.2 尝试在linux本地分支进行代码提交

 

linux分支比master分支新增一行数据

说明:

我们发现切换分支以后,在linux分支修改过的文件数据,完全还原成了master分支的文件内容

但是这里存在一个问题,假如我们在linux分支下,修改了文件,但是并未提交到本地仓库linux分支,而只是放到了暂存区就切换到master分支的话,那么会发生什么呢?

 

说明:

当linux的本地分支仓库和master本地分支仓库的代码不同时,如果你没把变更从暂存区提交到分支仓库,那么默认是不能切换分支的。

但是,这里还有一个问题,假如linux分支和master分支的本地仓库的代码相同,但是我仍旧没把linux分支的变更提交到本地linux分支仓库,那么能直接切换master分支吗?

 

说明:

如果本地分支仓库间的代码一致,那么就算不把变更提交到本地分支仓库,那么也可以切换分支

在工作中,为了避免意外,在切换分支前,务必要先将暂存区提交或者清空。

 

3.3 本地分支的合并与删除

想把linux的工作成果合并到master分支上; 
先切换到master分支 
git merge linux : 合并linux分支到master 
git branch -d linux :确定合并完成后,可以放心的删除Linux分支。

3.3.1 自动合并本地分支

3.3.2 本地分支的删除

 

假如linux分支的变更没有合并到当前分支,那么必须用-D参数强制删除分支

[root@Git01 mycode]# git branch

  linux

* master

[root@Git01 mycode]# git branch -d linux

error: 分支 'linux' 没有完全合并。

如果您确认要删除它,执行 'git branch -D linux'。

[root@Git01 mycode]# git branch -D linux

已删除分支 linux(曾为 7212474)。

3.3.3 手动合并本地分支===>本地分支代码冲突解决方案

当本地分支之间的同名目录-同名文件-同一行内容不同时,在进行分支合并时就会产生冲突,故为了解决代码冲突,就需要进行人工手动合并; 
在工作中,为了尽量避免冲突,一般开发人员之间尽可能不负责相同的功能模块,也就不至于同时修改同一个文件。

说明:

由上可知,本地linux分支的benet.txt文件和本地master分支的benet.txt文件的第五行代码产生冲突。如果此时,我们将本地linux分支的变更合并到本地master分支中,那么就会产生代码冲突。

合并本地linux分支

找出文件冲突内容,并修改。(此时冲突的benet.txt文件里已经被标注了冲突内容)

 

到了这里我们只能手动排除,选择保留后的内容,假如我们要保留linux分支的内容,然后再将工作目录中的变更提交即可人工解决代码冲突,并完成分支合并

 

3.4 GIT远程分支管理

3.4.1 将linux本地分支代码和标签推送到github远程仓库的linux分支

 在Git01上,创建本地分支linux,复制master分支代码。

 

将本地linux分支推送到远程github的linux分支

浏览器访问:https://github.com

创建本地标签,并推送到github

 

浏览器访问:https://github.com

 

3.4.2 从github远程仓库克隆一个linux分支到本地linux分支

1)克隆远程仓库master分支后,通过checkout切换成远程linux分支

 在Git02上进行操作

说明:

如果clone时不用-b linux指定分支进行克隆那么默认克隆的都是master分支;我们可以通过checkout切换远程分支的方式对于已经下载下来的master工作目录进行代码替换。

2)通过git clone -b linux URL直接指定远程仓库分支进行克隆

 克隆一个远程分支linux到本地工作目录(-b linux指定分支)

 

原文地址:https://www.cnblogs.com/wsnbba/p/10147256.html