初始化仓库

创建一个新的Git仓库,开始版本控制之旅。

git init [目录名]

描述:在指定目录或当前目录初始化Git仓库

# 在当前目录初始化
git init

# 创建并初始化新目录
git init my-project
提示:执行后会在目录中创建.git文件夹,包含所有版本控制信息。

添加文件到暂存区

将文件更改添加到Git的暂存区,准备提交。

git add [文件/目录]

描述:将文件或目录添加到暂存区

# 添加所有更改
git add .

# 添加特定文件
git add app.js

# 添加多个文件
git add app.js styles.css

# 添加所有txt文件
git add *.txt
提示:使用git add -p可以交互式地选择要添加的更改部分。

提交更改

将暂存区的更改永久保存到Git历史中。

git commit -m "提交信息"

描述:提交暂存区的更改

# 基本提交
git commit -m "Initial commit"

# 跳过暂存区直接提交
git commit -am "Fix login bug"

# 修改最后一次提交
git commit --amend -m "Updated message"
提示:推荐使用Conventional Commits格式,如feat: 添加新功能

查看状态

查看工作区和暂存区的当前状态。

git status

描述:显示工作区状态

# 查看详细状态
git status

# 查看简洁状态
git status -s

# 查看分支状态
git status -sb
提示:会显示已修改、已暂存和未跟踪的文件。Git 2.50版本改进了状态显示的可读性。

查看历史

查看项目的提交历史记录。

git log [选项]

描述:查看提交历史

# 查看完整历史
git log

# 查看简洁历史
git log --oneline

# 查看图形化历史
git log --graph --oneline

# 查看特定文件历史
git log --follow file.js
提示:q退出日志查看。现代Git日志输出更加美观和直观。

Git 适用场景

了解哪些情况下适合使用Git进行版本控制。

软件开发项目

Git最核心的应用场景,管理源代码的版本迭代。

✅ Web应用程序开发
✅ 移动应用开发
✅ 桌面应用开发
✅ 游戏开发
✅ API服务开发

文档与写作

协作写作和文档版本管理,追踪每次修改。

✅ 技术文档(Markdown、reStructuredText)
✅ 学术论文(LaTeX)
✅ 书籍写作
✅ 博客文章
✅ 法律合同文本

配置文件管理

管理服务器配置、系统设置等文件的变更。

✅ 服务器配置文件
✅ Docker/Kubernetes配置
✅ CI/CD流水线配置
✅ 云基础设施代码(Terraform)
✅ 系统脚本和工具

设计资源管理

管理设计文件和创意资源(配合Git LFS)。

✅ UI设计稿(SVG格式)
✅ 图标库
✅ 字体文件
✅ 设计规范文档
✅ 品牌资产

数据科学与研究

管理研究代码、实验配置和分析脚本。

✅ 数据分析脚本(Python/R)
✅ 机器学习模型代码
✅ 实验配置文件
✅ 研究项目代码
✅ 可复现性研究代码

教育与学习

课程项目、学习笔记和教学材料的版本管理。

✅ 课程作业
✅ 学习笔记
✅ 教学课件
✅ 编程练习
✅ 开源学习项目
提示:Git不仅适用于代码,任何需要追踪历史变更、支持多人协作的文本型项目都可以使用Git。对于大型二进制文件,建议使用Git LFS(Large File Storage)。

Git 不适用场景

了解哪些情况下不适合使用Git,避免误用。

大型二进制文件

Git不擅长处理大型二进制文件,会导致仓库体积膨胀。

❌ 高分辨率图片(RAW格式)
❌ 视频文件(MP4、AVI等)
❌ 音频文件(WAV、FLAC等)
❌ 压缩包(ZIP、RAR、7z)
❌ 安装包(EXE、DMG、APK)

建议:使用Git LFS、外部存储服务(AWS S3、阿里云OSS)或专门的媒体管理系统。

频繁变化的临时文件

临时文件、缓存文件等不需要版本控制的内容。

❌ 编译缓存(node_modules、.next)
❌ IDE配置(.idea、.vscode临时文件)
❌ 操作系统文件(.DS_Store、Thumbs.db)
❌ 日志文件(*.log)
❌ 数据库文件(SQLite、临时备份)

建议:使用.gitignore文件忽略这些文件。

敏感与机密数据

绝不应该将敏感信息提交到Git仓库。

❌ API密钥和访问令牌
❌ 数据库密码
❌ SSH私钥
❌ SSL证书
❌ 个人身份信息(PII)

建议:使用环境变量、密钥管理系统(HashiCorp Vault)或配置管理工具。

实时协作的富媒体编辑

需要多人同时在线编辑的富媒体文档。

❌ 实时协作文档(Google Docs风格)
❌ 复杂的Excel表格协作
❌ 在线白板绘图
❌ 视频剪辑项目
❌ 音频混音工程

建议:使用专门的协作工具(Google Docs、Notion、Figma、Miro等)。

极高频率的自动更新

每分钟甚至每秒都在变化的动态数据。

❌ 实时传感器数据
❌ 日志流(每秒写入)
❌ 交易记录
❌ 用户行为追踪数据
❌ 动态生成的报表

建议:使用数据库、时间序列数据库或日志收集系统。

受版权限制的付费内容

有版权限制或需要许可证的文件。

❌ 付费字体文件
❌ 商业图片库素材
❌ 付费软件包
❌ 音乐版权文件
❌ 授权插件

建议:使用外部存储服务,在代码中引用而非包含文件本身。

非结构化的大数据集

海量的非结构化数据不适合Git管理。

❌ 机器学习训练数据集(GB级别)
❌ 数据库备份
❌ 影像库
❌ 备份归档
❌ 历史日志归档

建议:使用数据存储服务(HDFS、S3)、数据湖或专门的备份系统。

提示:Git是分布式版本控制系统,专注于文本文件的版本追踪。对于不适用Git的场景,选择专门的工具往往更高效。合理使用.gitignore可以避免将不需要的文件纳入版本控制。

GUI 图形界面工具

图形化Git客户端,让版本控制更加直观便捷。

Sourcetree

免费且功能强大的Git客户端,支持Windows和Mac。

特点:
✅ 免费开源
✅ 中文界面支持
✅ Git Flow可视化
✅ 内置Diff工具
下载地址:sourcetreeapp.com

GitKraken

现代化Git客户端,界面美观功能丰富。

特点:
✅ 跨平台支持
✅ 可视化分支图
✅ 内置代码编辑器
✅ 支持GitHub/GitLab集成
下载地址:gitkraken.com

GitHub Desktop

GitHub官方桌面客户端,专为GitHub用户设计。

特点:
✅ 简洁易用
✅ GitHub深度集成
✅ Pull Request支持
✅ 分支管理便捷
下载地址:desktop.github.com

TortoiseGit

Windows资源管理器集成型Git客户端。

