Git 是目前最流行的分布式版本控制系统,被广泛应用于软件开发中。本文将全面介绍 Git 的各种功能和使用方法,包含大量代码示例和实践建议。
文章目录
- Git 基础概念
- 版本控制系统
- Git 的特点
- Git 的三个区域
- Git 文件状态
- Git 安装与配置
- 安装 Git
- Linux
- macOS
- Windows
- 初始配置
- Git 仓库创建与管理
- 初始化新仓库
- 克隆现有仓库
- 查看仓库状态
- 忽略文件
- Git 基本工作流程
- 添加文件到暂存区
- 提交更改
- 查看提交历史
- 比较差异
- Git 分支管理
- 创建与切换分支
- 合并分支
- 解决冲突
- 变基 (Rebase)
- Git 远程仓库操作
- 查看远程仓库
- 添加/移除远程仓库
- 获取与拉取
- 推送
- Git 撤销与回退
- 撤销工作目录修改
- 撤销暂存区修改
- 修改最后一次提交
- 回退提交
- 恢复删除的文件
- Git 标签管理
- 创建标签
- 查看标签
- 推送标签
- 删除标签
- 检出标签
- Git 高级操作
- 储藏更改
- 二分查找
- 子模块
- 重写历史
- 打包与归档
- Git 协作工作流
- 集中式工作流
- 功能分支工作流
- Git Flow
- Forking 工作流
- Git 问题排查
- 查看文件修改历史
- 查找问题提交
- 恢复丢失的提交
- 清理仓库
- Git 最佳实践
- 提交规范
- 分支命名规范
- 工作流程建议
- 大型项目建议
- 安全性建议
- 总结

