因为最近工作上多处都用到了基于 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. 通过自定义拦截器优雅的导出Excel并标红的重复数据

    平时我们导入导出Excel的时候如果用poi导出,会发现光设置格式都要很多代码,看起来非常的不优雅.后来业务中遇到了需要导入非常巨大的Excel的需求.如果继续用poi的方式,因为poi把所有exce ...

  2. Jmeter-BeanShell断言的运用二(不同Json格式的字段提取和断言判断)

    前言 为了更加熟悉BeanShell,所以用几个实例来记录说明下,不同的Json格式是怎么提取相应字段和判断断言的.(会持续更新...) 一.第一种Json格式 1.Json响应数据内容如下: { & ...

  3. 了不起的 Deno:带你极速获取各大平台今日热榜

    摘要:Deno 是一个 JavaScript/TypeScript 的运行时,默认使用安全环境执行代码,有着卓越的开发体验. 有人的地方就有江湖,有江湖的地方就有争论.前些天,继<[译]为什么如 ...

  4. IdentityServer4系列 | 常见术语说明

    一.前言 在上一篇中,我们IdentityServer4的说明,认识到是一个基于OpenID Connect协议标准的身份认证和授权程序,并简单的对基础知识的认识以及区别说明,从OAuth.OpenI ...

  5. node-sass版本问题

    node-sass sass-loader的问题 出现了版本的问题 版本太高 版本不兼容解决方法: cnpm i node-sass@4.14.1 cnpm i sass-loader@7.3.1 - ...

  6. Python基础篇学习感悟:学如不及,犹恐失之

    从2019年3月底开始学习Python,4月12日在CSDN发表第一篇博文,时至今日已有4个月零12天. 4个多月的学习,老猿从一个Python小白成长到今天,可以说对Python这门语言已经略知一二 ...

  7. 矩阵乘法优化DP复习

    前言 最近做毒瘤做多了--联赛难度的东西也该复习复习了. Warning:本文较长,难度分界线在"中场休息"部分,如果只想看普及难度的可以从第五部分直接到注意事项qwq 文中用(比 ...

  8. 【题解】「CF363A」Soroban

    哎呀呀,咕值要掉光了,赶快水篇题解( solution 这题就是个纯模拟,首先我们根据输出样例看一下输出算盘的规则. 看数最大的 720 ,我们发现,输出的算盘张这样(之所以我不用代码框而用 \(\K ...

  9. Java并发编程的艺术(六)——中断、安全停止线程

    什么是中断 Java的一种机制,用于一个线程去暂停另一个线程的运行.就是一个正在运行的线程被其他线程给打断,停止运行挂起了. 我觉得,在Java中,这种中断机制只是一种方便程序员编写进程间的通信罢了. ...

  10. mac系统下用ssh方式连接git仓库

    1.应用程序-终端,键入命令  ssh-keygen -t rsa -C "xxxxx@xxxxx.com"  ,后面是你的邮箱地址.一直回车,生成密钥. 2.键入  open ~ ...