git am / format-patch:行结尾的控制格式

时间:2011-06-09 06:41:26

标签: git format-patch

我使用

从三次提交中创建了一个补丁
git format-patch <revision_three_commits_ago>

这会创建三个我从笔记本邮寄的补丁文件,并在我的桌面计算机上读取邮件(两个都是Windows框)。

我现在这样做

git am --3way --ignore-space-change *.patch

补丁适用,但我没有为提交获得相同的SHA1 ID。在修补文件中搜索了一下,我发现桌面计算机上的修改后的行以LF结尾,而笔记本上的修改后的行(我创建补丁的行)以CR LF结束。

所以,我的第一个想法就是在没有--ignore-space-change的情况下拨打git am,但这会给我一个错误(补丁不适用)。

我怎么能告诉git format-patchgit am如何处理行结尾(msysgit 1.7.4)?

在应用修补程序之前,我是否真的需要使用VIM并将文件格式从UNIX更改为DOS


编辑:甚至不用VIM修改补丁文件有帮助:我认为,set ff=dos:%s/^M//g会有所帮助,但事实并非如此!

在我看来,应用补丁应该会导致完全相同的内容,以及我从其他创建补丁的repo中提取的相同提交哈希。我错了吗?

4 个答案:

答案 0 :(得分:19)

在使用各种选项(core.autocrlfcore.eol)后,我发现使用

git am --keep-cr

可以解决问题(但会引发有关尾随空格的警告)。

不需要手动编辑补丁文件或其他污垢。

但是,(当然)散列是不同的,如nikai的答案所述......感谢nikai指出我的哈希值。

在我的笔记本 - 桌面方案中,我想将一些更改从笔记本电脑离线转移到桌面计算机,但是当我在桌面上应用补丁然后执行操作时,回购不应该分歧也不应该发生相同的提交两次来自笔记本的git pull desktop

为实现这一目标,我做了以下工作:

  1. 在桌面上,使用git am --keep-cr ...
  2. 按上述方法应用修补程序
  3. 在笔记本上,到git pull desktop,这导致补丁引入的每个提交发生两次(一次用于原始笔记本提交,一次用于修补和拉入桌面提交)
  4. 现在(位于笔记本的master分支上),发出git rebase desktop/master会发出No changes -- Patch already applied消息,并将原始笔记本提交替换为桌面提交

答案 1 :(得分:5)

Git 2。3。0(2015年2月)将提出另一个新选项: --transfer-encoding ,以指定要使用的传输编码(quoted-printable,8bit,base64),而不是仅依靠--keep-cr

git send-email man page
git am man page

commit 8d81408Paolo Bonzini (bonzini)

  

git-send-email:添加--transfer-encoding选项

     

mailing-list thread详细说明在使用CRLF行结尾的存储库中应用带有“git am”的修补程序时的问题。
  在线程的示例中,存储库源自“git-svn”,因此无法在其上使用core.eol和朋友。

     

目前,最好的选择是使用“git am --keep-cr”   但是,当修补程序创建新文件时,修补程序应用程序进程将拒绝新文件,因为它找到“/dev/null\r”字符串而不是“/dev/null”。

     

问题是 SMTP transport是CRLF不安全的   通过电子邮件发送补丁与通过“dos2unix | unix2dos”传递补丁相同   新引入的CRLF通常是透明的,因为git-am剥离它们。 keepcr=true设置保留了它们,但它主要是偶然的,在具有混合LF和CRLF行结尾的存储库中有一个“git am”工作流是非常有问题的。

     

MIME solution to this is the quoted-printable transfer enconding   这不是我们想要默认启用的内容,因为它会使收到的电子邮件看起来很糟糕。
  但是,它非常适合将CRLF行结尾存储在存储库中的项目。

     

quoted-printable的唯一缺点是引用可打印   如果维护者使用“git am --keep-cr”,则补丁无法应用   这是因为解码后的补丁最后会有两个回车符   这条线   因此,添加对base64 transfer encoding的支持,这使收到的电子邮件无法在MUA (Mail User Agent)之外查看,但实际上只是有效。

     

该补丁涵盖所有基础,包括仍然生活在80年代后期的用户,同时提供7位内容传输编码,拒绝发送带有非ASCII字符的电子邮件。
  最后,“8bit”将添加Content-Transfer-Encoding标头,但不执行任何操作。

git send-email的文档现在包括:

--transfer-encoding=(7bit|8bit|quoted-printable|base64)
  

指定用于通过SMTP发送邮件的传输编码   遇到非ASCII消息时,7位将失败。

     

当存储库包含包含回车符的文件时,Quoted-printable会很有用,但会使原始修补程序电子邮件文件(从MUA保存)更难以手动检查。
  base64更加傻瓜式,但也更加不透明。

     

默认值是“sendemail.transferEncoding”配置值的值;如果未指定,git将使用8位而不添加Content-Transfer-Encoding标头。

答案 2 :(得分:3)

这里有一个类似的问题:apparently same commits give different sha1, why?

作为一个简短的回顾,git cat-file commit <sha>应该能够缩小树,父母,电子邮件,日期,作者或提交者的名称是否不同,或者是否在提交消息中引入了额外的'\ n'。

答案 3 :(得分:2)

简短回答:git am --committer-date-is-author-date

长篇故事:我刚刚发现我在同一条船上尝试在两个存储库之间进行sneakernet提交。在尝试使用git am选项后,我注意到文件ID始终匹配,但git am的连续运行为相同的选项生成不同的提交ID。事实证明,有两个时间戳 - 您通常看到的“作者”时间戳,以及创建提交时的“提交者”时间戳。默认情况下,后者在git am中设置为当前时间。您需要使用--committer-date-is-author-date选项来保持日期同步,这反过来会使您的提交ID同步。

因此,如果您的环境中有选项,我会说git bundle更可靠。