git am 用于应用由 git format-patch 打包的补丁,相比于简单使用 git diff 打包, 其添加了作者信息和提交信息,更加易读。

名字 am 表示它“应用(Apply)一系列来自邮箱(Mailbox)的补丁,从技术的角度看,git am 是为了读取 mbox 文件而构建的, mbox 是一种用来在单个文本文件中存储一个或多个电子邮件消息的简单纯文本格式。 其大致格式如下所示:

From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
From: Jessica Smith <jessica@example.com>
Date: Sun, 6 Apr 2008 10:17:23 -0700
Subject: [PATCH 1/2] add limit to log function
 
Limit log functionality to the first 20

这其实就是你前面看到的 git format-patch 命令输出的开始几行, 而同时它也是有效的 mbox 电子邮件格式。 如果有人使用 git send-email 命令将补丁以电子邮件的形式发送给你, 你便可以将它下载为 mbox 格式的文件,之后将 git am 命令指向该文件,它会应用其中包含的所有补丁。

假设使用附件下载了 patch 文件:(也可以使用 -i 参数来交互式依次应用每个补丁)

$ git am 0001-limit-log-function.patch
Applying: add limit to log function

你会看到补丁被顺利地应用,并且为你自动创建了一个新的提交。 其中的作者信息来自于电子邮件头部的 FromDate 字段,提交消息则取自 Subject 和邮件正文中补丁之前的内容。 比如,应用上面那个 mbox 示例后生成的提交是这样的:

$ git log --pretty=fuller -1
commit 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
Author:     Jessica Smith <jessica@example.com>
AuthorDate: Sun Apr 6 10:17:23 2008 -0700
Commit:     Scott Chacon <schacon@gmail.com>
CommitDate: Thu Apr 9 09:19:06 2009 -0700
 
   add limit to log function
 
   Limit log functionality to the first 20

其中 Commit 信息表示的是应用补丁的人和应用补丁的时间。 Author 信息则表示补丁的原作者和原本的创建时间。

处理应用冲突

有时候无法顺利地应用补丁。 这也许是因为你的主分支和创建补丁的分支相差较多,也有可能是因为这个补丁依赖于其他你尚未应用的补丁。 这种情况下,git am 进程将会报错并且询问你要做什么:

$ git am 0001-seeing-if-this-helps-the-gem.patch
Applying: seeing if this helps the gem
error: patch failed: ticgit.gemspec:1
error: ticgit.gemspec: patch does not apply
Patch failed at 0001.
When you have resolved this problem run "git am --resolved".
If you would prefer to skip this patch, instead run "git am --skip".
To restore the original branch and stop patching run "git am --abort".

该命令将会在所有出现问题的文件内加入冲突标记,就和发生冲突的合并或变基操作一样。 而你解决问题的手段很大程度上也是一样的——即手动编辑那些文件来解决冲突,暂存新的文件, 之后运行 git am --resolved 继续应用下一个补丁:

$ (fix the file)
$ git add ticgit.gemspec
$ git am --resolved
Applying: seeing if this helps the gem