【问题标题】:Merge 2 text files with differences marked as conflicts合并 2 个文本文件,其中差异标记为冲突
【发布时间】:2019-01-24 12:11:28
【问题描述】:

我想查看 2 个合并文件的完整输出,其中每个差异的标记方式与 git 标记文件中的冲突相同。 用例是合并 2 个相似的配置文件,检查合并后的文件,并提供视觉提示以明确文件之间的所有差异,以便轻松决定选择哪一个。

我已经尝试过使用 diff 和 diff3,但我只能获得差异(使用 diff)或仅标记冲突的完全合并文件(使用 diff3 -m -A file1 file1 file2)。我使用过 git diff 和相关工具,但它们都合并了不冲突的更改,而不是将它们标记为差异。

运行环境将是一个 bash shell 脚本,因此最好使用常用的 linux 工具达到所需的输出。

例子:

file1 的内容:

environment:
  base_branch: master
  branch: this_is_the_same_for_both_files

file2 的内容:

environment:
  base_branch: a_different_base_branch
  branch: this_is_the_same_for_both_files
  a_new_key: the_new_key_value

期望的输出:

environment:
<<<<< file1
  base_branch: master
=====
  base_branch: a_different_base_branch
>>>>> file2
  branch: this_is_the_same_for_both_files
<<<<< file1
=====
  a_new_key: the_new_key_value
>>>>> file2

【问题讨论】:

  • 这个answer 非常接近我的需要,但它不使用 git 样式分隔符(即 >>>>)。我需要使用它们,以便稍后我可以检查是否有任何差异仍未完全合并。
  • 我没有找到完全符合您要求的内容。所以我会在diff -DVERSION1 之上编写一个解析器,将其转换为 git 样式分隔符。这是一个非常简单的转换,只有几个逻辑分支,虽然 sed 不会这样做,因为您可能需要重新排序一些块。
  • 请注意,要获得正确的标记,您需要一个合并基础版本:通用版本,两者都不同。使用两者中的一个作为公共基础,就像您在 diff3 中所做的那样,意味着一侧对文件进行了no 更改,因此 all 更改必须具有根据定义来自另一方。

标签: bash git diff


【解决方案1】:

根据 cmets 的建议,我想出了一个似乎可以解决我的问题的班轮。 我本来希望在sed 替换中使用常量作为标记,但显然在mac os 中使用包含\nsed 的变量并不简单。

即使在使用 diffutils 的 docker alpine:3.8 中,此代码似乎也能正常工作。 其他选项(brew gnu-sed 和类似的)可能不容易移植。

diff -D AAAAAAA "${path}" <(echo -n "$decrypted") | \
  sed -e $'s/#ifndef AAAAAAA/<<<<<<< file-on-disk/g' | \
  sed -e $'s/#endif \/\* ! AAAAAAA \*\//=======\\\n>>>>>>> file-from-secret/g' | \

  sed -e $'s/#else \/\* AAAAAAA \*\//=======/g' | \

  sed -e $'s/#ifdef AAAAAAA/<<<<<<< file-on-disk\\\n=======/g' | \
  sed -e $'s/#endif \/\* AAAAAAA \*\//>>>>>>> file-from-secret/g';

解释:

diff -D AAAAAAA "${path}" &lt;(echo -n "$decrypted"):输出带有“#ifdef NAME”差异的合并文本。我使用 AAAAAAA 作为标记名称。 Diff 使用#ifndef AAAAAAA#endif /* ! AAAAAAA */ 包围仅存在于第一个文件中的文本,使用/#ifdef AAAAAAA#endif /* AAAAAAA */ 包围仅存在于第二个文件中的文本。注意第一个#ifndef 中的n 和第一个#endif 注释中的!。由于所有标记都不同,因此执行替换变得容易。

sed -e $'s/#endif \/\* ! AAAAAAA \*\//=======\\\n&gt;&gt;&gt;&gt;&gt;&gt;&gt; file-from-secret/g':将标记替换为

=======
>>>>>>> file-from-secret

由于有\n,替换字符串用$'' 括起来,它可以正确解释换行符。但是,\ 需要双重转义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 2012-08-10
    • 2013-05-10
    • 1970-01-01
    相关资源
    最近更新 更多