Cursor帮我写的-Git工作实战:规范与最佳实践指南

平时用Git用得比较多,用得多但是却用不好,就想着用Cursor帮我写一份Git的使用指南。

Git工作实战:规范与最佳实践指南

目录

日常工作规范与流程

开发者日常工作清单

每日工作启动流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#!/bin/bash
# daily-startup.sh - 每日工作启动脚本

echo "🌅 开始新的一天的开发工作"
echo "==============================="

# 1. 检查Git配置
echo "🔧 检查Git配置..."
git config --get user.name || echo "⚠️ 请设置用户名: git config --global user.name 'Your Name'"
git config --get user.email || echo "⚠️ 请设置邮箱: git config --global user.email 'your.email@company.com'"

# 2. 检查当前工作状态
echo ""
echo "📋 检查当前工作状态..."
current_branch=$(git branch --show-current)
echo "当前分支: $current_branch"

# 检查是否有未提交的更改
if ! git diff-index --quiet HEAD --; then
echo "⚠️ 发现未提交的更改:"
git status --porcelain
echo "💡 建议先处理这些更改再开始新工作"
fi

# 3. 同步远程代码
echo ""
echo "🔄 同步远程代码..."
git fetch origin

# 检查主分支是否有更新
main_branch="main"
if git show-ref --verify --quiet refs/remotes/origin/master; then
main_branch="master"
fi

local_main=$(git rev-parse $main_branch 2>/dev/null || echo "")
remote_main=$(git rev-parse origin/$main_branch 2>/dev/null || echo "")

if [ "$local_main" != "$remote_main" ]; then
echo "📥 主分支有更新,建议同步:"
echo " git checkout $main_branch && git pull origin $main_branch"
fi

# 4. 检查当前分支状态
if [ "$current_branch" != "$main_branch" ]; then
echo ""
echo "🌿 当前功能分支状态检查..."

# 检查是否落后于主分支
behind_count=$(git rev-list --count HEAD..origin/$main_branch 2>/dev/null || echo "0")
if [ "$behind_count" -gt 0 ]; then
echo "⚠️ 当前分支落后主分支 $behind_count 个提交"
echo "💡 建议执行: git rebase origin/$main_branch"
fi

# 检查是否有未推送的提交
ahead_count=$(git rev-list --count origin/$current_branch..HEAD 2>/dev/null || echo "0")
if [ "$ahead_count" -gt 0 ]; then
echo "📤 有 $ahead_count 个未推送的提交"
fi
fi

# 5. 显示今日计划
echo ""
echo "📅 今日开发计划:"
echo "1. 查看分配的任务: git log --oneline --grep='TODO\|FIXME'"
echo "2. 检查代码审查: git log --oneline --author='\$(git config user.name)' --since='1 day ago'"
echo "3. 更新任务状态"

echo ""
echo "✅ 日常启动检查完成,开始愉快的编码!"

功能开发标准流程

第一步:任务分析与准备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 任务开始前的准备工作
start_new_task() {
local task_name=$1
local task_description=$2

echo "🎯 开始新任务: $task_name"
echo "📝 任务描述: $task_description"

# 1. 确保在最新的主分支
git checkout main
git pull origin main

# 2. 创建功能分支
local branch_name="feature/$(echo $task_name | tr ' ' '-' | tr '[:upper:]' '[:lower:]')"
git checkout -b "$branch_name"

# 3. 推送分支到远程
git push -u origin "$branch_name"

# 4. 创建任务跟踪文件
cat > .git/CURRENT_TASK.md << EOF
# 当前任务: $task_name

## 任务描述
$task_description

## 开始时间
$(date)

## 分支信息
- 分支名: $branch_name
- 基于: main@$(git rev-parse --short main)

## 任务清单
- [ ] 分析需求
- [ ] 设计方案
- [ ] 编码实现
- [ ] 单元测试
- [ ] 集成测试
- [ ] 代码审查
- [ ] 文档更新

## 相关文件
(记录修改的文件)

## 测试用例
(记录测试场景)

## 注意事项
(记录开发过程中的重要信息)
EOF

echo "✅ 任务环境准备完成"
echo "📝 任务跟踪文件: .git/CURRENT_TASK.md"
echo "🌿 工作分支: $branch_name"
}

# 使用示例
# start_new_task "用户认证功能" "实现用户登录、注册和密码重置功能"

第二步:增量开发与提交

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# 增量开发的最佳实践
incremental_development() {
echo "🔄 增量开发指南"
echo "==============="

echo "1. 🎯 小步快跑原则"
echo " - 每次只实现一个小功能点"
echo " - 确保每次提交都能通过测试"
echo " - 提交频率建议:每30分钟到1小时一次"

echo ""
echo "2. 📝 提交前检查清单"
echo " □ 代码编译通过"
echo " □ 单元测试通过"
echo " □ 代码风格检查通过"
echo " □ 提交信息符合规范"
echo " □ 相关文档已更新"

echo ""
echo "3. 🔍 提交前自检脚本"
cat << 'SCRIPT'
#!/bin/bash
# pre-commit-check.sh

echo "🔍 执行提交前检查..."

# 检查代码编译
if command -v npm >/dev/null 2>&1 && [ -f package.json ]; then
echo "📦 检查Node.js项目..."
npm run build || { echo "❌ 构建失败"; exit 1; }
npm test || { echo "❌ 测试失败"; exit 1; }
elif command -v mvn >/dev/null 2>&1 && [ -f pom.xml ]; then
echo "☕ 检查Maven项目..."
mvn compile test || { echo "❌ 构建或测试失败"; exit 1; }
elif command -v python >/dev/null 2>&1 && [ -f requirements.txt ]; then
echo "🐍 检查Python项目..."
python -m pytest || { echo "❌ 测试失败"; exit 1; }
fi

# 检查代码风格
if command -v eslint >/dev/null 2>&1; then
eslint . || { echo "❌ ESLint检查失败"; exit 1; }
fi

if command -v black >/dev/null 2>&1; then
black --check . || { echo "❌ Black格式检查失败"; exit 1; }
fi

# 检查提交信息格式
commit_msg_file=".git/COMMIT_EDITMSG"
if [ -f "$commit_msg_file" ]; then
commit_msg=$(head -1 "$commit_msg_file")
if [[ ! $commit_msg =~ ^(feat|fix|docs|style|refactor|perf|test|chore|ci)(\(.+\))?: .+ ]]; then
echo "❌ 提交信息格式不符合规范"
echo "正确格式: type(scope): description"
exit 1
fi
fi

echo "✅ 所有检查通过"
SCRIPT
}

# 智能提交助手
smart_commit() {
local message=$1

if [ -z "$message" ]; then
echo "请提供提交信息"
return 1
fi

echo "🔍 准备提交: $message"

# 检查暂存区
if git diff --cached --quiet; then
echo "⚠️ 暂存区为空,自动添加所有更改"
git add .
fi

# 显示将要提交的更改
echo ""
echo "📝 将要提交的更改:"
git diff --cached --stat

# 确认提交
echo ""
read -p "确认提交? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
git commit -m "$message"
echo "✅ 提交成功"

# 可选:自动推送
read -p "是否推送到远程? (y/N): " push_confirm
if [[ $push_confirm =~ ^[Yy]$ ]]; then
git push
echo "📤 推送完成"
fi
else
echo "❌ 提交已取消"
fi
}

第三步:定期同步与整理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# 定期同步主分支
sync_with_main() {
local current_branch=$(git branch --show-current)
local main_branch="main"

echo "🔄 同步主分支更新..."

# 检查工作目录状态
if ! git diff-index --quiet HEAD --; then
echo "💾 发现未提交的更改,先暂存..."
git stash push -m "Auto-stash before sync $(date)"
local stashed=true
fi

# 获取最新代码
git fetch origin

# 切换到主分支并更新
git checkout $main_branch
git pull origin $main_branch

# 回到工作分支
git checkout $current_branch

# 选择同步策略
echo ""
echo "选择同步策略:"
echo "1. Rebase (推荐,保持线性历史)"
echo "2. Merge (保留分支历史)"
echo "3. 跳过同步"

read -p "请选择 (1-3): " choice

case $choice in
1)
echo "🔄 执行rebase..."
if git rebase origin/$main_branch; then
echo "✅ Rebase成功"
else
echo "❌ Rebase有冲突,请手动解决"
echo "解决冲突后运行: git rebase --continue"
return 1
fi
;;
2)
echo "🔄 执行merge..."
git merge origin/$main_branch
;;
3)
echo "⏭️ 跳过同步"
;;
esac

# 恢复暂存的更改
if [ "$stashed" = "true" ]; then
echo "📤 恢复暂存的更改..."
git stash pop
fi

echo "✅ 同步完成"
}

# 提交历史整理
cleanup_commits() {
echo "🧹 整理提交历史..."

# 显示未推送的提交
local unpushed=$(git log --oneline origin/$(git branch --show-current)..HEAD 2>/dev/null || git log --oneline -5)

echo "📝 当前未推送的提交:"
echo "$unpushed"

echo ""
echo "整理选项:"
echo "1. 交互式rebase (推荐)"
echo "2. 压缩所有提交为一个"
echo "3. 保持现状"

read -p "请选择 (1-3): " choice

case $choice in
1)
local commit_count=$(echo "$unpushed" | wc -l)
git rebase -i HEAD~$commit_count
;;
2)
git reset --soft origin/$(git branch --show-current) 2>/dev/null || git reset --soft HEAD~5
echo "所有更改已回到暂存区,请重新提交:"
git status
;;
3)
echo "⏭️ 保持现状"
;;
esac
}

代码质量日常维护

代码审查自检流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# 自我代码审查清单
self_code_review() {
echo "🔍 自我代码审查清单"
echo "==================="

# 1. 功能完整性检查
echo "1. 🎯 功能完整性"
echo " □ 所有需求功能都已实现"
echo " □ 边界条件都已处理"
echo " □ 错误处理机制完善"
echo " □ 用户体验良好"

# 2. 代码质量检查
echo ""
echo "2. 📝 代码质量"
echo " □ 变量和函数命名清晰"
echo " □ 函数长度合理 (建议<50行)"
echo " □ 注释充分且准确"
echo " □ 没有重复代码"
echo " □ 遵循团队编码规范"

# 3. 性能检查
echo ""
echo "3. ⚡ 性能优化"
echo " □ 没有不必要的API调用"
echo " □ 数据库查询优化"
echo " □ 内存使用合理"
echo " □ 算法复杂度可接受"

# 4. 安全检查
echo ""
echo "4. 🔒 安全考虑"
echo " □ 输入验证完善"
echo " □ 敏感信息已保护"
echo " □ 权限控制正确"
echo " □ 没有XSS/SQL注入风险"

# 5. 测试覆盖
echo ""
echo "5. 🧪 测试覆盖"
echo " □ 单元测试充分"
echo " □ 集成测试通过"
echo " □ 边界测试用例"
echo " □ 错误场景测试"

# 6. 自动化检查
echo ""
echo "6. 🤖 运行自动化检查..."

# 代码复杂度检查
if command -v radon >/dev/null 2>&1; then
echo "📊 代码复杂度分析:"
radon cc . -a -nb
fi

# 代码重复检查
if command -v jscpd >/dev/null 2>&1; then
echo "🔍 重复代码检查:"
jscpd . --threshold 10
fi

# 安全漏洞扫描
if command -v npm >/dev/null 2>&1 && [ -f package.json ]; then
echo "🔒 安全漏洞扫描:"
npm audit
fi
}

