Git 是一个功能强大的版本控制系统,提供了丰富的工具和命令来优化开发工作流程。本章将介绍一些 Git 的高效技巧和常见问题的解决方案,包括交互式变更、垃圾回收、版本库拆分、提交恢复、SVN 转换技巧、文件管理等,帮助开发者更高效地使用 Git。

21.1 对脏的工作目录灵活进行交互式变更

当工作目录中有未提交的修改时,可以使用 git stash 临时保存更改,以便进行其他操作。

21.1.1 暂存未提交的更改

  1. git stash

然后可以安全地切换分支、拉取最新代码等。

21.1.2 交互式选择暂存的部分更改

  1. git add -p

Git 会逐个显示未提交的代码块,并询问是否暂存 (y 暂存, n 跳过, s 分割, e 编辑)。

21.1.3 恢复暂存的更改

  1. git stash pop

或者仅应用暂存但不删除存储:

  1. git stash apply

21.2 删除残余的编辑器文件

当使用 IDE(如 VS Code、JetBrains IDE、Vim)时,Git 可能会检测到不必要的临时文件。这些文件应添加到 .gitignore 中,例如:

  1. # VS Code
  2. .vscode/
  3. # JetBrains
  4. .idea/
  5. # Vim
  6. *.swp

可以使用 git clean 删除未被 Git 追踪的文件:

  1. git clean -df

⚠️ 注意:此命令会永久删除未追踪的文件,请谨慎使用!


21.3 垃圾回收

Git 会保留所有的对象(提交、树、文件等),即使它们已被删除。可以使用 git gc 进行垃圾回收,以减少 Git 仓库的体积:

  1. git gc --aggressive --prune=now

查看当前存储的松散对象:

  1. git count-objects -vH

21.4 拆分版本库

如果希望从现有版本库中拆分一个子项目到新的 Git 仓库,可以使用 git filter-repo

  1. git filter-repo --path subproject/ --target-directory new-repo/

然后进入 new-repo/ 目录,初始化新的 Git 仓库:

  1. cd new-repo
  2. git init
  3. git remote add origin <new-repo-url>
  4. git push -u origin main

21.5 恢复提交的小贴士

如果不小心 git reset --hard,可以使用 git reflog 恢复丢失的提交:

  1. git reflog

找到丢失提交的哈希,然后执行:

  1. git checkout -b recovery-branch <commit-hash>

21.6 转换 Subversion 的技巧

21.6.1 迁移建议

迁移 SVN 到 Git 时,可以使用 git svn clone 逐步迁移:

  1. git svn clone --stdlayout https://svn.example.com/repo project

21.6.2 删除 SVN 导入后的 trunk

当从 SVN 迁移到 Git 时,通常会保留 trunk/ 目录,但在 Git 中不需要,可以使用 git filter-repo 删除它:

  1. git filter-repo --path trunk/ --invert-paths

21.6.3 删除 SVN 提交 ID

SVN 迁移后,Git 提交信息中可能会带有 git-svn-id,可以使用 git filter-repo 去除:

  1. git filter-repo --replace-text <(echo "git-svn-id==>REMOVE<")

21.7 操作来自两个版本库的分支

在 Git 里,可以从两个不同的远程仓库拉取分支。例如:

  1. git remote add upstream https://github.com/example/repo.git
  2. git fetch upstream
  3. git checkout -b feature upstream/main

21.8 从上游变基中恢复

如果上游仓库发生了变基(git rebase),可能会导致本地提交丢失。这时可以使用 git reflog 找回:

  1. git reflog
  2. git checkout <commit-hash>

21.9 定制 Git 命令

Git 允许用户创建自定义命令。例如,可以创建 git undo 命令来撤销最近一次提交:

  1. echo -e "#!/bin/bash\n git reset --soft HEAD~1" > ~/bin/git-undo
  2. chmod +x ~/bin/git-undo

现在可以使用 git undo 来撤销提交:

  1. git undo

21.10 快速查看变更

快速查看最近 5 次提交的变更内容:

  1. git log -p -5

仅查看哪些文件发生了变更:

  1. git diff --name-only HEAD~1

21.11 清理

清理未被 Git 追踪的文件和目录(⚠️ 无法恢复):

  1. git clean -fd

21.12 使用 git grep 来搜索版本库

Git 内置的 grep 命令可以高效搜索代码:

  1. git grep "TODO"

仅搜索特定分支:

  1. git grep "BUGFIX" main

21.13 更新和修改 ref

重命名分支:

  1. git branch -m old-branch new-branch

21.14 跟踪和忽略的文件

有时需要让 Git 忽略已提交的文件(但不删除它们):

  1. git update-index --assume-unchanged <file>

如果想要 Git 重新跟踪该文件:

  1. git update-index --no-assume-unchanged <file>

21.15 保留但不追踪文件

如果希望保留文件但 Git 不再跟踪,可以使用 git rm --cached

  1. git rm --cached secret-config.json
  2. git commit -m "停止追踪 secret-config.json"

然后添加到 .gitignore 以防止将来再次提交:

  1. echo "secret-config.json" >> .gitignore
  2. git add .gitignore
  3. git commit -m "添加 secret-config.json 到 .gitignore"

21.16 你来过这里吗?

如果想要知道一个提交是否在当前分支中,可以使用 git branch --contains

  1. git branch --contains <commit-hash>

如果想知道某个提交是否已经合并到 main,可以使用:

  1. git branch --merged | grep main

结论

本章介绍了一系列 Git 提示、技巧和技术,包括:

  • 优化日常 Git 操作(交互式暂存、垃圾回收、快速查看变更)。
  • 高级管理(拆分版本库、恢复提交、定制 Git 命令)。
  • SVN 迁移技巧(删除 trunk、清理 SVN ID)。

掌握这些技巧,可以极大地提高 Git 的使用效率,使版本控制更加灵活和高效。