4.1 贮藏(Stash)
贮藏是Git中一个非常实用的功能,它可以暂时保存当前未提交的修改,让你可以切换到其他分支工作,之后再恢复这些修改。
核心场景:
- 正在进行中的工作需要中断,切换到其他任务
- 分支切换前需要保存当前未完成的修改
- 尝试一些实验性修改,不想提交
基本操作:
# 保存当前工作区和暂存区的修改
git stash save "临时保存工作"
# 查看贮藏列表
git stash list
# 应用最近一次贮藏
git stash apply
# 应用并删除贮藏
git stash pop
# 删除最近一次贮藏
git stash drop
# 删除所有贮藏
git stash clear
案例:
# 在feature分支上工作,尚未完成
git add file1.txt
git status # 显示已暂存和未暂存的修改
# 突然需要切换到master分支处理紧急问题
git stash save "未完成的功能" # 保存当前修改
git checkout master # 切换到master分支
# 处理完紧急问题后,回到feature分支
git checkout feature
git stash pop # 恢复并删除贮藏
高级用法:
# 保存工作区修改但不保存暂存区
git stash push -k
# 应用指定的贮藏
git stash apply stash@{1}
# 查看贮藏的差异
git stash show -p stash@{0}
4.2 重置(Reset)与回退
Git的reset命令可以让你回退到历史的某个状态,但使用时需要谨慎,因为它可能会丢失未提交的修改。
三种重置模式:
- --soft:只移动HEAD指针,不改变暂存区和工作区
- --mixed(默认):移动HEAD指针并重置暂存区,但不改变工作区
- --hard:移动HEAD指针、重置暂存区和工作区,彻底丢弃未提交的修改
案例1:回退到上一个提交
# 回退到上一个提交,保留工作区修改
git reset HEAD^
# 回退到上一个提交,彻底丢弃修改
git reset --hard HEAD^
案例2:撤销错误的提交
# 错误地提交了一些内容
git commit -m "错误提交"
# 回退到上一个正确的提交,但保留修改
git reset HEAD^
# 重新提交正确的内容
git add .
git commit -m "正确提交"
找回丢失的提交:
如果不小心使用了git reset --hard,可以通过reflog找回丢失的提交:
# 查看引用日志
git reflog
# 恢复到指定的提交
git reset --hard <commit-hash>
4.3 变基(Rebase)
变基是将一个分支的修改应用到另一个分支的另一种方式,与merge不同,它会创建一个线性的提交历史。
基本操作:
# 在feature分支上
git rebase master # 将master的修改应用到feature分支
# 等价于
git checkout feature
git rebase master
变基 vs 合并:
- 合并(Merge):创建一个新的"合并提交",保留分支历史
- 变基(Rebase):将提交历史重新排列,创建线性历史
案例:
# 在feature分支上开发
git checkout -b feature
# 此时master分支有了新提交
git checkout master
git pull
# 将feature分支变基到最新的master
git checkout feature
git rebase master
# 推送到远程(第一次推送到新分支需要-f)
git push -f origin feature
交互式变基:
# 修改最近3个提交
git rebase -i HEAD~3
变基注意事项:
- 不要对已经推送到远程的分支进行变基(会导致提交历史混乱)
- 变基过程中可能会出现冲突,需要手动解决
4.4 子模块(Submodule)
子模块允许你在一个Git仓库中包含另一个Git仓库,适合管理大型项目中的独立组件。
基本操作:
# 添加子模块
git submodule add <repository-url> <path>
# 克隆包含子模块的仓库
git clone --recursive <repository-url>
# 初始化和更新子模块
git submodule init
git submodule update
# 更新子模块到最新版本
git submodule update --remote
案例:
# 添加子模块
git submodule add https://github.com/example/library.git lib/library
# 克隆包含子模块的项目
git clone --recursive https://github.com/example/main-project.git
# 更新子模块
cd main-project
git submodule update --remote
4.5 高级日志查看
Git的日志命令非常强大,可以通过各种参数定制输出格式。
常用参数:
# 简洁的单行输出
git log --oneline
# 显示文件改动
git log -p
# 统计改动
git log --stat
# 图形化输出
git log --graph --oneline --decorate
# 按作者过滤
git log --author="张三"
# 按日期过滤
git log --since="2023-01-01" --until="2023-12-31"
# 查看文件历史
git log --follow -p -- file.txt
自定义日志格式:
git log --format="%h %ad | %s%d [%an]" --date=short
4.6 别名与配置
Git允许你创建自定义命令别名,提高工作效率。
全局配置:
# 设置常用别名
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.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
# 使用vim作为默认编辑器
git config --global core.editor "vim"
案例:
# 使用别名
git co feature/branch # 相当于 git checkout feature/branch
git lg # 查看美观的日志
4.7 钩子(Hooks)
Git钩子是在特定事件发生前或发生后自动执行的脚本,可用于自动化工作流程。
常见钩子:
- pre-commit:提交前执行,可用于代码检查
- commit-msg:提交信息验证
- pre-push:推送前执行,可用于运行测试
- post-merge:合并后执行,可用于安装依赖
案例:创建pre-commit钩子检查代码格式
# 进入.git/hooks目录
cd .git/hooks
# 创建pre-commit文件
touch pre-commit
chmod +x pre-commit
# 编辑pre-commit文件,添加检查逻辑
#!/bin/sh
echo "正在检查代码格式..."
# 这里可以添加代码格式化或测试命令
4.8 总结
通过本章的学习,你已经掌握了Git的高级操作:
- 使用贮藏(Stash)临时保存未完成的工作
- 重置(Reset)和回退到历史状态
- 变基(Rebase)创建线性提交历史
- 子模块(Submodule)管理项目中的外部依赖
- 高级日志查看和自定义
- 配置别名提高效率
- 使用钩子自动化工作流程
在下一章中,我们将学习Git在团队协作中的最佳实践,包括工作流程、代码评审和常见问题解决。