一.理论概述

还记得之前不太熟悉Git时候,看到很多人都用这个,去百度了下,想知道这到底是个什么程序.大部分文章都在说是如何如何厉害的一个版本控制系统,说法未免太过于笼统

1. 什么是Git

程序员开发一个项目时,本地只有几十行代码或几百行代码,自己还可以有精力维护,但是代码数量太多或者多人同时开发一个项目,很容易出现代码的混乱,冲突,项目出问题也无法确认责任人.维护项目成本也变大.所以,就需要用到一个专业的版本控制系统,这样或许会容易理解好多.

版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。是的,我们就是可以这么理解,它就是这么的简单.

版本控制系统分类

版本控制系统 优点 缺点 特点
本地版本控制 简单,便捷 人为手动操作,出错性高 *
集中化的版本控制系统 集中管理代码 数据整体冗余性较差 代码集中存储在一台服务器上
分布式版本控制系统 几乎不用担心因为服务器故障而造成代码丢失 ? 每一个客户端都会把代码仓库完整地进项克隆下来,然后在进行修改

而Git就是一个开源的分布式版本控制系统,用来高效处理各种项目的版本管理.

一个原始的Git版本仓库,可以让其他主机克隆这个原始版本仓库,从而使得一个Git版本仓库可以同时分不到不同主机上,并且版本库一致

所以在Git中并不存在主库这样的概念,每份复制出去的库都可以独立使用,任何两个库之间的不一致之处都可以进行合并

2. GitLab和GitHub是什么

这两孪生兄弟到底是什么,又有什么区别呢?

先说一下相同点,二者都是基于web的Git仓库,在很大程度上GitLab是仿照GitHub来做的,它们都提供了分享开源项目的平台,为开发团队提供了存储、分享、发布和合作开发项目的中心化云存储的场所。

区别是:

在GitHub上的代码对于外界都是公开的,要想使用私有仓库是需要付费的.

​ 但是被微软给收购后提供了私有仓库,当然:条件就是,免费私有仓库最多只能添加三个协同操作者,这也就意味着适合小团队的项目协同管理。不过这已经很好了,毕竟这在以前可是为付费的用户和企业提供创建私有不公开的仓库,进行代码管理的。普通用户只能免费创建公开仓库,以致于一些私有代码无法通过 GitHub 来进行管理。

GitLab让开发团队对他们的代码仓库拥有更多的控制,相比于GitHub,它有不少的特色:允许免费设置仓库权限;允许用户选择分享一个project的部分代码;允许用户设置project的获取权限,进一步的提升安全性;可以设置获取到团队整体的改进进度;通过innersourcing让不在权限范围内的人访问不到该资源。

从代码私有性方面来看,有时公司并不希望员工获取到全部的代码,这个时候GitLab无疑是更好的选择。但对于开源项目而言,GitHub依然是代码托管的首选。

3.Git功能

  1. 从服务器上克隆数据库到本机;
  2. 在本机上自己创建的分支上提交代码
  3. 在本机上合并分支
  4. 新建一个分支,把服务器上最新版的代码fetch下来,跟自己的主分支合并
  5. 代码冲突解决,开发者之间使用pull命令解决冲突,解决完之后再向主开发者提交补丁

接下来根据配置命令以便于更好的理解它是如何工作的

二.结合具体命令了解其工作

像这三个仓库,使用几乎没什么差别,本案例主要以Git为例,辅助其它两种,对这三种进行相对透彻的理解

1.环境

主机名 ip 角色
gitremo 192.168.111.3 Git远程仓库
git 192.168.111.4 Git本地仓库

2.部署

Git仓库的使用

centos7系列默认自带Git,但版本比较老,这里我们配置epel源,使用yum安装

[root@git ~]# yum -y install git
[root@git ~]# git version
git version 1.8.3.1

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

[root@git ~]# git config --global user.name "joinbest"
[root@git ~]# git config --global user.email "joinbestbest@163.com"
[root@git ~]# git config --global color.ui true
#语法高亮
[root@git ~]# cat .gitconfig
[user]
name = joinbest
email = joinbestbest@163.com
[color]
ui = true

