Git 概述 安装指南 基础操作 核心概念 常用命令 分支管理 可视化演示 远程协作 高级主题 最佳实践 参考资源 Git 急救手册 工作流对比 平台实战

掌握 Git,掌控代码

全球最权威的分布式版本控制系统完全指南

Git 是由 Linus Torvalds 于 2005 年创建的分布式版本控制系统,旨在高效地处理从小型到大型项目的所有内容。本指南涵盖从安装配置到高级工作流的完整知识体系,助你成为 Git 专家。

开始学习 官网下载 Git 华为云镜像 中科大镜像 淘宝镜像

Git 概述

Git 是一个免费开源的分布式版本控制系统,由 Linux 之父 Linus Torvalds 于 2005 年创建。它的设计目标是速度、数据完整性以及对分布式非线性工作流的强大支持。

与集中式版本控制系统(如 SVN)不同,Git 为每个开发者提供完整的代码仓库副本,包括完整的历史记录。这意味着即使离线,开发者也能进行提交、查看历史、创建分支等操作。

发展历史

2005 年,Linux 内核开发社区与 BitKeeper 的商业授权终止,Linus Torvalds 决定自行开发一款新的版本控制系统。设计目标包括:

  • 速度快
  • 简单的设计
  • 对非线性开发(数千个并行分支)的完全支持
  • 完全分布式
  • 能够高效处理大型项目(如 Linux 内核)

核心特性

  • 分布式架构:每个副本都是完整仓库,不依赖中央服务器
  • 高效分支:轻量级分支,创建与切换几乎瞬时完成
  • 数据完整性:使用 SHA-1 哈希确保内容不被篡改
  • 暂存区:精细控制提交内容,支持多阶段提交
  • 离线工作:本地提交、查看历史、分支操作无需网络
  • 灵活工作流:支持多种协作模式(集中式、功能分支、Forking 等)

Git vs 其他版本控制系统

特性GitSVNMercurial
架构分布式集中式分布式
分支性能极快较慢快
离线操作完全支持有限完全支持
数据完整性SHA-1 校验无内置校验SHA-1 校验
社区规模最大中等较小

安装指南

Git 支持 Linux、macOS 和 Windows 系统。安装后,你可以在终端使用 git --version 验证安装是否成功。

Linux

Debian/Ubuntu:

sudo apt update
sudo apt install git

Fedora:

sudo dnf install git

Arch Linux:

sudo pacman -S git

macOS

使用 Homebrew 安装(推荐):

brew install git

或下载官方安装包:

https://git-scm.com/download/mac

Windows

下载官方安装程序:

https://git-scm.com/download/win

或使用 Winget:

winget install --id Git.Git -e --source winget

安装过程中建议选择 "Use Git from Git Bash only" 或 "Git from the command line and also from 3rd-party software"。

首次配置

安装完成后,配置用户名和邮箱(用于提交记录):

git config --global user.name "你的名字"
git config --global user.email "your.email@example.com"

查看配置:

git config --list

基础操作

初始化仓库

在项目目录中创建新的 Git 仓库:

git init

或克隆远程仓库:

git clone https://github.com/user/repo.git

基本工作流

Git 的典型工作流包含三个区域:

  1. 工作区(Working Directory):你看到的实际文件
  2. 暂存区(Staging Area):准备提交的更改快照
  3. 版本库(Repository):永久保存的提交历史
# 查看文件状态
git status

# 将文件添加到暂存区
git add filename.txt
git add .  # 添加所有更改

# 提交更改
git commit -m "提交说明"

# 查看提交历史
git log --oneline

撤销操作

# 撤销工作区的修改(未 add)
git checkout -- filename.txt

# 取消暂存(已 add 未 commit)
git reset HEAD filename.txt

# 修改最后一次提交
git commit --amend -m "新的提交说明"

核心概念

三个工作区域

工作区(Working Directory)是你在文件系统中看到的项目文件。暂存区(Index/Staging Area)是一个准备下一次提交的文件列表。版本库(Repository)是 Git 存储项目元数据和对象数据库的地方。

