如何使用git应用一个git单词差异(diff)?

10

我需要编辑一个混乱的提交(commit),它只更改了几行连续的单词,保留其中一些更改并删除其他更改。 这些更改在git diff --word-diff中很容易看到,在那种格式下我可以轻松地编辑差异块(hunks)以达到我的意图,但现在我有了一个像这样的文件。

diff --git a/cldf/forms.csv b/cldf/forms.csv
index 46c12a4..0374ece 100644
--- a/cldf/forms.csv
+++ b/cldf/forms.csv
@@ -1783,8 +1783,8 @@ ID,Lect_ID,Concept_ID,Form_according_to_Source,Form,Local_Orthography,Segments,C
1782,adan1251-lawah,day,dilɛlɛ,dilɛlɛ,dilele,d i l ɛ l ɛ,Lit. 'all day'.,datasets_Adang_Lawahing_tsv
1783,adan1251-lawah,day,wɛd saha,wɛd_saha,wed saha,w ɛ d _ s a h a,midday' lit. 'hot sun',datasets_Adang_Lawahing_tsv
1784,adan1251-lawah,morning,lalami,lalami,lalami,l a l a m i,,datasets_Adang_Lawahing_tsv
1785,adan1251-lawah,yesterday,ʔu:mi,ʔuːmi,[-umi-]{+'umi+},ʔ uː m i,,datasets_Adang_Lawahing_tsv
1786,adan1251-lawah,day_before_yesterday,ʔotariŋ alumi,ʔotariŋ_alumi,[-otaring-]{+'otaring+} alumi,ʔ o t a r i ŋ _ a l u m i,,datasets_Adang_Lawahing_tsv
1787,adan1251-lawah,tomorrow,dilɛlɛ,dilɛlɛ,dilele,d i l ɛ l ɛ,,datasets_Adang_Lawahing_tsv
1788,adan1251-lawah,day_after_tomorrow,a:lu,aːlu,alu,aː l u,,datasets_Adang_Lawahing_tsv
1789,adan1251-lawah,twilight_dawn,lalami,lalami,lalami,l a l a m i,"(lit, 'early morning')",datasets_Adang_Lawahing_tsv

我希望将此文件用作git apply的补丁。

然而,纯粹的git apply words.diff失败并显示fatal: corrupt patch at line 6——在未受影响的行中,正常的diff文件会以空格开头——我没有看到任何可能让git apply接受单词差异文件的内容。

如何说服git apply接受这种格式的文件作为补丁?或者如何轻松地将此文件转换为有效的补丁?


我有同样的问题,所以我在这个问题上设置了悬赏。如果有人能够展示如何将单词差异转换为普通差异并随后应用,则我也会授予悬赏。 - Henri Menke
你应该在这里检查user405725的答案:https://dev59.com/Pmsy5IYBdhLWcg3w2Bk6。他详细解释了补丁,这可能会给你更好的理解。 - Ekamjit Singh
1个回答

7

我找不到有效的解决方案,因此我编写了一个脚本,将单词差分转换为常规差分,以便应用:

#!/usr/bin/env perl
# convert-word-diff.pl -- rev. 2, this script is licensed under WTFPLv2

my (@minus, @plus);

sub flush_diff {
  print join("", map { "-$_" } @minus);
  print join("", map { "+$_" } @plus);
  @minus = (); @plus = ();
}

while (my $line = <>) {
  if ($line =~ /^(?:index |diff |\+\+\+ |\-\-\- |@@ )/) {
    flush_diff();
    print $line;
    next;
  }

  my $is_diff_line;

  if ($line =~ /\[\-.*\-\]/ || $line =~ /\{\+.*?\+\}/) {
    my $copy = $line;
    $copy =~ s/\[\-(.*?)\-\]\{\+.*?\+\}/\1/g;
    $copy =~ s/\[\-(.*?)\-\] ( )?/ \1 /g;
    $copy =~ s/\{\+.*?\+\} ?//g;
    push(@minus, $copy);

    $copy = $line;
    $copy =~ s/\[\-.*?\-\]//g;
    $copy =~ s/\{\+(.*?)\+\}/\1/g;
    push(@plus, $copy);
    $is_diff_line = 1;
  }

  unless ($is_diff_line) {
    flush_diff();
    print " $line" ;
  }
}

flush_diff();

使用方法:

cat word-diff.txt | perl convert-word-diff.pl | git apply

希望我没有搞砸什么,你现在正使用Linux/Mac操作系统,并且拥有Perl。


@HenriMenke 好的,经过仔细检查,我发现了一些问题。我已经更新了答案,并修复了转换器的第二个版本 :-) - eyevan
我仍然得到了一个损坏的补丁,但我还是授予了赏金以表彰你的努力。 - Henri Menke
@HenriMenke 你是怎么获得 word-diff 的?有没有可能你是手动编辑的?实际上,正确地手动编辑并不是很简单 :-) 如果您可以分享您的 diff,那么我们可以修复脚本或 diff。 - eyevan
我执行了 git show -w --word-diff 命令查看这个提交,因为我想消除过多的重新格式化。 - Henri Menke
问题:git diff --word-diff有损的printf 'a\n' >a.txt; printf 'a b\n\n' >b.txt; git diff --word-diff=plain --word-diff-regex=. a.txt b.txt - milahu
显示剩余2条评论

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