Skip to content

git ​

config ​

1. 临时修改用户名和邮箱 ​

如果只需要修改当前仓库的提交者信息,可以使用以下命令:

bash
git config user.name "新用户名"
git config user.email "新邮箱"

2. 全局修改用户名和邮箱 ​

bash
git config --global user.name "新用户名"
git config --global user.email "新邮箱"

remote ​

1. 查看当前远程地址 ​

bash
git remote -v

2. 修改远程地址 ​

bash
git remote set-url origin NEW_REMOTE_URL

3. 验证修改 ​

bash
git remote -v

4. 推送到新地址 ​

bash
git push origin main

5. 添加或替换其他远程地址 ​

bash
git remote add NAME NEW_REMOTE_URL

6. 删除远程地址 ​

bash
git remote remove NAME
操作命令
修改远程地址git remote set-url origin NEW_URL
添加远程地址git remote add NAME NEW_URL
删除远程地址git remote remove NAME

撤销修改 ​

1. 丢弃已暂存的修改 ​

bash
git reset HEAD FILE
  • git reset HEAD FILE 会将指定文件从暂存区移回工作区,修改仍然保留在工作区中,但不会再被标记为已暂存。

2. 丢弃工作区的修改 ​

bash
git checkout -- FILE
  • git checkout -- FILE 会将文件恢复到上一次提交时的状态,丢弃工作区中的修改
场景命令
仅取消暂存区的修改git reset HEAD FILE
取消暂存区修改并恢复文件内容git reset HEAD FILE → git checkout -- FILE

Git 三步曲 ​

Git 的核心工作流围绕本地仓库与远程仓库之间的同步展开:

text
工作区 → 暂存区 → 本地仓库 → 远程仓库
  edit    add     commit     push
                        ← pull ←
步骤作用为什么不可或缺
commit将暂存区的变更提交到本地仓库,形成一个新的提交节点没有commit,你的修改只停留在本地,无法被版本管理追踪
pull从远程仓库拉取最新代码并合并到本地没有pull,你可能在过时的代码基础上push,导致冲突或覆盖他人工作
push将本地提交推送到远程仓库,与团队共享没有push,你的commit只存在于本地,团队成员看不到你的成果

顺序逻辑:

  1. 先 commit:先固化自己的工作成果,确保有据可查
  2. 再 pull:获取他人最新工作,尽早发现冲突,在本地解决比远程解决更安全
  3. 后 push:在确认本地与远程一致后,安全地推送

⚠️ 如果先 push 再 pull,可能直接覆盖远程的他人提交;如果先 pull 再 commit,可能在过时代码上开发,后续合并更痛苦。

commit ​

git commit [options]

参数说明示例
-m [msg]直接指定提交信息,不打开编辑器git commit -m "feat: 添加用户登录接口"
-a自动暂存所有已跟踪文件的修改(跳过 git add)git commit -a -m "fix: 修复空指针异常"
--amend修改上一次提交(追加修改或改写提交信息)git commit --amend -m "feat: 更新登录逻辑"
--no-verify跳过 pre-commit 和 commit-msg 钩子(慎用)git commit --no-verify -m "wip: 临时提交"
--allow-empty允许提交空变更(常用于 CI 触发)git commit --allow-empty -m "chore: 触发部署"
-s / --signoff在提交信息末尾追加 Signed-off-by 签名git commit -s -m "feat: 新功能"
--author=[author]指定作者(覆盖 git config user)git commit --author="Alice [a@b.com]" -m "..."
--date=[date]指定提交日期git commit --date="2026-01-01T00:00:00" -m "..."

常用组合:

bash

bash
git commit -am "fix: 修复分页查询bug"
# 等价于 git add -u && git commit -m "fix: 修复分页查询bug"

💡 提交信息规范(Conventional Commits):

  • feat: 新功能 | fix: 修复 | docs: 文档 | refactor: 重构
  • style: 格式 | test: 测试 | chore: 构建/工具

pull ​

git pull [options] [remote [branch]]

参数说明示例
(无参数)默认 git fetch + git mergegit pull
--rebase用 rebase 代替 merge 合并,保持线性历史git pull --rebase
--no-rebase强制使用 merge 合并(显式指定)git pull --no-rebase
--ff-only仅允许快进合并,有分歧则拒绝(最安全)git pull --ff-only
--no-ff禁止快进,始终产生合并提交git pull --no-ff
--commit合并后自动提交(默认行为)git pull --commit
--no-commit合并但不自动提交,可先审查git pull --no-commit
--squash将远程提交压缩为一个,不自动提交git pull --squash
--tags同时拉取远程标签git pull --tags
--depth=<n>浅克隆,仅拉取最近 n 层提交历史git pull --depth=1
--allow-unrelated-histories允许合并不相关的历史git pull --allow-unrelated-histories

常用组合:

bash
git pull --rebase origin main
# 拉取 origin/main 并以 rebase 方式合并,历史更整洁

💡 merge vs rebase 选择:

  • merge:保留完整分支历史,安全但历史图复杂
  • rebase:线性历史,更整洁,但改写了提交的基底(公共分支慎用)
  • 推荐:个人分支用 --rebase,公共分支用 merge

push ​

git push [options] [remote [refspec...]]

参数说明示例
(无参数)推送当前分支到对应上游分支git push
-u / --set-upstream推送并设置上游跟踪分支(首次推送必用)git push -u origin feature/login
--force / -f强制推送,覆盖远程历史(⚠️ 危险)git push --force
--force-with-lease安全版强制推送,仅当远程未被他人更新时才覆盖git push --force-with-lease
--all推送所有本地分支git push --all origin
--tags推送所有本地标签git push --tags
--delete删除远程分支git push --delete origin old-branch
--dry-run模拟推送,不实际执行(预检查)git push --dry-run
--no-verify跳过 pre-push 钩子git push --no-verify
--prune推送时删除远程已不存在的本地分支的跟踪引用git push --prune