文件在 Git 中有四种状态:未跟踪(Untracked)、已修改(Modified)、已暂存(Staged)、已提交(Committed)。

Git 对象模型

Git 的核心是一个内容寻址文件系统,包含四种基本对象类型:

  • Blob(二进制大对象):存储文件内容
  • Tree(树):存储目录结构和文件名
  • Commit(提交):存储作者、时间、提交信息及指向 tree 的指针
  • Tag(标签):对提交的引用,通常用于版本标记

所有对象都通过 SHA-1 哈希值唯一标识,确保数据完整性。

引用与分支

分支本质上是一个指向提交的轻量级可移动指针。默认分支名为 main(或旧版中的 master)。HEAD 是一个特殊引用,指向当前所在的本地分支。

# 查看分支
git branch

# 创建分支
git branch feature-x

# 切换分支
git checkout feature-x
# 或简写
git switch feature-x

常用命令速查

日常命令

git status              # 查看状态
git add <file>          # 添加文件到暂存区
git add -p              # 交互式选择补丁片段
git commit -m "msg"     # 提交更改
git commit -a -m "msg"  # 跳过 add,直接提交所有修改
git diff                # 查看工作区与暂存区的差异
git diff --cached       # 查看暂存区与最后一次提交的差异
git log --oneline --graph --all  # 图形化查看历史
git show <commit>       # 显示某次提交的详细信息和差异

文件操作

git rm <file>           # 删除文件并暂存
git mv <old> <new>      # 重命名文件并暂存
git restore <file>      # 恢复文件到上次提交状态(Git 2.23+)
git restore --staged <file>  # 取消暂存

历史与回退

git log -p -2           # 查看最近两次提交的差异
git log --author="name" --since="2024-01-01"
git blame <file>        # 逐行查看文件修改作者
git reset --soft HEAD~1  # 撤销最后一次提交,保留更改在暂存区
git reset --mixed HEAD~1 # 撤销最后一次提交,保留更改在工作区
git reset --hard HEAD~1  # 彻底删除最后一次提交及更改(慎用)
git revert <commit>     # 创建新提交来撤销某次提交的更改(安全)

分支管理

创建与切换

git branch              # 列出本地分支
git branch -a           # 列出所有分支(含远程)
git branch <name>       # 创建分支
git checkout <name>     # 切换分支
git checkout -b <name>  # 创建并切换
git switch <name>       # 新命令:切换分支
git switch -c <name>    # 新命令:创建并切换

合并分支

将特性分支合并到主分支:

git checkout main
git merge feature-x

Git 提供两种合并策略:

  • Fast-forward(快进):目标分支没有新提交,直接将指针前移
  • Three-way merge(三方合并):创建一个新的合并提交,包含两个分支的历史

解决冲突

当两个分支修改了同一文件的同一部分,合并时会产生冲突。Git 会在冲突文件中标记冲突区域:

<<<<<<< HEAD
当前分支的内容
=======
被合并分支的内容
>>>>>>> feature-x

手动编辑文件解决冲突后:

git add <file>
git commit

合并策略

git merge --no-ff       # 禁用快进,强制创建合并提交
git merge --squash      # 将分支所有提交压缩为一个提交
git rebase main         # 将当前分支变基到 main 最新提交上

Merge vs Rebase:Merge 保留完整历史但可能产生复杂的提交图;Rebase 产生线性历史但会改写提交记录。在共享分支上避免使用 Rebase。

Git 可视化

点击「下一步」逐步执行命令,观察分支指针与提交图的移动。merge 产生合并提交、保留分叉历史;rebase 复制提交、重写为线性历史。

$

远程协作

远程仓库配置

git remote -v                    # 查看远程仓库
git remote add origin <url>     # 添加远程仓库
git remote rename old new        # 重命名远程仓库
git remote remove origin         # 删除远程仓库

同步操作

git fetch origin                 # 下载远程分支更新(不合并)
git pull origin main             # fetch + merge
git pull --rebase origin main    # fetch + rebase(推荐)
git push origin main             # 推送到远程
git push -u origin main          # 首次推送并设置上游分支

协作工作流

