如果存在合并冲突,如何让 git 自动打开合并工具?

Posted

技术标签:

【中文标题】如果存在合并冲突,如何让 git 自动打开合并工具?【英文标题】:How do I make git automatically open the mergetool if there is a merge conflict? 【发布时间】:2012-04-19 09:49:19 【问题描述】:

如何让 git 针对任何合并冲突自动运行 git mergetool?这应该适用于所有合并,使用 mergerebasepull 等。

【问题讨论】:

也许你可以使用githook,例如post-checkout(不知道是不是真的在合并的时候调用了。post-merge需要合并成功) @TobiasKienzler 您可能正在做某事。如果你能找到一个可行的解决方案,我会给你这个问题的赏金。 @QuinnStrahl 我认为目前不存在一个在导致合并的各种命令之前执行的钩子,因此rospov's wrapper 可能是最简单的解决方案。或者修改 git 源以实现 pre-merge 钩子功能,在这种情况下,您当然可以简单地让 git run mergetool 发生冲突,这取决于配置设置...... 嗯,好的。谢谢您的帮助。我想我会提交一个补丁。 @QuinnStrahl 如果你现在已经提交了补丁,我会很感激这里的链接:) 【参考方案1】:

你不能(还)让 git 这样做。


这可能是也可能不是可接受的解决方法。

在您的~/.bashrc 中创建一个函数:

git() 
 
  if [[ $1 == "merge" ]] || [[ $1 == "rebase" ]] || [[ $1 == "pull" ]]; then 
    command git "$@" 
    rc=$?
    if [[ $rc == 1 ]]; then
      echo "There are conflicts, better run git-mergetool!!!"
      # There might be some other condition that returns a '1',
      # if so you can add another check like this:
      # if grep Conflicts $(git --git-dir)/MERGE_MSG;
      command git mergetool
    fi
  else 
    command git "$@"
  fi

合并时不调用 Mergetool:

$ git merge non_conflicting_branch
Merge made by the 'recursive' strategy.
 bar | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 bar

发生冲突时调用Mergetool:

$ git merge conflicting_branch
Auto-merging foo
CONFLICT (content): Merge conflict in foo
Automatic merge failed; fix conflicts and then commit the result.
There are Conflicts, better run git-mergetool!!!

Mergetool 不会因其他错误而被调用:

$ git merge adasds
fatal: adasds - not something we can merge

【讨论】:

这不是让git自动打开mergetool,而是让shell来做。 为什么投反对票?这本质上是实现 rosipov 答案的一种更简洁的方式。 如何清洁?您缺少某些类型的冲突(例如git stash pop)。因为他不按命令过滤,所以这不是问题。正如您自己注意到的那样,当前代码将在任何状态为 1 的错误上启动 git mergetool 我不能确定是否有任何其他错误,返回值为 1 的命令,因为 git 返回值通常没有记录。不过,我还没有找到一个不是合并冲突的。 @QuinnStrahl git (还)不能做到这一点,那么通过 shell 完成它是一个错误的答案吗?【参考方案2】:

你总是可以使用别名

alias 'git-merge'='git merge && git mergetool'
alias 'git-rebase'='git rebase && git mergetool'
alias 'git-pull'='git pull && git mergetool'

和/或按照这些思路编写一个帮助脚本

#/bin/bash
git $*
[ "$(git ls-files –abbrev –unmerged | wc -l)" -gt 0 ] && git mergetool

然后

alias git='~/.git/git-script'

没有直接调用mergetool的方法,因为它只是几种合并方法中的一种(参见man 1 git-merge中的“HOW TO RESOLVE CONFLICTS”)。

【讨论】:

正如我所提到的,如果有冲突,我只想打电话给mergetool。 “合并的几种方法中只有一种”的论点没有说服力。是的,有多种方式,但选择一种作为默认方式是很合理的。 如果没有冲突,git mergetool 不会做任何事情。【参考方案3】:

据我所知,没有瓷器可以做到这一点。

您可以像这样围绕 git 进行包装(文件 git_mergetool.sh,在您的路径上,+x):

#!/bin/bash

SEARCH="CONFLICT"
OUTPUT=$(git "$@" 2>&1 | tee /dev/tty)
if `echo $OUTPUT | grep -i "$SEARCH" 1>/dev/null 2>&1`
then
  git mergetool
fi

然后添加别名:

echo alias git=\"git_mergetool.sh\" >> ~/.bashrc

每次调用 git 时,包装器都会检查是否弹出“冲突”一词。如果是 - 包装器启动合并工具。

这可以通过向$SEARCH 添加更精确的短语来改进(例如“自动合并失败;修复冲突然后提交结果。”)以及检查第一个参数 ($1) 是否在列表中导致合并冲突的命令(pullmerge 等...)。否则如果 git 命令输出太长,你最终会解析很多不必要的数据。

【讨论】:

是否可以不有效地给 git 起别名? @QuinnStrahl 您可以将脚本命名为 git(不带文件扩展名)并在实际 git 可执行文件之前放入您的路径。但这几乎只是另一种混叠方式。所以不,我不知道没有别名 git 的方法。 应该有点可行,但 CONFLICT 正则表达式需要改进。我认为它目前会在任何地方捡起它,即使在例如差异输出。至少您可以按行位置(例如锚点)进行过滤,并且可以扩展文本。

以上是关于如果存在合并冲突,如何让 git 自动打开合并工具?的主要内容,如果未能解决你的问题,请参考以下文章

idea的git无法使用三路合并

Git:关于合并算法、冲突格式以及与合并工具的相互作用的困惑

如何在Git中手动合并所有文件?

成功自动解决合并冲突后,使用 KDiff 审查合并操作

IntelliJ git 合并工具

用于解决 git 中的合并冲突的控制台 UI 工具......就像 vimdiff 但“更容易”