Git:我怎样才能找到与目录最匹配的提交?

时间:2011-06-17 15:44:15

标签: git diff commit patch

有人拿了Moodle的一个版本(我不知道),在一个目录中应用了很多变化,然后发布了它(tree here)。

如何确定最有可能编辑原始项目的哪个提交以形成此树?

这将允许我在使用此补丁的适当提交时形成分支。当然,它来自1.81.9分支,可能来自发布标记,但特定提交之间的差异对我没有多大帮助。

事后更新: knittl's answer让我尽可能接近我。我首先添加了我的补丁仓库作为远程“外来”(没有共同的提交,没关系),然后在带有几个格式选项的循环中做差异。第一个使用--shortstat格式:

for REV in $(git rev-list v1.9.0^..v1.9.5); do 
    git diff --shortstat "$REV" f7f7ad53c8839b8ea4e7 -- mod/assignment >> ~/rdiffs.txt; 
    echo "$REV" >> ~/rdiffs.txt; 
done;

第二个只计算了没有上下文的统一差异中的行变化:

for REV in $(git rev-list v1.9.0^..v1.9.5); do 
    git diff -U0 "$REV" f7f7ad53c8839b8ea4e7 -- mod/assignment | wc -l >> ~/rdiffs2.txt;
    echo "$REV" >> ~/rdiffs2.txt; 
done;

有数以千计的提交可以通过,但this one似乎是最接近的匹配。

5 个答案:

答案 0 :(得分:12)

您可以编写一个脚本,该脚本将给定树与存储库中的修订范围区分开来。

假设我们首先将更改的树(没有历史记录)提取到我们自己的存储库中:

git remote add foreign git://…
git fetch foreign

然后我们为要匹配的每个修订输出diffstat(简短形式):

for REV in $(git rev-list 1.8^..1.9); do
   git diff --shortstat foreign/master $REV;
done

查找具有最小更改量的提交(或使用某种排序机制)

答案 1 :(得分:2)

这是我的解决方案:

#!/bin/sh

start_date="2012-03-01"
end_date="2012-06-01"
needle_ref="aaa"

echo "" > /tmp/script.out;
shas=$(git log --oneline --all --after="$start_date" --until="$end_date" | cut -d' ' -f 1)
for sha in $shas
do
    wc=$(git diff --name-only "$needle_ref" "$sha" | wc -l)
    wc=$(printf %04d $wc);
    echo "$wc $sha" >> /tmp/script.out
done
cat /tmp/script.out | grep -v ^$ | sort | head -5

答案 2 :(得分:0)

如何使用git从1.8的所有版本创建补丁。和这个新版本的1.9。 然后你可以看到哪个补丁更有“感觉”。

例如,如果补丁“删除”了很多方法,那么可能不是这个版本,而是之前的版本。如果补丁有许多部分作为单个编辑没有意义,那么它可能也不是这个版本。

等等......实际上,遗憾的是,没有一种算法可以完美地完成这项工作。我必须要有一些启发式。

答案 3 :(得分:0)

这里有一些非常好的解决方案!

我使用了类似的方法来尝试找到壁橱源文件的修订版(给定目标文件):

  1. 向后遍历分支merge中的所有提交
  2. 寻找与文件target.txt最接近的匹配项
  3. 打印出git revision和不同文本行数

N.B。在新的一次性分支内执行-reset --hard具有破坏性(afaik)。

for REV in $(git rev-list merge); do
    git reset --hard "$REV"
    echo "$REV" `comm -2 -3 source.txt ../target.txt | wc -l`
done

您将获得类似以下的输出,它告诉您哪个修订版本是最接近的匹配项(即差异最小的行):

1c58bd5925a1fc8233730626**************** 771
HEAD is now at ...
9b2c29b00f1b4541a4135906**************** 775
HEAD is now at ...
b8e0bf5ec4372ebbcbd4edd0**************** 342
HEAD is now at ...
ba0d474bf2aac40dae48923e**************** 342
HEAD is now at ...
6d96921d3e9ad760ce55e76c**************** 335 <-- Closest match
HEAD is now at ...
795cd4caae5a5b08563443c9**************** 396
HEAD is now at ...
8743f42b24dd77e3bcc897dd**************** 399
HEAD is now at ...
d1b74dd33074c17da3fff638**************** 929

进一步阅读:

  • comm-用于输出不同的行
  • wc-用于计数文本行

信用:

答案 4 :(得分:-2)

如何使用'git blame'?它会告诉您,每行,谁更改了它,以及在哪个版本中。