Forking 工作流:在 GitHub/GitLab 上 Fork 仓库到自己的账号,克隆个人仓库,推送更改后提交 Pull Request。

功能分支工作流:主仓库中创建 feature 分支,完成后通过 Merge Request 合并。

# Fork 工作流示例
git clone https://github.com/your-name/repo.git
git remote add upstream https://github.com/original/repo.git
git fetch upstream
git rebase upstream/main

Pull Request 最佳实践

  • 每个 PR 专注于一个功能或修复
  • 保持提交历史清晰,适当使用 rebase 整理
  • 添加详细的 PR 描述,说明改动原因和测试方法
  • 确保 CI 检查通过后再请求审查
  • 及时响应审查意见,保持沟通礼貌

高级主题

交互式变基

交互式变基允许你修改、合并、删除或重新排序提交:

git rebase -i HEAD~3

常用命令:

  • pick:保留提交
  • reword:修改提交信息
  • squash:合并到上一个提交
  • fixup:类似 squash 但不保留提交信息
  • drop:删除提交

储藏(Stash)

临时保存未提交的更改,以便切换到其他分支:

git stash push -m "描述"   # 储藏更改
git stash list               # 查看储藏列表
git stash pop                # 应用并删除最新储藏
git stash apply stash@{1}    # 应用指定储藏但不删除
git stash drop stash@{0}     # 删除指定储藏

标签管理

标签用于标记重要的提交(如版本发布):

git tag                          # 列出标签
git tag v1.0.0                   # 创建轻量标签
git tag -a v1.0.0 -m "版本 1.0.0"  # 创建附注标签
git push origin v1.0.0           # 推送单个标签
git push origin --tags           # 推送所有标签
git tag -d v1.0.0                # 删除本地标签

拣选(Cherry-pick)

将特定提交应用到当前分支:

git cherry-pick <commit-hash>

适用于将 bug 修复从维护分支应用到主分支等场景。

Git 钩子

钩子是 Git 在特定事件触发时执行的脚本,位于 .git/hooks/ 目录:

  • pre-commit:提交前执行(代码检查)
  • prepare-commit-msg:提交信息编辑前
  • post-merge:合并后执行(如安装依赖)
  • pre-push:推送前执行(运行测试)

配合 Husky 等工具可在团队中共享钩子配置。

子模块

子模块允许你将一个 Git 仓库作为另一个仓库的子目录:

git submodule add https://github.com/user/lib.git libs/lib
git submodule update --init --recursive

最佳实践

提交规范

  • 提交信息使用祈使句(如 "添加搜索功能" 而非 "添加了搜索功能")
  • 标题不超过 50 个字符,正文每行不超过 72 个字符
  • 正文解释为什么做此更改,而非如何更改
  • 使用 Conventional Commits 规范:类型(范围): 描述
feat(auth): 添加 OAuth2 登录支持

实现了 GitHub 和 Google 的 OAuth2 登录,
替代原有的邮箱密码认证方式。

Closes #123

分支策略

