Git

技术栈
工具链
version-controldvcsgithubgitlabcollaboration

概览

Git 技术栈概览

Git 是 Linus Torvalds 于 2005 年创建的分布式版本控制系统(DVCS),为解决 Linux 内核开发协作问题而生。每个开发者本地拥有完整仓库副本,不依赖中央服务器即可进行提交、分支、合并等操作。

解决什么问题

  • 代码变更无记录 → commit 快照保存每次变更
  • 多人协作冲突 → 分支+合并机制
  • 版本回退困难 → git reset/revert 精确回退
  • 代码丢失风险 → 分布式架构,每人都有完整备份
  • 发布管理混乱 → tag + release 标记版本

关键特性

  • 分布式:每个 Clone 都是完整仓库(含全部历史)
  • 快照存储:每次 commit 是整个项目状态快照(非文件差异)
  • 分支即指针:分支创建快如闪电(40 字节指针移动)
  • 暂存区(Index):工作区 → 暂存区 → 仓库 三阶段
  • SHA-1 哈希:所有内容校验和,不可篡改
  • GitHub/GitLab 生态:PR/MR 协作流、CI/CD 集成

安装

环境准备

  • OS:全平台支持(Linux/macOS/Windows)
  • GitHub/GitLab 账号:远程仓库托管(可选)

安装命令

Linux

# Debian/Ubuntu
sudo apt install git

# Fedora
sudo dnf install git

# Arch
sudo pacman -S git

macOS

# 系统自带旧版,推荐 Homebrew 获得最新版
brew install git

Windows

winget install Git.Git
# 或下载 Git for Windows: https://git-scm.com/download/win

初始配置

git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git config --global init.defaultBranch main
git config --global core.autocrlf input  # macOS/Linux
# git config --global core.autocrlf true  # Windows

验证

git --version

常见问题

Q1: git pushPermission denied (publickey)

SSH Key 未配置或未添加到 GitHub。生成并添加:

ssh-keygen -t ed25519 -C "your@email.com"
cat ~/.ssh/id_ed25519.pub  # 复制到 GitHub Settings → SSH Keys

Q2: Windows 换行符警告 LF will be replaced by CRLF

配置 core.autocrlf true(Windows)或 input(macOS/Linux)。

Q3: fatal: not a git repository

当前目录不在 Git 仓库中,cd 到仓库目录或 git init

示例

Git 例程:分支协作完整流程

目标

实操 Git 核心流程:init → add → commit → branch → merge → tag,覆盖单人开发到多人协作。

完整操作

# ═══ 初始化 ═══
git init my-project
cd my-project

# ═══ 第一次提交 ═══
echo "# My Project" >; README.md
git add README.md              # 加入暂存区
git commit -m "feat: 初始化项目"

# ═══ 查看状态与历史 ═══
git status                     # 工作区状态
git log --oneline --graph      # 提交历史(图形化)

# ═══ 创建功能分支 ═══
git checkout -b feature/login  # 创建并切换

echo "function login() {}" >; auth.js
git add auth.js
git commit -m "feat: 添加登录函数"

echo "function logout() {}" >;> auth.js
git add auth.js
git commit -m "feat: 添加登出函数"

# ═══ 切回主分支 ═══
git checkout main
git log --oneline              # feature/login 的提交不在这里!

# ═══ 合并分支 ═══
git merge feature/login        # fast-forward 或三方合并
# 如果没有冲突,自动完成

# ═══ 模拟冲突 ═══
git checkout -b feature/config
echo "const HOST = 'localhost'" >; config.js
git add config.js &;& git commit -m "config: 本地配置"

git checkout main
echo "const HOST = 'production'" >; config.js
git add config.js &;& git commit -m "config: 生产配置"

git merge feature/config        # ⚠️ 冲突!
# 手动编辑 config.js 解决冲突标记
# <<<<<<< HEAD
# const HOST = 'production'
# =======
# const HOST = 'localhost'
# >>>>>>> feature/config