# 代码质量报告生成
generate_quality_report() {
local branch_name=$(git branch --show-current)
local report_file="quality-report-$(date +%Y%m%d-%H%M%S).md"

echo "📊 生成代码质量报告..."

cat > "$report_file" << EOF
# 代码质量报告

## 基本信息
- 分支: $branch_name
- 生成时间: $(date)
- 作者: $(git config user.name)

## 代码统计
\`\`\`
$(git diff --stat origin/main..HEAD 2>/dev/null || echo "无法获取统计信息")
\`\`\`

## 提交历史
\`\`\`
$(git log --oneline origin/main..HEAD 2>/dev/null || git log --oneline -10)
\`\`\`

## 代码复杂度
EOF

# 添加复杂度分析
if command -v radon >/dev/null 2>&1; then
echo "\`\`\`" >> "$report_file"
radon cc . -a -nb >> "$report_file"
echo "\`\`\`" >> "$report_file"
else
echo "无法获取复杂度信息(需要安装radon)" >> "$report_file"
fi

echo "" >> "$report_file"
echo "## 测试覆盖率" >> "$report_file"

# 添加测试覆盖率
if command -v npm >/dev/null 2>&1 && [ -f package.json ]; then
echo "\`\`\`" >> "$report_file"
npm run test:coverage 2>/dev/null >> "$report_file" || echo "无法获取覆盖率信息" >> "$report_file"
echo "\`\`\`" >> "$report_file"
fi

echo "✅ 质量报告已生成: $report_file"
}

代码重构指导

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# 代码重构安全指南
safe_refactoring() {
echo "🔧 安全重构指南"
echo "==============="

echo "1. 📋 重构前准备"
echo " ✓ 确保所有测试通过"
echo " ✓ 创建重构分支"
echo " ✓ 备份当前代码"
echo " ✓ 确保有完整的测试覆盖"

echo ""
echo "2. 🎯 重构原则"
echo " ✓ 一次只重构一个方面"
echo " ✓ 保持功能不变"
echo " ✓ 小步迭代,频繁测试"
echo " ✓ 每次重构后立即提交"

echo ""
echo "3. 🔄 重构流程"

# 创建重构分支
local current_branch=$(git branch --show-current)
local refactor_branch="refactor/$(date +%Y%m%d)-$current_branch"

echo "📝 创建重构分支: $refactor_branch"
git checkout -b "$refactor_branch"

echo ""
echo "4. 📊 重构前代码指标记录"

# 记录重构前的代码指标
cat > ".git/REFACTOR_LOG.md" << EOF
# 重构日志

## 重构信息
- 原分支: $current_branch
- 重构分支: $refactor_branch
- 开始时间: $(date)
- 重构目标: [请填写重构目标]

## 重构前指标
### 代码行数
\`\`\`
$(find . -name "*.js" -o -name "*.ts" -o -name "*.py" -o -name "*.java" | xargs wc -l | tail -1)
\`\`\`

### 文件数量
\`\`\`
$(find . -type f -name "*.js" -o -name "*.ts" -o -name "*.py" -o -name "*.java" | wc -l) 个代码文件
\`\`\`

### 测试状态
\`\`\`
$(npm test 2>&1 | tail -5 || echo "无法获取测试信息")
\`\`\`

## 重构计划
- [ ] 第一步:[具体计划]
- [ ] 第二步:[具体计划]
- [ ] 第三步:[具体计划]

## 重构记录
EOF

echo "📝 重构日志已创建: .git/REFACTOR_LOG.md"
echo ""
echo "5. 🎯 开始重构"
echo " 记住:每完成一个小步骤就提交一次"
echo " 使用: git commit -m 'refactor: [具体改动描述]'"
}

# 重构完成验证
verify_refactoring() {
echo "✅ 重构完成验证"
echo "==============="

echo "1. 🧪 运行所有测试"
if command -v npm >/dev/null 2>&1 && [ -f package.json ]; then
npm test || { echo "❌ 测试失败,请检查"; return 1; }
fi

echo ""
echo "2. 📊 对比重构前后指标"

# 生成重构后指标
echo "### 重构后指标" >> .git/REFACTOR_LOG.md
echo "#### 代码行数" >> .git/REFACTOR_LOG.md
echo "\`\`\`" >> .git/REFACTOR_LOG.md
find . -name "*.js" -o -name "*.ts" -o -name "*.py" -o -name "*.java" | xargs wc -l | tail -1 >> .git/REFACTOR_LOG.md
echo "\`\`\`" >> .git/REFACTOR_LOG.md

echo ""
echo "3. 🔍 代码质量检查"
if command -v eslint >/dev/null 2>&1; then
eslint . || echo "⚠️ 发现代码质量问题"
fi

echo ""
echo "4. 📝 更新重构日志"
echo "" >> .git/REFACTOR_LOG.md
echo "## 重构完成" >> .git/REFACTOR_LOG.md
echo "- 完成时间: $(date)" >> .git/REFACTOR_LOG.md
echo "- 测试状态: ✅ 通过" >> .git/REFACTOR_LOG.md
echo "- 代码质量: 符合标准" >> .git/REFACTOR_LOG.md

echo "✅ 重构验证完成"
echo "📝 重构日志已更新"
echo "🔄 可以考虑合并到原分支"
}

团队协作日常规范

代码审查协作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# 代码审查请求模板
create_review_request() {
local feature_branch=$(git branch --show-current)
local base_branch=${1:-main}

echo "📝 创建代码审查请求"
echo "==================="

# 生成PR描述
local pr_description_file=".git/PR_DESCRIPTION.md"

cat > "$pr_description_file" << EOF
## 🎯 功能描述
[简要描述本次PR的目的和实现的功能]

## 📝 变更内容
### 新增功能
- [ ] [具体功能点1]
- [ ] [具体功能点2]

### Bug修复
- [ ] [修复的问题1]
- [ ] [修复的问题2]

### 重构优化
- [ ] [重构内容1]
- [ ] [重构内容2]

## 🧪 测试情况
### 自动化测试
- [ ] 单元测试通过
- [ ] 集成测试通过
- [ ] E2E测试通过

### 手动测试
- [ ] 功能测试完成
- [ ] 兼容性测试完成
- [ ] 性能测试完成

## 📊 代码统计
\`\`\`
$(git diff --stat $base_branch..HEAD)
\`\`\`

## 🔗 相关链接
- 需求文档: [链接]
- 设计文档: [链接]
- 测试用例: [链接]
- 相关Issue: #[issue号]

## 📱 截图/录屏
[如果是UI变更,请提供截图或录屏]

## ⚠️ 注意事项
### 破坏性变更
- [ ] 无破坏性变更
- [ ] 有破坏性变更(请详细说明)

### 部署注意事项
- [ ] 无特殊部署要求
- [ ] 需要数据库迁移
- [ ] 需要环境变量更新
- [ ] 需要服务重启

### 依赖变更
- [ ] 无依赖变更
- [ ] 新增依赖包
- [ ] 更新依赖版本

## ✅ 检查清单
### 代码质量
- [ ] 代码符合团队规范
- [ ] 函数和变量命名清晰
- [ ] 注释充分且准确
- [ ] 无重复代码
- [ ] 错误处理完善

### 安全检查
- [ ] 输入验证完善
- [ ] 权限控制正确
- [ ] 敏感信息已保护
- [ ] 无安全漏洞

### 性能优化
- [ ] 无性能问题
- [ ] 数据库查询优化
- [ ] 算法复杂度合理

## 👥 审查者
@[reviewer1] @[reviewer2]

## 📅 期望合并时间
[请提供期望的合并时间]

---
**审查指南**: 请重点关注代码逻辑、安全性、性能影响和测试覆盖率
EOF

echo "✅ PR描述模板已生成: $pr_description_file"

# 显示变更概要
echo ""
echo "📊 本次变更概要:"
git diff --stat $base_branch..HEAD

echo ""
echo "📝 提交历史:"
git log --oneline $base_branch..HEAD

echo ""
echo "💡 下一步操作:"
echo "1. 完善 $pr_description_file 中的描述"
echo "2. 推送分支: git push origin $feature_branch"
echo "3. 在GitHub/GitLab创建Pull Request"
echo "4. 通知审查者"
}

# 审查反馈处理
handle_review_feedback() {
echo "📝 处理审查反馈"
echo "==============="

echo "1. 📋 反馈分类处理"
echo ""
echo "🔴 必须修复的问题:"
echo " - 功能性bug"
echo " - 安全漏洞"
echo " - 性能问题"
echo " - 代码规范违反"
echo ""
echo "🟡 建议改进的问题:"
echo " - 代码可读性"
echo " - 变量命名"
echo " - 注释完善"
echo " - 代码结构优化"
echo ""
echo "🟢 讨论性问题:"
echo " - 技术方案选择"
echo " - 架构设计"
echo " - 未来扩展性"

echo ""
echo "2. 🔧 修复流程"

# 创建修复追踪文件
cat > ".git/REVIEW_FIXES.md" << EOF
# 审查反馈修复记录

## 修复时间
$(date)

## 必须修复项
- [ ] [具体问题1] - [修复说明]
- [ ] [具体问题2] - [修复说明]

## 建议改进项
- [ ] [改进点1] - [改进说明]
- [ ] [改进点2] - [改进说明]

## 讨论回复
- [ ] [讨论点1] - [回复说明]
- [ ] [讨论点2] - [回复说明]

## 修复提交
- [提交hash] [提交说明]

## 测试验证
- [ ] 修复功能测试通过
- [ ] 回归测试通过
- [ ] 代码质量检查通过
EOF

echo "📝 修复追踪文件已创建: .git/REVIEW_FIXES.md"

echo ""
echo "3. 💡 修复建议"
echo " ✓ 一次只修复一个问题"
echo " ✓ 每次修复后提交"
echo " ✓ 使用清晰的提交信息"
echo " ✓ 修复后通知审查者"

echo ""
echo "4. 📝 提交信息格式"
echo " fix(review): [具体修复内容]"
echo " refactor(review): [重构说明]"
echo " docs(review): [文档更新]"
}

团队协作工作流规范

工作流选择原则

根据团队规模和项目特点选择合适的工作流:

1
2
3
4
5
6
7
8
9
10
graph TD
A[团队规模评估] --> B{小团队 < 5人?}
B -->|是| C[GitHub Flow]
B -->|否| D{发布频率}
D -->|频繁发布| E[GitHub Flow + Feature Flags]
D -->|定期发布| F[Git Flow]

C --> G[简单高效]
E --> H[持续部署]
F --> I[严格流程控制]

1. GitHub Flow(推荐小团队使用)

核心原则:main分支始终可部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 标准工作流程
# 1. 从main创建功能分支
git checkout main
git pull origin main
git checkout -b feature/user-profile

# 2. 开发并推送
git add .
git commit -m "feat(profile): add user avatar upload"
git push -u origin feature/user-profile

# 3. 创建Pull Request
# 4. 代码审查通过后合并
# 5. 删除功能分支
git checkout main
git pull origin main
git branch -d feature/user-profile

优势

  • 流程简单,学习成本低
  • 适合持续部署
  • 减少分支管理复杂性

2. Git Flow(推荐大团队使用)

分支结构详解

1
2
3
4
5
6
7
8
永久分支:
├── main/master # 生产环境分支
└── develop # 开发集成分支

临时分支:
├── feature/* # 功能开发分支
├── release/* # 版本发布分支
└── hotfix/* # 紧急修复分支

实际操作示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 功能开发完整流程
# 1. 创建功能分支
git checkout develop
git pull origin develop
git checkout -b feature/shopping-cart

# 2. 开发过程中定期同步develop分支
git fetch origin develop
git rebase origin/develop # 保持线性历史

# 3. 功能完成后合并到develop
git checkout develop
git merge --no-ff feature/shopping-cart
git push origin develop
git branch -d feature/shopping-cart

# 4. 发布流程
git checkout -b release/v1.2.0 develop
# 进行发布前的bug修复和版本号更新
git checkout main
git merge --no-ff release/v1.2.0
git tag -a v1.2.0 -m "Release version 1.2.0"
git checkout develop
git merge --no-ff release/v1.2.0

分支命名规范

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 功能分支
feature/user-authentication
feature/payment-integration
feature/JIRA-1234 # 对应任务编号

# 修复分支
bugfix/login-error
bugfix/payment-timeout

# 发布分支
release/v1.2.0
release/v2.0.0-beta

# 热修复分支
hotfix/security-patch
hotfix/critical-bug-fix

# 实验分支
experiment/new-ui-design
experiment/performance-test

分支管理策略与实践

分支保护规则

main/master分支保护设置

1
2
3
4
5
6
7
8
9
10
11
# GitHub分支保护规则配置
branch_protection:
required_status_checks:
- continuous-integration
- code-review
enforce_admins: true
required_pull_request_reviews:
required_approving_review_count: 2
dismiss_stale_reviews: true
require_code_owner_reviews: true
restrictions: null

本地Git钩子实现

1
2
3
4
5
6
7
8
9
10
11
# .git/hooks/pre-push (防止直接推送到保护分支)
#!/bin/sh
protected_branches="main master develop"
current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')

for branch in $protected_branches; do
if [ "$current_branch" = "$branch" ]; then
echo "Direct push to $branch is not allowed"
exit 1
fi
done

分支清理策略

自动化分支清理

1
2
3
4
5
6
7
8
9
10
# 清理已合并的本地分支
git branch --merged main | grep -v "main\|develop" | xargs -n 1 git branch -d

# 清理远程跟踪分支
git remote prune origin

# 批量删除远程已合并分支(谨慎使用)
git for-each-ref --format='%(refname:short)' refs/remotes/origin |
grep -E '^origin/feature/' |
xargs -I {} git push origin --delete {}

分支生命周期管理

1
2
3
4
5
6
7
8
9
10
11
graph LR
A[创建分支] --> B[开发阶段]
B --> C[代码审查]
C --> D[合并到主分支]
D --> E[删除分支]

B --> F[定期同步主分支]
F --> B

C --> G[审查不通过]
G --> B

代码提交规范

Conventional Commits标准

提交信息格式

1
2
3
4
5
<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

提交类型详解

类型 用途 示例
feat 新功能 feat(auth): add OAuth2 login
fix Bug修复 fix(api): handle null response
docs 文档更新 docs(readme): update setup guide
style 代码格式 style: fix eslint warnings
refactor 重构 refactor(utils): extract common functions
perf 性能优化 perf(db): optimize query performance
test 测试相关 test(auth): add unit tests
chore 构建/工具 chore(deps): update dependencies
ci CI配置 ci: add automated testing workflow

实际提交示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 好的提交示例
git commit -m "feat(user): add profile picture upload

- Support JPEG, PNG, WebP formats
- Add image compression and resizing
- Implement upload progress indicator
- Add error handling for oversized files

Closes #123
Breaking change: Requires new AWS S3 bucket permissions"

# 不好的提交示例(避免)
git commit -m "fix stuff"
git commit -m "update"
git commit -m "various changes"

提交原子性原则

一个提交只做一件事

1
2
3
4
5
6
7
8
9
10
11
12
13
# 正确的原子性提交
git add src/auth/login.js
git commit -m "feat(auth): implement login validation"

git add src/auth/logout.js
git commit -m "feat(auth): implement logout functionality"

git add docs/auth.md
git commit -m "docs(auth): add authentication guide"

# 错误的非原子性提交(避免)
git add .
git commit -m "add login, logout, and update docs"

使用交互式暂存

1
2
3
4
5
6
7
8
9
# 分块提交同一文件的不同部分
git add -p src/app.js

# 交互选项:
# y - 暂存这个块
# n - 不暂存这个块
# s - 分割成更小的块
# e - 手动编辑块
# q - 退出

提交历史整理

使用交互式rebase整理提交

1
2
3
4
5
6
7
8
9
10
11
12
# 整理最近3次提交
git rebase -i HEAD~3

# 编辑器中的操作选项:
pick f1d2d2f feat(auth): add login form
squash 310154e fix(auth): fix validation error
reword a5f4a0d feat(auth): implement authentication

# 变成:
pick f1d2d2f feat(auth): add login functionality
# 第二个提交被压缩到第一个
# 第三个提交的消息被重写

提交历史的最佳实践

1
2
3
4
5
6
7
8
# 推送前整理提交历史
git log --oneline origin/main..HEAD # 查看待推送的提交

# 如果有多个小提交,可以压缩为一个
git rebase -i origin/main

# 推送整理后的历史
git push origin feature/clean-commits

分支合并深度解析

理解Git合并的本质

在Git中,分支合并是将两个或多个开发历史线整合在一起的过程。每种合并方式都有其特定的使用场景和影响。

1
2
3
4
5
6
7
8
graph LR
A[main分支] --> B[共同提交点]
B --> C[main新提交]
B --> D[feature分支]
D --> E[feature新提交]
C --> F[合并点]
E --> F
F --> G[合并后状态]

合并方式详细对比

1. Fast-Forward合并(快进合并)

适用场景:目标分支(通常是main)没有新的提交

1
2
3
4
5
6
7
8
9
10
11
# 初始状态
# main: A---B---C
# \
# feature: D---E

# 执行合并
git checkout main
git merge feature

# 结果:main指针直接移动到E
# main: A---B---C---D---E

详细操作流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1. 确认当前状态
git log --oneline --graph --all
# * e1f2g3h (feature) Add new feature
# * d4e5f6g Implement core logic
# * c7d8e9f (HEAD -> main) Initial setup

# 2. 切换到目标分支
git checkout main

# 3. 执行快进合并
git merge feature
# Updating c7d8e9f..e1f2g3h
# Fast-forward
# feature.js | 10 ++++++++++
# 1 file changed, 10 insertions(+)

# 4. 查看结果
git log --oneline
# e1f2g3h (HEAD -> main, feature) Add new feature
# d4e5f6g Implement core logic
# c7d8e9f Initial setup

快进合并的特点

  • ✅ 保持线性历史,简洁清晰
  • ✅ 没有额外的合并提交
  • ✅ 执行速度快
  • ❌ 丢失分支信息,无法追溯feature分支的存在
  • ❌ 无法看出哪些提交是作为一个功能单元开发的

2. 非快进合并(Three-way Merge)

适用场景:目标分支有新的提交,需要真正的合并

1
2
3
4
5
6
7
8
9
10
11
12
13
# 初始状态
# main: A---B---C---F (main有新提交)
# \
# feature: D---E

# 执行合并
git checkout main
git merge feature

# 结果:创建合并提交M
# main: A---B---C---F---M
# \ /
# feature: D---E---/

详细操作流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 1. 查看分支状态
git log --oneline --graph --all
# * f9a8b7c (main) Fix main branch bug
# | * e1f2g3h (feature) Add new feature
# | * d4e5f6g Implement core logic
# |/
# * c7d8e9f Initial setup

# 2. 执行三方合并
git checkout main
git merge feature
# Merge made by the 'recursive' strategy.
# feature.js | 10 ++++++++++
# 1 file changed, 10 insertions(+)

# 3. 查看合并后的历史
git log --oneline --graph
# * a1b2c3d (HEAD -> main) Merge branch 'feature'
# |\
# | * e1f2g3h (feature) Add new feature
# | * d4e5f6g Implement core logic
# * | f9a8b7c Fix main branch bug
# |/
# * c7d8e9f Initial setup

三方合并的工作原理

1
2
3
4
5
6
7
8
9
10
11
graph TD
A[Base: 共同祖先提交] --> B[Three-way Merge算法]
C[Ours: 当前分支HEAD] --> B
D[Theirs: 要合并的分支] --> B
B --> E[合并结果]

B --> F{文件状态比较}
F -->|Base=Ours≠Theirs| G[使用Theirs版本]
F -->|Base=Theirs≠Ours| H[使用Ours版本]
F -->|Base≠Ours=Theirs| I[使用共同版本]
F -->|Base≠Ours≠Theirs| J[产生冲突]

3. 强制非快进合并(–no-ff)

使用场景:即使可以快进,也要创建合并提交

1
2
3
4
5
6
7
# 强制创建合并提交
git merge --no-ff feature

# 结果:即使可以快进,也会创建合并提交
# main: A---B---C-------M
# \ /
# feature: D---E---/

详细示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 1. 模拟快进场景
git checkout main
git checkout -b feature/user-auth
echo "auth code" > auth.js
git add auth.js
git commit -m "feat: add authentication"

# 2. 回到main,执行no-ff合并
git checkout main
git merge --no-ff feature/user-auth
# 会打开编辑器输入合并信息

# 3. 查看历史图
git log --oneline --graph
# * d1e2f3g (HEAD -> main) Merge branch 'feature/user-auth'
# |\
# | * a4b5c6d (feature/user-auth) feat: add authentication
# |/
# * g7h8i9j Initial commit

–no-ff的优势

  • ✅ 明确标记功能边界
  • ✅ 便于功能回滚
  • ✅ 保持分支结构信息
  • ✅ 符合Git Flow工作流

4. Squash合并(压缩合并)

使用场景:将功能分支的多个提交压缩为一个

1
2
3
4
5
6
7
# 压缩合并
git merge --squash feature

# 结果:feature分支的所有更改作为一个新提交
# main: A---B---C---S
# \
# feature: D---E---F (不会被合并到main历史中)

详细操作流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 1. 创建有多个提交的功能分支
git checkout -b feature/multi-commits
echo "step 1" > steps.txt
git add steps.txt
git commit -m "feat: implement step 1"

echo "step 2" >> steps.txt
git add steps.txt
git commit -m "feat: implement step 2"

echo "step 3" >> steps.txt
git add steps.txt
git commit -m "feat: implement step 3"

# 2. 回到main执行squash合并
git checkout main
git merge --squash feature/multi-commits
# Squash commit -- not updating HEAD
# Automatic merge went well; stopped before committing as requested

# 3. 查看状态(更改已暂存但未提交)
git status
# On branch main
# All conflicts fixed but you are still merging.
# (use "git commit" to conclude merge)
# Changes to be committed:
# new file: steps.txt

# 4. 手动提交压缩后的更改
git commit -m "feat: implement multi-step feature

- Add step 1 implementation
- Add step 2 implementation
- Add step 3 implementation

Squashed commits from feature/multi-commits"

# 5. 查看最终历史
git log --oneline
# f1e2d3c (HEAD -> main) feat: implement multi-step feature
# a4b5c6d Initial commit

Squash合并的特点

  • ✅ 保持主分支历史整洁
  • ✅ 每个功能对应一个提交
  • ✅ 便于代码审查和回滚
  • ❌ 丢失详细开发历史
  • ❌ 无法追溯具体开发步骤

Rebase vs Merge深度对比

Rebase(变基)原理

1
2
3
4
5
6
7
8
# 使用rebase整理历史
git checkout feature
git rebase main

# rebase过程:
# 1. 找到共同祖先
# 2. 将feature分支的提交"重放"到main最新提交之后
# 3. 创建新的提交对象(SHA-1会改变)

Rebase详细流程

1
2
3
4
5
6
7
8
9
10
11
sequenceDiagram
participant F as Feature分支
participant M as Main分支
participant G as Git

F->>G: git rebase main
G->>G: 1. 找到共同祖先
G->>G: 2. 保存feature分支提交
G->>G: 3. 重置feature到main HEAD
G->>G: 4. 逐个重放保存的提交
G->>F: 返回线性历史

Interactive Rebase(交互式变基)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 交互式rebase最近3个提交
git rebase -i HEAD~3

# 编辑器会显示:
pick f1d2d2f feat: add login form
pick 310154e fix: fix form validation
pick a5f4a0d docs: update login docs

# 修改为:
pick f1d2d2f feat: add login form
squash 310154e fix: fix form validation
reword a5f4a0d docs: update login docs

# 结果:
# - 第二个提交被压缩到第一个
# - 第三个提交的消息会被重写

可用的rebase操作

命令 简写 作用 使用场景
pick p 使用提交 保持提交不变
reword r 使用提交但修改消息 改正提交信息错误
edit e 使用提交但停下来修改 需要修改提交内容
squash s 使用提交但合并到前一个 合并相关提交
fixup f 类似squash但丢弃消息 修复性提交
exec x 运行命令 执行测试或构建
break b 在此处停止 检查中间状态
drop d 移除提交 删除错误提交
label l 标记当前HEAD 复杂rebase操作
reset t 重置HEAD到标记 复杂rebase操作

Merge vs Rebase选择指南

使用Merge的场景

1
2
3
4
5
6
7
8
9
10
11
# 1. 保留完整历史记录
git merge feature/important-feature

# 2. 团队协作中的功能集成
git merge --no-ff feature/team-work

# 3. 发布分支合并
git merge --no-ff release/v1.2.0

# 4. 不确定rebase安全性时
git merge feature/complex-changes

使用Rebase的场景

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. 个人分支整理
git rebase main

# 2. 保持线性历史
git rebase -i HEAD~5

# 3. 清理提交历史后再合并
git rebase -i origin/main
git checkout main
git merge feature/clean-history # 这会是fast-forward

# 4. 同步最新主分支变更
git fetch origin
git rebase origin/main

Golden Rule of Rebase(Rebase黄金法则)

1
2
3
4
5
6
# ❌ 永远不要rebase已经推送到公共仓库的提交
# 如果其他人基于这些提交工作,rebase会造成混乱

# ✅ 只rebase本地的、未推送的提交
git log --oneline origin/feature..HEAD # 查看未推送的提交
git rebase -i origin/feature # 安全的rebase范围

合并策略深入分析

1. Recursive策略(默认)

1
2
3
4
5
6
7
# Git默认使用recursive策略
git merge feature # 等同于 git merge -s recursive feature

# 适用场景:
# - 大多数标准合并情况
# - 两个分支的合并
# - 能智能处理重命名和移动

Recursive策略的选项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 冲突时优先采用我们的版本
git merge -X ours feature

# 冲突时优先采用他们的版本
git merge -X theirs feature

# 忽略空白字符差异
git merge -X ignore-space-change feature

# 忽略空白字符数量
git merge -X ignore-all-space feature

# 关闭重命名检测(提高性能)
git merge -X no-renames feature

2. Octopus策略(多路合并)

1
2
3
4
5
6
7
8
# 同时合并多个分支
git merge branch1 branch2 branch3

# 等同于:
git merge -s octopus branch1 branch2 branch3

# 实际案例:
git merge feature/auth feature/ui feature/api

Octopus合并的限制

  • 不能有冲突,否则会失败
  • 适用于简单的多分支整合
  • 常用于release分支整合多个功能

3. Ours策略(完全忽略其他分支)

1
2
3
4
5
6
# 创建合并提交但完全忽略other-branch的更改
git merge -s ours other-branch

# 使用场景:
# - 标记某个分支已经"合并"但不要其内容
# - 废弃某个功能分支但保留合并记录

4. Subtree策略(子项目合并)

1
2
3
4
5
6
# 将另一个项目作为子目录合并
git merge -s subtree -Xsubtree=lib/ library-project

# 使用场景:
# - 集成第三方库
# - 单体仓库架构

合并最佳实践

1. 合并前检查清单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# ✅ 合并前必做检查
# 1. 确保当前分支是最新的
git fetch origin
git status

# 2. 确保工作目录干净
git status
# 应该显示 "nothing to commit, working tree clean"

# 3. 查看即将合并的内容
git log --oneline main..feature
git diff main...feature

# 4. 运行测试确保功能正常
npm test # 或其他测试命令

# 5. 检查是否有冲突
git merge-tree $(git merge-base main feature) main feature

2. 合并后验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ✅ 合并后必做验证
# 1. 确认合并成功
git log --oneline -5

# 2. 运行完整测试套件
npm test
npm run lint
npm run build

# 3. 检查功能是否正常工作
# 手动测试关键功能

# 4. 确认没有意外的文件变更
git status
git diff HEAD~1

3. 团队合并规范

Pull Request工作流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 开发者操作
git checkout -b feature/new-feature
# ... 开发工作 ...
git push origin feature/new-feature
# 创建Pull Request

# 审查者操作
git fetch origin
git checkout feature/new-feature
git merge origin/main # 确保能正常合并
# 进行代码审查

# 合并操作(通过PR界面或命令行)
git checkout main
git merge --no-ff feature/new-feature
git push origin main

合并提交信息规范

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 好的合并提交信息
git merge --no-ff feature/user-auth -m "Merge branch 'feature/user-auth'

Add comprehensive user authentication system

- OAuth2 integration with Google and GitHub
- JWT token management
- Password reset functionality
- Email verification
- User profile management

Closes #123, #124, #125
Reviewed-by: @reviewer1, @reviewer2"

# 避免的合并信息
git merge feature/stuff # 自动生成的简单信息

冲突处理与预防

理解冲突产生的根本原因

Git冲突本质上是同一文件的同一位置被不同分支以不同方式修改时发生的。理解冲突产生的机制有助于更好地预防和解决冲突。

冲突产生的技术原理

1
2
3
4
5
6
7
8
graph TD
A[共同祖先提交] --> B[分支A的修改]
A --> C[分支B的修改]
B --> D[合并操作]
C --> D
D --> E{三方比较}
E -->|A≠B且都≠祖先| F[产生冲突]
E -->|A=B或其一=祖先| G[自动合并]

三方合并算法详解

1
2
3
4
5
6
7
8
9
# Git使用三个版本进行合并决策:
# 1. Base(共同祖先)- 两个分支分叉前的状态
# 2. Ours(当前分支)- 我们正在合并到的分支
# 3. Theirs(目标分支)- 要合并进来的分支

# 查看三方合并的具体内容
git show :1:文件名 # Base版本
git show :2:文件名 # Ours版本
git show :3:文件名 # Theirs版本

冲突类型详细分析

1. 内容冲突(Content Conflict)

最常见的冲突类型,发生在同一文件的同一行或相邻行被不同修改时。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 共同祖先版本(Base)
function calculatePrice(item) {
return item.price;
}

// 分支A的修改(Ours)
function calculatePrice(item) {
return item.price * 1.1; // 加10%税费
}

// 分支B的修改(Theirs)
function calculatePrice(item) {
return item.price * 0.9; // 打9折
}

// 合并时产生的冲突标记
function calculatePrice(item) {
<<<<<<< HEAD (当前分支)
return item.price * 1.1; // 加10%税费
=======
return item.price * 0.9; // 打9折
>>>>>>> feature/discount (要合并的分支)
}

解决内容冲突的策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 1. 查看冲突文件
git status
git diff

# 2. 分析冲突原因
git log --oneline --graph --all
git show HEAD # 查看当前分支的修改
git show MERGE_HEAD # 查看要合并分支的修改

# 3. 选择解决方案
# 方案A: 完全采用当前分支版本
git checkout --ours src/price.js

# 方案B: 完全采用目标分支版本
git checkout --theirs src/price.js

# 方案C: 手动合并(推荐)
# 编辑文件,创建最佳解决方案
function calculatePrice(item) {
// 综合考虑税费和折扣
const priceWithTax = item.price * 1.1;
const finalPrice = priceWithTax * 0.9;
return finalPrice;
}

# 4. 标记已解决
git add src/price.js
git commit

2. 添加/添加冲突(Add/Add Conflict)

发生场景:两个分支都创建了同名文件但内容不同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 分支A创建的config.json
{
"database": {
"host": "localhost",
"port": 5432
}
}

# 分支B创建的config.json
{
"api": {
"endpoint": "https://api.example.com",
"timeout": 30000
}
}

# 合并时的冲突标记
{
<<<<<<< HEAD
"database": {
"host": "localhost",
"port": 5432
}
=======
"api": {
"endpoint": "https://api.example.com",
"timeout": 30000
}
>>>>>>> feature/api-config
}

解决添加/添加冲突

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 1. 查看两个版本的完整内容
git show :2:config.json # 当前分支版本
git show :3:config.json # 目标分支版本

# 2. 合并配置(通常是合并对象属性)
{
"database": {
"host": "localhost",
"port": 5432
},
"api": {
"endpoint": "https://api.example.com",
"timeout": 30000
}
}

# 3. 解决冲突
git add config.json
git commit -m "merge: combine database and api configurations"

3. 修改/删除冲突(Modify/Delete Conflict)

发生场景:一个分支修改了文件,另一个分支删除了同一文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 冲突提示信息
CONFLICT (modify/delete): old-feature.js deleted in feature/cleanup
and modified in HEAD. Version HEAD of old-feature.js left in tree.

# 解决选项:
# 选项1: 保留修改,不删除文件
git add old-feature.js

# 选项2: 确认删除文件
git rm old-feature.js

# 选项3: 重命名文件(如果修改很重要)
git mv old-feature.js legacy-feature.js
git add legacy-feature.js

4. 重命名冲突(Rename Conflict)

发生场景:两个分支将同一文件重命名为不同名称。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 分支A: utils.js → helpers.js
# 分支B: utils.js → common.js

# 冲突信息
CONFLICT (rename/rename): Rename "utils.js"->"helpers.js" in branch "HEAD"
rename "utils.js"->"common.js" in "feature/refactor"

# 解决方案:
# 1. 选择一个名称
git rm common.js
git add helpers.js

# 2. 或者保留两个文件(如果内容不同)
git add helpers.js
git add common.js

# 3. 或者创建新的统一名称
git mv helpers.js utility-functions.js
git rm common.js
git add utility-functions.js

高级冲突解决技巧

1. 使用三方合并工具

配置专业合并工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 配置Beyond Compare
git config --global merge.tool bc
git config --global mergetool.bc.path "C:/Program Files/Beyond Compare 4/bcomp.exe"

# 配置KDiff3
git config --global merge.tool kdiff3
git config --global mergetool.kdiff3.path "/usr/bin/kdiff3"

# 配置VS Code
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'

# 配置Vim(内置)
git config --global merge.tool vimdiff

使用合并工具解决冲突

1
2
3
4
5
6
7
8
9
10
11
# 启动配置的合并工具
git mergetool

# 对于每个冲突文件,工具会显示:
# - Left: Ours(当前分支版本)
# - Base: 共同祖先版本
# - Right: Theirs(目标分支版本)
# - Bottom: 合并结果

# 完成后清理临时文件
git clean -f *.orig

2. 分块解决冲突

针对大文件的逐块处理

1
2
3
4
5
6
7
8
9
10
11
12
# 使用git diff查看冲突区域
git diff --name-only --diff-filter=U # 列出所有冲突文件
git diff HEAD MERGE_HEAD -- filename # 查看特定文件的差异

# 分块处理策略
# 1. 先解决简单的冲突
# 2. 再处理复杂的逻辑冲突
# 3. 最后验证整体功能

# 使用编辑器的冲突解决功能
# VS Code: 点击"Accept Current Change"/"Accept Incoming Change"/"Accept Both Changes"
# IntelliJ: 使用内置的三方合并界面

3. 冲突解决的验证流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# ✅ 冲突解决后的验证清单

# 1. 确保没有遗漏的冲突标记
grep -r "<<<<<<< " .
grep -r "=======" .
grep -r ">>>>>>> " .

# 2. 语法检查
npm run lint # 或其他语法检查工具

# 3. 功能测试
npm test # 运行测试套件

# 4. 构建检查
npm run build # 确保能正常构建

# 5. 手动功能验证
# 启动应用,测试修改的功能

# 6. 提交合并结果
git add .
git commit # 完成合并提交

冲突预防策略升级

1. 代码架构层面的预防

模块化设计原则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 按功能模块组织代码,减少文件冲突
src/
├── auth/ # 认证模块 - 团队A负责
│ ├── login.js
│ ├── register.js
│ └── utils.js
├── payment/ # 支付模块 - 团队B负责
│ ├── stripe.js
│ ├── paypal.js
│ └── utils.js
├── shared/ # 共享模块 - 需要协调
│ ├── api.js
│ ├── constants.js
│ └── helpers.js
└── config/ # 配置文件 - 集中管理
├── development.js
├── production.js
└── common.js

文件分层策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 避免:所有配置都在一个大文件中
// config.js (容易产生冲突)
export default {
database: { /* ... */ },
api: { /* ... */ },
auth: { /* ... */ },
payment: { /* ... */ }
};

// 推荐:按功能分离配置
// config/database.js
export default { host: 'localhost', port: 5432 };

// config/api.js
export default { endpoint: '/api/v1', timeout: 30000 };

// config/index.js
import database from './database.js';
import api from './api.js';
export { database, api };

2. 开发流程层面的预防

每日同步策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/bin/bash
# daily-sync.sh - 每日同步脚本

echo "🔄 开始每日同步..."

# 1. 保存当前工作
current_branch=$(git branch --show-current)
if ! git diff-index --quiet HEAD --; then
echo "📦 暂存当前工作..."
git stash push -m "Daily sync auto-stash $(date)"
stashed=true
fi

# 2. 获取最新代码
echo "📥 获取远程更新..."
git fetch origin

# 3. 检查是否需要同步
if git merge-base --is-ancestor origin/main HEAD; then
echo "✅ 已经是最新状态"
else
echo "🔄 正在同步主分支..."

# 使用rebase保持线性历史
if git rebase origin/main; then
echo "✅ 同步成功"
else
echo "❌ 同步时发现冲突,请手动解决"
echo "💡 解决冲突后运行: git rebase --continue"
exit 1
fi
fi

# 4. 恢复工作状态
if [ "$stashed" = true ]; then
echo "📤 恢复工作状态..."
git stash pop
fi

echo "🎉 每日同步完成!"

功能开发协调机制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 团队协调工具
# 1. 创建功能开发公告
git checkout -b feature/user-profile
echo "开发用户资料功能,影响文件:
- src/components/UserProfile.jsx
- src/api/user.js
- src/styles/profile.css
预计完成时间:3天" > .git/FEATURE_NOTICE

# 2. 推送公告分支
git add .git/FEATURE_NOTICE
git commit -m "docs: add feature development notice"
git push origin feature/user-profile

# 3. 其他开发者检查冲突风险
git fetch origin
git diff origin/feature/user-profile...HEAD --name-only

3. 技术工具层面的预防

Pre-merge检查脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/bin/bash
# pre-merge-check.sh

target_branch=${1:-main}
current_branch=$(git branch --show-current)

echo "🔍 检查与 $target_branch 的潜在冲突..."

# 1. 检查文件级冲突
echo "📁 检查文件变更..."
changed_files=$(git diff --name-only $target_branch...HEAD)
echo "当前分支修改的文件:"
echo "$changed_files"

# 2. 检查是否有重叠的文件修改
echo "🔍 检查重叠修改..."
target_changed=$(git diff --name-only $target_branch~1..$target_branch)
overlap=$(comm -12 <(echo "$changed_files" | sort) <(echo "$target_changed" | sort))

if [ -n "$overlap" ]; then
echo "⚠️ 发现重叠修改的文件:"
echo "$overlap"
echo "💡 建议先同步 $target_branch 分支"
else
echo "✅ 没有发现重叠修改"
fi

# 3. 模拟合并测试
echo "🧪 模拟合并测试..."
if git merge-tree $(git merge-base HEAD $target_branch) HEAD $target_branch > /tmp/merge-test 2>&1; then
if grep -q "<<<<<<< " /tmp/merge-test; then
echo "❌ 模拟合并发现冲突"
echo "冲突文件预览:"
grep -A 5 -B 5 "<<<<<<< " /tmp/merge-test
else
echo "✅ 模拟合并成功,无冲突"
fi
else
echo "❌ 模拟合并失败"
fi

rm -f /tmp/merge-test

智能冲突检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# conflict-detector.sh - 智能冲突检测
#!/bin/bash

# 检查代码风格一致性
echo "🎨 检查代码风格..."
if command -v prettier &> /dev/null; then
prettier --check . || echo "⚠️ 代码格式不一致,可能导致格式冲突"
fi

# 检查导入语句冲突
echo "📦 检查导入语句..."
find . -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" | \
xargs grep -l "^import" | \
while read file; do
# 检查是否有重复的导入
duplicates=$(grep "^import" "$file" | sort | uniq -d)
if [ -n "$duplicates" ]; then
echo "⚠️ $file 有重复导入,可能导致冲突"
fi
done

# 检查配置文件变更
echo "⚙️ 检查配置文件..."
config_files="package.json yarn.lock package-lock.json .env .gitignore"
for file in $config_files; do
if git diff --name-only HEAD origin/main | grep -q "^$file$"; then
echo "⚠️ $file 被修改,注意合并时的冲突"
fi
done

团队冲突解决协议

冲突解决优先级

1
2
3
4
5
6
7
8
9
10
11
# 🥇 第一优先级:功能完整性
# - 确保合并后功能正常工作
# - 不破坏现有功能

# 🥈 第二优先级:代码质量
# - 保持代码风格一致
# - 遵循项目架构原则

# 🥉 第三优先级:历史整洁性
# - 保持提交历史清晰
# - 适当压缩无关紧要的提交

复杂冲突的团队处理流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
flowchart TD
A[发现复杂冲突] --> B{能否独立解决?}
B -->|是| C[独立解决并文档化]
B -->|否| D[寻求代码作者协助]

D --> E[代码作者参与]
E --> F[共同分析冲突]
F --> G[制定解决方案]
G --> H[实施解决方案]
H --> I[测试验证]
I --> J[文档化解决过程]

C --> K[提交并通知团队]
J --> K

团队冲突解决SOP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 1. 冲突发现和分类
git status
echo "冲突类型:[内容/添加/删除/重命名]"
echo "影响范围:[文件数量/功能模块]"
echo "复杂程度:[简单/中等/复杂]"

# 2. 寻求协助(复杂冲突)
echo "涉及代码作者:"
git log --pretty=format:"%an %ae" -- conflicted-file.js | sort | uniq
echo "通知相关人员参与解决"

# 3. 解决过程文档化
echo "## 冲突解决记录

### 冲突描述
- 发生时间:$(date)
- 涉及分支:$(git branch --show-current) <- $(git name-rev MERGE_HEAD --name-only)
- 冲突文件:$(git diff --name-only --diff-filter=U | tr '\n' ' ')

### 解决方案
[描述采用的解决策略]

### 验证结果
[描述测试验证过程]

### 经验教训
[记录避免类似冲突的方法]
" >> .git/CONFLICT_RESOLUTION.md

# 4. 解决后的团队通知
git commit -m "resolve: merge conflicts in user module

- Resolved content conflicts in user.js
- Combined authentication methods
- Updated tests for merged functionality

Co-authored-by: Teammate <teammate@email.com>"

通过这些详细的分支合并和冲突处理策略,团队可以更好地理解Git合并的机制,有效预防冲突,并在冲突发生时快速、正确地解决问题。记住,冲突是团队协作中的正常现象,关键是建立好的流程和工具来处理它们。

Cherry-pick挑选提交与异常处理

Cherry-pick基本原理

Cherry-pick是Git中一个强大的功能,允许从一个分支选择特定的提交应用到另一个分支上。与merge或rebase不同,cherry-pick只会应用选定提交的更改,而不会改变分支的整体历史结构。

Cherry-pick的工作机制

1
2
3
4
5
6
7
8
graph LR
A[源分支] --> B[选择提交]
B --> C[应用到目标分支]
D[目标分支] --> E[新提交]
C --> E

F[原提交: abc123] --> G[新提交: def456]
G --> H[相同内容, 不同SHA]

技术原理详解

1
2
3
4
5
6
7
8
9
10
11
12
13
# Cherry-pick的三步过程
# 1. 计算目标提交相对于其父提交的差异(patch)
# 2. 将这个差异应用到当前分支的HEAD
# 3. 创建一个新的提交对象

# 查看提交的具体变更
git show <commit-hash>
# 等同于
git diff <commit-hash>~1 <commit-hash>

# Cherry-pick实际上执行的操作
git diff <commit-hash>~1 <commit-hash> | git apply
git commit -c <commit-hash> # 复制提交信息

Cherry-pick使用场景详解

1. 热修复场景(最常用)

场景描述:生产环境发现严重bug,需要立即修复,但develop分支已经有很多未发布的新功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 初始状态
# main: A---B---C (生产环境)
# develop: A---B---C---D---E---F---G (包含未发布功能)
# |
# bug修复

# 1. 在develop分支修复bug
git checkout develop
# 修复bug...
git add .
git commit -m "fix: resolve critical payment processing bug"
# 现在G是bug修复提交

# 2. 将修复应用到main分支
git checkout main
git cherry-pick G
# 创建新提交H,内容与G相同但SHA不同

# 结果:
# main: A---B---C---H (包含bug修复)
# develop: A---B---C---D---E---F---G (原始修复)

完整操作流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 步骤1: 在功能分支修复问题
git checkout develop
git pull origin develop

# 修复代码
echo "fixed payment bug" >> payment.js
git add payment.js
git commit -m "fix(payment): resolve null pointer exception in checkout

- Add null check for payment object
- Handle edge case when user cancels payment
- Add unit tests for error scenarios

Fixes #123"

# 记录提交SHA
COMMIT_SHA=$(git rev-parse HEAD)
echo "Bug fix commit: $COMMIT_SHA"

# 步骤2: 应用到生产分支
git checkout main
git pull origin main

# 执行cherry-pick
git cherry-pick $COMMIT_SHA

# 步骤3: 推送并部署
git push origin main
echo "Hot fix deployed to production"

# 步骤4: 确保develop分支同步(避免冲突)
git checkout develop
git merge main # 或者 git rebase main
git push origin develop

2. 功能分拣场景

场景描述:功能分支包含多个提交,但只需要其中某些功能。

1
2
3
4
5
6
7
8
9
10
11
12
# 功能分支包含多个提交
# feature: A---B---[C]---D---[E]---F
# | |
# 需要的 需要的

# 只选择需要的提交
git checkout main
git cherry-pick C E

# 结果:
# main: A---B---C'---E'
# feature: A---B---C---D---E---F (原分支不变)

实际操作示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 查看功能分支的提交历史
git log --oneline feature/user-management
# f1a2b3c Add user role management
# e4d5c6b Add user profile editing ← 需要
# d7e8f9a Fix user authentication bug ← 需要
# a1b2c3d Add experimental user analytics ← 不需要
# 9x8y7z6 Update user database schema

# 选择需要的提交
git checkout main
git cherry-pick d7e8f9a e4d5c6b

# 验证应用结果
git log --oneline -3
# a9b8c7d Add user profile editing
# b8c7d6e Fix user authentication bug
# original-main-commit Previous main commit

3. 版本回退特定功能

场景描述:需要从历史版本中恢复某个被误删或修改的功能。

1
2
3
4
5
6
7
8
9
10
11
12
# 历史提交中有需要恢复的功能
# main: A---B---[C]---D---E---F (当前)
# |
# 需要恢复的功能

# 恢复历史功能
git cherry-pick C

# 如果有冲突,可能需要解决
git cherry-pick C
# 解决冲突...
git cherry-pick --continue

4. 跨仓库提交迁移

场景描述:需要将一个仓库的某些提交应用到另一个仓库。

1
2
3
4
5
6
7
8
9
10
11
12
# 添加源仓库作为远程仓库
git remote add source-repo https://github.com/source/repo.git
git fetch source-repo

# 查看源仓库的提交
git log --oneline source-repo/main

# 挑选需要的提交
git cherry-pick source-repo/main~3 # 选择源仓库的第三个提交

# 清理远程仓库引用(可选)
git remote remove source-repo

Cherry-pick高级用法

1. 批量Cherry-pick

选择连续的提交范围

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 选择从A到E的所有提交(不包括A,包括E)
git cherry-pick A..E

# 选择从A到E的所有提交(包括A和E)
git cherry-pick A^..E

# 实际示例
git log --oneline feature-branch
# e1f2g3h Final feature implementation
# d4e5f6g Add feature tests
# c7d8e9f Add feature core logic
# b1a2c3d Add feature config
# a4b5c6d Start feature development

# 选择中间三个提交
git cherry-pick b1a2c3d..d4e5f6g

选择多个不连续的提交

1
2
3
4
5
6
7
8
9
10
11
# 选择多个特定提交
git cherry-pick commit1 commit2 commit3

# 使用通配符模式
git cherry-pick feature-branch~5 feature-branch~3 feature-branch~1

# 从文件读取提交列表
echo "commit1" > commits.txt
echo "commit2" >> commits.txt
echo "commit3" >> commits.txt
git cherry-pick $(cat commits.txt)

2. 交互式Cherry-pick

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 进入交互模式,可以编辑提交信息
git cherry-pick -e <commit-hash>

# 只应用更改,不自动提交
git cherry-pick -n <commit-hash>
# 手动检查和修改
git status
git diff --cached
# 满意后提交
git commit

# 记录原始提交信息
git cherry-pick -x <commit-hash>
# 会在提交信息末尾添加:(cherry picked from commit <original-hash>)

3. Cherry-pick策略选项

1
2
3
4
5
6
7
# 使用不同的合并策略
git cherry-pick -X ours <commit-hash> # 冲突时优先当前分支
git cherry-pick -X theirs <commit-hash> # 冲突时优先cherry-pick的内容

# 指定主线(用于合并提交)
git cherry-pick -m 1 <merge-commit> # 选择合并提交的第一个父提交的更改
git cherry-pick -m 2 <merge-commit> # 选择合并提交的第二个父提交的更改

Cherry-pick异常处理详解

1. 冲突处理

冲突发生的原因

  • 目标文件在两个分支中都被修改
  • 上下文发生变化导致patch无法干净应用
  • 文件被重命名或删除

冲突处理流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 执行cherry-pick遇到冲突
git cherry-pick abc123
# error: could not apply abc123... commit message
# hint: after resolving the conflicts, mark the corrected paths
# hint: with 'git add <paths>' or 'git rm <paths>'
# hint: and commit the result with 'git commit'

# 1. 查看冲突状态
git status
# On branch main
# You are currently cherry-picking commit abc123.
# (fix conflicts and run "git cherry-pick --continue")
# (use "git cherry-pick --abort" to cancel the cherry-pick operation)
#
# Unmerged paths:
# both modified: src/app.js

# 2. 查看冲突内容
git diff
# <<<<<<< HEAD
# current branch content
# =======
# cherry-picked content
# >>>>>>> abc123... commit message

# 3. 解决冲突(三种方式)

# 方式A: 手动编辑解决
vim src/app.js
# 编辑文件,解决冲突
git add src/app.js

# 方式B: 使用合并工具
git mergetool
git add src/app.js

# 方式C: 选择一方的版本
git checkout --ours src/app.js # 保留当前分支版本
# 或
git checkout --theirs src/app.js # 使用cherry-pick版本
git add src/app.js

# 4. 继续cherry-pick
git cherry-pick --continue

# 或者放弃cherry-pick
git cherry-pick --abort

处理复杂冲突的策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 分析冲突原因
echo "=== 冲突分析 ==="
echo "原始提交: $(git show --no-patch --format='%h %s' CHERRY_PICK_HEAD)"
echo "目标分支: $(git branch --show-current)"
echo "冲突文件:"
git diff --name-only --diff-filter=U

# 查看三方差异
git show CHERRY_PICK_HEAD -- conflicted-file.js # 要应用的更改
git show HEAD -- conflicted-file.js # 当前版本
git show $(git merge-base HEAD CHERRY_PICK_HEAD) -- conflicted-file.js # 共同祖先

# 智能冲突解决
for file in $(git diff --name-only --diff-filter=U); do
echo "处理冲突文件: $file"
# 检查冲突类型
if git diff --check $file 2>/dev/null; then
echo " - 空白字符冲突,可自动修复"
git diff --ignore-space-change $file
else
echo " - 内容冲突,需要手动处理"
git mergetool $file
fi
done

2. 常见异常情况处理

异常1: 空提交问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 当cherry-pick的更改已经存在时
git cherry-pick abc123
# The previous cherry-pick is now empty, possibly due to conflict resolution.
# If you wish to commit it anyway, use:
# git commit --allow-empty

# 处理方案:
# 方案A: 允许空提交(保持记录)
git commit --allow-empty

# 方案B: 跳过此提交
git cherry-pick --skip

# 方案C: 检查是否确实需要此更改
git show abc123 # 查看原始更改
git diff HEAD~1..HEAD # 查看当前更改

异常2: 提交依赖问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 当cherry-pick的提交依赖其他提交时
git cherry-pick def456
# error: could not apply def456... commit message
# hint: This commit depends on changes from commit abc123

# 解决方案:
# 方案A: 按依赖顺序cherry-pick
git cherry-pick abc123 def456

# 方案B: 使用三方合并策略
git cherry-pick -X patience def456

# 方案C: 手动应用更改
git show def456 --format="" | git apply
git commit -c def456

异常3: 二进制文件冲突

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 处理二进制文件冲突
git cherry-pick image-update-commit
# error: Cannot merge binary files: images/logo.png (HEAD vs. image-update-commit)

# 解决方案:
# 查看两个版本
git show HEAD:images/logo.png > current-logo.png
git show image-update-commit:images/logo.png > new-logo.png

# 选择需要的版本
git checkout --ours images/logo.png # 保留当前版本
# 或
git checkout --theirs images/logo.png # 使用新版本

git add images/logo.png
git cherry-pick --continue

3. Cherry-pick中断恢复

场景:Cherry-pick过程被意外中断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 检查cherry-pick状态
git status
if git rev-parse --verify CHERRY_PICK_HEAD >/dev/null 2>&1; then
echo "Cherry-pick正在进行中"
echo "目标提交: $(git show --no-patch --format='%h %s' CHERRY_PICK_HEAD)"

# 查看已解决的文件
echo "已解决的文件:"
git diff --cached --name-only

# 查看未解决的冲突
echo "待解决的冲突:"
git diff --name-only --diff-filter=U

# 继续操作指导
echo "解决所有冲突后运行: git cherry-pick --continue"
echo "或者放弃操作: git cherry-pick --abort"
else
echo "没有进行中的cherry-pick操作"
fi

恢复脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/bin/bash
# cherry-pick-recovery.sh
echo "=== Cherry-pick恢复助手 ==="

# 检查状态
if ! git rev-parse --verify CHERRY_PICK_HEAD >/dev/null 2>&1; then
echo "❌ 没有检测到进行中的cherry-pick操作"
exit 1
fi

echo "🔍 检测到进行中的cherry-pick操作"
CHERRY_COMMIT=$(git rev-parse CHERRY_PICK_HEAD)
echo "目标提交: $(git show --no-patch --format='%C(yellow)%h%C(reset) %s' $CHERRY_COMMIT)"

# 分析冲突状态
CONFLICTS=$(git diff --name-only --diff-filter=U)
STAGED=$(git diff --cached --name-only)

if [ -n "$CONFLICTS" ]; then
echo "⚠️ 仍有未解决的冲突:"
echo "$CONFLICTS" | sed 's/^/ - /'

echo ""
echo "📝 冲突解决选项:"
echo "1. 手动编辑文件解决冲突"
echo "2. 使用merge工具: git mergetool"
echo "3. 选择一方版本:"
echo " - git checkout --ours <file> (保留当前分支)"
echo " - git checkout --theirs <file> (使用cherry-pick版本)"

elif [ -n "$STAGED" ]; then
echo "✅ 冲突已解决,已暂存文件:"
echo "$STAGED" | sed 's/^/ - /'
echo ""
echo "▶️ 运行以下命令完成cherry-pick:"
echo " git cherry-pick --continue"

else
echo "🤔 状态异常,建议重新开始:"
echo " git cherry-pick --abort"
echo " git cherry-pick $CHERRY_COMMIT"
fi

echo ""
echo "🔧 其他选项:"
echo " git cherry-pick --abort (放弃此次cherry-pick)"
echo " git cherry-pick --skip (跳过此提交)"

Cherry-pick最佳实践

1. 提交选择策略

选择原则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# ✅ 适合cherry-pick的提交特征
# - 原子性提交(一个提交只做一件事)
# - 独立性强(不依赖其他提交)
# - 影响范围小(修改文件少)

# ❌ 不适合cherry-pick的提交
# - 大型重构提交
# - 有复杂依赖的提交
# - 合并提交(除非明确知道选择哪个父提交)

# 提交质量检查脚本
check_cherry_pick_suitability() {
local commit=$1
echo "=== 检查提交 $commit 的cherry-pick适用性 ==="

# 检查修改的文件数量
local file_count=$(git show --name-only $commit | grep -v "^commit\|^Author\|^Date\|^$" | wc -l)
echo "修改文件数: $file_count"

# 检查代码行数变化
local stats=$(git show --shortstat $commit | grep -o '[0-9]\+ file\|[0-9]\+ insertion\|[0-9]\+ deletion')
echo "代码变化: $stats"

# 检查是否为合并提交
local parent_count=$(git show --format="%P" -s $commit | wc -w)
if [ $parent_count -gt 1 ]; then
echo "⚠️ 这是一个合并提交,需要指定 -m 参数"
fi

# 评估适用性
if [ $file_count -le 5 ]; then
echo "✅ 适合cherry-pick"
elif [ $file_count -le 10 ]; then
echo "⚠️ 谨慎cherry-pick,可能有冲突"
else
echo "❌ 不建议cherry-pick,影响范围太大"
fi
}

2. Cherry-pick工作流集成

团队协作中的Cherry-pick规范

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# 1. 申请cherry-pick流程
create_cherry_pick_request() {
local source_commit=$1
local target_branch=$2
local reason=$3

echo "=== Cherry-pick申请 ==="
echo "源提交: $(git show --no-patch --format='%h %s' $source_commit)"
echo "目标分支: $target_branch"
echo "申请原因: $reason"
echo "申请人: $(git config user.name)"
echo "申请时间: $(date)"

# 创建申请记录
cat > ".git/cherry-pick-request-$(date +%s).md" << EOF
# Cherry-pick申请

## 基本信息
- 源提交: $source_commit
- 目标分支: $target_branch
- 申请人: $(git config user.name) <$(git config user.email)>
- 申请时间: $(date)

## 申请原因
$reason

## 影响分析
$(git show --stat $source_commit)

## 风险评估
- [ ] 无依赖冲突
- [ ] 已通过测试
- [ ] 影响范围可控

## 审批状态
- [ ] 团队leader审批
- [ ] 技术负责人审批
EOF

echo "申请文件已创建,请提交审批"
}

# 2. 执行cherry-pick的标准流程
execute_cherry_pick() {
local commit=$1
local target_branch=$2

echo "=== 执行Cherry-pick ==="

# 准备工作
git fetch origin
git checkout $target_branch
git pull origin $target_branch

# 创建备份分支
local backup_branch="backup-$(date +%s)-$target_branch"
git checkout -b $backup_branch
git checkout $target_branch

echo "备份分支已创建: $backup_branch"

# 执行cherry-pick
echo "开始cherry-pick提交: $commit"
if git cherry-pick -x $commit; then
echo "✅ Cherry-pick成功"

# 运行测试
if command -v npm >/dev/null 2>&1; then
echo "运行测试..."
npm test || echo "⚠️ 测试失败,请检查"
fi

# 推送更改
echo "推送到远程分支..."
git push origin $target_branch

# 清理备份分支
git branch -D $backup_branch

else
echo "❌ Cherry-pick失败,请手动解决冲突"
echo "备份分支: $backup_branch"
echo "解决冲突后运行: git cherry-pick --continue"
echo "或放弃操作: git cherry-pick --abort"
fi
}

# 3. Cherry-pick记录追踪
track_cherry_pick() {
local original_commit=$1
local cherry_picked_commit=$(git rev-parse HEAD)

# 创建追踪记录
echo "$(date): $original_commit -> $cherry_picked_commit ($(git branch --show-current))" >> .git/cherry-pick-log

# 添加标签便于追踪
git tag "cherry-pick-$(date +%s)" -m "Cherry-picked from $original_commit"
}

3. 自动化Cherry-pick工具

智能Cherry-pick脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#!/bin/bash
# smart-cherry-pick.sh

set -e

# 配置
DRY_RUN=false
INTERACTIVE=false
BACKUP=true

usage() {
echo "用法: $0 [选项] <提交> [目标分支]"
echo "选项:"
echo " -d, --dry-run 模拟执行,不实际应用"
echo " -i, --interactive 交互模式"
echo " -n, --no-backup 不创建备份分支"
echo " -h, --help 显示帮助"
}

# 解析命令行参数
while [[ $# -gt 0 ]]; do
case $1 in
-d|--dry-run)
DRY_RUN=true
shift
;;
-i|--interactive)
INTERACTIVE=true
shift
;;
-n|--no-backup)
BACKUP=false
shift
;;
-h|--help)
usage
exit 0
;;
*)
if [ -z "$COMMIT" ]; then
COMMIT=$1
elif [ -z "$TARGET_BRANCH" ]; then
TARGET_BRANCH=$1
fi
shift
;;
esac
done

# 验证参数
if [ -z "$COMMIT" ]; then
echo "错误: 请指定要cherry-pick的提交"
usage
exit 1
fi

if [ -z "$TARGET_BRANCH" ]; then
TARGET_BRANCH=$(git branch --show-current)
fi

# 验证提交存在
if ! git cat-file -e "$COMMIT^{commit}" 2>/dev/null; then
echo "错误: 提交 $COMMIT 不存在"
exit 1
fi

echo "=== 智能Cherry-pick工具 ==="
echo "源提交: $(git show --no-patch --format='%C(yellow)%h%C(reset) %s' $COMMIT)"
echo "目标分支: $TARGET_BRANCH"
echo "模式: $([ "$DRY_RUN" = true ] && echo "模拟执行" || echo "实际执行")"

# 兼容性检查
echo ""
echo "🔍 执行兼容性检查..."

# 检查修改的文件
MODIFIED_FILES=$(git show --name-only $COMMIT | tail -n +2)
echo "修改的文件:"
echo "$MODIFIED_FILES" | sed 's/^/ - /'

# 检查潜在冲突
echo ""
echo "🔍 检查潜在冲突..."
CONFLICTS=0
for file in $MODIFIED_FILES; do
if git ls-tree $TARGET_BRANCH "$file" >/dev/null 2>&1; then
# 文件在目标分支存在,检查是否有冲突
if ! git merge-tree $(git merge-base $COMMIT $TARGET_BRANCH) $COMMIT $TARGET_BRANCH -- "$file" >/dev/null 2>&1; then
echo " ⚠️ $file 可能有冲突"
CONFLICTS=$((CONFLICTS + 1))
else
echo " ✅ $file 无冲突"
fi
else
echo " ➕ $file 是新文件"
fi
done

# 风险评估
echo ""
echo "📊 风险评估:"
if [ $CONFLICTS -eq 0 ]; then
echo " ✅ 低风险 - 预计无冲突"
RISK_LEVEL="LOW"
elif [ $CONFLICTS -le 2 ]; then
echo " ⚠️ 中等风险 - 可能有少量冲突"
RISK_LEVEL="MEDIUM"
else
echo " ❌ 高风险 - 预计有多处冲突"
RISK_LEVEL="HIGH"
fi

# 交互确认
if [ "$INTERACTIVE" = true ]; then
echo ""
echo "是否继续? (y/N)"
read -r CONFIRM
if [[ ! $CONFIRM =~ ^[Yy]$ ]]; then
echo "操作已取消"
exit 0
fi
fi

# 模拟执行模式
if [ "$DRY_RUN" = true ]; then
echo ""
echo "🎭 模拟执行模式 - 以下操作将会执行:"
echo "1. 切换到分支: $TARGET_BRANCH"
echo "2. 拉取最新代码"
[ "$BACKUP" = true ] && echo "3. 创建备份分支"
echo "4. 执行: git cherry-pick -x $COMMIT"
echo "5. 运行测试验证"
echo "6. 推送到远程分支"
exit 0
fi

# 实际执行
echo ""
echo "🚀 开始执行cherry-pick..."

# 切换分支
echo "1. 切换到目标分支..."
git fetch origin
git checkout $TARGET_BRANCH
git pull origin $TARGET_BRANCH

# 创建备份
if [ "$BACKUP" = true ]; then
BACKUP_BRANCH="backup-$(date +%s)-$TARGET_BRANCH"
echo "2. 创建备份分支: $BACKUP_BRANCH"
git checkout -b $BACKUP_BRANCH
git checkout $TARGET_BRANCH
fi

# 执行cherry-pick
echo "3. 执行cherry-pick..."
if git cherry-pick -x $COMMIT; then
echo "✅ Cherry-pick成功"

# 运行测试
echo "4. 运行测试验证..."
if command -v npm >/dev/null 2>&1 && [ -f package.json ]; then
if npm test; then
echo "✅ 测试通过"
else
echo "⚠️ 测试失败,请检查"
exit 1
fi
fi

# 推送
echo "5. 推送到远程分支..."
git push origin $TARGET_BRANCH

# 记录
NEW_COMMIT=$(git rev-parse HEAD)
echo "$(date): $COMMIT -> $NEW_COMMIT ($TARGET_BRANCH)" >> .git/cherry-pick-log

# 清理备份
if [ "$BACKUP" = true ]; then
git branch -D $BACKUP_BRANCH
fi

echo ""
echo "🎉 Cherry-pick完成!"
echo "新提交: $(git show --no-patch --format='%C(green)%h%C(reset) %s' $NEW_COMMIT)"

else
echo "❌ Cherry-pick失败"
if [ "$BACKUP" = true ]; then
echo "备份分支: $BACKUP_BRANCH"
fi
echo "请手动解决冲突后运行:"
echo " git cherry-pick --continue"
echo "或放弃操作:"
echo " git cherry-pick --abort"
exit 1
fi

通过这个详细的Cherry-pick章节,开发者可以全面掌握Cherry-pick的原理、使用场景、异常处理和最佳实践,确保在实际工作中能够安全、高效地使用这个强大的Git功能。

日常分支合并场景实战

场景1:功能分支合并到开发分支

最常见的日常合并场景,需要考虑代码冲突、测试验证等多个方面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# 功能分支合并标准流程
merge_feature_to_develop() {
local feature_branch=$1
local develop_branch=${2:-develop}

echo "🔄 功能分支合并流程"
echo "=================="
echo "源分支: $feature_branch"
echo "目标分支: $develop_branch"

# 1. 预合并检查
echo ""
echo "1. 📋 预合并检查..."

# 检查分支是否存在
if ! git rev-parse --verify "$feature_branch" >/dev/null 2>&1; then
echo "❌ 功能分支 $feature_branch 不存在"
return 1
fi

# 检查当前工作目录状态
if ! git diff-index --quiet HEAD --; then
echo "⚠️ 工作目录有未提交的更改,请先处理"
git status
return 1
fi

# 2. 同步最新代码
echo ""
echo "2. 🔄 同步最新代码..."
git fetch origin

# 3. 切换并更新目标分支
echo "3. 📥 更新目标分支..."
git checkout "$develop_branch"
git pull origin "$develop_branch"

# 4. 检查功能分支状态
echo ""
echo "4. 🔍 检查功能分支状态..."

# 检查功能分支是否基于最新的develop
merge_base=$(git merge-base "$develop_branch" "$feature_branch")
develop_head=$(git rev-parse "$develop_branch")

if [ "$merge_base" != "$develop_head" ]; then
echo "⚠️ 功能分支不是基于最新的 $develop_branch"
echo "💡 建议先更新功能分支:"
echo " git checkout $feature_branch"
echo " git rebase $develop_branch"

read -p "是否继续合并? (y/N): " continue_merge
if [[ ! $continue_merge =~ ^[Yy]$ ]]; then
echo "❌ 合并已取消"
return 1
fi
fi

# 5. 模拟合并测试
echo ""
echo "5. 🧪 模拟合并测试..."
if ! git merge-tree "$merge_base" "$develop_branch" "$feature_branch" >/dev/null 2>&1; then
echo "⚠️ 发现潜在冲突,需要谨慎处理"
else
echo "✅ 预测无冲突"
fi

# 6. 执行合并
echo ""
echo "6. 🔀 执行合并..."
if git merge --no-ff "$feature_branch" -m "feat: merge $feature_branch into $develop_branch

$(git log --oneline $develop_branch..$feature_branch)"; then
echo "✅ 合并成功"

# 7. 合并后验证
echo ""
echo "7. ✅ 合并后验证..."

# 运行测试
if command -v npm >/dev/null 2>&1 && [ -f package.json ]; then
echo "🧪 运行测试套件..."
if npm test; then
echo "✅ 测试通过"
else
echo "❌ 测试失败,考虑回滚合并"
echo "回滚命令: git reset --hard HEAD~1"
return 1
fi
fi

# 8. 推送并清理
echo ""
echo "8. 📤 推送并清理..."
git push origin "$develop_branch"

# 询问是否删除功能分支
read -p "是否删除功能分支 $feature_branch? (y/N): " delete_branch
if [[ $delete_branch =~ ^[Yy]$ ]]; then
git branch -d "$feature_branch"
git push origin --delete "$feature_branch"
echo "🗑️ 功能分支已删除"
fi

echo "🎉 合并流程完成!"

else
echo "❌ 合并失败,存在冲突"
echo "请解决冲突后继续..."
return 1
fi
}

# 使用示例
# merge_feature_to_develop "feature/user-auth" "develop"

场景2:紧急热修复合并

生产环境紧急问题的快速合并流程,需要特别注意安全性和速度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# 紧急热修复合并流程
emergency_hotfix_merge() {
local hotfix_branch=$1
local production_branch=${2:-main}
local develop_branch=${3:-develop}

echo "🚨 紧急热修复合并流程"
echo "===================="
echo "热修复分支: $hotfix_branch"
echo "生产分支: $production_branch"
echo "开发分支: $develop_branch"

# 1. 快速验证
echo ""
echo "1. ⚡ 快速验证..."

# 检查热修复分支
if ! git rev-parse --verify "$hotfix_branch" >/dev/null 2>&1; then
echo "❌ 热修复分支不存在"
return 1
fi

# 检查修复的有效性
echo "📝 热修复提交:"
git log --oneline "$production_branch..$hotfix_branch"

echo ""
read -p "确认这是紧急修复且已经过测试? (y/N): " confirm
if [[ ! $confirm =~ ^[Yy]$ ]]; then
echo "❌ 请先完成测试验证"
return 1
fi

# 2. 创建备份
echo ""
echo "2. 💾 创建安全备份..."
local backup_tag="backup-before-hotfix-$(date +%Y%m%d-%H%M%S)"
git tag "$backup_tag" "$production_branch"
echo "📝 备份标签: $backup_tag"

# 3. 合并到生产分支
echo ""
echo "3. 🔥 合并到生产分支..."
git checkout "$production_branch"
git pull origin "$production_branch"

if git merge --no-ff "$hotfix_branch" -m "hotfix: emergency fix from $hotfix_branch

Critical fix for production issue.
Tested and verified safe for immediate deployment.

$(git log --oneline $production_branch..$hotfix_branch)"; then
echo "✅ 生产分支合并成功"

# 立即推送
git push origin "$production_branch"
echo "📤 已推送到生产分支"

# 4. 同步到开发分支
echo ""
echo "4. 🔄 同步到开发分支..."
git checkout "$develop_branch"
git pull origin "$develop_branch"

if git merge --no-ff "$hotfix_branch" -m "hotfix: sync emergency fix to develop

Emergency fix from production has been applied to develop branch
to prevent future regressions.

$(git log --oneline $develop_branch..$hotfix_branch)"; then
echo "✅ 开发分支同步成功"
git push origin "$develop_branch"
else
echo "⚠️ 开发分支同步有冲突,需要手动处理"
echo "💡 请解决冲突后手动合并"
fi

# 5. 创建发布标签
echo ""
echo "5. 🏷️ 创建发布标签..."
local version_tag="hotfix-$(date +%Y%m%d-%H%M%S)"
git checkout "$production_branch"
git tag -a "$version_tag" -m "Hotfix release: $version_tag

Emergency fix deployed to resolve critical production issue.
"
git push origin "$version_tag"
echo "📝 发布标签: $version_tag"

# 6. 清理热修复分支
echo ""
echo "6. 🧹 清理热修复分支..."
git branch -d "$hotfix_branch"
git push origin --delete "$hotfix_branch"

echo ""
echo "🎉 紧急热修复合并完成!"
echo "📝 备份标签: $backup_tag"
echo "🏷️ 发布标签: $version_tag"
echo "🚀 可以立即部署生产环境"

else
echo "❌ 生产分支合并失败"
echo "🔙 回滚到备份: git reset --hard $backup_tag"
return 1
fi
}

场景3:版本发布分支合并

版本发布时的规范化合并流程,确保发布质量和追溯性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# 版本发布分支合并
release_branch_merge() {
local release_branch=$1
local version=${2:-$(date +%Y.%m.%d)}
local production_branch=${3:-main}
local develop_branch=${4:-develop}

echo "🚀 版本发布合并流程"
echo "=================="
echo "发布分支: $release_branch"
echo "版本号: $version"
echo "生产分支: $production_branch"
echo "开发分支: $develop_branch"

# 1. 发布前检查
echo ""
echo "1. 📋 发布前检查清单..."

checklist=(
"所有功能测试完成"
"性能测试通过"
"安全检查完成"
"文档已更新"
"版本号已确认"
"数据库迁移脚本准备就绪"
"回滚方案已准备"
)

for item in "${checklist[@]}"; do
read -p "✓ $item (y/N): " check
if [[ ! $check =~ ^[Yy]$ ]]; then
echo "❌ 检查项未完成: $item"
return 1
fi
done

# 2. 版本信息准备
echo ""
echo "2. 📝 准备版本信息..."

# 生成变更日志
local changelog_file="CHANGELOG-$version.md"
cat > "$changelog_file" << EOF
# 版本发布日志 v$version

## 发布信息
- 版本: $version
- 发布日期: $(date)
- 发布分支: $release_branch
- 发布人: $(git config user.name)

## 功能变更
$(git log --oneline $production_branch..$release_branch --grep="feat")

## Bug修复
$(git log --oneline $production_branch..$release_branch --grep="fix")

## 性能优化
$(git log --oneline $production_branch..$release_branch --grep="perf")

## 破坏性变更
$(git log --oneline $production_branch..$release_branch --grep="BREAKING")

## 代码统计
\`\`\`
$(git diff --stat $production_branch..$release_branch)
\`\`\`

## 测试报告
- [ ] 单元测试通过率: _%
- [ ] 集成测试通过率: _%
- [ ] E2E测试通过率: _%
- [ ] 性能测试结果: 满足要求

## 部署注意事项
- [ ] 数据库迁移: 需要/不需要
- [ ] 配置更新: 需要/不需要
- [ ] 服务重启: 需要/不需要
- [ ] 缓存清理: 需要/不需要

## 回滚计划
如果发布出现问题,执行以下回滚步骤:
1. 停止新版本服务
2. 恢复数据库备份(如有必要)
3. 回滚到标签: $(git describe --tags --abbrev=0 $production_branch || echo "上一个稳定版本")
4. 重启服务
5. 验证功能正常

EOF

echo "📝 变更日志已生成: $changelog_file"

# 3. 执行合并到生产分支
echo ""
echo "3. 🚀 合并到生产分支..."

git checkout "$production_branch"
git pull origin "$production_branch"

if git merge --no-ff "$release_branch" -m "release: version $version

$(cat $changelog_file)"; then
echo "✅ 生产分支合并成功"

# 4. 创建版本标签
echo ""
echo "4. 🏷️ 创建版本标签..."
git tag -a "v$version" -m "Release version $version

$(head -20 $changelog_file)"

# 5. 推送生产分支和标签
echo ""
echo "5. 📤 推送生产分支和标签..."
git push origin "$production_branch"
git push origin "v$version"

# 6. 合并回开发分支
echo ""
echo "6. 🔄 合并回开发分支..."
git checkout "$develop_branch"
git pull origin "$develop_branch"

if git merge --no-ff "v$version" -m "release: merge version $version back to develop

Merge production release v$version back to develop branch
to ensure all release changes are included in future development."; then
echo "✅ 开发分支合并成功"
git push origin "$develop_branch"
else
echo "⚠️ 开发分支合并有冲突,需要手动处理"
fi

# 7. 清理发布分支
echo ""
echo "7. 🧹 清理发布分支..."
git branch -d "$release_branch"
git push origin --delete "$release_branch"

# 8. 生成发布报告
echo ""
echo "8. 📊 生成发布报告..."
echo "✅ 版本 $version 发布完成!"
echo "🏷️ 版本标签: v$version"
echo "📝 变更日志: $changelog_file"
echo "🚀 可以开始部署到生产环境"

else
echo "❌ 生产分支合并失败"
return 1
fi
}

合并问题快速诊断

合并问题分类与解决

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# 合并问题诊断工具
diagnose_merge_issues() {
echo "🔍 Git合并问题诊断工具"
echo "====================="

# 1. 检查当前Git状态
echo "1. 📋 检查当前状态..."

# 检查是否在合并过程中
if git rev-parse --verify MERGE_HEAD >/dev/null 2>&1; then
echo "🔄 检测到正在进行的合并操作"
diagnose_active_merge
return 0
fi

# 检查是否在rebase过程中
if [ -d ".git/rebase-merge" ] || [ -d ".git/rebase-apply" ]; then
echo "🔄 检测到正在进行的rebase操作"
diagnose_active_rebase
return 0
fi

# 检查是否在cherry-pick过程中
if git rev-parse --verify CHERRY_PICK_HEAD >/dev/null 2>&1; then
echo "🍒 检测到正在进行的cherry-pick操作"
diagnose_active_cherry_pick
return 0
fi

# 2. 常规问题诊断
echo ""
echo "2. 🔍 常规问题诊断..."

# 检查工作目录状态
if ! git diff-index --quiet HEAD --; then
echo "⚠️ 工作目录有未提交的更改"
echo "未提交的文件:"
git status --porcelain
echo ""
echo "解决方案:"
echo "1. 提交更改: git add . && git commit -m 'WIP: save changes'"
echo "2. 暂存更改: git stash"
echo "3. 丢弃更改: git checkout -- ."
fi

# 检查分支状态
local current_branch=$(git branch --show-current)
echo ""
echo "当前分支: $current_branch"

# 检查是否有未推送的提交
local unpushed=$(git log --oneline @{u}..HEAD 2>/dev/null | wc -l)
if [ "$unpushed" -gt 0 ]; then
echo "📤 有 $unpushed 个未推送的提交"
echo "建议先推送: git push"
fi

# 检查是否落后于远程
local behind=$(git log --oneline HEAD..@{u} 2>/dev/null | wc -l)
if [ "$behind" -gt 0 ]; then
echo "📥 落后远程分支 $behind 个提交"
echo "建议先同步: git pull"
fi

echo ""
echo "3. 🛠️ 常见问题修复建议..."
suggest_common_fixes
}

# 诊断正在进行的合并
diagnose_active_merge() {
echo ""
echo "🔄 合并状态诊断"
echo "==============="

# 显示合并信息
local merge_msg=$(cat .git/MERGE_MSG 2>/dev/null || echo "无合并信息")
echo "合并信息: $merge_msg"

# 显示冲突文件
local conflicts=$(git diff --name-only --diff-filter=U)
if [ -n "$conflicts" ]; then
echo ""
echo "🔥 冲突文件:"
echo "$conflicts" | sed 's/^/ - /'

echo ""
echo "📊 冲突统计:"
for file in $conflicts; do
local conflict_count=$(grep -c "<<<<<<< " "$file" 2>/dev/null || echo "0")
echo " $file: $conflict_count 个冲突"
done

echo ""
echo "🛠️ 解决步骤:"
echo "1. 逐个编辑冲突文件"
echo "2. 删除冲突标记 <<<<<<<, =======, >>>>>>>"
echo "3. git add <resolved-file>"
echo "4. git commit (完成合并)"
echo ""
echo "或者:"
echo "- 中止合并: git merge --abort"

else
echo "✅ 没有冲突文件"
echo "可以提交合并: git commit"
fi
}

# 诊断正在进行的rebase
diagnose_active_rebase() {
echo ""
echo "🔄 Rebase状态诊断"
echo "================"

# 检查rebase类型
if [ -d ".git/rebase-merge" ]; then
echo "类型: 交互式rebase"
local current_patch=$(cat .git/rebase-merge/msgnum 2>/dev/null || echo "0")
local total_patches=$(cat .git/rebase-merge/end 2>/dev/null || echo "0")
echo "进度: $current_patch/$total_patches"

# 显示当前处理的提交
local current_commit=$(cat .git/rebase-merge/stopped-sha 2>/dev/null || echo "unknown")
if [ "$current_commit" != "unknown" ]; then
echo "当前提交: $(git show --no-patch --format='%h %s' $current_commit)"
fi

elif [ -d ".git/rebase-apply" ]; then
echo "类型: 应用式rebase"
local current_patch=$(cat .git/rebase-apply/next 2>/dev/null || echo "0")
local total_patches=$(cat .git/rebase-apply/last 2>/dev/null || echo "0")
echo "进度: $current_patch/$total_patches"
fi

# 检查冲突
local conflicts=$(git diff --name-only --diff-filter=U)
if [ -n "$conflicts" ]; then
echo ""
echo "🔥 冲突文件:"
echo "$conflicts" | sed 's/^/ - /'

echo ""
echo "🛠️ 解决步骤:"
echo "1. 解决冲突文件"
echo "2. git add <resolved-file>"
echo "3. git rebase --continue"
echo ""
echo "或者:"
echo "- 跳过当前提交: git rebase --skip"
echo "- 中止rebase: git rebase --abort"
fi
}

# 常见问题修复建议
suggest_common_fixes() {
echo "📝 常见合并问题及解决方案:"
echo ""

echo "🔸 问题1: 合并后测试失败"
echo " 解决方案:"
echo " - git reset --hard HEAD~1 # 撤销合并"
echo " - 修复问题后重新合并"
echo ""

echo "🔸 问题2: 错误的合并提交"
echo " 解决方案:"
echo " - git reset --hard HEAD~1 # 如果未推送"
echo " - git revert -m 1 <merge-commit> # 如果已推送"
echo ""

echo "🔸 问题3: 合并历史混乱"
echo " 解决方案:"
echo " - 使用 git log --graph --oneline 查看历史"
echo " - 考虑使用 git rebase 整理历史"
echo ""

echo "🔸 问题4: 大量冲突"
echo " 解决方案:"
echo " - git merge --abort # 中止当前合并"
echo " - git rebase origin/main # 先变基到最新"
echo " - 分批处理冲突"
echo ""

echo "🔸 问题5: 二进制文件冲突"
echo " 解决方案:"
echo " - git checkout --ours <file> # 保留当前版本"
echo " - git checkout --theirs <file> # 使用目标版本"
echo " - 手动选择正确版本"
}

# 合并回滚工具
rollback_merge() {
local merge_commit=${1:-HEAD}

echo "🔙 合并回滚工具"
echo "=============="

# 检查是否为合并提交
local parent_count=$(git show --format="%P" -s "$merge_commit" | wc -w)
if [ "$parent_count" -le 1 ]; then
echo "❌ $merge_commit 不是合并提交"
return 1
fi

echo "🔍 合并提交信息:"
git show --no-patch --format="提交: %h%nAuthor: %an <%ae>%nDate: %ad%nMessage: %s" "$merge_commit"

echo ""
echo "📊 合并影响的文件:"
git show --name-only --format="" "$merge_commit"

echo ""
echo "🔙 回滚选项:"
echo "1. 撤销合并 (如果未推送)"
echo "2. 反向合并 (如果已推送)"
echo "3. 只查看,不执行"

read -p "请选择 (1-3): " choice

case $choice in
1)
echo "⚠️ 即将执行: git reset --hard $merge_commit~1"
read -p "确认继续? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
git reset --hard "$merge_commit~1"
echo "✅ 合并已撤销"
fi
;;
2)
echo "⚠️ 即将执行: git revert -m 1 $merge_commit"
read -p "确认继续? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
git revert -m 1 "$merge_commit"
echo "✅ 已创建反向提交"
fi
;;
3)
echo "👀 仅查看模式,未执行任何操作"
;;
esac
}

通过这些详细的日常工作规范、分支合并场景和问题处理方法,开发者可以更有效地处理日常Git操作,减少错误,提高团队协作效率。这些实用的脚本和流程可以直接应用到实际工作中,帮助建立标准化的开发流程。

代码审查最佳实践

Pull Request规范

PR标题和描述模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
## PR标题格式
feat(scope): brief description of changes

## PR描述模板
### 🎯 变更目的
简要说明这个PR的目的和解决的问题

### 📝 变更内容
- [ ] 添加了XX功能
- [ ] 修复了XX问题
- [ ] 重构了XX模块
- [ ] 更新了XX文档

### 🧪 测试情况
- [ ] 单元测试通过
- [ ] 集成测试通过
- [ ] 手动测试通过
- [ ] 性能测试通过(如适用)

### 📸 截图(如适用)
![功能截图](url)

### 🔗 相关链接
- 关联Issue: #123
- 设计文档: [链接]
- API文档: [链接]

### ⚠️ 注意事项
- 这个变更需要数据库迁移
- 需要更新环境变量配置
- 破坏性变更说明

代码审查清单

功能性审查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 审查前的本地检查
git fetch origin
git checkout feature/new-feature
git merge origin/main # 确保能正常合并

# 运行测试套件
npm test
npm run lint
npm run build

# 功能验证
# 1. 功能是否按需求实现?
# 2. 边界条件是否考虑?
# 3. 错误处理是否完善?
# 4. 性能是否有影响?

代码质量审查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// ✅ 好的代码示例
function calculateOrderTotal(items, discounts = []) {
if (!Array.isArray(items) || items.length === 0) {
throw new Error('Items array is required and cannot be empty');
}

const subtotal = items.reduce((sum, item) => {
return sum + (item.price * item.quantity);
}, 0);

const totalDiscount = discounts.reduce((sum, discount) => {
return sum + calculateDiscount(subtotal, discount);
}, 0);

return Math.max(0, subtotal - totalDiscount);
}

// ❌ 需要改进的代码
function calc(items, disc) {
let total = 0;
for(let i = 0; i < items.length; i++) {
total += items[i].price * items[i].qty;
}
// 缺少错误处理、注释和类型检查
return total;
}

审查工具集成

GitHub Actions自动检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# .github/workflows/pr-checks.yml
name: PR Quality Checks
on:
pull_request:
branches: [main, develop]

jobs:
quality-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run linter
run: npm run lint

- name: Run tests
run: npm test -- --coverage

- name: Check test coverage
uses: codecov/codecov-action@v3

- name: Security audit
run: npm audit --audit-level high

版本发布管理

语义化版本控制

版本号规则

1
2
3
4
5
6
7
8
9
10
11
主版本号.次版本号.修订号 (MAJOR.MINOR.PATCH)

示例:
1.0.0 → 1.0.1 (向后兼容的bug修复)
1.0.1 → 1.1.0 (向后兼容的新功能)
1.1.0 → 2.0.0 (不向后兼容的重大更改)

预发布版本:
1.0.0-alpha.1 (内部测试版)
1.0.0-beta.1 (公开测试版)
1.0.0-rc.1 (发布候选版)

自动化版本管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 使用npm version管理版本
npm version patch # 1.0.0 → 1.0.1
npm version minor # 1.0.1 → 1.1.0
npm version major # 1.1.0 → 2.0.0

# 自动创建tag和commit
git config --global push.followTags true

# 发布脚本示例
#!/bin/bash
# release.sh
VERSION_TYPE=${1:-patch}

# 确保在main分支
git checkout main
git pull origin main

# 运行测试
npm test || exit 1

# 更新版本号
npm version $VERSION_TYPE

# 推送tag
git push origin main --tags

# 触发部署流程
echo "Release completed. Version $(npm -s run env echo '$npm_package_version') tagged and pushed."

发布分支管理

Release分支工作流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1. 创建发布分支
git checkout develop
git pull origin develop
git checkout -b release/v1.2.0

# 2. 发布准备
# - 更新版本号
# - 更新CHANGELOG.md
# - 修复发布相关的bug
# - 进行最终测试

# 3. 完成发布
git checkout main
git merge --no-ff release/v1.2.0
git tag -a v1.2.0 -m "Release version 1.2.0"

# 4. 回合到develop
git checkout develop
git merge --no-ff release/v1.2.0

# 5. 清理发布分支
git branch -d release/v1.2.0
git push origin --delete release/v1.2.0

CHANGELOG维护

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# CHANGELOG.md
## [1.2.0] - 2024-01-15

### Added
- 用户头像上传功能
- 邮箱验证机制
- 多语言支持框架

### Changed
- 优化登录流程UX
- 升级React到18.2.0
- 改进错误提示信息

### Fixed
- 修复密码重置邮件发送问题
- 解决Safari浏览器兼容性问题
- 修复内存泄漏问题

### Security
- 修复XSS漏洞
- 加强API访问控制

### Removed
- 移除过时的IE11支持

应急处理与代码恢复

快速回滚策略

生产环境紧急回滚

1
2
3
4
5
6
7
8
9
10
11
12
# 场景1:最新部署有问题,需要立即回滚
git checkout main
git reset --hard v1.1.0 # 回滚到上一个稳定版本
git push --force-with-lease origin main

# 场景2:保持历史记录的安全回滚
git revert HEAD # 创建一个反向提交
git push origin main

# 场景3:部分功能回滚
git revert <feature-merge-commit> -m 1
git push origin main

分支误删恢复

1
2
3
4
5
6
7
8
# 使用reflog找回删除的分支
git reflog --all | grep "branch-name"
# 找到分支最后的commit hash
git checkout -b recovered-branch <commit-hash>

# 从远程恢复已删除的分支
git fetch origin
git checkout -b recovered-branch origin/branch-name

数据恢复技巧

提交恢复方案

1
2
3
4
5
6
7
8
9
10
11
12
# 1. 使用reflog恢复本地提交
git reflog
git reset --hard HEAD@{2}

# 2. 从远程仓库恢复
git fetch origin
git reset --hard origin/main

# 3. 恢复未提交的更改
git fsck --lost-found
ls .git/lost-found/other/
git show <dangling-commit-hash>

文件级恢复

1
2
3
4
5
6
7
8
9
10
# 恢复误删的文件
git checkout HEAD -- deleted-file.txt
git checkout <commit-hash> -- path/to/file

# 从其他分支恢复文件
git checkout feature/branch -- src/component.js

# 恢复到特定时间点的文件
git log --oneline -- path/to/file
git checkout <commit-hash>~1 -- path/to/file

应急处理流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
flowchart TD
A[发现问题] --> B{问题严重程度}
B -->|严重| C[立即回滚]
B -->|一般| D[创建hotfix分支]

C --> E[通知团队]
C --> F[记录问题]
C --> G[制定修复计划]

D --> H[快速修复]
H --> I[测试验证]
I --> J[部署修复]

G --> K[修复后测试]
K --> L[重新部署]

性能优化与大型项目管理

大型仓库优化

部分克隆策略

1
2
3
4
5
6
7
8
9
10
11
# 只克隆最近的提交历史
git clone --depth 1 https://github.com/large-repo.git

# 后续需要时获取更多历史
git fetch --unshallow

# 稀疏检出特定目录
git config core.sparseCheckout true
echo "frontend/*" > .git/info/sparse-checkout
echo "!frontend/node_modules/*" >> .git/info/sparse-checkout
git read-tree -m -u HEAD

Git LFS大文件管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 安装并初始化LFS
git lfs install

# 配置要跟踪的文件类型
git lfs track "*.psd"
git lfs track "*.zip"
git lfs track "*.mp4"
git lfs track "design-assets/*"

# .gitattributes会自动创建
cat .gitattributes
# *.psd filter=lfs diff=lfs merge=lfs -text
# *.zip filter=lfs diff=lfs merge=lfs -text

# 正常提交,LFS会自动处理大文件
git add design.psd
git commit -m "Add design assets"

性能配置优化

Git配置调优

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 启用多线程处理
git config --global pack.threads 0
git config --global index.threads 0

# 优化网络传输
git config --global http.postBuffer 1048576000
git config --global http.version HTTP/2

# 启用文件系统缓存 (Windows)
git config --global core.fscache true
git config --global core.preloadindex true

# 配置压缩级别
git config --global core.compression 6
git config --global pack.compression 6

# 自动垃圾回收优化
git config --global gc.auto 256
git config --global gc.autopacklimit 4

仓库维护脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash
# optimize-repo.sh
echo "开始优化Git仓库..."

# 清理无用文件
git clean -fd

# 垃圾回收
git gc --aggressive --prune=now

# 重新打包
git repack -ad

# 验证仓库完整性
git fsck --full

# 显示优化结果
echo "优化前后对比:"
git count-objects -vH

echo "仓库优化完成!"

Git Hooks自动化

客户端Hooks

pre-commit质量检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/sh
# .git/hooks/pre-commit

echo "Running pre-commit checks..."

# 1. 代码格式检查
npm run lint
if [ $? -ne 0 ]; then
echo "❌ Lint check failed"
exit 1
fi

# 2. 单元测试
npm run test:unit
if [ $? -ne 0 ]; then
echo "❌ Unit tests failed"
exit 1
fi

# 3. 检查提交文件大小
for file in $(git diff --cached --name-only); do
if [ -f "$file" ]; then
size=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null || echo 0)
if [ $size -gt 5242880 ]; then # 5MB
echo "❌ File $file is larger than 5MB"
echo "Consider using Git LFS for large files"
exit 1
fi
fi
done

echo "✅ Pre-commit checks passed"

commit-msg规范检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/sh
# .git/hooks/commit-msg

commit_regex='^(feat|fix|docs|style|refactor|perf|test|chore|ci)(\(.+\))?: .{1,50}'

if ! grep -qE "$commit_regex" "$1"; then
echo "❌ Invalid commit message format!"
echo ""
echo "Format: <type>[optional scope]: <description>"
echo ""
echo "Types:"
echo " feat: 新功能"
echo " fix: Bug修复"
echo " docs: 文档更新"
echo " style: 代码格式"
echo " refactor: 重构"
echo " perf: 性能优化"
echo " test: 测试"
echo " chore: 构建/工具"
echo " ci: CI配置"
echo ""
echo "Example: feat(auth): add login validation"
exit 1
fi

echo "✅ Commit message format is valid"

服务端Hooks

pre-receive分支保护

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/sh
# hooks/pre-receive

protected_branches="main master develop"

while read oldrev newrev refname; do
branch=$(echo $refname | sed -e 's,.*/\(.*\),\1,')

for protected in $protected_branches; do
if [ "$branch" = "$protected" ]; then
echo "❌ Direct push to $protected branch is not allowed"
echo "Please use Pull Request workflow"
exit 1
fi
done
done

Hooks管理工具

使用husky统一管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
"pre-push": "npm run test"
}
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write",
"git add"
],
"*.{css,scss,less}": [
"stylelint --fix",
"prettier --write",
"git add"
]
}
}

常见问题解决方案

Git状态异常恢复

工作区状态问题

问题1:误删除文件恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# 文件恢复工具集
recover_deleted_files() {
echo "🔍 文件恢复工具"
echo "=============="

echo "1. 📋 检查删除状态..."

# 检查工作区中被删除的文件
deleted_files=$(git status --porcelain | grep "^ D" | awk '{print $2}')
if [ -n "$deleted_files" ]; then
echo "🗑️ 工作区中被删除的文件:"
echo "$deleted_files" | sed 's/^/ - /'
echo ""
echo "恢复方法:"
echo "git checkout HEAD -- <filename> # 恢复单个文件"
echo "git checkout HEAD -- . # 恢复所有删除的文件"
fi

# 检查暂存区中被删除的文件
staged_deleted=$(git status --porcelain | grep "^D " | awk '{print $2}')
if [ -n "$staged_deleted" ]; then
echo "📦 暂存区中被删除的文件:"
echo "$staged_deleted" | sed 's/^/ - /'
echo ""
echo "恢复方法:"
echo "git reset HEAD -- <filename> # 撤销删除暂存"
echo "git checkout HEAD -- <filename> # 恢复文件内容"
fi

# 检查已提交但被删除的文件
echo ""
echo "2. 🔍 从历史版本恢复文件..."

read -p "输入要恢复的文件名 (留空跳过): " filename
if [ -n "$filename" ]; then
echo "📈 文件 $filename 的历史版本:"
git log --oneline --follow -- "$filename" | head -10
echo ""
read -p "输入要恢复的提交hash (留空使用最新): " commit_hash

if [ -n "$commit_hash" ]; then
git checkout "$commit_hash" -- "$filename"
echo "✅ 文件已从 $commit_hash 恢复"
else
# 查找文件最后存在的提交
last_commit=$(git log -1 --format="%H" --follow -- "$filename")
if [ -n "$last_commit" ]; then
git checkout "$last_commit" -- "$filename"
echo "✅ 文件已从最后存在的版本恢复: $last_commit"
else
echo "❌ 找不到文件历史记录"
fi
fi
fi
}

# 批量文件恢复
batch_file_recovery() {
echo "📁 批量文件恢复工具"
echo "=================="

# 显示所有可恢复的文件
echo "1. 📋 扫描可恢复的文件..."

# 使用git fsck查找悬空对象
echo "🔍 查找悬空的文件对象..."
git fsck --lost-found 2>/dev/null | grep "dangling blob" | while read line; do
blob_hash=$(echo "$line" | awk '{print $3}')
echo "发现悬空文件对象: $blob_hash"

# 尝试恢复文件内容
mkdir -p .git/recovered
git show "$blob_hash" > ".git/recovered/$blob_hash.txt" 2>/dev/null
done

echo ""
echo "2. 📂 检查恢复目录..."
if [ -d ".git/recovered" ]; then
echo "恢复的文件保存在: .git/recovered/"
ls -la .git/recovered/
echo ""
echo "💡 请检查这些文件,确认需要的内容后手动复制到正确位置"
else
echo "📭 没有找到可恢复的文件"
fi
}

问题2:工作区混乱重置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# 工作区清理工具
cleanup_working_directory() {
echo "🧹 工作区清理工具"
echo "================"

# 1. 显示当前状态
echo "1. 📋 当前工作区状态:"
git status --porcelain

echo ""
echo "2. 🔧 清理选项:"
echo "1. 丢弃所有未暂存的更改"
echo "2. 丢弃所有更改(包括暂存的)"
echo "3. 清理未跟踪的文件"
echo "4. 完全重置到HEAD状态"
echo "5. 交互式清理"
echo "6. 取消操作"

read -p "请选择 (1-6): " choice

case $choice in
1)
echo "⚠️ 即将丢弃所有未暂存的更改"
read -p "确认继续? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
git checkout -- .
echo "✅ 未暂存的更改已丢弃"
fi
;;
2)
echo "⚠️ 即将丢弃所有更改(包括暂存的)"
read -p "确认继续? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
git reset --hard HEAD
echo "✅ 所有更改已丢弃"
fi
;;
3)
echo "📁 未跟踪的文件:"
git clean -n
echo ""
read -p "确认删除这些文件? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
git clean -f
echo "✅ 未跟踪的文件已清理"
fi
;;
4)
echo "⚠️ 即将完全重置到HEAD状态"
echo "这将删除所有更改和未跟踪的文件"
read -p "确认继续? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
git reset --hard HEAD
git clean -fd
echo "✅ 工作区已完全重置"
fi
;;
5)
echo "🔍 交互式清理模式"
echo "逐一确认每个文件的处理方式..."

# 处理修改的文件
git diff --name-only | while read file; do
echo ""
echo "📝 文件: $file"
echo "变更内容:"
git diff "$file" | head -10
echo ""
echo "处理选项: (k)eep保留 (d)iscard丢弃 (s)kip跳过"
read -p "请选择: " action
case $action in
d) git checkout -- "$file"; echo "✅ 已丢弃 $file 的更改" ;;
k) echo "✅ 保留 $file 的更改" ;;
s) echo "⏭️ 跳过 $file" ;;
esac
done
;;
6)
echo "❌ 操作已取消"
;;
esac
}

提交历史问题

问题3:提交信息错误修复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# 提交信息修复工具
fix_commit_messages() {
echo "📝 提交信息修复工具"
echo "=================="

echo "1. 🔍 检查最近的提交..."
git log --oneline -10

echo ""
echo "2. 🛠️ 修复选项:"
echo "1. 修改最后一次提交信息"
echo "2. 修改最后一次提交内容和信息"
echo "3. 修改历史提交信息(交互式rebase)"
echo "4. 批量修改提交信息"
echo "5. 取消操作"

read -p "请选择 (1-5): " choice

case $choice in
1)
echo "📝 修改最后一次提交信息"
echo "当前提交信息: $(git log -1 --pretty=format:'%s')"
read -p "输入新的提交信息: " new_message
if [ -n "$new_message" ]; then
git commit --amend -m "$new_message"
echo "✅ 提交信息已更新"
fi
;;
2)
echo "📝 修改最后一次提交的内容和信息"
echo "💡 请先暂存要修改的文件,然后继续"
read -p "按回车键继续..."
git commit --amend
echo "✅ 提交已更新"
;;
3)
echo "📝 交互式修改历史提交"
read -p "输入要修改的提交数量: " count
if [[ $count =~ ^[0-9]+$ ]] && [ $count -gt 0 ]; then
echo "💡 在编辑器中将要修改的提交从'pick'改为'reword'"
git rebase -i HEAD~$count
else
echo "❌ 无效的提交数量"
fi
;;
4)
echo "📝 批量修改提交信息"
echo "使用格式: 's/old_pattern/new_pattern/g'"
read -p "输入sed替换表达式: " pattern
if [ -n "$pattern" ]; then
echo "⚠️ 这将修改历史,请确保分支未被其他人使用"
read -p "确认继续? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
git filter-branch -f --msg-filter "sed '$pattern'" HEAD~10..HEAD
echo "✅ 批量修改完成"
fi
fi
;;
5)
echo "❌ 操作已取消"
;;
esac
}

问题4:提交顺序错误调整

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# 提交顺序调整工具
reorder_commits() {
echo "🔄 提交顺序调整工具"
echo "=================="

echo "1. 📋 最近的提交历史:"
git log --oneline -10 --graph

echo ""
echo "2. 🔧 调整方法:"
echo "1. 交互式rebase调整顺序"
echo "2. 移动单个提交到其他位置"
echo "3. 压缩多个提交"
echo "4. 拆分一个提交"
echo "5. 取消操作"

read -p "请选择 (1-5): " choice

case $choice in
1)
read -p "输入要调整的提交数量: " count
if [[ $count =~ ^[0-9]+$ ]] && [ $count -gt 0 ]; then
echo "💡 在编辑器中调整提交顺序(剪切粘贴行)"
git rebase -i HEAD~$count
fi
;;
2)
echo "📝 移动单个提交"
read -p "输入要移动的提交hash: " commit_hash
read -p "输入目标位置的提交hash: " target_hash

if [ -n "$commit_hash" ] && [ -n "$target_hash" ]; then
echo "⚠️ 这将重写历史,请确保安全"
read -p "确认继续? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
# 使用cherry-pick实现移动
echo "🔄 执行提交移动..."
git rebase --onto "$target_hash" "$commit_hash^" "$commit_hash"
fi
fi
;;
3)
echo "📦 压缩多个提交"
read -p "输入要压缩的提交数量: " count
if [[ $count =~ ^[0-9]+$ ]] && [ $count -gt 1 ]; then
echo "💡 在编辑器中将要压缩的提交标记为'squash'"
git rebase -i HEAD~$count
fi
;;
4)
echo "✂️ 拆分提交"
echo "💡 这将重置到要拆分的提交,然后您可以分别提交更改"
read -p "输入要拆分的提交hash: " commit_hash

if [ -n "$commit_hash" ]; then
echo "⚠️ 工作区将被重置,请确保已保存当前工作"
read -p "确认继续? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
git reset --mixed "$commit_hash^"
echo "✅ 提交已重置,现在可以分别提交更改"
git status
fi
fi
;;
5)
echo "❌ 操作已取消"
;;
esac
}

远程仓库问题

推送问题解决

问题5:推送被拒绝处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# 推送问题诊断和解决
resolve_push_issues() {
echo "📤 推送问题解决工具"
echo "=================="

# 1. 诊断推送失败原因
echo "1. 🔍 诊断推送失败原因..."

local current_branch=$(git branch --show-current)
local remote_branch="origin/$current_branch"

# 检查远程分支是否存在
if ! git rev-parse --verify "$remote_branch" >/dev/null 2>&1; then
echo "📝 远程分支不存在,这是首次推送"
echo "解决方案: git push -u origin $current_branch"
return 0
fi

# 检查是否有未合并的远程更改
local behind_count=$(git rev-list --count HEAD.."$remote_branch")
local ahead_count=$(git rev-list --count "$remote_branch"..HEAD)

echo "📊 分支状态分析:"
echo " - 本地领先: $ahead_count 个提交"
echo " - 本地落后: $behind_count 个提交"

if [ "$behind_count" -gt 0 ]; then
echo "🔄 本地分支落后于远程分支"
echo ""
echo "📝 远程新增的提交:"
git log --oneline HEAD.."$remote_branch"

echo ""
echo "2. 🛠️ 解决方案:"
echo "1. 先拉取再推送 (merge策略)"
echo "2. 变基后推送 (rebase策略)"
echo "3. 强制推送 (危险操作)"
echo "4. 查看详细差异"
echo "5. 取消操作"

read -p "请选择 (1-5): " choice

case $choice in
1)
echo "🔄 执行 pull + push 策略..."
if git pull origin "$current_branch"; then
echo "✅ 拉取成功,现在推送..."
git push origin "$current_branch"
else
echo "❌ 拉取时发生冲突,请手动解决"
fi
;;
2)
echo "🔄 执行 rebase + push 策略..."
if git pull --rebase origin "$current_branch"; then
echo "✅ 变基成功,现在推送..."
git push origin "$current_branch"
else
echo "❌ 变基时发生冲突,请手动解决"
fi
;;
3)
echo "⚠️ 强制推送将覆盖远程历史"
echo "🚨 这可能影响其他开发者的工作"
read -p "确认执行强制推送? (yes/N): " confirm
if [ "$confirm" = "yes" ]; then
git push --force-with-lease origin "$current_branch"
echo "✅ 强制推送完成"
else
echo "❌ 强制推送已取消"
fi
;;
4)
echo "📊 详细差异分析:"
echo ""
echo "🔹 本地独有的提交:"
git log --oneline "$remote_branch"..HEAD
echo ""
echo "🔹 远程独有的提交:"
git log --oneline HEAD.."$remote_branch"
echo ""
echo "🔹 文件级差异:"
git diff HEAD "$remote_branch" --stat
;;
5)
echo "❌ 操作已取消"
;;
esac
else
echo "✅ 本地分支是最新的,推送应该成功"
echo "💡 如果推送仍然失败,可能是权限问题或网络问题"
fi
}

问题6:远程分支管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# 远程分支管理工具
manage_remote_branches() {
echo "🌐 远程分支管理工具"
echo "=================="

echo "1. 📋 远程仓库状态:"
git remote -v

echo ""
echo "2. 🌿 所有分支状态:"
git branch -a

echo ""
echo "3. 🧹 清理选项:"
echo "1. 清理已删除的远程分支引用"
echo "2. 删除本地的远程跟踪分支"
echo "3. 同步远程分支信息"
echo "4. 批量删除合并后的本地分支"
echo "5. 查看分支关系"
echo "6. 取消操作"

read -p "请选择 (1-6): " choice

case $choice in
1)
echo "🧹 清理已删除的远程分支引用..."
git remote prune origin
echo "✅ 清理完成"
;;
2)
echo "📁 本地的远程跟踪分支:"
git branch -r | grep -v "HEAD"
echo ""
read -p "输入要删除的远程跟踪分支名 (如 origin/feature-name): " branch_name
if [ -n "$branch_name" ]; then
git branch -r -d "$branch_name"
echo "✅ 已删除远程跟踪分支: $branch_name"
fi
;;
3)
echo "🔄 同步远程分支信息..."
git fetch origin
git remote prune origin
echo "✅ 同步完成"
;;
4)
echo "🧹 批量删除已合并的本地分支..."
local main_branch="main"
if git show-ref --verify --quiet refs/heads/master; then
main_branch="master"
fi

echo "📝 已合并到 $main_branch 的本地分支:"
local merged_branches=$(git branch --merged "$main_branch" | grep -v "\* $main_branch\| $main_branch")

if [ -n "$merged_branches" ]; then
echo "$merged_branches"
echo ""
read -p "确认删除这些分支? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
echo "$merged_branches" | xargs -n 1 git branch -d
echo "✅ 已删除合并后的分支"
fi
else
echo "📭 没有找到已合并的分支"
fi
;;
5)
echo "🔗 分支关系图:"
git show-branch --all
echo ""
echo "📊 分支跟踪关系:"
git branch -vv
;;
6)
echo "❌ 操作已取消"
;;
esac
}

性能和大文件问题

仓库性能优化

问题7:仓库体积过大

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# 仓库大小优化工具
optimize_repository_size() {
echo "📦 仓库大小优化工具"
echo "=================="

echo "1. 📊 仓库大小分析..."

# 显示仓库总大小
local repo_size=$(du -sh .git | cut -f1)
echo "🗃️ 仓库大小: $repo_size"

# 显示对象统计
echo ""
echo "📈 对象统计:"
git count-objects -vH

# 找出大文件
echo ""
echo "2. 🔍 查找大文件..."
echo "📁 历史中的大文件 (前10个):"
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 -10 |
while read size hash path; do
echo " $(numfmt --to=iec-i --suffix=B $size) $path"
done

echo ""
echo "3. 🛠️ 优化选项:"
echo "1. 垃圾回收和压缩"
echo "2. 移除大文件历史"
echo "3. 清理reflog"
echo "4. 重新打包仓库"
echo "5. 完整优化(组合操作)"
echo "6. 取消操作"

read -p "请选择 (1-6): " choice

case $choice in
1)
echo "🧹 执行垃圾回收和压缩..."
git gc --aggressive --prune=now
echo "✅ 垃圾回收完成"

# 显示优化后的大小
echo "📊 优化后仓库大小: $(du -sh .git | cut -f1)"
;;
2)
echo "🗑️ 移除大文件历史"
read -p "输入要移除的文件路径: " file_path
if [ -n "$file_path" ]; then
echo "⚠️ 这将重写历史,请确保其他人没有基于当前历史工作"
read -p "确认继续? (yes/N): " confirm
if [ "$confirm" = "yes" ]; then
echo "🔄 正在移除文件历史..."
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch '$file_path'" \
--prune-empty --tag-name-filter cat -- --all

# 清理引用
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now

echo "✅ 文件历史已移除"
fi
fi
;;
3)
echo "🧹 清理reflog..."
git reflog expire --expire-unreachable=now --all
git gc --prune=now
echo "✅ Reflog已清理"
;;
4)
echo "📦 重新打包仓库..."
git repack -ad
echo "✅ 重新打包完成"
;;
5)
echo "🔧 执行完整优化..."
echo "步骤1: 清理reflog..."
git reflog expire --expire-unreachable=now --all

echo "步骤2: 垃圾回收..."
git gc --aggressive --prune=now

echo "步骤3: 重新打包..."
git repack -ad

echo "步骤4: 验证仓库完整性..."
git fsck --full

echo "✅ 完整优化完成"
echo "📊 优化后仓库大小: $(du -sh .git | cut -f1)"
;;
6)
echo "❌ 操作已取消"
;;
esac
}

高级故障排除

Git配置问题

问题8:配置问题诊断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# Git配置诊断工具
diagnose_git_config() {
echo "⚙️ Git配置诊断工具"
echo "=================="

echo "1. 📋 基本配置检查..."

# 检查用户配置
local user_name=$(git config user.name)
local user_email=$(git config user.email)

if [ -z "$user_name" ]; then
echo "❌ 缺少用户名配置"
echo "修复: git config --global user.name 'Your Name'"
else
echo "✅ 用户名: $user_name"
fi

if [ -z "$user_email" ]; then
echo "❌ 缺少邮箱配置"
echo "修复: git config --global user.email 'your.email@example.com'"
else
echo "✅ 邮箱: $user_email"
fi

# 检查核心配置
echo ""
echo "2. 🔧 核心配置检查..."

local autocrlf=$(git config core.autocrlf)
local editor=$(git config core.editor)
local pager=$(git config core.pager)

echo "📝 行尾处理: ${autocrlf:-未设置}"
echo "📝 默认编辑器: ${editor:-系统默认}"
echo "📝 分页器: ${pager:-默认}"

# 检查远程配置
echo ""
echo "3. 🌐 远程仓库配置..."
git remote -v

# 检查分支配置
echo ""
echo "4. 🌿 分支配置..."
git branch -vv

# 检查别名配置
echo ""
echo "5. 🔖 配置的别名..."
git config --get-regexp alias

# 配置问题修复建议
echo ""
echo "6. 🛠️ 常见配置问题修复..."
echo ""
echo "🔧 推荐的基础配置:"
echo "git config --global init.defaultBranch main"
echo "git config --global pull.rebase false"
echo "git config --global push.default simple"
echo "git config --global core.autocrlf input # Linux/Mac"
echo "git config --global core.autocrlf true # Windows"
echo ""
echo "🔧 有用的别名:"
echo "git config --global alias.st status"
echo "git config --global alias.co checkout"
echo "git config --global alias.br branch"
echo "git config --global alias.ci commit"
echo "git config --global alias.unstage 'reset HEAD --'"
echo "git config --global alias.last 'log -1 HEAD'"
echo "git config --global alias.visual '!gitk'"
}

# 一键配置修复
quick_config_fix() {
echo "⚡ Git快速配置修复"
echo "=================="

# 检查必要配置
if [ -z "$(git config user.name)" ]; then
read -p "输入用户名: " name
git config --global user.name "$name"
fi

if [ -z "$(git config user.email)" ]; then
read -p "输入邮箱: " email
git config --global user.email "$email"
fi

# 应用推荐配置
echo "🔧 应用推荐配置..."
git config --global init.defaultBranch main
git config --global pull.rebase false
git config --global push.default simple

# 根据操作系统设置autocrlf
if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
git config --global core.autocrlf true
echo "✅ Windows配置已应用"
else
git config --global core.autocrlf input
echo "✅ Unix/Linux配置已应用"
fi

# 设置有用的别名
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

echo "✅ 快速配置修复完成"
}

应急处理工具包

完整的应急恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# Git应急恢复工具包
emergency_recovery_toolkit() {
echo "🚨 Git应急恢复工具包"
echo "===================="

echo "1. 🔍 快速状态诊断..."

# 检查仓库状态
if ! git status >/dev/null 2>&1; then
echo "❌ 当前目录不是Git仓库"
return 1
fi

echo "✅ Git仓库状态正常"

# 检查是否有进行中的操作
local in_progress=""

if git rev-parse --verify MERGE_HEAD >/dev/null 2>&1; then
in_progress="merge"
elif [ -d ".git/rebase-merge" ] || [ -d ".git/rebase-apply" ]; then
in_progress="rebase"
elif git rev-parse --verify CHERRY_PICK_HEAD >/dev/null 2>&1; then
in_progress="cherry-pick"
fi

if [ -n "$in_progress" ]; then
echo "⚠️ 检测到进行中的 $in_progress 操作"
fi

echo ""
echo "2. 🛠️ 应急处理选项:"
echo "1. 中止所有进行中的操作"
echo "2. 创建当前状态的安全备份"
echo "3. 恢复到最近的安全状态"
echo "4. 从reflog恢复丢失的提交"
echo "5. 完整的仓库健康检查"
echo "6. 重置到远程分支状态"
echo "7. 导出当前工作内容"
echo "8. 取消操作"

read -p "请选择 (1-8): " choice

case $choice in
1)
echo "🛑 中止所有进行中的操作..."

if [ "$in_progress" = "merge" ]; then
git merge --abort
echo "✅ 合并操作已中止"
elif [ "$in_progress" = "rebase" ]; then
git rebase --abort
echo "✅ 变基操作已中止"
elif [ "$in_progress" = "cherry-pick" ]; then
git cherry-pick --abort
echo "✅ Cherry-pick操作已中止"
else
echo "📭 没有检测到进行中的操作"
fi
;;
2)
echo "💾 创建安全备份..."
local backup_branch="emergency-backup-$(date +%Y%m%d-%H%M%S)"
local current_branch=$(git branch --show-current)

git branch "$backup_branch"
git tag "backup-$(date +%Y%m%d-%H%M%S)"

echo "✅ 备份创建完成:"
echo " 分支备份: $backup_branch"
echo " 标签备份: backup-$(date +%Y%m%d-%H%M%S)"

# 如果有未提交的更改,也进行暂存
if ! git diff-index --quiet HEAD --; then
git stash push -m "Emergency backup stash $(date)"
echo " 工作区备份: 已暂存到stash"
fi
;;
3)
echo "🔙 恢复到最近的安全状态..."
echo "📋 选择恢复目标:"
echo "1. 恢复到最近的提交"
echo "2. 恢复到最近的标签"
echo "3. 恢复到远程分支状态"

read -p "请选择: " restore_choice
case $restore_choice in
1)
git reset --hard HEAD
git clean -fd
echo "✅ 已恢复到最近的提交"
;;
2)
local latest_tag=$(git describe --tags --abbrev=0 2>/dev/null)
if [ -n "$latest_tag" ]; then
echo "最近的标签: $latest_tag"
read -p "确认恢复到此标签? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
git reset --hard "$latest_tag"
git clean -fd
echo "✅ 已恢复到标签: $latest_tag"
fi
else
echo "❌ 没有找到任何标签"
fi
;;
3)
local current_branch=$(git branch --show-current)
git fetch origin
git reset --hard "origin/$current_branch"
git clean -fd
echo "✅ 已恢复到远程分支状态"
;;
esac
;;
4)
echo "🔍 从reflog恢复丢失的提交..."
echo "📈 最近的reflog记录:"
git reflog --oneline -20

read -p "输入要恢复的提交hash: " commit_hash
if [ -n "$commit_hash" ]; then
local recovery_branch="recovered-$(date +%Y%m%d-%H%M%S)"
git checkout -b "$recovery_branch" "$commit_hash"
echo "✅ 已恢复提交到新分支: $recovery_branch"
fi
;;
5)
echo "🔍 完整的仓库健康检查..."
echo "1. 检查对象完整性..."
git fsck --full

echo ""
echo "2. 检查引用完整性..."
git for-each-ref --format="%(refname) %(objectname)"

echo ""
echo "3. 检查工作区状态..."
git status

echo ""
echo "4. 检查远程连接..."
git remote -v
git ls-remote origin >/dev/null && echo "✅ 远程连接正常" || echo "❌ 远程连接失败"
;;
6)
echo "🌐 重置到远程分支状态..."
local current_branch=$(git branch --show-current)
echo "⚠️ 这将丢失所有本地更改"
read -p "确认重置到 origin/$current_branch? (yes/N): " confirm

if [ "$confirm" = "yes" ]; then
git fetch origin
git reset --hard "origin/$current_branch"
git clean -fd
echo "✅ 已重置到远程分支状态"
fi
;;
7)
echo "📤 导出当前工作内容..."
local export_dir="git-export-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$export_dir"

# 导出工作区文件
rsync -av --exclude='.git' . "$export_dir/"

# 导出Git信息
git status > "$export_dir/git-status.txt"
git log --oneline -20 > "$export_dir/git-log.txt"
git diff > "$export_dir/git-diff.txt"
git diff --cached > "$export_dir/git-diff-staged.txt"

echo "✅ 工作内容已导出到: $export_dir"
;;
8)
echo "❌ 操作已取消"
;;
esac
}

通过这些详细的问题解决方案,开发者可以有效应对Git使用过程中遇到的各种问题,从简单的工作区清理到复杂的历史重写,从配置问题到性能优化,都有相应的工具和方法。这些脚本不仅提供了解决方案,还包含了详细的诊断步骤,帮助理解问题的根本原因。

团队开发最佳实践总结

建立团队规范

  1. 统一工作流程:选择适合团队的Git工作流
  2. 制定分支规范:明确分支命名和生命周期
  3. 规范提交信息:使用Conventional Commits标准
  4. 建立审查机制:强制代码审查和自动化检查
  5. 定期维护仓库:清理无用分支和优化性能

持续改进策略

1
2
3
4
5
6
graph LR
A[团队规范制定] --> B[工具和流程实施]
B --> C[团队培训]
C --> D[实践中反馈]
D --> E[持续优化]
E --> A

关键成功因素

  1. 自动化优先:使用hooks和CI/CD减少人为错误
  2. 文档完善:维护清晰的工作流程文档
  3. 工具统一:团队使用相同的Git配置和工具
  4. 经验分享:定期分享Git技巧和最佳实践
  5. 应急预案:建立代码恢复和问题处理流程

通过遵循这些规范和最佳实践,团队可以显著提高开发效率,减少协作冲突,确保代码质量,并建立可持续的开发流程。记住,Git不仅是版本控制工具,更是团队协作的基础设施。

Cursor帮我写的-Git工作实战:规范与最佳实践指南

https://blogs.52fx.biz/posts/1025129566.html

作者

eyiadmin

发布于

2025-06-03

更新于

2025-06-03

许可协议

评论