使用Git管理变更日志的一些好方法是什么?

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

在任何情况下,我们开始建立一些势头,我认为能够向人们展示自上个版本以来发生了什么变化是非常好的。问题是,我一直没有维护变更日志,因为我不知道如何去做。对于这个特定的时间,我可以遍历日志并手动创建一个,但这会很快让人厌倦。

我试着在谷歌上搜索“git changelog”;和“git管理变更日志”,但是我没有发现任何真正谈论代码变更的工作流以及它如何与变更日志相一致的内容。我们目前正在遵循Rein Henrichs的开发流程,我想要一些与此相关的东西。

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

137705 次浏览

你可以使用一些git log来帮助你:

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

如果你很好地命名你的分支,这样merge to 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

然后在你的版本release commit中提交。

如果您的问题是这些提交主题与您想要放入变更日志中的内容完全不同,那么您几乎有两个选择:继续手动完成所有事情(并尝试更定期地跟上它,而不是在发布时追赶它),或者修复您的提交消息样式。

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

我不完全确定Git还能帮助您创建更改日志。也许我误解了你说的“管理”的意思?

一个更切题的更新日志:

git log --since=1/11/2011 --until=28/11/2011 --no-merges --format=%B

由于为每个版本创建一个标记是最佳实践,您可能希望为每个版本划分您的变更日志。在这种情况下,这个命令可以帮助您:

git log YOUR_LAST_VERSION_TAG..HEAD --no-merges --format=%B

gitlog-to-changelog脚本可以方便地生成一个gnu风格的ChangeLog

gitlog-to-changelog --help所示,你可以使用选项--since选择用于生成ChangeLog文件的提交:

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包含在ChangeLog中记录的最新提交的SHA-1标识符,并存储在Git存储库中。ChangeLog也被记录在存储库中,这样它就可以在不改变提交消息的情况下被编辑(例如纠正拼写错误)。

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

git log --oneline --decorate

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

git log --oneline --decorate --color

将输出管道输送到更新日志是我目前在所有项目中使用的,这简直令人惊叹。

你可能想检查Gitchangelog自己的更新日志或生成前一个的ASCII输出

如果你想从Git历史记录中生成一个更新日志,你可能需要考虑:

  • 输出格式。(纯自定义ASCII, Debian更改日志类型,减价休息等)
  • 一些提交过滤(你可能不想在你的更改日志中看到所有的拼写错误或修饰性更改)
  • 一些提交文本争论之前被包括在更新日志。(确保消息的第一个大写字母或最后一个点是规范化的,但也可以删除摘要中的一些特殊标记。)
  • 是你的Git历史兼容?。大多数工具并不总是那么容易支持合并和标记。这取决于你如何管理你的历史。

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

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

有一个提交消息约定是必须的,以创建一个良好的变更日志(使用或不使用gitchangelog)。

提交消息约定

以下是关于在提交消息中添加哪些内容可能有用的建议。

你可能想把你的提交大致分成几个大的部分:

  • 按意图(例如:新的、修复的、改变的等等)
  • 按对象(例如:文档、打包、代码等)
  • 按受众划分(例如:开发人员、测试人员、用户等)

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

  • 作为“minor"提交不应该被输出到您的更改日志(装饰性的更改,注释中的一个小错别字,等等)
  • 作为“refactor"如果你真的没有任何重要的功能变化。因此,这也不应该是显示给最终用户的更改日志的一部分,但是如果您有一个开发人员更改日志,它可能会引起一些兴趣。
  • 你也可以加上“;API"”标记API更改或新的API内容…
  • 等……

尽可能多地以用户(功能)为目标来编写提交信息。

例子

这是标准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} ... ]

要查看实际的输出结果,可以查看gitchangelogPyPI页的末尾。

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

如何从中生成一个精致的变更日志

然后,就可以很容易地进行一个完整的更改日志。你可以很快地编写自己的脚本,或者使用gitchangelog

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

我相信你知道还有很多其他的git logchangelog工具。

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

GNU风格变更日志

对于GNU风格变更日志,我已经烹煮了函数:

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
}

用这个:

  • 我定期将我的更改提交到备份中,并在对更改日志进行最终编辑之前重新编制它们
  • 然后运行: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的观点:在更新日志中复制Git提交数据是没有用的。

如果你要做一个更改日志,让它成为一个良好的总结正在发生什么,可能在保持一个更新日志中指定。

我还为此做了一个库。它完全可以通过胡子模板进行配置。能:

我还做了:

更多详细信息见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}}
"

或者用詹金斯的话来说:

Enter image description here

git log --oneline --no-merges `git describe --abbrev=0 --tags`..HEAD | cut -c 9- | sort

是我喜欢用的。它获得自最后一个标记以来的所有提交。cut去掉提交哈希。如果你在提交消息的开头使用票号,它们会被归为sort。如果你在某些提交前加上fixtypo等前缀,排序也会有所帮助。

基于bithavoc,下面列出了最后的标记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.0v1.0.1的日志:

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

我让CI服务器为每个新版本输送以下内容到名为CHANGELOG的文件中,并在release-filename中设置日期:

git log --graph --all --date=relative --pretty=format:"%x09 %ad %d %s (%aN)"