echo "const HOST = process.env.HOST || 'localhost'" >; config.js
git add config.js
git commit -m "merge: 解决配置冲突"

# ═══ 打标签 ═══
git tag v1.0.0 -m "首次发布"
git tag                         # 查看所有标签

# ═══ 查看差异 ═══
git diff HEAD~1                 # 与上一次提交的差异
git diff main feature/login     # 分支间差异

# ═══ 回退操作 ═══
# 撤销工作区修改(未 add)
git checkout -- config.js

# 撤销暂存区(已 add 未 commit)
git reset HEAD config.js

# 撤销最近一次提交(保留修改)
git reset --soft HEAD~1

# ═══ 切出某个提交(detached HEAD) ═══
git checkout <;commit-hash>
git checkout main               # 回来

分支策略速查

策略 说明
Git Flow main + develop + feature/release/hotfix
GitHub Flow main + feature branches + PR
Trunk-Based main 直接提交 + 短命分支 + feature flag

.gitignore 示例

node_modules/
dist/
.env
*.log
.DS_Store

关键要点

  • 暂存区让 commit 更精细(只提交部分修改)
  • 分支是廉价指针——大胆创建和删除
  • rebase vs merge:rebase 保持历史线性但重写历史;merge 保留真实合并记录
  • git stash 临时保存未提交修改,切换分支后 git stash pop

教程

Git 版本控制入门到协作教程

第一章:Git 的三种状态

工作目录        暂存区          Git 仓库
(Working)  →  (Staging)  →  (Repository)
   ↑              ↑              ↑
  edit        git add        git commit
                ↑
          git reset HEAD

commit 内部结构

每次 commit 是一个完整快照(非差异):

Commit Object → Tree Object → Blob (文件内容)
                           → Tree (子目录)
              → parent Commit

第二章:分支本质

Git 分支是一个指向 commit 的40 字节 SHA-1 指针

main:    refs/heads/main → a1b2c3
feature: refs/heads/feature → d4e5f6

HEAD → refs/heads/feature  (当前在 feature 分支)

这就是为什么:

  • 创建分支几乎瞬间完成(写一个指针文件)
  • 切换分支修改 HEAD 指向
  • git checkout -b = git branch + git checkout

第三章:合并策略对比

Fast-Forward(快进)

main:    A---B
feature:       C---D
合并后:  A---B---C---D  (main 直接移动到 D)

条件:feature 基于 main 最新 commit。

Three-Way Merge

main:    A---B---E
feature:       C---D
合并后:  A---B---E---M  (三方合并节点)

条件:两分支各有提交,不能快进。

Rebase

main:    A---B---E
feature:       C---D
变基后:  A---B---E---C'---D'  (历史线性)

适合个人分支整理,不要 rebase 公共分支

第四章:远程协作

git remote add origin git@github.com:user/repo.git
git push -u origin main
git pull origin main           # = fetch + merge
git fetch origin               # 仅下载不合并

Pull Request (PR) 流程

  1. Fork 或创建 feature 分支
  2. 提交并 push 到远程
  3. 在 GitHub 发起 PR
  4. Code Review → CI 通过 → Merge

第五章:常用场景速查

场景 命令
撤销最后一次 commit(保留改动) git reset --soft HEAD~1
修改最后一次 commit 信息 git commit --amend -m "new msg"
临时保存工作区 git stash / git stash pop
查看某文件谁改过 git blame filename
查找哪个 commit 引入 bug git bisect
cherry-pick 单 commit git cherry-pick <hash>
删除远程 branch git push origin --delete branch

思考题

  1. git mergegit rebase 的根本区别是什么?各自适用场景?
  2. detached HEAD 状态是什么?什么时候会进入这个状态?
  3. .git 目录里有什么?objects/refs/ 各存什么?

参考资料

暂无参考文献