repo 导出本地 git tag 给他人
背景
使用 repo
管理了多个 git
仓库,有时需要将本地仓库的tag
同步给其他人,但又不能直接推到远程(例如权限问题)。
实际场景举例
- 本地复现了一个问题,需要让其他人回退到相同环境来排查。
- 本地集成验证好了一个版本需要发布,打好
tag
却没有权限推送,得告知各个仓库负责人在同样的commit
上打tag
并推送到远程仓库。
仓库少的话,简单告知下各个仓库对应的commit
号就可以了,对方手工找到对应的commit
号进行操作。
涉及的仓库数量多或者本地 tag
可能发生变更需要多次同步的时候,手工操作就比较麻烦了。
自动化脚本
让我们来考虑下如何让同步本地 tag
这个事情变得简单些。(不看实现过程的话,可直接拉到最后总结部分)
后续演示基于一个简单的repo
环境
mkdir test-repo;
cd test-repo;
repo init -u https://github.com/zqb-all/zqb-manifest
repo sync
#打上tag方便后续测试
repo forall -c git tag test-v1
基础命令
tag
名是已知的,要提取的关键信息就只有 仓库
和 commit号
。
repo
可以帮我们遍历所有仓库,在每个仓库下执行git
命令,使用方式是repo forall -c git xxx
。
已知tagname
,要获取commit
号,可以通过git log tagname
列出对应的commit
,我们只需要一个commit
,于是可以加上-1
参数只列出一个提交。
组合一下就得到了
#!/bin/bash
# v1
tag=$1
repo forall -c git log -1 $tag
试试效果,
$ ./repo_share_tag.sh test-v1
commit e9e78ee6df545fb057eb6baaaf9446327cabdfa7
Author: zhuangqiubin <zhuangqiubin@gmail.com>
Date: Mon Apr 6 00:14:54 2020 +0800
fix typo
commit 059c803e9f1d0df8e5c89aec11340224c1d85f0e
Author: zqb-all <zhuangqiubin@gmail.com>
Date: Fri Aug 30 10:11:51 2019 +0800
fix save name, support vim
以下省略多个commit信息
得到的结果是每个仓库对应这个tag
的commit
打印。
有几个问题。
- 没有打印仓库名
- 对于没有打上该
tag
的仓库,git log
会有报错信息 - 打印的冗余信息太多,例如时间,
commit
信息等,都无关紧要,只需要唯一的commit
号即可
定制格式
问题1
和2
可以通过为repo forall
加上-p
参数来一并解决。
使用repo forall -p -c git xxx
,会打印出仓库路径,并忽略错误。
问题3
可以通过定制git log
的格式来解决。
我是想到了平时一直在使用的一个git
的alias
,它可以定制git log
的显示格式。
$cat ~/.gitconfig | grep "lg"
lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
明显看出用--pretty=format
就可以指定格式,各个参数的含义对照执行结果也容易猜测出来,不想猜就通过man git log
来确认下。
如果平时没用过定制的git log
输出,只要有这个想法,搜索一下也有很多介绍。
既然有git
原生提供的功能,就不要自己费力气去过滤处理了。
所以问题3
的解决方式是,加上--pretty=format:'%h'
参数。
修改后为
#!/bin/bash
# v2
tag=$1
repo forall -p -c git log -1 $tag --pretty=format:'%h'
此时就没有冗余信息了,输出格式清爽多了。
$ ./repo_share_tag.sh test-v1
project python/convertfb/
774ddb6
project rust/cut-trailing-bytes/
e9e78ee
project shell/EasierMinicom/
059c803
project shell/PathMarker/
4b6e219
project shell/pop-up-task-diary/
5d85ed2
project shell/smartbc/
9d7bc06
生成脚本
导出轻松了,但接收方还是得手工打tag
。
能不能直接生成一个脚本,给到接收方运行,自动打tag
呢 ?
观察下这个输出,规律很简单,一行仓库路径,一行commit
号。如果每两行合为一行,再适当插入一些shell
命令,应该就可以得到shell
脚本了。
两行合并为一行,根据经验sed
和awk
应该都能做,具体命令就得搜索下了,简单搜索可得到
sed -n '{N;s/\n/\t/p}' test //sed的方法
awk '{tmp=$0;getline;print tmp"\t"$0}' test //awk方法
观察下,awk
似乎更方便进一步定制,那就选awk
吧
#!/bin/bash
# v3
tag=$1
repo forall -p -c git log -1 $tag --pretty=format:'%h' | awk '{tmp=$0;getline;print tmp"\t"$0}'
得到的结果
$ ./repo_share_tag.sh test-v1
project python/convertfb/ 774ddb6
project rust/cut-trailing-bytes/ e9e78ee
project shell/EasierMinicom/ 059c803
project shell/PathMarker/ 4b6e219
project shell/pop-up-task-diary/ 5d85ed2
project shell/smartbc/ 9d7bc06
以上的project
我们是不要的,只要保留 仓库path
和 commit
。这一点可以将awk
命令中的$0
改成$2
来实现,$0
是整行,$1
对应project
,$2
则刚好是我们需要的path
。
另外得再插入一些固定的字符,将 <path> <commit>
变成 cd <path> ; git tag <commit> tagname
,考虑处理完一个仓库后还得要退回源目录,方便处理下一个仓库,那再加个 cd -
。cd -
表示回到上一个目录,很实用的命令。
以上都可以通过修改awk
命令来实现,修改后得到:
#!/bin/bash
# v4
tag=$1
repo forall -p -c git log -1 $tag --pretty=format:'%h' | awk '{tmp=$2;getline;print "cd "tmp"; git tag '$tag' "$1"; cd -;"}'
看起来差不多了,重定向到文件中,加上必要的sheban
,即#!/bin/bash
#!/bin/bash
# v5
tag=$1
file=set-tag-$tag.sh
echo "#!/bin/bash" > $file
echo "" >> $file
repo forall -p -c git log -1 $tag --pretty=format:'%h' | awk '{tmp=$2;getline;print "cd "tmp"; git tag '$tag' "$1"; cd -;"}' >> $file
chmod +x $file
#for debug
cat $file
执行后可得到set-tag-test-v1.sh脚本
$cat ./set-tag-test-v1.sh
#!/bin/bash
cd python/convertfb/; git tag test-v1 774ddb6; cd -;
cd rust/cut-trailing-bytes/; git tag test-v1 e9e78ee; cd -;
cd shell/EasierMinicom/; git tag test-v1 059c803; cd -;
cd shell/PathMarker/; git tag test-v1 4b6e219; cd -;
cd shell/pop-up-task-diary/; git tag test-v1 5d85ed2; cd -;
cd shell/smartbc/; git tag test-v1 9d7bc06; cd -;
接收方运行这个脚本即可。
完善脚本
实际验证下,很快发现问题
- 已经打过了
tag
需要更新,重复打会报错,需要先删除同名tag
- 如果接收方代码中不存在对应的
commit
(例如代码未更新),虽然会报错,但脚本没有暂停,可能会让人忽略该报错 - 没有提示处理的仓库路径
- 存在冗余信息,例如
cd -
会打印路径,其实是没作用的
解决方式
- 打
tag
之前先删除原有同名tag
,即执行git tag -d $tag
,再考虑tag
可能不存在会报错,加上错误log
重定向2>/dev/null
- 打
tag
失败则中止运行,即加上|| exit 1
cd
之前,先打印目标路径, 即加上echo tmp
- 屏蔽掉
cd -
的输出, 即加上> /dev/null
顺便加点换行,调整下输出的脚本,可得到
#!/bin/bash
# v6
tag=$1
file=update-tag-$tag.sh
echo "#!/bin/bash" > $file
echo "" >> $file
repo forall -p -c git log -1 $tag --pretty=format:'%h' | awk '{tmp=$2;getline;print "echo "tmp"\ncd "tmp"\ngit tag -d '$tag' 2>/dev/null\ngit tag '$tag' "$1" || exit 1\ncd - > /dev/null\n"}' >> $file
chmod +x $file
#for debug
cat $file
此时生成的打tag脚本就变成了
$ cat ./update-tag-test-v1.sh
#!/bin/bash
echo python/convertfb/
cd python/convertfb/
git tag -d test-v1 2>/dev/null
git tag test-v1 774ddb6 || exit 1
cd - > /dev/null
echo rust/cut-trailing-bytes/
cd rust/cut-trailing-bytes/
git tag -d test-v1 2>/dev/null
git tag test-v1 e9e78ee || exit 1
cd - > /dev/null
echo shell/EasierMinicom/
cd shell/EasierMinicom/
git tag -d test-v1 2>/dev/null
git tag test-v1 059c803 || exit 1
cd - > /dev/null
echo shell/PathMarker/
cd shell/PathMarker/
git tag -d test-v1 2>/dev/null
git tag test-v1 4b6e219 || exit 1
cd - > /dev/null
echo shell/pop-up-task-diary/
cd shell/pop-up-task-diary/
git tag -d test-v1 2>/dev/null
git tag test-v1 5d85ed2 || exit 1
cd - > /dev/null
echo shell/smartbc/
cd shell/smartbc/
git tag -d test-v1 2>/dev/null
git tag test-v1 9d7bc06 || exit 1
cd - > /dev/null
最后加点提示语句,参数检查
#!/bin/bash
show_help()
{
echo -e "Usage: share_tag.sh <tag>"
echo -e 'Eg. ./share_tag.sh release-v1'
}
[ x"$1" = x"" ] && {
show_help
exit 1
}
tag=$1
file=update-tag-$tag.sh
echo "#!/bin/bash" > $file
echo "" >> $file
repo forall -p -c git log -1 $tag --pretty=format:'%h' | awk '{tmp=$2;getline;print "echo "tmp"\ncd "tmp"\ngit tag -d '$tag' 2>/dev/null\ngit tag '$tag' "$1" || exit 1\ncd - > /dev/null\n"}' >> $file
chmod +x $file
#for debug
cat $file
echo -e '\033[0;31;1m'
echo "to update tag $tag, please run ./$file"
echo -e '\033[0m'
总结
本地已打好tag
,如 test-v1
,需要分享给他人则运行./repo_share_tag.sh test-v1
本地没有tag
,那可以先批量打一个tag
,再如上所述导出脚本给他人。
批量打tag
: repo forall -c git tag test-v1
批量删tag
: repo forall -c git tag -d test-v1
东拼西凑出来的脚本,暂时也够用了,后续有更新会放到 https://github.com/zqb-all/repo-share-tag
blog:https://www.cnblogs.com/zqb-all/p/13057786.html
公众号:https://sourl.cn/BKeNSL
repo 导出本地 git tag 给他人的更多相关文章
- Git tag相关命令
常见命令如下: // 查看标签,可加上参数-l(列表形式列出) -n(附加说明) git tag [-l -n] // 查看符合检索条件的标签 git tag -l .*.* // 查看对应标签状态 ...
- git tag本地删除以及远程删除
假设存在tag:12345 git tag -d 12345 #删除本地记录 git push origin :refs/tags/12345 #删除远程记录 PS: 如果您觉得我的文章对您有帮助,可 ...
- git tag知多少
这个命令,其实很有用,类似clearcase中的label,就是给一个版本设置一个标记(标签),方便后期查找特定的版本. tag和commit的sha1那串字符串的关系,不是很大,但是还是要说一下的. ...
- 带GPG签名的Git tag
原文地址http://airk000.github.io/git/2013/09/30/git-tag-with-gpg-key Git tag ###Tag用来做什么? Tag即标签,用以给项目仓储 ...
- git tag使用标记
git跟其它版本控制系统一样,可以打标签(tag), 作用是标记一个点为一个版本号,如0.1.3, v0.1.7, ver_0.1.3.在程序开发到一个阶段后,我们需要打个标签,发布一个版本,标记的作 ...
- Git tag push 到远端仓库
很早之前,我们就提到过用Git tag来给工程打上标签,但是这个命令只是在本地仓库打标签而已, 为了能把标签同步到远程服务器,我们可以这样做: 默认情况下,git push并不会把tag标签传送到远端 ...
- git tag — 标签相关操作
标签可以针对某一时间点的版本做标记,常用于版本发布. 列出标签 $ Git tag # 在控制台打印出当前仓库的所有标签$ git tag -l 'v0.1.*' # 搜索符合模式的标签 打标签 gi ...
- Git tag 给当前分支打标签
原文已经找不到出处,重新整理格式,仅作个人收藏! 标签(Tag)可以针对某一时间点的版本做标记,常用于版本发布. 列出tag $ git tag # 在控制台打印出当前仓库的所有tag $ git t ...
- git命令之git tag 给当前分支打标签
git tag - 标签相关操作 发表于 2011年06月29日 由 机器猫 标签可以针对某一时间点的版本做标记,常用于版本发布. 列出标签 $ git tag # 在控制台打印出当前仓库的所有标签$ ...
随机推荐
- 我参与 Seata 开源项目的一些感悟
丁老师在他的知识星球邀请我回答以下一个问题: 我觉得这个问题非常有意思,姑且把它贴到公众号这里,与大家分享一下我对这个问题的一些感悟. 感谢丁老师的邀请问答: 在这里我就简单说下,我这段时间参与 Se ...
- vue父子组件之间相互传值
1. 子组件使用父组件方法,并向父组件传值 子组件代码 <template> <div class="menu"> <div class=" ...
- 【Django+Element UI】使用一个接口文件,搞定分页获取数据,模糊查询后分页获取数据
1:序列化获取数据的接口设计 1:分页获取序列化数据 2:是个能传参数的接口 class Society(APIView): def post(self, request): keywords = s ...
- scroll 方法 获取滚轴距离顶部高度
$(window).scroll(function(){ var supportPageOffset = window.pageXOffset !== undefined; // 判断是否支持page ...
- 安装的SQL Server2008 R2版的连接不到本地数据,提示未找到或无法访问服务器。----复制自百度知道
安装的SQL Server2008 R2版的连接不到本地数据,提示未找到或无法访问服务器.使用Windows身份验证 2012-09-17 00:23hj168926 | 分类:数据库DB | 浏览3 ...
- linux DRM/KMS 测试工具 modetest、kmscude、igt-gpu-tools (二)
kmscube kmscube is a little demonstration program for how to drive bare metal graphics without a c ...
- SPL基础接口
Iterator 迭代器接口 SPL规定,所有实现了Iterator接口的class,都可以用在foreach Loop中.Iterator接口中包含5个必须实现的方法: interface Iter ...
- 初识Mysql 外键
1.创建学生表(主表) CREATE TABLE `stu` ( `stunum` int(10) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT N ...
- SpringCloud(三)- OpenFeign简介及@FeignClient等注解的使用
唯能极于情,故能极于剑 有问题或错误请及时联系小编或关注小编公众号 "CodeCow",小编一定及时回复和改正,期待和大家一起学习交流 此文由四部分组成(OpenFeign简介.@ ...
- [Objective-C] 015_Delegate(委托代理)
Delegate在iOS开发中随处可见,Delegate是一种功能强大的软件架构设计理念,它的功能是程序中一个对象代表另一个对象,或者一个对象与另外一个对象协同工作(如小明喜欢一个女孩如花,却苦于没有 ...