【问题标题】:git am/format-patch: control format of line endingsgit am/format-patch:控制行尾的格式
【发布时间】:2011-09-11 10:51:53
【问题描述】:

我使用三个提交创建了一个补丁

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 会有所帮助,但它没有!

在我看来,应用补丁应该会产生完全相同相同的内容和相同的提交哈希,就像我从创建补丁的其他存储库中提取的一样。我想错了吗?

【问题讨论】:

  • 注意:您现在可以选择使用 Git 2.3.0(2015 年 2 月):您现在可以使用 --transfer-encoding 指定要使用的传输编码(quoted-printable),而不是依赖 --keep-cr ,8位,base64)。见my answer below

标签: git format-patch


【解决方案1】:

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

git am --keep-cr

成功了(但会导致有关尾随空格的警告)。

无需手动编辑补丁文件或其他脏东西。

但是,(当然)哈希值与nikai 的回答中描述的不同...感谢 nikai 将我指向哈希值。

在我的 notebook-desktop-scenario 中,我想将一些更改从笔记本离线传输到台式计算机,但是当我在桌面上应用补丁然后执行git pull desktop 来自笔记本。

为此,我做了以下工作:

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

【讨论】:

    【解决方案2】:

    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 消息时 7bit 会失败。

    当存储库包含包含回车的文件时,Quoted-printable 可能很有用,但会使原始补丁电子邮件文件(从 MUA 保存)更难手动检查。

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


    使用 Git 2.32(2021 年第二季度),“git mailinfo(man)(因此“git am(man))了解到"--quoted-cr" 选项用于控制如何处理以 CRLF 结尾的以 base64 或 qp 包装的行。

    请参阅commit 59b519acommit 133a4fdcommit f1aa299commit 0b68956(2021 年 5 月 10 日)和commit dd9323bcommit d582992(2021 年 5 月 6 日)Đoàn Trần Công Danh (sgn)
    (由Junio C Hamano -- gitster -- 合并于commit 483932a,2021 年 5 月 16 日)

    mailinfo:如果在解码的 base64/QP 电子邮件中发现 CRLF,则发出警告

    签字人:Đoàn Trần Công Danh

    当 SMTP 服务器收到 8 位电子邮件消息时,可能只有 LF 作为行尾,其中一些决定将所述 LF 更改为 CRLF。

    一些邮件列表软件在收到 8 位电子邮件消息时,决定将这些消息编码为 base64 或引用打印。

    如果一封电子邮件通过上述邮件服务器传输,然后由此类邮件列表软件分发,收件人将收到一封电子邮件,其中包含一个带有 CRLF 编码的补丁,该补丁在另一个编码中编码。

    因此,这样的 CR(在 CRLF 中)不能被“mailsplit”删除。
    因此,无法干净地应用邮寄的补丁。
    此类事故have been observed in the wild.

    如果发现此类 CR(作为 CRLF 的一部分),让我们向我们的用户发出一些警告,而不是默默地拒绝这些消息。

    警告将是:

    warning: quoted CRLF detected
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 我忘记了日期也包含在提交的哈希中。因此,可以理解为什么相同的内容不会给出相同的哈希值。但这仍然不能回答为什么会有不同的行尾。
      【解决方案4】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-11
        • 2013-03-25
        • 2023-03-31
        • 2013-05-17
        • 1970-01-01
        • 1970-01-01
        • 2019-03-04
        • 2018-07-02
        相关资源
        最近更新 更多