在另一台机器创建git的仓库

[root@gitremo ~]# mkdir /git_data
[root@gitremo ~]# useradd git
[root@gitremo ~]# echo "123456" | passwd --stdin git
更改用户 git 的密码 。
passwd:所有的身份验证令牌已经成功更新。
[root@gitremo ~]# chown -Rf git:git /git_data/

初始化一个git仓库

[root@gitremo ~]# cd /git_data/
[root@gitremo git_data]# ls
[root@gitremo git_data]# git --bare init
初始化空的 Git 版本库于 /git_data/
[root@gitremo git_data]# ls
branches config description HEAD hooks info objects refs

将111.4机器上的公钥上传到111.3,因为111.4机器会clone111.3上的git仓库

[root@git ~]# ssh-keygen 

[root@git ~]# ssh-copy-id 192.168.111.3

克隆在111.3上刚刚创建的git仓库

[root@git ~]# git clone root@192.168.111.3:/git_data
正克隆到 'git_data'...
warning: 您似乎克隆了一个空版本库。

git库所在的文件夹中的文件大致有4种状态

Untracked: 未跟踪, 此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过git add 状态变为Staged.

Unmodify: 文件已经入库, 未修改, 即版本库中的文件快照内容与文件夹中完全一致. 这种类型的文件有两种去处, 如果它被修改, 而变为Modified. 如果使用git rm移出版本库, 则成为Untracked文件

Modified: 文件已修改, 仅仅是修改, 并没有进行其他的操作. 这个文件也有两个去处, 通过git add可进入暂存staged状态, 使用git checkout 则丢弃修改过, 返回到unmodify状态, 这个git checkout即从库中取出文件, 覆盖当前修改

Staged: 暂存状态. 执行git commit则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为Unmodify状态. 执行git reset HEAD filename取消暂存, 文件状态为Modified

更详细的可以参考官方文档

Git仓库工作流程

pull流程:客户端从远程仓库将指定的代码仓库克隆到本机

push流程:客户端必须先将需要上传到远程仓库的代码文件使用git add添加到本地的暂存区staged;然后执行git commit将暂存区的所有文件同步到本地的代码仓库里;随后使用git push将本地仓库的代码文件同步到远程仓库上.

简单命令解释

[root@git git_data]# touch README
[root@git git_data]# git status
# 位于分支 master
#
# 初始提交
#
# 未跟踪的文件:
# (使用 "git add <file>..." 以包含要提交的内容)
#
# README
提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪)

如上命令,在本地Git仓库所在的文件夹新建一个文件,这是它处于untracked状态

[root@git git_data]# git add README
[root@git git_data]# git status
# 位于分支 master
#
# 初始提交
#
# 要提交的变更:
# (使用 "git rm --cached <file>..." 撤出暂存区)
#
# 新文件: README

如上命令,将该文件添加到缓存区

[root@git git_data]# git commit -m 'joinbestRDME'
[master(根提交) 1f73750] joinbestRDME
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README
[root@git git_data]# git status
# 位于分支 master
无文件要提交,干净的工作区

如上命令将缓存区所有的提交到了本地的Git仓库

[root@git git_data]# git push root@192.168.111.3:/git_data
fatal: 您正推送至远程 'root@192.168.111.3:/git_data'(其并非当前分支 'master' 的上游),
而没有告诉我要推送什么、更新哪个远程分支。

报错:原因这里也没有深深专研,但是只是用git push后面不加任何参数,是可以同步到远程仓库的,后来试了一下源码包安装的2.*的版本,该问题得到了解决


删除暂存区数据

rm -rf FileName
#删除为添加到暂存区的文件 git rm --cached FileName
#将该文件从暂存区追踪列表删除 git rm -f FileName
#将该文件从暂存区追踪列表和实际的工作目录下删除

重命名暂存区数据

[root@git git_data]# ls
1123
无文件要提交,干净的工作区
[root@git git_data]# git mv 1123 11
[root@git git_data]# git status
# 位于分支 master
# 要提交的变更:
# (使用 "git reset HEAD <file>..." 撤出暂存区)
#
# 重命名: 1123 -> 11
#
[root@git git_data]# ls
11

