Git高级使用技巧
掌握Git进阶功能,提升团队协作效率
Git工作流
选择合适的Git工作流对团队协作至关重要。
常见工作流: Git Flow、GitHub Flow、GitLab Flow、Trunk-based Development。
1. 分支管理策略
1.1 Git Flow
# Git Flow分支结构
main # 主分支,用于生产环境
└── develop # 开发分支,集成所有功能
├── feature/* # 功能分支,开发新功能
├── release/* # 发布分支,准备发布版本
└── hotfix/* # 热修复分支,紧急修复生产问题
# 初始化Git Flow
git flow init
# 开始新功能
git flow feature start feature-name
# 完成功能开发
git flow feature finish feature-name
# 开始发布
git flow release start 1.0.0
# 完成发布
git flow release finish 1.0.0
# 开始热修复
git flow hotfix start hotfix-name
# 完成热修复
git flow hotfix finish hotfix-name
1.2 GitHub Flow
# GitHub Flow简化流程
main # 主分支,始终可部署
└── feature/* # 功能分支,每个功能独立分支
# 基本流程
1. 从main创建功能分支
git checkout -b feature/xxx
2. 开发并提交代码
git add .
git commit -m "feat: add xxx feature"
3. 推送分支
git push origin feature/xxx
4. 创建Pull Request
# 在GitHub/GitLab上操作
5. 代码审查和讨论
6. 部署到测试环境验证
7. 合并到main分支
# 使用Squash and Merge保持提交历史整洁
8. 立即部署到生产环境
2. 高级提交操作
2.1 修改提交历史
# 修改最近一次提交
git commit --amend
# 修改提交信息
git commit --amend -m "新的提交信息"
# 添加文件到最近提交
git add forgotten-file.txt
git commit --amend --no-edit
# 交互式rebase(修改多个提交)
git rebase -i HEAD~3
# 在rebase界面中:
# pick - 保留提交
# reword - 修改提交信息
# edit - 修改提交内容
# squash - 合并到前一个提交
# fixup - 合并并丢弃提交信息
# drop - 删除提交
# 修改特定提交(如第3个)
git rebase -i HEAD~3
# 将第三行的pick改为edit,保存退出
# 修改文件后
git add .
git commit --amend
git rebase --continue
# 放弃rebase
git rebase --abort
2.2 重写历史
# 删除敏感信息(如密码)
git filter-branch --tree-filter 'rm -f config/passwords.txt' HEAD
# 修改作者信息
git filter-branch --env-filter '
OLD_EMAIL="old@example.com"
NEW_NAME="New Name"
NEW_EMAIL="new@example.com"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_COMMITTER_NAME="$NEW_NAME"
export GIT_COMMITTER_EMAIL="$NEW_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_AUTHOR_NAME="$NEW_NAME"
export GIT_AUTHOR_EMAIL="$NEW_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags
# 使用BFG工具(更高效)
java -jar bfg.jar --delete-files passwords.txt .git
git reflog expire --expire=now --all && git gc --prune=now --aggressive
# 注意:重写历史后需要强制推送
git push --force-with-lease
3. 暂存和恢复
3.1 Stash使用
# 保存当前工作
git stash
git stash save "正在开发的功能描述"
# 保存未跟踪的文件
git stash -u
git stash --include-untracked
# 保存所有文件(包括忽略的文件)
git stash -a
git stash --all
# 查看暂存列表
git stash list
# 应用暂存(不删除)
git stash apply
git stash apply stash@{2}
# 应用暂存(并删除)
git stash pop
git stash pop stash@{1}
# 删除暂存
git stash drop stash@{0}
git stash clear # 删除所有暂存
# 从暂存创建分支
git stash branch new-branch-name stash@{0}
# 查看暂存内容
git stash show -p stash@{0}
3.2 Worktree使用
# 添加工作树
git worktree add ../feature-branch feature/xxx
# 添加工作树并切换分支
git worktree add -b new-feature ../new-feature main
# 列出工作树
git worktree list
# 移除工作树
git worktree remove ../feature-branch
# 清理已删除的工作树
git worktree prune
# 锁定工作树(防止被清理)
git worktree lock ../feature-branch
# 解锁工作树
git worktree unlock ../feature-branch
4. 高级合并和变基
4.1 Rebase vs Merge
# 普通合并(保留分支历史)
git checkout main
git merge feature-branch
# 变基(线性历史)
git checkout feature-branch
git rebase main
git checkout main
git merge feature-branch
# 交互式变基
git rebase -i main
# 变基并解决冲突
git rebase main
# 遇到冲突时
git status # 查看冲突文件
# 编辑文件解决冲突
git add resolved-file.txt
git rebase --continue
# 或放弃变基
git rebase --abort
# 变基指定提交
git rebase --onto new-base old-base feature-branch
# 只变基部分提交
git rebase -i --onto main feature-branch~3 feature-branch
5. 子模块和子树
5.1 Git Submodule
# 添加子模块
git submodule add https://github.com/username/repo.git path/to/submodule
# 克隆包含子模块的项目
git clone https://github.com/username/main-repo.git
cd main-repo
git submodule init
git submodule update
# 或一次性操作
git clone --recurse-submodules https://github.com/username/main-repo.git
# 更新所有子模块
git submodule update --remote --recursive
# 进入子模块
cd path/to/submodule
git checkout main
git pull origin main
# 提交子模块更新
cd ..
git add path/to/submodule
git commit -m "更新子模块"
# 移除子模块(较复杂)
# 1. 删除子模块目录
git rm --cached path/to/submodule
rm -rf path/to/submodule
# 2. 删除.gitmodules中的对应行
# 3. 删除.git/config中的子模块配置
# 4. 删除.git/modules/path/to/submodule
# 5. 提交更改
git commit -m "移除子模块"
5.2 Git Subtree
# 添加子树
git subtree add --prefix=lib/third-party \
https://github.com/username/third-party.git main --squash
# 从子树拉取更新
git subtree pull --prefix=lib/third-party \
https://github.com/username/third-party.git main --squash
# 推送更改到子树仓库
git subtree push --prefix=lib/third-party \
https://github.com/username/third-party.git feature-branch
# 分割子树(提取目录为独立仓库)
git subtree split --prefix=lib/third-party -b split-branch
# 查看子树状态
git log --oneline --graph --decorate --all
# 子树与子模块对比
# 子树:文件在项目内,管理简单,但历史合并复杂
# 子模块:外部引用,管理复杂,但历史清晰
6. 钩子(Hooks)和配置
6.1 Git Hooks
# 客户端钩子位置
.git/hooks/
# 预提交钩子示例
#!/bin/bash
# .git/hooks/pre-commit
# 运行测试
npm test
if [ $? -ne 0 ]; then
echo "测试失败,提交被阻止"
exit 1
fi
# 代码风格检查
npm run lint
if [ $? -ne 0 ]; then
echo "代码风格检查失败"
exit 1
fi
# 提交消息格式检查
commit_msg_file=$1
commit_msg=$(cat $commit_msg_file)
if ! echo "$commit_msg" | grep -qE "^(feat|fix|docs|style|refactor|test|chore): "; then
echo "提交消息格式错误"
echo "格式应为: <type>: <description>"
echo "类型: feat, fix, docs, style, refactor, test, chore"
exit 1
fi
# 预推钩子示例
#!/bin/bash
# .git/hooks/pre-push
# 检查是否在main分支
current_branch=$(git symbolic-ref --short HEAD)
protected_branches=("main" "develop")
if [[ " ${protected_branches[@]} " =~ " ${current_branch} " ]]; then
echo "错误:不能在 $current_branch 分支直接推送"
echo "请创建Pull Request"
exit 1
fi
# 提交后钩子
#!/bin/bash
# .git/hooks/post-commit
# 自动生成changelog
npm run changelog
# 服务器端钩子(需要Git服务器支持)
# update - 验证分支更新
# pre-receive - 验证所有引用更新
# post-receive - 触发部署
6.2 Git配置优化
# 全局配置
git config --global user.name "小薛同学"
git config --global user.email "xxw11228@qq.com"
git config --global core.editor "code --wait"
git config --global core.autocrlf input # Linux/Mac
git config --global core.autocrlf true # Windows
# 别名配置
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative"
git config --global alias.prune-branches '!git fetch -p && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print $1}'"'"' | xargs git branch -D'
# 性能优化
git config --global core.preloadindex true
git config --global core.fscache true
git config --global gc.auto 256
# 差异工具配置
git config --global diff.tool vscode
git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE'
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
# 提交模板
git config --global commit.template ~/.gitmessage.txt
# 模板内容示例
# ------------------------ >8 ------------------------
# 类型: feat|fix|docs|style|refactor|test|chore
# 影响范围: module-name|global
# 关联issue: #123
# ------------------------ >8 ------------------------
#
# 简短描述(不超过50字)
#
# 详细描述(如有必要)
#
# 破坏性变更描述(如有)
#
# 测试说明
7. 团队协作最佳实践
7.1 Code Review流程
# 1. 创建功能分支
git checkout -b feature/user-authentication
# 2. 开发并提交
git add .
git commit -m "feat: add user authentication"
git commit -m "test: add authentication tests"
git commit -m "docs: update API documentation"
# 3. 同步主分支
git fetch origin
git rebase origin/main
# 4. 推送分支
git push -u origin feature/user-authentication
# 5. 创建Pull Request
# - 填写清晰的标题和描述
# - 关联相关issue
# - 添加Reviewers
# - 设置Labels
# 6. 代码审查
# - 使用建议(Suggestions)功能
# - 进行有建设性的评论
# - 及时回复评论
# 7. 修改代码
git commit --amend # 修改最近提交
git push --force-with-lease # 安全强制推送
# 8. 合并策略选择
# - Merge commit: 保留完整历史
# - Squash and merge: 整洁的历史
# - Rebase and merge: 线性历史
# 9. 清理分支
git checkout main
git pull origin main
git branch -d feature/user-authentication
git push origin --delete feature/user-authentication
7.2 大文件管理
# 使用Git LFS(大文件存储)
# 安装Git LFS
git lfs install
# 跟踪大文件类型
git lfs track "*.psd"
git lfs track "*.mp4"
git lfs track "*.zip"
# 查看跟踪规则
git lfs track
# 提交跟踪规则
git add .gitattributes
git commit -m "添加Git LFS跟踪规则"
# 推送文件
git add file.psd
git commit -m "添加设计文件"
git push origin main
# 克隆包含LFS的项目
git clone https://github.com/username/repo.git
git lfs pull
# 迁移现有仓库到LFS
git lfs migrate import --include="*.psd,*.mp4" --everything
# 检查LFS状态
git lfs status
git lfs ls-files
# 从历史中清除大文件
git filter-repo --strip-blobs-bigger-than 10M
总结
Git是一个强大的版本控制系统,掌握其高级功能可以显著提升开发效率和代码质量。关键是选择合适的工具和流程,并保持一致性。
最佳实践建议:
- 选择合适的Git工作流
- 编写有意义的提交信息
- 定期同步主分支
- 使用代码审查流程
- 配置合适的钩子和别名