Git 基础概念
版本控制系统
版本控制系统 (Version Control System, VCS) 是记录文件内容变化,以便将来查阅特定版本修订情况的系统。
Git 的特点
- 分布式:每个开发者都有完整的仓库副本
- 高效:大部分操作在本地完成
- 完整性:使用 SHA-1 哈希保证数据完整性
- 灵活性:支持多种非线性开发流程
Git 的三个区域
- 工作目录 (Working Directory):实际文件所在目录
- 暂存区 (Staging Area):准备提交的文件快照
- Git 仓库 (Repository):永久存储的文件快照
Git 文件状态
- 未跟踪 (Untracked):新文件,未被 Git 管理
- 已修改 (Modified):文件已修改但未暂存
- 已暂存 (Staged):文件已修改并标记为下次提交
- 已提交 (Committed):文件已安全保存在本地数据库
Git 安装与配置
安装 Git
Linux
# Debian/Ubuntu
sudo apt-get install git
# Fedora
sudo dnf install git
# CentOS
sudo yum install git
macOS
# 使用 Homebrew
brew install git
# 或下载官方安装包
https://git-scm.com/download/mac
Windows
下载 Git for Windows: https://git-scm.com/download/win
初始配置
配置用户信息:
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
配置默认编辑器:
git config --global core.editor "vim"
查看配置:
git config --list
常用别名配置:
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 仓库创建与管理
初始化新仓库
mkdir my-project
cd my-project
git init
克隆现有仓库
git clone https://github.com/user/repo.git
git clone https://github.com/user/repo.git my-local-folder # 指定本地目录名
git clone --depth 1 https://github.com/user/repo.git # 浅克隆,只获取最新版本
查看仓库状态
git status
git status -s # 简洁输出
忽略文件
创建 .gitignore
文件:
# 忽略所有 .a 文件
*.a
# 但跟踪所有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a
# 忽略当前目录下的 TODO 文件
/TODO
# 忽略 build/ 目录下的所有文件
build/
# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt
# 忽略 doc/ 目录下所有 .pdf 文件
doc/**/*.pdf
# 忽略所有 .log 文件
*.log
# 忽略 node_modules 目录
node_modules/
# 忽略 .env 环境文件
.env
Git 基本工作流程
添加文件到暂存区
git add file1.txt # 添加单个文件
git add file2.txt file3.txt # 添加多个文件
git add . # 添加所有修改和新文件
git add -A # 添加所有修改、新文件和删除操作
git add -u # 添加所有修改和删除,但不包括新文件
git add -p # 交互式添加
提交更改
git commit -m "Initial commit" # 简单提交
git commit -a -m "Commit all changes" # 跳过暂存区,直接提交所有已跟踪文件的修改
git commit --amend # 修改最后一次提交
git commit --amend --no-edit # 修改最后一次提交但不修改提交信息
查看提交历史
git log
git log -p # 显示每次提交的内容差异
git log -2 # 显示最近2次提交
git log --stat # 显示简略统计信息
git log --pretty=oneline # 单行显示
git log --pretty=format:"%h - %an, %ar : %s"
git log --since=2.weeks # 显示两周内的提交
git log --author="John" # 按作者筛选
git log --grep="bug fix" # 按提交信息筛选
git log -S"function_name" # 按代码内容筛选
git log -- path/to/file # 查看特定文件的修改历史
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit # 漂亮的图形化输出
比较差异
git diff # 工作目录与暂存区的差异
git diff --staged # 暂存区与最后一次提交的差异
git diff HEAD # 工作目录与最后一次提交的差异
git diff branch1..branch2 # 两个分支间的差异
git diff commit1 commit2 # 两次提交间的差异
git diff --name-only commit1 commit2 # 只显示有差异的文件名
git diff --word-diff # 单词级别的差异
Git 分支管理
创建与切换分支
git branch # 查看本地分支
git branch -a # 查看所有分支(包括远程)
git branch new-branch # 创建新分支
git checkout branch-name # 切换分支
git checkout -b new-branch # 创建并切换到新分支
git checkout -b new-branch origin/remote-branch # 基于远程分支创建本地分支
git branch -d branch-name # 删除已合并的分支
git branch -D branch-name # 强制删除分支
git branch -m old-name new-name # 重命名分支
git branch --merged # 查看已合并到当前分支的分支
git branch --no-merged # 查看未合并到当前分支的分支
合并分支
git merge branch-name # 合并指定分支到当前分支
git merge --no-ff branch-name # 禁用快进合并
git merge --squash branch-name # 压缩合并
git merge --abort # 中止合并
解决冲突
当合并发生冲突时,Git 会在冲突文件中标记冲突部分:
<<<<<<< HEAD
当前分支的内容
=======
要合并的分支的内容
>>>>>>> branch-name
手动解决冲突后:
git add resolved-file.txt
git commit
变基 (Rebase)
git rebase branch-name # 将当前分支变基到指定分支
git rebase --continue # 解决冲突后继续变基
git rebase --abort # 中止变基
git rebase -i HEAD~3 # 交互式变基,修改最近3次提交
交互式变基常用操作:
- pick: 使用提交
- reword: 使用提交但修改提交信息
- edit: 使用提交但暂停修改
- squash: 将提交合并到前一个提交
- fixup: 类似 squash 但丢弃提交信息
- drop: 删除提交
Git 远程仓库操作
查看远程仓库
git remote # 列出远程仓库
git remote -v # 显示远程仓库URL
git remote show origin # 显示远程仓库详细信息
添加/移除远程仓库
git remote add origin https://github.com/user/repo.git # 添加远程仓库
git remote rename origin new-name # 重命名远程仓库
git remote remove origin # 移除远程仓库
git remote set-url origin https://github.com/user/new-repo.git # 修改远程仓库URL
获取与拉取
git fetch origin # 从远程获取最新信息但不合并
git fetch --prune # 清理已不存在的远程分支的本地引用
git pull origin master # 获取并合并远程分支
git pull --rebase # 使用变基方式拉取
推送
git push origin master # 推送本地分支到远程
git push -u origin master # 推送并设置上游分支
git push origin --delete branch-name # 删除远程分支
git push origin --tags # 推送所有标签
git push origin HEAD # 推送当前分支
git push --force # 强制推送(慎用)
git push --force-with-lease # 更安全的强制推送
Git 撤销与回退
撤销工作目录修改
git checkout -- file.txt # 撤销工作目录中文件的修改
git checkout -- . # 撤销所有工作目录修改
撤销暂存区修改
git reset HEAD file.txt # 将文件从暂存区移出
git reset HEAD . # 将所有文件从暂存区移出
修改最后一次提交
git commit --amend # 修改提交信息或内容
git commit --amend --no-edit # 修改提交内容但不修改信息
回退提交
git reset --soft HEAD~1 # 回退提交但保留修改在暂存区
git reset --mixed HEAD~1 # 回退提交并保留修改在工作目录(默认)
git reset --hard HEAD~1 # 彻底回退提交,丢弃所有修改
git revert HEAD # 创建新提交来撤销之前的提交
恢复删除的文件
git checkout HEAD -- deleted-file.txt # 恢复已删除的文件
git checkout $(git rev-list -n 1 HEAD -- deleted-file.txt)^ -- deleted-file.txt # 恢复在之前提交中删除的文件
Git 标签管理
创建标签
git tag v1.0 # 轻量标签
git tag -a v1.0 -m "Version 1.0" # 附注标签
git tag -a v1.0 9fceb02 # 给特定提交打标签
git tag -s v1.0 -m "Signed version 1.0" # 签名标签
查看标签
git tag # 列出所有标签
git show v1.0 # 查看标签详情
git tag -l "v1.*" # 过滤标签
推送标签
git push origin v1.0 # 推送单个标签
git push origin --tags # 推送所有标签
删除标签
git tag -d v1.0 # 删除本地标签
git push origin --delete v1.0 # 删除远程标签
git push origin :refs/tags/v1.0 # 另一种删除远程标签的方式
检出标签
git checkout v1.0 # 检出标签(进入分离头指针状态)
git checkout -b version1 v1.0 # 基于标签创建新分支
Git 高级操作
储藏更改
git stash # 储藏当前工作目录和暂存区的修改
git stash save "message" # 带消息的储藏
git stash list # 列出所有储藏
git stash apply # 应用最近的储藏
git stash apply stash@{1} # 应用特定储藏
git stash pop # 应用并移除最近的储藏
git stash drop stash@{1} # 删除特定储藏
git stash clear # 清除所有储藏
git stash branch new-branch # 从储藏创建新分支
git stash -u # 储藏包括未跟踪文件
git stash -a # 储藏包括所有文件(包括.gitignore忽略的)
二分查找
git bisect start # 开始二分查找
git bisect bad # 当前版本有问题
git bisect good v1.0 # v1.0版本是好的
git bisect reset # 结束二分查找
git bisect run test-script.sh # 自动运行测试脚本进行二分查找
子模块
git submodule add https://github.com/user/repo.git path/to/submodule # 添加子模块
git submodule init # 初始化子模块
git submodule update # 更新子模块
git submodule update --init --recursive # 递归初始化并更新所有子模块
git submodule foreach 'git checkout master' # 对所有子模块执行命令
git clone --recurse-submodules https://github.com/user/repo.git # 克隆包含子模块的仓库
重写历史
git filter-branch --tree-filter 'rm -f passwords.txt' HEAD # 从所有提交中删除文件
git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_EMAIL" = "old@email.com" ];
then
GIT_AUTHOR_NAME="New Name";
GIT_AUTHOR_EMAIL="new@email.com";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD # 修改作者信息
注意:重写历史会改变提交哈希,只适用于尚未共享的提交。
打包与归档
git bundle create repo.bundle HEAD master # 创建包含master分支的bundle文件
git clone repo.bundle repo -b master # 从bundle文件克隆
git archive --format=zip HEAD > archive.zip # 创建当前提交的zip归档
git archive --format=tar --prefix=project/ HEAD | gzip > project.tar.gz # 创建带前缀的tar.gz归档
Git 协作工作流
集中式工作流
- 开发者克隆中央仓库
- 在本地提交更改
- 推送更改到中央仓库
- 解决冲突(如果有)
功能分支工作流
- 为每个新功能创建独立分支
- 在功能分支上开发
- 完成后合并到主分支
- 删除功能分支
git checkout -b new-feature
# 开发功能...
git commit -a -m "Implement new feature"
git checkout master
git merge new-feature
git branch -d new-feature
Git Flow
Git Flow 是一种流行的分支模型,定义严格的分支角色和交互方式。
主要分支:
- master: 生产代码
- develop: 集成开发分支
支持分支:
- feature/*: 功能开发分支
- release/*: 准备发布分支
- hotfix/*: 紧急修复分支
# 初始化Git Flow
git flow init
# 开始新功能
git flow feature start myfeature
# 完成功能
git flow feature finish myfeature
# 发布新版本
git flow release start 1.0.0
git flow release finish 1.0.0
# 紧急修复
git flow hotfix start 1.0.1
git flow hotfix finish 1.0.1
Forking 工作流
- 开发者fork中央仓库
- 克隆自己的fork到本地
- 创建功能分支开发
- 推送更改到自己的fork
- 创建Pull Request请求合并到中央仓库
# 克隆fork的仓库
git clone https://github.com/yourname/repo.git
# 添加上游仓库
git remote add upstream https://github.com/original/repo.git
# 获取上游更改
git fetch upstream
git merge upstream/master
# 创建功能分支
git checkout -b new-feature
# 开发完成后推送到自己的fork
git push origin new-feature
# 然后在GitHub上创建Pull Request
Git 问题排查
查看文件修改历史
git blame file.txt # 查看文件的逐行修改历史
git blame -L 10,20 file.txt # 查看特定行的修改历史
git log -p file.txt # 查看文件的完整修改历史
git show commit-id:file.txt # 查看特定提交中的文件内容
查找问题提交
git bisect start # 开始二分查找
git bisect bad # 标记当前版本有问题
git bisect good v1.0 # 标记v1.0版本是好的
# Git会自动检出中间版本,你测试后标记good或bad
git bisect reset # 结束二分查找
恢复丢失的提交
git reflog # 查看所有HEAD指向的历史
git fsck --lost-found # 查找悬空对象
git show commit-id # 检查找到的提交
git merge commit-id # 恢复丢失的提交
清理仓库
git gc # 清理不必要的文件并优化本地仓库
git clean -n # 显示将被删除的未跟踪文件(干跑)
git clean -f # 删除未跟踪文件
git clean -fd # 删除未跟踪文件和目录
git prune # 删除悬空对象
Git 最佳实践
提交规范
- 提交信息应清晰描述修改内容
- 第一行不超过50字符,作为摘要
- 第二行空行
- 第三行开始详细说明(如有必要)
- 使用现在时态、命令语气(如"Fix bug"而非"Fixed bug")
示例:
Summarize changes in around 50 characters or less
More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of the commit and the rest of the text as the body. The
blank line separating the summary from the body is critical (unless
you omit the body entirely); various tools like `log`, `shortlog`
and `rebase` can get confused if you run the two together.
Explain the problem that this commit is solving. Focus on why you
are making this change as opposed to how (the code explains that).
Are there side effects or other unintuitive consequences of this
change? Here's the place to explain them.
Further paragraphs come after blank lines.
- Bullet points are okay, too
- Typically a hyphen or asterisk is used for the bullet, preceded
by a single space, with blank lines in between, but conventions
vary here
分支命名规范
- feature/*: 新功能开发
- bugfix/*: 错误修复
- hotfix/*: 紧急修复
- release/*: 版本发布准备
- docs/*: 文档更新
- test/*: 测试相关
工作流程建议
- 频繁提交,原子性提交(每个提交只做一件事)
- 在推送前整理本地提交历史
- 使用分支进行功能开发和问题修复
- 定期从上游拉取更改
- 使用Pull Request进行代码审查
大型项目建议
- 使用子模块或子树管理依赖
- 使用浅克隆减少下载量
- 使用稀疏检出只获取需要的文件
- 使用Git LFS管理大文件
# 浅克隆
git clone --depth 1 https://github.com/user/repo.git
# 稀疏检出
git init repo
cd repo
git remote add origin https://github.com/user/repo.git
git config core.sparseCheckout true
echo "some/dir/" >> .git/info/sparse-checkout
git pull origin master
安全性建议
- 不要提交敏感信息(密码、密钥等)
- 使用.gitignore忽略不必要的文件
- 定期检查提交历史中的敏感信息
- 必要时重写历史删除敏感信息
# 检查历史中是否包含敏感信息
git log -p | grep "password"
总结
Git 是一个功能强大且灵活的工具,掌握它可以极大提高开发效率。本文涵盖了 Git 的各个方面,从基础操作到高级技巧,从个人使用到团队协作。建议读者在实际项目中多加练习,逐步掌握 Git 的各种功能。
记住,Git 的核心概念是快照而非差异,理解这一点有助于更好地使用 Git。同时,遵循最佳实践可以使版本控制更加高效和安全。
Git 的学习曲线可能较陡峭,但一旦掌握,它将成为你开发工作中不可或缺的利器。