shell Git -提取上次提交数据和主信息之前的数据并导出到CSV文件

lf3rwulv  于 2022-11-16  发布在  Shell
关注(0)|答案(1)|浏览(169)

我想写一个脚本,将我在bitbucket中拥有的所有分支的名称写入csv文件,其中还包括以下字段:
1.上次提交ID
1.上次提交开发人员
1.上次提交日期
1.最后提交消息
1.在主机之前(是/否)
我找到了下面的脚本,它生成分支名称和最后一个提交开发者,并将其保存到csv文件中:
对于git branch -a |grep remotes |awk '{print $1}' | cut -d"/" -f 3,4,5 |grep -v ^master$ |grep -v ^HEAD$中i;重复“git log -1 --pretty=format:\"%an (%ae)\" origin/$i| $i”;完成|排序〉/tmp/分支.csv
有没有什么想法应该如何调整这个脚本,以获得最后提交id,最后提交日期,最后提交消息,以及它是否在master之前?任何其他想法也是最受欢迎的。
谢谢你,本尼

py49o6xq

py49o6xq1#

根据定义,任何分支中的最后一次提交都是存储在分支名称中的哈希ID。
假设你使用refs/remotes/origin/blah来查看origin/blah,而不是 * 分支 * 名称,你看到的是你自己的 * 远程跟踪名称 *。这些名称是 * 从 * 其他Git仓库的分支名称中复制的,所以它们具有相同的属性。但这些名称不是分支名称,而是远程跟踪名称。(在其他一些Git仓库中,它们是分支名称。到现在为止,它们可能已经过时了 * 秒 *。你需要确保这没问题,考虑运行git fetch --prunegit remote update --prune,这样它就只有几秒钟,而不是几分钟、几小时或更糟。)
您现有的代码有一个(轻微的)缺陷,如下所示:

$ echo remotes/origin/feature/one/two/three/four | cut -d"/" -f 3,4,5 
feature/one/two

但是,您应该使用Git *plumbing命令 * git for-each-ref,而不是使用git branch -a。这使您能够使用%(refname:short)

$ git for-each-ref --format='%(refname:short)' refs/remotes
origin/HEAD
origin/main
origin/maint
origin/master
origin/next
origin/seen
origin/todo

你可能仍然想抛弃HEAD符号引用和master符号引用,但是现在你可以直接得到提交哈希ID:

$  git for-each-ref --format='%(objectname) %(refname:short)' refs/remotes
9bf691b78cf906751e65d65ba0c6ffdcd9a5a12c origin/HEAD
9bf691b78cf906751e65d65ba0c6ffdcd9a5a12c origin/main
ad60dddad72dfb8367bd695028b5b8dc6c33661b origin/maint
9bf691b78cf906751e65d65ba0c6ffdcd9a5a12c origin/master
91fe8e635439f67be8837601cbf4bd61eddc41b4 origin/next
d0cdfd77733ad946e8c60e9b50286778fb813e56 origin/seen
59d992158534c8291f548563a9c949dae4ad7796 origin/todo

将此管道通过grep -v连接至沟渠/master/HEAD,如前所述:

$ git for-each-ref --format='%(objectname) %(refname:short)' refs/remotes | grep -E -v '/master$|/HEAD$'
9bf691b78cf906751e65d65ba0c6ffdcd9a5a12c origin/main
ad60dddad72dfb8367bd695028b5b8dc6c33661b origin/maint
91fe8e635439f67be8837601cbf4bd61eddc41b4 origin/next
d0cdfd77733ad946e8c60e9b50286778fb813e56 origin/seen
59d992158534c8291f548563a9c949dae4ad7796 origin/todo

直接拒绝for-each-ref中不需要的名字是可能的,但这要复杂得多,而且无论如何我们都必须运行git log来获取作者信息,所以我们最好在这里留下for-each-ref部分。
但是,我们现在应该做的是将输出通过管道 * 传送到 * 一个shell脚本。

  • 从提交中获取更多信息,如作者和提交者姓名;
  • 计算相对于任何其他提交的提前和/或落后计数,包括由refs/remotes/origin/master标识的提交;
  • 根据需要格式化输出。

接下来是简单的shell编程,但有一点需要注意:没有git log的管道等价物,因此您必须在此处使用ceramine命令。有关所有可用的%-指令,请参阅git log文档的PRETTY FORMATS部分。
要计算哈希值为$h的提交相对于哈希值为refs/remotes/origin/master的提交的超前和滞后值,请使用git rev-list --count --left-right

$ git rev-list --count --left-right d0cdfd77733ad946e8c60e9b50286778fb813e56...refs/remotes/origin/master
253     0

这表明origin/seenorigin/master之前是253,在origin/master之后是零(或者等价地,origin/masterorigin/seen之前是零,在origin/seen之后是253)。注意,这需要三点语法,并且不依赖于上游设置。
虽然git log -1 --format=%ad d0cdfd77733ad946e8c60e9b50286778fb813e56工作正常:

$ git log -1 --format=%ad d0cdfd77733ad946e8c60e9b50286778fb813e56
Wed Aug 17 15:47:50 2022 -0700

我个人更喜欢git log --no-walk。可以将多个提交哈希ID写入git log --no-walk(例如,使用--stdin),而-1则不是这种情况。在这个特定的情况下,您希望一次控制一个项目,但没有压倒一切的理由选择--no-walk
最终脚本可能类似于:

git for-each-ref --format='%(objectname) %(refname:short)' refs/remotes |
grep -E -v '/master$|/HEAD$' |
while read hash ref; do
    author=$(git log --no-walk --format="%an (%ae)" $hash);
    authordate=$(git log --no-walk --format="%ad" $hash);
    aheadbehind=$(git rev-list --count --left-right $hash...origin/master);
    ... insert other items here as desired ...
    echo "$ref,$hash,$author,$authordate,$aheadbehind,..."
done > output-csv.csv

、或类似物。
如果您只需要“超前”计数,而不是超前和滞后,请注意git rev-list --count refs/remotes/origin/master..$hash(注意:* 两个 * 点,没有--left-right)获得该数字。
这 * 可以 * 变得更高效,代价是可读性降低。最大的效率增益可能是通过在指定的哈希值上使用单个git log调用来实现的:您可能能够以正确的格式生成所需的大部分信息。但是,请注意,有些人的姓名可能包含逗号(或CSV文件的任何分隔符)。对文本进行净化总是明智的。您不希望在出现Little Bobby Tables时成为负责数据库的学校管理员。

相关问题