git —— 配置与脚本的版本控制
git —— 配置与脚本的版本控制
分类:07 自动化与版本 适用:git 2.2x ~ 2.4x 一句话:运维的配置、脚本、Playbook、K8s 清单都该进 Git,出问题能 diff、能回滚、能追责。
1. 它解决什么问题
- 配置文件改了不知道改了什么、谁改的、为什么改。
- 改坏了要回到昨天的版本。
- 多人维护同一套脚本,避免互相覆盖。
- 变更要走评审(MR/PR)。
2. 最小配置
git config --global user.name "你的名字"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main
git config --global pull.rebase false # 或 true,团队统一
git config --global core.editor vim
git config --global alias.st status
git config --global alias.lg "log --oneline --graph --decorate --all"
git config --list --show-origin
3. 日常流程
git clone git@gitlab.example.com:ops/ansible.git
cd ansible
git status # 当前状态(最常用)
git diff # 未暂存的改动
git diff --staged # 已暂存的改动
git add file.yml
git add -A # 全部(含删除)
git add -p # 交互式挑选片段(推荐)
git commit -m "调整 nginx worker 数"
git commit -am "..." # 跳过 add(仅已跟踪文件)
git push origin main
提交信息规范
类型(范围): 简短描述
详细说明为什么这么改,影响范围。
类型:feat、fix、docs、style、refactor、perf、test、chore、revert。
好的提交信息让 git log 直接当变更记录用。
4. 查看历史
git log
git log --oneline --graph --all
git log -p file.yml # 某文件的每次改动
git log --author="alice"
git log --since="2 weeks ago"
git log -S "关键词" # 搜索引入/删除该字符串的提交
git log --stat
git show <commit>
git blame file.yml # 每行是谁改的
git diff HEAD~3 HEAD -- file.yml # 三次提交之间的差异
5. 分支
git branch # 本地分支
git branch -a # 含远程
git switch -c feature/nginx # 新建并切换(推荐)
git switch main
git branch -d feature/nginx # 删除已合并
git branch -D feature/nginx # 强制删除
git push -u origin feature/nginx # 推新分支并建立跟踪
6. 合并与变基
git merge feature # 合并(保留分支历史)
git rebase main # 变基(线性历史)
git rebase -i HEAD~3 # 交互式整理最近 3 个提交
git merge --abort
git rebase --abort
git rebase --continue
| 场景 | 用 |
|---|---|
| 公共分支合并 | merge(不要 rebase 公共历史) |
| 个人分支跟进主干 | rebase(历史干净) |
| 整理本地零碎提交 | rebase -i squash |
已经 push 的公共分支不要 rebase,会导致其他人历史错乱。
7. 撤销(最需要背清楚的部分)
| 目的 | 命令 | 影响 |
|---|---|---|
| 丢弃工作区改动 | git restore file |
不可恢复 |
| 取消暂存 | git restore --staged file |
保留改动 |
| 修改最后一次提交 | git commit --amend |
改写历史 |
| 回退提交但保留改动 | git reset --soft HEAD~1 |
改动回到暂存区 |
| 回退提交且取消暂存 | git reset HEAD~1(mixed) |
改动回到工作区 |
| 彻底丢弃提交与改动 | git reset --hard HEAD~1 |
⚠️ 不可恢复 |
| 生成反向提交(安全) | git revert <commit> |
不改历史,适合公共分支 |
公共分支用 revert,本地未推送用 reset。
8. 暂存与拣选
git stash # 暂存当前改动
git stash -u # 含未跟踪文件
git stash list
git stash pop # 恢复并删除
git stash apply stash@{1} # 恢复但不删
git stash drop
git cherry-pick <commit> # 把某个提交搬到当前分支
git cherry-pick A^..B # 一段连续提交
排查线上问题时,stash 能让你快速切分支而不丢改动。
9. 远程
git remote -v
git remote add origin <url>
git remote set-url origin <new-url>
git fetch --all --prune # 拉取所有分支并清理已删除的
git pull # fetch + merge
git pull --rebase # fetch + rebase
git push
git push origin --delete feature
git push --tags
git fetch 是安全的(只更新本地引用),git pull 会改工作区。
10. 找问题:bisect 与 reflog
reflog(救命神器)
git reflog # 所有 HEAD 移动记录
git reset --hard HEAD@{5} # 回到误操作前
reset --hard 或误删分支后,reflog 通常能救回来。
bisect(二分定位引入 bug 的提交)
git bisect start
git bisect bad # 当前版本有问题
git bisect good v1.2.0 # 这个版本正常
# 每次 git 会切到一个中间提交,测试后标记
git bisect good / git bisect bad
git bisect reset # 结束
自动化:
git bisect run ./test.sh # 脚本返回 0 表示 good
11. 运维场景实践
11.1 配置仓库结构
ops-config/
├── ansible/
├── k8s/
├── nginx/
├── scripts/
├── docs/
└── README.md
配合 CI:push 到 main 触发 ansible-playbook --check,合并后人工执行。
11.2 变更前打 tag
git tag -a v2026.11.05 -m "上线前基线"
git push origin v2026.11.05
出问题 git checkout v2026.11.05 即可回到基线。
11.3 紧急修复流程
git switch -c hotfix/nginx-502 main
# 改配置
git commit -am "fix: 修复 upstream 超时"
git push -u origin hotfix/nginx-502
# 走 MR 评审后合并
git switch main && git pull
11.4 忽略不该提交的文件
.gitignore:
*.log
.env
*.retry
.terraform/
terraform.tfstate
terraform.tfstate.backup
*.pem
*.key
vault_pass
已经提交过的文件要停止跟踪:
git rm --cached .env
git commit -m "chore: 停止跟踪 .env"
11.5 找回被删的文件
git log --diff-filter=D --summary # 找删除记录
git checkout <commit>^ -- path/to/file # 从删除前恢复
12. 常见坑
reset --hard丢改动:执行前git status确认,必要时先stash。git clean -fdx删掉未跟踪文件:包括.env、本地配置,先-n预览。- 在公共分支
amend后强推:影响所有人,团队禁止。 - 大文件进仓库:
.git膨胀,用 Git LFS 或干脆不入库。 - 提交了密钥:立刻轮换密钥,再从历史中清除(
git filter-repo),仅删文件不够。 pull产生意外 merge commit:团队统一pull.rebase策略。- 换行符问题:Windows 提交 CRLF,Linux 脚本执行报
bad interpreter,配core.autocrlf或.gitattributes。 - 子模块忘记更新:
git submodule update --init --recursive。 git blame只显示最后修改者:要追溯历史用git log -L。- 分支删了但提交还在:
reflog能找回,30 天后才真正回收。 force push前没--force-with-lease:会覆盖别人刚推的提交,用--force-with-lease更安全。- 仓库权限过宽:运维配置仓库含敏感信息,按最小权限授权。
13. 速查表
git status / diff / diff --staged
git add -A / add -p
git commit -m "msg" / commit --amend
git log --oneline --graph --all
git log -p <file> / blame <file>
git switch -c <branch> / switch <branch>
git merge <branch> / rebase <branch>
git restore <file> / restore --staged <file>
git reset --soft|--mixed|--hard HEAD~1
git revert <commit>
git stash / stash pop / stash list
git cherry-pick <commit>
git fetch --all --prune / pull --rebase / push
git reflog
git bisect start/good/bad/reset
git tag -a v1 -m "msg" && git push --tags
git rm --cached <file>
git clean -nd / clean -fd