常用组合:

bash
git push -u origin feature/login   # 首次推送新分支并建立跟踪
git push --force-with-lease        # rebase 后安全强制推送
git push origin --delete feature/old  # 删除远程分支

💡 force-with-lease vs force:

  • --force:无条件覆盖,可能丢失他人提交
  • --force-with-lease:如果远程分支已被他人更新,推送会被拒绝,更安全

branch ​

1. 查看分支 ​

bash
git branch
git branch -a
git branch -r

2. 创建分支 ​

bash
git branch BRANCH_NAME
git checkout -b BRANCH_NAME

3. 切换分支 ​

bash
git checkout BRANCH_NAME
git checkout BRANCH_NAME COMMIT_HASH
# git 2.23之后推荐使用git switch
git switch BRANCH_NAME

切换分支前应该注意不要带着脏工作区切换,有变动的内容要么 commit,要么 stash。例如:在dev分支新增了a.txt文件未提交,切换到main分支后,这个文件还在,会污染main分支的工作区

4. 删除分支 ​

bash
#安全删除:只有在分支已经被成功合并到上游分支(或当前分支)时,才会允许删除。
#如果分支尚未合并,Git 会拒绝删除并给出警告
git branch -d BRANCH_NAME

#强制删除:等价于 git branch -d --force,无论分支是否已合并,都会直接删除。
#不会做任何合并检查,直接删除分支及其指向的提交。当你确定不再需要该分支上的任何提交时使用。
git branch -D BRANCH_NAME
git push origin --delete BRANCH_NAME

5. 合并分支 ​

bash
git merge BRANCH_NAME

解决冲突后:

bash
git add FILE
git commit -m DESC

6. 推送分支 ​

基本语法:

bash
git push 远程仓库名 本地分支:远程分支

常用参数:

参数说明
git push将当前分支推送到对应的远程分支(需已设置上游分支)
git push origin推送到 origin 远程仓库
git push origin main将本地 main 分支推送到 origin/main
git push origin local:remote将本地 local 分支推送到远程 remote 分支(分支名不同时)

常用选项:

选项说明
-u / --set-upstream推送的同时设置上游分支,后续可直接 git push
--all推送所有本地分支到远程
--tags推送所有标签(tag)
--delete删除远程分支,如 git push --delete origin feature
-f / --force强制推送,覆盖远程历史(⚠️ 危险)
--force-with-lease安全强制推送,只有远程分支未被他人更新时才覆盖(✅ 推荐)
-d等价于 --delete,删除远程分支
--dry-run模拟推送,只显示会推送什么,不实际执行
-v / --verbose显示详细推送信息
-q / --quiet静默模式,只输出错误信息
--no-tags推送时不推送标签

常见用法示例:

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

# 推送标签
git push origin v1.0.0

# 删除远程分支
git push origin --delete feature
# 或简写
git push origin -d feature

# 强制推送(推荐用 --force-with-lease 替代 --force)
git push --force-with-lease origin main

# 推送本地 feature 分支到远程的 dev 分支
git push origin feature:dev

# 删除远程分支的另一种写法(推送空分支)
git push origin :feature

--force vs --force-with-lease:

选项行为安全性
--force无条件覆盖远程分支⚠️ 可能覆盖他人的提交
--force-with-lease仅当远程分支仍是你上次拉取的状态时才覆盖✅ 更安全

日常 rebase 后推送,优先使用 --force-with-lease,避免误覆盖协作者的提交。

7. 重命名分支 ​

bash
git branch -m NEW_BRANCH_NAME
git branch -m OLD_BRANCH_NAME NEW_BRANCH_NAME

8. 分支比较 ​

9. 分支管理常见流程 ​

操作命令
创建分支git branch BRANCH_NAME
切换分支git switch BRANCH_NAME
删除分支git branch -d BRANCH_NAME
合并分支git merge BRANCH_NAME
推送分支git push origin BRANCH_NAME
跟踪分支git branch --set-upstream-to=origin/BRANCH_NAME

stash ​

git stash用来暂存更改,一般用来解决切换分支前当前功能未完成又不想临时提交的问题。

git stash 保存 ​

参数说明示例
(无参数)暂存已跟踪文件的修改和暂存区内容git stash
-u / --include-untracked同时包含未跟踪的文件git stash -u
-a / --all包含未跟踪文件和 .gitignore 忽略的文件git stash -a
-m添加备注信息git stash -m "开发登录功能"
-k / --keep-index只暂存工作区修改,保留暂存区内容不动git stash -k
-p / --patch交互式选择要暂存的修改块git stash -p
push显式写法(可配合路径参数只暂存指定文件)git stash push -m "备注" path/to/file

git stash 查看 / 恢复 / 删除 / 其他 ​

参数说明示例
list列出所有 stash 记录git stash list
show查看最新 stash 的文件变更概要git stash show
show -p查看最新 stash 的完整 diffgit stash show -p
show stash@{n}查看指定 stash 的概要git stash show stash@{1}
pop恢复最新 stash 并删除该记录git stash pop
pop stash@{n}恢复指定 stash 并删除该记录git stash pop stash@{1}
apply恢复最新 stash 但保留记录git stash apply
apply stash@{n}恢复指定 stash 但保留记录git stash apply stash@{1}
drop删除最新的 stash 记录git stash drop
drop stash@{n}删除指定的 stash 记录git stash drop stash@{1}
clear删除所有 stash 记录git stash clear
branch <名称>基于最新 stash 创建新分支并应用git stash branch hotfix stash@{1}

