[英]git diff --name-only and SHA
我需要在两次提交之间运行git diff,结果应该是使用相应的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
}
因此获取修改$ f文件的最后一次提交/ SHA。
不知道是否有内部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
您的问题掩盖了一个基本问题。 让我们看一个典型的提交图片段:
...--E--F--G--H--I--J <-- master
您选择两个提交,例如E
和I
,然后运行git diff --name-only
(或git diff --name-status
)进行比较:
$ git diff --name-only <hash-E> <hash-I> myfolder/a.txt code/snippet.c test.txt
但然后说:
...结果应该是与相应的SHA一起引入的文件。
这些文件名出来的事实意味着所有三个文件都存在于提交E
和/或I
,但是如果您在工作树中拥有提交E
并想对其进行修改以得到提交I
,那么这三个文件将需要一些某种更改:创建,修改,甚至删除。 使用--name-status
会给你怎样的变化,以及: A
对“的文件将被新成立的”, M
为“该文件将被修改”,并D
为“该文件将被删除” 。 (有,当然,可能在这两个文件中的几十个或上千E
和I
是相同 ,因此在这里没有打印出来。)
但是现在,您需要在引入此更改的位置输入相应的哈希值。 可能没有一个哈希值。 可能不止一个 。 (当然必须至少有一个)。 例如, test.txt
可能会被错误地完全删除(而不是被更正)在F
,然后将其原封不动地放回H
,然后在I
更正。 同时,可以在G
和 I
中都修改code/snippet.c
。
您希望每个文件使用哪个提交哈希? 这个问题的答案决定了如何去发现它们。 (当然,如果只有一个这样的哈希,问题就消失了。)
xxfelixxx的答案给出了一种获取错误(提交错误,但易于修复和改进)的方法-第一个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
可以获取接触文件的最新提交,例如,在我们的示例中, G
和I
中的code/snippet.c
都为提交I
了哈希值。 这是因为Git从新的提交到旧的提交都向后工作。 如果要使用第一个,请使用tail -1
,如果要全部使用,则需要更高级的格式。 :-)
(这里在git log
和git rev-list
之间还有另一个细微的差别,涉及合并提交,但这可能不会影响您。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.