Git实战宝典:从翻车现场到绝地求生

Git实战宝典:从翻车现场到绝地求生

学了前四期,你已经掌握了Git的理论和最佳实践。但现实世界不是童话,翻车才是常态。

这一期,我们直面那些让新手崩溃、让老手头秃的真实场景。每个问题都有救,只要你知道正确的方法。

紧急救援手册

场景1:commit后发现写错了

情况A:还没push

# 修改最后一次提交
git commit --amend -m "正确的提交信息"

# 或者补充文件
git add forgotten-file.txt
git commit --amend --no-edit

情况B:已经push了

# 如果只有你在这个分支工作
git commit --amend -m "正确的提交信息"
git push --force-with-lease

# 如果有别人也在用这个分支,不要用amend!
# 而是创建新的修复提交
git revert HEAD
git push

场景2:提交到错误的分支

# 你在main分支提交了,但应该在feature分支

# 1. 撤销当前提交,保留改动
git reset HEAD~1 --soft

# 2. 切换到正确的分支
git checkout feature-branch

# 3. 重新提交
git commit -m "feat: xxx"

场景3:需要撤回多个提交

# 撤回最近3个提交,保留改动在工作区
git reset HEAD~3

# 撤回最近3个提交,保留改动在暂存区
git reset HEAD~3 --soft

# 撤回最近3个提交,丢弃所有改动(危险!)
git reset HEAD~3 --hard

场景4:误删分支

# 查找被删分支的最后一个提交
git reflog

# 找到类似这样的记录
# abc1234 HEAD@{5}: checkout: moving from feature-xxx to main

# 重建分支
git checkout -b feature-xxx abc1234

场景5:误删文件

# 删除了工作区文件,想恢复
git checkout -- deleted-file.txt
# 或
git restore deleted-file.txt

# 删除了文件并已提交
git checkout HEAD~1 -- deleted-file.txt
git commit -m "restore: 恢复误删文件"

场景6:需要撤销已push的提交

# 方法1:revert(推荐,不改写历史)
git revert 
git push

# 方法2:reset + force push(危险,仅限个人分支)
git reset --hard 
git push --force-with-lease

revert创建一个新提交来撤销改动,不改写历史,适合已push的提交。reset回退指针,会改写历史。

场景7:merge出错想重来

# 合并过程中发现冲突太多,想放弃
git merge --abort

# 已经合并完成但想撤销
git reset --hard HEAD~1

场景8:需要合并特定的几个提交

# 方法1:cherry-pick
git cherry-pick   

# 方法2:交互式rebase
git rebase -i 
# 在编辑器中把不需要的提交标记为drop

历史改写

修改历史提交信息

# 修改最近3个提交的信息
git rebase -i HEAD~3

# 把要修改的提交前面的pick改成reword
# 保存后Git会逐个让你编辑提交信息

合并历史提交

git rebase -i HEAD~3

# 把后面几个提交的pick改成squash
# 保存后编辑合并后的提交信息

删除历史提交

git rebase -i HEAD~5

# 把要删除的提交改成drop

从历史中删除敏感文件

# 使用BFG Repo-Cleaner(快)
bfg --delete-files secrets.yml
git reflog expire --expire=now --all
git gc --prune=now --aggressive
git push --force

# 使用git filter-repo(现代推荐)
pip install git-filter-repo
git filter-repo --path secrets.yml --invert-paths

# 使用git filter-branch(慢,已废弃)
git filter-branch --force --index-filter \
  'git rm --cached --ignore-unmatch secrets.yml' \
  --prune-empty --tag-name-filter cat -- --all

重要:改写历史后通知所有协作者重新clone!

大文件处理

问题:仓库太大

# 查看哪些文件占用空间
git rev-list --objects --all | \
  git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
  sed -n 's/^blob //p' | \
  sort --numeric-sort --key=2 | \
  tail -20

解决方案1:Git LFS

# 安装Git LFS
brew install git-lfs  # Mac
apt install git-lfs   # Ubuntu

# 初始化
git lfs install

# 跟踪大文件
git lfs track "*.psd"
git lfs track "*.zip"
git lfs track "assets/**"

# 查看跟踪规则
git lfs track

# 提交跟踪规则
git add .gitattributes
git commit -m "chore: 配置Git LFS"

解决方案2:清理历史

# 从历史中彻底删除大文件
git filter-repo --path huge-file.zip --invert-paths

# 清理垃圾
git reflog expire --expire=now --all
git gc --prune=now --aggressive

性能优化

clone太慢

# 浅克隆(只克隆最近的历史)
git clone --depth 1 https://github.com/user/repo.git

# 单分支克隆
git clone --single-branch --branch main https://github.com/user/repo.git

