235

我已经使用 Git 有一段时间了,最​​近我开始使用它来标记我的版本,以便我可以更轻松地跟踪更改并能够查看我们的每个客户正在运行的版本(不幸的是,目前的代码要求每个客户都有自己的 PHP 站点副本;我正在更改此内容,但进展缓慢)。

无论如何,我们开始建立一些动力,我认为能够向人们展示自上次发布以来发生的变化真的很好。问题是,我没有维护变更日志,因为我不知道如何去做。在这段特殊的时间里,我可以浏览日志并手动创建一个,但这很快就会很累。

我尝试用谷歌搜索“git changelog”和“git manage changelog”,但我没有找到任何真正谈论代码更改工作流程以及它如何与更改日志一致的内容。我们目前正在关注Rein Henrichs 的开发工作流程,我会喜欢随之而来的东西。

是否有我缺少的标准方法,或者这是一个每个人都做自己的事情的领域?

4

11 回答 11

199

这是在 2015 年,但为了未来的搜索者,现在可以生成华丽的日志:

git log --oneline --decorate

或者,如果你想要它更漂亮(终端颜色):

git log --oneline --decorate --color

我目前在所有项目中都使用管道输出到ChangeLog ,这简直太棒了。

于 2014-03-18T22:30:40.637 回答
65

您可以使用一些风味git log来帮助您:

git log --pretty=%s                 # Only prints the subject

如果您很好地命名您的分支,以便合并到 master 显示为类似“Merged branch feature-foobar”的内容,您可以通过仅显示该消息来缩短内容,而不是您合并的所有小提交,它们一起形成特征:

git log --pretty=%s --first-parent  # Only follow the first parent of merges

您可能可以使用自己的脚本来扩充它,它可以执行诸如去除“合并分支”位、标准化格式等操作。当然,在某些时候您必须自己编写它。

然后,您可以为每个版本的更改日志创建一个新部分:

git log [opts] vX.X.X..vX.X.Y | helper-script > changelogs/X.X.Y

并在您的版本发布提交中提交。

如果您的问题是那些提交主题与您想要放入更改日志中的内容不同,那么您几乎有两个选择:继续手动执行所有操作(并尝试更经常地跟上它,而不是玩catch-在发布时更新),或修复您的提交消息样式。

一种选择,如果主题不打算为你做这件事,将在你的提交消息的正文中放置诸如“更改:添加的功能 foobar”之类的行,以便稍后你可以做一些事情,比如git log --pretty=%B | grep ^change:只抓取那些超级- 消息的重要部分。

我不完全确定 Git 能真正帮助您创建变更日志的程度。也许我误解了您所说的“管理”是什么意思?

于 2010-08-19T20:42:39.197 回答
64

TL;DR:您可能想要检查gitchangelog 自己的更改日志或生成前一个更改日志的ASCII 输出。

如果您想从 Git 历史记录中生成变更日志,您可能需要考虑:

  • 输出格式。(纯自定义 ASCII、Debian变更日志类型、MarkdownREST等)
  • 一些提交过滤(您可能不希望看到更改日志中出现的所有拼写错误或外观更改)
  • 在包含在更改日志中之前,一些提交文本争论不休。(确保消息标准化为首字母大写或最后一个点,但它也可能会删除摘要中的一些特殊标记。)
  • 你的Git 历史兼容吗?大多数工具并不总是那么容易支持合并和标记。这取决于你如何管理你的历史。

或者,您可能需要一些分类(新事物、更改、错误修复等)。

考虑到这一切,我创建并使用了 gitchangelog。它旨在利用Git 提交消息约定来实现之前的所有目标。

必须有一个提交消息约定才能创建一个漂亮的更改日志(使用或不使用gitchangelog)。

提交消息约定

以下是对考虑添加提交消息可能有用的建议。

您可能希望将您的提交大致分成大的部分:

  • 按意图(例如:新建、修复、更改等)
  • 按对象(例如:doc、包装、代码等)
  • 按受众(例如:开发人员、测试人员、用户等)