Git Flow:适用于有发布周期的项目

  • main:生产分支
  • develop:开发分支
  • feature/*:功能分支
  • release/*:发布分支
  • hotfix/*:紧急修复分支

GitHub Flow:适用于持续部署的项目

  • main 始终可部署
  • 从 main 创建功能分支
  • 通过 PR 审查后合并到 main

实用技巧

  • 使用 .gitignore 排除不需要版本控制的文件(如依赖目录、编译产物、环境配置文件)
  • 定期使用 git gc 清理和优化仓库
  • 使用 git bisect 二分查找引入 bug 的提交
  • 配置别名简化常用命令:git config --global alias.co checkout
  • 使用 git log --all --graph --oneline --decorate 查看完整分支图

参考资源

官方资源

图形化工具

  • GitHub Desktop — 简洁易用的 Git 客户端
  • SourceTree — Atlassian 出品的免费 Git 客户端
  • GitKraken — 跨平台 Git GUI,可视化能力强
  • Fork — macOS/Windows 上快速的 Git 客户端
  • Tower — 专业的 macOS/Windows Git 客户端

代码托管平台

  • GitHub — 全球最大的代码托管平台
  • GitLab — 支持自托管的 DevOps 平台
  • Gitee — 国内知名的代码托管平台
  • Bitbucket — Atlassian 的代码托管服务

学习资源

Git 急救手册

找回丢失的提交(reflog)

只要提交过的内容,默认 90 天内几乎都能找回来。Git 的 reflog 记录了 HEAD 的每一次移动:

# 查看最近的 HEAD 移动记录
git reflog

# 从目标提交重建分支(推荐,不动当前分支)
git branch recover-feature a1b2c3d

# 或让当前分支直接指回该提交
git reset --hard a1b2c3d

原理:reflog 默认保留 90 天(gc.reflogExpire),期间悬空提交不会被垃圾回收。

恢复误删的分支

# 从 reflog 找到分支最后的提交位置
git reflog

# 用该哈希重建分支
git branch feature-x a1b2c3d

# reflog 也找不到?搜索悬空提交
git fsck --lost-found

好习惯:删除分支时 Git 会输出 Deleted branch feature-x (was a1b2c3d),随手记下这个哈希最保险。

撤销 git reset --hard

reset --hard 只是移动分支指针,提交对象仍留在本地仓库:

git reflog                       # 找到 reset 之前的提交
git reset --hard HEAD@{1}        # 整体回到 reset 前的状态

# 只想恢复部分文件?
git checkout HEAD@{1} -- path/to/file

边界:仅对本地未推送的操作有效;提交已 push 到共享分支时,用 git revert 撤销更安全。

改错提交信息 / 漏提交文件

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

# 漏了文件?追加进最后一次提交,不产生新提交
git add forgotten.txt
git commit --amend --no-edit

# 已 push 的提交要修改,需强制更新(确认没人在此分支上开发)
git push --force-with-lease origin main

原则:--amend 只用于尚未共享的提交;改公共分支的历史会让协作者混乱。

提交到了错误的分支

# 场景:本应提交到 feature 的代码,提交到了 main
git branch feature-x             # 1. 在当前位置建分支,提交不丢
git reset --hard HEAD~1          # 2. main 退回上一个提交
git switch feature-x             # 3. 切到新分支继续开发

# 只想把某一个提交搬到另一分支:cherry-pick
git switch feature-x
git cherry-pick a1b2c3d          # 把该提交复制过来
git switch main
git reset --hard HEAD~1          # 再从 main 上移除

合并冲突:别慌

# 查看哪些文件存在冲突
git status

# 手动编辑解决后,标记并完成合并
git add <file>
git commit

# 搞砸了想重来?
git merge --abort                 # 放弃本次合并,回到合并前
git rebase --abort                # rebase 同理

进阶:git config --global merge.conflictstyle diff3 会在冲突块中显示共同祖先,更容易判断双方各改了什么。

force push 事故与恢复

自己强推覆盖了别人,或被别人的强推覆盖——被覆盖的提交通常还留在某台机器的 reflog 里:

# 在还有旧提交的机器上(你的或协作者的)
git reflog
git branch rescue a1b2c3d         # 先抢救成分支

# 服务器端一般不会立即 GC,可联系管理员
# 或到平台的事件流(如 GitHub Events)查 force push 前的哈希

预防:永远用 --force-with-lease 替代 --force——远程有别人的新提交时会拒绝推送,从源头避免覆盖。

git clean 误删未跟踪文件

这是 Git 唯一几乎无法找回的操作——未跟踪文件从未进入对象库:

# 永远先 dry-run,看清将删除什么
git clean -nd

# 确认无误再真正删除
git clean -fd

# 重要未跟踪文件?先 stash(含 -u 才包含未跟踪)
git stash -u                      # 随时可恢复

预防:把 git clean 想象成 rm -rf 级别操作;日常清理依赖目录用 git clean -ndx 预览更稳妥。

工作流对比

为什么需要工作流

Git 本身不规定团队怎么协作,工作流(Workflow)是围绕分支使用约定出的协作模式。选错工作流的代价很高:评审形同虚设、发布手忙脚乱、hotfix 冲突不断。下面四种是业界主流,按团队规模与发布节奏选择即可。

Git Flow —— 有明确发布周期的项目

五类分支:main(生产)、develop(集成)、feature/*、release/*、hotfix/*。

# 紧急修复走 hotfix,直接基于 main
git switch -c hotfix/1.2.1 main
# ...修复并验证...
git switch main
git merge --no-ff hotfix/1.2.1    # 合入 main
git tag -a v1.2.1 -m "hotfix"
git switch develop
git merge --no-ff hotfix/1.2.1    # 同步回 develop

适合:版本化发布(App、桌面软件、有发布窗口的产品)。代价:分支多、维护成本高,持续部署团队会觉得繁琐。

GitHub Flow —— 持续部署的最简模式

只有 main 一条常驻分支,一切通过 PR 完成:拉分支 → 提交 → PR 评审 + CI → 合并即部署。

git switch -c feat/search main
# 开发、提交...
git push -u origin feat/search    # 推送并创建 PR

适合:Web 服务、SaaS 等可随时部署的项目。关键约束:main 必须始终可部署,CI 是唯一的质量闸门。

GitLab Flow —— 在两者之间取平衡

在 GitHub Flow 之上增加环境分支或发布分支:

  • 环境分支:main → pre-production → production,代码只向前晋升
  • 发布分支:为每个维护版本开 1-2-stable,修复用 cherry-pick 同步

适合:需要多环境灰度发布,或需同时维护多个已发布版本的团队。

Trunk-based Development —— 高频小步提交

所有人直接向 main(trunk)提交,或使用生命周期不足一天的短命分支,未完成功能用特性开关(Feature Flag)隐藏:

git switch main
git pull --rebase origin main     # 小步同步,避免大合并

# 新功能包在开关后面合并,随时可安全发布
if (features.newSearch) {
  renderNewSearch();
}

适合:CI/CD 成熟、测试覆盖高、追求高频部署的团队。门槛:没有自动化测试与特性开关,不要上这套。

四种工作流对比

维度Git FlowGitHub FlowGitLab FlowTrunk-based
常驻分支main + developmainmain + 环境分支main
发布方式release 分支合并即部署环境晋升持续部署
部署节奏版本周期随时多环境灰度每天多次
维护成本高低中低但要求高
适合团队版本化产品中小 Web 团队多环境/多版本成熟 CI/CD 团队

选择建议:个人项目与中小团队从 GitHub Flow 起步;有发布窗口再引入 release 分支;不要为了"规范"直接上 Git Flow 全家桶。

Conventional Commits:让提交可机器读

统一提交格式后,版本号与 CHANGELOG 可以全自动生成:

feat(search): 支持拼音搜索        # 新功能 → 次版本号 +1
fix(auth): 修复 token 过期判断    # 修复 → 补丁号 +1
feat!: 重构 API 响应结构          # 破坏性变更 → 主版本号 +1
chore / docs / refactor / test    # 其他类型,不影响版本号
# 配套工具链:提交时自动校验格式
npm install -D husky @commitlint/cli @commitlint/config-conventional
npx husky init
echo 'npx --no -- commitlint --edit "$1"' > .husky/commit-msg

收益:配合 semantic-release / changesets,从提交历史自动产出版本号、CHANGELOG 与发布。

平台实战

三大托管平台,怎么选

本地 Git 操作在哪个平台都完全一样,差异只在托管层:协作模型、CI 与生态。GitHub 是全球最大的开源社区,Actions 生态最丰富,开源曝光与协作首选;GitLab 胜在内置一体化 DevOps(CI/CD、容器仓库、议题看板),且支持私有化部署,企业内网主流;Gitee 服务器在国内,克隆推送稳定快速,也是给开源项目做国内镜像的现实选择。

三平台横向对比

维度GitHubGitLabGitee
定位开源社区 · 全球协作DevOps 一体化 · 可自建国内托管 · 访问稳定
协作单元Pull RequestMerge RequestPull Request
CI/CDGitHub ActionsGitLab CI(.gitlab-ci.yml)Gitee Go
私有化部署不支持支持(CE/EE 自建)企业版支持
国内直连时好时坏官方云慢 / 自建快快
开源生态最大中等成长中

务实建议:开源项目主仓放 GitHub、Gitee 做镜像;公司内网自建选 GitLab CE。不必纠结"哪个最好"——很多团队多平台并用(见下方「多平台同步推送」)。

SSH 密钥:一次配置,三平台通用

免密拉取与推送的标准做法。生成一对 ed25519 密钥,把公钥贴到各平台的「SSH Keys」设置:

# 生成密钥对(一路回车,或设口令保护)
ssh-keygen -t ed25519 -C "you@example.com"

# 复制公钥内容,粘贴到平台的 SSH Keys 设置页
cat ~/.ssh/id_ed25519.pub

# 各平台连通性测试(首次连接输入 yes)
ssh -T git@github.com
ssh -T git@gitlab.com
ssh -T git@gitee.com

多平台、多账号用 ~/.ssh/config 给每把钥匙指定用途:

# ~/.ssh/config
Host github
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_github

Host gitee
  HostName gitee.com
  User git
  IdentityFile ~/.ssh/id_gitee

之后克隆地址写成 git@gitee:user/repo.git(用别名代替域名)。原则:一平台一把钥匙,泄露可单独吊销;ed25519 比 RSA 更短更快。

HTTPS + 访问令牌:密码推送已成历史

GitHub 自 2021 年起禁止账户密码推送,HTTPS 方式统一改用 Personal Access Token(GitLab 同名,Gitee 叫「私人令牌」):在平台「设置 → 开发者选项」生成,推送时当密码用。令牌交给凭据管理器,只需配置一次:

# Windows 用 Git Credential Manager(安装 Git 时默认附带)
git config --global credential.helper manager

# 首次 push 弹窗登录授权,之后自动携带 token
git push origin main

安全提示:不要把 token 写进远程 URL(https://oauth2:TOKEN@...)——它会明文留在 .git/config;只授予 repo 等最小权限范围,并定期轮换。

PR / MR:协作的核心单元

GitHub、Gitee 叫 Pull Request,GitLab 叫 Merge Request,本质相同:把一个分支的提交申请合并进目标分支,评审、CI、讨论都挂在这个单元上。标准特性分支流程:

git switch -c feat/login
git commit -m "feat(login): 支持手机号验证码登录"
git push -u origin feat/login
# 网页上创建 PR/MR → CI 通过 → 评审 → 合并(merge / squash)

给开源项目贡献代码走 fork 模式:先把项目 Fork 到自己账号,clone 自己的副本,再指向上游:

git remote add upstream https://github.com/owner/awesome.git
git fetch upstream
git rebase upstream/main      # 让自己的提交基于最新上游
git push origin feat/xxx      # 然后向上游发起 PR

经验:PR 小而聚焦最快合并;分支搁置越久,rebase 冲突越滚越大。

国内访问加速实战

GitHub 在国内的连通性不稳定,三类场景各有稳的做法:

  • 克隆大仓库:浅克隆 + 只取目标分支,下载量降一个数量级:git clone --depth=1 --single-branch --branch main <url>
  • 日常稳定拉取:在 Gitee「导入仓库」建立镜像,日常从 Gitee 克隆;公司团队可直接自建 GitLab。
  • 只要发布产物:不克隆源码,直接到 Release 页面下载压缩包与二进制文件。

提醒:第三方加速代理地址变动频繁,且可能记录访问内容——涉及私有代码或凭据的流量,不要图方便走不明代理。

一份代码,多平台同步推送

主仓在 GitHub、镜像在 Gitee 的典型双托管,用多 remote 一次推送:

# 方式一:多个 remote,分别推送(fetch / push 关系清晰)
git remote add github git@github.com:user/repo.git
git remote add gitee  git@gitee.com:user/repo.git
git push github main
git push gitee main

# 方式二:一个 remote 挂多个 push URL,一条命令全推
git remote set-url --add --push origin git@github.com:user/repo.git
git remote set-url --add --push origin git@gitee.com:user/repo.git
git push origin main

注意:--add --push 之后 fetch 仍只认第一个 URL;若在某平台单独改写过历史(force-push),两边 main 会分叉,同步前先分别 git fetch 确认。