使用git管理变更日志的好方法?


214

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

无论如何,我们正在开始建立动力,我认为能够向人们展示自上一版本以来发生了什么变化是非常好的。问题是,我没有维护变更日志,因为我对如何处理它不了解。在这段特定的时间里,我可以浏览日志并手动创建一个日志,但是那样会很累。

我尝试使用谷歌搜索“ git changelog”和“ git manage changelog”,但没有发现任何真正谈论代码更改的工作流程以及与更改日志一致的内容。目前,我们正在关注Rein Henrichs的开发工作流程,我很乐意与此同时进行。

我是否缺少标准方法,还是每个人都在做自己的事情的领域?

非常感谢您的评论/回答!

Answers:


181

这大约是3-4年前,但是为了将来的搜索者,现在可以使用以下方法生成精美的日志:

git log --oneline --decorate

或者,如果您希望它更漂亮(带有终端颜色):

git log --oneline --decorate --color

我现在在所有项目中都使用将输出输出到ChangeLog的方式,这真是太了不起了。


4
另一个有用的标记是--graph,该标记可以直观地显示提交所在的分支。
Eruant 2014年

44
我强烈建议您不要使用礼物记录差异作为CHANGELOG:keepachangelog.com
Olivier Lacan,

4
git log输出复制到changelog没有意义。您需要进行过滤和编辑工作才能获得可读的变更日志,否则,为什么还要使用变更日志?我认为您可以自动生成变更日志,但是请不要对进行原始复制git log
vaab 2015年

19
这样做的问题是,即使假设项目的每个贡献者都编写清晰可读的提交消息,您仍将生成包含“噪音”的“更改日志”。编写变更日志的目的是向项目用户解释在发行版之间发生的与他们有关显着更改,而提交消息应集中于向开发人员说明您的提交对代码哪些改进。有时那里有重叠,但并非总是如此。
Ajedi32 '16

7
或者,为了使它更具体一点,此方法将创建一个“更改日志”,其中包含许多条目,例如“ ZModule中的fooMethod的固定拼写”和“重构XModule以使用新版本的XYLibarary”。您的用户不在乎。他们想知道什么样的变化,从做他们的观点是用户,而不是你的观点作为一个开发者。甚至忽略了诸如“从xdev / foo合并PR#123”和“ Opps,已修复newFeature使其真正起作用”之类的东西,这些东西可能存在于任何现实世界的回购中。
Ajedi32 '16

60

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

git log --pretty=%s                 # only print the subject

如果您很好地命名分支,以使与master的合并显示为“ Merged branch feature-foobar”之类的内容,则可以通过仅显示该消息而不是合并的所有小提交来缩短内容,从而共同构成了特征:

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

您也许可以使用自己的脚本来对此进行扩充,该脚本可以执行以下操作:删除“合并分支”位,规范化格式等。当然,在某些时候您必须自己编写。

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

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

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

如果您的问题是那些提交主题与您想要放入变更日志中的主题不同,那么您几乎有两个选择:继续手动进行所有操作(并尝试更定期地跟上它,而不是像捉迷藏一样- (在发布时更新),或修正您的提交消息样式。一种选择是,如果主题不会为您做这件事,那就是在提交消息的正文中放置诸如“ change:add feature foobar”之类的行,以便以后您可以做一些事情,例如git log --pretty=%B | grep ^change:仅抓住那些超级消息的重要位。

我不完全确定git还可以真正帮助您创建变更日志。也许我误解了“管理”的意思?


2
那绝对是个不错的开始,我也没想过要给身体添加修饰剂,以便以后再使用它。那可能就是我最后要做的。感谢您的反馈!如果在第二天左右没有更多答案,我将标记您的答案:-)
Topher Fangio 2010年

60

免责声明:我是gitchangelog的作者,我将在下面进行介绍。

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

如果要从git历史记录生成变更日志,则可能必须考虑:

  • 输出格式。(纯自定义ASCII,Debian changelog类型,Markdow,ReST ...)
  • 一些提交过滤(您可能不希望将所有错字或外观更改都包含在变更日志中)
  • 一些提交文本在包含在变更日志中之前一直处于争执状态。(确保将消息标准化为具有首字母大写或最后一个点,但也可以删除摘要中的一些特殊标记)
  • 您的git历史记录兼容吗?大多数工具并不总是那么容易地支持合并,标记。这取决于您如何管理历史记录。

可选地,您可能需要一些分类(新事物,更改,错误修正)...

考虑到所有这些,我创建并使用了gitchangelog。这意味着利用git commit消息约定来实现所有先前的目标。

必须使用提交消息约定来创建一个不错的变更日志(无论是否使用gitchangelog)。

提交消息约定

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

您可能希望将提交大致分为以下几部分:

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

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

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

尝试通过尽可能地定位用户(功能)来编写提交消息。

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

* 5a39f73 fix: encoding issues with non-ascii chars.
* 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...),并且可以合理地配置为自己的提交约定。由于使用temp Mustache,它支持任何类型的输出Mako templating,并且具有以原始python编写的默认旧式引擎;当前所有3个引擎都有如何使用它们的示例,并且可以输出changelog的内容作为gitchangelog的PyPI页面上显示的内容。

我敢肯定,你知道,有很多其他的git logchangelog工具,在那里也。


1
这太棒了,正是我想要的。我会尝试的,非常感谢!
杰夫·基萨(Jia Kiiza)


23

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包含记录在其中的最新提交的SHA1标识符,ChangeLog并存储在Git存储库中。 ChangeLog也记录在存储库中,以便可以在不更改提交消息的情况下对其进行编辑(例如,纠正输入错误)。



这应该是一个成功的项目!为什么不在github上安装它?
Omer Dagan

20

由于按版本创建标记是最佳做法,因此您可能需要按版本对变更日志进行分区。在这种情况下,此命令可以帮助您:

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

15

对于GitHub项目,它可能会有用:github-changelog-generator

它从标签已关闭的问题以及合并的拉取请求中生成变更日志。

这个CHANGELOG.md由此脚本生成。

例:

变更日志

1.2.5(2015-01-15)

完整的变更日志

实施的增强功能:

  • 使用里程碑指定修复了哪个版本的错误#22

修正错误:

  • 尝试为没有标签的回购生成日志时出错 #32的

合并拉取请求:


这样的项目是最好的:)您这样做的动机是什么?同样由于您的灵感,我制作了一个类似的工具,该工具无需标签,可以拆分为“添加/更改/固定/删除”,并且使用PHP(我的“母语”语言):github.com/Symplify/ChangelogLinker 您是否撰写有关Changlogs的帖子?我想读他们
托马什Votruba

1
@TomášVotruba感谢您的热情话。这只是我的爱好。我没有发布太多。但是我认为这是值得的。最好的祝愿!
skywinder

10

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

我还做了:

有关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}}
"

或在詹金斯:

在此处输入图片说明


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

是我喜欢用的。它获取自上一个标记以来的所有提交。cut摆脱提交哈希。如果您在提交消息的开头使用票证编号,则会将它们与分组sort。如果在某些提交之前加上,等等fix,排序也很有用typo


3

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

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

2

对于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
}

有了这个:

  • 在对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 commit数据是没有用的。

如果要进行变更日志,请对其进行很好的总结,可能是在http://keepachangelog.com/上指定的。


2

基于bithavoc,它列出了last tag直到HEAD。但我希望在2个标签之间列出日志。

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

列出2个标签之间的日志。

// 2 or 3 dots between 2 tags
git log FROM_TAG...TO_TAG

例如,它将列出从v1.0.0到的日志v1.0.1

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.