Skip to content

Git

作者:青见春山
发表于:2026-07-29
字数统计:5500 字
预计阅读19分钟

涵盖 Git rebase vs merge、Git 三大区、常用命令速查、Git Flow、撤销与回滚。

一、Git 三大区

Plain
┌──────────────┐   git add    ┌──────────────┐   git commit   ┌──────────────┐
│ Working      │ ─────────→ │ Staging       │ ───────────→ │ Repository    │
│ Directory    │            │ Area (Index)  │              │ (.git)        │
│ (工作区)      │   git reset │ (暂存区)       │  git reset    │ (版本库)      │
│              │ ←───────── │               │ ←─────────── │              │
└──────────────┘   --        └──────────────┘   --          └──────────────┘
                          (撤销暂存)                      (回退版本)

二、git rebase vs git merge

1. 概念

Plain
共同目标:把分支合并到目标分支

merge:
- 在目标分支上创建一个 merge commit
- 保留分支历史(保留"合并动作")
- 历史是分叉的图状结构

rebase:
- 把当前分支的 commit 重新"接到"目标分支最新 commit 之后
- 改写 commit 历史(commit hash 会变)
- 历史是线性结构

2. 实际效果对比

Plain
初始状态:
A---B---C  (master)
     \
      D---E  (feature)

git checkout feature
git merge master:

A---B---C---F  (master)
     \       /
      D---E    (feature)

          merge commit

git checkout feature
git rebase master:

A---B---C---D'---E'  (feature)

     master 指针

效果:feature 分支的 commit 被"重新接到" master 最新 commit 之后

3. 优缺点

维度mergerebase
历史真实(保留分叉)整洁(线性)
commit hash不变变化(被改写)
冲突处理一次合并冲突每个 commit 可能都冲突
回溯简单(保留 commit)复杂(commit hash 变了)
适用场景公共分支、保留历史本地分支、整理提交

4. 黄金法则

Plain
默认不要改写其他协作者已经基于其开发的公共历史;只有团队明确协调、了解影响并允许重写时才考虑这样做。

原因:
- rebase 会改写 commit hash
- 其他人的分支会与远程不一致
- 导致协作混乱

安全使用:
- 仅对自己本地的、还未推送的分支使用 rebase
- 团队约定主分支不用 rebase
- rebase 后强制推送前确认(git push --force-with-lease)

5. 实战命令

Bash
# 基础 rebase
git checkout feature
git rebase master  # 把 feature 接到 master 最新 commit 后

# 解决冲突
# 1. 编辑冲突文件
# 2. git add <冲突文件>
# 3. git rebase --continue
# 4. 如要放弃:git rebase --abort

# 交互式 rebase(整理 commit)
git rebase -i HEAD~3  # 修改最近 3 个 commit
# 命令:
# pick = 保留
# reword = 修改 commit 信息
# edit = 修改 commit 内容
# squash = 合并到前一个 commit
# drop = 删除 commit

6. 合并策略选择

Plain
团队分支流程:
1. 在 feature 分支开发
2. 提交前先 git fetch + git rebase origin/master
3. 解决冲突后,再合并到 master(用 merge)
4. 这种方式:master 历史线性,feature 历史保留

即:本地 rebase + 远程 merge

三、Git 常用命令速查

1. 仓库操作

Bash
# 初始化
git init
git clone <url>

# 配置
git config --global user.name "Your Name"
git config --global user.email "your@email.com"

# 远程仓库
git remote add origin <url>
git remote -v
git push -u origin main

2. 基本操作

Bash
# 查看状态
git status

# 添加到暂存区
git add <file>          # 单个文件
git add .               # 所有修改
git add -p              # 交互式添加(推荐)

# 提交
git commit -m "feat: 新增功能"
git commit --amend      # 修改最后一次提交(重新写信息或追加改动)

# 查看历史
git log
git log --oneline --graph
git log -p <file>       # 查看某文件的历史修改

3. 撤销与回滚

Bash
# 撤销工作区修改
git checkout -- <file>
git restore <file>      # 新版命令

# 撤销暂存
git reset HEAD <file>
git restore --staged <file>

# 回退版本
git reset --soft HEAD^       # 撤销 commit,保留修改在暂存区
git reset --mixed HEAD^      # 撤销 commit + 暂存,保留修改在工作区(默认)
git reset --hard HEAD^       # 撤销一切(危险!)

# 安全回退(推荐)
git revert <commit>          # 生成新 commit 撤销指定 commit(适合已推送)

# 找回丢失的 commit
git reflog                   # 查看所有 HEAD 移动记录

4. 分支操作

