惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Vulnerabilities – Threatpost
T
The Blog of Author Tim Ferriss
S
SegmentFault 最新的问题
D
DataBreaches.Net
博客园_首页
罗磊的独立博客
B
Blog
T
Threat Research - Cisco Blogs
C
Cisco Blogs
GbyAI
GbyAI
Engineering at Meta
Engineering at Meta
WordPress大学
WordPress大学
G
GRAHAM CLULEY
H
Help Net Security
酷 壳 – CoolShell
酷 壳 – CoolShell
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
爱范儿
爱范儿
SecWiki News
SecWiki News
T
Threatpost
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Schneier on Security
Schneier on Security
T
The Exploit Database - CXSecurity.com
Google Online Security Blog
Google Online Security Blog
T
Tor Project blog
小众软件
小众软件
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Y
Y Combinator Blog
H
Hacker News: Front Page
V
V2EX
Security Latest
Security Latest
Cloudbric
Cloudbric
Simon Willison's Weblog
Simon Willison's Weblog
Attack and Defense Labs
Attack and Defense Labs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
P
Proofpoint News Feed
博客园 - 三生石上(FineUI控件)
NISL@THU
NISL@THU
S
Secure Thoughts
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
V2EX - 技术
V2EX - 技术
Vercel News
Vercel News
P
Palo Alto Networks Blog
IT之家
IT之家
MyScale Blog
MyScale Blog
有赞技术团队
有赞技术团队
Application and Cybersecurity Blog
Application and Cybersecurity Blog
D
Docker
Google DeepMind News
Google DeepMind News
Webroot Blog
Webroot Blog

胡涂说

当心流量别被 Agent 都吃了 当 AI 构建自己 阿嬷 ā mó Bun 要从 Zig 迁移到 Rust ? 好奇心周刊第25期: 如何让AI写好代码 好奇心周刊第24期: 关于AI编程的一些体会和设想 云何降伏其心 好奇心周刊第23期: Claude Code 氛围编程初体验 好奇心周刊第22期: 纳瓦尔谈人生 不确定性世界的生存策略 好奇心周刊第21期: 推理模型的构建与未来 好奇心周刊第20期: 从四个方面了解Palantir 周刊第19期: 一起学习 MCP 周刊第18期: 什么是理工科思维 周刊第17期: 如何构建智能体(Agent) 周刊第16期: Andrej Karpathy 讲 AI 读《毛泽东传》对个人的启发 周刊第15期:Nat Friedman 和 Derek Sivers 的自我介绍 周刊第14期:罗振宇和《罗辑思维》 我看《哪吒》 为什么写作? 心猿意马 从铁幕到硅幕 银弹飞过先锋大厦 从神经网络到 Hugging Face 在大理,听打雷 Git 纪元 凡所有相,皆是虚妄 马斯克的故事与模式 纳瓦尔的智慧 当魔法消失时 人生无论怎么度过都像是浪费 我们都是新穷人 代码、法律和自由软件 乾隆的性格 当下我们还需要启蒙吗? 云门胡饼赵州茶 上海周末骑行:从浦东到外白渡桥 如何选择图书译本? No.13: 周刊的周刊 读书日,推荐些童话和小说 学习邓小平的智慧 自建博客 Nginx 基本配置 给博客换了套新评论系统 我所理解的存在主义 心经说了什么 觉悟之道就是活在当下 巨人的笔记 从零到百亿美金之路 人生如逆旅,我亦是行人 和自己非暴力沟通 听斯蒂芬·金谈写作 行不尽,行不尽,一路青山 周刊第12期:第一次十字军东征 周刊第11期:玄奘之路 周刊第十期:敦煌 周刊第九期:卡片盒笔记法 爸爸是最聪明的 Ruby 编程语言入门 影响人类命运的是什么? 周刊第八期:如何应对公开错误 周刊第七期:如何学习 周刊第六期 周刊第五期 只买书:一个失败的微信小程序产品 改变世界的一次代码提交 如何成为一名黑客 通往开源之路 空山不见人 如何做好演讲 “人生在世,永远也不该演戏作假” 周刊第四期 大卫四岁读的书 宇宙就是一个蛋 周刊第三期 周刊第二期 周刊开刊 重学C语言 英国随记 变成神的动物 人类伟大的时刻 最著名的黑客 《巨婴国》读后 若为自由故 买房记 答案在风中飘 陪产记 自由的代价 谈一谈英语学习 读《霍乱时期的爱情》 简洁 嵌套的梦 四月莎士比亚 七律三首 从明天起,做一个Scrum Master 不能承受的生命之轻 我是丽莎呀 爱美丽、黑暗王子和豌豆公主 诗歌与烟台
阅读开源代码小技巧
胡涂说 · 2019-08-18 · via 胡涂说