fetch ​

git fetch 用于从远程仓库获取最新的提交、分支、标签等引用信息,但不会修改本地工作区和当前分支。它是 git pull 的"安全版"。

1. 基本用法 ​

bash
# 拉取所有远程分支的更新
git fetch

# 拉取指定远程仓库的更新
git fetch origin

# 拉取指定远程分支的更新
git fetch origin main

2. fetch 与 pull 的区别 ​

对比项git fetchgit pull
拉取远程数据✅✅
修改本地工作区❌ 不修改✅ 自动合并/快进
产生合并冲突的可能性无可能有
安全性安全,不影响当前工作可能破坏当前工作状态
本质仅下载git fetch + git merge

git pull = git fetch + git merge(默认行为)。也可以配置为 git fetch + git rebase(git pull --rebase)。

3. 各自使用场景 ​

场景推荐命令说明
想查看远程更新但不影响本地git fetch先拉取远程信息,再决定是否合并
rebase 工作流中同步主分支git fetch配合 git rebase origin/main 使用,避免 git pull 产生的多余合并提交
本地分支落后远程,直接同步git pull简单场景下快速同步,等同于 fetch + merge
本地有未提交的改动git fetchgit pull 可能产生冲突或覆盖提示,fetch 更安全

git pull适用于同一个分支的同步。例如:你在 main 分支上,想把远程 main 的最新代码拉下来

你当前所在分支你想同步主分支最新代码该敲什么命令为什么
在 feature 分支上想同步 main必须用 git fetch origin main用 pull 会把 main 直接塞进 feature,破坏分支纯净度,导致后续无法 rebase。
在 main 分支上想更新本地 main直接用 git pull origin main因为 main 本来就是用来同步的,pull 自动合并,省去一步手动 merge的操作。

4. fetch 后的常用操作 ​

bash
# 拉取远程更新
git fetch origin

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

# 查看远程分支列表
git branch -r

# 确认无误后,手动合并或变基
git merge origin/main
# 或
git rebase origin/main

5. 实战示例:fetch + rebase 工作流 ​

以下是一个典型的"在功能分支上同步主分支最新代码并继续开发"的流程,体现了 git fetch 与 git pull 的核心区别:

bash
# 1. 切换到功能分支
git checkout feature/login

# 2. 拉取最新的 main(仅下载,不修改本地分支)
git fetch origin main

# 3. 在功能分支上执行 rebase(把功能分支的提交放到最新 main 后面)
git rebase origin/main

# 4. 继续开发,提交新功能
git add . && git commit -m "feat: 增加验证码登录"

# 5. 强制推送覆盖远程的功能分支(因为只有你用,所以安全)
git push --force-with-lease origin feature/login

为什么这里用 git fetch 而不是 git pull?

  • git pull origin main 会自动将远程 main 合并到当前分支(feature/login),产生一个多余的合并提交,污染提交历史。
  • git fetch origin main 只下载远程 main 的最新数据到 origin/main 引用,不触碰当前分支,再由 git rebase origin/main 将功能分支干净地变基到最新 main 之上,保持线性历史。
  • git push --force-with-lease 比 git push --force 更安全,它会在远程分支没有被他人更新时才允许强制推送,避免覆盖他人的提交。

rebase ​

git rebase 是 Git 中用于将一个分支的提交"重新应用"到另一个分支上的操作,从而产生线性、整洁的提交历史。与 git merge 不同,rebase 会重写提交历史。

1. 基本概念 ​

  • git rebase 的作用:将当前分支的提交变基到目标分支的最新提交之上,使提交历史呈线性。
  • 核心原理:取出当前分支的每个提交,依次"重放"到目标分支的顶端。

2. 基本用法 ​

bash
# 将当前分支变基到 TARGET_BRANCH 上
git rebase TARGET_BRANCH

示例:在 feature 分支上执行 git rebase main,会将 feature 分支的提交移到 main 最新提交之后。

3. 交互式 rebase ​

交互式 rebase 允许在变基过程中对提交进行编辑、合并、重排序、删除等操作。

bash
git rebase -i TARGET_BRANCH

在打开的编辑器中,每个提交前有一个操作关键字:

关键字说明
pick保留该提交(默认)
reword保留提交,但修改提交信息
edit保留提交,但暂停以便修改提交内容
squash将该提交合并到前一个提交,合并提交信息
fixup将该提交合并到前一个提交,丢弃该提交信息
drop删除该提交

4. 处理冲突 ​

变基过程中如果出现冲突:

bash
# 解决冲突后,继续变基
git add .
git rebase --continue

# 跳过当前提交
git rebase --skip

# 放弃整个变基操作,回到变基前的状态
git rebase --abort

5. 常用场景与建议 ​

场景是否推荐说明
本地分支更新到最新主分支✅ 推荐在 feature 分支上 git rebase main,保持提交历史整洁
压缩本地提交✅ 推荐使用 git rebase -i 合并、整理本地提交
多人协作的共享分支❌ 不推荐会导致他人的提交历史被重写,造成混乱和冲突

6. rebase vs merge 对比 ​

对比项rebasemerge
提交历史线性、整洁保留分支交叉历史
是否产生合并提交否是(默认)
是否重写提交历史是否
多人共享分支安全性不安全安全

⚠️ 黄金法则:不要对已经推送到远程仓库且他人正在使用的分支执行 rebase。 rebase 会重写提交历史,导致协作者的提交丢失或产生冲突。rebase 最适合用于本地私有分支的整理和更新。

代码合入 main ​

