如何把未提交的改动导出为 Git 补丁文件
已跟踪文件的未暂存改动用 git diff --binary > ../changes.patch,已暂存改动用 git diff --cached --binary > ../changes.patch;未跟踪文件需显式纳入,应用前用 git apply --check 检查。适合跨机器搬运改动、临时备份工作区、不方便 push 时分享修改。
看改动处于哪个状态:未暂存的用 git diff --binary > ../changes.patch 导出;已暂存(staged)的用 git diff --cached --binary > ../changes.patch。对方或另一台机器上用 git apply changes.patch 应用。这是不经过远程仓库搬运改动的经典办法。
三种状态的导出
# 1. 未暂存的改动(工作区 vs 暂存区)
git diff --binary > ../uncommitted.patch
# 2. 已暂存的改动(暂存区 vs HEAD)
git diff --cached --binary > ../staged.patch
# 3. 全部未提交改动(工作区+暂存区 vs HEAD)
git diff --binary HEAD > ../all-changes.patch
注意:git diff 不包含未跟踪的新文件。新文件先显式 git add -N 新文件(intent-to-add)再导出;普通 git stash create / store 不会自动包含未跟踪文件。git diff HEAD 要求已有 HEAD,合并导出也不会保留暂存/未暂存的原始区分。示例把补丁写到工作树外,避免误把补丁本身纳入。
应用补丁
git apply --check ../changes.patch # 先检验能否干净应用
git apply ../changes.patch # 再应用到工作区
git apply --stat ../changes.patch # 看看补丁涉及哪些文件
git apply -R ../changes.patch # 仅上下文仍匹配时可反向应用,并非通用撤销
已提交的改动导出
已提交的用 git format-patch(生成带提交信息的补丁,可用 git am 应用成完整提交):
git format-patch -1 HEAD # 最近一次提交导出为 0001-xxx.patch
git am 0001-xxx.patch # 在对端应用为提交
常见问题(FAQ)
Q:patch 应用时冲突了怎么办?
git apply 要求上下文精确匹配,目标文件已变化时会失败。补丁记录了原始 blob 标识且本地对象可用时,可用 git apply --3way ../changes.patch 尝试三方合并;该选项隐含 --index,会涉及暂存区。冲突处以冲突标记写入文件,手工解决即可。
Q:二进制文件(图片等)的改动能进补丁吗?
默认 diff 不含二进制内容。加 --binary:git diff --binary > changes.patch,应用方才能完整还原。
Q:patch 和 stash 怎么选?
同仓库临时存放用 stash;跨机器、跨仓库、发给别人评审,用 patch 文件。