通过阅读源码来学习开源项目是最直接也最有效的方法。而想要了解一个开源项目,最好是从第一个 commit 开始看起,特别是第一个最小可用版本发布前的 commits, 通过阅读对每一次 commit 提交源码,能够最直接的理解作者的设计思路和开发过程中的思考。

在 GitHub 的 repository 页面上可以很方便的看到所有历史记录及其演进。不过,使用 IDE 或有跳转功能的编辑器来阅读会更方便。这就需要我们将代码仓 Clone 到本地。

Clone 下来的开源 Git 仓,想要签出第一次 commit 也简单:通过 git log --reverse 倒序展示 log,排在第一个的即是第一次 commit, 拷贝 commit sha 值,然后 git checkout commit_sha 便可以签出该commit的代码。

当我们想继续跟着作者的节奏看接来下开发的内容,便需要再次 show log, 并找出下一次的 commit sha 值,如果 commit 记录很多,找起来就不那么容易了。因此我在看 git 代码历史的时候想,能不能将 git commits 历史记录当成像网站页面一样可以分页查看呢,通过简单的上翻下翻命令来 checkout 到各 commit 节点的代码。

其实也不难,无非是用管道将上面提到的命令串起来,写成 shell 可执行文件放到 git 安装的 bin 目录即可。签出第一次 Commit 节点代码的 shell 脚本如下:(通过 git log --reverse --pretty=%H 可以将 log 记录倒序并只显示sha值,然后通过 args 获取管道输出 checkout.)

将它存为 git-first 可执行文件,放到 git 安装的 bin 目录(Linux、Mac 或 Windows 皆可)。在 git 仓中执行 git first 即可 checkout 出第一次 commit 节点的代码。

Windows 的 Git 一般安装在 C:\Program Files\Git 下,bin 目录非根目录下的 bin, 而是在 usr/bin 下,直接将 git-first 等文件拷贝至该目录即可。(注意:该目录原来有 git-flow 等文件。)

签出当前 commit 记录的下一个节点代码要稍微复杂些,不过也就是多了些命令的组合, stackoverflow 搜一下就能找到。通过 git rev-parse HEAD 可获取当前工作区代码的 commit sha 值,然后用 grep -A 找出倒序 log 后当前 commit sha 值的后一条记录,得到 sha 值后进行 Checkout 操作。git-next 的脚本如下:

同样的,签出最后一条记录(git-last)和上一条记录(git-prev)也可以通过命令组合来实现。我还增加可选参数,可以一次上翻/下翻 n条 commit. 四个脚本的源码放在了GitHub上。

在查看 git 仓库源码时便可以通过 git next, git prev 来轻松逐个 commit 进行 checkout 了。也可以通过 git next 5 来签出当前 commit 依次往后第5条 commit 的代码。 通过git first, git last 来签出第一条 commit 及最后一条节点的代码。

于是,拿到一份开源代码后,我便首先通过 git first 签出第一次 commit 的代码,然后通过 git next 逐个 commit 进行阅读。为了快速了解 commit 之间的差异,可以通过执行 git diff HEAD^ HEAD 来了解当前 commit 改了哪些内容。(嫌每次执行 diff 命令太长,可以设置 alias: git config --global alias.df 'diff HEAD^ HEAD'。这样,每次仅需执行 git df 便可以快速浏览差异了。)

在调试脚本时发现一个问题, shell 中的函数如果写上function在 Ubuntu 等 Linux 上反倒执行会报错。比如first() {...} 写成 function first() {...}. 执行时会报 syntax error: "(" unexpected. 的错误。上网查了一下,了解到在某些 Linux 发行版上 sh 指向 dash,不识别 function 标志符。 解决办法是要么将脚本的执行器改成 bash ,或直接将 function 去掉,这也是能兼容多种 shell 的最好方式。

最后再附一遍脚本地址,如果你觉得有用,请加 star: hutusi/git-paging,提 issue 或 pr 帮助改进。 1


Footnotes

  1. 之前脚本源码放在 gist (https://gist.github.com/hutusi/e4f32e2bcd8d53ec86de8254ab0d5127)上,但 gist 管理批量源码不太方便,且有时访问不了,因此移到 repos 中管理,也方便提 issue 或 pr.