rebase 完成后,feature 的代码还在 feature 分支上,要合入 main 有两种方式:

方式一:Pull Request / Merge Request(推荐) ​

text
git push --force-with-lease origin feature
        ↓
在 GitHub/GitLab 上创建 PR:feature → main
        ↓
代码审查 → 通过 → 合并
        ↓
此时 origin/main 才有 feature 的代码

这是团队协作的标准流程,rebase 后提 PR,在平台上完成合并。

方式二:本地合并后推送 ​

bash
# 1. rebase 完成,feature 已是最新
git push --force-with-lease origin feature

# 2. 切到 main
git checkout main

# 3. 拉取最新 main
git pull origin main

# 4. 合并 feature 到 main(因为 rebase 过,这里是 fast-forward 合并)
git merge feature

# 5. 推送 main
git push origin main

# 此时 origin/main 才有 feature 的代码

因为 rebase 后 feature 的提交都在 main 最新提交之后,所以 git merge feature 会是 fast-forward 合并,不会产生合并提交,历史完全线性:

text
合并前:                    合并后(fast-forward):

      C'--D' feature       A---B---E---C'---D' main, feature
     /                      
A---B---E  main

完整流程图 ​

text
git rebase origin/main
        │
        │  feature 的提交被重放到 origin/main 之后
        │  origin/main 不变
        ▼
git push --force-with-lease origin feature
        │
        │  远程 feature 分支更新
        │  origin/main 依然不变
        ▼
   ┌────┴────┐
   │         │
   ▼         ▼
  PR合并    本地合并
   │         │
   │    git checkout main
   │    git pull origin main
   │    git merge feature
   │    git push origin main
   │         │
   └────┬────┘
        │
        ▼
  origin/main 包含 feature 的代码

rebase 是"准备"工作,让 feature 的提交历史干净地接在 main 后面;合并才是"交付"工作,把代码真正合入 main。


merge ​

git merge 是 Git 中用于将多个分支的内容合并到一个分支的操作。它是团队协作开发中处理分支合并的核心命令之一。

1. 基本概念 ​

  • git merge 的作用:将另一个分支的更改整合到当前分支。
  • 合并的前提:必须在某个分支上运行 git merge 命令,目标是将另一个分支的更改合并到当前分支。

2. 参数说明 ​

参数说明是否产生合并提交
(无参数)默认行为:能快进则快进,不能快进则三方合并视情况
--ff允许快进合并(与默认行为一致)视情况
--no-ff禁用快进合并,始终创建合并提交✅
--ff-only只允许快进合并,不能快进则报错拒绝❌
--squash将所有提交压缩到工作区,不自动提交,需手动 git commit❌
--abort取消正在进行的合并,恢复合并前状态—
--continue冲突解决后继续完成合并—
--commit合并成功后自动提交(默认行为)—
--no-commit执行合并但不自动提交,便于检查合并结果—
-m <msg>指定合并提交的信息—
--stat合并完成后显示差异统计—
--no-stat合并完成后不显示差异统计—

3. 合并的基本步骤 ​

a. 切换到目标分支(合并到哪个分支):

bash
git checkout TARGET_BRANCH
# 或者更常用的方式:
git switch TARGET_BRANCH

b. 执行合并:

bash
# 将 SOURCE_BRANCH 的更改合并到 TARGET_BRANCH
git merge SOURCE_BRANCH

c. 解决冲突(如有):

  • 如果合并过程中有冲突,Git 会提示哪些文件有冲突。
  • 手动编辑冲突的文件,解决冲突后执行:
bash
git add CONFLICTED_FILE
git commit

4. 合并模式 ​

git merge 主要有两种模式:快进合并(Fast-Forward)和 三方合并(3-Way Merge)。

快进合并 (Fast-Forward Merge) ​

当目标分支没有新的提交时,Git 直接将目标分支指针移动到源分支的最新提交。有时,为了保持主分支的线性历史,主分支合并其他分支前,会将其他分支进行变基(rebase)操作,为的就是主分支可以快进合并其他分支。

三方合并 (3-Way Merge) ​

当两个分支都有新的提交时,Git 会创建一个新的合并提交。有时,为了更好的分支可视化,合并时就算分支没有新的提交或冲突,也需要保留一个合并提交。--no-ff 参数可以实现这一点。

--no-ff:

优点说明
保留分支拓扑即使可以快进合并,也强制创建合并提交,能清晰看到分支的创建、合并点
便于整体回退可通过 git revert -m 1 MERGE_COMMIT 一次性回退整个分支的合并
历史更可读合并提交记录了"何时合并了一个分支",而非将分支提交"摊平"到主线上

对比示意:

text
# 默认快进合并(ff):提交历史呈一条直线,看不出分支存在过(merge feature分支时,main还在c版本,feature的d、e版本会快进合并到main分支)
# 当两个分支已经分叉(main 和 feature 各有新提交),无论有没有冲突,和 git merge --no-ff feature 产生的结果是一样的————都会创建一个有两个父节点的合并提交。
A---B---C---D---E  (main)

# --no-ff 合并:保留分支合并节点,就算没有F提交,也会产生合并提交G。
# --no-ff 的作用仅是阻止快进合并。当快进不可能发生时(分叉、冲突),它和ff或无参的行为完全一致,产生的合并提交在历史上没有区别.
A---B---C---F---G  (main)
         \   /
          D---E  (feature)

⚠️ 注意: 如果是同步上游更新(如 git merge origin/main 到本地 main),快进合并是合理的,无需 --no-ff。--no-ff 主要用于合并 feature/fix 等功能分支。 合并方式无所谓优劣,根据实际情况选择合适的合并策略。

