你已经在用 git add、git commit、git push、git pull。这是开发者的 Git。DevOps 工程师用的是另一套 Git——用于自动化、排查、救火和代码考古。
这节课讲 6 个你面试会被问到、工作中会救命的高级操作。
默认的 git log 输出太啰嗦。DevOps 的标准配方:
# 一行一个 commit,带图形化分支
git log --oneline --graph --all
# 只看最近 10 条
git log --oneline -10
# 找特定人的 commit
git log --oneline --author="bram35mm"
# 找特定时间段的
git log --oneline --since="2026-07-01" --until="2026-07-15"
# 找改过某个字符串的 commit(比如找谁动了 API_URL)
git log -S "API_URL" --oneline
# 看某个文件的变更历史
git log --oneline -- package.json
~/.gitconfig 里加个 alias:git lg = log --oneline --graph --all,以后打 git lg 就行。
场景:你在 feature 分支改了一半,突然线上出 bug 需要切回 main 修。但你不想 commit 半成品。
git stash # 把当前改动「藏起来」,工作区恢复干净
git stash list # 查看所有 stash
git stash pop # 恢复最近一次 stash 并删除它
git stash apply stash@{1} # 恢复指定 stash,不删除
git stash drop stash@{1} # 删除指定 stash
git stash save "WIP: login" # 带备注 stash
DevOps 场景:你在改 CI 配置,突然需要切回去修 pipeline。stash → 切分支 → 修完 → stash pop。
这是面试最爱问的。rebase 和 merge 都能合并分支,但结果不同:
# merge:产生一个额外的 merge commit,历史是「网状的」
# rebase:把你的 commit 「搬到」目标分支最新 commit 之后,历史是「线性的」
交互式 rebase(最强大):
git rebase -i HEAD~4 # 对最近 4 个 commit 进行交互式操作
会打开编辑器,列出最近 4 个 commit,每行前面有一个命令:
| 命令 | 效果 | 什么时候用 |
|---|---|---|
pick | 保留这个 commit | 默认 |
squash | 合并到上一个 commit,保留 commit message | 把「fix typo」合并进主 commit |
fixup | 合并到上一个 commit,丢弃 commit message | 同上但不需要保留 message |
reword | 只改 commit message | message 写错了 |
drop | 删除这个 commit | 不小心提交了敏感信息 |
把某个 commit 的改动「复制」到当前分支。不合并整个分支,只要一个 commit。
git cherry-pick abc1234 # 把 commit abc1234 的改动应用到当前分支
DevOps 场景:你在 release 分支上,只需要 hotfix 分支里的一个 commit,不需要整个 hotfix 分支。
场景:3 天前的版本没问题,现在的版本有问题。中间有 50 个 commit。谁引入的?
git bisect start # 开始二分搜索
git bisect bad HEAD # 标记当前版本是坏的
git bisect good abc1234 # 标记 3 天前的版本是好的
# Git 会自动 checkout 到中间一个 commit
# 你测试一下 → 如果是好的就 git bisect good
# → 如果是坏的就 git bisect bad
# 重复几次后 Git 找到第一个坏的 commit
git bisect reset # 结束搜索,回到原地
50 个 commit 只需要大约 log₂(50) ≈ 6 次测试就能定位。这是 DevOps 排查线上问题的神器。
你做了 git reset --hard,删掉了 3 天的代码。panic?不用。
git reflog # 显示 HEAD 的所有移动历史(包括「丢失」的 commit)
git reset --hard HEAD@{3} # 回到 3 步之前的状态
reflog 是本地 Git 的「操作日志」,记录了每一次 HEAD 变动。只要 commit 过,就永远能找到(默认保留 90 天)。
Git Hook 是在特定 Git 事件发生时自动执行的脚本。它们存在 .git/hooks/ 下(每个 repo 一份)。
| Hook | 触发时机 | DevOps 用途 |
|---|---|---|
pre-commit | commit 之前 | 跑 lint、格式化、检查密码泄漏 |
commit-msg | 编辑完 commit message 后 | 检查 message 格式(如 Conventional Commits) |
pre-push | push 之前 | 跑测试,不通过则阻止 push |
post-receive | 服务端收到 push 后 | 触发 CI/CD 流水线! |
# 快速试一下 pre-commit hook
cd /tmp && mkdir hook-demo && cd hook-demo && git init
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash
echo "🔍 Running pre-commit checks..."
# 检查是否有 console.log 残留
if git diff --cached | grep -q "console\.log"; then
echo "❌ Found console.log! Remove it before committing."
exit 1
fi
echo "✅ All checks passed!"
EOF
chmod +x .git/hooks/pre-commit
# 测试
echo "console.log('test')" > app.js
git add app.js
git commit -m "test" # 会被 hook 拦截!
在你的终端里建一个临时仓库来练习(不会影响任何项目):
cd /tmp && rm -rf git-practice && mkdir git-practice && cd git-practice
git init
# 创建 5 个 commit 来模拟真实开发
echo "v1" > file.txt && git add . && git commit -m "init"
echo "v2" >> file.txt && git add . && git commit -m "feat: add v2"
echo "v3" >> file.txt && git add . && git commit -m "fix: typo"
echo "v4" >> file.txt && git add . && git commit -m "wip"
echo "v5" >> file.txt && git add . && git commit -m "feat: add v5"
# 1. 用 git log --oneline 看历史
# 2. 用 git rebase -i HEAD~4 把后 4 个 commit 压缩成 1 个
# → 保留第一个 "init",其余改成 squash 或 fixup
# 3. 用 git log --oneline 确认只有 2 个 commit 了
# 4. 用 git reflog 看被你「压缩掉」的原始 commit 还在
~/.gitconfig 加这个 alias,终身受用:
[alias]
lg = log --oneline --graph --all
unstage = reset HEAD --
undo = reset --soft HEAD~1
last = log -1 HEAD
下一课我们进入 Shell 脚本编程——把命令行操作变成可重复执行的自动化脚本。这是所有 CI/CD 流水线和自动化运维的基础。
git rebase --abort 可以安全退出。