我可以将元数据添加到 git 提交吗?或者我可以在 gitk 中隐藏一些标签吗

发布于 2024-08-30 02:19:25 字数 218 浏览 8 评论 0原文

我想将自定义元数据与 git commit 相关联。特别是记录来自代码审查的审查 ID,但它可以是任何东西。标签似乎是一种自然的方法,但我希望对每个提交进行审查,并且我不想用大量标签弄乱 gitk 。是否有其他机制来添加自定义元数据?我可以让某些标签不可见吗?如果我可以告诉 gitk 不要显示与某些模式或 RE 匹配的标签,这可能会起作用,但我看不到有办法做到这一点。

I want to associate custom metadata with a git commit. Specifically to record a review ID from a code review but it could be anything. Tags seem a natural way to do that but I expect to have a review for every commit and I don't want to clutter gitk with tons of tags. Is there some other mechanism to add custom metadata? Can I make certain tags invisible? If I could tell gitk not to display tags matching some pattern or RE, that would likely work but I don't see a way to do that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

嘿看小鸭子会跑 2024-09-06 02:19:25

Git-notes

使用 git Notes,您可以向提交添加“注释”。您还可以添加它们
到其他 Git 对象,但我们只关注提交,因为这就是
问题是关于。

注释是一个 Git 对象,原则上可以是“任何”(任意)
数据)。但出于我们的目的,我们将专注于简单和文本的内容。

示例:review id

该问题提到了review id,所以让我们用一些方式来表示
这样的事。我不知道评论 ID 到底是什么样子,但是
希望以下内容是明智的:

Review-id: 42

所以这实际上是一个键值对。让我们将上面的字符串添加到
当前提交:

git notes add -m "Review-id: 42"

如果您运行 git log,注释将内联显示:[1]

Author: Victor Version Control <[email protected]>
Date:   Tue Nov 8 21:10:25 2016 +0100

    Implement feature x

Notes:
    Review-id: 42

另一个示例

当然,您可以向此注释添加更多“子注释”(我们将坚持使用
简单的 key: value 语法,每行一个值)。例如,如果您
三个月后发现commit message有东西
错误,只需将更正附加到注释中:

git notes append --no-separator -m "Errata: It was actually feature y."

git log

Author: Victor Version Control <[email protected]>
Date:   Tue Nov 8 21:10:25 2016 +0100

    Implement feature x

Notes:
    Review-id: 42
    Errata: It was actually feature y.

我们使用 gitnotesappend 以便轻松地将这些额外数据添加到
笔记。您还可以使用 git Notes edit 来编辑文件
直接地。

当然,由于 Git 注释只是一个可变文件,因此您可以运行
陷入合并冲突。为了降低这种可能性,您可以:

  1. 坚持使用上面这样的简单数据(每行一个键值)。
  2. 使用特殊的合并策略;请参阅 man git-notes,“注释”部分
    合并策略”。

可见性

OP 询问:

> 我可以让某些标签不可见吗?

默认情况下,git log只显示一条注释,即
.git/refs/notes/commitscommits 只是命名空间中的一个注释。
也许您希望问题位于自己的命名空间中:

git notes --ref=issues add -m "Fixes: #32"

因为它存储在 .git/refs/notes/issues 中,而不是存储在
.git/refs/notes/commits,运行时不会显示“Fixes: #32”
git 日志。因此,您实际上已默认将此类注释设置为不可见。

如果您希望显示它,请将 --notes=issues 传递给 git log

$ git log --notes=issues
Author: Victor Version Control <[email protected]>
Date:   Tue Nov 8 21:10:25 2016 +0100

    Implement feature x

Notes (issues):
    Fixes: #32

但现在 .git/refs/notes/commits 是隐。那一个可以很容易地被
还包括:

$ git log --notes=issues --notes=commits
Author: Victor Version Control <[email protected]>
Date:   Tue Nov 8 21:10:25 2016 +0100

    Implement feature x

Notes (issues):
    Fixes: #32

