git:通过提交

时间:2017-05-29 14:49:19

标签: git

我想看看在第147行对this文件做了哪些更改。所以我通过以下方式逐行查询文件:

git blame include/svl/itemset.hxx

这是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; }

现在我想看看使用SHA d210c6ccc3对这些行进行了哪些更改。基本上我想看到这个提交对文件所做的更改。所以我做了:

`git show d210c6ccc3 include/svl/itemset.hxx`

但这似乎没有给我正确的输出,实际上它什么都没输出。任何人都可以建议我可以缺少什么?或者也许还有其他更好的方法来了解所选提交对文件做了哪些更改?

4 个答案:

答案 0 :(得分:13)

eftshift0's answer是正确的(我已经投了赞成票)。这里是为什么,以及另外一件可能出错的事情。

大多数案例中,git show commit -- path是正确的,并会向您显示:

  • 指定提交的日志消息,
  • 该特定文件的补丁,通过将该提交与其父级进行比较而生成。

补丁与git diff commit^1 commit -- path生成的补丁相同。 (请注意,^1后缀是文字文本,而 commit 部分是您替换的哈希ID。后缀语法表示“查找第一个父项”。您可以将此后缀添加到大多数提交选择器中,但不是对使用某些搜索模式的选择器添加。请参阅the gitrevisions documentation。)

有两个重要的例外。这里只有其中一个适用,因为git blame通常不会归咎于合并,它会尝试跟踪将输入合并的更改的。不过,我想提一下,因为git show在合并时的行为很有趣。 : - )

如果您查看合并提交git show,默认情况下,您将看到组合差异(“所有父项”与合并提交的内容)。在这种情况下,您可能希望直接退回到git diff,以便您可以指定要比较的父级(^1^2,如果这是章鱼合并则更多)。原因是组合差异故意省略任何与其中一个父提交中的版本匹配的文件:这意味着从该点开始存储库中的任何内容,它来自两个中的一个(或N如果N> 2)合并的“边”。

使用git blame,您正在寻找“谁改变了什么”。进行合并的人通常不是进行更改的人 - 因此您应该继续“合并后”以找出真正更改了谁。

第二个例外是在这里引起问题的一个例子,而且在开发期间文件被重命名时,git blame的工作方式实际上就更多了。

git blame正在分析文件的更改(例如include/svl/itemset.hxx)时,它会从您指定的任何提交开始,逐步退回一次提交。如果您没有选择自己的起点,则从HEAD开始,即当前提交。然后它查看父提交(就像通过git show一样)。例如,如果当前提交922e935c8812是普通提交且其父提交为22c6554c98e2,则会将提交922e935c881222c6554c98e2进行比较。如果22c6554c98e2有一个同名的文件,那可能是相同的文件 ...但是如果不是,Git会尝试弄清楚 22c6554c98e2中的哪个文件include/svl/itemset.hxx是同一个文件。

在这种情况下,确切的事情发生在提交b9337e22ce1d。在提交include/svl/itemset.hxx中有一个名为b9337e22ce1d的文件,但在提交b9337e22ce1d^f4e1642a1761中,该文件名为svl/inc/svl/itemset.hxx。 Git在从提交b9337e22ce1d退回到提交f4e1642a1761时检测到此重命名,然后git blame名称从提交f4e1642a1761带回来提交d210c6ccc3

但是,当您运行git show d210c6ccc3时,Git会直接跳转到d210c6ccc3(及其父7f0993d43019)。它不再知道include/svl/itemset.hxx中名为HEAD的文件在svl/inc/svl/itemset.hxx中被命名为d210c6ccc3。因此必须发现这一点,并将之前的名称传递给Git。

您可能想知道如何找到这个。答案是使用git log --follow--follow的{​​{1}}代码不是很好, 1 但它是git log使用的相同的代码,所以它生成相同的代码答案,至少。这是我做的:

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

如果$ 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 出现在“d210c6ccc3之前”,则必须使用更早的路径名 - 但提交e6b4345c7f40d210c6ccc3的后代。 },而不是祖先。

1 当合并发生变化时,从根本上讲,这确实需要同时跟随两个(或所有)输入提交。但是,Git不能(目前?)能够做到这一点:e6b4345c7f40git log --follow实际上只遍历文件的最终版本“来自”的父级。也就是说,如果我们查看包含合并文件git blame的典型合并提交M,则有两个输入FM^1:F,以及一个输出M^2:F 。如果M:FM:F相同,我们应该完全忽略 M^1:FM^2:F的所有内容都来自提供{{1}的人}}。如果M:FM^1:F相同,我们应该完全忽略 M:FM^2:F的所有内容都来自提供{{1}的人}}

请注意,这仅适用于一次一个文件,即便如此,只有当文件完全匹配两个输入中的一个时,它才有效。否则,我们应该查看组合diff 以查看如何从两个输入修改文件。这是组合差异和历史简化背后的逻辑。但在极少数情况下它过于简化,因此有时会出错。

答案 1 :(得分:6)

您必须提供该修订中的路径:

git show d210c6ccc3 -- svl/inc/svl/itemset.hxx

应该这样做

答案 2 :(得分:1)

您可以使用

git diff d210c6ccc3^ d210c6ccc3 include/svl/itemset.hxx

查看对提交(d210c6ccc3)中的文件所做的更改与其前任(d210c6ccc3^)相比。

d210c6ccc3^是'base',而d210c6ccc3是您要与基地进行比较的提交。

如果您在问题的评论中提到过,那么您正在查看错误的提交,然后替换上面的SHA。

这将给出文件内容的diff输出,您提供的git show命令将输出提交消息 - 仅当在指定的提交中修改了该文件时。

答案 3 :(得分:0)

尝试public class Quick { public static void Sort(IComparable[] a) { Random r = new Random(); a = a.OrderBy(x => r.Next()).ToArray(); Sort(a, 0, a.Length - 1); } private static void Sort(IComparable[] a, int lo, int hi) { if (lo >= hi) return; int p = Partition(a, lo, hi); Sort(a, lo, p - 1); Sort(a, p + 1, hi); } private static int Partition(IComparable[] a, int lo, int hi) { int i = lo, j = hi; IComparable p = a[lo]; while (true) { while (Less(a[++i], p)) { if (i == hi) break; } while (Less(p, a[--j])) { if (j == lo) break; } if (i >= j) break; Exch(a, i, j); } Exch(a, lo, j); return j; } private static void Exch(IComparable[] a, int lo, int hi) { IComparable tmp = a[lo]; a[lo] = a[hi]; a[hi] = tmp; } private static bool Less(IComparable a, IComparable b) { return a.CompareTo(b) < 0; } public static void Main(string[] args) { string[] nums = File.ReadAllLines(args[0]); for (int i = 0; i < nums.Length; i++) { Console.WriteLine(nums[i]); } Sort(nums); Console.WriteLine("After sorting:"); for (int i = 0; i < nums.Length; i++) { Console.WriteLine(nums[i]); } Console.ReadKey(); } }