因为最近工作上多处都用到了基于 Git 的开发,需要深入理解 Git 的工作原理,以往的 Git 基本知识已经满足不了需求了,因此写下这篇 Git 进阶的文章,主要是介绍了一些大家平时会碰到但是很少去了解的 Git 知识以及 Git 的一些内部工作原理。我们平时用 Git 的很多操作可能只是记住了一个专业术语,或者一个命令而已,并不知道 Git 为什么要这样做,写下这篇文章也是为了让大家对 Git 应用得更加的得心应手。

读完本篇文章你会了解到 Git 的以下内容:

✦ 为什么使用 Git

✦ Git 基本用法概述

✦ checkout,merge,rebase,reset,reverse 的区别

✦ Git flow

✦ Git hooks

✦ Git 子模块

✦ Git 内部工作原理

为什么使用Git

集中化的版本控制

例如我们常用的 svn,这种版本控制最大的缺点就是中央服务器的单点故障,一旦中央服务器宕机,所有的开发人员都无法正常更新代码工作了,如果中心数据所在的磁盘损坏又没有备份,版本数据将永久丢失。

分布式版本控制系统

客户端不只是提取最新版本的文件快照,而是将整个代码仓库完整的镜像拉下来,svn 以文件变更列表的方式存储信息,这类系统将它们保存的信息看作是一组基本文件和每个文件随时间逐步累积的差异。

Git 基本用法概述

Git 提交与同步流程

Git 撤销更改

Git 常用命令

checkout、reverse、reset、rebase、merge

1.  checkout

这里我们主要讨论 git checkout 检出分支的操作,当我们执行 git checkout <branchname> 操作时,其实原理上是将 head 指针指向了要检出的这个分支上。

分叉情况:

当我们在多个分支上同时开发时,不同的分支会有不同的提交记录,这样就会出现分叉情况。

此时要协同开发我们需要将各种分支合并到主干分支上,也就是 git 中的 merge 操作。如图,上游的分支在之后就与我们的分支有了差异,此时我们执行 merge 命令其实就是将 C , D 提交的内容进行一个融合,然后作为提交。

2.  git merge

3.  git rebase <branchname>

merge 操作是将 C , D 合并成一个 commit,如果我们不想这么做,可以使用变基操作。顾名思义,变基就是将自己的根基改变了(个人理解),rebase 是直接将当前开叉的提交强行给挪到了另一个分支的后面。

4.  git reset

reset 操作 HEAD 指针从 C 变到了 D ,也就是说之后的提交线从 B 的后面开始,C 就变成游离的状态了。

5.  git revert

相对 reset 操作,revert 就相对安全些,因为它并没有将 C 丢弃调,而是在 C 的后面复制了一份 B 作为 B' .

Git flow

Git 工作流主要是为了让开发者在协同开发时统一规范,统一流程,减少额外的工作量。

简单的说就是我们在开发流程时干特定的事要用到特定的分支,想想如果大家在开发的时候,测试,改 bug,发布都放在同一个分支做,此时项目的管理者要在众多的分支中挑选出他想要的提交进行合并是多么头疼的一件事情。git flow 就是为了解决此类问题。

Git flow 会有两个长期分支:

master:用于记录官方发布轨迹

develope:集成分支,用于记录开发新功能的轨迹

此外还有其他的一些临时的分支:

Feature(新功能分支) :从 develop 分支中派生出来的分支,当需要添加一个新的功能时可用这个分支,新功能完成后,feature 又合并到 develop 中去。

Release(发布分支) :用于合并 develop 中的 feature 分支。

Mantaince(热修复分支):线上 bug 修复分支,直接从 maser 分支中派生出来,完成后合并到 master 和 develop 分支上去。

Release(发布分支) :用于合并 develop 中的 feature 分支。

Mantaince(热修复分支) :线上 bug 修复分支,直接从 maser 分支中派生出来,

完成后合并到 master 和 develop 分支上去。

上图的蓝色分支是master,紫色是develop,红色是hotfix,橙色是feature,绿色是release

Git flow 开发步骤

1. 创建 develop 分支

git branch develop

git push -u origin develop

2. checkout develop 分支

git checkout -b develop origin/develop

3. 基于 develop 创建新功能分支

git checkout -b feature/my-feature develop

4. 合并分支

git pull origin develop

git checkout develop

git merge feature/my-feature

git push

git branchn  -d feature/my-feature

5. 线上版本发布

a.从 develop 分支下创建准备发布的 realse 分支

git checkout -b release-1.0.0  develop

git push

b.将realse分支合并到 develop

c.打标签。realse 是一个 develop 合并到 master 的一个缓冲的分支,每当有源码需要合并到 master 时应该打上标签

git  tag -a 1.0.0-release -m "first release" master

git push --tags

