我可以将元数据添加到 git 提交吗?或者我可以在 gitk 中隐藏一些标签吗
我想将自定义元数据与 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Git-notes
使用 git Notes,您可以向提交添加“注释”。您还可以添加它们
到其他 Git 对象,但我们只关注提交,因为这就是
问题是关于。
注释是一个 Git 对象,原则上可以是“任何”(任意)
数据)。但出于我们的目的,我们将专注于简单和文本的内容。
示例:review id
该问题提到了review id,所以让我们用一些方式来表示
这样的事。我不知道评论 ID 到底是什么样子,但是
希望以下内容是明智的:
所以这实际上是一个键值对。让我们将上面的字符串添加到
当前提交:
如果您运行
git log
,注释将内联显示:[1]另一个示例
当然,您可以向此注释添加更多“子注释”(我们将坚持使用
简单的
key: value
语法,每行一个值)。例如,如果您三个月后发现commit message有东西
错误,只需将更正附加到注释中:
git log
:我们使用
gitnotesappend
以便轻松地将这些额外数据添加到笔记。您还可以使用 git Notes edit 来编辑文件
直接地。
当然,由于 Git 注释只是一个可变文件,因此您可以运行
陷入合并冲突。为了降低这种可能性,您可以:
man git-notes
,“注释”部分合并策略”。
可见性
OP 询问:
> 我可以让某些标签不可见吗?
默认情况下,
git log
只显示一条注释,即.git/refs/notes/commits
。commits
只是命名空间中的一个注释。也许您希望问题位于自己的命名空间中:
因为它存储在 .git/refs/notes/issues 中,而不是存储在
.git/refs/notes/commits
,运行时不会显示“Fixes: #32”git 日志
。因此,您实际上已默认将此类注释设置为不可见。如果您希望显示它,请将
--notes=issues
传递给git log
:但现在
.git/refs/notes/commits
是隐。那一个可以很容易地被还包括:
有一些变量可以配置默认显示哪些注释;看
man git-config
。与提交消息相比的好处
元数据当然可以直接记录在提交消息中。 [1] 但是
提交消息是不可变的,因此更改它们实际上意味着创建一个
全新的承诺,以及随之而来的所有连锁反应。
另一方面,Git-notes 是可变的,所以你总是能够
修改它们。而每一个笔记的修改当然都是版本
受控。在我们的例子中,对于
.git/refs/notes/commits
:另一个好处是您可以放置仅在某些情况下有用或有趣的元数据。例如,Git 项目存储提交补丁来自的电子邮件消息 ID:
这里我们可以将消息 ID 粘贴到以下位置的末尾:
并获取补丁电子邮件的链接以及有关该补丁的所有讨论:
https://lore.kernel.org/git/[email protected]/
与提交消息相比的缺点
最大的缺点是如果您使用 git-rebase(1) 之外的重写机制和 <代码>git commit --amend (如 git-cherry-pick(1),如果你认为这是“重写”);请参阅后面的“重写”部分。
此外,它是一个(或多个,如果使用更多命名空间)更多级别的间接。如果您在将元数据提交到“永久历史记录”之前确定自己的元数据,那么您可以将其添加到提交消息中。
没有什么可错过或忘记取的。没有可以忽略的上下文。
共享笔记
默认情况下,您的笔记不会被共享;你必须明确地这样做。和
与其他参考文献相比,共享笔记不太人性化。我们有
使用refspec语法:
上面的代码会将您的所有笔记推送到遥控器。
看来取笔记有点复杂;你可以做到,如果
您指定了 refspec 的两侧:
所以这绝对不方便。如果你打算使用 Git-notes
通常,您可能需要将 gitconfig 设置为始终获取
Notes:
这将从远程获取所有笔记,但拒绝更新您的
如果更新不是快进,则为本地引用。如果你想永远
根据远程更新您的本地引用(即使它不是
快进),添加一个
+
:假设您想遵循前面提到的
amlog
注释GitHub Git 镜像。然后您可以添加以下内容:
请注意,这里我们需要
+
因为历史记录是有规律的压扁了。
旁注:为所有参考更新启用参考日志
一旦您开始从事共享笔记业务,您应该
为所有引用启用引用日志,以便您拥有所有引用日志
你的笔记。
这样你就可以重置强制更新你的笔记的获取:(
这里我们想要倒数第二次提交)
通过使用:
继承重写笔记(不同的机制)
这里的故事是方格的。一些重写机制适用于注释(通过某些设置),而另一些则不适用。
变基和修改
Git 有一个不方便的默认设置,即提交时注释不会被保留
使用 git-rebase(1) 和 git commit --amend 重写。所以如果你为了
示例 rebase 一系列提交,注释不会延续到
新的提交。
变量
notes.rewrite.
默认设置为true
,因此可以假设注释被继承。但问题是变量
notes.rewriteRef
,它决定哪些笔记将被结转,没有默认值。要设置此值以匹配所有注释,请执行以下命令:
现在,在执行 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 在评论中提及)您可能会
只是想将数据合并到提交消息中,如果你真的
想要将注释作为正确的元数据共享。
变更日志(主要)
+
refspeclogAllRefUpdates
的旁注部分注释
“这是
git log
的默认设置 [ …]当没有--pretty
时,--format
或命令行上给出的--oneline
选项。” ―man git-log
,git 版本 2.10.2在 Git 和 Linux 内核等项目中使用的元数据提交消息的一种做法/惯例是添加密钥 –提交消息的“预告片”中的值对,即底部。例如,请参阅此提交 作者:莱纳斯·托瓦兹 (Linus Torvalds):
参见:
man git-interpret-trailers
(通常是键值对)用于各种项目。
我很确定 Git 邮件列表上已经对此进行了讨论。我能找到的最好的来源是这个.
Git-notes
With
git notes
you can add a “note” to a commit. You can also add themto 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:
So this is effectively a key-value pair. Let’s add the above string to
the current commit:
If you run
git log
the note will be shown inline: [1]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 youfound out three months later that the commit message got something
wrong, just append the correction to the note:
git log
:We use
git notes append
in order to easily add this extra data to thenote. You could also use
git notes edit
in order to edit the filedirectly.
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:
man git-notes
, section “Notesmerge 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:
Since this is stored in
.git/refs/notes/issues
and not in.git/refs/notes/commits
, “Fixes: #32” won’t show up when you rungit log
. So you have effectively made such notes invisible by default.If you want it to be shown, pass
--notes=issues
togit log
:But now
.git/refs/notes/commits
are hidden. That one can easily beincluded as well:
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
: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:
Here we can paste the message id at the end of:
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:
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:
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:
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
+
:Say you want to follow the aforementioned
amlog
notes on theGitHub Git mirror. Then you can add this:
Note that we need
+
here since the history is regularlysquashed.
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.
That way you can reset a fetch that force-updated your notes:
(Here we want the penultimate commit)
By using:
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 forexample rebase a series of commits, the notes will not carry over to the
new commits.
The variable
notes.rewrite.<command>
is by default set totrue
, so one mightassume that notes are carried over. But the problem is that the variable
notes.rewriteRef
, which determines which notes will be carried over, has nodeafult vaule. To set this value to match all notes, execute the following:
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)
git-format-patch
(thanks to larsks)+
refspeclogAllRefUpdates
Notes
“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.2One 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:
See:
man git-interpret-trailers
(usually key–value pairs) that are used in various projects.
I’m pretty sure that this has been discussed on the Git mailing list. The best source I could find is this.
这正是 git 笔记 的用途。
That's precisely what git notes are for.