# 后续获取完整历史
git fetch --unshallow

仓库太大

# 清理无用对象
git gc

# 更激进的清理
git gc --aggressive --prune=now

# 清理reflog
git reflog expire --expire=now --all
git gc --prune=now

status太慢

# 禁用文件监控(大仓库)
git config core.fsmonitor false
git config core.untrackedCache false

子模块

添加子模块

git submodule add https://github.com/user/lib.git libs/lib

克隆包含子模块的仓库

# 方法1:克隆时自动初始化
git clone --recursive https://github.com/user/repo.git

# 方法2:克隆后手动初始化
git clone https://github.com/user/repo.git
cd repo
git submodule init
git submodule update

更新子模块

# 更新到最新
git submodule update --remote

# 更新所有子模块
git submodule foreach git pull origin main

删除子模块

# 删除子模块(Git 1.8.3+)
git submodule deinit libs/lib
git rm libs/lib
rm -rf .git/modules/libs/lib

常见错误

error: Your local changes would be overwritten

# 情况1:想保留本地修改
git stash
git pull
git stash pop

# 情况2:丢弃本地修改
git reset --hard
git pull

fatal: refusing to merge unrelated histories

# 两个仓库历史不相关,需要强制合并
git pull origin main --allow-unrelated-histories

! [rejected] main -> main (non-fast-forward)

# 远程有新提交,先拉取
git pull --rebase origin main
git push origin main

fatal: Authentication failed

# 检查SSH密钥
ssh -T git@github.com

# 检查远程URL
git remote -v

# 切换到SSH
git remote set-url origin git@github.com:user/repo.git

# 或使用token
git remote set-url origin https://@github.com/user/repo.git

fatal: not a git repository

# 当前目录不在Git仓库中
# 初始化仓库
git init

# 或进入正确的目录
cd /path/to/repo

调试技巧

查看某行代码的修改历史

# 查看文件的每一行是谁在什么时候改的
git blame filename.txt

# 只看某几行
git blame -L 10,20 filename.txt

# 查看某行代码的完整历史
git log -p -S "特定代码" filename.txt

找出引入bug的提交

# 二分查找
git bisect start
git bisect bad          # 当前版本有bug
git bisect good v1.0    # v1.0版本正常
# Git会自动跳到中间提交,你测试后标记
git bisect good/bad
# 重复直到找到
git bisect reset

查看reflog(操作日志)

# 查看所有操作记录
git reflog

# 找到误删的提交
git checkout 

最佳实践总结

DO

  1. 频繁提交:小步快跑,每个逻辑改动一个提交
  2. 写好提交信息:让未来的自己和队友能看懂
  3. 先pull再push:避免不必要的冲突
  4. 使用分支:不要在main上直接开发
  5. 定期备份:重要分支推送到远程

DON’T

  1. 不要push --force:除非你确定自己在做什么
  2. 不要commit敏感信息:密码、密钥一旦push就很难彻底清除
  3. 不要在公共分支rebase:会改写历史,坑队友
  4. 不要忽略.gitignore:node_modules、.env必须忽略
  5. 不要提交大文件:使用Git LFS

Git速查表

# 初始化
git init                          # 初始化仓库
git clone                    # 克隆仓库

# 日常操作
git status                        # 查看状态
git add                     # 添加到暂存区
git commit -m "message"           # 提交
git push                          # 推送
git pull                          # 拉取

# 分支操作
git branch                  # 创建分支
git checkout              # 切换分支
git checkout -b           # 创建并切换
git merge                 # 合并分支
git branch -d             # 删除分支

# 撤销操作
git checkout --             # 撤销工作区修改
git reset HEAD              # 撤销暂存
git commit --amend                # 修改最后一次提交
git revert                # 撤销提交(安全)
git reset --hard          # 回退到指定提交(危险)

# 历史查看
git log --oneline --graph         # 图形化日志
git blame                   # 查看每行修改记录
git reflog                        # 操作历史

# 暂存工作
git stash                         # 暂存当前工作
git stash pop                     # 恢复暂存

系列总结

恭喜你完成了整个Git系列!

第一期:Git基础 - 从安装到日常操作
第二期:分支管理 - 在平行宇宙中开发
第三期:团队协作 - Pull Request与代码审查
第四期:自动化 - 钩子、CI/CD与效率工具
第五期:实战宝典 - 从翻车到救命

你现在已经是Git高手了。但记住:Git只是工具,真正重要的是团队协作的规范和习惯。工具再好,用不好也是白搭。

保持学习,保持实践,保持分享。Git的世界还有很多宝藏等你探索。


进阶资源


恭喜!你已经掌握了Git的全部核心技能。去征服代码世界吧!

Views: 0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Index