1

我有一个包含大量(数百个)类似大块的提交,我想列出提交中的每个唯一大块以便比较它们。

我编写了以下 GNU awk 脚本,它将每个块写入一个唯一的文件 ( hunk-[md5-of-hunk].txt):

BEGIN {
  hunk = ""
  buildhunk = 0
}

function writeHunk() {
  if (length(hunk) > 0) {
    print hunk > "hunk.tmp"
    close("hunk.tmp")
    cmd = "cat hunk.tmp | md5"
    cmd | getline md5
    close(cmd)
    if (!(md5 in hunkfiles)) {
      hunkfilename = "hunk-" md5 ".txt"
      print hunk > hunkfilename
      hunkfiles[md5] = hunkfilename
    }
  }
}

/^@@|^diff/ {
  writeHunk()
  hunk = ""
  buildhunk = ($1 == "@@") ? 1 : 0
}

/^[ +-]/ {
  if (buildhunk) {
    hunk = hunk $0 "\n"
  }
}

END {
  writeHunk()
  system("rm hunk.tmp")
  for (md5 in hunkfiles) {
    print hunkfiles[md5]
  }
}

然后我用 运行它git show [commit-SHA] | awk -f my_script.awk,它会创建并列出结果文件。它适用于我的目的,但有没有办法使用 git 的管道命令更有效地做到这一点。

例子

假设提交的补丁看起来像这样(为了清楚起见,减少到下面的 1 行上下文):

diff --git a/file1.txt b/file1.txt
index a3fb2ed..4d6f587 100644
--- a/file1.txt
+++ b/file1.txt
@@ -3,2 +3,3 @@ context
 context
+added line
 context
@@ -7,2 +8,3 @@ context
 context
+added line
 context
@@ -11,2 +13,3 @@ context
 context
+added line
 context
@@ -15,2 +18,3 @@ context
 context
+different added line
 context
@@ -19,2 +23,3 @@ context
 context
+different added line
 context
@@ -23,2 +28,3 @@ context
 context
+different added line
 context
@@ -27,2 +33,3 @@ context
 context
+even more different added line
 context
@@ -31,2 +38,3 @@ context
 context
+even more different added line
 context

我希望能够确定只有 3 个独特的帅哥,看看它们是什么。即:

独特的大块头1:

 context
+added line
 context

独特的大块头2:

 context
+different added line
 context

独特的大块头3:

 context
+even more different added line
 context
4

1 回答 1

3

提交是快照,因此它们没有差异

当然,差异确实有差异。因此,如果您只有一次提交,则根本无法执行此操作。你需要两次提交。然后,您只需区分它们并做您正在做的事情。

请注意,git show <commit-hash>真正的意思是git diff <parent or parents of commit> <commit-hash>. 如果指定的提交是合并提交,这会产生一个组合的 diff,这可能对您的目的没有用,因为组合的 diff 故意完全忽略了许多更改。您可能希望仅针对提交的第一个父项运行显式差异(仅查看作为合并的一部分引入的更改)。

Git 的某些部分在内部做一些事情,比如你正在做的事情,forgit rereregit patch-id. 但是,它们并没有完全按照您正在做的事情:因为rerere它们仅记录存在合并冲突的差异块,并将这些差异块(由哈希 ID 和文件名保存)与稍后记录的分辨率相匹配。因为patch-id他们去除了行号和空白,但将来自提交的整个更改集累积到一个大块中。如果 Git 有一点管道来git patch-id逐个地完成部分工作,而不依赖于计算提交的整体补丁 ID,那可能会很好,但事实并非如此。

于 2017-05-17T05:38:11.450 回答