2017-03-23 84 views
0

我需要在两次提交之间运行git diff,并且结果应该是与相应的SHA一起引入的文件。git diff --name-only和SHA

目前,我可以这样做:

git diff --name-only [start-sha] [end-sha] 

这给:

myfolder/a.txt 
code/snippet.c 
test.txt 

但我怎么拿到SHA因为当每个地方修改/添加这些文件的,因此所得到的输出变为:

myfolder/a.txt  2314d344 
code/snippet.c  gfhr76kl 
test.txt   jk5534bf 

图我可能只是这样做:

$files = git diff --name-only [start-sha] [end-sha] 
foreach ($f in $files) { 
    $sha = git log -n1 --format=format:%H $f 
    print $f $sha 
} 

因此让最后提交/ SHA所在的文件$ F已被修改。

回答

1

不知道是否有一个内部的git命令要做到这一点,但你总是刚刚超过您的文件回路和抢第一承诺:

for file in `git diff [start-sha] [end-sha] --name-only`; 
    do echo -n "$file "; git log --pretty=short [start-sha] [end-sha] -- $file | /bin/grep commit | cut -b8- | head -n 1; 
done 
1

你的问题掩盖了一个基本问题。让我们来看看一个典型的承诺图形片段:

...--E--F--G--H--I--J <-- master 

你挑两次提交,如EI,并运行git diff --name-only(或git diff --name-status)比较他们:

$ git diff --name-only <hash-E> <hash-I> 
myfolder/a.txt 
code/snippet.c 
test.txt 

但是然后说:

......结果是d是与对应的SHA引入的文件。

事实上,这些文件的名称问世意味着,所有这三个文件都存在于提交E和/或I,但如果你有承诺在您的工作树E,想修改它得到承诺I,这三个文件需要进行某种更改:创建,修改或甚至删除。使用--name-status也会给你种类的变更:A为“新建文件”,M为“文件将被修改”,D为“文件将被删除”。 (有,当然,大概几十成千上万的文件,在这两个EI相同,因此这里不打印。)

但现在你问相应的散列结果,其中这种变化是介绍。有可能不存在散列。可能有多于一个。 (当然必须有至少)。例如,test.txt可能被F完全删除(而不是被更正),在H中放回完整但是错误,然后在I中更正。同时code/snippet.c可能在GI中被修改。

哪个提交哈希(es)你想每个文件? 的答案是决定如何找到它们。 (当然,如果只有一个这样的散列,问题就消失了。)

xxfelixxx's answer给出了一个(slighlty错误但容易修复和改进)的方法来获得一个提交 - 第一个git log打印。要修复一个漏洞,提高它一下,更换do序列有:

do echo -n "$file "; git rev-list <starthash>..<endhash> -- "$file" | head -1 

也就是说,我们要找到git rev-list打印提交哈希值之一,当只在指定的开始运行/停止点寻找对一个文件的更改。我们需要<starthash>..<endhash>来执行初始提交限制,并且-- $file只选择添加,修改或删除该一个路径的提交。请注意,如果文件名中有空格,则需要引用它(所以我做过),但是然后读取git diff的输出本身也变得棘手。

使用head -1让你的最近提交感动的文件,例如,我们的例子code/snippet.c两个GI,你会得到提交I哈希值。这是因为Git向后工作,从较新的提交到较旧的提交。如果你想第一个之一,使用tail -1,如果你想要所有这些,你将需要一个fancier格式。 :-)

(还有一种微妙的区别就在这里,git loggit rev-list之间,涉及合并的提交,但可能不会影响到你。)