特点:
✅ 右键菜单集成
✅ 无需离开资源管理器
✅ 中文界面支持
✅ 稳定可靠
下载地址:tortoisegit.org

lazygit

终端里的Git UI工具,轻量级且高效。

特点:
✅ 终端界面
✅ 键盘操作
✅ 资源占用极低
✅ 支持自定义
安装:brew install lazygit

国外代码托管平台

主流的海外在线Git代码托管服务。

GitHub

全球最大的开源代码托管平台。

特点:
✅ 全球最大开源社区
✅ GitHub Actions CI/CD
✅ Pull Request功能
✅ GitHub Pages静态托管
✅ Copilot AI编程助手
✅ GitHub Packages
官网:github.com

GitLab

一站式DevOps平台,支持自托管。

特点:
✅ 支持自托管部署
✅ 内置CI/CD流水线
✅ 代码审查功能强大
✅ 权限管理灵活
✅ GitLab Duo AI助手
✅ Docker Registry
官网:gitlab.com

Bitbucket

Atlassian旗下的代码托管服务。

特点:
✅ 免费私有仓库
✅ Jira集成
✅ Bitbucket Pipelines
✅ Azure DevOps集成
✅ Mercurial支持
官网:bitbucket.org

SourceForge

历史悠久的开源项目托管平台。

特点:
✅ 历史悠久
✅ 免费开源项目
✅ 下载统计
✅ SF.net VPN服务
✅ 项目管理工具
官网:sourceforge.net

Azure DevOps

微软的企业级DevOps平台。

特点:
✅ Azure Repos代码托管
✅ Azure Pipelines CI/CD
✅ Azure Boards项目管理
✅ 企业级安全合规
✅ Azure Test Plans
官网:azure.microsoft.com

国内代码托管平台

国内常用的代码托管服务,访问速度快,生态完善。

Gitee (码云)

国内领先的代码托管平台,访问速度快。

特点:
✅ 国内访问速度最快
✅ 中文界面友好
✅ 私有仓库免费
✅ Gitee CI持续集成
✅ 企业版支持
✅ 码云开源专区
官网:gitee.com

GitCode

华为云提供的代码托管服务。

特点:
✅ 华为云背书
✅ 免费私有仓库
✅ CI/CD流水线
✅ 项目管理功能
✅ 企业级安全
官网:gitcode.com

阿里云 Codeup

阿里云提供的企业级代码托管平台。

特点:
✅ 阿里云生态集成
✅ 企业级代码管理
✅ 代码检测能力
✅ 访问控制
✅ 代码备份
官网:codeup.aliyun.com

腾讯云 Coding

腾讯云旗下的一站式DevOps平台。

特点:
✅ 腾讯云生态
✅ 免费私有仓库
✅ 持续集成/部署
✅ 项目管理
✅ 代码审查
官网:coding.net

GitHub 中国镜像

GitHub的国内镜像服务,提升访问速度。

镜像站点:
hub.fastgit.xyz
ghproxy.com
mirror.ghproxy.com

使用方法:
git clone https://hub.fastgit.xyz/user/repo.git

开源中国 Gitee

国内最大的开源社区代码托管平台。

开源项目推荐:
✅ 鸿蒙系统 OpenHarmony
✅ 深度操作系统 deepin
✅ 飞桨 PaddlePaddle
✅ 腾讯开源项目
✅ 阿里巴巴开源项目
官网:gitee.com

自托管Git服务

可以部署在自有服务器上的Git托管解决方案。

Gogs

轻量级的自托管Git服务,完全开源免费。

特点:
✅ 极其轻量(资源占用少)
✅ 易于安装和配置
✅ 支持MySQL、PostgreSQL、SQLite
✅ 中文界面
✅ 支持Markdown和WiKi
✅ Webhooks和Git钩子

GitHub:gogs/gogs

Gitea

Gogs的社区fork,功能更丰富。

特点:
✅ Gogs的增强版
✅ 更多功能特性
✅ 活跃的社区支持
✅ 支持Docker部署
✅ LDAP/OAuth认证
✅ 问题跟踪和PR

GitHub:go-gitea/gitea

GitLab CE/EE

GitLab开源版,可完全自托管。

特点:
✅ 功能最全面
✅ 支持Docker/K8s部署
✅ 内置CI/CD
✅ 权限管理完善
✅ 高可用架构
✅ 社区版免费

官网:gitlab.com/install

Forgejo

从Gitea社区分叉的轻量级Git服务。

特点:
✅ Gitea社区分叉
✅ 专注于简单易用
✅ 完全开源
✅ Docker支持
✅ 轻量级要求
✅ 治理透明

官网:forgejo.org

GitBlit

纯Java写的Git仓库管理工具。

特点:
✅ 纯Java实现
✅ 无数据库依赖
✅ 易于部署
✅ 管理界面友好
✅ Groovy支持
✅ 适合小团队

官网:gitblit.com

搭建推荐

推荐部署方案:

个人/小团队
→ Gogs 或 Forgejo(轻量)

中等规模团队
→ Gitea(功能丰富)

企业级需求
→ GitLab CE/EE(功能全面)

Docker快速部署
docker run -d --name gitea -p 3000:3000 -p 2222:22 -v gitea:/data gitea/gitea:latest

查看分支

查看本地和远程的所有分支。

git branch [选项]

描述:列出、创建或删除分支

# 查看本地分支
git branch

# 查看所有分支(包括远程)
git branch -a

# 查看远程分支
git branch -r

# 查看分支详细信息
git branch -vv
提示:当前分支会显示星号(*)标记。

创建分支

创建新的开发分支。

git branch [分支名]

描述:创建新分支

# 创建新分支
git branch feature-login

# 从指定提交创建分支
git branch feature-login abc123

# 创建并切换到新分支
git checkout -b feature-login
提示:推荐使用描述性的分支名,如feature/bugfix/前缀。

切换分支

在不同的分支之间切换。

git checkout [分支名]

描述:切换到指定分支

# 切换到分支
git checkout feature-login

# 使用switch命令(Git 2.23+)
git switch feature-login

# 切换到上一个分支
git checkout -
提示:确保当前工作区是干净的,或使用git stash保存未提交的更改。

合并分支

将一个分支的更改合并到当前分支。

git merge [分支名]

描述:合并指定分支到当前分支

# 合并分支
git merge feature-login

# 禁用快进合并
git merge --no-ff feature-login

# 中断合并
git merge --abort
提示:如果出现冲突,需要手动解决冲突后再次提交。

删除分支

删除不再需要的分支。

git branch -d [分支名]

描述:删除分支

# 删除已合并的分支
git branch -d feature-login

# 强制删除分支
git branch -D feature-login

# 删除远程分支
git push origin --delete feature-login
提示:-d只删除已合并的分支,-D可以删除未合并的分支(谨慎使用)。

添加远程仓库

