git:通过提交查看对特定文件的更改
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/44245286/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
git: See changes to a specific file by a commit
提问by Rohan Kumar
I want to see the what changes were made to thisfile's at line 147. So i enquired the file line by line for commits by:
我想看看在第 147 行对该文件进行了哪些更改。所以我逐行查询文件中的提交:
git blame include/svl/itemset.hxx
Here is the trimmed output of git blame:
这是 git blame 的修剪输出:
4b3a535ae3 include/svl/itemset.hxx (Michael Stahl 2015-04-08 15:02:47 +0200 145) SfxItemPool* GetPool() const { return m_pPool; }
4b3a535ae3 include/svl/itemset.hxx (Michael Stahl 2015-04-08 15:02:47 +0200 146) const sal_uInt16* GetRanges() const { return m_pWhichRanges;
}
d210c6ccc3 svl/inc/svl/itemset.hxx (Xiaofei Zhang 2010-07-29 10:56:19 +0800 147) void SetRanges( const sal_uInt16 *pRanges );
d210c6ccc3 svl/inc/svl/itemset.hxx (Xiaofei Zhang 2010-07-29 10:56:19 +0800 148) void MergeRange( sal_uInt16 nFrom, sal_uInt16 nTo );
4b3a535ae3 include/svl/itemset.hxx (Michael Stahl 2015-04-08 15:02:47 +0200 149) const SfxItemSet* GetParent() const { return m_pParent; }
Now i want to to see what changes did that commit with SHA d210c6ccc3
to those lines. Basically i want to see the changes made by this commit to the file. So i did :
现在我想看看使用 SHAd210c6ccc3
对这些行进行了哪些更改。基本上我想看看这个提交对文件所做的更改。所以我做了 :
`git show d210c6ccc3 include/svl/itemset.hxx`
But this does not seem to give me right output, in fact it outputs nothing. Could anyone please suggest what could i be missing? Or maybe there is some other better way to know what changes were made to a file by a selected commit?
但这似乎没有给我正确的输出,实际上它什么都不输出。任何人都可以请建议我可能会遗漏什么吗?或者也许还有其他更好的方法来了解选定提交对文件进行了哪些更改?
采纳答案by torek
eftshift0's answeris correct (and I've upvoted it). Here's why, though—along with the one other thing that can go wrong here.
eftshift0 的答案是正确的(我已经赞成)。不过,这就是为什么- 以及这里可能出错的另一件事。
In mostcases, git show commit-- path
would be correct and would show you:
在大多数情况下,是正确的,并且会告诉你:git show commit-- path
- the log message for the specified commit, and
- a patch for that particular file, as produced by comparing that commit with its parent.
- 指定提交的日志消息,以及
- 该特定文件的补丁,通过将该提交与其父提交进行比较而产生。
The patch would be the same as that produced by git diff commit^1 commit-- path
. (Note that the ^1
suffix here is literal text while the commit
part is a hash ID that you replace. The suffix syntax means "find the first parent". You can add this suffix to most commit selectors, although not to selectors that use certain search patterns. See the gitrevisions documentation.)
该补丁将与. (请注意,这里的后缀是文字,而部分是您替换的哈希 ID。后缀语法的意思是“找到第一个父级”。您可以将此后缀添加到大多数提交选择器,但不能添加到使用某些搜索模式的选择器. 请参阅gitrevisions 文档。)git diff commit^1 commit-- path
^1
commit
There are two important exceptions. Only one of these applies here, because git blame
normally does not blame a merge, it tries to trace the sourceof the change that fed intothe merge. Still, I want to mention it, because git show
's behavior on merges is ... interesting. :-)
有两个重要的例外。这里只有其中一个适用,因为git blame
通常不会归咎于合并,它会尝试追踪进入合并的更改的来源。尽管如此,我还是想提一下,因为在合并时的行为是......很有趣。:-)git show
If you look at a merge commit with git show
, you will see, by default, a combined diff("all parents" vs the merge commit's content). In this case you may wish to fall back directly on git diff
, so that you can specify the parent you want to compare (^1
, ^2
, and even more if this is an octopus merge). The reason is that combined diffs deliberately omit any file that matches the version in one of the parent commits: this means that whatever is in the repository from that point forward, it came from oneof the two (or N if N > 2) "sides" of the merge.
如果您查看带有 的合并提交git show
,默认情况下您会看到一个组合差异(“所有父级”与合并提交的内容)。在这种情况下,您可能希望直接回退到git diff
,以便您可以指定要比较的父级(^1
, ^2
,如果这是章鱼合并,则更多)。其原因是,合并的diff故意省略的版本在父提交的任意一个相符的文件:这意味着无论是从该点向前库,它来自一个两个(或N,如果N> 2)“双方”的合并。
With git blame
, you are looking for "who changed what". The person who did the merge is often not the person who made the change—so you should keep going "behind the merge" to find who reallychanged it.
使用git blame
,您正在寻找“谁改变了什么”。进行合并的人通常不是做出改变的人——所以你应该继续“在合并之后”找到真正改变它的人。
The second exception is the one that caused a problem for you here, and it's really more a case of the way git blame
works when files get renamedduring development.
第二个例外是在这里给您带来问题的例外,它实际上更像是在开发过程中重命名git blame
文件时的工作方式。
When git blame
is analyzing changes to a file, such as include/svl/itemset.hxx
, it steps back one commit at at time, starting from whichever commit you specify. If you don't select your own starting point, it starts from from HEAD
, i.e., the current commit. It then looks at the parent commit(s) (as if via git show
for instance). For instance, if the current commit 922e935c8812
is an ordinary commit and its parent is 22c6554c98e2
, it compares commit 922e935c8812
to 22c6554c98e2
. If 22c6554c98e2
has a file of the same name, that's probably the same file... but if not, Git tries to figure out which filein 22c6554c98e2
is the same file as include/svl/itemset.hxx
.
在git blame
分析对文件的更改(例如 )时include/svl/itemset.hxx
,它会从您指定的任何提交开始,一次后退一个提交。如果您不选择自己的起点,则从 开始HEAD
,即当前提交。然后它查看父提交(git show
例如,好像通过)。例如,如果当前提交922e935c8812
是普通提交并且其父提交是22c6554c98e2
,则将提交922e935c8812
与进行比较22c6554c98e2
。如果22c6554c98e2
有一个文件同名,这可能是同一个文件...但如果不是,Git会试图找出哪些文件中22c6554c98e2
是同一个文件include/svl/itemset.hxx
。
In this case, that exact thing happens at commit b9337e22ce1d
. There is a file named include/svl/itemset.hxx
in commit b9337e22ce1d
, but in commit b9337e22ce1d^
or f4e1642a1761
, the file is named svl/inc/svl/itemset.hxx
. Git detects this rename when stepping back from commit b9337e22ce1d
to commit f4e1642a1761
, and git blame
then carries the newname back with it from commit f4e1642a1761
to commit d210c6ccc3
.
在这种情况下,确切的事情发生在 commit b9337e22ce1d
。有一个名为include/svl/itemset.hxx
commit的文件b9337e22ce1d
,但在 commit b9337e22ce1d^
or 中f4e1642a1761
,该文件名为svl/inc/svl/itemset.hxx
. Git的步进从提交回来时,检测到这一命名b9337e22ce1d
承诺f4e1642a1761
,并git blame
随后进行了新的与它的名字从回犯f4e1642a1761
犯d210c6ccc3
。
When you run git show d210c6ccc3
, however, Git jumps directly to d210c6ccc3
(and its parent 7f0993d43019
). It no longer knows that the file named include/svl/itemset.hxx
in HEAD
is named svl/inc/svl/itemset.hxx
in d210c6ccc3
. So youmust discover this, and pass the earlier name to Git.
git show d210c6ccc3
但是,当您运行时,Git 会直接跳转到d210c6ccc3
(及其父7f0993d43019
)。它不再知道名为include/svl/itemset.hxx
in的文件HEAD
名为svl/inc/svl/itemset.hxx
in d210c6ccc3
。因此,您必须发现这一点,并将较早的名称传递给 Git。
You might wonder how you can find this. The answer is to use git log --follow
. The --follow
code for git log
is not great,1but it's the samecode that git blame
uses, so it produces the same answers, at least. Here is what I did:
您可能想知道如何找到它。答案是使用git log --follow
. 的--follow
代码git log
不是很好,1但它使用的代码相同git blame
,所以它至少产生相同的答案。这是我所做的:
$ git log --oneline --follow --name-status include/svl/itemset.hxx
00aa9f622c29 Revert "used std::map in SfxItemSet"
M include/svl/itemset.hxx
afaa10da2572 make SfxItemSet with SAL_WARN_UNUSED
M include/svl/itemset.hxx
[snip]
a7724966ab4f Bin comments that claim to say why some header is included
M include/svl/itemset.hxx
b9337e22ce1d execute move of global headers
R100 svl/inc/svl/itemset.hxx include/svl/itemset.hxx
There's a second rename even earlier. Here's another, shorter way to find onlythe renames:
还有更早的第二次重命名。这是仅查找重命名的另一种更短的方法:
$ git log --oneline --follow --diff-filter=R --name-status include/svl/itemset.hxx
b9337e22ce1d execute move of global headers
R100 svl/inc/svl/itemset.hxx include/svl/itemset.hxx
e6b4345c7f40 #i103496#: split svtools in two libs, depending on whether the code needs vcl or not
R100 svtools/inc/svtools/itemset.hxx svl/inc/svl/itemset.hxx
If d210c6ccc3
came "before" e6b4345c7f40
, you would have to use the even-earlier path name—but commit d210c6ccc3
is a descendant of (comes after) e6b4345c7f40
, not an ancestor.
如果d210c6ccc3
出现在 "before" e6b4345c7f40
,你将不得不使用更早的路径名——但 commitd210c6ccc3
是 (comes after) 的后代e6b4345c7f40
,而不是祖先。
1When changes occur at merges, this really, in a fundamental sense, requires following both(or all) input commits simultaneously. However, Git is not (currently?) capable of doing this: both git log --follow
and git blame
really only traverse whichever parent the final version of the file "came from". That is, if we look at a typical merge commit M
containing merged file F
, there are two inputs M^1:F
and M^2:F
, and one output, M:F
. If M:F
is the same as M^1:F
, we should ignoreM^2:F
entirely: all the contents of M:F
are those from whoever provided M^1:F
. If M:F
is the same as M^2:F
, we should ignoreM^1:F
entirely: all the contents of M:F
are those from whoever provided M^2:F
.
1当合并发生更改时,从根本上讲,这确实需要同时遵循两个(或所有)输入提交。然而,Git 没有(目前?)能够做到这一点:两者git log --follow
和git blame
实际上只遍历文件“来自”的最终版本的任何父级。也就是说,如果我们查看M
包含合并文件的典型合并提交F
,则有两个输入M^1:F
和M^2:F
和一个输出M:F
。如果M:F
与 相同M^1:F
,则应完全忽略M^2:F
:所有内容M:F
均来自提供者M^1:F
。如果M:F
与 相同M^2:F
,我们应该完全忽略M^1:F
:所有内容M:F
是那些提供的人M^2:F
。
Note that this only works for one file at a time, and even then, it only works if the file exactly matchesone of the two inputs. Otherwise, we should look at the combined diffto see how the file got modified from bothinputs. This is the logic behind both combined diffs and History Simplification. But it's over-simplified in some rare cases, and hence sometimes gets things wrong.
请注意,这一次仅适用于一个文件,即使如此,它也仅适用于文件与两个输入之一完全匹配的情况。否则,我们应该查看组合差异以查看文件是如何从两个输入中修改的。这是组合差异和历史简化背后的逻辑。但在一些罕见的情况下它过于简化,因此有时会出错。
回答by eftshift0
You have to provide the path in that revision:
您必须在该修订版中提供路径:
git show d210c6ccc3 -- svl/inc/svl/itemset.hxx
That should do
那应该做
回答by Peter Reid
You can use
您可以使用
git diff d210c6ccc3^ d210c6ccc3 include/svl/itemset.hxx
to view the changes made to a file in commit (d210c6ccc3
) compared to it's predecessor (d210c6ccc3^
).
查看提交 ( d210c6ccc3
) 中的文件与其前身 ( d210c6ccc3^
)相比所做的更改。
Where d210c6ccc3^
is the 'base' and d210c6ccc3
is the commit you want to compare to the base.
d210c6ccc3^
“基础”在哪里,d210c6ccc3
是您要与基础进行比较的提交。
If as mentioned in comments on your question, you are looking at the wrong commit then replace the SHA above.
如果在对您的问题的评论中提到,您正在查看错误的提交,然后替换上面的 SHA。
This will give a diff
output of the contents of the files, the git show
command you gave will output the commit message - only if that file was modified in the commit specified.
这将给出diff
文件内容的输出,git show
您给出的命令将输出提交消息 - 只有在指定的提交中修改了该文件。
回答by Robin Wieruch
Try git diff <commit> -- include/svl/itemset.hxx
尝试 git diff <commit> -- include/svl/itemset.hxx