6.线上 bug 修复

在代码都提交到 master 后项目开始上线,此时如提交修复线上 bug 的代码?

a.创建 hotfix分支   git checkout -b issue-#001 master

b.修复 bug

c.完成修复合并到 master

d.打标签

e.合并到 develop

Git hooks (钩子)

Git hooks 是一些可以在仓库中的任何时刻自动运行的脚本,这些脚本类似于一些拦截器,可以在执行 git 操作的前后执行一些特定的事件。

当初始化仓库时,会自动在 .git/hooks 目录下生成 .example 为后缀的文件,这些文件就是 hooks,git 为防止这些hooks默认执行,加了 .example 后缀,要执行这些 hooks只需把 .example 后缀去掉即可。

hooks 分为本地的 hooks 和服务器端的 hooks。

本地 hooks:

pre-commit

prepare-commit-msg

commit-msg

post-commit

这些都是在 commit 的整个过程中的一些 hooks。

post-checkout

pre-rebase

这两个 hooks 是用于做一些额外操作或者一些安全检查。

pre 前缀的 hooks 用于添加多余操作,post 前缀的 hooks 用于放送通知。

案例演示:

安装一个 prepare-commit-msg hook。

首先,我们先将 .git/hooks 目录下的 prepare-commit-msg.example 的后缀去掉。

接着我们使用打开这个文件进行编辑,这是一个 shell 脚本,我们也可以用 python 或 ruby这样的语言写 hooks。

保存退出,这个 hooks 是在 commit 操作时添加 msg 之后触发。

我们来进行一次提交操作。

可以看到在 hooks 中的程序已经执行了。

以上的这些 hooks 都是本地的 hooks,还有一些 hooks 是加在远程仓库的,这些就是服务器端的 hooks。

pre-receive:执行 git push 操作时触发

update:每次 push 之后触发

post receive:push 成功之后触发

Git 子模块

在工作当中我们经常会遇到这样的情况:我们在当前项目里想引入例外一个项目,也有可能是一个库,但是假如我们直接把这个项目加入到中,我们必须要确保每个仓库中含有这个库,不然部署很困难,我们每次对这个项目或库进行自定义操作时还会使上游的合并变得异常的困难。如果我们可以将这个库克隆到自己的项目中,并且保持这个库的提交独立那就完美了。git 子模块就是为了解决这个问题。

接下来我们就来演示一下如何在一个被分成多个子项目的项目中进行开发。

首先我们要在我们的主项目 pro-main 中添加子模块 pro-service

pro-main 的仓库地址为:git@github.com:CodeNerverEnd/pro-main.git

pro-service 的仓库地址为:git@github.com:CodeNerverEnd/pro-service.git

先将我们的主项目克隆下来,

然后在主项目中添加子模块,

使用命令  git submodule add git@github.com:CodeNerverEnd/pro-service.git

我们可以在仓库中看到如下目录

多了一个 .gitmodules 文件,打开这个文件看到,保存了子模块的路径,如果你不想将子模块放到主项目仓库路径下,可以将这里的路径改成你想要的路径。

我们把添加了子模块的主项目提交到远程仓库后,所有的开发人员都可以用这个库了,下面我们就来看看其他开发人员怎么用它。

首先其他的开发人员会克隆含子模块的项目,我们可以用以下的命令:

git clone --recursive git@github.com:CodeNerverEnd/pro-main.git

如果我们克隆的时候没有加  --recursive,默认是不会将子模块的内容克隆下来,你只能在项目中看到一个子模块的文件夹,但里面的内容是空的。

现在假如开发人员需要更新子模块,执行以下命令:

git submodule update --remote

假如此时开发人员想要在主项目下编码的同时又在子模块下编码,可以执行以下步骤

1.进入子模块目录检出一个分支

git checkout stable

2.merge子模块

git submodule update --remote --merge

3.假如其他人在上游做了修改,我们需要并入

git submodule --remote --rebase

4.我们在本地改好了以后想发布子模块的改动

git push --recurse-submodules=ondemand

对于 Git 来讲,这些远远是不足以叙述它的全面。我将在下一个篇幅里,继续为你们介绍 Git 的进阶。