关联本地仓库到远程仓库。

git remote add [名称] [URL]

描述:添加远程仓库

# 添加origin远程仓库
git remote add origin https://github.com/user/repo.git

# 查看远程仓库
git remote -v

# 修改远程仓库URL
git remote set-url origin https://github.com/user/new-repo.git
提示:origin是远程仓库的默认名称,可以自定义多个远程仓库。

克隆仓库

从远程仓库克隆到本地。

git clone [URL] [目录]

描述:克隆远程仓库

# 克隆到当前目录
git clone https://github.com/user/repo.git

# 克隆到指定目录
git clone https://github.com/user/repo.git my-project

# 克隆特定分支
git clone -b develop https://github.com/user/repo.git
提示:克隆后会自动创建.git文件夹,并设置origin远程仓库。

推送代码

将本地提交推送到远程仓库。

git push [远程] [分支]

描述:推送本地分支到远程

# 推送当前分支
git push origin main

# 推送并设置上游分支
git push -u origin main

# 推送所有分支
git push --all origin

# 强制推送(谨慎使用)
git push --force origin main
提示:-u参数设置上游分支后,后续只需执行git push

拉取代码

从远程仓库拉取最新代码并合并。

git pull [远程] [分支]

描述:拉取并合并远程更新

# 拉取当前分支
git pull origin main

# 拉取并变基
git pull --rebase origin main

# 只拉取不合并
git fetch origin main
提示:git pull等同于git fetch + git merge

获取更新

从远程仓库获取最新更新但不合并。

git fetch [远程]

描述:获取远程更新

# 获取所有远程更新
git fetch

# 获取特定远程仓库
git fetch origin

# 获取特定分支
git fetch origin main
提示:获取后可以查看差异再决定是否合并,这是更安全的工作方式。

暂存工作

临时保存当前工作区的更改。

git stash [命令]

描述:暂存当前工作区的更改

# 暂存当前更改
git stash

# 带消息暂存
git stash save "work in progress"

# 恢复最近暂存
git stash pop

# 查看暂存列表
git stash list
提示:在切换分支前使用,避免未提交的更改造成冲突。

撤销提交

撤销或修改提交历史。

git reset [模式] [提交]

描述:重置当前分支到指定状态

# 撤销最后一次提交但保留更改
git reset HEAD~1

# 撤销提交并删除更改
git reset --hard HEAD~1

# 修改最后一次提交
git commit --amend
提示:--soft保留更改在暂存区,--mixed保留更改在工作区,--hard完全删除。

变基操作

重新应用提交到另一个基础。

git rebase [分支]

描述:变基操作,线性化提交历史

# 变基到main分支
git rebase main

# 交互式变基
git rebase -i HEAD~3

# 跳过变基
git rebase --skip

# 中止变基
git rebase --abort
提示:现代Git提供了更友好的交互式rebase界面。

选择提交

选择特定提交应用到当前分支。

git cherry-pick [提交]

描述:选择特定提交应用

# 选择单个提交
git cherry-pick abc123

# 选择多个提交
git cherry-pick abc123..def456

# 选择但不自动提交
git cherry-pick -n abc123
提示:需要提供完整的commit hash,可以使用git log查看。

AI 生成提交信息

使用AI工具分析代码变更,生成符合规范的提交信息。

AI Commit Generation

描述:AI辅助生成提交信息

# GitHub Copilot CLI
git add .
git commit -m "$(gh copilot suggest '生成描述这些变更的提交信息')"

# Gitmoji AI 助手
git commit -m "$(gitmoji -ai)"

# 自定义AI脚本
git commit -m "$(python ai-commit-generator.py)"
提示:AI能够理解代码语义,生成符合Conventional Commits规范的提交信息。

AI 代码审查

使用AI分析Pull Request,提供代码质量建议。

AI Code Review

描述:AI辅助代码审查

# GitHub Copilot 自动审查
# AI会自动检测潜在的bug、性能问题和安全漏洞

# GitLab Duo AI 审查
gitlab-duo review feature/new-ui

# 本地AI审查工具
ai-review --diff HEAD~1
提示:AI审查可以捕捉人工可能遗漏的问题,如未处理的边界条件、安全漏洞、性能优化机会等。主流平台都已集成AI审查功能。

AI 冲突解决

AI辅助理解和解决Git合并冲突。

AI Conflict Resolution

描述:AI辅助冲突解决

# 使用 AI 理解冲突
git conflict explain

# AI 建议合并策略
git merge-suggest feature/new-ui

# AI 自动解决简单冲突
git resolve-conflict --ai file.js
提示:现代Git工具已集成AI,可以解释冲突上下文并建议最佳合并方案。

AI 命令预测

AI根据上下文预测下一个Git命令。

AI Command Prediction

描述:AI预测下一个命令

# GitSense AI(假设的AI助手)
$ git [Tab]
# AI提示:根据您的更改,可能需要:
# git add modified-file.js
# git commit -m "fix: 修复登录验证逻辑"
# git push origin feature/login

# 配置shell集成
eval "$(git-predict init)"
提示:AI命令预测基于项目历史和个人使用模式,学习您的习惯并提供个性化建议。现代智能终端(如Warp、Fig)都集成了此功能。

GPG 签名验证

使用GPG/SSH密钥签名提交,验证作者身份。

Git GPG Signing

描述:启用GPG签名验证

# 配置GPG签名
git config --global commit.gpgsign true
git config --global gpg.program gpg2

# 查看签名状态
git log --show-signature

# 使用SSH签名
git config --global commit.gpgsign true
git config --global gpg.format ssh
提示:主流平台(GitHub/GitLab)推荐使用签名验证提交,提高代码可信度。

Conventional Commits

遵循规范化的提交信息格式。

Conventional Commits

描述:规范化提交信息格式

# 格式: type(scope): subject
git commit -m "feat(auth): 添加OAuth2登录支持"
git commit -m "fix(api): 修复用户数据获取bug"
git commit -m "docs(readme): 更新安装说明"
git commit -m "style(button): 优化按钮样式"

# 安装commitlint
npm install @commitlint/cli @commitlint/config-conventional
提示:使用commitlint工具自动验证提交信息格式,便于自动生成变更日志。

Partial Clone

部分克隆大型仓库,节省时间和空间。

Git Partial Clone

描述:部分克隆大型仓库

# 按需克隆(不下载历史)
git clone --filter=blob:none https://github.com/user/repo.git

# 仅克隆特定分支
git clone --single-branch --branch main repo.git

# 克隆特定文件
git clone --depth 1 --filter=blob:limit=1m repo.git
提示:对于包含大型媒体文件或历史的仓库,部分克隆可提速90%以上。Git 2.50版本进一步优化了partial clone的性能。

Sparse Checkout

只检出仓库的特定目录。

Git Sparse Checkout

描述:稀疏检出特定目录