5. 工作流模式与合并策略 ​

工作流模式推荐策略命令示例原因
个人开发,追求线性历史rebase + --ff-onlygit rebase main → git merge --ff-only dev历史干净无噪音,无合并节点,bisect 友好
团队协作,feature 分支合并--no-ffgit merge --no-ff feature保留分支边界,便于整体回退和审计
同步上游更新默认(--ff)git merge origin/main快进即可,无需合并提交
不关心提交粒度,压成一个提交--squashgit merge --squash dev → git commit历史简洁,但丢失分支提交细节
紧急修复,直接合入主线--no-ffgit merge --no-ff hotfix保留修复的合并记录,便于追溯

6. 示例 ​

如果主分支追求线性历史,各功能开发必须有功能分支(如feature-x),合并到main分支后关闭功能分支。

bash
git checkout feature-x
# 所有更改都已提交, 先巩固成果,同步到上游分支
git push origin feature-x
# 变基到main分支,保持线性历史
git rebase main

git switch main
# 合并feature-x分支到main分支,由于feature-x分支已经变基到main分支,一般都是可以快进合并,--ff-only保险不会产生合并提交
git merge --ff-only feature-x
git push origin main
# 删除功能分支,一般合并完成后不需要保留功能分支
git branch -d feature-x
# 如果远程分支也不保留
git push origin --delete feature-x

功能分支rebase并合并到主分支后一般是不保留的,如果需要开发其他功能,一般基于主分支最新版本创建新的功能分支。如果懒得新增分支操作,或者是自己维护的长期分支(多人维护的分支不建议变基,会改变历史,影响协作者),想继续在分支上开发,因为此时本地feature-x已变基,推送上游分支会失败的,推荐git push --force-with-lease同步到远程分支。

如果主分支追求提交历史好追溯,那么合并分支时建议强制保留一个合并提交较好。假设在dev阶段性开发完毕后,需要合并到main分支。推荐步骤如下:

bash
# 1. 确保当前在 dev 分支,提交所有改动
git add .
git commit -m "你的提交信息"
# 2. 先 push dev 到远程(保存工作成果)
git push origin dev
# 3. 切换到 main 分支
git checkout main
# 4. 拉取远程 main 最新代码
git pull origin main
# 5. 合并 dev 到 main(推荐 --no-ff),保留分支交叉历史
git merge --no-ff dev
# 6. 推送 main 到远程
git push origin main

如果你不希望 dev 上的零碎提交出现在 main 上,用 squash 合并(main分支会丢失 dev 分支的提交历史,丢失贡献痕迹)

bash
git push origin dev
git checkout main
git pull origin main
# --squash会将dev分支的提交压缩到工作区,不自动提交,需手动 `git commit`
git merge --squash dev
git commit -m "feat: 合并 dev 分支改动"
git push origin main

cherry-pick ​

1. 用法 ​

bash
git cherry-pick COMMIT_HASH

2. 提交多个hash ​

bash
git cherry-pick START_COMMIT_HASH^..END_COMMIT_HASH
  • START_COMMIT_HASH 是起始提交的哈希值。
  • END_COMMIT_HASH 是结束提交的哈希值。

3. cherry-pick 选项 ​

选项说明
-e编辑提交信息
-n不自动提交
-x在提交信息中记录来源
bash
git cherry-pick -e COMMIT_HASH
git cherry-pick -n COMMIT_HASH
git cherry-pick -x COMMIT_HASH

revert ​

git revert 用于撤销某次提交的更改,方式是创建一个新的提交来抵消目标提交的修改。与 git reset 不同,git revert 不会修改提交历史,是撤销已推送提交的安全方式。

1. 基本用法 ​

bash
# 撤销指定提交,生成一个新的撤销提交
git revert COMMIT_HASH

# 撤销最近一次提交
git revert HEAD

# 撤销多个提交(按顺序逐个撤销)
git revert COMMIT_HASH_1 COMMIT_HASH_2

# 撤销一个范围的提交(不包含 START,包含 END)
git revert START..END

2. 常用选项 ​

选项说明示例
--no-edit使用默认撤销提交信息,不打开编辑器git revert --no-edit HEAD
-e / --edit打开编辑器修改撤销提交信息(默认行为)git revert -e HEAD
-n / --no-commit撤销更改但不自动提交,可合并多次撤销后一起提交git revert -n COMMIT_HASH
--continue冲突解决后继续撤销操作git revert --continue
--abort取消整个撤销操作git revert --abort
--skip跳过当前提交git revert --skip

3. 撤销合并提交 ​

合并提交有两个父提交,撤销时需要指定保留哪个父提交的历史:

bash
# 撤销合并提交,保留主分支(第 1 个父提交)的历史
git revert -m 1 MERGE_COMMIT_HASH
  • -m 1:保留合并到的分支(如 main)的历史,撤销被合并分支(如 feature)的更改
  • -m 2:保留被合并分支的历史,撤销合并到的分支的更改

4. revert vs reset 对比 ​

对比项git revertgit reset
撤销方式创建新提交来抵消更改直接移动分支指针,丢弃提交
是否修改提交历史❌ 不修改✅ 修改(重写历史)
是否安全用于已推送分支✅ 安全❌ 危险,会导致他人历史不一致
适用场景撤销已推送到远程的提交撤销本地未推送的提交
操作可逆性可逆(可以 revert 这个 revert)不可逆(提交被丢弃后难以恢复)

⚠️ 黄金法则:对于已经推送到远程仓库的提交,始终使用 git revert 而非 git reset。 git reset 会重写历史,在多人协作中会导致严重问题。

reset ​

