Git 在这样的工作环境中,您如何计算出上一个标记?

Git 在这样的工作环境中,您如何计算出上一个标记?,git,build,tags,workflow,Git,Build,Tags,Workflow,我有一个项目,我使用了一个相当不寻常的标签策略。我们的标签最后是叶子,因此我们的历史如下所示: 0.3.0 0.3.0 |/ | | 0.2.0 rather than 0.2.0 |/ | | 0.1.0 0.1.0 |/

我有一个项目,我使用了一个相当不寻常的标签策略。我们的标签最后是叶子,因此我们的历史如下所示:

  0.3.0                        0.3.0
|/                               |
| 0.2.0      rather than       0.2.0
|/                               |
| 0.1.0                        0.1.0
|/                               |
我这样做的原因是,我们的标记应该包括
dist
输出,而在开发过程中,我们不希望将这些文件提交到版本控制中。因此,当我运行构建时,构建工具会自动分支,使用生成的提交添加构建工件(
dist
文件夹),然后在那里创建标记

这个工作流乍一看可能有些奇怪,但到目前为止,我发现它非常方便,因为我们需要在标记中包含
dist
文件夹,以便进行下游部署过程


现在的问题是,我想自动生成发行说明,问题是,在这样的场景中,我如何计算出前面的标记?我知道给出的答案,但由于标签是叶子,这不起作用。

这是迄今为止我能想到的最好的事情:

git标记| sort-n-t-k1,1-k2,2-k3,3 |尾-1

排序只是以一种理智的方式对它们进行排序


但是,这并没有真正考虑到您当前的
头部位置。因此,如果您签出
0.2.0
,然后运行它,您仍然会得到
0.3.0
作为前一个标记,这并不完全正确。然而,对于我的用例来说,这不是一个大问题,但如果有人能想出一些真正正确的方法,我仍然很感兴趣。

您需要一种不同的方法,使用多个回购协议(毕竟,Git是一种分布式VCS):

  • 正如你所描述的
  • 一个具有与发布分支组合的发布标签:
您的发布是您在为每个发布创建的发布分支上的最新提交:

0.3.0--(dist) 0.3.0-branch
  |
0.2.0--(dist) 0.2.0-branch
  |
0.1.0--(dist) 0.1.0-branch
  |
这使您能够:

  • 将标签贴在主支管上
  • 通过在标记之间轻松查找提交来推断发行说明(例如,
    git descripe
    在这里实际起作用)
  • 有一个发布分支专门用于存储您的
    dist
    文件夹,但也可以进行热修复
  • 当这些热修复程序出现时,在所述发布分支上标记更多提交(
    0.1.1
    0.1.2
    ,…)
您所需要做的就是在发布分支的顶部创建一个标记,并将该标记(和分支)推送到发布repo上,这符合部署系统的预期:

 0.3.0
|/
| 0.2.0
|/
| 0.1.0
|/   

如果“叶”标记只有一个来自主分支的提交:

git log --pretty=format:"%d %h %s" | grep '^ (' | grep -A2 '0.3.0' | tail -n1
您得到了包含以前版本标签的行,如:

 (0.2.0) b5f4956 Commit message
使用awk抓取()中的标记或()后的sha1以继续您的工作


你可以根据你的情景将
grep-A2
调整为
-A1
-B2

如果我理解正确,当你当前的头在
0.3.0
时,你想得到
0.2.0
,而在
0.2.0
时,你想得到
0.1.0
,依此类推。您可以通过两个步骤完成此操作:

  • 使用git descripe--tags获取当前标记

  • 获取按日期排序的标记列表,当前标记后的行应为前一个标记

  • 例如:

    current=$(git describe --tags)
    git for-each-ref --sort=-authordate refs/tags --format '%(refname)' | \
      cut -d/ -f3 | grep -A1 -F $current | tail -n 1
    
    如果这仍然不是您想要的,请告诉我。

    (编辑:下面的原始答案,这里有一种更简单的方法,可以让标记合并基础,以便git description
    可以找到它们

    doit () 
    { 
        cleanup="`mktemp -t`";
        git for-each-ref refs/tags/"$1" --format='
               echo git tag -d base/%(refname:short) >> '"$cleanup"'
               git tag base/%(refname:short) $(git merge-base HEAD %(refname:short))
            ' | sh -x;
        result=`git describe --tags`;
        sh -x "$cleanup";
        rm "$cleanup"
        echo ${result#base/}
    }
    doit "0.*"
    
    )


    通过以下方式使用
    latest.awk

    doit ()
    {
            git rev-list --topo-order --first-parent --children --tags --format=%d \
            | awk -f path/to/latest.awk \
            | sed -n /$1"/,$ { /"$1"/! {p;q} }"
    }
    
    测试:

    ~/sandbox/15$git lgdo--topo order--tags

    *ecb363d(标签:tag4)tag4

    *cd9f402主机

    |*26aa94b(标签:tag3)tag3

    |/

    *a1b6c1b主机

    |*8866091
    (标记:tag2)

    |/

    *b5d5283主机

    |*29a4e54
    (标记:tag1)

    |/

    *cfcd7dc主机

    *6120ab4(标记:空)

    ~/sandbox/15$doit tag2

    29a4e54debae973dfc3955d6663f14d6ade73df9(标签:tag1)

    ~/sandbox/15$

    (编辑:和

    )



    git lgdo
    git log--graph--decoration--oneline
    的别名,其中的“master”是一个提交消息工件,使我成为提交助手)

    是的,我知道这样会更好。然而,我们的部署目前只监视标记,并将它们作为版本选择,以便在用户可见的管理区域中提供。不幸的是,不能告诉部署系统只监视具有给定命名约定的标记。因此,如果我这样做,那么没有
    dist
    文件夹的所有常规标记(或分支)也会进入管理页面。这反过来意味着它列出了很多版本,如果用户尝试这些版本,这些版本将无法工作。我知道,实际上应该修复的是部署系统。但我没有那个密码,只是想进一步澄清一下。我也不能让它监视新的分支。我对一个简单的监听器处理新标签的能力非常有限,所有标签都将被平等处理:-/@克里斯托夫:没问题。我编辑了我的答案,以满足部署系统的特定需求。如果您签出
    0.2.0
    ,则
    git description--tags
    将为您提供
    0.2.0
    。这不是你想要的吗?不,我需要从叶子中找出上一个标记,这就是为什么
    git descripe
    不起作用。我的答案对你不起作用?只是好奇。。。(似乎对我有用…)我仍然建议保持适当的结构(在一个回购协议中标记主分支,在另一个回购协议中释放分支,如我的回答所示。但你的方法似乎正好回答了问题
    ~/sandbox/15$ git checkout tag4
    HEAD is now at ecb363d...  tag4
    ~/sandbox/15$ git describe --tags
    tag4
    ~/sandbox/15$ doit `git describe --tags`
    26aa94bad1e37602791c354823cb4a84ff6fc437  (tag: tag3)
    ~/sandbox/15$