Git标签管理
我们可以针对某一次的提交打上一个标签,有点类似于给某次提交取个别名,比如1.0版本发布时打个标签叫v1.0,2.0版本发布时打个标签叫v2.0,因为每次版本提交的结果都是一连串的哈希码,不容易记忆,打上v1.0,v2.0这些具有某种含义的标签后,可以方便我们进行版本管理。
本文是Git系列的第七篇,了解前面的文章有助于更好的理解本文:
轻量级标签
轻量级标签就像是个不会变化的分支,实际上它就是个指向特定提交对象的引用。
首先我们可以通过如下命令来查看当前仓库中的所有标签:
$ git tag
打标签的方式很简单,直接通过git tag <tagname>
来完成即可,如下命令:
$ git tag v1
表示创建了一个名为v1的tag,这个tag默认是创建在最新一次的commit上的,如下:
我们可以利用git show <tagname>
来查看标签对应的版本信息,如下:
我们可以通过$ git tag -d <tagname>
命令删除一个标签:
$ git tag -d v1
如下图:
如果我想给历史上的某次commit打一个标签呢?我们可以通过如下命令git tag <tagname> <commitversion>
,如下:
$ git tag v0.0 7d519
表示给commit的哈希码为7d519的那一次commit打上一个标签,如下图:
含附注的标签
而含附注标签,实际上是存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,标签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。
打一个含附注的标签很简单,使用git tag -a <tagname> -m <msg>
命令,如下:
$ git tag -a v0.0 -m "文件初次建立" 7d519
如下:
如果不加最后的版本号参数,表示给最新的一次commit打标签。
签署标签
说到签署标签我们得先介绍一下GPG:
GPG是加密软件,可以使用GPG生成的公钥在网上安全的传播你的文件、代码。为什么说安全的?以Google所开发的repo为例,repo即采用GPG验证的方式,每个里程碑tag都带有GPG加密验证,假如在里程碑v1.12.3处你想要做修改,修改完后将这个tag删除,然后又创建同名tag指向你的修改点,这必然是可以的。但是,在你再次clone你修改后的项目时,你会发现,你对此里程碑tag的改变不被认可,验证失败,导致你的修改在这里无法正常实现。这就是GPG验证的作用,这样就能够保证项目作者(私钥持有者)所制定的里程碑别人将无法修改。那么,就可以说,作者的代码是安全传播的。为什么会有这种需求?一个项目从开发到发布,再到后期的更新迭代,一定会存在若干的稳定版本与开发版本(存在不稳定因素)。作为项目发起者、持有者,有权定义他(们)所认可的稳定版本,这个稳定版本,将不允许其他开发者进行改动。还以Google的repo项目为例,项目所有者定义项目开发过程中的点A为稳定版v1.12.3,那么用户在下载v1.12.3版本后,使用的肯定是A点所生成的项目、产品,就算其他开发者能够在本地对v1.12.3进行重新指定,指定到他们修改后的B点,但是最终修改后的版本给用户用的时候,会出现GPG签名验证不通过的问题,也就是说这样的修改是不生效的。
——摘自<[带GPG签名的Git tag]>一文
使用签署标签我们先要生成GPG Key,生成命令如下:
$ gpg --gen-key
能默认的就直接按回车默认,不能默认的就根据提示输入相应的值,这里的都很简单,不再赘述。完了之后,就可以通过如下命令来打标签了:
$ git tag -s v0.0 -u "laowang" -m "文件初次建立" 7d519
就把上面的-a换成-s,然后添加-u参数,-u参数的值是我们在生成GPG Key的时候配置的name属性的值,注意-u参数不可以写错,否则标签会创建失败,如下:
如上图,-u参数写错时,标签创建失败。
标签推送到远程仓库
git push命令并不会把tag提交到远程仓库中去,需要我们手动提交,如下:
$ git push origin v0.0
表示将v0.0标签提交到远程仓库,也可以通过$ git push origin --tags
提交所有的tag到远程仓库,如下:
此时别人调用git pull更新代码之后,就能看到我们的tag。如下:
Ok,Git标签管理我们先说这么多。有问题欢迎留言讨论。
参考资料:
1.《GitHub入门与实践》 2.《Pro Git》
- HTTP请求详解
- 漫谈Java IO之 NIO那些事儿
- 1593: [Usaco2008 Feb]Hotel 旅馆
- BZOJ 1823: [JSOI2010]满汉全席(2-SAT)
- 3360: [Usaco2004 Jan]算二十四
- JavaScript 数据类型
- 3361: [Usaco2004 Jan]培根距离
- Java NIO
- 1342: [Baltic2007]Sound静音问题
- 加深理解HTTP请求---网络基础TCP/IP
- BZOJ2199: [Usaco2011 Jan]奶牛议会(2-SAT)
- 数据结构之链表、栈和队列 java代码实现
- 洛谷P3209 [HNOI2010]PLANAR(2-SAT)
- javascript 面向对象(多种创建对象的方式)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- springboot maven项目引入并打包本地JAR
- 移植lua5.2和luasocket库到嵌入式linux,使能强大的lua脚本和网络功能
- Go或者C中调用Lua业务脚本,实现终端应用的热更新机制
- 多线程基础(八):ReentrantLock的使用及与synchronized的区别
- 在java中notify和notifyAll的区别
- 我在近期求职中遇到的前端面试问题及其解法
- 腾讯云 云开发 部署 Blazor网站
- 最新基准测试:Kafka、Pulsar 和 RabbitMQ 哪个最快?
- 基于飞桨实现高光谱反演:通过遥感数据获取土壤某物质含量
- 飞桨Tracking目标跟踪库开源!涵盖业界主流的VOT算法,精准检测动态目标轨迹
- 基于react的组件库主题设计方案
- Xilinx MPSoC PS/PL之间的数据交互和外设设计
- 基于Res-Unet网络实现肝脏肿瘤分割任务
- golang判断map中key是否存在的方法
- 迁移实战:一次AntDB(基于pgxl分布式架构的数据库)数据库迁移经验分享