如何将最新的 git 提交元数据自动包含到提交的文件中?

How to auto include the newest git commit metadata into the commited files?

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

# 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 脚本,该脚本将上述内容的输出添加到文件中。 但这会修改​​文件,并且存储库实际上永远不会是最新的。

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

提前致谢=)

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

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


创建日期非常固定,因此可以在文件创建时插入并保持原样;

对于 header 的其他部分:我认为 filter 最接近正确的方法

官方文档在这里:gitattributes

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

你会写两个脚本:

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

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

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


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

经过一些修改,我选择了这种格式(这里是.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)
  • 的 Author/Modifier
  • 来自$(git rev-parse --abbrev-ref HEAD)
  • 的当前分支

我还是遵循了@LeGEC的方法,一个脚本做两件事,如下:

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

目前,我运行在运行宁git add <modified files>之前手动完成此操作。

我在下面附加了代码。这是我的第一次 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;