学习用工具来驾驭 Git 历史

现在,我们来深入了解怎么去使用 git 的历史以及如何很轻松地去浏览它的历史。

-- Ilija Eftimov

致谢

编译自 | https://ieftimov.com/learn-your-tools-navigating-git-history

作者 | Ilija Eftimov

译者 | qhwdw 共计翻译:82篇 贡献时间:120 天

在你的日常工作中,不可能每天都从头开始去开发一个新的应用程序。而真实的情况是,在日常工作中,我们大多数时候所面对的都是遗留下来的一个代码库,去修改一些特性的内容或者现存的一些代码行,这是我们在日常工作中很重要的一部分。而这也就是分布式版本控制系统 的价值所在。现在,我们来深入了解怎么去使用 的历史以及如何很轻松地去浏览它的历史。

Git 历史

首先和最重要的事是,什么是 历史?正如其名字一样,它是一个 仓库的提交历史。它包含一堆提交信息,其中有它们的作者的名字、该提交的哈希值以及提交日期。查看一个 仓库历史的方法很简单,就是一个 命令。

旁注:为便于本文的演示,我们使用 Ruby on Rails 的仓库的 分支。之所以选择它的理由是因为,Rails 有良好的 历史,漂亮的提交信息、引用以及对每个变更的解释。如果考虑到代码库的大小、维护者的年龄和数量,Rails 肯定是我见过的最好的仓库。当然了,我并不是说其它的 仓库做的不好,它只是我见过的比较好的一个仓库。

那么,回到 Rails 仓库。如果你在 Ralis 仓库上运行 。你将看到如下所示的输出:

正如你所见, 展示了提交的哈希、作者及其 email 以及该提交创建的日期。当然, 输出的可定制性很强大,它允许你去定制 命令的输出格式。比如说,我们只想看提交信息的第一行,我们可以运行 ,它将输出一个更紧凑的日志:

如果你想看 的全部选项,我建议你去查阅 的 man 页面,你可以在一个终端中输入 或者 来获得。

小提示:如果你觉得 看起来太恐怖或者过于复杂,或者你觉得看它太无聊了,我建议你去寻找一些 的 GUI 或命令行工具。在之前,我使用过GitX

[1]

,我觉得它很不错,但是,由于我看命令行更“亲切”一些,在我尝试了tig

[2]

之后,就再也没有去用过它。

寻找尼莫

现在,我们已经知道了关于 命令的一些很基础的知识之后,我们来看一下,在我们的日常工作中如何使用它更加高效地浏览历史。

假如,我们怀疑在 方法中有一个预期之外的行为,我们希望能够找出原因,并且定位出实现它的代码行。

为达到上述目的,你可以使用的第一个命令是 ,通过它可以找到这个方法定义在什么地方。简单来说,这个命令输出了匹配特定模式的那些行。现在,我们来找出定义它的方法,它非常简单 —— 我们对 运行 grep,然后看到的输出如下:

现在,虽然我们已经看到这个方法是在哪里创建的,但是,并不能够确定它是哪一行。如果,我们在 命令上增加 标志, 将提供匹配的行号:

更好看了,是吧?考虑到上下文,我们可以很轻松地找到,这个方法在 的第 205 行的 方法,它看起来像这样,是不是很容易?

尽管我们找到的这个方法是在 上的一个常见的调用,它调用了 上的另一个同名的方法。根据之前的 的结果,我们可以很轻松地发现结果的第二行, 在 186 行上。我们正在寻找的方法是这样的:

酷!考虑到 Rails 仓库的大小,我们借助 找到它,用时都没有超越 30 秒。

那么,最后的变更是什么?

现在,我们已经找到了所要找的方法,现在,我们需要搞清楚这个文件所经历的变更。由于我们已经知道了正确的文件名和行数,我们可以使用 。这个命令展示了一个文件中每一行的最后修订者和修订的内容。我们来看一下这个文件最后的修订都做了什么:

虽然我们得到了这个文件每一行的最后的变更,但是,我们更感兴趣的是对特定方法(176 到 189 行)的最后变更。让我们在 命令上增加一个选项,让它只显示那些行的变化。此外,我们将在命令上增加一个 (忽略)选项,去跳过那一行变更时的作者名字和修订(提交)的时间戳:

现在, 命令的输出展示了指定行的全部内容以及它们各自的修订。让我们来看一下指定的修订,换句话说就是,每个变更都修订了什么,我们可以使用 命令。当指定一个修订哈希(像 )作为一个参数时,它将展示这个修订的全部内容。包括作者名字、时间戳以及完整的修订内容。我们来看一下 188 行最后的修订都做了什么?