还原历史数据

Git有一个叫做HEAD的版本指针,用户执行响应命令申请还原数据时,其实就是将HEAD指针指向到某个特定的提交版本,默认会指向到最近一次提交版本记录,上一个提交版本就叫HEAD^,上两个版本叫HEAD^^,一般会用HEAD~5往上数第五个提交版本.

[root@git git_data]# touch 111
[root@git git_data]# echo 111 > 111
[root@git git_data]# git add 111
[root@git git_data]# git commit -m '2019年7月5日22:23:24'
[master 8dc13a6] 2019年7月5日22:23:24
2 files changed, 1 insertion(+)
rename 1123 => 11 (100%)
create mode 100644 111
[root@git git_data]# git log
commit 8dc13a616d3fe894f4d20805f546525fff990192
Author: joinbest <joinbestbest@163.com>
Date: Sat Apr 27 18:21:50 2019 +0800
2019年7月5日22:23:24
commit ac2497fe01337cff9e538c22f05867e64cd154dc
Author: joinbest <joinbestbest@163.com>
Date: Sat Apr 27 17:04:56 2019 +0800
[root@git git_data]# ls
11 111
[root@git git_data]# git reset --hard ac2497fe
HEAD 现在位于 ac2497f 2019年7月5日20:05:43
#后面的值为历史还原点的SHA-1的值,不用写全
[root@git git_data]# ls
1123

还原未来数据

接着上面例子,我还原了,但是又后悔了,想回到还原前的文件状态,git log已经不显示了呢.

[root@git git_data]# git reflog
#查看未来历史更新点
ac2497f HEAD@{0}: reset: moving to ac2497fe
8dc13a6 HEAD@{1}: commit: 2019年7月5日22:23:24
ac2497f HEAD@{2}: commit: 2019年7月5日20:05:43
478dfea HEAD@{3}: clone: from root@192.168.111.3:/git_data.git
[root@git git_data]# git reset --hard 8dc13a6
HEAD 现在位于 8dc13a6 2019年7月5日22:23:24
[root@git git_data]# ls
11 111

标签使用

像其他版本控制系统(VCS)一样,Git 可以给历史中的某一个提交打上标签,以示重要。 比较有代表性的是开发人员会使用这个功能来标记发布结点(v1.0 等等)。

在 Git 中列出已有的标签是非常简单直观的。 只需要输入 git tag

$ git tag
v0.1
v1.3
[root@git git_data]# git tag v1
#针对于当前数据提交情况创建一个标签 [root@git git_data]# git tag
v1
[root@git git_data]# git tag -d v1
已删除 tag 'v1'(曾为 8dc13a6)
#-d删除标签
[root@git git_data]# git tag
[root@git git_data]# git tag v1 -m "2019年7月5日22:38:37"
#-m说明文字
[root@git git_data]# git tag
v1
[root@git git_data]# git show v1
tag v1
Tagger: joinbest <joinbestbest@163.com>
Date: Sat Apr 27 18:38:20 2019 +0800
2019年7月5日22:38:37
...
#查看改标签的详细信息 [root@git git_data]# ls
11 111
[root@git git_data]# rm -rf *
[root@git git_data]# ls
[root@git git_data]# git reset --hard v1
HEAD 现在位于 8dc13a6 2019年7月5日22:23:24
#针对于标签进行数据还原
[root@git git_data]# ls
11 111

Git中的分支理解及配置

Git的"master"分支并不是一个特殊分支.它跟其他我们自定义创建的分支完全没有区别,之所以几乎每一个仓库都有master分支,是因为git init命令默认创建它,并且大多数人都懒得去改动它

分支的作用

分支这块笔者整理的并不是很好,只是便于理解,如果需要深入理解参考这篇文章

假如开发人员开发一个新功能,但是需要一周能完成,第一天完成了20%,如果立刻提交,由于代码还没有完成,代码库不完整导致别人没法正常工作.如果等代码全部完成再一次性提交,会存在丢失每天进度的风险

