git —— 配置与脚本的版本控制

运维工具手册 07-自动化与版本 5.8 KB 原文

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. 常见坑

  1. reset --hard 丢改动:执行前 git status 确认,必要时先 stash。
  2. git clean -fdx 删掉未跟踪文件:包括 .env、本地配置,先 -n 预览。
  3. 在公共分支 amend 后强推:影响所有人,团队禁止。
  4. 大文件进仓库:.git 膨胀,用 Git LFS 或干脆不入库。
  5. 提交了密钥:立刻轮换密钥,再从历史中清除(git filter-repo),仅删文件不够。
  6. pull 产生意外 merge commit:团队统一 pull.rebase 策略。
  7. 换行符问题:Windows 提交 CRLF,Linux 脚本执行报 bad interpreter,配 core.autocrlf 或 .gitattributes。
  8. 子模块忘记更新:git submodule update --init --recursive。
  9. git blame 只显示最后修改者:要追溯历史用 git log -L。
  10. 分支删了但提交还在:reflog 能找回,30 天后才真正回收。
  11. force push 前没 --force-with-lease:会覆盖别人刚推的提交,用 --force-with-lease 更安全。
  12. 仓库权限过宽:运维配置仓库含敏感信息,按最小权限授权。

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