# 启用稀疏检出
git clone --no-checkout repo.git
cd repo
git sparse-checkout init
git sparse-checkout set src/api docs

# 添加更多目录
git sparse-checkout add src/components

# 禁用稀疏检出
git sparse-checkout disable
提示:在monorepo项目中,只检出需要的目录可以大幅减少磁盘占用。

性能优化

优化大型仓库的性能。

Git Performance Optimization

描述:优化Git性能

# 启用并行索引操作
git config --global core.parallelIndex 8

# 优化大文件处理
git lfs install
git lfs track "*.psd"

# 使用Git 2.50+的新索引格式
git update-index --index-version 4

# 清理无用文件
git gc --prune=now
提示:Git 2.50版本增强了分支信息的显示。

日常工作流

程序员日常开发中最常用的Git操作流程。

标准开发流程

# 1. 拉取最新代码
git pull origin main

# 2. 创建功能分支
git checkout -b feature/new-feature

# 3. 开发并查看状态
git status

# 4. 添加更改到暂存区
git add .

# 5. 提交代码
git commit -m "feat: 添加新功能"

# 6. 推送到远程
git push -u origin feature/new-feature

# 7. 创建Pull Request/Merge Request

提交前检查

# 查看将要提交的更改
git diff --cached

# 查看未暂存的更改
git diff
提示:保持main分支干净,所有开发都在功能分支上进行。

修复Bug流程

发现Bug后如何使用Git进行修复。

# 1. 从main创建bug修复分支
git checkout main
git pull origin main
git checkout -b bugfix/login-error

# 2. 定位问题提交
git log --oneline --all
git bisect start
git bisect bad HEAD
git bisect good v1.0.0

# 3. 修复代码并提交
git add .
git commit -m "fix: 修复登录验证错误"

# 4. 推送并创建PR
git push -u origin bugfix/login-error

查看变更历史

# 查看文件变更历史
git log --follow -p filename.js

# 查看谁在什么时候修改的
git blame filename.js
提示:bugfix分支命名使用"bugfix/"前缀,方便团队识别。

紧急修复

生产环境紧急问题的快速处理流程。

# 1. 基于生产标签创建hotfix分支
git checkout -b hotfix/critical-bug v1.0.0

# 2. 快速修复问题
git add .
git commit -m "hotfix: 修复生产环境严重错误"

# 3. 打补丁标签
git tag -a v1.0.1 -m "Hotfix patch"

# 4. 合并回main和develop
git checkout main
git merge --no-ff hotfix/critical-bug
git tag v1.0.1

# 5. 推送所有
git push origin main --tags
提示:Hotfix应该尽可能小,专注于修复核心问题。

常用别名

配置常用命令别名,提高工作效率。

# 设置别名
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

# 使用别名
git st
git co feature/login
git br -a
git ci -m "fix bug"
git lg
提示:在 ~/.gitconfig 文件中管理全局别名配置。

忽略文件

配置 .gitignore 忽略不需要版本控制的文件。

.gitignore 规则
# .gitignore 示例

# 依赖目录
node_modules/
vendor/

# 编译输出
dist/
build/
*.min.js

# 环境配置
.env
.env.local

# IDE 配置
.vscode/
.idea/

# 日志文件
*.log
npm-debug.log*

# 操作系统文件
.DS_Store
Thumbs.db

# 忽略所有 .txt 文件
*.txt

# 但保留 important.txt
!important.txt

常用命令

# 查看已被忽略的文件
git ls-files --others --ignored --exclude-standard

# 从版本控制中移除已跟踪文件(保留本地)
git rm --cached filename

# 移除目录下所有已跟踪文件
git rm -r --cached directory/
提示:GitHub提供官方 .gitignore 模板,涵盖各种语言和框架。

存储结构

深入了解Git的底层存储架构和目录结构。

.git 目录结构

.git/
├── HEAD # 当前分支引用
├── config # 仓库配置文件
├── description # 仓库描述
├── hooks/ # Git钩子脚本
│ ├── pre-commit
│ ├── post-commit
│ └── ...
├── info/ # 排除文件
│ └── exclude
├── objects/ # Git对象存储
│ ├── info/ # 包文件信息
│ │ └── packs
│ └── pack/ # 压缩包文件
│ ├── pack-*.idx # 索引文件
│ └── pack-*.pack # 数据文件
└── refs/ # 引用存储
├── heads/ # 本地分支
│ ├── main
│ └── develop
├── tags/ # 标签
│ ├── v1.0.0
│ └── v1.1.0
└── remotes/ # 远程引用
└── origin/
├── main
└── develop

核心目录详解

objects/ - 存储所有Git对象,使用前2位哈希作为目录名,剩余38位作为文件名

refs/ - 存储分支、标签等引用,内容是commit哈希

HEAD - 指向当前分支的符号引用

index - 暂存区二进制文件(隐藏)

config - 仓库特定配置(用户名、邮箱、远程仓库等)

hooks/ - 自定义脚本,在特定Git操作时自动执行

Git对象存储结构图

objects/
├── ab/                    # 哈希前2位作为目录
│   └── cdef1234...        # 剩余38位作为文件名
├── de/
│   └── f4567890...
└── pack/                  # 打包存储(优化)
    ├── abc123.idx         # 索引文件
    └── abc123.pack        # 数据文件
                        

查看内部结构

# 查看objects目录
ls -la .git/objects/

# 查看HEAD内容
cat .git/HEAD

# 查看分支引用
cat .git/refs/heads/main

# 查看所有对象
git rev-list --all --objects

# 查看对象大小
git count-objects -vH
提示:Git使用内容寻址存储,相同内容只存储一次,这使Git非常高效。

对象模型

Git的四种核心对象类型及其作用。

四种Git对象

# 1. Blob 对象 - 存储文件内容
# 文件内容被压缩并计算SHA-1哈希
# 相同内容只存储一次(去重)
# 不包含文件名、路径等信息

# 2. Tree 对象 - 类似目录
# 记录文件名、权限和blob/tree引用
# 递归形成文件系统树
# 一个tree可以包含blob和其他tree

# 3. Commit 对象 - 提交记录
# 包含:tree引用、父commit、作者、时间、消息
# 形成提交链(DAG - 有向无环图)

# 4. Tag 对象 - 标签
# 指向特定commit,包含签名和消息
# 用于版本标记,可以是轻量级或带注释