你亲自做实验了吗?如果没有做,我直接告诉你结果,这个令人惊叹的提交

[3]

是由Schneems

[4]

完成的,他通过使用 frozen 字符串做了一个非常有趣的性能优化,这在我们当前的场景中是非常有意义的。但是,由于我们在这个假设的调试会话中,这样做并不能告诉我们当前问题所在。因此,我们怎么样才能够通过研究来发现,我们选定的方法经过了哪些变更?

搜索日志

现在,我们回到 日志,现在的问题是,怎么能够看到 方法经历了哪些修订?

命令非常强大,因此它提供了非常多的列表选项。我们尝试使用 选项去看一下保存了这个文件的 日志内容,这个选项的意思是在 日志中显示这个文件的完整补丁:

这将给我们展示一个很长的修订列表,显示了对这个文件的每个修订。但是,正如下面所显示的,我们感兴趣的是对指定行的修订。对命令做一个小的修改,只显示我们希望的内容:

命令接受 选项,它用一个行的范围和文件名做为参数。它的格式可能有点奇怪,格式解释如下:

当我们运行这个命令之后,我们可以看到对这些行的一个修订列表,它将带我们找到创建这个方法的第一个修订:

现在,我们再来看一下 —— 它是在 2011 年提交的。 可以让我们重回到这个时间。这是一个很好的例子,它充分说明了足够的提交信息对于重新了解当时的上下文环境是多么的重要,因为从这个提交信息中,我们并不能获得足够的信息来重新理解当时的创建这个方法的上下文环境,但是,话说回来,你不应该对此感到恼怒,因为,你看到的这些项目,它们的作者都是无偿提供他们的工作时间和精力来做开源工作的。(向开源项目贡献者致敬!)

回到我们的正题,我们并不能确认 方法最初实现是怎么回事,考虑到这个第一次的提交只是一个重构。现在,如果你认为,“或许、有可能、这个方法不在 176 行到 189 行的范围之内,那么就你应该在这个文件中扩大搜索范围”,这样想是对的。我们看到在它的修订提交的信息中提到了“重构”这个词,它意味着这个方法可能在那个文件中是真实存在的,而且是在重构之后它才存在于那个行的范围内。

但是,我们如何去确认这一点呢?不管你信不信, 可以再次帮助你。 命令有一个 选项,它可以传递一个特定的字符串作为参数,然后去查找代码变更(添加或者删除)。也就是说,如果我们执行 这样的命令,我们可以看到所有包含 字符串的变更行的提交。

如果你在 Ralis 仓库上运行上述命令,首先你会发现这个命令运行有点慢。但是,你应该会发现 实际上解析了在那个仓库中的所有修订来匹配这个字符串,其实它的运行速度是非常快的。在你的指尖下 再次展示了它的强大之处。因此,如果去找关于 方法的第一个修订,我们可以运行如下的命令:

它将返回所有这个方法的引用和修改的地方。如果你一直往下看,你将看到日志中它的最后的提交:

很酷!是吧?它初次被提交到 Rails,是由 DHH 在一个 仓库上做的!这意味着 大概在一开始就被提交到了 Rails 仓库。现在,我们去看一下这个提交的所有变更信息,我们运行如下的命令:

非常好!我们终于找到它的根源了。现在,我们使用 的输出,结合 命令来跟踪这个方法都发生了哪些变更。

下次见

当然,我们并没有真的去修改任何 bug,因为我们只是去尝试使用一些 命令,来演示如何查看 方法的演变历史。但是不管怎样, 是一个非常强大的工具,我们必须学好它、用好它。我希望这篇文章可以帮助你掌握更多的关于如何使用 的知识。

你喜欢这些内容吗?

作者简介:

后端工程师,对 Ruby、Go、微服务、构建弹性架构来解决大规模部署带来的挑战很感兴趣。我在阿姆斯特丹的 Rails Girls 担任顾问,维护着一个小而精的列表,并且经常为开源做贡献。

那个列表是我写的关于软件开发、编程语言以及任何我感兴趣的东西。

via:https://ieftimov.com/learn-your-tools-navigating-git-history

作者:Ilija Eftimov

[6]

译者:qhwdw校对:wxy

本文由LCTT原创编译,Linux中国荣誉推出

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180228B06Q4200?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券