此外,您可能想要标记一些提交:

  • 作为不应输出到您的变更日志的“次要”提交(外观更改,评论中的小错字等)
  • 如果您确实没有任何重大的功能更改,则作为“重构”。因此,这也不应该是显示给最终用户的更改日志的一部分,但如果您有开发人员更改日志,它可能会引起一些兴趣。
  • 您也可以使用“API”标记来标记 API 更改或新的 API 内容...
  • ...ETC...

尽可能多地针对用户(功能)来编写提交信息。

例子

这是git log --oneline显示如何存储此信息的标准:

* 5a39f73 fix: encoding issues with non-ASCII characters.
* a60d77a new: pkg: added ``.travis.yml`` for automated tests.
* 57129ba new: much greater performance on big repository by issuing only one shell command for all the commits. (fixes #7)
* 6b4b267 chg: dev: refactored out the formatting characters from Git.
* 197b069 new: dev: reverse ``natural`` order to get reverse chronological order by default. !refactor
* 6b891bc new: add UTF-8 encoding declaration !minor

因此,如果您注意到,我选择的格式是:

{new|chg|fix}: [{dev|pkg}:] COMMIT_MESSAGE [!{minor|refactor} ... ]

要查看实际输出结果,您可以查看gitchangelog的PyPI页面末尾。

要查看我的提交消息约定的完整文档,您可以查看参考文件gitchangelog.rc.reference

如何由此生成精美的变更日志

然后,制作完整的变更日志非常容易。您可以非常快速地制作自己的脚本,或者使用gitchangelog.

gitchangelog将生成一个完整的变更日志(具有分段支持NewFix...),并且可以根据您自己的提交约定进行合理配置。它支持任何类型的输出,这要归功于通过 、 和 的模板化MustacheMako templating并且有一个用原始 Python 编写的默认遗留引擎;当前所有三个引擎都有如何使用它们的示例,并且可以输出更改日志作为显示在gitchangelog的 PyPI 页面上的日志。

我敢肯定你知道那里还有很多其他git logchangelog工具。

免责声明:我是gitchangelog的作者,我将在下面谈到它。

于 2014-04-13T20:13:14.283 回答
30

更中肯的变更日志:

git log --since=1/11/2011 --until=28/11/2011 --no-merges --format=%B
于 2011-11-28T10:07:34.113 回答
24

gitlog-to-changelog脚本可以方便地生成 GNU 样式的ChangeLog.

如图所示,您可以使用以下任一选项gitlog-to-changelog --help选择用于生成文件的提交:ChangeLog--since

gitlog-to-changelog --since=2008-01-01 > ChangeLog

或通过在 之后传递其他参数--,这些参数将传递给git-log(由 内部调用gitlog-to-changelog):

gitlog-to-changelog -- -n 5 foo > last-5-commits-to-branch-foo

例如,我在我的一个项目的顶层使用以下规则Makefile.am

.PHONY: update-ChangeLog
update-ChangeLog:
    if test -d $(srcdir)/.git; then                         \
       $(srcdir)/build-aux/gitlog-to-changelog              \
          --format='%s%n%n%b%n' --no-cluster                \
          --strip-tab --strip-cherry-pick                   \
          -- $$(cat $(srcdir)/.last-cl-gen)..               \
        >ChangeLog.tmp                                      \
      && git rev-list -n 1 HEAD >.last-cl-gen.tmp           \
      && (echo; cat $(srcdir)/ChangeLog) >>ChangeLog.tmp    \
      && mv -f ChangeLog.tmp $(srcdir)/ChangeLog            \
      && mv -f .last-cl-gen.tmp $(srcdir)/.last-cl-gen      \
      && rm -f ChangeLog.tmp;                               \
    fi

EXTRA_DIST += .last-cl-gen

此规则在发布时ChangeLog使用最新的尚未记录的提交消息进行更新。该文件.last-cl-gen包含记录的最新提交的 SHA-1 标识符,ChangeLog并存储在 Git 存储库中。 ChangeLog也记录在存储库中,因此可以在不更改提交消息的情况下对其进行编辑(例如更正拼写错误)。

于 2013-05-24T15:24:19.043 回答
22

由于为每个版本创建标签是最佳实践,因此您可能希望按版本对变更日志进行分区。在这种情况下,此命令可以帮助您:

git log YOUR_LAST_VERSION_TAG..HEAD --no-merges --format=%B
于 2012-09-19T13:47:38.383 回答
10

我也为此做了一个图书馆。它完全可以使用Mustache模板进行配置。这样可以:

我还做了:

更多细节在 GitHub 上:https ://github.com/tomasbjerre/git-changelog-lib

从命令行:

npx git-changelog-command-line -std -tec "
# Changelog

Changelog for {{ownerName}} {{repoName}}.

{{#tags}}
## {{name}}
 {{#issues}}
  {{#hasIssue}}
   {{#hasLink}}
### {{name}} [{{issue}}]({{link}}) {{title}} {{#hasIssueType}} *{{issueType}}* {{/hasIssueType}} {{#hasLabels}} {{#labels}} *{{.}}* {{/labels}} {{/hasLabels}}
   {{/hasLink}}
   {{^hasLink}}
### {{name}} {{issue}} {{title}} {{#hasIssueType}} *{{issueType}}* {{/hasIssueType}} {{#hasLabels}} {{#labels}} *{{.}}* {{/labels}} {{/hasLabels}}
   {{/hasLink}}
  {{/hasIssue}}
  {{^hasIssue}}
### {{name}}
  {{/hasIssue}}

  {{#commits}}
**{{{messageTitle}}}**

{{#messageBodyItems}}
 * {{.}}
{{/messageBodyItems}}

[{{hash}}](https://github.com/{{ownerName}}/{{repoName}}/commit/{{hash}}) {{authorName}} *{{commitTime}}*

  {{/commits}}

 {{/issues}}
{{/tags}}
"

或者在詹金斯:

在此处输入图像描述

于 2015-12-08T12:57:54.377 回答
4

GNU 风格变更日志

对于GNU 风格的 changelog,我已经编写了函数:

gnuc() {
  {
    printf "$(date "+%Y-%m-%d")  John Doe  <john.doe@gmail.com>\n\n"
    git diff-tree --no-commit-id --name-only -r HEAD | sed 's/^/\t* /'
  } | tee /dev/tty | xsel -b
}

有了这个:

  • 在对 ChangeLog 进行最终编辑之前,我会定期提交我的更改以备份和重新设置它们
  • 然后运行:gnuc

现在我的剪贴板包含以下内容:

2015-07-24  John Doe  <john.doe@gmail.com>

        * gdb/python/py-linetable.c (): .
        * gdb/python/py-symtab.c (): .

然后我使用剪贴板作为更新 ChangeLog 的起点。

它并不完美(例如,文件应该相对于它们的 ChangeLog 路径,所以python/py-symtab.c没有,gdb/因为我将编辑gdb/ChangeLog),但它是一个很好的起点。

更高级的脚本:

不过,我必须同意 Tromey:在 ChangeLog 中复制 Git 提交数据是没有用的。

如果您要制作变更日志,请将其作为对正在发生的事情的一个很好的总结,可能在Keep a Changelog中指定。

于 2015-07-24T09:27:28.700 回答
3
git log --oneline --no-merges `git describe --abbrev=0 --tags`..HEAD | cut -c 9- | sort

是我喜欢用的。它获取自最后一个标签以来的所有提交。cut摆脱提交哈希。如果您在提交消息的开头使用票号,它们将与sort. 如果您在某些提交前加上fix,typo等,排序也会有所帮助。

于 2015-12-08T15:39:12.503 回答
3

我让CI服务器将以下内容通过管道传输到CHANGELOG为每个新版本命名的文件中,并在发布文件名中设置日期:

git log --graph --all --date=relative --pretty=format:"%x09 %ad %d %s (%aN)"
于 2016-10-01T15:34:54.957 回答
2

基于bithavoc,下面列出了最后一个标签until HEAD。但我希望列出两个标签之间的日志。

// Two or three dots between `YOUR_LAST_VERSION_TAG` and `HEAD`
git log YOUR_LAST_VERSION_TAG..HEAD --no-merges --format=%B

列出两个标签之间的日志:

// Two or three dots between two tags
git log FROM_TAG...TO_TAG

例如,这将列出来自v1.0.0to 的日志v1.0.1

git log v1.0.0...v1.0.1 --oneline --decorate

于 2016-07-12T07:02:27.390 回答