对象关系图

                    Commit (HEAD)
                    ┌─────────────────────────────────┐
                    │ tree: abc123...                │
                    │ parent: def456...               │
                    │ author: 张三 <zhang@example.com> │
                    │ date: 2024-01-15 10:30:00      │
                    │ message: "添加新功能"           │
                    └─────────────────────────────────┘
                               │
                               ▼
                    Tree (abc123...)
                    ┌─────────────────────────────────┐
                    │ 100644 blob 789abc...  README.md│
                    │ 100644 blob 456def...  main.js  │
                    │ 040000 tree 123456...  src/     │
                    └─────────────────────────────────┘
                               │
                    ┌──────────┼──────────┐
                    ▼          ▼          ▼
              Blob       Blob        Tree
            (README)    (main.js)   (src/)
                                      │
                                      ▼
                               Tree (123456...)
                    ┌─────────────────────────────────┐
                    │ 100644 blob 789012...  app.js   │
                    └─────────────────────────────────┘
                                      │
                                      ▼
                                  Blob (app.js)
                        

查看对象

# 查看对象类型
git cat-file -t <hash>

# 查看对象内容
git cat-file -p <hash>

# 查看对象大小
git cat-file -s <hash>

# 查看所有对象
git rev-list --all --objects

# 查看对象的原始数据
git cat-file <hash>

哈希计算原理

# 对象哈希 = SHA1("type size\0content")

# 示例:内容为"hello"的blob对象
# Header: "blob 5\0hello"
# SHA1("blob 5\0hello") = a0423896b8...

# 这保证:相同内容 = 相同哈希
# 不同类型 = 不同哈希
# 即使内容相同,类型不同,哈希也不同

对象不可变性

Git对象一旦创建就不可修改。修改内容会创建新的对象,新的哈希。这就是为什么Git操作(如修改提交)实际上是创建新对象。

提示:SHA-1哈希使Git能够高效去重和验证数据完整性。每个对象都是唯一的,通过哈希引用。

索引机制

理解暂存区(index)的工作原理。

什么是索引

索引(Index)是一个二进制文件,位于 .git/index,记录了暂存区的文件信息。它是工作区和提交之间的桥梁。

索引结构图

                    ┌─────────────────────────────────────┐
                    │         工作区 (Working Dir)        │
                    │  ┌──────────┐  ┌──────────┐        │
                    │  │file1.txt │  │file2.txt │        │
                    │  │ (已修改) │  │ (未修改) │        │
                    │  └──────────┘  └──────────┘        │
                    └──────────────┬──────────────────────┘
                                   │ git add
                                   ▼
                    ┌─────────────────────────────────────┐
                    │            索引 (.git/index)         │
                    │  ┌──────────────────────────────┐  │
                    │  │ file1.txt → blob: abc123...  │  │
                    │  │ file2.txt → blob: def456...  │  │
                    │  │ (按路径排序,支持快速查找)    │  │
                    │  └──────────────────────────────┘  │
                    └──────────────┬──────────────────────┘
                                   │ git commit
                                   ▼
                    ┌─────────────────────────────────────┐
                    │           提交 (Commit)              │
                    │  ┌──────────────────────────────┐  │
                    │  │ tree: xyz789...              │  │
                    │  │ parent: ...                  │  │
                    │  │ message: "..."               │  │
                    │  └──────────────────────────────┘  │
                    └─────────────────────────────────────┘
                        

索引条目结构

# 每个条目包含:
# - ctime/mtime: 文件修改时间
# - dev/ino: 文件设备/索引节点
# - mode: 文件权限 (100644/100755/120000)
# - uid/gid: 用户/组ID
# - size: 文件大小
# - object_id: blob对象哈希
# - flags: 状态标志
# - path: 文件路径

# 索引按路径排序,支持二分查找

查看索引

# 查看索引内容(简洁)
git ls-files -s

# 查看索引详细信息
git ls-files --stage

# 查看暂存区文件状态
git diff --cached

# 查看索引统计信息
git ls-files --debug

# 查看索引的二进制内容
git ls-files --debug --format='%(objectname) %(path)'

git add 原理

# git add 执行流程:

# 1. 读取工作区文件内容
# 2. 计算内容的SHA-1哈希
# 3. 在objects目录中查找该哈希
# 4. 如果对象不存在,创建blob对象并存储
# 5. 更新索引,添加/更新文件条目

# 这就是为什么"添加"很快:
# - 内容未变则复用已有对象
# - 只更新索引,不立即提交
# - 增量更新,不复制整个文件

索引状态

# 文件的三种状态:

# 1. 未跟踪 (untracked)
# - 新文件,从未被add

# 2. 已暂存 (staged)
# - 在索引中,等待提交

# 3. 已修改 (modified)
# - 工作区与索引不一致

# 查看状态:
git status
提示:索引是工作区和提交之间的桥梁,决定了哪些文件会被提交。git add只是更新索引,不创建提交。

引用机制

理解Git如何通过引用定位对象和分支。

引用类型

# 1. HEAD - 当前分支引用
# .git/HEAD 内容: ref: refs/heads/main

# 2. 分支引用 - refs/heads/
# .git/refs/heads/main 内容: abc123... (commit哈希)

# 3. 远程引用 - refs/remotes/
# .git/refs/remotes/origin/main 内容: def456...

# 4. 标签引用 - refs/tags/
# .git/refs/tags/v1.0 内容: 789abc...

# 5. 特殊引用 - refs/stash, refs/original/*

引用关系图

                    ┌─────────────────────────────────────┐
                    │              HEAD                  │
                    │         ref: refs/heads/main       │
                    └─────────────────┬───────────────────┘
                                      │
                                      ▼
                    ┌─────────────────────────────────────┐
                    │      refs/heads/main (分支)          │
                    │            abc123def...             │
                    └─────────────────┬───────────────────┘
                                      │
                                      ▼
                    ┌─────────────────────────────────────┐
                    │            Commit                   │
                    │  tree: xyz789...                    │
                    │  parent: (上一提交)                 │
                    │  message: "..."                     │
                    └─────────────────────────────────────┘
                                      │
                                      ▼
                    ┌─────────────────────────────────────┐
                    │         refs/tags/v1.0 (标签)        │
                    │            abc123def...             │
                    └─────────────────────────────────────┘

                    ┌─────────────────────────────────────┐
                    │    refs/remotes/origin/main (远程)  │
                    │            def456ghi...             │
                    └─────────────────────────────────────┘
                        

引用解析

# 查看所有引用
git show-ref

# 查看特定引用
git show-ref heads/main

# 查看HEAD指向
git symbolic-ref HEAD

# 查看引用日志
git reflog show main

# 解析引用到commit
git rev-parse main

detached HEAD 状态

当HEAD直接指向commit而非分支引用时,称为detached HEAD状态。

                    正常状态:
                    HEAD → refs/heads/main → abc123... (commit)

                    Detached HEAD:
                    HEAD → abc123... (commit 直接指向)
                        
# 进入detached HEAD状态
git checkout abc123def

# 查看当前HEAD状态
cat .git/HEAD

# 从detached状态恢复
git checkout main

# 在detached状态下创建新分支
git checkout -b new-branch

轻量级标签 vs 带注释标签

# 轻量级标签(直接指向commit)
git tag v1.0
# .git/refs/tags/v1.0 内容: abc123...

