ChatGPT解决这个技术问题 Extra ChatGPT

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

每次我进行合并时,我都需要生成一个合并提交,并且我希望它不仅仅是所有提交的摘要。

我的问题是如何格式化 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

l
laszlok

我知道这不是在回答最初的问题,但是为了像我这样的 git noobs 到达这个页面,因为它目前是“git change merge commit message”的第一个谷歌结果,我会提到它是可能的至:

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

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


它使 git log --graph 停止绘制分支图。
如果您只想将默认合并提交从“合并分支 ... 更改为主”,请尝试使用 git merge --no-edit -m "your-custom-commit-message"
-1:这不能回答问题。无论谷歌在这里提出什么查询,这都不应该是最佳答案。它甚至可能根本不应该是这个问题的答案。
@Jasper 在技术上是正确的,但作为回答者,标题没有准确地捕捉正文中的问题几乎不是我的错。这也不是我的错,显然人们发现这对它有足够的帮助使其上升到顶峰。现在已经使用了一段时间了(并且有足够的声誉这样做,这在很大程度上是由于这个特定的答案),现在我可能会改为编辑问题,以澄清标题并添加指向相关问答的链接.
在我看来,回答者的错是没有尝试回答问题,而是回答了一个从未被问过的问题。 (如果这个问题没有得到自我回答,那就不会那么糟糕了,但这不会改变任何事情。)也许一个带有相似但不同问题的链接的评论会是一个更好的主意。
R
Roman

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

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

从这个版本开始,交互式会话中的“git merge”命令将在它自动解析合并时启动一个编辑器,以便用户解释生成的提交,就像“git commit”命令在没有给出时所做的那样提交消息。

(虽然我没有在 Windows 上的 msysgit 中看到它)。


C
Community

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

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

个人注意:我使用的是第一个解决方案,因为它完全依赖于 git 的钩子和配置属性,而不是外部脚本。对于真正的解决方案,必须扩展一个名为“fmt-merge-msg”的 git 命令,该命令在传递 --log 选项时生成单行描述(如果你真的需要这个解决方案,你必须创建自己的补丁(对于git)并从源代码编译)。

<强> 1。使用 prepare-commit-message 作为 VonC suggested
此解决方案存在您需要中断提交然后手动提交的问题

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

[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 那么它将在底部生成)


好,很好。但坦率地说——这比它应该做的要困难得多。
发布了一个更好的答案!查看已接受的
G
GaetaWoo

我想做这样的事情。我没有找到任何合理的方法让 git fmt-merge-msg 工作。我认为它不像我希望的那样工作(传递一个完全自定义的文本以用于消息)。因此,我想出了另一种使用 -no-commitcommit -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 命令。它将当前分支(如果您将不同的分支合并到主分支,则为主分支)设置为一个变量,以便我们稍后使用它。
第 2 行 使用当前分支和分支打印第一行您给原始命令的名称(就像在普通的合并命令中一样)。它将其写入临时文件。
第 3 行 获取传入分支中不在当前分支中的提交的日志,并仅将这些提交的主题写入临时文件
Line 4 将下一行打印到 temp。
Line 5 获取当前分支中不在传入分支中的提交日志, 并仅将这些提交的主题写入临时文件。
第 6 行 在摘要和详细信息部分之间打印一个小的水平分隔符。
第 7 行 将当前分支和传入分支中所有提交的日志返回到它们刚从彼此分支或最后共享祖先之后的时间。左右给出一个箭头,显示提交来自哪个分支。 <表示当前分支和>表示传入分支。
第 8 行 执行与传入分支的合并命令,没有快进(所以你得到一个提交)和没有提交(所以你必须自己写一个.. . 啊,但你没有!)
第 9 行 使用 -e-F 参数执行提交命令,以允许编辑并告诉提交使用指定文件中的文本。根据需要完成提交消息后,它会提交合并并删除临时文件。

多田!该长命令末尾的两个 ; 使 printf 函数不会写入控制台,而只会写入文件。


这太棒了!!它与问题完美契合,并且可以轻松定制。谢谢!
事实上,我已经对它进行了更多的定制。我只是为一个特定的项目制作的,但我可能会将它用于所有合并。
p
przbadu

<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 merge 后发生冲突,然后简单地解决你的冲突并执行以下操作:

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

为什么要在答案的最后一行对尚未发生的提交执行 --amend ?不应该只是git commit -m "your commit message"吗?
我的不好,谢谢指出。它应该是 git commit -m "your commit message" 因为没有为合并完成任何提交。
当您指定 --no-commit 标志时,“因为没有为合并完成任何提交”,就像您所做的那样:-)
在这里, git merge b --no-commit 将分支 b 合并到分支 a,所有分支 b 提交(这是显而易见的)和分支 b 的提交消息。它不会添加额外的提交消息,例如:“合并分支 b 与分支 a”
如果您的合并不是快进的,您将收到类似“自动合并顺利;在按要求提交之前停止”之类的消息。现在,您不需要运行 git add .,但是,您可以直接使用 git commit -m "your commit message" 提交合并
C
Cascabel