Git分支比其它版本控制系统优势很明显,创建,切换和删除分支,速度非常快

在工作中,一般保持master分支稳定,仅用于发布新版本,平时开发工作都在dev分支上,每个人员从dev分支创建自己个人分支,开发完合并到dev分支,最后dev分支合并到master分支

[root@git git_data]# git branch joinbest
#基于当前所在分支提交情况创建新分支
[root@git git_data]# git branch
joinbest
* master
#*表示当前所处于的分支
[root@git git_data]# git checkout joinbest
切换到分支 'joinbest'
#切换到该分支
[root@git git_data]# git branch
* joinbest
master
[root@git git_data]# git merge joinbest
#合并分支,将joinbest分支合并到master

分支合并失败解决

模仿冲突

[root@git git_data]# git branch
linux
* master [root@git git_data]# cat notice
hello,git
hello,gitlab
hello,joinbest
[root@git git_data]# echo "hi,joinbest" >> notice
[root@git git_data]# git commit -a -m "2019年7月6日10:33:23"
[master f3338c2] 2019年7月6日10:33:23
1 file changed, 2 insertions(+), 1 deletion(-)

切到Linux分支

[root@git git_data]# git checkout linux
切换到分支 'linux' [root@git git_data]# cat notice
hello,git
hello,gitlab
hello,joinbest [root@git git_data]# echo "hi,joinbesterror" >> notice
[root@git git_data]# git commit -a -m "2019年7月6日10:36:03"
[linux a64f014] 2019年7月6日10:36:03
1 file changed, 2 insertions(+), 1 deletion(-)

现在的合并冲突是代码文件同一行出现了不同代码

回到master分区,合并分支

[root@git git_data]# git checkout master
切换到分支 'master'
[root@git git_data]# git merge linux
自动合并 notice
冲突(内容):合并冲突于 notice
自动合并失败,修正冲突然后提交修正的结果。
[root@git git_data]# vim notice hello,git
hello,gitlab
hello,joinbest
<<<<<<< HEAD
hi,joinbest
=======
hi,joinbesterror
>>>>>>> linux

解决冲突看我们想保留哪个分支的代码,就把另一个冲突分支删除掉即可,这里是手动解决冲突,此外也是有很多小工具解决冲突

#手动解决就是把不想保留的删除即可
[root@git git_data]# git commit -a -m "2019年7月6日10:42:02"
[master dd33a51] 2019年7月6日10:42:02
#这种一条命令可以提交的情况,主要是用于文件已跟踪,后来修改过的代码文件,如果是新建的文件还是需要两条命令才可以提交到本地的仓库
#git branch -d joinbest
#表示删除一个分支

3.Windows下Git的安装与使用参考文章

三.总结

  • Git和GitLab以及GitHub的关系,我想还是再次总结下.

    • Git是一个版本控制系统,可以有本地仓库,也可以从别的仓库里克隆到本地
    • GitLab本质上讲跟Git没什么两样,但是更方便使用,比如提供web界面等等,它是基于Git做了些扩展
    • GitLab多用于企业自己的私有代码仓库管理,都是自己进行搭建的GitLab.而GitHub是在互联网上存在的一个代码仓库