# 带注释标签(指向tag对象)
git tag -a v1.0 -m "版本1.0"
# .git/refs/tags/v1.0 内容: def456... (tag对象)

# 查看标签类型
git cat-file -t refs/tags/v1.0
提示:引用是可变的文件,而对象是不可变的哈希,这种设计使Git高效且安全。分支、标签本质上都是指向commit的引用。

命令原理

深入理解常用Git命令的底层实现。

git commit 原理

# 执行步骤:
# 1. 基于索引创建tree对象
# 2. 读取当前HEAD获取父commit
# 3. 创建commit对象(包含tree、父commit、作者、消息)
# 4. 计算commit对象的SHA-1哈希
# 5. 更新当前分支引用指向新commit

# 验证commit内容:
git cat-file -p HEAD

# 查看commit的tree:
git cat-file -p HEAD | grep tree | awk '{print $2}' | xargs git cat-file -p

git merge 原理

# 执行步骤:
# 1. 找到两个分支的共同祖先(LCA)
# 2. 比较分支与祖先的差异(三方差异)
# 3. 使用祖先作为基准进行三方合并
# 4. 如果无冲突,创建merge commit(两个父commit)

# 三方合并算法:
# - 两个分支修改了不同区域 → 自动合并
# - 只有一个分支修改 → 采用该修改
# - 两个分支修改相同区域 → 产生冲突

三方合并示意图

                        A (共同祖先)
                       / \
                      /   \
                     B     C  (两个分支)
                      \   /
                       \ /
                        D  (merge commit)

                        三方合并:
                        - 以A为基准
                        - 比较A→B的变更
                        - 比较A→C的变更
                        - 合并到D
                        

git checkout 原理

# 执行步骤:
# 1. 更新HEAD引用指向目标分支
# 2. 读取目标commit的tree对象
# 3. 递归遍历tree,用blob更新工作区文件
# 4. 更新索引匹配新的tree
# 5. 删除工作区中不存在于新tree的文件

# 这就是为什么切换分支会改变文件!
# checkout本质是:更新HEAD + 恢复工作区 + 更新索引

git rebase 原理

# 执行步骤:
# 1. 找到当前分支和目标分支的共同祖先
# 2. 提取当前分支从祖先开始的所有commit
# 3. 暂存这些commit的变更
# 4. 将当前分支重置到目标分支
# 5. 在目标分支上依次重新应用每个commit
# 6. 为每个commit创建新的commit(新哈希)

# rebase vs merge:
# merge: 保留完整历史,有分支图
# rebase: 线性历史,重写提交哈希

