有没有办法比较两个差异或补丁?

时间:2011-12-20 01:15:38

标签: git version-control

有没有办法测试两个差异或补丁是否相同?

假设您有以下git提交历史记录,其中功能F和G可以完全重新映射到E:

     G
    /
A--B--C--D--E
 \
  F

由于我们当前部署过程中的限制,我们有以下相关图表(它不受版本控制)

              G'
             /
------------E'
             \
              F'

F'和G'最终将被应用于头部E',其中一些将被确定为顺序,因此它最终会像

一样
------------E'--G'--F'

有没有办法测试从E'到G'的差异与B中G的Git提交产生的​​补丁相同?

我完全意识到,在一个理想的世界中,修订控制可以解决这个问题,而且我们已经到了那里,但那不是我们现在所处的位置。

你可以基本上在单独的结账时播放两个补丁并比较输出,但这看起来很笨重。并且比较差异本身,我假设,不会工作,因为行号可能会改变。即使G'和F'被重新定义为E',F'的补丁也将最终应用于G',使得补丁的差异上下文不同。

4 个答案:

答案 0 :(得分:33)

diff <(git show COMMIT1SHA) <(git show COMMIT2SHA)

答案 1 :(得分:7)

从git 2.19开始,有一个额外的工具可用于:git range-diff

所以您可能想要:

git range-diff E..G E..G'

即使在每个范围内有多个补丁,这也应该起作用。

答案 2 :(得分:2)

我会让git尝试看看:

git checkout E -b FG
git cherry-pick F' G'
git checkout E -b GF
git cherry-pick G' F'
git diff FG GF
git branch -D FG GF

答案 3 :(得分:2)

为了读者的利益,这是the answer of @mrbrdo的更新,稍作调整:

  • 添加git sdiff别名以便于访问。 sdiff代表show diff
  • 使用^{}后缀忽略带注释的标记标题。
  • 允许diff使用-u等选项。

在您使用git的每个帐户中运行一次:

git config --global alias.sdiff '!'"bash -c 'O=(); A=(); while x=\"\$1\"; shift; do case \$x in -*) O+=(\"\$x\");; *) A+=(\"\$x^{}\");; esac; done; g(){ git show \"\${A[\$1]}\" && return; echo FAIL \${A[\$1]}; git show \"\${A[\$2]}\"; }; diff \"\${O[@]}\" <(g 0 1) <(g 1 0)' --"

之后你可以使用它:

git sdiff F G

请注意,这需要bash版本3或更高版本。

说明:

  • git config --global alias.sdiff在全局git sdiff中添加了名为~/.gitconfig的别名。

  • !以别名命令

  • 运行别名
  • bash -c我们需要bash(或ksh),因为<(..)无效dash(又名/bin/sh )。

  • O=(); A=(); while x="$1"; shift; do case $x in -*) O+=("$x");; *) A+=("$x^{}");; esac; done;分隔选项(-something)和参数(其他所有内容)。选项位于数组O中,而参数位于数组A中。请注意,所有参数都附加了^{},这些参数会跳过注释(这样您就可以使用带注释的标记)。

  • g(){ git show "${A[$1]}" && return; echo FAIL ${A[$1]}; git show "${A[$2]}"; };创建一个辅助函数,对第一个参数执行git show。如果失败,则输出&#34; FAIL first-argument&#34;然后输出第二个参数。这是一个减少开销失败的技巧。 (适当的错误管理会太多。)

  • diff "${O[@]}" <(g 0 1) <(g 1 0)使用针对第一个参数和第二个参数的给定选项运行diff(将所述FAIL错误回退到另一个参数以减少diff)。

  • --允许将diff - 选项(-something)传递给此别名/脚本。

错误:

  • 未检查参数数量。第二个参数背后的所有内容都会被忽略,如果你给它太少,你只会看到FAIL或者什么都没有。

  • 错误行为有点奇怪,输出混乱。如果您不喜欢这样,请使用2>/dev/null运行它(或适当更改脚本)。

  • 如果出现问题,它不会返回错误。

  • 您可能希望默认将其提供给寻呼机。

请注意,很容易定义一些别名,如:

git config --global alias.udiff '!git sdiff -u'
git config --global alias.bdiff '!git sdiff -b'

git config --global alias.pager '!pager() { cd "$GIT_PREFIX" && git -c color.status=always -c color.ui=always "$@" 2>&1 | less -XFR; }; pager'
git config --global alias.ddiff '!git pager udiff'

我希望不需要进一步解释。

对于更多这样的别名,或许可以查看my GitHub repo