Git默认合并提交信息不包括冲突信息。

14

在将origin/base分支合并到我的feature分支后,我需要解决Parameter.java文件上的一个冲突。 我启动了我的Git合并工具,并进行了解决。一旦解决完成,我执行了git commit,这打开了带有默认合并提交消息的Vim编辑器。

问题是,这个默认提交消息包含以#开始的冲突列表,因此它们将被忽略在提交消息中。

Merge remote-tracking branch 'origin/base' into feature

# Conflicts:
#       Parameter.java
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
#       .git/MERGE_HEAD
# and try again.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch feature
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
#       modified:   Parameters.java
#       modified:   SpecialParameters.java
#       modified:   Traveller.java

是否有一些配置可以添加到提交消息中,以便将这些冲突行自动放入其中?因此,在 Conflicts 部分删除冲突文件上的

Is there some config to add to put these conflicts lines automatically in the commit message? Therefore removing the # on the conflicting files in the Conflicts part?
4个回答

10

我找到了一种方法,可以不用任何钩子或脚本来完成这个操作:使用 ---cleanup scissors

% git commit --cleanup scissors

这将导致默认提交信息为:

Merge branch 'branch'

# Conflicts:
#       baz.txt
#       foo.txt
# ------------------------ >8 ------------------------
# Do not modify or remove the line above.
# Everything below it will be ignored.
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
#       .git/MERGE_HEAD
# and try again.


# Please enter the commit message for your changes. Lines starting
# with '#' will be kept; you may remove them yourself if you want to.
# An empty message aborts the commit.
#
# On branch master
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
#       modified:   bar.txt
#       modified:   baz.txt
#       modified:   foo.txt
#

如果您接受这个更改,将会得到以下提交信息:

% git log -1
commit 64425eab687f9d4fc531da69495dcb401372104b (HEAD -> master)
Merge: efd152d 474a8f4
Author: Dave Dribin <dave@example.com>
Date:   Fri Oct 19 23:47:19 2018 -0500

    Merge branch 'branch'

    # Conflicts:
    #       baz.txt
    #       foo.txt

这不会删除#前缀,但它包括了冲突文件的清单。为什么这样做?这将截取特殊的“剪刀”行之后的所有内容,而不是注释字符串前缀。以下是--cleanup scissors的文档,来自于git-commit(1)man页面

       --cleanup=<mode>
       This option determines how the supplied commit message should be
       cleaned up before committing. The <mode> can be strip, whitespace,
       verbatim, scissors or default.

       strip
           Strip leading and trailing empty lines, trailing whitespace,
           commentary and collapse consecutive empty lines.

       whitespace
           Same as strip except #commentary is not removed.

       verbatim
           Do not change the message at all.

       scissors
           Same as whitespace except that everything from (and including)
           the line found below is truncated, if the message is to be
           edited. "#" can be customized with core.commentChar.

               # ------------------------ >8 ------------------------

       default
           Same as strip if the message is to be edited. Otherwise
           whitespace.

       The default can be changed by the commit.cleanup configuration
       variable (see git-config(1)).

2
很遗憾,这个行为在Git 2.22.0中被更改了(Git 2.22.0发布说明)。 - aaron
@aaron:那很不幸。我还没有尝试过Git 2.22.0,但希望只是将剪刀线下移的问题吗? - Dave Dribin
删除下面两行代码(这三行代码被移到了“冲突”之前),所以有点不方便,但大部分还是可以正常工作的。 - aaron

9
您可以使用prepare-commit-msg钩子来实现此操作。
.git/hooks/prepare-commit-msg.sample复制到.git/hooks/prepare-commit-msg
其中的示例实际上在冲突部分添加了#:
case "$2,$3" in
  merge,)
    /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;

这个钩子非常有意义,因为之前的版本默认会这样做(例如像在Linux git 1.7.10.4版本中)。现在你想要做的正好相反:删除冲突部分的#。事实上,git version 2.6.2.windows.1默认将冲突部分注释掉,所以你只需更新prepare-commit-msg命令,如下所示:
/usr/bin/perl -i.bak -ne 's/^#// if /^# Conflicts/ .. /^#\R/; print' "$1" ;;

这个钩子包含三个例子。第一个注释掉了合并提交的“冲突:”部分。它写在文件开头,所以实际上是相反的。无论如何,我尝试按照您的建议将其重命名,我重新启动了Git bash,但它仍然不起作用,冲突部分仍然被注释掉了。

- jeerbl
2
对于Perl,请使用以下命令替换:sed -i.bak '/^# Conflicts:/,/^#$/ s/..//' "$1" - jthill

2

我使用这个命令,它利用了 sed模式范围(基于jthill的回答)。

人话翻译:在介于 # Conflicts:# 或空行之间的那些行中,移除前缀 #(space) 或单独的 ## \?)。

sed -i '/start/,/stop/ s/# \?//'

prepare-commit-msg钩子:

# prepare-commit-msg
case "$2,$3" in
  merge,)
    # Uncomment Conflicts section in merge commit body
    sed -i '/^# Conflicts:/,/^#\?$/ s/# \?//' "$1"
    ;;
  *) ;;
esac

这会导致
Conflicts:
    GIT-VERSION-GEN
    RelNotes

-1

您不需要自己将其添加到提交消息中。一旦您进行了合并提交,如果存在冲突,git 将告诉您它们的位置。只需在包含冲突的合并提交上运行 git show --name-only [commit sha],您就会在消息中看到它。


你能展示一个例子吗?我已经测试过了,但好像不起作用。据我所知,一旦提交完成,Git 就不会存储任何关于冲突的信息。 - Igal S.
你可以在这里看到一个例子:https://help.github.com/articles/resolving-a-merge-conflict-from-the-command-line/ - mohammedkhan
有趣。也许是git版本的问题。我在尝试时没有看到它。 - Igal S.
1
git show 命令在合并提交上的结果是否包含足够的信息以查看原始冲突,取决于如何解决冲突。如果合并提交在一个小区域内与两个父提交存在差异,则可以在 git show 中看到它。但是,例如,如果通过从一个父提交中获取所有内容来解决提交,则不会在 git show 中显示。 - Dave

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接