별도의 동일한 행 없이 diff를 생성하는 방법

별도의 동일한 행 없이 diff를 생성하는 방법

C 함수를 처음부터 다시 작성한다고 가정해 보겠습니다. 일부 줄, 특히 빈 줄과 닫는 중괄호가 앞뒤로 정확히 동일한 경우가 종종 발생합니다. 통합 diff( git diff또는 일반 GNU 사용)를 만들 때 diff -u동일한 줄이 큰 덩어리를 분리하여 검토자가 패치를 읽기 어렵게 만듭니다. 최소한의 차이를 만들어내려는 Diff의 야망은 때때로 가독성을 희생하는데, 이는 제가 원하는 것이 아닙니다. 대량을 함께 유지하기 위해 diff 희생을 최소화하는 방법이 있습니까?

예: diff에 의해 생성된 다음을 고려하십시오.


--- A   2018-10-01 09:37:37.606642955 +0200
+++ B   2018-10-01 09:37:40.405675295 +0200
@@ -1,6 +1,9 @@
 int fib(int n) {
-  if (n <= 1) {
-    return n;
+  int i, t1 = 0, t2 = 1;
+  for (i = 0; i < n; ++i) {
+    int next = t1 + t2;
+    t1 = t2;
+    t2 = next;
   }
-  return fib(n-1) + fib(n-2);
+  return t1;
 }
다음과 같은 패치가 읽기 더 쉬울 것 같지만 한 줄만 더 필요합니다.

--- A   2018-10-01 09:37:37.606642955 +0200
+++ B   2018-10-01 09:37:40.405675295 +0200
@@ -1,6 +1,9 @@
 int fib(int n) {
-  if (n <= 1) {
-    return n;
-  }
-  return fib(n-1) + fib(n-2);
+  int i, t1 = 0, t2 = 1;
+  for (i = 0; i < n; ++i) {
+    int next = t1 + t2;
+    t1 = t2;
+    t2 = next;
+  }
+  return t1;
 }

따라서 가능한 경험적 방법 중 하나는 "같은 행이 존재하고 해당 행 전후에 행이 추가 및 제거된 경우 동일한 행을 변경하는 것을 고려하는 것"입니다. 기존 패치에 이 규칙을 적용하기 위해 자체 스크립트를 만들 수도 있지만 문제를 해결할 수 있는 기존 도구가 있습니까?

답변1

diff -u출력을 다음으로 파이프하여 메서드를 구현할 수 있습니다 .

perl -0777 -pe '1 while s{^-.*\n\K((?:\+.*\n)+) ((.*\n)(?:-.*\n)+)}
                         {-$2$1+$3}mg'

이제는 외로운 공통 스레드를 표시하지 않는 것이 항상 가독성에 도움이 된다고 확신하지 않습니다. 예를 들면 다음과 같습니다.

--- A   2018-10-01 09:37:37.606642955 +0200
+++ B   2018-10-01 09:37:40.405675295 +0200
@@ -1,8 +1,11 @@
 int fib(int n) {
-  if (n <= 1) {
-    return n;
+  int i, t1 = 0, t2 = 1;
+  for (i = 0; i < n; ++i) {
+    int next = t1 + t2;
+    t1 = t2;
+    t2 = next;
   }
-  /* assinging foo */
+  /* assigning foo */
   foo = (bar ? bar : complicated_stuff(*a.asd.qwe|(FLAG1|FLAG2)));
-  return fib(n-1) + fib(n-2);
+  return t1;

perl위 코드의 출력은 다음과 같습니다.

--- A   2018-10-01 09:37:37.606642955 +0200
+++ B   2018-10-01 09:37:40.405675295 +0200
@@ -1,8 +1,11 @@
 int fib(int n) {
-  if (n <= 1) {
-    return n;
-  }
-  /* assinging foo */
-  foo = (bar ? bar : complicated_stuff(*a.asd.qwe|(FLAG1|FLAG2)));
-  return fib(n-1) + fib(n-2);
+  int i, t1 = 0, t2 = 1;
+  for (i = 0; i < n; ++i) {
+    int next = t1 + t2;
+    t1 = t2;
+    t2 = next;
+  }
+  /* assigning foo */
+  foo = (bar ? bar : complicated_stuff(*a.asd.qwe|(FLAG1|FLAG2)));
+  return t1;

나는 그것이 더 유용하다고 생각합니다. 그것은 diff복잡한 선이 변경되지 않았다는 것을 알려줍니다. 확장 버전에서는 둘 사이의 차이점을 찾아보고 싶을 수도 있습니다.

짧고 외로운 공통 줄(또는 공백이 아닌 수) 만 고려하기 ((.*\n)위해 로 바꿀 수 있습니다 .((.{0,20}\n)(((?:\h*\H){0,10}\h*\n)

답변2

다음 스크립트는 diff에서 "거의 완전히 다른" 시퀀스를 감지하고 이를 완전히 다른 것으로 처리하여 상황을 개선했습니다. 더 나은 솔루션을 찾으세요.

#!/usr/bin/python
import sys
(mbefore, pbefore, mid, mafter) = ([], [], [], [])
def flush():
    for x in (mbefore, pbefore, mid, mafter):
        sys.stdout.write(''.join(x))
        del x[:]

for line in sys.stdin:
    if line[0] == '-':
        if mid:
            mafter.append(line)
        else:
            flush()
            mbefore.append(line)
    elif line[0] == '+':
        if mafter:
            mbefore.append('-' + mid[0][1:])
            pbefore.append('+' + mid[0][1:])
            mbefore += mafter
            pbefore.append(line)
            del mafter[:]
            del mid[:]
        elif not mid and mbefore:
            pbefore.append(line)
        else:
            flush()
            sys.stdout.write(line)
    elif line[0] == ' ':
        if pbefore and not mid:
            mid.append(line)
        else:
            flush()
            sys.stdout.write(line)
    else:
        flush()
        sys.stdout.write(line)
flush()

관련 정보