Skip to content

Git 生成指定提交之间的 patch 并应用

  • 状态:已验证
  • 来源:对话整理
  • 更新时间:2026-03-16

关键结论

  • git diff commit1 commit2 > patch 可以生成普通 patch。
  • git diff 生成 patch 时的参数顺序是 old -> new
  • 第一个 commit 表示原始版本,第二个 commit 表示目标版本。
  • 如果两个 commit 顺序写反,生成的 patch 会变成回滚补丁。
  • git diff --binary 可以把二进制文件变化包含进 patch。
  • 在 Git 仓库中,git apply 通常比通用的 patch 更适合应用 Git 生成的差异。
  • 如果需要按 commit 粒度保留提交说明和作者信息,应使用 git format-patch 配合 git am
  • git bundle 不是 patch 的一种,而是仓库级传递与备份方式;相关内容应查看 bundle.md

详细分析

  • Git 中常见的差异传递方式可以分为两类:

    1. 补丁类:普通 diff patch、commit patch
    2. 仓库级传递:repository bundle
  • 本条目只讲补丁的生成与应用,不把 bundle 当作补丁类型展开。

普通 diff patch

  • 生成方式:
bash
git diff commit1 commit2 > changes.patch
  • 特点:
    • 只包含文件差异
    • 不包含 commit message、作者等提交元信息
    • 可使用 patchgit apply 应用
  • git diff <old> <new> 的语义是“把代码从 old 版本修改到 new 版本”。
  • 生成出的 patch 记录的是:
    • old 中被删除的内容,用 - 表示
    • new 中新增的内容,用 + 表示
  • 因此:
bash
git diff old_commit new_commit > changes.patch
  • 表示生成一个“从 old_commit 前进到 new_commit”的正向 patch。
  • 如果写成:
bash
git diff new_commit old_commit > revert.patch
  • 则语义会变成“把 new_commit 回退到 old_commit”,得到的是反向 patch。

commit patch

  • 生成方式:
bash
git format-patch commit1..commit2
  • 特点:
    • 每个 commit 单独生成一个 patch 文件
    • 保留 commit message、作者和时间等提交信息
    • 应使用 git am 应用,而不是 git apply

repository bundle

  • 生成方式:
bash
git bundle create repo.bundle --all
  • 特点:

    • 保存完整 Git 对象和 refs
    • 更适合离线仓库传输、完整迁移和备份
    • 与 patch 不同,它保留的是仓库级数据而不是单纯文本差异
  • 在代码迁移、跨仓库同步或离线传输时,如果只是需要把两个提交之间的改动内容送到另一边,普通 patch 足够;如果还需要保留提交历史语义,则应优先考虑 format-patch

  • 如果需要传递的是完整 Git 仓库对象、refs 或离线备份,而不是单纯的文件差异,应优先查看 bundle.md

可执行步骤

  1. 生成两个提交之间的 patch:
bash
git diff --binary old_commit new_commit > changes.patch
  1. 在目标仓库检查 patch 是否可应用:
bash
git apply --check changes.patch
  1. 在目标仓库应用 patch:
bash
git apply changes.patch
  1. 如果需要以 commit 粒度导出 patch:
bash
git format-patch commit1..commit2
  1. 在目标仓库按 commit 应用 patch:
bash
git am *.patch

命令 / 配置 / 代码

bash
# 生成包含二进制内容的普通 patch
git diff --binary old_commit new_commit > changes.patch

# 检查 patch 是否可应用
git apply --check changes.patch

# 应用 patch
git apply changes.patch

# 生成 commit 级 patch
git format-patch commit1..commit2

# 应用 commit 级 patch
git am *.patch

# 生成完整仓库 bundle
git bundle create repo.bundle --all

风险与注意事项

  • git diff 的 commit 顺序写错,会直接生成反向 patch。
  • 如果不加 --binary,普通 diff patch 可能无法正确表达二进制文件变化。
  • 普通 patch 不包含 commit history,只保留文件差异。
  • patch 应用通常要求目标仓库具备兼容的目录结构和基础上下文,否则容易失败。
  • git apply 只应用文件改动,不会自动生成 commit;应用后通常还需要手工提交。
  • git format-patchgit am 适合保留提交语义,但前提是目标仓库具备能接住这组 commit 的上下文历史。

关联条目