【问题标题】:How to auto include the newest git commit metadata into the commited files?如何将最新的 git commit 元数据自动包含到提交的文件中?
【发布时间】:2020-10-22 05:32:55
【问题描述】:

我的目标是在每个文件的顶部添加一个基本的更改日志,例如:

# Changelog: 
# Last Modified on: 31.2.2020
# Last Modified by: Arthur Dent
# Last Modification: "After a Trillian tries, it works"
# File created: 01.01.1970

def whale2pot(args) ....

现在,为了不必手动执行此操作,我想包含

的输出
git log -1

到此提交所涉及的文件。 (虽然不确定是否包含提交消息是明智的..)

执行此操作的一种方法是通过 bash 脚本,该脚本将上述输出添加到文件中。 但这会修改​​文件,并且 repo 实际上永远不会是最新的。

因此:有没有办法“超载”git commit 或以某种方式在 git 不注意的情况下将其潜入?

提前致谢 =)

【问题讨论】:

  • 我想知道预提交挂钩是否可以解决问题。
  • 你不能使用上次提交的信息因为会改变需要新修订版的文件内容创建以保存此修改。
  • 这当然是可行的,不过,如果不把 repo 变成合并的噩梦,我只是没有正确的想法。
  • @GregBurghardt,感谢您向我介绍 git hooks。我将使用 pre-push 钩子尝试它,因为我想在最后一次提交的输出之前添加。不过,如果我要推送多个提交,我猜这将是一个挑战。 ¯_(ツ)_/¯

标签: bash git logging header changelog


【解决方案1】:

经过一番修改,我选择了这种格式(这里是 .m 文件):

%% ------------------------------------------------  
%  
% Created on:       <date_of_creation>  
% Author:           <author>  
%  
% Last modifier:    <modifier>  
% Last modified:    <date_of_last_mod>  
% On Branch:        <branch>  
%  
%%-------------------------------------------------

...并意识到我不需要提交元数据来实现我的目标。我明白了:

  • 日期来自$(date)
  • 来自$(git config user.name)的作者/修改者
  • 来自$(git rev-parse --abbrev-ref HEAD)的当前分支

我仍然遵循 @LeGEC 的 方法,即拥有一个执行两件事的脚本,如下所示:

  • insert_changelog.sh:这可确保每个具有特定扩展名的未跟踪文件都会收到更改日志。进一步填充&lt;date_of_creation&gt;&lt;author&gt;的静态信息。
  • update_changelog.sh:此脚本更新每个跟踪和修改文件的后 3 个字段。

目前,我在运行git add &lt;modified files&gt;之前手动运行它。

我在下面附加代码。这是我的第一次 bash 脚本编写经验,请随时指出可以改进的地方


insert_changelog.sh:

#!/bin/bash

#If there are no .m files for which this would apply, suppress the this notification (If i get that right)
shopt -s nullglob

#Act on untracked files 
files=($(git ls-files --others --exclude-standard))
for item in ${files[*]}
do
    #For time being, only consider matlab files
    if [[ $item == *.m ]]
    then
        #Check whether the header already exists
        read -r first_line < $item 
        first_cl_line="%% ------------------------------------------------"
        if [ "$first_line" = "$first_cl_line" ]
        then
            continue
        else
            #Include Changelog into file
            cat changelog_template.txt > tempfile
            cat $item >> tempfile 
            mv tempfile $item

            #Fill in static fields of inception date and author
            sed -i "3,4d" $item
            sed -i "2 a % Created on:       $(date)" $item
            sed -i "3 a % Author:           $(git config user.name)" $item

            #Update current changelog
            ./update_changelog.sh $item
        fi
    fi
done;

update_changelog.sh:

#!/bin/bash
USER=$(git config user.name)  
BRANCH=$(git rev-parse --abbrev-ref HEAD)  
#Remove outdated lines and replace with updated ones.  
   for item in $(git ls-files -m)  
   do  
       sed -i "5,8d" $item  
       sed -i "5 a % Last Modifier:    $USER" $item  
       sed -i "6 a % Last Modified:    $(date)" $item  
       sed -i "7 a % On Branch:        $BRANCH" $item  
       sed -i "8 a %" $item  
   done;

【讨论】:

    【解决方案2】:

    在您的存储库中有如此明显的合并冲突来源可能会令人惊讶,
    当你浏览你的 repo (git log -1 the/file) 时,很容易从 git 中提取信息。

    在深入研究如何实际将该信息存储在文件内容中之前, 也许您可以选择一个方便的 shell 快捷方式,或者集成到您的编辑器中的大纲? vscode 例如有 git lens 扩展,它给你一些非常接近的东西(实际上是每行注释)


    创建日期将是相当静态的,因此可以在文件创建时插入并保持这种状态;

    对于标题的其他部分:我认为filter 将是最接近正确的方法

    这里的官方文档:gitattributes

    请参阅此 SO 答案中的解释:Can git filter out certain lines before commit?

    你会写两个脚本:

    • 其中一个 clean 脚本将用常量值替换标题行(例如:# Last Modified : 没有日期)
    • 第二个脚本 smudge 将运行 git log -1 并用所需的值填充行

    clean 脚本将在暂存文件时运行,并确保存储在 git 中的 blob 具有恒定的标头,以避免在合并、变基等时出现问题

    smudge 脚本将在签出文件时运行,并将在工作树版本中写入正确的内容——磁盘上的文件,您将在编辑器中实际打开该文件。


    此答案中未排序的要点是:涂抹脚本在标准输入上接收 文件的内容,而不是 文件的名称,所以我看不到干净的从该脚本运行git log -1 file/name 的方法。

    【讨论】:

    • "[在此处插入指向相关@VonC 答案的链接]" 链接仍然丢失! :-)
    • @phd 你是说stackoverflow.com/a/59336862/6309吗?但不要忘记使用 Git 2.27+:stackoverflow.com/a/60905975/6309
    • @VonC :我在想一个更简单的解释 :) 关于内容过滤器:只有设置一个长时间运行的过滤器进程 (filter.[driver].process),您才能访问这些信息,对吗?没有办法将它们插入涂抹脚本?
    • @LeGEC 我通常只使用涂抹/脚本,而不是git-scm.com/docs/gitattributes#_long_running_filter_process中描述的长时间运行的过滤器
    • 谢谢大家很高兴,互联网真是个好地方! this Stack Exchange answer 似乎可以解决问题。会及时通知您。
    猜你喜欢
    • 2015-06-26
    • 2014-11-20
    • 1970-01-01
    • 2017-08-16
    • 2011-09-25
    • 2011-06-14
    • 2021-06-21
    • 2011-04-06
    • 2015-04-30
    相关资源
    最近更新 更多