Bash
# 创建与切换
git branch <name>
git checkout -b <name>       # 创建并切换
git switch -c <name>         # 新版命令

# 查看分支
git branch -a                # 所有分支(含远程)
git branch -vv               # 带跟踪信息

# 合并与衍合
git merge <branch>
git rebase <branch>

# 删除分支
git branch -d <name>         # 安全删除(合并后才能删)
git branch -D <name>         # 强制删除

5. 远程操作

Bash
# 拉取与推送
git fetch            # 只拉取,不合并
git pull             # fetch + merge(默认)
git pull --rebase    # fetch + rebase(推荐)

# 推送
git push
git push -f          # 强制推送(危险!)
git push --force-with-lease  # 安全强制推送(推荐)

# 远程分支
git push origin --delete <branch>  # 删除远程分支

6. 储藏(Stash)

Bash
# 临时保存工作区修改
git stash
git stash save "message"

# 查看
git stash list

# 恢复
git stash pop           # 恢复并删除
git stash apply stash@{0}  # 恢复但保留

# 删除
git stash drop stash@{0}
git stash clear         # 清除所有

四、Git Flow 工作流

Plain
Git Flow 是一种经典的工作流,适合有版本发布周期的项目:

master(主分支)         —— 稳定版本,每个 commit 都是一个 release
develop(开发分支)       —— 日常开发
feature/*(功能分支)    —— 新功能,从 develop 切出,完成后合并回 develop
release/*(发布分支)    —— 版本发布准备,从 develop 切出,发布后合并到 master + develop
hotfix/*(热修复分支)    —— 紧急修复,从 master 切出,修复后合并回 master + develop

工作流:
1. 从 develop 切出 feature/login
2. 开发完成,PR 到 develop
3. 准备发布,从 develop 切出 release/v1.0
4. 测试通过,合并 release/v1.0 到 master(打 tag)和 develop
5. 上线后如有问题,从 master 切出 hotfix/bug
6. 修复后合并回 master 和 develop

简化版:GitHub Flow

Plain
GitHub Flow(适合持续部署):
1. master 永远是可部署的
2. 从 master 切出功能分支
3. 在功能分支提交
4. 提 PR(Pull Request)
5. Code Review 后合并回 master
6. 合并后自动部署

简单直接,适合现代 SaaS 项目

五、冲突解决

Plain
冲突发生的场景:
1. 两个分支修改了同一文件的同一行
2. 一个分支删除了文件,另一个分支修改了文件

冲突标记:
<<<<<<< HEAD
当前分支的内容
=======
合并分支的内容
>>>>>>> branch-name

解决步骤:
1. git status 看哪些文件冲突
2. 编辑冲突文件,决定保留哪部分
3. 删除冲突标记
4. git add <file>
5. git commit(或 git rebase --continue)

六、面试高频问答

Q1: git rebase 和 git merge 的区别?

  • merge:在目标分支创建一个 merge commit,保留分支历史(分叉结构)
  • rebase:把当前分支的 commit 重新接到目标分支最新 commit 之后,改写历史(线性结构)

协作原则:不要在未协调的情况下 rebase 并强推共享分支;若团队明确允许历史重写,应通知协作者并优先使用 --force-with-lease,同时理解它也不是并发写入的绝对保险。

实战选择

  • 自己本地分支:用 rebase(整理历史)
  • 团队协作:用 merge(保留真实历史)
  • 推荐模式:本地 rebase + 远程 merge

Q2: git reset 和 git revert 的区别?

  • git reset:回退到指定 commit,改写历史(不推荐用于已推送)
    • --soft:保留修改在暂存区
    • --mixed:保留修改在工作区(默认)
    • --hard:完全丢弃修改(危险)
  • git revert:生成一个新的 commit,撤销指定 commit 的改动(适合已推送)
    • 不会改写历史
    • 会保留原 commit 记录

Q3: 怎样找回被 reset --hard 的 commit?

Bash
# 1. git reflog 查看所有 HEAD 移动
git reflog

# 2. 找到目标 commit hash
# a1b2c3d HEAD@{5}: commit: feat: 提交功能

# 3. 重置回去
git reset --hard a1b2c3d

# 注意:reflog 只在本地保留 30-90 天(取决于 gc 设置)

Q4: git pull 和 git pull --rebase 的区别?

  • git pull = git fetch + git merge
  • git pull --rebase = git fetch + git rebase

如果本地有未推送的 commit,merge 会产生 merge commit,rebase 会让本地 commit 接到远程最新 commit 之后(保持线性历史)。

推荐:默认用 git pull --rebase,可以通过配置设为默认:

Bash
git config --global pull.rebase true

七、关联文档