rebase 示意图

                        Rebase 前:           Rebase 后:
                             A                       A
                            / \                        |
                           B   C                       C
                          / \                          |
                         D   E                         D'
                        /                             /|
                       F                             F' E'
                    
                        (B和C是共同祖先后的分支)
                        (D', E', F'是重新应用的commit)
                        

git diff 原理

# git diff(工作区 vs 暂存区)
# 比较工作区文件和索引中的blob对象

# git diff --cached(暂存区 vs HEAD)
# 比较索引和HEAD的tree对象

# git diff branch1 branch2
# 比较两个commit的tree对象

# 使用的是差异算法(如Myers算法)
# 找出最小的编辑序列将A转换为B

git pull 原理

# git pull = git fetch + git merge

# 执行步骤:
# 1. git fetch: 从远程拉取更新
# - 更新 refs/remotes/origin/*
# - 不修改工作区
# 2. git merge: 合并远程更新
# - 默认使用快进合并
# - 或创建merge commit

# git pull --rebase = git fetch + git rebase

git push 原理

# 执行步骤:
# 1. 打包本地objects
# 2. 发送到远程仓库
# 3. 更新远程引用(refs/heads/*)

# 快进推送:
# 本地提交是远程提交的后继

# 强制推送:
# 覆盖远程历史(谨慎使用)
提示:理解命令原理有助于更好地使用Git和解决复杂问题。所有Git操作本质都是创建新对象和更新引用。

Git 比较算法

深入了解Git如何计算文件和目录之间的差异。

Myers 差异算法

Git使用Myers差异算法来计算两个文本之间的最小编辑序列,这是最经典的diff算法之一。

算法核心思想

通过构建一个编辑图(Edit Graph),寻找从起点到终点的最短路径。每条路径代表一种编辑操作(插入、删除、匹配)。

编辑图示例:
文件A: ABCAB
文件B: ACBBC

        C   B   B   C
      ┌───┬───┬───┬───┐
    A │ × │ \ │ × │ \ │  (×=删除, \=对角线=匹配)
      ├───┼───┼───┼───┤
    B │ \ │ × │ \ │ × │
      ├───┼───┼───┼───┤
    C │ × │ \ │ × │ \ │
      ├───┼───┼───┼───┤
    A │ \ │ × │ \ │ × │
      ├───┼───┼───┼───┤
    B │ × │ \ │ × │ \ │
      └───┴───┴───┴───┘

最短路径 = 最少编辑操作
                        
时间复杂度
# 最坏情况:O(ND)
# N = 文件A的行数
# D = 最小编辑距离

# 实际应用中:通常接近O(N+M)
# M = 文件B的行数

# Git优化:使用二分查找和启发式加速

Patience Diff 算法

Git 2.11+引入的另一种diff算法,在某些场景下比Myers算法更符合人类直觉。

算法原理

寻找文件中"独特且有序"的共同行(unique common elements),作为锚点进行匹配。

文件A:           文件B:
1. import A       1. import A        ← 锚点(唯一且顺序一致)
2. function foo   2. function bar
3. const x = 1    3. const x = 1     ← 锚点
4. function bar   4. function foo
5. const y = 2    5. const y = 2     ← 锚点
6. export B       6. export B        ← 锚点

Patience Diff识别锚点后,在锚点之间使用Myers算法
                        
适用场景
✅ 函数或代码块重新排序
✅ 大量相似的重复代码
✅ 结构性重构

❌ 纯文本替换
❌ 微小的局部修改

Histogram Diff 算法

Git默认的diff算法,结合了Myers和Patience的优点,使用直方图统计来优化匹配。

算法特点
# 1. 统计每行出现的次数(直方图)
# 2. 优先匹配出现次数少的行(更可能是锚点)
# 3. 在锚点之间使用Myers算法
# 4. 对锚点附近的行进行局部优化

# 优势:
# - 比纯Myers更符合人类直觉
# - 比Patience diff适用范围更广
# - 性能优化更好

diff 算法对比

算法 速度 准确性 可读性 使用场景
Myers ★★★☆☆ ★★★★☆ ★★★☆☆ 通用,Git默认
Patience ★★☆☆☆ ★★★★★ ★★★★★ 代码重排
Histogram ★★★★☆ ★★★★☆ ★★★★☆ 现代Git默认
Minimal ★☆☆☆☆ ★★★★★ ★★★☆☆ 精确分析

切换 diff 算法

# 使用Patience diff
git diff --patience

# 使用Histogram diff(默认)
git diff --histogram

# 使用Myers diff
git diff --minimal

# 全局配置默认算法
git config --global diff.algorithm histogram

# 仓库级别配置
git config diff.algorithm patience

diff 优化技巧

# 忽略空白字符差异
git diff --ignore-space-at-eol
git diff --ignore-space-change
git diff --ignore-all-space

# 单词级别的diff
git diff --word-diff
git diff --word-diff=color

# 限制上下文行数
git diff -U3 # 只显示3行上下文

# 忽略特定目录的diff
git diff -- . ':!node_modules'

# 使用外部diff工具
git difftool --tool=vimdiff
提示:Histogram diff是Git 2.9.1+的默认算法,它在大多数情况下提供了最佳的平衡。对于特殊的diff需求,可以临时切换算法或使用外部工具。

分支合并原理

深入理解Git如何合并不同分支的更改。

合并基础概念

Git合并的核心是找到共同祖先(Common Ancestor),然后进行三方合并(3-way merge)。

                        ┌─────────────────────────────────────┐
                        │         合并前状态                   │
                        └─────────────────────────────────────┘
                                     A (共同祖先)
                                    / \
                          分支1:   B   C   分支2
                                   |   |
                                   D   E
                        
                        合并 main ← feature:
                        找到共同祖先: A
                        合并 B→D 和 C→E 的变更
                        结果: 新的merge commit
                        

三方合并算法

Git使用递归三方合并(Recursive 3-way merge)算法,这是最常用的合并策略。

合并步骤
# 1. 找到两个分支的共同祖先(LCA)
# 2. 比较 祖先→分支1 的变更(diff1)
# 3. 比较 祖先→分支2 的变更(diff2)
# 4. 逐文件合并:
# - 如果只在diff1中修改 → 采用diff1
# - 如果只在diff2中修改 → 采用diff2
# - 如果都修改了同一行 → 产生冲突
# - 如果都修改了不同行 → 自动合并
# 5. 创建merge commit(两个父commit)
合并示例
共同祖先 (A):
const x = 1;
const y = 2;
const z = 3;

分支1 (B):          分支2 (C):         合并结果:
const x = 10;       const x = 1;        const x = 10;   ← 冲突!
const y = 20;       const y = 2;        const y = 20;   ← 冲突!
const z = 3;        const z = 30;       const z = 30;   ← 自动合并

冲突标记:
<<<<<<< HEAD
const x = 10;
const y = 20;
=======
const x = 1;
const y = 2;
>>>>>>> feature
                        

递归合并策略

当存在多个共同祖先时,Git使用递归合并策略。

递归合并原理
                        多个共同祖先的情况:
                             A (共同祖先1)
                            / \
                           B   C
                          / \ / \
                         D   E   F (两个共同祖先: D, F)
                          \ /   /
                           G   H
                            \ /
                             I (合并点)

                        递归合并步骤:
                        1. 找到所有共同祖先: [D, F]
                        2. 合并 D 和 F (虚拟祖先)
                        3. 使用虚拟祖先进行三方合并
                        
                        优势:
                        - 处理复杂的交叉合并
                        - 减少冲突
                        - 更智能的合并决策
                        

合并策略类型

策略 命令 描述 适用场景
recursive git merge 递归三方合并(默认) 大多数场景
resolve -s resolve 简单的三方合并 快速合并,冲突少
octopus 自动选择 合并多个分支 合并3+分支
ours -s ours 保留当前分支 丢弃其他分支
subtree -s subtree 子树合并 子模块替代

冲突解决原理

当两个分支修改了同一行内容时,Git无法自动决定采用哪个版本,产生冲突。

冲突标记格式
<<<<<<< HEAD (当前分支的修改)
当前分支的内容
======= (分隔符)
合并分支的内容
>>>>>>> feature (合并分支的修改)

# 解决冲突后运行:
git add
git commit
冲突类型
# 1. 内容冲突
# - 两个分支修改了同一行
# - 相邻的修改导致无法自动合并

# 2. 树冲突
# - 一个分支重命名文件,另一个修改
# - 一个分支删除文件,另一个修改

# 3. 二进制冲突
# - 二进制文件无法diff
# - 需要手动选择版本

合并冲突检测优化

# 设置冲突检测粒度
git config --global merge.conflictstyle diff3

# diff3 风格包含共同祖先内容
<<<<<<< HEAD
当前版本
||||||| merged common ancestors
共同祖先版本
=======
合并版本
>>>>>>> feature

# 使用外部合并工具
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'

快进合并 (Fast-forward)

当目标分支是当前分支的直接后继时,可以使用快进合并。

                        快进合并前:         快进合并后:
                        main:   A ← B      main:   A ← B ← C
                                    ↑
                                feature:
                                A ← B ← C
                        
                        条件: feature 是 main 的直接后继
                        结果: 简单地移动指针,无额外commit
                        
                        禁用快进:
                        git merge --no-ff feature
                        
                        保留完整历史:
                         A ← B ← C ← D (merge commit)
                             \_____/
                        
# 允许快进合并(默认)
git merge feature

# 禁用快进合并
git merge --no-ff feature

# 仅快进合并
git merge --ff-only feature

Rebase 合并 vs Merge 合并

                        Merge 合并:
                            A---B---C---D (main)
                                 \       \
                                  E---F---G (merge)
                        
                        优点: 保留完整历史
                        缺点: 历史图复杂
                        
                        Rebase 合并:
                            A---B---C---D (main)
                                    \
                                     E'---F' (rebase后)
                        
                        优点: 线性历史,简洁
                        缺点: 重写历史,改变commit哈希
                        
# Merge: 保留分支历史
git merge feature

# Rebase: 线性化历史
git rebase main
git merge feature

合并性能优化

# 限制合并历史搜索范围
git merge --strategy-option patience

# 跳过冲突文件的自动合并
git merge --strategy-option theirs

# 使用稀疏合并(大仓库)
git sparse-checkout init
git sparse-checkout set src

# 并行合并(Git 2.27+)
git -c merge.parallelism=8 merge feature
提示:理解合并原理有助于更好地处理冲突。大多数情况下,使用默认的recursive策略即可。对于特殊场景,可以选择其他策略或使用外部工具辅助。

本地与远程分支关系

深入理解本地分支和远程分支的映射关系和同步机制。

远程分支概念

远程分支(remote branch)是远程仓库状态的本地引用,存储在refs/remotes/目录下。

远程分支特点
# 1. 只读引用
# - 不能直接修改
# - 通过fetch/push更新

# 2. 缓存远程状态
# - 反映上次fetch时的远程状态
# - 不是实时同步的

# 3. 独立于本地分支
# - origin/main ≠ main
# - 它们是独立的commit引用
远程分支存储结构:
.git/refs/remotes/
└── origin/
    ├── main          (远程main分支)
    ├── develop       (远程develop分支)
    ├── feature/login (远程feature/login分支)
    └── HEAD          (默认分支引用)

查看远程分支:
git branch -r
git show-ref refs/remotes/origin/main
                        

本地分支与远程分支的映射

本地分支和远程分支通过"上游分支"(upstream)概念建立关联。

上游分支设置
# 设置上游分支(首次push)
git push -u origin main
# 等同于:
git push origin main
git branch --set-upstream-to=origin/main main

# 查看上游分支
git branch -vv

# 修改上游分支
git branch --set-upstream-to=origin/develop main
本地分支配置(.git/config):
[branch "main"]
    remote = origin
    merge = refs/heads/main

这表示:
- 本地main分支跟踪origin远程仓库
- 合并目标是origin/main分支

查看配置:
git config branch.main.remote
git config branch.main.merge
                        

分支关系示意图

                        远程仓库 (GitHub):
                            main: A ← B ← C

                        本地仓库:
                            本地main分支
                                ↓ (上游)
                            origin/main (远程引用)
                                ↓ (fetch后)
                            main: A ← B ← C
                            
                        工作流程:
                        
                        1. 初始状态 (克隆后):
                           main (本地) = origin/main = 远程main
                        
                        2. 本地提交后:
                           远程main:  A ← B ← C
                           origin/main: A ← B ← C
                           main (本地): A ← B ← C ← D ← E
                           
                        3. push后:
                           远程main:  A ← B ← C ← D ← E
                           origin/main: A ← B ← C ← D ← E
                           main (本地): A ← B ← C ← D ← E
                           
                        4. 远程有新提交后:
                           远程main:  A ← B ← C ← D ← E ← F
                           origin/main: A ← B ← C ← D ← E (未fetch)
                           main (本地): A ← B ← C ← D ← E
                           
                        5. fetch后:
                           远程main:  A ← B ← C ← D ← E ← F
                           origin/main: A ← B ← C ← D ← E ← F
                           main (本地): A ← B ← C ← D ← E
                           
                        6. merge后:
                           远程main:  A ← B ← C ← D ← E ← F
                           origin/main: A ← B ← C ← D ← E ← F
                           main (本地): A ← B ← C ← D ← E ← F
                        

fetch 更新机制

git fetch从远程仓库获取最新数据,更新远程分支引用。

fetch 执行过程
# 1. 连接到远程仓库
# 2. 获取远程的引用列表
# 3. 下载缺失的对象(commits, trees, blobs)
# 4. 更新 refs/remotes/* 引用
# 5. 不修改工作区和本地分支

# 注意:
# - 不自动合并到本地分支
# - 只更新远程引用
# - 可以安全地随时执行
fetch 命令示例
# 获取所有远程更新
git fetch

# 获取特定远程仓库
git fetch origin

# 获取特定分支
git fetch origin main

# 获取所有远程仓库
git fetch --all

# 获取并修剪已删除的远程分支
git fetch --prune

push 同步机制

git push将本地提交推送到远程仓库,更新远程分支。

push 执行过程
# 1. 打包本地objects(增量)
# 2. 发送到远程仓库
# 3. 远程验证(权限、快进检查)
# 4. 更新远程引用
# 5. 触发远程hooks(如果配置)

# 快进检查:
# - 本地分支必须是远程分支的后继
# - 否则需要强制推送或先pull
push 命令示例
# 推送当前分支到上游
git push

# 推送指定分支
git push origin main

# 推送并设置上游
git push -u origin feature

# 推送所有分支
git push --all

# 推送标签
git push --tags

# 强制推送(谨慎使用)
git push --force
git push --force-with-lease

pull 合并机制

git pullgit fetchgit merge的组合。

pull 执行过程
# git pull = git fetch + git merge

# 1. git fetch origin
# - 更新 refs/remotes/origin/*
# 2. git merge origin/main
# - 合并远程更新到当前分支

# git pull --rebase = git fetch + git rebase
# - 先fetch,然后rebase当前分支
                        pull merge vs pull rebase:
                        
                        场景: 本地和远程都有新提交
                        
                        pull merge (默认):
                        
                        远程main:    A ← B ← C
                        本地main:    A ← B ← D
                        pull后:      A ← B ← C ← E ← D
                                      \_____/
                                   (merge commit)
                        
                        pull rebase:
                        
                        远程main:    A ← B ← C
                        本地main:    A ← B ← D
                        pull后:      A ← B ← C ← D'
                                              (rebased)
                        

分支追踪关系查看

# 查看分支和上游关系
git branch -vv

# 输出示例:
# * main abc123 [origin/main: ahead 2, behind 1] Add feature
# develop def456 [origin/develop] Update code
# feature ghi789 [origin/feature: gone] Old feature

# 含义:
# - ahead 2: 本地领先远程2个提交
# - behind 1: 本地落后远程1个提交
# - gone: 远程分支已被删除

# 查看远程分支详情
git remote show origin

# 查看本地和远程的差异
git log HEAD..origin/main

远程分支删除与清理

# 删除远程分支
git push origin --delete feature
# 或
git push origin :feature

# 删除本地已删除的远程分支引用
git fetch --prune
# 或
git remote prune origin

# 查看已删除的远程分支引用
git branch -r --merged
git branch -r --no-merged

多远程仓库管理

一个本地仓库可以关联多个远程仓库。

# 添加多个远程仓库
git remote add origin https://github.com/user/repo.git
git remote add upstream https://github.com/original/repo.git
git remote add fork https://github.com/fork/repo.git

# 查看所有远程仓库
git remote -v

# 从不同远程拉取
git fetch origin
git fetch upstream

# 推送到不同远程
git push origin main
git push fork feature

# 删除远程仓库
git remote remove fork
多远程仓库配置(.git/config):
[remote "origin"]
    url = https://github.com/user/repo.git
    fetch = +refs/heads/*:refs/remotes/origin/*

[remote "upstream"]
    url = https://github.com/original/repo.git
    fetch = +refs/heads/*:refs/remotes/upstream/*

常用场景: Fork项目
- origin: 自己的fork仓库
- upstream: 原始项目仓库
- 定期从upstream获取更新,推送到origin
                        

远程分支同步最佳实践

# 1. 定期获取更新
git fetch --all --prune

# 2. 查看状态再操作
git status
git branch -vv

# 3. 使用rebase保持历史整洁
git pull --rebase

# 4. 推送前先拉取
git pull --rebase origin main
git push origin main

# 5. 谨慎使用强制推送
git push --force-with-lease # 比较安全
# 而不是
git push --force # 危险
提示:理解本地和远程分支的关系是协作开发的基础。记住:远程分支是只读的本地引用,通过fetch/push同步。使用git fetch --prune定期清理已删除的远程分支引用。