Git 从入门到精通
涵盖了核心概念、常用命令、协作流程和高级技巧:
核心理念:
- 版本控制: 记录文件变化历史,可回溯到任意版本。
- 分布式: 每个开发者拥有完整的仓库副本(包括完整历史),可离线工作。
- 快照(Snapshot): Git 记录的是文件系统的快照,而非差异(虽然内部优化存储)。
- 三个区域:
- 工作目录 (Working Directory): 你实际看到和修改文件的地方。
- 暂存区 (Staging Area / Index): 一个准备区,标记了哪些修改将要被提交。
- 本地仓库 (Local Repository):
.git
目录,存储项目的完整历史、元数据(如分支、标签)。
- 三种状态:
- 已修改 (Modified): 文件在工作目录中被修改,但尚未放入暂存区。
- 已暂存 (Staged): 修改的文件已放入暂存区,等待提交。
- 已提交 (Committed): 数据已安全地保存在本地仓库中。
第一部分:入门基础 (Getting Started)
- 安装:
- 官网 (https://git-scm.com/) 下载对应操作系统的安装包。
- 安装时注意选择适合你环境的配置(如默认编辑器、PATH 环境变量)。
- 初始配置 (首次使用必做):
git config --global user.name "Your Name"
(设置用户名)git config --global user.email "your.email@example.com"
(设置邮箱)git config --global core.editor "vim"
(可选,设置默认文本编辑器,如 vscode, nano, vim)git config --list
(查看当前配置)
- 创建仓库:
- 初始化新仓库:
git init
(在当前目录创建新的空 Git 仓库) - 克隆现有仓库:
git clone <repository_url>
(将远程仓库完整复制到本地)
- 初始化新仓库:
- 基本工作流 (单兵作战):
- 修改文件: 在工作目录编辑文件 -> 状态变为
Modified
。 - 添加文件到暂存区:
git add <file_name>
或git add .
(添加所有修改/新文件) -> 状态变为Staged
。 - 提交更改:
git commit -m "Descriptive commit message"
-> 状态变为Committed
,快照存入本地仓库。 - 查看状态:
git status
(查看工作目录、暂存区状态) - 查看历史:
git log
(查看提交历史)git log --oneline
(简洁历史)git log -p
(带详细差异)
- 修改文件: 在工作目录编辑文件 -> 状态变为
- 忽略文件 (.gitignore):
- 创建
.gitignore
文件,列出不想被 Git 跟踪的文件/目录模式(如编译产物、日志、临时文件、敏感信息)。 - 规则支持通配符 (
*
,?
), 目录 (/
), 取反 (!
)。
- 创建
第二部分:分支与协作 (Branching & Collaboration)
- 分支 (Branch):
- 概念: 轻量级的可移动指针,指向某个提交。用于隔离开发(新功能、修复 Bug)、实验。
- 创建分支:
git branch <branch_name>
(基于当前提交创建新分支) - 切换分支:
git checkout <branch_name>
或git switch <branch_name>
(更新工作目录到该分支最新状态) - 创建并切换:
git checkout -b <new_branch>
或git switch -c <new_branch>
- 查看分支:
git branch
(列出本地分支,*
表示当前分支)git branch -a
(列出所有分支,包括远程) - 删除分支:
git branch -d <branch_name>
(安全删除,需合并过)git branch -D <branch_name>
(强制删除未合并分支)
- 远程仓库 (Remote):
- 概念: 托管在网络上的仓库(如 GitHub, GitLab, Bitbucket),用于团队协作和备份。
- 查看远程:
git remote -v
- 添加远程:
git remote add <remote_name> <repository_url>
(通常远程默认名为origin
) - 拉取更新:
git fetch <remote_name>
(从远程下载最新数据到本地仓库的remote/<remote_name>/<branch>
,不自动合并) - 拉取并合并:
git pull <remote_name> <remote_branch>
(相当于git fetch
+git merge origin/<remote_branch>
) - 推送更新:
git push <remote_name> <local_branch>:<remote_branch>
(将本地分支推送到远程分支,常用git push origin main
) - 跟踪分支:
git push -u origin <local_branch>
(首次推送时设置上游跟踪,后续可直接git push
)
- 合并 (Merge):
- 概念: 将一个分支的更改集成到另一个分支。
- 操作: 切换到目标分支 (如
main
),执行git merge <source_branch>
。 - 结果: 创建一个新的“合并提交”(Merge Commit),该提交有两个父提交。
- 冲突解决: 当同一文件的同一区域在不同分支有不同修改时发生。需手动编辑文件(Git 会标记冲突内容),
git add
解决后的文件,然后git commit
完成合并。
- 变基 (Rebase):
- 概念: 将当前分支的提交“重放”在目标分支(通常是更上游的分支,如
main
)的最新提交之上。 - 操作: 切换到要变基的分支 (如
feature
),执行git rebase <target_branch>
(如main
)。 - 结果: 历史线变得线性、整洁,避免了不必要的合并提交。本质是重写历史!
- 适用场景: 整理本地分支历史、保持特性分支更新。
- 黄金法则: 永远不要变基已经推送到远程仓库且与他人共享的分支! (会导致协作混乱)
- 交互式变基:
git rebase -i <commit>
(如HEAD~3
),可编辑、压缩(squash)、删除、重排提交。强大但需谨慎。
- 概念: 将当前分支的提交“重放”在目标分支(通常是更上游的分支,如
- 协作工作流:
- 集中式工作流 (Centralized): 类似 SVN,所有人向一个
main
分支提交。简单但易冲突。 - 功能分支工作流 (Feature Branch): 每个新功能/修复在独立分支开发,完成后通过 Pull Request (PR) / Merge Request (MR) 请求合并到
main
。主流协作方式。 - Gitflow: 更复杂的分支模型(
main
,develop
,feature
,release
,hotfix
分支),适合有严格发布流程的项目。学习成本稍高。 - Forking Workflow: 常用于开源项目。贡献者 Fork 主仓库到自己的账号下,在 Fork 出的仓库开发,然后向主仓库发起 PR。
- 集中式工作流 (Centralized): 类似 SVN,所有人向一个
第三部分:进阶技巧 (Advanced Techniques)
- 撤销更改:
- 丢弃工作目录修改:
git restore <file>
(Git 2.23+) 或git checkout -- <file>
- 取消暂存:
git restore --staged <file>
(Git 2.23+) 或git reset HEAD <file>
- 撤销最近提交:
- 创建新提交撤销:
git revert <commit>
(安全,推荐用于已推送的提交) - 移除提交 (重写历史):
git reset [--soft|--mixed|--hard] <commit>
(危险! 慎用于已推送提交)--soft
:移动HEAD
和分支指针,保留修改在暂存区。--mixed
(默认):移动指针,保留修改在工作目录(未暂存)。--hard
:移动指针,丢弃工作目录和暂存区所有修改。
- 创建新提交撤销:
- 丢弃工作目录修改:
- 储藏更改 (Stash):
- 概念: 临时保存工作目录和暂存区的修改,以便切换分支处理其他事情。
- 储藏:
git stash
或git stash push -m "message"
- 查看储藏列表:
git stash list
- 应用储藏:
git stash apply [stash@{n}]
(不删除储藏项)git stash pop [stash@{n}]
(应用并删除) - 删除储藏:
git stash drop [stash@{n}]
- 标签 (Tag):
- 概念: 给某个重要的提交(如发布版本)打上永久标记。
- 创建轻量标签:
git tag <tagname>
(指向特定提交) - 创建附注标签:
git tag -a <tagname> -m "message"
(包含打标者、日期、信息,是完整的 Git 对象) - 查看标签:
git tag
git show <tagname>
- 推送标签:
git push origin <tagname>
或git push origin --tags
(推送所有标签)
- 子模块 (Submodule):
- 概念: 将一个 Git 仓库作为另一个仓库的子目录嵌套使用。
- 添加子模块:
git submodule add <repository_url> <path>
- 克隆包含子模块的仓库:
git clone --recurse-submodules <repository_url>
或git clone
后git submodule update --init --recursive
- 更新子模块: 进入子模块目录手动
git pull
或git submodule update --remote
- 注意: 管理较复杂,需谨慎使用。
- 二分查找 (Bisect):
- 概念: 自动化地使用二分搜索定位引入 Bug 的提交。
- 开始:
git bisect start
- 标记坏提交:
git bisect bad [commit]
(通常当前HEAD
是坏的) - 标记好提交:
git bisect good <commit>
(已知没有 Bug 的提交) - 测试与标记: Git 会自动检出中间提交,你测试并标记
git bisect good
或git bisect bad
,重复直到找到第一个坏提交。 - 结束:
git bisect reset
- 钩子 (Hooks):
- 概念: 在特定 Git 操作(如
commit
,push
,pre-receive
)前后自动触发的自定义脚本(位于.git/hooks/
)。 - 常见用途: 代码风格检查、测试运行、提交信息格式校验、部署触发。
- 注意: 钩子脚本不随仓库分发(
.git/hooks/
不被跟踪),需其他机制共享(如模板)。
- 概念: 在特定 Git 操作(如
- Reflog:
- 概念: 记录本地仓库中
HEAD
和分支指针移动的历史日志,是后悔药。 - 查看:
git reflog
或git reflog show <branch>
- 用途: 恢复误删的分支、找回丢失的提交(即使
reset --hard
过)、理解操作历史。
- 概念: 记录本地仓库中
第四部分:精通与最佳实践 (Mastery & Best Practices)
- 理解 Git 内部原理 (提升故障诊断能力):
- 对象: Blob (文件内容), Tree (目录结构), Commit (提交信息、父提交指针、Tree), Tag (标签)。
- 引用 (Refs): 分支 (
refs/heads/
), 标签 (refs/tags/
), 远程跟踪分支 (refs/remotes/
),HEAD
(指向当前检出的提交或分支)。 - 存储: 对象存储在
.git/objects/
中,通过 SHA-1 哈希值寻址。 - 打包: Git 自动打包松散对象以节省空间 (
git gc
)。
- 编写优秀的提交信息 (Commit Message):
- 格式:
- 第一行:简短摘要 (<50字符),动词开头,说明做了什么。
- 空一行。
- 详细描述:解释为什么做这些改动,解决了什么问题,可能的影响。使用现在时态。
- 参考规范: Conventional Commits。
- 格式:
- 高效工作流:
- 频繁提交: 小步快跑,每个提交聚焦一个逻辑更改。
- 善用分支: 隔离开发,避免在主分支直接修改。
- 保持主分支稳定:
main
/master
分支应总是可部署状态。 - Code Review: 使用 PR/MR 进行代码审查是提高质量的关键。
- 定期拉取更新: 减少合并冲突。
- 清理分支: 合并/废弃后及时删除本地和远程分支。
- 处理大型仓库/文件:
- Git LFS (Large File Storage): 将大文件(二进制、媒体)存储在外部服务器,仓库中只存指针。
- 浅克隆:
git clone --depth=1
(只克隆最近一次提交,节省空间和时间)。 - 稀疏检出:
git sparse-checkout
(只检出仓库的指定子目录)。
- 选择 GUI 工具 (辅助理解):
- 官方:
git gui
(提交工具),gitk
(历史查看器)。 - 第三方: Sourcetree, Fork, GitKraken, VS Code GitLens, GitHub Desktop, Tower 等。可视化操作有助于理解分支关系、提交历史。
- 官方:
- 持续学习:
- 官方文档:
git help <command>
或 https://git-scm.com/doc 是最权威的参考。 - Pro Git 书籍: https://git-scm.com/book/en/v2 (免费在线,非常全面)。
- 社区: Stack Overflow, Git 官方邮件列表/论坛。
- 官方文档:
关键警告:
- 谨慎使用
git reset --hard
和git push --force
(或git push --force-with-lease
): 它们会重写历史。如果历史已被推送到共享远程仓库,强制推送会破坏其他协作者的工作。仅在绝对必要且了解后果时使用(如在个人分支上整理未推送的本地提交)。 - 理解
rebase
vsmerge
: 选择哪种取决于团队约定和对历史整洁度的要求。变基提供更干净的历史,但操作不当风险更高(尤其是在共享分支上)。
总结:
从入门到精通 Git 是一个循序渐进的过程:
- 掌握基础:
init
,clone
,add
,commit
,status
,log
,.gitignore
。 - 理解分支与协作:
branch
,checkout
/switch
,fetch
,pull
,push
,merge
, 冲突解决。 - 提升效率:
rebase
,stash
,tag
,revert
, 撤销操作。 - 深入原理与高级: 理解对象模型、Reflog、钩子、二分查找、子模块、内部命令。
- 实践最佳实践: 优秀提交信息、高效工作流、善用工具、安全操作。
实践是最好的老师! 多动手操作,遇到问题善用 git help
和搜索。理解 Git 的思维方式(快照、分支指针)比死记命令更重要。祝你 Git 之旅顺利!