git reset 用于将当前分支的 HEAD 指针移动到指定提交,同时可以选择如何处理暂存区和工作区。它是撤销本地提交的常用命令,但会重写提交历史,不应用于已推送的提交。

1. 三种模式 ​

git reset 的核心区别在于对暂存区(index)和工作区(working directory)的处理方式:

模式HEAD暂存区工作区说明
--soft移动不变不变仅移动 HEAD,提交的更改保留在暂存区,可重新提交
--mixed(默认)移动重置不变移动 HEAD 并重置暂存区,更改退回工作区(未暂存状态)
--hard移动重置重置移动 HEAD 并重置暂存区和工作区,所有更改丢失

图示:

text
--soft:    HEAD → 目标提交  |  暂存区保留更改  |  工作区不变
--mixed:   HEAD → 目标提交  |  暂存区重置      |  工作区保留更改
--hard:    HEAD → 目标提交  |  暂存区重置      |  工作区重置(更改丢失!)

2. 基本用法 ​

bash
# 默认 --mixed 模式:撤销提交,更改退回工作区
git reset COMMIT_HASH

# --soft:撤销提交,更改保留在暂存区
git reset --soft COMMIT_HASH

# --hard:撤销提交,所有更改丢弃
git reset --hard COMMIT_HASH

3. 常用场景 ​

撤销最近一次提交(保留更改) ​

bash
# 撤销最近一次提交,更改保留在暂存区,可修改后重新提交
git reset --soft HEAD~1

# 撤销最近一次提交,更改退回工作区(未暂存状态)
git reset HEAD~1

撤销最近 N 次提交 ​

bash
# 撤销最近 3 次提交,更改保留在暂存区
git reset --soft HEAD~3

丢弃所有本地更改 ​

bash
# 重置到远程分支的状态,丢弃所有本地修改
git fetch origin
git reset --hard origin/main

清空暂存区(取消 git add) ​

bash
# 将所有已暂存的文件退回工作区
git reset

# 将指定文件退回工作区
git reset FILE

4. HEAD~n 说明 ​

写法说明
HEAD当前提交
HEAD~1 / HEAD^当前提交的上一个提交
HEAD~2当前提交往前第 2 个提交
HEAD~n当前提交往前第 n 个提交

5. 找回丢失的提交 ​

git reset --hard 后提交似乎丢失了,但 Git 内部仍保留了一段时间的引用,可以通过以下方式找回:

bash
# 查看所有操作记录,找到丢失提交的哈希
git reflog

# 恢复到指定提交
git reset --hard COMMIT_HASH

⚠️ 注意: git reflog 的记录有有效期(默认 90 天),过期后引用可能被垃圾回收清除,无法恢复。

6. reset 使用建议 ​

场景推荐命令说明
撤销本地提交,想修改提交信息git reset --soft HEAD~1更改保留在暂存区,直接重新 git commit
撤销本地提交,想重新整理更改git reset HEAD~1更改退回工作区,重新选择暂存
丢弃所有本地更改,恢复到远程状态git reset --hard origin/main⚠️ 不可恢复,谨慎使用
已推送的提交需要撤销使用 git revertreset 会重写历史,影响协作者

rm ​

1. 何时使用 rm ​

git rm 用于从 Git 版本库中移除文件的跟踪。与直接在文件管理器中删除文件不同,git rm 会同时从暂存区和工作区中删除文件,并将该删除操作记录为一次待提交的更改。

场景推荐操作说明
确定不再需要某文件,从项目中彻底删除git rm FILE从版本库和工作区同时删除,删除会进入暂存区
停止跟踪某文件,但保留本地文件git rm --cached FILE从版本库中移除跟踪,工作区文件保留(常用于 .gitignore 补救)
误将敏感文件(密码、密钥)提交到仓库git rm --cached FILE + 提交 + 加入 .gitignore从版本库移除跟踪,防止后续推送泄露

⚠️ 注意: 直接用系统命令(如 del 或在资源管理器中删除)删除文件,Git 不会自动将删除操作加入暂存区,需要再手动执行 git add FILE 或 git rm FILE 才能将删除纳入提交。使用 git rm 一步到位。

2. 常用操作 ​

bash
git rm FILE

2. 选项详解 ​

选项说明
--cached仅从版本库中删除,保留工作区文件
bash
git rm --cached FILE

3. 注意事项 ​

恢复已删除的文件:

bash
git checkout COMMIT_HASH -- file.txt

tag ​

1. 查看现有标签 ​

bash
git tag

2. 创建附注标签 ​

bash
git tag -a TAG_NAME -m "MESSAGE"

3. 给特定的提交打标签 ​

bash
git tag TAG_NAME COMMIT_HASH

4. 推送标签到远程仓库 ​

bash
git push origin TAG_NAME

5. 删除标签 ​

bash
git tag -d TAG_NAME
git push origin --delete TAG_NAME

6. 检查标签详细信息 ​

bash
git show TAG_NAME

7. 拉取标签 ​

8. 拉取标签和代码的区别 ​

9. 检出到某个标签 ​

bash
git checkout TAG_NAME
git checkout -b NEW_BRANCH_NAME

log ​

git log 用于查看提交历史记录,是 Git 中最常用的审查命令之一。

1. 基本用法 ​

bash
git log

2. 参数详解 ​

git log [options]

