简历项目经验描述
版本1 - 适合初中级
参与团队 Git 工作流规范制定,提升代码管理效率
- 采用 GitFlow 分支管理策略,规范开发、测试、发布流程
- 制定 Commit 提交规范,使用 commitizen 工具,代码提交质量提升 60%
- 配置 Husky 钩子,实现提交前代码检查,避免低级错误 80%+
版本2 - 适合高级
设计并推行团队 Git 工作流体系,显著提升协作效率
- 建立 GitFlow + Trunk-Based 混合分支策略,适配敏捷开发节奏,发布周期缩短 50%
- 搭建 Commit 规范 + Changelog 自动生成系统,版本文档生成效率提升 10 倍
- 实施 MR/PR 强制评审机制,引入 Code Review 标准,线上 Bug 率降低 40%
- 开发冲突自动检测工具,提前识别合并冲突,解决冲突时间减少 70%
版本3 - 适合架构方向
主导 Git 工作流架构设计,建立标准化的代码协作体系
- 设计多环境分支策略,支持开发/测试/预发/生产四环境,部署准确率 99%+
- 建立 Git Hooks + CI/CD 联动机制,自动化检查覆盖率达 90%,人工介入减少 80%
- 制定代码评审标准和流程,培训 Code Review 最佳实践,团队代码质量评分提升 35%
- 优化大仓库 Git 性能,通过浅克隆、稀疏检出等技术,克隆时间从 30 分钟降至 3 分钟
面试标准回答话术
Q1: GitFlow 分支管理是什么?你们是怎么用的?
标准回答
"GitFlow 是一种 Git 分支管理模型,通过不同的分支承载不同的职责,让团队协作更规范。
基本分支
- master/main 分支 - 生产环境代码,只能从 release 或 hotfix 合并
- develop 分支 - 开发分支,集成所有开发完成的功能
- feature 分支 - 功能开发分支,从 develop 切出,完成后合并回 develop
- release 分支 - 发布分支,从 develop 切出,测试通过后合并到 master 和 develop
- hotfix 分支 - 紧急修复分支,从 master 切出,修复后合并到 master 和 develop
我们团队的实际用法
日常开发流程
# 1. 从 develop 切出功能分支
git checkout develop
git pull origin develop
git checkout -b feature/user-login
# 2. 开发功能,提交代码
git add .
git commit -m "feat: 实现用户登录功能"
# 3. 推送到远程
git push origin feature/user-login
# 4. 在 GitLab/GitHub 创建 MR/PR
# 5. Code Review 通过后,合并到 develop
# 6. 删除功能分支
git branch -d feature/user-login
发布流程
# 1. 从 develop 切出 release 分支
git checkout develop
git pull origin develop
git checkout -b release/v1.2.0
# 2. 在 release 分支上做发布准备(修改版本号、更新 changelog 等)
npm version 1.2.0
git add .
git commit -m "chore: 发布 v1.2.0"
# 3. 测试通过后,合并到 master
git checkout master
git pull origin master
git merge --no-ff release/v1.2.0
git tag -a v1.2.0 -m "Release v1.2.0"
git push origin master --tags
# 4. 同时合并回 develop
git checkout develop
git merge --no-ff release/v1.2.0
git push origin develop
# 5. 删除 release 分支
git branch -d release/v1.2.0
紧急修复流程
# 1. 从 master 切出 hotfix 分支
git checkout master
git pull origin master
git checkout -b hotfix/fix-login-bug
# 2. 修复 bug
git add .
git commit -m "fix: 修复登录时的空指针问题"
# 3. 合并到 master
git checkout master
git merge --no-ff hotfix/fix-login-bug
git tag -a v1.2.1 -m "Hotfix v1.2.1"
git push origin master --tags
# 4. 合并到 develop
git checkout develop
git merge --no-ff hotfix/fix-login-bug
git push origin develop
# 5. 删除 hotfix 分支
git branch -d hotfix/fix-login-bug
分支命名规范
feature/功能名称 例如: feature/user-profile
bugfix/问题描述 例如: bugfix/fix-login-error
hotfix/问题描述 例如: hotfix/fix-payment-bug
release/版本号 例如: release/v1.2.0
我们还做了一些优化
- 小团队简化 - 如果团队小(3-5人),可以去掉 release 分支,直接从 develop 合并到 master
- 结合 CI/CD - 每个分支推送后自动触发 CI 流程,跑测试和构建
- 保护分支 - master 和 develop 设置为保护分支,只能通过 MR 合并,不能直接 push
这套流程在我们 10 人团队里用了 2 年,很稳定,代码管理很清晰。"
Q2: Commit 规范是什么?怎么保证团队遵守?
标准回答
"Commit 规范就是统一提交信息的格式,让提交历史清晰易读。我们用的是 Angular 规范。
Commit 格式
<type>(<scope>): <subject>
<body>
<footer>
type(必须)
- feat: 新功能
- fix: 修复 bug
- docs: 文档更新
- style: 代码格式(不影响代码运行)
- refactor: 重构(既不是新功能,也不是修 bug)
- perf: 性能优化
- test: 测试相关
- chore: 构建过程或辅助工具的变动
scope(可选): 影响的范围,如: user, product, order
subject(必须): 简短描述
例子
feat(user): 添加用户注册功能
实现了用户注册的完整流程:
- 表单验证
- 邮箱验证
- 密码加密
Closes #123
如何保证团队遵守?
1. 使用 commitizen 工具
安装:
npm install -g commitizen
npm install cz-conventional-changelog --save-dev
配置 package.json:
{
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
},
"scripts": {
"commit": "git-cz"
}
}
使用:
# 不用 git commit,改用
npm run commit
# 会出现交互式提示
? Select the type of change: (Use arrow keys)
> feat: A new feature
fix: A bug fix
docs: Documentation only changes
style: Changes that do not affect the meaning of the code
refactor: A code change that neither fixes a bug nor adds a feature
perf: A code change that improves performance
test: Adding missing tests
? What is the scope of this change (e.g. component or file name): user
? Write a short description: 添加用户注册功能
? Provide a longer description: (press enter to skip)
? Are there any breaking changes? No
? Does this change affect any open issues? Yes
? Add issue references: #123
2. 使用 commitlint 检查
安装:
npm install --save-dev @commitlint/cli @commitlint/config-conventional
配置 commitlint.config.js:
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
[
'feat',
'fix',
'docs',
'style',
'refactor',
'perf',
'test',
'chore',
'revert'
]
],
'subject-case': [0], // 不限制 subject 大小写
'subject-max-length': [2, 'always', 100] // subject 最长 100 字符
}
}
3. 使用 Husky 钩子
安装:
npm install --save-dev husky
npx husky install
添加 commit-msg 钩子:
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit $1'
现在提交不规范的 commit 会被拦截:
git commit -m "随便写的"
# 报错
⧗ input: 随便写的
✖ subject may not be empty [subject-empty]
✖ type may not be empty [type-empty]
✖ found 2 problems, 0 warnings
4. 自动生成 Changelog
安装:
npm install --save-dev standard-version
配置 package.json:
{
"scripts": {
"release": "standard-version"
}
}
生成 changelog:
npm run release
# 会自动:
# 1. 根据 commit 生成 CHANGELOG.md
# 2. 更新版本号
# 3. 创建 git tag
CHANGELOG.md 示例:
# Changelog
## [1.2.0] - 2024-01-15
### Features
- **user**: 添加用户注册功能 (#123)
- **product**: 支持产品批量导入 (#124)
### Bug Fixes
- **login**: 修复登录时的空指针问题 (#125)
### Performance Improvements
- **list**: 优化列表加载性能,提升 50% (#126)
完整的提交流程
# 1. 修改代码
vim src/user.js
# 2. 添加到暂存区
git add src/user.js
# 3. 使用规范的 commit
npm run commit
# 4. 推送
git push
# 5. 发版时生成 changelog
npm run release
我们团队实施这套规范后,提交历史清晰了很多,发版文档也不用手写了,自动生成就行。"
Q3: MR/PR 评审机制是怎么做的?
标准回答
"MR (Merge Request) 或 PR (Pull Request) 评审就是代码合并前,让其他同事 review 一下,保证代码质量。
我们的评审流程
1. 提交 MR/PR
开发完成后,在 GitLab/GitHub 创建 MR:
# 推送功能分支
git push origin feature/user-login
# 在 GitLab 页面创建 MR
# 填写以下信息:
# - 标题: feat(user): 添加用户登录功能
# - 描述: 实现了用户登录的完整流程
# - 指派给: @reviewer
# - 标签: feature, frontend
MR 描述模板:
## 改动内容
实现了用户登录功能,包括:
- 登录表单
- 密码加密
- Session 管理
## 相关 Issue
Closes #123
## 测试说明
1. 访问 /login 页面
2. 输入用户名密码
3. 点击登录,验证是否跳转到首页
## 截图

## Checklist
- [x] 代码通过 ESLint 检查
- [x] 添加了单元测试
- [x] 更新了文档
2. 自动检查
MR 创建后,自动触发 CI 流程:
# .gitlab-ci.yml
stages:
- lint
- test
- build
lint:
stage: lint
script:
- npm run lint
only:
- merge_requests
test:
stage: test
script:
- npm run test
coverage: '/Statements\s+:\s+(\d+\.\d+)%/'
only:
- merge_requests
build:
stage: build
script:
- npm run build
only:
- merge_requests
检查内容:
- 代码规范(ESLint)
- 单元测试(Jest)
- 测试覆盖率(至少 80%)
- 构建是否成功
3. Code Review
Reviewer 检查代码,提出意见:
检查清单:
## 功能
- [ ] 功能是否完整?
- [ ] 是否有边界情况考虑不周?
- [ ] 是否有性能问题?
## 代码质量
- [ ] 代码是否易读易懂?
- [ ] 命名是否规范?
- [ ] 是否有重复代码?
- [ ] 是否有 TODO 或 FIXME?
## 测试
- [ ] 是否有单元测试?
- [ ] 测试覆盖率是否足够?
- [ ] 测试用例是否完整?
## 文档
- [ ] 是否更新了相关文档?
- [ ] 复杂逻辑是否有注释?
评论示例:
Line 25: 这里建议用 async/await 代替 Promise.then,代码更清晰
Line 45: 这个魔法数字 10000 建议提取为常量
Line 60: 这个 if 条件太复杂,建议抽取为单独的函数
整体看下来代码质量不错,就这几个小问题,改完就可以合并了。
4. 修改和再次评审
开发者根据意见修改代码:
# 修改代码
vim src/user.js
# 提交修改
git add .
git commit -m "fix: 根据 review 意见优化代码"
git push origin feature/user-login
# MR 自动更新,CI 重新跑
5. 合并
评审通过后,合并到目标分支:
# 在 GitLab 页面点击 "Merge" 按钮
# 或使用命令行
git checkout develop
git merge --no-ff feature/user-login
git push origin develop
# 删除功能分支
git push origin --delete feature/user-login
评审标准
我们团队的标准:
- 至少 1 人 approve 才能合并
- 关键模块(支付、权限)至少 2 人 approve
- CI 必须全部通过
- 测试覆盖率不能降低
评审工具
除了 GitLab/GitHub 自带的,我们还用:
- SonarQube: 自动代码质量分析
- Danger: 自动评论常见问题
- CodeClimate: 代码可维护性评分
评审效率优化
- 小而频繁的 MR - 每个 MR 改动不超过 500 行,容易 review
- 及时响应 - 规定 MR 创建后 2 小时内要有人 review
- 结对编程 - 复杂功能提前和 reviewer 沟通,减少返工
- 知识分享 - 每周分享 review 中发现的典型问题
通过这套机制,我们团队的代码质量提升了很多,线上 bug 明显减少。"
Q4: 代码冲突怎么解决?有什么预防措施?
标准回答
"代码冲突就是两个人改了同一个地方,Git 不知道该保留谁的,需要手动解决。
常见冲突场景
- 同时修改同一文件的同一位置
- 一个人修改文件,另一个人删除文件
- 文件名冲突(一个人重命名,另一个人也在改这个文件)
解决方法
场景1: 合并分支时冲突
git checkout develop
git merge feature/user-login
# 提示冲突
Auto-merging src/user.js
CONFLICT (content): Merge conflict in src/user.js
Automatic merge failed; fix conflicts and then commit the result.
# 查看冲突文件
git status
# 打开冲突文件
vim src/user.js
冲突标记:
<<<<<<< HEAD
function login(username, password) {
// develop 分支的代码
return api.login({ username, password })
}
=======
function login(user, pass) {
// feature 分支的代码
return api.userLogin({ user, pass })
}
>>>>>>> feature/user-login
手动解决:
// 保留正确的代码,删除冲突标记
function login(username, password) {
return api.login({ username, password })
}
提交解决:
git add src/user.js
git commit -m "merge: 解决 user.js 冲突"
git push origin develop
场景2: Rebase 时冲突
git checkout feature/user-login
git rebase develop
# 提示冲突
CONFLICT (content): Merge conflict in src/user.js
# 解决冲突后
git add src/user.js
git rebase --continue
# 如果有多个冲突,会继续提示,重复解决
# 如果想放弃 rebase
git rebase --abort
场景3: Pull 时冲突
git pull origin develop
# 提示冲突
CONFLICT (content): Merge conflict in src/user.js
# 解决后提交
git add src/user.js
git commit -m "merge: 解决冲突"
git push origin develop
冲突解决工具
- VS Code - 内置冲突解决工具,可视化很友好
显示:
Accept Current Change | Accept Incoming Change | Accept Both Changes
- GitKraken - 图形化工具,三方对比
- 命令行工具:
# 使用 vimdiff
git mergetool --tool=vimdiff
# 使用 meld
git mergetool --tool=meld
预防冲突的措施
1. 频繁同步
# 每天开始工作前,先同步 develop
git checkout develop
git pull origin develop
# 再合并到自己的分支
git checkout feature/user-login
git merge develop
2. 小步提交
不要攒了一周的代码一次提交,每天多次提交,减少冲突概率。
3. 功能拆分
大功能拆成小功能,多个分支并行,互不影响。
4. 沟通协作
如果知道要改同一个文件,提前沟通,约定谁先改。
5. 代码格式统一
使用 Prettier 统一代码格式,避免格式差异导致的冲突:
npm install --save-dev prettier
# .prettierrc
{
"semi": false,
"singleQuote": true,
"trailingComma": "es5"
}
# 格式化代码
npx prettier --write "src/**/*.{js,vue}"
6. 文件锁定(特殊场景)
对于一些不能冲突的文件(如配置文件),可以用 Git LFS 锁定:
git lfs track "config.json"
git lfs lock config.json
# 修改后解锁
git lfs unlock config.json
自动检测冲突
我们写了个脚本,在 MR 创建时自动检测潜在冲突:
// scripts/check-conflicts.js
const { execSync } = require('child_process')
function checkConflicts(sourceBranch, targetBranch) {
try {
// 尝试模拟合并
execSync(`git fetch origin ${targetBranch}`)
execSync(`git merge-tree $(git merge-base ${sourceBranch} origin/${targetBranch}) ${sourceBranch} origin/${targetBranch}`)
console.log('✓ 没有冲突')
return true
} catch (error) {
console.error('✗ 检测到潜在冲突:')
console.error(error.stdout.toString())
return false
}
}
checkConflicts('feature/user-login', 'develop')
在 GitLab CI 中运行:
check-conflicts:
stage: check
script:
- node scripts/check-conflicts.js
only:
- merge_requests
通过这些措施,我们团队的冲突率降低了 70%,即使有冲突,也能快速解决。"
核心难点与解决方案
难点1: 大型仓库的 Git 性能优化
问题描述: 项目越来越大,Git 操作越来越慢。clone 仓库要 30 分钟,pull 要 5 分钟,严重影响开发效率。
解决方案
"大型仓库的性能问题主要是历史提交太多、二进制文件太大。我做了几个优化:
优化1: 浅克隆(Shallow Clone)
只克隆最近的提交,不要完整历史:
# 只克隆最近 1 次提交
git clone --depth 1 https://github.com/user/repo.git
# 只克隆某个分支
git clone --depth 1 --branch develop https://github.com/user/repo.git
# 后续需要历史时,再拉取
git fetch --unshallow
效果:
- 完整克隆: 30 分钟,5GB
- 浅克隆: 3 分钟,500MB
优化2: 稀疏检出(Sparse Checkout)
只检出需要的文件夹:
git clone --filter=blob:none --sparse https://github.com/user/repo.git
cd repo
# 设置稀疏模式
git sparse-checkout init --cone
# 只检出 src 目录
git sparse-checkout set src
# 后续添加更多目录
git sparse-checkout add docs
优化3: Git LFS (大文件存储)
把大文件(图片、视频、设计稿)放到 LFS:
# 安装 Git LFS
git lfs install
# 跟踪大文件
git lfs track "*.psd"
git lfs track "*.mp4"
git lfs track "design/**"
# 提交 .gitattributes
git add .gitattributes
git commit -m "chore: 配置 Git LFS"
LFS 的好处:
- 大文件不存在 Git 历史里,只存指针
- Clone 时只下载指针,按需下载大文件
- 仓库体积减小 90%+
优化4: 清理历史大文件
如果仓库里已经有大文件,需要清理:
# 找出大文件
git rev-list --objects --all | \
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
sed -n 's/^blob //p' | \
sort --numeric-sort --key=2 | \
tail -20
# 使用 BFG 清理
brew install bfg # macOS
# 或下载 https://rtyley.github.io/bfg-repo-cleaner/
# 删除大于 10MB 的文件
bfg --strip-blobs-bigger-than 10M repo.git
# 清理和垃圾回收
cd repo.git
git reflog expire --expire=now --all
git gc --prune=now --aggressive
优化5: Git 配置调优
# 启用文件系统缓存
git config core.fscache true
# 启用 preload 索引
git config core.preloadindex true
# 增加压缩级别
git config core.compression 9
# 启用并行处理
git config pack.threads 0
# 增加 pack 文件大小
git config pack.packSizeLimit 2g
优化6: Monorepo 工具
如果项目特别大,考虑用 Monorepo 工具:
# 使用 git-worktree 分离工作目录
git worktree add ../repo-feature feature/new-feature
# 或使用 sparse-index
git config index.sparse true
效果对比
优化前:
- Clone: 30 分钟
- Pull: 5 分钟
- Checkout: 2 分钟
- 仓库大小: 5GB
优化后:
- Clone: 3 分钟
- Pull: 30 秒
- Checkout: 10 秒
- 仓库大小: 500MB
团队反馈开发体验好了很多,不用等半天才能开始工作了。"
难点2: 多人协作的分支管理策略
问题描述: 团队有 20 个人,每天都有新功能和 bug 修复,分支太多太乱,经常不知道哪个分支是干什么的。
解决方案
"我们制定了详细的分支管理策略和自动化工具:
策略1: 分支命名规范
# 功能分支
feature/用户名-功能描述
例: feature/zhangsan-user-login
# Bug 修复
bugfix/用户名-问题描述
例: bugfix/lisi-fix-login-error
# 紧急修复
hotfix/问题描述
例: hotfix/fix-payment-crash
# 发布分支
release/版本号
例: release/v1.2.0
# 测试分支
test/测试环境
例: test/qa-env
策略2: 分支生命周期管理
自动清理过期分支:
# scripts/clean-branches.sh
#!/bin/bash
# 删除已合并的本地分支
git branch --merged | grep -v "\*\|master\|develop" | xargs -n 1 git branch -d
# 删除远程已删除的本地跟踪分支
git fetch --prune
# 删除 30 天前的远程分支(排除保护分支)
git for-each-ref --format '%(refname:short) %(committerdate:raw)' refs/remotes/origin | \
while read branch date timestamp; do
if [ $(($(date +%s) - $timestamp)) -gt 2592000 ]; then
# 跳过保护分支
if [[ ! $branch =~ (master|develop|release/) ]]; then
echo "删除过期分支: $branch"
git push origin --delete ${branch#origin/}
fi
fi
done
定时运行:
# .gitlab-ci.yml
clean-branches:
stage: cleanup
script:
- bash scripts/clean-branches.sh
only:
- schedules
when: manual
策略3: 分支保护规则
GitLab 设置:
# master 分支保护
Protected branches:
- master
- Allowed to merge: Maintainers
- Allowed to push: No one
- Require approval: 2 approvals
- Require passing pipeline
# develop 分支保护
- develop
- Allowed to merge: Developers
- Allowed to push: No one
- Require approval: 1 approval
- Require passing pipeline
策略4: 分支关联 Issue
每个分支都要关联 Issue:
# 从 Issue 创建分支
# Issue #123: 实现用户登录功能
git checkout -b feature/zhangsan-123-user-login
# 提交时关联 Issue
git commit -m "feat: 实现用户登录 #123"
# MR 描述中关联
Closes #123
好处:
- 可追溯:知道每个分支是为了解决什么问题
- 自动关闭:MR 合并后自动关闭 Issue
- 统计方便:可以统计每个人的工作量
策略5: 分支可视化
用 GitKraken 或在线工具查看分支图:
# 命令行查看分支图
git log --graph --oneline --all
# 更美观的输出
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --all
配置别名:
git config --global alias.tree "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --all"
# 使用
git tree
策略6: 分支权限管理
不同角色的权限:
实习生: 只能创建 feature 分支,不能合并
初级: 可以合并到 develop,不能合并到 master
中级: 可以创建 release 分支
高级: 可以合并到 master,可以创建 hotfix
通过这套策略,20 人团队的分支管理井井有条,很少出现混乱。"
难点3: CI/CD 与 Git Hooks 的深度集成
问题描述: 代码提交前没有检查,经常提交有问题的代码,导致 CI 失败,浪费时间。
解决方案
"我们建立了完整的 Git Hooks + CI/CD 联动体系:
本地 Hooks (Husky)
npm install --save-dev husky lint-staged
# 初始化
npx husky install
# 添加到 package.json
npm set-script prepare "husky install"
pre-commit: 提交前检查
npx husky add .husky/pre-commit "npx lint-staged"
// package.json
{
"lint-staged": {
"*.{js,vue}": [
"eslint --fix",
"prettier --write"
],
"*.{css,scss}": [
"stylelint --fix",
"prettier --write"
],
"*.md": [
"markdownlint --fix",
"prettier --write"
]
}
}
commit-msg: 提交信息检查
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit $1'
pre-push: 推送前检查
npx husky add .husky/pre-push "npm run test"
// .husky/pre-push
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# 运行测试
npm run test
# 检查是否有未解决的冲突标记
if git diff --cached --name-only | xargs grep -l "<<<<<<< HEAD" 2>/dev/null; then
echo "Error: 发现未解决的冲突标记"
exit 1
fi
# 检查是否有 TODO
if git diff --cached --name-only | xargs grep -l "TODO" 2>/dev/null; then
echo "Warning: 发现 TODO 标记,确认要推送吗? (y/n)"
read answer
if [ "$answer" != "y" ]; then
exit 1
fi
fi
服务端 Hooks
在 GitLab 服务器上配置:
# /var/opt/gitlab/git-data/repositories/project.git/hooks/pre-receive
#!/bin/bash
# 检查提交大小
while read oldrev newrev refname; do
# 获取推送的文件
files=$(git diff --name-only $oldrev $newrev)
# 检查单个文件大小
for file in $files; do
size=$(git cat-file -s $newrev:$file 2>/dev/null)
if [ "$size" -gt 10485760 ]; then # 10MB
echo "Error: 文件 $file 大小超过 10MB"
exit 1
fi
done
done
GitLab CI 配置
# .gitlab-ci.yml
stages:
- pre-check
- lint
- test
- build
- deploy
variables:
NODE_VERSION: "18"
# 缓存
cache:
paths:
- node_modules/
# 安装依赖
before_script:
- npm install
# 代码规范检查
lint:
stage: lint
script:
- npm run lint
only:
- merge_requests
- develop
- master
# 单元测试
test:
stage: test
script:
- npm run test
coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage/cobertura-coverage.xml
only:
- merge_requests
- develop
- master
# 构建
build:
stage: build
script:
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 week
only:
- develop
- master
- /^release\/.*$/
# 部署到测试环境
deploy:test:
stage: deploy
script:
- npm run deploy:test
environment:
name: test
url: https://test.example.com
only:
- develop
when: manual
# 部署到生产环境
deploy:prod:
stage: deploy
script:
- npm run deploy:prod
environment:
name: production
url: https://example.com
only:
- master
when: manual
needs:
- build
自动化流程图
开发者提交代码
↓
pre-commit hook (格式化代码)
↓
commit-msg hook (检查提交信息)
↓
pre-push hook (运行测试)
↓
推送到 GitLab
↓
GitLab CI 开始运行
↓
Lint (代码规范检查)
↓
Test (单元测试)
↓
Build (构建)
↓
Deploy (部署) - 手动触发
效果
- 本地就能发现 90% 的问题
- CI 失败率从 30% 降到 5%
- 代码质量显著提升
这套体系让我们团队的代码质量上了一个台阶。"
完整技术实现
1. 项目初始化脚本
# scripts/init-git-workflow.sh
#!/bin/bash
echo "🚀 初始化 Git 工作流..."
# 1. 安装依赖
echo "📦 安装依赖..."
npm install --save-dev \
husky \
lint-staged \
@commitlint/cli \
@commitlint/config-conventional \
commitizen \
cz-conventional-changelog \
standard-version
# 2. 初始化 Husky
echo "🐶 配置 Husky..."
npx husky install
npm set-script prepare "husky install"
# 3. 添加 Git Hooks
npx husky add .husky/pre-commit "npx lint-staged"
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit $1'
npx husky add .husky/pre-push "npm run test"
# 4. 创建配置文件
echo "📝 创建配置文件..."
# commitlint.config.js
cat > commitlint.config.js << 'EOF'
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
[
'feat',
'fix',
'docs',
'style',
'refactor',
'perf',
'test',
'chore',
'revert'
]
],
'subject-max-length': [2, 'always', 100]
}
}
EOF
# 5. 配置 package.json
echo "⚙️ 配置 package.json..."
npm set-script commit "git-cz"
npm set-script release "standard-version"
# 添加 lint-staged 配置
node -e "
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
pkg['lint-staged'] = {
'*.{js,vue}': ['eslint --fix', 'prettier --write'],
'*.{css,scss}': ['stylelint --fix', 'prettier --write']
};
pkg.config = {
commitizen: {
path: 'cz-conventional-changelog'
}
};
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2));
"
# 6. 创建分支管理脚本
mkdir -p scripts
cat > scripts/clean-branches.sh << 'EOF'
#!/bin/bash
echo "🧹 清理已合并的分支..."
git branch --merged | grep -v "\*\|master\|develop" | xargs -n 1 git branch -d
echo "🔄 更新远程分支信息..."
git fetch --prune
echo "✅ 完成!"
EOF
chmod +x scripts/clean-branches.sh
echo "✨ Git 工作流初始化完成!"
echo ""
echo "使用方法:"
echo " npm run commit - 规范化提交"
echo " npm run release - 生成 changelog 并发布"
echo " bash scripts/clean-branches.sh - 清理分支"
2. MR 模板
<!-- .gitlab/merge_request_templates/Default.md -->
## 改动类型
<!-- 勾选适用的类型 -->
- [ ] 新功能 (feat)
- [ ] Bug 修复 (fix)
- [ ] 性能优化 (perf)
- [ ] 代码重构 (refactor)
- [ ] 文档更新 (docs)
- [ ] 其他
## 改动内容
<!-- 详细描述这次改动 -->
## 相关 Issue
<!-- 如果有相关 Issue,请关联 -->
Closes #
## 测试说明
<!-- 如何测试这次改动 -->
1.
2.
3.
## 截图/录屏
<!-- 如果是 UI 改动,请提供截图或录屏 -->
## Checklist
- [ ] 代码通过 ESLint 检查
- [ ] 添加了必要的单元测试
- [ ] 测试覆盖率不低于 80%
- [ ] 更新了相关文档
- [ ] 本地测试通过
- [ ] 没有遗留 console.log 或 debugger
- [ ] 没有遗留 TODO 或 FIXME
## 额外说明
<!-- 其他需要说明的内容 -->
3. Changelog 生成配置
// .versionrc.js
module.exports = {
types: [
{ type: 'feat', section: '✨ Features' },
{ type: 'fix', section: '🐛 Bug Fixes' },
{ type: 'perf', section: '⚡ Performance' },
{ type: 'refactor', section: '♻️ Refactor' },
{ type: 'docs', section: '📝 Documentation' },
{ type: 'style', section: '💄 Styles' },
{ type: 'test', section: '✅ Tests' },
{ type: 'chore', hidden: true }
],
// 跳过的提交类型
skip: {
bump: true,
changelog: true,
commit: true,
tag: true
},
// Changelog 文件路径
infile: 'CHANGELOG.md',
// 首次生成时的版本
firstRelease: false,
// 提交消息格式
commitUrlFormat: '{{host}}/{{owner}}/{{repository}}/commit/{{hash}}',
compareUrlFormat: '{{host}}/{{owner}}/{{repository}}/compare/{{previousTag}}...{{currentTag}}',
issueUrlFormat: '{{host}}/{{owner}}/{{repository}}/issues/{{id}}',
// 自定义更新文件
bumpFiles: [
{
filename: 'package.json',
type: 'json'
},
{
filename: 'package-lock.json',
type: 'json'
}
]
}
面试常见追问
Q: 如何处理紧急上线和常规开发并行?
"我们用双轨制:
正常功能走 develop -> release -> master
紧急修复走 master -> hotfix -> master + develop
# 紧急修复流程
git checkout master
git pull
git checkout -b hotfix/urgent-fix
# 修复后合并到 master
git checkout master
git merge hotfix/urgent-fix
git tag v1.2.1
# 同时合并到 develop
git checkout develop
git merge hotfix/urgent-fix
```"
### Q: 如何回滚已发布的版本?
"有几种方案:
#### 方案1: Revert
```bash
# 撤销某次提交
git revert <commit-hash>
git push
方案2: Reset(慎用)
# 回退到某个版本
git reset --hard <commit-hash>
git push --force
方案3: 重新部署旧版本
# 切换到旧 tag
git checkout v1.2.0
npm run build
npm run deploy
我们一般用方案1,保留历史记录。"
Q: 大文件误提交了怎么办?
"用 BFG 清理:
# 克隆裸仓库
git clone --mirror https://github.com/user/repo.git
# 删除大文件
bfg --delete-files *.mp4 repo.git
# 清理
cd repo.git
git reflog expire --expire=now --all
git gc --prune=now --aggressive
# 推送
git push
注意:这会改写历史,需要团队协调。"
项目经验总结
踩过的坑
- force push 覆盖他人代码 - 禁用 force push,改用 force-with-lease
- merge 和 rebase 混用 - 统一用 merge,保留完整历史
- 大文件提交 - 没配置 Git LFS,导致仓库巨大
- 提交信息随意 - 实施 commitlint 后才规范
性能数据
- Commit 规范遵守率:95%+
- MR 平均审查时间:< 2小时
- CI 失败率:5%(优化前 30%)
- 代码冲突率:< 10%(优化前 40%)
可以吹的点
- 建立完整的 Git 工作流体系
- Commit 规范 + 自动生成 Changelog
- Git Hooks + CI/CD 深度集成
- 大仓库性能优化,clone 时间减少 90%
- 团队代码质量显著提升