30 - Git 与 GitHub 项目管理
前提条件
- 已完成自动化部署与镜像管理章节(Ansible / Packer 流程已建立)
- 本章操作以 ops 普通用户执行,不使用 root 进行 Git 日常操作
- 系统运行在 Debian 12 Bookworm
- 需要 GitHub 账号(或自建 Gitea 实例)
- SSH 密钥已生成(第 8 章)
全局参数
主机名 linuxdc,IP 192.168.1.100/24,SSH 端口 2222,运维用户 ops
Git 操作使用 ops 用户
Git 相关操作应以普通用户 ops 身份执行,不使用 root 账户进行日常代码管理。root 账户的提交信息会暴露服务器 root 账户的存在,且不符合最小权限原则。
详细步骤
以下所有命令以 ops 用户执行:
su - ops
1. 安装 Git 并全局配置
# 安装(root 执行)
apt update && apt install -y git
# 以下配置由 ops 用户执行
git config --global user.name "Ops User"
git config --global user.email "ops@linuxdc.local"
git config --global core.editor "vim"
git config --global init.defaultBranch main
git config --global pull.rebase false # merge 策略(推荐明确设置)
# 验证配置
git config --list
2. 创建本地仓库与基础操作
mkdir ~/my-project && cd ~/my-project
git init
echo "# My Debian Ops Project" > README.md
git add README.md
git commit -m "init: add README"
# 查看状态与历史
git status
git log --oneline --graph --all
3. 配置 GitHub SSH 认证
将已有公钥添加到 GitHub(Settings → SSH and GPG keys → New SSH key):
cat ~/.ssh/id_ed25519.pub
# 复制输出内容,粘贴到 GitHub SSH Keys 页面
测试 SSH 连接:
ssh -T git@github.com
# 成功输出:Hi <username>! You've successfully authenticated, but GitHub does not provide shell access.
4. 关联远程仓库并推送
在 GitHub 创建新仓库(不要勾选"Initialize this repository"):
git remote add origin git@github.com:<your-username>/my-project.git
git branch -M main
git push -u origin main
5. 日常工作流(功能分支模型)
分支命名约定:
| 分支类型 | 命名格式 | 说明 |
|---|---|---|
| 主分支 | main |
生产代码,只合并经过 Review 的代码 |
| 功能分支 | feature/<描述> |
新功能开发 |
| 修复分支 | fix/<描述> |
bug 修复 |
| 紧急修复 | hotfix/<描述> |
生产紧急修复 |
| 发布分支 | release/<版本> |
发布前的最终测试 |
功能开发示例:
# 从 main 创建功能分支
git checkout -b feature/add-logrotate-config
# 开发并提交
vim logrotate/nginx.conf
git add logrotate/nginx.conf
git commit -m "feat: add nginx logrotate config (rotate 14, compress)"
# 推送到远程
git push origin feature/add-logrotate-config
在 GitHub 创建 Pull Request,经过 Review 后合并到 main。
6. 常用运维 Git 技巧
.gitignore 配置(运维仓库推荐):
vim .gitignore
# 日志文件
*.log
logs/
# 备份目录
/backup/
# 敏感文件(绝不提交)
*.key
*.pem
*credentials*
vault-password*
.env
# OS 临时文件
.DS_Store
Thumbs.db
撤销操作:
| 场景 | 命令 | 说明 |
|---|---|---|
| 撤销工作区修改 | git restore <file> |
丢弃未暂存的修改 |
| 取消暂存 | git restore --staged <file> |
从暂存区移出,保留工作区 |
| 安全撤销已推送提交 | git revert HEAD |
新建反向提交,保留历史 |
| 危险:彻底丢弃本地提交 | git reset --hard HEAD~1 |
不可推送到共享分支 |
标签管理(版本标记):
# 创建带注释的标签
git tag -a v1.0.0 -m "Release v1.0.0: initial stable deployment"
# 推送标签到远程
git push origin v1.0.0
# 推送所有标签
git push origin --tags
# 列出所有标签
git tag -l
查看文件变更历史:
git log --follow -p -- playbooks/install-nginx.yml
git blame playbooks/install-nginx.yml
7. 仓库目录结构建议(运维项目)
debian-ops/
├── playbooks/ # Ansible playbooks
├── roles/ # Ansible roles
├── inventory/ # Ansible inventory
├── group_vars/ # 变量文件(secrets 用 vault 加密)
├── packer/ # Packer 模板
├── scripts/ # Shell 脚本
├── docs/ # 运维文档(Markdown)
├── .gitignore
└── README.md
8. GitHub 项目管理建议
- 分支保护:Settings → Branches → Add protection rule → 对
main分支启用Require pull request reviews - Issues:用于跟踪任务、bug、待办项,关联 Pull Request(
Closes #123) - Actions:CI/CD 自动化(语法检查、ansible-lint、packer validate),在 Push 时自动触发
实践任务
- 安装 Git,完成全局配置,创建本地仓库
my-debian-ops,提交 README.md 并推送到 GitHub - 配置 SSH 密钥认证,验证
ssh -T git@github.com成功,测试无密码推送 - 创建
feature/add-logrotate分支,添加 logrotate 配置文件,提交并推送,在 GitHub 创建 Pull Request - 在本地修改 README.md,用
git revert撤销最新提交,观察提交历史的变化
自测问题
1. git config --global init.defaultBranch main 的作用是什么?
Git 2.28 前,git init 创建的默认分支名为 master。该配置将新仓库的默认初始分支名改为 main,与 GitHub 等平台的当前默认值保持一致,避免本地 master 与远程 main 不匹配导致推送时需要额外的 git branch -M main 操作。这是全局配置,对当前用户之后创建的所有新仓库生效。
2. SSH 密钥认证相比 HTTPS 的主要优势是什么?
HTTPS 认证需要每次输入用户名和 Personal Access Token(GitHub 已停止支持账号密码),即使配置了 credential helper 本地缓存,令牌仍以明文形式存储在文件中。SSH 密钥认证使用非对称加密,私钥从不离开本地,服务端只存储公钥;可以为私钥设置 passphrase 并配合 ssh-agent 实现安全的免密操作;一个密钥对可用于多个 Git 服务(GitHub、GitLab、Gitea);密钥可按设备管理,单独吊销而不影响其他设备。
3. git revert 和 git reset 的区别是什么?什么时候用哪个?
git revert <commit> 创建一个新提交来撤销目标提交的内容,保留完整提交历史,适合已推送到共享分支(main)的提交——其他人拉取后不会出现历史分歧。git reset --hard <commit> 将 HEAD 和工作区直接回退到目标提交,丢弃其后的所有提交,如果已推送则需要 git push --force,会破坏其他人的本地仓库。原则:已推送的共享提交用 revert;仅本地未推送的提交可用 reset。
4. 为什么生产环境中建议保护 main 分支并要求 Pull Request 审核?
直接向 main 推送跳过了代码审查和 CI 检查,一个误操作(错误的 Ansible playbook、删除生产配置)可能直接影响所有从 main 部署的环境。分支保护规则强制所有变更通过 Pull Request 流程:至少一名审核者 Review 代码;CI 检查(ansible-lint、packer validate、shellcheck)通过后才能合并;所有变更有完整的讨论记录和审批轨迹,满足合规和审计要求。这是将"四眼原则"落实到代码管理层面的标准实践。
总结
Git 是运维工作中版本控制、协作、审计的核心工具。以 ops 用户管理 Git 仓库,将所有脚本、Ansible playbook、Packer 模板、运维文档纳入版本控制,是实现"基础设施即代码"可追溯性的基础。结合 Pull Request + CI 自动检查 + 分支保护,形成安全可靠的配置变更管控流程。