参数说明示例
(无参数)显示完整提交历史git log
-n / -[n]限制显示最近 n 条提交git log -5
--oneline每条提交压缩为一行(哈希+信息)git log --oneline
--all显示所有分支的提交历史git log --all
--graph以 ASCII 图形显示分支与合并历史git log --graph
--decorate显示引用(分支、标签)指向的提交git log --decorate
-p / -u显示每条提交的完整 diffgit log -p
--stat显示每条提交的文件变更统计(增删行数)git log --stat
--shortstat仅显示每条提交的增删行数汇总git log --shortstat
--name-only仅显示每条提交变更的文件名git log --name-only
--name-status显示变更文件名及状态(A/M/D)git log --name-status
--author=<pattern>按作者筛选(支持正则)git log --author="Alice"
--committer=<pattern>按提交者筛选git log --committer="Bob"
--grep=<pattern>按提交信息筛选(支持正则)git log --grep="feat"
-i / --regexp-ignore-case配合 --author/--grep 忽略大小写git log --grep="fix" -i
--since=<date>显示指定日期之后的提交git log --since="2026-01-01"
--after=<date>同 --sincegit log --after="2026-01-01"
--until=<date>显示指定日期之前的提交git log --until="2026-06-01"
--before=<date>同 --untilgit log --before="2026-06-01"
-- <path>仅显示涉及指定路径/文件的提交git log -- src/main.py
-L <start>,<end>:<file>显示文件指定行范围的演变历史git log -L 10,20:main.py
--follow跟踪文件重命名历史(需配合路径)git log --follow -- README.md
--no-merges不显示合并提交git log --no-merges
--merges仅显示合并提交git log --merges
--first-parent仅沿第一父提交链显示(忽略分支侧)git log --first-parent
--reverse按时间正序显示(最早的在前)git log --reverse
--abbrev-commit缩短提交哈希值git log --abbrev-commit
--relative-date以相对时间显示日期(如 "2 days ago")git log --relative-date
--show-signature显示 GPG 签名验证结果git log --show-signature
--diff-filter=<type>按变更类型筛选(A=新增, M=修改, D=删除)git log --diff-filter=M
--format=<fmt> / --pretty=<fmt>自定义输出格式git log --format="%h %s"

3. 自定义格式占位符 ​

--format / --pretty 支持的常用占位符:

占位符说明
%H完整提交哈希
%h缩短提交哈希
%T完整树哈希
%t缩短树哈希
%an作者名字
%ae作者邮箱
%cn提交者名字
%ce提交者邮箱
%ad作者日期
%cd提交者日期
%ar作者相对日期
%cr提交者相对日期
%s提交信息(首行)
%b提交信息(正文)
%d引用装饰(分支、标签)
%n换行

4. 范围查询 ​

用法说明示例
<since>..<until>显示从 since 到 until 之间的提交git log main..dev
<branch1>...<branch2>显示两分支各自的独有提交git log main...dev
^<commit>排除指定提交及其祖先git log ^main dev
-L :<func>:<file>显示函数的演变历史git log -L :main:app.py

5. 常用组合 ​

bash
git log --oneline --graph --all --decorate
# 经典可视化:所有分支、图形化、一行式、带标签

git log --oneline -10
# 最近 10 条提交,一行式

git log --since="1 week ago" --oneline --author="Alice"
# Alice 最近一周的提交

git log --grep="feat" --oneline
# 提交信息包含 "feat" 的提交

git log --stat -5
# 最近 5 条提交的文件变更统计

git log --format="%h - %an, %ar : %s"
# 自定义格式:短哈希 - 作者, 相对时间 : 提交信息

git log main..feature/login --oneline
# feature/login 有而 main 没有的提交(即将合并的内容)

git log -p -- src/main.py
# 查看 main.py 的完整变更历史及 diff

💡 实用技巧:

  • git log --oneline --graph --all --decorate 是最常用的可视化组合,建议设为别名:git config --global alias.lg "log --oneline --graph --all --decorate"
  • git log branch1..branch2 可查看 branch2 相对 branch1 的新提交,常用于合并前审查
  • 配合 --since/--until 可快速定位时间段内的变更
  • -L 参数(行范围追踪)是排查某段代码演变历史的利器

团队协作工作流 ​

1. Centralized Workflow(集中式工作流) ​

最简单的工作流,所有人在同一分支(通常是 main)上直接提交。

text
          main
A --- B --- C --- D --- E
      ↑     ↑     ↑     ↑
    Alice  Bob  Alice  Carol

流程:

bash
# 每个人在 main 上直接工作
git pull origin main
# 编写代码...
git add . && git commit -m "feat: 新功能"
git pull origin main          # 推送前先拉取最新
git push origin main

特点:

优点缺点
简单易上手,无需分支管理冲突频繁,互相阻塞
适合小团队无法并行开发多个功能
适合持续部署的小项目main 不稳定,随时可能被破坏

适用场景: 2-3 人的小团队、个人项目、内部工具


2. Feature Branch Workflow(功能分支工作流) ​

每个功能/修复在独立分支上开发,通过 Pull Request/Merge Request 合入主分支。

text
                main
A --- B --- C --------- F --------- I
              \           \           \
          D --- E     G --- H     J --- K
        feature/a    feature/b    feature/c

流程:

bash
# 1. 从 main 创建功能分支
git checkout -b feature/login main

# 2. 在功能分支上开发
git add . && git commit -m "feat: 实现登录页面"
git add . && git commit -m "feat: 添加表单验证"

# 3. 同步 main 最新代码(推荐 rebase)
git fetch origin main
git rebase origin/main

# 4. 推送功能分支
git push -u origin feature/login

# 5. 在 GitHub/GitLab 上创建 Pull Request
#    → 代码审查 → 通过 → 合并到 main

# 6. 合并后删除功能分支
git checkout main
git pull origin main
git branch -d feature/login
git push origin --delete feature/login

特点:

优点缺点
main 始终稳定分支管理成本略高
支持代码审查(PR)需要平台支持(GitHub/GitLab)
功能隔离,冲突减少—
支持并行开发—