深入浅出Git(偏向理论)的更多相关文章

  1. 深入浅出Git教程【转载】转载

    深入浅出Git教程(转载)   目录 一.版本控制概要 1.1.什么是版本控制 1.2.常用术语 1.3.常见的版本控制器 1.4.版本控制分类 1.4.1.本地版本控制 1.4.2.集中版本控制 1 ...

  2. 深入浅出Git教程(转载)

    目录 一.版本控制概要 1.1.什么是版本控制 1.2.常用术语 1.3.常见的版本控制器 1.4.版本控制分类 1.4.1.本地版本控制 1.4.2.集中版本控制 1.4.3.分布式版本控制 1.5 ...

  3. 深入浅出git

    图文 http://www.cnblogs.com/syp172654682/p/7689328.html 廖雪峰 https://www.liaoxuefeng.com/wiki/001373951 ...

  4. 深入浅出 Git

    开篇 你可能遇到过 如果你遇到这个场景,那你可能需要版本控制. 什么是版本控制 版本控制最主要的功能就是追踪文件的变更.它将什么时候.什么人更改了文件的什么内容等信息忠实地了已录下来.每一次文件的改变 ...

  5. Git基本理论---重点

    Git本地有三个工作区域: 工作目录(Working Directory): 存放项目代码 暂存区(Stage/Index) : 临时存放文件的改动,保存的是文件列表信息 资源库 (Repositor ...

  6. Git 03 理论

    参考源 https://www.bilibili.com/video/BV1FE411P7B3?spm_id_from=333.999.0.0 版本 本文章基于 Git 2.35.1.2 四个区域 G ...

  7. 第四十三篇:Git知识(基本理论)

    好家伙,最近准备考试,有点忙 首先从版本控制开始 1.版本控制(版本迭代,新的版本) 如果一个项目由多个人去开发,那么总会需要去管理版本 你更一点,我更一点,一冲突,这个项目就炸了 所以需要版本控制. ...

  8. Git 的核心概念解读

    本文不是Git使用教学篇,而是偏向理论方面,旨在更加深刻的理解Git,这样才能更好的使用它,让工具成为我们得力的助手. 版本控制系统 Git 是目前世界上最优秀的分布式版本控制系统.版本控制系统是能够 ...

  9. Git 核心概念

    原文链接 Git的核心概念 聪聪的个人网站 本文不是Git使用教学篇,而是偏向理论方面,旨在更加深刻的理解Git,这样才能更好的使用它,让工具成为我们得力的助手. 版本控制系统 Git 是目前世界上最 ...

随机推荐

  1. Qt编写气体安全管理系统19-端口管理

    一.前言 所有设备的信息配置,主要就三大点:端口管理.控制器管理.探测器管理,整个硬件系统的架构是有多个不同的通信端口(主要是串口和网络),每个通信端口下面挂着多个控制器(每个控制器都有唯一的地址,从 ...

  2. 【426】C 传递数组给函数

    参考:C 传递数组给函数 参考:C语言二维数组作为函数参数传递 参考:二维数组作为函数参数传递剖析(C语言)(6.19更新第5种) 总结: 一维数组参数,可以是地址.arr[].arr[n] 二维数组 ...

  3. Docker容器(三)——容器端口映射

    (1).容器端口映射 容器的端口映射用到了-p选项,-p [物理机端口]:[容器实例端口] 让centos:httpd运行在后台 [root@youxi1 ~]# docker run -d -p 8 ...

  4. 深入浅出深度学习:原理剖析与python实践_黄安埠(著) pdf

    深入浅出深度学习:原理剖析与python实践 目录: 第1 部分 概要 1 1 绪论 2 1.1 人工智能.机器学习与深度学习的关系 3 1.1.1 人工智能——机器推理 4 1.1.2 机器学习—— ...

  5. JS语言中的JSON.parse()和JSON.stringify()

    parse()用于从一个字符串中解析出json对象,如 var str = '{"name":"huangxiaojian","age":& ...

  6. 安装 KVM

    安装 KVM 需要的包 sudo apt-get install -y qemu-kvm qemu-system libvirt-bin virt-manager bridge-utils vlan ...

  7. django2.x报错No module named 'django.core.urlresolvers'

    解决方法如下 from django.urls import reverse 最近从django1.9迁移到django2.0中出现一个意外的报错: No module named 'django.c ...

  8. flask的信号使用

    from blinker import Namespace from datetime import datetime from flask import request namespace = Na ...

  9. Suspended Animation——《The Economist》阅读积累(考研英语二·2010 Reading Text 1)

    [知识小百科] Damien Hirst(达米恩●赫斯特):生于1965年,是新一代英国艺术家的主要代表人物之一.他主导了90年代英国艺术发展并享有很高的国际声誉.赫斯特在1986年9月就读于伦敦大学 ...

  10. KEGG富集分析散点图.md

    输入数据格式 pathway = read.table("kegg.result",header=T,sep="\t") pp = ggplot(pathway ...