git使用上的更多相关文章

  1. git push上传代码到gitlab上,报错401或403

    之前部署的gitlab代码托管平台,采用ssh方式连接gitlab,在客户机上产生公钥上传到gitlab的SSH-Keys里,则git clone下载和git push上传都没问题,这种方式很安全. ...

  2. git将本地代码 和服务器git@osc 上的代码 关联

    将本地代码 和服务器git@osc 上的代码 关联 要使用git 首先,你得安装一个git 下载 http://git-scm.com/downloads 安装完成后,需要简单的配置一下,打开 Git ...

  3. 记一次小团队Git实践(上)

    公司规模不大,成立之初,选择了svn作为版本控制系统.这对于用惯了git的我来说,将就了一段时间后,极为不爽,切换到git-svn勉强能用.随后,因为产品需要发布不同的版本,而git-svn对远程分支 ...

  4. Windows 和 Mac 系统下安装git 并上传,修改项目

    首先在MAC上怎么操作. 在gitHub创立一个账户,在创立一个项目,这就不用我说了对吧. 创建完之后是这样的: 接下来,我们打开https://brew.sh 这是下载homebrew的网站,hom ...

  5. 花点时间顺顺Git(上)

    花点时间顺顺Git(上) 为了让你们点进来贼努力的想了一个色彩斑斓大吉大利的标题,好,看正文 历史:Linus的作者创建了开源的Linux,02年以前代码管理都依赖手动合并,后来管理不了了,拒绝SVN ...

  6. Git Bash上传文件

    今天通过Git Bash上传了一个项目(之前是通过Github Desk上传的),操作命令如下: 在目录下shift+右键打开Git Bash 1.git init 2.git add *.py 3. ...

  7. 在git服务器上创建项目过程及遇到的问题

    一: 登录git服务器,输入用户名,密码等 二: New Project 添加项目 设置组可见,项目名称等. 创建成功的项目可以看到该项目的clone地址,可以通过http,ssh两种方式来获取: 三 ...

  8. Git本地上传到服务器

    Git本地上传到服务器 2018年05月17日 10:45:02 VV-King 阅读数:643 标签: git   1.本机window系统的话先下载msysgit  下载后在开始菜单里面找到 &q ...

  9. Git的上传步骤

    Git的上传步骤 1.Git的命令基础 Git是当下最流行的版本控制工具(VCS),由linux系统之父linus开发.它能实现 团队中的代码协作开发,它在代码同步和代码管理方面功能强大,理念先进. ...

  10. git push上传代码到gitlab上,报错401/403(或需要输入用户名和密码)

    之前部署的gitlab,采用ssh方式连接gitlab,在客户机上产生公钥上传到gitlab的SSH-Keys里,git clone下载和git push上传都没问题,这种方式很安全. 后来应开发同事 ...

随机推荐

  1. vue微博回调空页面

    1.vue微博回调空页面 注:微博回调空页面为:http://127.0.0.1:8888/oauth/callback/ 1.1 页面路径 components\oauth.vue <temp ...

  2. C++调用C接口

    目录 C++调用C代码 解决调用失败问题 思考:那C代码能够被C程序调用吗 C代码既能被C++调用又能被C调用 C++调用C代码 一个C语言文件p.c #include <stdio.h> ...

  3. 软件工程与UML第三次作业

    博客班级 软件工程与UML2班 作业要求 本次作业要求 作业目标 <给至少5名同学提他的代码issue并用博客记录;根据收到的issue修改自己的代码> 作业源代码 我的码云仓库 学号 & ...

  4. CentOS 安装ElasticSearch-head插件

    1 下载ElasticSearch-head安装包 1.1 Git下载ElasticSearch-head #安装git,若机器环境已存在,不需要再次安装 yum install git #下载 gi ...

  5. springsecurity实现前后端分离之jwt-资料收集

    https://www.jianshu.com/p/5b9f1f4de88d https://www.jianshu.com/p/725d32ab92f8 https://blog.csdn.net/ ...

  6. 老猿学5G:3GPP和中国移动5G计费架构概览

    ☞ ░ 前往老猿Python博文目录 ░ 一.引言 老猿学5G这个专栏主要记录笔者因工作原因学习了解5G计费相关知识,文章按时间顺序循序渐进的介绍5G基础概念以及5G计费相关知识,该专栏前期已经完结, ...

  7. 第二十四章、containers容器类部件QScrollArea滚动区域详解

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 容器部件就是可以在部件内放置其他部件的部件,在Qt Designer中可以使用的容器部件有 ...

  8. PyQt(Python+Qt)学习随笔:QTreeWidgetItem项下子项的指示符展示原则childIndicatorPolicy

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 树型部件QTreeWidget中的QTreeWidgetItem项下可以有子项,如果存在子项,则父项 ...

  9. THE BUG 队第一次团队项目作业

    队名: THE BUG 队 2.队员学号: 杨梓琦 3118005115(队长) 温海源,3118005109 陈杰才,3118005089 李华,3118005097 钟明康,3118005123 ...

  10. 第 5 篇 Scrum 冲刺博客

    每天举行会议 会议照片: 昨天已完成的工作与今天计划完成的工作及工作中遇到的困难: 成员姓名 昨天完成工作 今天计划完成的工作 工作中遇到的困难 蔡双浩 实现重设计个人界面的功能添加 实现关注,被关注 ...