likes
comments
collection
share

只会 git log? 其实 git 还有两个好用的 log 命令

作者站长头像
站长
· 阅读数 41

git log 是经常用的 git 命令,用于展示 commit 历史的,除了它之外,git 还有两个 log 命令:git shortlog、git reflog。

后两个命令也很有用,但是很多人都不知道。

这篇文章我们就过一下这 3 个 git 的 log 命令吧。

用 git branch 看一下本地的分支,有 main、0.5-stable 这两个,当前在 main 分支:

只会 git log? 其实 git 还有两个好用的 log 命令

也就是这样的:

只会 git log? 其实 git 还有两个好用的 log 命令

每个 commit 都有自己的 hash,并且记录着父 commit 的 hash。

分支名记录着它指向的 commit。

HEAD 指针指向当前的分支,这里就是 main 分支。

在 .git 的 HEAD 文件里也可以看到 HEAD 指针的指向:

只会 git log? 其实 git 还有两个好用的 log 命令

除了分支之外,tag 也是指向 commit 的一个指针。

比如 git tag -l 可以看到我本地有这些 tag:

只会 git log? 其实 git 还有两个好用的 log 命令

其实这些也就是指向某个 commit 的指针:

只会 git log? 其实 git 还有两个好用的 log 命令

HEAD、branch、tag 这些都是指针,在 git 里叫做 ref。

git log 默认是打印的 HEAD 指针指向的 commit 的历史。

只会 git log? 其实 git 还有两个好用的 log 命令

你也可以加任何一个 ref 来打印那个指针指向的 commit 的历史:

只会 git log? 其实 git 还有两个好用的 log 命令

比如我加了 branch 的名字,那 log 的就是 0.5-stable 这个 branch 的历史。

也可以加 tag 的名字,或者某个具体 commit 的 hash 来打印它的历史:

只会 git log? 其实 git 还有两个好用的 log 命令

只会 git log? 其实 git 还有两个好用的 log 命令

上面就是分别打印了某个 tag 的、某个 commit 的历史。

git log 支持一些 option 来对输出的 log 做限定。

比如你可以根据作者过滤:

git log --author="xxx"

只会 git log? 其实 git 还有两个好用的 log 命令

支持模糊搜索。

你也可以根据 commit 的内容来过滤:

git log --grep="xxx"

只会 git log? 其实 git 还有两个好用的 log 命令

--grep 和 --author 不一样,它是支持正则的,你可以根据正则来过滤 commit message

比如这样:

git log --grep="Add.*runtime"

就是过滤 commit message 里有 Add 开头、中间任意个字符然后加 runtime 的 commit:

只会 git log? 其实 git 还有两个好用的 log 命令

因为支持了正则,所以这个 --grep 是挺强大的。

此外,还可以根据时间来过滤,比如:

git log --after="2022-01-01" --before="2022-01-31"

就可以过滤 2022 年 1 月份的 commit:

只会 git log? 其实 git 还有两个好用的 log 命令

这里的 --before、--after 可以换成 --until、--since,一样的含义。

我个人更习惯 before、after。

除了过滤之外,还可以控制打印的格式,比如:

git log --format="%h %as %s %an"

这里的 %h 是缩写的 commit hash,%as 是日期的一种格式,%s 是 commit 的主题,%an 是 commit 的作者。

打印出来的就是这样的:

只会 git log? 其实 git 还有两个好用的 log 命令

我们可以给它加上一些换行,通过 %n:

git log --format="hash: %h %n日期: %as %n主题: %s %n作者: %an %n"

就是这样的:

只会 git log? 其实 git 还有两个好用的 log 命令

还可以用 %Cred %Creset 包裹来把中间字符串变红,或者 %Cblue %Creset 包裹,把中间字符串变蓝:

git log --format="hash:%Cred %h %Creset%n日期: %as %n主题:%Cblue %s %Creset%n作者: %an %n"

效果是这样的:

只会 git log? 其实 git 还有两个好用的 log 命令

具体有哪些变量、哪些颜色,可以去看文档。

总之,log 输出的格式和颜色是可以控制的。

学了这些 option 之后,我们来做个综合的需求吧。

周会的时候,我想看看某个同学上一周的 commit,应该怎么做呢?

比如这样:

git log --author="guang" --after="2022-01-01" --before="2022-01-07"

这样其实有问题,因为他可能不是在 main 分支开发的,可能是在某个 feture 分支开发的,然后合并到了 main。

如何查看他在所有分支的过去一周的 commit 呢?