现在还有一个用于 git-merge--log 选项,它可以完成您想要的一半 - 它将短日志(提交摘要)放在合并消息中。不过,完整的解决方案必须使用 VonC 的答案中的钩子。


好吧,我已经在全局范围内设置了该选项,挂钩不会起作用,因为它们在合并期间不会激活(除非您使用 --no-commit 停止它)
“钩子不会起作用,因为它们在合并期间不会激活(除非你用 --no-commit 停止它)”;这本身就是一个好问题:为什么在合并的提交部分没有激活任何钩子?
@VonC:实际上,我认为这是故意的-从源代码的快速浏览中,直接合并调用 commit_tree
-m 选项对 --log 很有用。此外,对于像我这样的菜鸟,在检查合并到的分支的结果日志时不要使用 --oneline 选项(使用 --log),否则您只会看到合并提交消息而不是单个提交消息合并后的分支。
V
VonC

您可以尝试定义 prepare-commit-msg hooksample one 确实会生成一些自定义“默认提交消息”)


在某种程度上工作得很好,我必须与 --no-commit 合并,然后才提交,否则 prepare-commit-msg 钩子似乎没有运行(merge_msg 是标准的).. 我想要完整的合并要自动添加的详细信息,因为这些是我提交给 CVS 的提交
@shil88:您是否尝试查看在 git merge 期间是否激活了 commit-msg 钩子?
@shil88:刚刚意识到我已经回答了你的第一个问题(stackoverflow.com/questions/2817897/…):你终于设法实现了一个钩子来保持 git 和 cvs repo 同步吗?
@VonC 对不起,没有足够的声誉来评论答案,但我实现了一个 CVSNT 后命令挂钩,在一小段延迟后强制“主要”Git 存储库执行 cvsimport ......虽然仍在调整它,我会发布我的解决方案它完全可用(自动提交是一个非常糟糕的主意,现在我更喜欢从我的本地仓库提交)
@VonC commit-msg 挂钩未激活
C
Christian Severin

迟到了,但现在我们可以使用
git merge --squash <branch>
将另一个分支合并到我当前分支上的单个提交中并使用所有合并的提交预填充我们的提交消息消息——以及详细的消息,不仅仅是单行。
我为这个命令寻找了很多年。


我是不是弄错了,或者这就像你失去分支上下文的快进一样?我刚试过,也许我用错了。你给自己的命令似乎并没有提交合并,但后来我跑了 git merge ,它只是快进了。我很好奇这里发生了什么,或者你描述的如何使用它。
V
VonC

除了 Christian Severinanswer 中提到的 git merge --squash 之外,您现在还可以使用配置 merge.suppressDest 作为自定义(一小部分)提交消息的新方法。

在 Git 2.29(2020 年第四季度)中,“git merge(man) 学会了在具有 merge.suppressDest 配置的默认合并消息的标题末尾选择性地省略“into <branch>”。

请参阅 Junio C Hamano (gitster)commit 6e6029a(2020 年 7 月 29 日)和 commit 2153192(2020 年 7 月 30 日)。
(由 Junio C Hamano -- gitster --commit 341a196 中合并,2020 年 8 月 1 日)

fmt-merge-msg:允许再次省略合并目标帮助者:Linus Torvalds 帮助者:Jeff King

在 Git 2.28 中,我们在生成默认合并消息时停止了特殊的大小写“master”,只需删除在消息末尾压制“进入 'master'”的代码。引入多值 merge.suppressDest 配置变量,该变量提供一组 glob 以匹配进行合并的分支的名称,让用户指定应该缩短哪个分支 fmt-merge-msg 的输出。未设置时,默认情况下将“master”用作变量的唯一值。上述举措主要是在没有相关配置的存储库中恢复 2.28 之前的默认设置。

git config 现在在其 man page 中包含:

merge.suppressDest 通过向这个多值配置变量添加一个与集成分支名称匹配的 glob,为合并到这些集成分支中计算的默认合并消息将在其标题中省略“into ”。具有空值的元素可用于清除从先前配置条目累积的 glob 列表。当没有定义 merge.suppressDest 变量时,master 的默认值用于向后兼容。

和:

还原“fmt-merge-msg:停止特别对待主人”

这将恢复提交 489947cee5095b168cbac111ff7bd1eadbbd90dd,它在准备默认合并消息时停止将合并到“主”分支中视为特殊。由于目标不是将任何单个分支指定为特殊分支,因此它通过在任何和所有分支的默认合并消息标题的末尾保留“into ”来解决这个问题。一个明显而简单的平等对待每个人的替代方法可能是为每个分支删除它,但这会导致信息丢失。我们将引入一种新机制,让最终用户指定合并到哪些分支将省略默认合并消息标题中的“into ”,并使该机制在未配置时将传统的“主”视为特殊同样,因此我们之前对测试所做的所有更改都将变得不必要,因为这些测试将在不配置所述新机制的情况下运行。


n
nilsM

一个非常简单的 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 ...