判官007 发表于 2018-1-13 18:25:04

将git版本号编译进程序

问题的提出
  不管是什么版本管理工具,每一条提交记录都会有一个对应的版本号,一般是一个整数,git是一个hash字符串。不管怎样,这个版本号是唯一的,有时候我们在程序运行的时候会在日志里面输出程序的版本号,或者在命令行运行的时候在控制台中输出当前程序的版本号。一般而言,如果我们程序输出的版本号,与版本控制系统源码对应的版本号有关联关系是最好不过的,这样当运行的程序出现问题的时候,可以通过程序的版本号,去源码的版本控制系统中找到对应的源码进行分析,也就是说我们知道当前运行的程序对应在版本控制系统中的源码。

通过git命令得到版本号
  这里的使用环境是linux,我们的源码客户端是git,通过git命令我们可以得到当前最新版本库中的源码版本,使用git log 命令的格式化输出,可以得到每次提交结果中的各个部分,例如版本号,提交时间,提交日志。git log 命令默认情况下会输出所有提交记录的详细信息,通过使用其提供的--pretty选项我们可以指定git log 输出我们需要的部分,例如代表版本号的hash字符串部分。
  git log --pretty=format:"%H"
  输出:
  082472d159a9ccd72fe241319d120b1a3dd87283
  59ab0468389b511d0949aaef4e5324277e1899ce
  134cb39bbb64b203b146626776a56037bccb469f
  395db26c60e2f3544ec85d62e6caef911e9b16df
  a29c1f4b7d72bb636ea844fc2d2e70c6f49eb046
  当然我们也可以只输出短hash即可,例如:
  git log --pretty=format:"%h"
  输出:
  082472d
  59ab046
  134cb39
  395db26
  a29c1f4
  同样我们的代码提交时候的时间可以通过下面的格式得到,仅仅是修改format参数即可:
  git log --format="%ct"
  输出:
  1499330142
  1499245162
  1499244031
  1499237075
  1498813631
  这里输出的是所有提交记录的Unix时间戳,我们要得到最新的一条,只需要加上参数 -n其中n为大于0的整数,表示输出log的前n次的提交记录,例如:
  git log -1 --format="%ct"
  输出:
  1499330142
  表示输出最新的一次提交的提交时间戳。既然有了这些信息,我们就可以得到当前最新的源码各个部分的信息,其实最重要就是提交时间,以及版本号码了,有了前面的命令使用,我们可以写出下面的shell代码:
  

#!/bin/sh  
commit_ts=`git log -1 --format="%ct"`
  
commit_time=`date -d@$commit_ts +"%Y-%m-%d %H:%M:%S"`
  
current_time=`date +"%Y-%m-%d %H:%M:%S"`
  
git_version=`git log -1 --format="%h"`
  
seds/MYVERSION/"version: $git_version commit: $commit_time build: $current_time"/g version.h.tmp > version.h
  
make clean
  
make
  

  

  将脚本内容保存为 build.sh 每次提交源码之后,直接运行build.sh 脚本即会生成最新的头文件,该头文件被编译到程序中,我们看到版本信息包含了最新的版本号,提交时间,编译时间。其中我们有一个模版文件,version.h.tmp,其内容如下:
  

#ifndef _VERSION_  
#define _VERSION_ "MYVERSION"
  
#endif
  

  

  运行build.sh之后生成的version.h文件类似如下:
  

#ifndef _VERSION_  
#define _VERSION_ "version: 082472d commit: 2017-07-06 16:35:42 build: 2017-07-11 21:01:31"
  
#endif
  

  

  在我们的源文件中直接使用 _VERSION_ 宏就可以啦,在git提交版本的时候我们应该将version.h.tmp模版文件添加到版本控制系统中,而脚本生成的version.h由于每次build都会变化,可以忽略掉。

关于git log 命令的格式说明
  我这里列出一份git log 更加全面的格式说明,供大家参考:
  

%H: commit hash  
%h: 缩短的commit hash
  
%T: tree hash
  
%t: 缩短的 tree hash
  
%P: parent hashes
  
%p: 缩短的 parent hashes
  
%an: 作者名字
  
%aN: mailmap的作者名字 (.mailmap对应,详情参照git-shortlog(1)或者git-blame(1))
  
%ae: 作者邮箱
  
%aE: 作者邮箱 (.mailmap对应,详情参照git-shortlog(1)或者git-blame(1))
  
%ad: 日期 (--date= 制定的格式)
  
%aD: 日期, RFC2822格式
  
%ar: 日期, 相对格式(1 day ago)
  
%at: 日期, UNIX timestamp
  
%ai: 日期, ISO 8601 格式
  
%cn: 提交者名字
  
%cN: 提交者名字 (.mailmap对应,详情参照git-shortlog(1)或者git-blame(1))
  
%ce: 提交者 email
  
%cE: 提交者 email (.mailmap对应,详情参照git-shortlog(1)或者git-blame(1))
  
%cd: 提交日期 (--date= 制定的格式)
  
%cD: 提交日期, RFC2822格式
  
%cr: 提交日期, 相对格式(1 day ago)
  
%ct: 提交日期, UNIX timestamp
  
%ci: 提交日期, ISO 8601 格式
  
%d: ref名称
  
%e: encoding
  
%s: commit信息标题
  
%f: sanitized subject line, suitable for a filename
  
%b: commit信息内容
  
%N: commit notes
  
%gD: reflog selector, e.g., refs/stash@{1}
  
%gd: shortened reflog selector, e.g., stash@{1}
  
%gs: reflog subject
  
%Cred: 切换到红色
  
%Cgreen: 切换到绿色
  
%Cblue: 切换到蓝色
  
%Creset: 重设颜色
  
%C(...): 制定颜色, as described in color.branch.* config option
  
%m: left, right or boundary mark
  
%n: 换行
  
%%: a raw %
  
%x00: print a byte from a hex code
  
%w([[,[,]]]): switch line wrapping, like the -w option of git-shortlog(1).
  

  

  最后分享一个比较好的git log 格式输出:
  

git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %cn %s %Cgreen(%cr)%Creset' --abbrev-commit --date=relative  

  

  其输出效果如下:
https://images.cnblogs.com/cnblogs_com/wangqiguo/1035956/o_git_log_format.png
页: [1]
查看完整版本: 将git版本号编译进程序