适用场景: 中小团队、需要代码审查的项目

💡 提示:这是目前最主流的工作流,GitHub、GitLab、Bitbucket 均原生支持。


3. GitFlow 工作流 ​

Vincent Driessen 提出的经典分支模型,使用两类分支(长期分支 + 短期分支)管理项目的完整生命周期。

分支结构:

分支类型分支名生命周期说明
长期分支main永久生产环境代码,每个提交都是一个可发布版本
长期分支develop永久开发集成分支,包含下一个版本的所有功能
短期分支feature/*功能完成后删除从 develop 创建,合并回 develop
短期分支release/*发布完成后删除从 develop 创建,合并回 main 和 develop
短期分支hotfix/*修复完成后删除从 main 创建,合并回 main 和 develop
text
                                      main
A ---------------------------------------- M --- N
\                                        /       \
 develop   D --- E --- F --- G --- H --- L --- O
          /         /           /       /
    feature/a  feature/b  release/1.1  hotfix/xxx
    C --- D'  F'--- G'    I --- J     K

流程:

日常功能开发 ​

bash
# 1. 从 develop 创建功能分支
git checkout -b feature/user-profile develop

# 2. 开发并提交
git add . && git commit -m "feat: 用户个人资料页面"

# 3. 完成后合并回 develop
git checkout develop
git merge --no-ff feature/user-profile
git branch -d feature/user-profile

准备发布 ​

bash
# 1. 从 develop 创建发布分支
git checkout -b release/1.2.0 develop

# 2. 在发布分支上修复 bug、更新版本号(不再接受新功能)
git add . && git commit -m "fix: 修复发布前发现的 bug"

# 3. 发布:合并到 main 和 develop
git checkout main
git merge --no-ff release/1.2.0
git tag -a v1.2.0 -m "Release 1.2.0"

git checkout develop
git merge --no-ff release/1.2.0

git branch -d release/1.2.0

紧急修复 ​

bash
# 1. 从 main 创建热修复分支
git checkout -b hotfix/critical-bug main

# 2. 修复并提交
git add . && git commit -m "fix: 修复生产环境严重 bug"

# 3. 合并到 main 和 develop
git checkout main
git merge --no-ff hotfix/critical-bug
git tag -a v1.2.1 -m "Hotfix 1.2.1"

git checkout develop
git merge --no-ff hotfix/critical-bug

git branch -d hotfix/critical-bug

特点:

优点缺点
分支职责清晰,各司其职分支模型复杂,学习成本高
main 始终对应生产环境日常开发需在 develop 和 feature 间频繁切换
支持并行开发、发布和热修复release 分支与 develop 的双向合并容易遗漏
有明确的版本管理(tag)对持续部署项目过于笨重

适用场景: 有明确版本发布周期的项目、需要同时维护多个版本的项目

💡 提示:GitFlow 适合有计划发布(如每两周一个版本)的项目。如果项目采用持续部署,Trunk-Based 工作流更合适。


4. Trunk-Based Development(主干开发工作流) ​

所有人在 main(trunk)上频繁提交,功能通过 Feature Flag 控制可见性,不再依赖长期存在的功能分支。

text
              main (trunk)
A --- B --- C --- D --- E --- F --- G
      ↑     ↑     ↑     ↑     ↑     ↑
    Alice  Bob  Alice  Carol  Bob  Alice

短生命周期分支(可选):

text
              main
A --- B --- C --------- F --- G
          \           /
          D --- E
       feature/x (1-2天)

流程:

bash
# 方式一:直接在 main 上提交(最简单)
git pull origin main
# 编写代码,用 Feature Flag 包裹新功能
git add . && git commit -m "feat: 新功能(flag: NEW_LOGIN)"
git push origin main

# 方式二:使用短生命周期分支(1-2天)
git checkout -b feature/quick-fix main
git add . && git commit -m "fix: 快速修复"
git push -u origin feature/quick-fix
# 创建 PR → 审查 → 合并(分支存活不超过 1-2 天)

Feature Flag 示例:

python
# 新功能用 flag 包裹,合并到 main 但不影响生产
if feature_flag.is_enabled("NEW_LOGIN"):
    return new_login_flow()
else:
    return old_login_flow()

特点:

优点缺点
历史始终线性,简单清晰需要 Feature Flag 基础设施支持
强制小批量、频繁集成代码审查必须快速(否则阻塞所有人)
与 CI/CD 完美契合未完成功能进入 main,需 flag 控制风险
无分支管理开销对团队纪律性要求高

适用场景: 持续部署/持续交付的项目、高成熟度团队、微服务架构

💡 提示:Google、Facebook 等大厂普遍采用此工作流。关键前提是完善的 CI 流水线和 Feature Flag 系统。


工作流对比 ​

特性集中式Feature BranchGitFlowTrunk-Based
分支复杂度最低低高最低
main 稳定性❌ 低✅ 高✅ 高⚠️ 中(依赖 flag)
代码审查❌ 无✅ PR✅ PR✅ PR(快速)
并行开发❌ 不支持✅ 支持✅ 支持✅ 支持
发布管理❌ 无手动✅ 规范✅ 持续部署
热修复流程❌ 混乱手动✅ 规范✅ 直接提交
CI/CD 契合度低中低✅ 最高
团队规模2-3人5-20人10-50人不限
学习成本最低低高中

工作流选择建议 ​

text
团队规模 + 发布方式 → 推荐工作流

2-3人,随意发布        → 集中式工作流
5-20人,需代码审查     → Feature Branch 工作流
10+人,有版本发布周期   → GitFlow 工作流
成熟团队,持续部署      → Trunk-Based 工作流