加个 --all 就好了:

git log --author="guang" --after="2022-01-01" --before="2022-01-07" --all

但这里面免不了多了一个 merge 的 commit,而这些 commit 其实没啥具体内容。

所以可以加个 --no-merges。

--merges 是只保留 merge 的 commit:

只会 git log? 其实 git 还有两个好用的 log 命令

--no-merges 正好反过来,只保留非 merge 的 commit:

只会 git log? 其实 git 还有两个好用的 log 命令

所以可以这样写:

git log --author="guang" --after="2022-01-01" --before="2022-01-07" --all --no-mreges

这就是 guang 在 2022-01-01 到 2022-01-07 这一周的在所有分支的 commit(排除了 merge 的 commit)。

但我如果想看所有同学的一周的 commit 这样也太麻烦了吧。

有没有什么按照人来分组统计的命令呢?

还真有,就是 git shortlog。

只会 git log? 其实 git 还有两个好用的 log 命令

它展示的就是每个作者提交了多少个 commit,都是啥。

是一个 git log 的统计结果。

默认是按照作者名的字母顺序来排列的,也可以按照 commit 数来倒序排列:

git shortlog -n

只会 git log? 其实 git 还有两个好用的 log 命令

这样我如果想看某段时间内,谁提交了哪些 commit,就可以这样写:

git shortlog -n --after="2022-01-01" --before="2022-01-31" --all --no-merges

就是输出在 2022-01-01 到 2022-01-31 这一个月内,所有人的 commit 的统计结果,包含所有分支的除去 merge commit 的 commit,按照 commit 数倒序排列。

只会 git log? 其实 git 还有两个好用的 log 命令

这里的 log 也可以修改格式:

git shortlog -n --after="2022-01-01" --before="2022-01-31" --all --no-merges --format="%h %as %s"

比如我只要 hash、日期、主题,就可以 --format="%h %as %s"

只会 git log? 其实 git 还有两个好用的 log 命令

总之, git log 是查看 commit 历史的,而 git shortlog 是查看分组的统计结果的。

那 git reflog 是干啥的呢?

它是记录 ref 的修改历史的。

什么 ref 前面讲过了,branch、HEAD、tag 这些都是。

比如你新增了一个 commit、新建了一个 branch、新增了一个 tag、刚 pull 下来一个分支,这些都是对 ref 的修改。

git 会把它记录在 reflog 里。

只会 git log? 其实 git 还有两个好用的 log 命令

比如这里的新的 commit、reset 到历史 commit、checkout 新分支等都是 ref 的变动。

只会 git log? 其实 git 还有两个好用的 log 命令

但默认只显示 HEAD 指针的变化历史。

想看到所有分支的 ref 变化历史,可以加个 --all。

只会 git log? 其实 git 还有两个好用的 log 命令

这样就多了别的分支的 ref 变化历史:

只会 git log? 其实 git 还有两个好用的 log 命令

有的同学可能会问,记录 ref 变化历史干啥用?

比如说当你 git reset 到了一个之前的分支,又想恢复回去,这时候不知道之前的那个 commit 的 hash 是啥了。

这时候就可以看 reflog 里的 ref 变化历史,找到之前的 commit 的 hash。

然后 git reset 到那个 hash。

这就是 git reflog 的作用。

那这些 reflog 保存在哪里呢?

在 .git 的 logs/refs 目录下: 只会 git log? 其实 git 还有两个好用的 log 命令

比如 HEAD 的 reflog,对比下是不是一毛一样(顺序是反的):

只会 git log? 其实 git 还有两个好用的 log 命令

这里就是 reflog 保存的地方。

总结

git 有 3 个 log 命令:git log、git shortlog、git reflog。

git log 是查看 commit 历史的,可以指定 branch、tag、某个 commit 等来查看对应的 commit 历史。

可以通过 --author、--before、--after、--grep、--merges、--no-merges、--all 来过滤某个作者、某段时间内、某个 commit 内容、非 merge 的 commit、全部分支的 commit 等 commit。

还可以通过 --format 来指定输出的颜色和格式。

git shortlog 是 git log 的统计结果,可以按照作者来分组统计。比如查看上一周每个人提交了多少个 commit。

git reflog 记录的是 ref 的变化历史,比如分支切换、reset、新的 commit 等都会记录下来。

可以通过 git reflog 命令来查看,也可以直接在 .git/logs/refs 下查看。

git 的 3 个 log 命令各有各自的用途,都是很常用的 git 命令。