如何自定义git的合并提交消息?


73

每次执行合并时,都需要生成合并提交,我希望它不仅具有所有提交的摘要。

我的问题是如何格式化git-fmt-merge-msg或确定该自动消息的方式(我可以在提交后通过修改并使用git-log --pretty = format:'...'手动完成此操作)

例如,我想这样格式化:

 Merge branch 'test'  
    * test:  
      [BZ: #123] fifth commit subject  
      [BZ: #123] fourth commit subject  
      [BZ: #123] third commit subject  
      [BZ: #123] second commit subject  
      [BZ: #123] first commit subject  

 __________________________________________
 Merge details:  
     [BZ: #123] fifth commit subject  
               at 2010-06-30 11:29:00 +0100  
       - fifth commit body  

     [BZ: #123] fourth commit subject  
               at 2010-06-30 11:22:17 +0100  
       - fourth commit body  

     [BZ: #123] third commit subject  
               at 2010-06-30 11:21:43 +0100  
       - third commit body  

     [BZ: #123] second commit subject  
               at 2010-06-30 11:21:30 +0100  
       - second commit body  

     [BZ: #123] first commit subject  
               at 2010-06-30 11:29:57 +0100  
       - first commit body

Answers:


13

我想做这样的事情。我没有找到任何合理的git fmt-merge-msg上班方式。我认为这不符合我的期望(传递用于消息的完全自定义文本)。因此,我想出了另一种使用-no-commitandcommit -F命令的方法。输出当然是可定制的,但几乎可以完全反映您说的想要输出的内容。

样本提交消息输出:

Merge branch fix4 into master

::SUMMARY::
Branch fix4 commits:
Add fix4b-4
Add fix4b-3
Add fix4b-2
Add fix4b-1

Branch master commits:
fix4b-5 on master

* * * * * * * * * * * * * * * * * * * * * * * * *
::DETAILS::
commit < 98ffa579e14610b3566e1a3f86556a04dc95a82b
Author: -----
Date:   Fri Aug 17 17:23:26 2018 -0400

    fix4b-5 on master

commit > 7e386dddee16a7c2588954d25dd6793cdaa1b562
Author: -----
Date:   Fri Aug 17 15:18:17 2018 -0400

    Add fix4b-4

    use log output as commit message

    commit 2e630b1998312ec1093d73f9fe77b942407f45e8
    Author: -----
    Date:   Fri Aug 17 15:15:28 2018 -0400

        Add fix4b-3

commit > 2e630b1998312ec1093d73f9fe77b942407f45e8
Author: -----
Date:   Fri Aug 17 15:15:28 2018 -0400

    Add fix4b-3

commit > c9bb199be49c17ca739d019d749263314f05fc46
Author: -----
Date:   Fri Aug 17 15:15:27 2018 -0400

    Add fix4b-2

commit > 5b622a935c9d078c7d0ef9e195bccf1f98cce5e4
Author: -----
Date:   Fri Aug 17 15:15:27 2018 -0400

    Add fix4b-1

用法是:

$ git mergelogmsg branch-name

我将在此处复制别名:

[alias]
    mergelogmsg = "!f() { var=$(git symbolic-ref --short HEAD) && printf 'Merge branch %s into %s\n\n::SUMMARY::\nBranch %s commits:\n' $1 $var $1 > temp_merge_msg && git log --format=format:'%s' $var..$1 >> temp_merge_msg && printf '\n\nBranch %s commits:\n' $var >> temp_merge_msg && git log --format=format:'%s' $1..$var >> temp_merge_msg && printf '\n\n* * * * * * * * * * * * * * * * * * * * * * * * *\n::DETAILS::\n' >> temp_merge_msg && git log --left-right $var...$1 >> temp_merge_msg && git merge --no-ff --no-commit $1 && git commit -eF temp_merge_msg; rm -f temp_merge_msg;}; f" 

如果要复制并粘贴以自定义它,请使用上面的方法。以下版本有您不希望使用的换行符,但我将用它来解释我在做什么:

[alias]
1   mergelogmsg = "!f() { var=$(git symbolic-ref --short HEAD) && 
2        printf 'Merge branch %s into %s\n\n::SUMMARY::\nBranch %s commits:\n' $1 $var $1 > temp_merge_msg && 
3        git log --format=format:'%s' $var..$1 >> temp_merge_msg && 
4        printf '\n\nBranch %s commits:\n' $var >> temp_merge_msg && 
5        git log --format=format:'%s' $1..$var >> temp_merge_msg && 
6        printf '\n\n* * * * * * * * * * * * * * * * * * * * * * * * *\n::DETAILS::\n' >> temp_merge_msg && 
7        git log --left-right $var...$1 >> temp_merge_msg && 
8        git merge --no-ff --no-commit $1 && 
9        git commit -eF temp_merge_msg; rm -f temp_merge_msg;}; f"

好的...

第1行将自定义函数作为bash shell脚本启动,因此git知道它不是git命令。它将当前分支(如果将另一个分支合并到master中,则为master)设置为变量,以便我们稍后使用。
第2行使用当前分支和您赋予原始命令的分支名称(与在普通merge命令中一样)打印第一行。它将其写入临时文件。
第3行获取传入分支中不在当前分支中的提交的日志,并且仅将这些提交的主题写到temp文件中。
第4行将下一行打印到temp。
5号线获取当前分支中不在传入分支中的提交的日志,并且仅将这些提交的主题写到temp文件中。
第6行在摘要和详细信息部分之间打印了一个小的水平分隔符。
第7行将当前分支和传入分支中所有提交的日志返回到它们彼此分支或最后共享祖先之后的时间。左右方向给出一个箭头,显示提交来自哪个分支。<表示当前分支,而>表示传入分支。
第8行使用传入分支执行合并命令,该分支没有快进(因此您可以提交),也没有提交(因此您必须自己编写一个……嗯,但是您不可以!)使用
9号线使用-e-F参数执行commit命令,以进行编辑并告诉提交使用指定文件中的文本填充消息。根据需要完成提交消息后,它将提交合并并删除临时文件。

多田 该;长命令末尾的两个使它生效,因此printf函数不会写出到控制台,而只写到文件。


1
这太棒了!!它非常适合该问题,并且可以轻松自定义。谢谢!
shil88

确实,我已经对其进行了更多自定义。我只是为特定项目制作的,但我可能会将其用于所有合并。
GaetaWoo

52

我知道这并不能回答最初的问题,但是为了像我这样的git noob的利益,他们到达了此页面,因为这是Google的第一个“ git change merge commit message”结果,我会提到这是可能的至:

git commit --amend -m"New commit message"

更改合并提交的提交消息,而不会丢失到任何合并提交的父级的链接。


1
这让git log --graph停止绘制分支图。
ciastek 2012年

4
如果您只是想将默认的合并提交从“合并的分支...更改为master”,请尝试使用git merge --no-edit -m "your-custom-commit-message"
Elad

4
-1:这不能回答问题。不论google对这里进行什么查询,这都不是最好的答案。甚至根本不应该是这个问题的答案。
贾斯珀(Jasper)

1
@Jasper从技术上讲是正确的,但是作为回答者,标题没有准确地捕获正文中的问题并不是我的错。显然,人们发现此功能足以使其升至最高点也不是我的错。现在已经使用SO了一段时间(并且由于这个特定的答案而在一定程度上享有足够的声誉),如今,我可能会编辑问题,以澄清标题并添加指向相关问答的链接。
laszlok

我认为,答案者的错误是没有尝试回答问题,而是回答了从未问过的问题。(如果这个问题没有得到自我回答,那还不错,但这不会改变任何东西。)也许带有相似但不同的问题链接的注释是一个更好的主意。
贾斯珀(Jasper)

22

Git 1.7.8版本开始,您可以git merge --edit ... 指定提交消息。

1.7.10开始,进入编辑模式将是默认行为。

从此版本开始,交互式会话中的“ git merge”命令将在自动解决合并以供用户解释生成的提交时启动编辑器,就像“ git commit”命令在未给予提示时一样。提交消息。

(尽管我没有在Windows的msysgit中看到它)


16

我发现有两种方法可以解决此问题

注意:请勿同时使用两者,因为如果提交合并失败,它将再次将日志添加到底部。

个人说明:我正在使用第一个解决方案,因为它完全依赖git的hooks和config属性,而不是外部脚本。
对于真正的解决方案,必须扩展一个名为'fmt-merge-msg'的git命令,该命令在传递--log选项时生成单行描述(如果您确实需要此解决方案,则必须创建自己的补丁程序(对于git)并从源代码进行编译)。

1.使用prepare-commit-message作为VonC建议
此解决方案存在以下问题,您需要中断提交然后手动提交

设置别名以构建所需的提交消息:

[alias]  
lm = log --pretty=format:'%s%n   by %C(yellow)%an%Creset (%ad)%n %n%b' --date=local

通过在$ GIT_DIR / hooks /中创建可执行的prepare-commit-msg来创建prepare-commit-msg挂钩(下面的示例脚本)

#!/bin/sh
#...

case "$2,$3" in  
  merge,)  
  echo "Merge details:" >> $1  
  echo "" >> $1  
  git lm ORIG_HEAD..MERGE_HEAD >> "$1" ;;  
*) ;;  
esac  

应该定义一个别名提交信息,例如

[alias]  
m = merge --no-ff --no-commit

2.使用将自动生成合并的自定义命令
(使用在1中创建的lm别名)。

#!/bin/sh

echo ""
echo "merge with commit details -- HEAD..$1"
git merge --no-ff --no-log -m "`git lm HEAD..$1`" --no-commit $1

然后执行一个相当严格的命令:

./cmd-name <branch to merge>

如果您仍然希望对提交有一个描述,则需要在-m参数中添加新命令或其他内容(如果使用--log,则它将在底部生成)


好,很好。但坦率地说-这比应做的要困难得多。
Ed Randall

一个更好的答案被发布了!签出接受的一个
shil88 '18

11

合并<branch A>到后<branch B>,git会自动提交一条消息,说“将分支合并<branch A><branch B>

如果要自定义git的合并提交消息,可以尝试:

$ git commit --amend -m "Your merge message"

该命令会将您的git的合并提交消息更新为您的提交消息。

您也可以尝试:

$ git merge <branch A> --no-commit

它会合并您<branch B><branch A>,用的名单 <Branch B>'s提交和邮件提交

如果它无法快速前进,那么您将获得以下内容:

Automatic merge went well; stopped before committing as requested

# check this with git status 
$ git status

它将向您显示,您的提交已经添加到舞台上但尚未提交,因此,您可以在不运行它们的情况下提交它们git add

$ git commit -m "your merge commit message"

如果您想更改<branch B>的最后提交消息,则可以再次尝试:

$ git commit --amend -m "your new commit message"

但是,通常,我们不会更新其他提交消息,除非它们不正确。

假设您在git合并后遇到冲突,然后只需解决冲突并执行以下操作:

$ git add .
$ git commit -m "your commit message"

1
--amend在答案的最后一行中,为什么要对尚未发生的提交执行操作?难道不是git commit -m "your commit message"吗?
darthbith 2014年

1
我不好,谢谢指出。它应该是git commit -m“您的提交消息”,因为没有完成合并的提交。
przbadu 2014年

当您指定--no-commit标志时,“因为没有完成合并提交” :-)
darthbith 2014年

在这里,git merge b --no-commit会将分支b合并到分支a,同时包含所有分支b的提交(很明显)以及分支b的提交消息。它不会添加额外的提交消息,例如:“将分支b与分支a合并”
przbadu 2014年

如果合并不是快进的,您将收到类似“自动合并进展顺利;在按要求提交之前停止”的消息。现在,您无需运行git add .,但是,您可以直接使用git commit -m "your commit message"
przbadu

6

现在还有一个--log选项git-merge,它可以完成您所需的一半-将shortlog(提交摘要)放入合并消息中。但是,完整的解决方案将不得不使用VonC答案中的钩子。


好吧,我已经在全局设置了该选项,因为钩子不会在合并过程中激活(除非您使用--no-commit停止它),所以钩子将
无法解决问题

1
“钩子不会成功,因为它们不会在合并过程中激活(除非您使用--no-commit停止它)”;这本身就是一个好问题:为什么在合并的提交部分没有钩子被激活?
VonC'7

@VonC:实际上,我认为这是故意的-从源代码中快速浏览一下,commit_tree直接合并调用。
卡斯卡贝尔

-m选项与--log一起使用。另外,对于像我这样的菜鸟,在检查合并到的分支的结果日志(使用--log)时,请不要使用--oneline选项,否则,您只会看到合并提交消息,而不是单个提交消息合并分支的名称。
乔恩(Jon)

4

您可以尝试定义一个prepare-commit-msg挂钩示例确实会生成一些自定义的“默认提交消息”)


1
在某种程度上可以正常工作,我必须与--no-commit合并,然后才提交,否则prepare-commit-msg钩子似乎无法运行(merge_msg是标准的)。详细信息将自动添加,因为这些是我提交给CVS的提交
shil88

@ shil88:您是否尝试过查看commit-msg钩子是否在激活期间被激活git merge
VonC

@ shil88:刚刚意识到我已经回答了您的第一个问题(stackoverflow.com/questions/2817897/…):您最终设法实现了一个挂钩,以保持git和cvs repo同步吗?
VonC

1
@VonC对不起,我没有足够的声誉来对答案发表评论,但是我实现了一个CVSNT后命令钩子,该钩子在稍有延迟之后迫使'main'Git存储库执行cvsimport ...尽管仍在进行调整,但是当我将其发布时,我会发布解决方案它完全可用(自动提交是一个非常糟糕的主意,现在我更喜欢从本地存储库提交)
shil88

1
@VonC commit-msg挂钩未激活
shil88

1

一个非常简单的bash函数,它设置默认消息并添加您的参数。--edit如果要进行更改,它将使用开关打开编辑器。

编辑〜/ .bashrc或bash_aliases。(不要忘记source ~/.bashrc)在您的bashrc中应用更改

function mergedevelop()
{
    git merge --no-ff --edit -m "master <-- develop: $1" develop;
}

采用:

mergedevelop "PR #143..." 有消息:

大师<-开发:PR#143 ...


1

聚会晚了,但是如今,我们可以使用
git merge --squash <branch>
将另一个分支合并到我当前分支上的单个提交中,使用所有合并的提交消息以及详细消息(不仅是单行代码)预填充我们的提交消息
我为此命令寻找了很长时间。


0

除了git merge --squash提到Christian Severin回答的内容外,您现在还拥有配置merge.suppressDest作为自定义提交消息(一小部分)的新方法。

使用Git 2.29(Q4 2020年) “ git merge男人学会了选择性省略“into <branch>在默认合并消息的标题的末尾”merge.suppressDest配置。

参见commit 6e6029a(2020年7月29日)和Junio C Hamano()的commit 2153192(2020年7月30日(通过合并JUNIOÇ滨野- -提交341a196gitster
gitster,2020年8月1日)

fmt-merge-msg:允许再次忽略合并目标

帮助:莱纳斯·托瓦尔兹
帮助:杰夫·金

在Git 2.28中,我们停止了特殊大小写'master在生成默认合并消息时 ',只需删除into 'master'消息末尾的静噪代码“ ”。

引入多值merge.suppressDest配置变量,该变量给出一组与要合并到的分支的名称相匹配的glob,以便用户指定应缩短fmt-merge-msg的输出。
如果未设置,“master默认情况下 '用作变量的唯一值。

上面的举动主要是还原没有相关配置的存储库中的2.28之前的默认设置。

git config现在在其手册页中包括:

merge.suppressDest

通过向该多值配置变量添加与集成分支的名称匹配的glob,为合并到这些集成分支而计算的默认合并消息将省略“ into <branch name>在其标题中 ”。

具有空值的元素可用于清除从先前配置条目累积的全局列表。如果merge.suppressDest未定义任何变量,master则使用默认值来实现向后兼容。

和:

Revert "fmt-merge-msg:停止master特殊对待”

这将还原提交489947cee5095b168cbac111ff7bd1eadbbd90ddmaster在准备默认的合并消息时,该合并停止将合并到特殊分支'中。
由于目标是不将任何分支指定为特殊分支,因此通过into <branchname>在所有分支的默认合并消息标题的末尾保留“ ”来解决该问题。
一个对所有人都一视同仁的简单明了的替代方法可能是将其每个分支都删除,但这会导致信息丢失。

我们将引入一种新的机制,让最终用户指定合并,分支将忽略into <branchname>默认合并消息标题中的“ ”,并使该机制在未配置时master再次对待传统的' ',因此所有我们无需更改先前的测试,因为无需配置所述新机制即可运行这些测试。

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.