Notes:
    Review-id: 42
    Errata: It was actually feature y.

有一些变量可以配置默认显示哪些注释;看
man git-config

与提交消息相比的好处

元数据当然可以直接记录在提交消息中。 [1] 但是
提交消息是不可变的,因此更改它们实际上意味着创建一个
全新的承诺,以及随之而来的所有连锁反应。
另一方面,Git-notes 是可变的,所以你总是能够
修改它们。而每一个笔记的修改当然都是版本
受控。在我们的例子中,对于 .git/refs/notes/commits

$ git log refs/notes/commits
Author: Victor Version Control <[email protected]>
commit 9f0697c6bbbc6a97ecce9834d4c9afa0d668bcad
Date:   Tue Nov 8 21:13:52 2016 +0100

    Notes added by 'git notes append'

commit b60997e49444732ed2defc8a6ca88e9e21001a1d
Author: Victor Version Control <[email protected]>
Date:   Tue Nov 8 21:10:38 2016 +0100

    Notes added by 'git notes add'

另一个好处是您可以放置​​仅在某些情况下有用或有趣的元数据。例如,Git 项目存储提交补丁来自的电子邮件消息 ID:

commit 5b2424b658701c16e4fe12babf83fdb15d0f165a
Author: Junio C Hamano <[email protected]>
Date:   Thu Oct 12 10:28:16 2023 -0700

    grep: -f <path> is relative to $cwd

    Just like OPT_FILENAME() does, "git grep -f <path>" should treat
    the <path> relative to the original $cwd by paying attention to the
    prefix the command is given.

    Signed-off-by: Junio C Hamano <[email protected]>

Notes (amlog):
    Message-Id: <[email protected]>

这里我们可以将消息 ID 粘贴到以下位置的末尾:

https://lore.kernel.org/git/

并获取补丁电子邮件的链接以及有关该补丁的所有讨论:

https://lore.kernel.org/git/[email protected]/

与提交消息相比的缺点

最大的缺点是如果您使用 git-rebase(1) 之外的重写机制和 <代码>git commit --amend (如 git-cherry-pick(1),如果你认为这是“重写”);请参阅后面的“重写”部分。

此外,它是一个(或多个,如果使用更多命名空间)更多级别的间接。如果您在将元数据提交到“永久历史记录”之前确定自己的元数据,那么您可以将其添加到提交消息中。

没有什么可错过或忘记取的。没有可以忽略的上下文。

共享笔记

默认情况下,您的笔记不会被共享;你必须明确地这样做。和
与其他参考文献相比,共享笔记不太人性化。我们有
使用refspec语法:

git push origin refs/notes/*

上面的代码会将您的所有笔记推送到遥控器。

看来取笔记有点复杂;你可以做到,如果
您指定了 refspec 的两侧:

git fetch origin refs/notes/*:refs/notes/*

所以这绝对不方便。如果你打算使用 Git-notes
通常,您可能需要将 gitconfig 设置为始终获取
Notes:

[remote "origin"]
    …
    fetch = refs/notes/*:refs/notes/*

这将从远程获取所有笔记,但拒绝更新您的
如果更新不是快进,则为本地引用。如果你想永远
根据远程更新您的本地引用(即使它不是
快进),添加一个 +

[remote "origin"]
    …
    fetch = +refs/notes/*:refs/notes/*

假设您想遵循前面提到的 amlog 注释
GitHub Git 镜像。然后您可以添加以下内容:

[remote "o"]
    url = https://github.com/git/git/
    […]
    fetch = +refs/notes/amlog:refs/notes/amlog

请注意,这里我们需要 + 因为历史记录是有规律的
压扁了。

旁注:为所有参考更新启用参考日志

一旦您开始从事共享笔记业务,您应该
所有引用启用引用日志,以便您拥有所有引用日志
你的笔记。

[core]
    […]
    logAllRefUpdates = always

这样你就可以重置强制更新你的笔记的获取:(

c4c120de490 refs/notes/commits@{1}: fetch gitster: forced-update
c5acdf419f0 refs/notes/commits@{2}: notes: Notes added by 'git commit --amend'

这里我们想要倒数第二次提交)

通过使用:

git update-ref -m 'Bad fetch' refs/notes/commits c5acdf419f0

继承重写笔记(不同的机制)

这里的故事是方格的。一些重写机制适用于注释(通过某些设置),而另一些则不适用。

变基和修改

Git 有一个不方便的默认设置,即提交时注释不会被保留
使用 git-rebase(1) 和 git commit --amend 重写。所以如果你为了
示例 rebase 一系列提交,注释不会延续到
新的提交。

变量 notes.rewrite. 默认设置为 true,因此可以
假设注释被继承。但问题是变量
notes.rewriteRef,它决定哪些笔记将被结转,没有
默认值。要设置此值以匹配所有注释,请执行以下命令:

git config --global notes.rewriteRef "refs/notes/*"

现在,在执行 git rebase 和 `git commit --amend** 等重写操作时,所有注释都将被保留。

git-cherry-pick(1)

Notes 重写不适用于 git-cherry-pick(1)。 [3]

git-filter-repo(1)

这是一个第三方工具,但通常推荐使用该程序,而不是劣质的内置 git-filter-branch(1)。

使用此工具时重写笔记不起作用。请参阅此问题

在电子邮件补丁中共享注释(注意:不用于存储)

如果您使用 git format-patch 来格式化您的更改以作为电子邮件发送,
并且您有一些元数据存储为 Git 注释,您可以传递 --notes
选项 git format-patch 以便将注释附加到电子邮件草稿中。

但请记住,这个开关看起来并不是真正的意思
用于将笔记作为元数据共享;它们只是在提交之间添加
自由格式信息中的消息和补丁适当部分
部分。所以(就像larsks 在评论中提及)您可能会
只是想将数据合并到提交消息中,如果你真的
想要将注释作为正确的元数据共享。


变更日志(主要)

  • 2023-04-28:关于 git-format-patch 的警告(感谢 larsks)
  • 2024-01-29:
    • 充实“重写”部分
    • 添加“缺点”部分(感谢 larsks)
    • 提及另一个好处
  • 2024-02-18:
    • 不要强调强制更新+ refspec
    • 添加有关 logAllRefUpdates 的旁注部分

注释

  1. “这是 git log 的默认设置 [ …]当没有--pretty时,
    --format 或命令行上给出的 --oneline 选项。” ― man git-log,git 版本 2.10.2

  2. 在 Git 和 Linux 内核等项目中使用的元数据提交消息的一种做法/惯例是添加密钥 –提交消息的“预告片”中的值对,即底部。例如,请参阅此提交 作者:莱纳斯·托瓦兹 (Linus Torvalds):


    mm:从 __get_user_pages() 中删除 gup_flags FOLL_WRITE 游戏
    这是一个古老的错误,实际上曾经尝试修复过一次
    (严重)十一年前我在提交 4ceb5db9757a 中(“修复
    get_user_pages() 争夺写访问权限”),但随后由于以下原因而被撤消
    s390 上的问题,提交 f33ea7f404e5(“修复 get_user_pages bug”)。
    
    与此同时,s390的情况早已得到解决,我们现在可以
    通过正确检查 pte_dirty() 位来修复它(并且做得更好)。这
    s390脏位在abf09bed3cce中实现(“s390/mm:实现
    软件脏位”),它进入了 v3.9。早期的内核将
    必须查看页面状态本身。
    
    此外,VM 变得更具可扩展性,并且使用纯粹的
    那时的理论竞赛已经变得更容易触发。
    
    为了解决这个问题,我们引入了一个新的内部 FOLL_COW 标志来标记“是的,
    我们已经做了 COW”,而不是用 FOLL_WRITE 玩激烈的游戏
    非常基础,然后使用 pte dirty 标志来验证
    FOLL_COW 标志仍然有效。
    
    报告和测试者:Phil“不是 Paul”Oester <[电子邮件受保护] >
    确认者:Hugh Dickins [电子邮件受保护]>
    审核者:Michal Hocko <[电子邮件受保护]>
    抄送:Andy Lutomirski [电子邮件受保护]>
    抄送:Kees Cook [电子邮件受保护]>
    抄送:Oleg Nesterov [电子邮件受保护]>
    抄送:Willy Tarreau <[电子邮件受保护]>
    抄送:Nick Piggin [电子邮件受保护]>
    抄送:Greg Thelen <[电子邮件受保护]>
    抄送:[电子邮件受保护]
    签署人:Linus Torvalds [电子邮件受保护]>
    

    参见:

    • man git-interpret-trailers
    • submitting-patches 记录Linux 内核项目中使用的常见预告片
    • 此内核 Wiki 页面,其中列出了各种预告行
      (通常是键值对)用于各种项目。
  3. 我很确定 Git 邮件列表上已经对此进行了讨论。我能找到的最好的来源是这个.

Git-notes

With git notes you can add a “note” to a commit. You can also add them
to other Git objects, but let’s just focus on commits since that is what
the question is about.

A note is a Git object, and can in principle be “whatever” (arbitrary
data). But we’ll focus on something simple and textual for our purposes.

Example: review id

The question mentions review ids, so let’s make up some way to represent
such a thing. I don’t know what review ids really look like, but
hopefully the following would be sensible:

Review-id: 42

So this is effectively a key-value pair. Let’s add the above string to
the current commit:

git notes add -m "Review-id: 42"

If you run git log the note will be shown inline: [1]

Author: Victor Version Control <[email protected]>
Date:   Tue Nov 8 21:10:25 2016 +0100

    Implement feature x

Notes:
    Review-id: 42

Another example

Of course you can add more “subnotes” to this note (we will stick with
the simple key: value syntax, one value per line). For example, if you
found out three months later that the commit message got something
wrong, just append the correction to the note:

git notes append --no-separator -m "Errata: It was actually feature y."

git log:

Author: Victor Version Control <[email protected]>
Date:   Tue Nov 8 21:10:25 2016 +0100

    Implement feature x

Notes:
    Review-id: 42
    Errata: It was actually feature y.

We use git notes append in order to easily add this extra data to the
note. You could also use git notes edit in order to edit the file
directly.

Of course, since a Git note is just a single mutable file, you can run
into merge conflicts. To make that less likely, you can:

  1. Stick to simple data like the above (one key-value per line).
  2. Use special merge strategies; see man git-notes, section “Notes
    merge strategies”.

Visibility

The OP asked:

> Can I make certain tags invisible?

By default, git log only shows one note, namely
.git/refs/notes/commits. commits is just one note in the namespace.
Maybe you want issues to be in their own namespace:

git notes --ref=issues add -m "Fixes: #32"

Since this is stored in .git/refs/notes/issues and not in
.git/refs/notes/commits, “Fixes: #32” won’t show up when you run
git log. So you have effectively made such notes invisible by default.

If you want it to be shown, pass --notes=issues to git log:

$ git log --notes=issues
Author: Victor Version Control <[email protected]>
Date:   Tue Nov 8 21:10:25 2016 +0100

    Implement feature x

Notes (issues):
    Fixes: #32

But now .git/refs/notes/commits are hidden. That one can easily be
included as well:

$ git log --notes=issues --notes=commits
Author: Victor Version Control <[email protected]>
Date:   Tue Nov 8 21:10:25 2016 +0100

    Implement feature x

Notes (issues):
    Fixes: #32

Notes:
    Review-id: 42
    Errata: It was actually feature y.

There are variables to configure which notes are shown by default; see
man git-config.

Benefits compared to commit messages

Metadata can of course be recorded in the commit message directly. [1] But
commit messages are immutable, so to change them really means to make a
whole new commit, with all the rippling consequences that that entails.
Git-notes on the other hand are mutable, so you are always able to
revise them. And each modification of a note is of course version
controlled. In our case, for .git/refs/notes/commits:

$ git log refs/notes/commits
Author: Victor Version Control <[email protected]>
commit 9f0697c6bbbc6a97ecce9834d4c9afa0d668bcad
Date:   Tue Nov 8 21:13:52 2016 +0100

    Notes added by 'git notes append'

commit b60997e49444732ed2defc8a6ca88e9e21001a1d
Author: Victor Version Control <[email protected]>
Date:   Tue Nov 8 21:10:38 2016 +0100

    Notes added by 'git notes add'

Another benefit is that you can put metadata that might only be useful or interesting in certain circumstances. For example, the Git project stores the email message id of where the patch of the commit came from:

commit 5b2424b658701c16e4fe12babf83fdb15d0f165a
Author: Junio C Hamano <[email protected]>
Date:   Thu Oct 12 10:28:16 2023 -0700

    grep: -f <path> is relative to $cwd

    Just like OPT_FILENAME() does, "git grep -f <path>" should treat
    the <path> relative to the original $cwd by paying attention to the
    prefix the command is given.

    Signed-off-by: Junio C Hamano <[email protected]>

Notes (amlog):
    Message-Id: <[email protected]>

Here we can paste the message id at the end of:

https://lore.kernel.org/git/

And get a link to the patch email and in turn all the discussion on it:

https://lore.kernel.org/git/[email protected]/

Drawbacks compared to commit messages

The biggest drawback is if you use rewrite mechanisms beyond git-rebase(1) and git commit --amend (like git-cherry-pick(1), if you consider that “rewriting”); see the later “rewrites” section.

Also, it’s one (or more, if more namespaces are used) more level of indirection. If you are sure about your metadata prior to committing it to the “permanent history” then you can just add it to the commit message.

Nothing to miss or forget to fetch. No context that can be elided.

Sharing notes

Your notes aren’t shared by default; you have to do so explicitly. And
compared to other refs, sharing notes isn’t very user-friendly. We have
to use the refspec syntax:

git push origin refs/notes/*

The above will push all of your notes to your remote.

It seems that fetching notes is a bit more involved; you can do it if
you specify both sides of the refspec:

git fetch origin refs/notes/*:refs/notes/*

So that’s definitely not convenient. If you intend to use Git-notes
regularly, you’ll probably want to set up your gitconfig to always fetch
notes:

[remote "origin"]
    …
    fetch = refs/notes/*:refs/notes/*

This will fetch all notes from the remote but refuse to update your
local ref if the update is not a fast-forward. If you want to always
update your local ref according to the remote (even if it is not a
fast-forward), add an +:

[remote "origin"]
    …
    fetch = +refs/notes/*:refs/notes/*

Say you want to follow the aforementioned amlog notes on the
GitHub Git mirror. Then you can add this:

[remote "o"]
    url = https://github.com/git/git/
    […]
    fetch = +refs/notes/amlog:refs/notes/amlog

Note that we need + here since the history is regularly
squashed.

Side note: enable reflog for all ref updates

Once you start getting into the business of sharing notes, you should
enable the reflog for all refs so that you have reflogs for all of
your notes.

[core]
    […]
    logAllRefUpdates = always

That way you can reset a fetch that force-updated your notes:

c4c120de490 refs/notes/commits@{1}: fetch gitster: forced-update
c5acdf419f0 refs/notes/commits@{2}: notes: Notes added by 'git commit --amend'

(Here we want the penultimate commit)

By using:

git update-ref -m 'Bad fetch' refs/notes/commits c5acdf419f0

Carry over notes on rewrites (different mechanisms)

The story here is checkered. Some rewrite mechanisms work with notes (with some setup) while others do not.

Rebase and amend

Git has the inconvenient default that notes are not carried over when a commit
is rewritten with git-rebase(1) and git commit --amend. So if you for
example rebase a series of commits, the notes will not carry over to the
new commits.

The variable notes.rewrite.<command> is by default set to true, so one might
assume that notes are carried over. But the problem is that the variable
notes.rewriteRef, which determines which notes will be carried over, has no
deafult vaule. To set this value to match all notes, execute the following:

git config --global notes.rewriteRef "refs/notes/*"

Now all notes will be carried over when doing rewrite operations like git rebase and `git commit --amend**.

git-cherry-pick(1)

Notes rewriting does not work with git-cherry-pick(1). [3]

git-filter-repo(1)

This is a third-party tool but is the commonly recommended program to be used instead of the inferior built-in git-filter-branch(1).

Rewriting notes does not work when using this tool. See this issue.

Sharing notes in email patches (note: not for storing)

If you are using git format-patch to format your changes to be sent as emails,
and you have some metadata stored as Git notes, you can pass the --notes
option to git format-patch in order to append the notes to the email draft.

But keep in mind that this switch doesn’t really seem like it is meant
for sharing notes as metadata; they are just added between the commit
message and the patch proper part, in the free-form information
section. So (like larsks mentions in the comments) you might
just want to incorporate the data in the commit message, if you really
want to share the note as proper metadata.


Changelog (major)

  • 2023-04-28: caveat about git-format-patch (thanks to larsks)
  • 2024-01-29:
    • Flesh out “rewrite” section
    • Add a “drawbacks” section (thanks to larsks)
    • Mention another benefit
  • 2024-02-18:
    • Don’t emphasize force-update + refspec
    • Add side-note section about logAllRefUpdates

Notes

  1. “This is the default for git log […] when there is no --pretty,
    --format, or --oneline option given on the command line.” ― man git-log, git version 2.10.2

  2. One practice/convention for metadata-in-commit-messages that is used in projects like e.g. Git and the Linux kernel is to add key–value pairs in the “trailer” of the commit message, i.e. at the bottom. See for example this commit by Linus Torvalds:

    mm: remove gup_flags FOLL_WRITE games from __get_user_pages()
    This is an ancient bug that was actually attempted to be fixed once
    (badly) by me eleven years ago in commit 4ceb5db9757a ("Fix
    get_user_pages() race for write access") but that was then undone due to
    problems on s390 by commit f33ea7f404e5 ("fix get_user_pages bug").
    
    In the meantime, the s390 situation has long been fixed, and we can now
    fix it by checking the pte_dirty() bit properly (and do it better).  The
    s390 dirty bit was implemented in abf09bed3cce ("s390/mm: implement
    software dirty bits") which made it into v3.9.  Earlier kernels will
    have to look at the page state itself.
    
    Also, the VM has become more scalable, and what used a purely
    theoretical race back then has become easier to trigger.
    
    To fix it, we introduce a new internal FOLL_COW flag to mark the "yes,
    we already did a COW" rather than play racy games with FOLL_WRITE that
    is very fundamental, and then use the pte dirty flag to validate that
    the FOLL_COW flag is still valid.
    
    Reported-and-tested-by: Phil "not Paul" Oester <[email protected]>
    Acked-by: Hugh Dickins <[email protected]>
    Reviewed-by: Michal Hocko <[email protected]>
    Cc: Andy Lutomirski <[email protected]>
    Cc: Kees Cook <[email protected]>
    Cc: Oleg Nesterov <[email protected]>
    Cc: Willy Tarreau <[email protected]>
    Cc: Nick Piggin <[email protected]>
    Cc: Greg Thelen <[email protected]>
    Cc: [email protected]
    Signed-off-by: Linus Torvalds <[email protected]>
    

    See:

    • man git-interpret-trailers
    • submitting-patches documents the common trailers used in the Linux Kernel project
    • This Kernel Wiki page which lists various trailer lines
      (usually key–value pairs) that are used in various projects.
  3. I’m pretty sure that this has been discussed on the Git mailing list. The best source I could find is this.

鹤仙姿 2024-09-06 02:19:25

这正是 git 笔记 的用途。

That's precisely what git notes are for.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文