版本控制基础:Git核心概念、仓库结构、提交历史与差异分析、常用命令速查
做漏洞狩猎,版本控制是基本功。说白了,没有Git,补丁对比就是空中楼阁。
我刚开始接触安全研究时,总觉得Git就是个代码备份工具。直到有一次,我追一个CVE的根因,在commit历史里翻了两天,才意识到——每一次提交,都是一次攻击面的变化记录。从那以后,我再也不敢小看Git了。
Git核心概念:你只需要记住三个东西
Git的概念很多,但对我们做补丁分析来说,核心就三个:
- 提交(commit):代码的快照。每次commit,Git都会记录当前所有文件的完整状态。注意,是完整状态,不是差异。
- 分支(branch):指向某个commit的指针。默认是master或main。分支就是开发线的标签。
- HEAD:你当前在哪个commit上。HEAD可以指向分支,也可以直接指向某个commit( detached HEAD 状态)。
我个人习惯:在分析漏洞时,先把HEAD切换到漏洞修复前的那个commit,再切到修复后的commit。两边一对比,差异就出来了。这个操作,我一天能做几十次。
仓库结构:.git目录里有什么?
每个Git仓库下都有个.git目录。你不需要完全搞懂它,但有几个东西你得知道:
objects/:存储所有数据的地方。commit、tree、blob都在这里。每个对象用SHA-1哈希值命名。refs/:引用。包括分支(heads/)、标签(tags/)、远程分支(remotes/)。HEAD:一个文件,里面写着当前分支的引用路径。index:暂存区。你执行git add后,文件就进了这里。
嗯,这里要注意:不要手动修改.git目录里的文件。我曾经手贱改过一次,仓库直接崩了,花了一下午才恢复。
提交历史与差异分析:漏洞狩猎的核心操作
补丁对比,本质上就是看两个commit之间的差异。Git提供了几个命令,我几乎每天都在用:
1. 查看提交历史
git log --oneline -10
只看最近10条commit,每条一行。简洁,够用。
git log --oneline --graph --all
图形化显示所有分支的提交历史。我习惯用这个来快速定位漏洞修复的commit在哪个分支上。
避坑指南:我曾经在分析一个Linux内核漏洞时,发现修复commit在某个子模块的分支上,而主分支的log里根本看不到。用--all参数才找到。所以,永远记得加--all。
2. 查看具体差异
git diff commit1 commit2
比较两个commit之间的差异。这是补丁对比的核心命令。
git show commit_hash
查看某个commit的详细信息,包括作者、日期、提交信息,以及具体的代码改动。
为什么会这样?因为git show会把commit的完整内容展示出来,包括diff。我一般先用git log找到可疑的commit,然后用git show看具体改了啥。
3. 查看文件级别的改动
git diff --stat commit1 commit2
只看改动了哪些文件,不显示具体内容。适合快速了解改动范围。
git diff commit1 commit2 -- path/to/file
只看某个文件的差异。当你知道漏洞可能出在哪个文件时,这个命令最有用。
常用命令速查:我每天必用的几个
下面这个表格,是我自己整理的。你直接拿去用:
| 场景 | 命令 | 说明 |
|---|---|---|
| 查看历史 | git log --oneline -5 |
最近5条commit |
| 查看差异 | git diff A B |
比较A和B两个commit |
| 查看某个commit | git show <hash> |
显示完整改动 |
| 切换分支 | git checkout <branch> |
切换到指定分支 |
| 创建并切换 | git checkout -b <new> |
创建新分支并切换过去 |
| 暂存改动 | git stash |
临时保存当前工作区 |
| 恢复暂存 | git stash pop |
恢复最近一次stash |
| 查看分支图 | git log --graph --oneline --all |
图形化所有分支 |
警告:git checkout会直接切换工作区的文件。如果你有未提交的改动,可能会被覆盖。我建议你养成习惯:切换前先git status看一眼,或者用git stash暂存一下。
实战小技巧:如何快速定位漏洞修复的commit
你想想看,一个开源项目可能有几千甚至几万个commit。怎么找到那个修复漏洞的commit?
我的做法是:
- 看提交信息:搜索"fix"、"security"、"vulnerability"、"CVE"等关键词。
- 看文件路径:如果知道漏洞出在哪个模块,直接过滤文件路径。
- 看作者:有些安全研究员会专门提交修复,记住他们的名字。
# 搜索提交信息中包含"security"的commit
git log --oneline --grep="security"
# 搜索某个文件相关的commit
git log --oneline -- path/to/file.c
我记得有一次,我在分析一个Web应用漏洞时,提交信息里只写了"minor fix"。但文件改动里,有一行代码从strcpy改成了strncpy。嗯,这就是典型的缓冲区溢出修复。所以,别只看提交信息,要结合diff一起看。
好了,Git基础就这些。说白了,你只要会用git log、git diff、git show这三个命令,就能应付90%的补丁对比场景。剩下的,遇到再查也不迟。