Git中的补丁是如何工作的?

30
我是新手Git用户,但熟悉SVN。作为测试,我使用 git init 在本地目录中创建了一个仓库。然后,我使用SSH(127.0.0.1)在另一个本地目录中克隆了空仓库(这也是我想要测试的另一件事)。我在仓库2中添加了一些文件,然后运行了git add *,最后运行了git commit -a -m "First source code"
现在,我想用 git format-patch 创建一个补丁,并将其应用于仓库1。我该怎么做?我知道有一个手册,但这些东西非常复杂,让我想对我的显示器做某些事情。

2
如果你使用Git,就不需要像以前那样频繁地使用补丁了。请查看下面的答案。 - Ana Betts
1
这篇文章可能有助于理解使用Git创建和应用补丁的完整过程。 - Abhishek Gupta
6个回答

23

通过以下方式创建您的补丁:

$ git format-patch master --stdout > patch.diff

然后 patch.diff 将包含差异,您可以将其发送给其他人使用以下方法应用:

$ git am < patch.diff
有时候,当手册有点复杂的时候,寻找教程是很有意义的: http://luhman.org/blog/2009/09/22/git-patch-tutorial

当我应用补丁时,出现了这个错误:“fatal: previous rebase directory .git/rebase-apply still exists but mbox given.” - Nicolas S.Xu

14

从最后一个提交(或最近几个提交)创建补丁的最简单方法是使用format-patch命令,使用负数来指定要为其创建补丁的提交数量:

git format-patch -1

你将会得到一个以提交描述命名的补丁文件。使用 am 命令将其插入到另一个仓库中:

git am << name_of_patch_file

3
只是一个小细节; 它不是一个负数,只是一个标志,用于指示深度。没有奇怪的魔法!如果更自然的话,您还可以指定一系列提交,例如:git format-patch origin/master.. 等等(请参阅 git rev-parse 手册以了解所有表达这些参数的方式)。 - Matt Enright
在Windows上使用git am name_of_patch_file - Anton Krouglov

2

很好,不过链接不幸地无法使用了。 :( - Johny Skovdal

2

如果您正在使用Git,正确而简单的方法是通过远程操作:

cd \path\to\repo1
git remote add otherrepo \path\to\repo2
git fetch otherrepo

git log otherrepo/master  ## Find the commit you want to steal in the list

git cherry-pick SOME_SHA1  ## Snag just one commit
git merge otherrepo/master  ## Merge all of the new commits from otherrepo/master

这将迁移一个仓库中的提交记录,包括其作者和提交信息,并且可以帮助您解决合并冲突(特别是在移动>1个提交记录时)。

当他的初始仓库不同时,这个方法还能行得通吗?由于有不同的历史记录,所有提交的哈希值都会不同。那么难道打补丁是唯一的方法吗? - Johny Skovdal

1

随着 Git 2.25(2020 年第一季度)的到来,git format-patch 得以进化,更好地使用分支描述("git branch --edit-description")作为主题。

请查看提交 bf8e65b, 提交 a92331d, 提交 46273df (2019年10月15日) 由Denton Liu (Denton-L)完成。
(由Junio C Hamano -- gitster --合并于提交 b75ba9b, 2019年11月10日)

format-patch:教授 --cover-from-description 选项

签名:Denton Liu

以前,当 format-patch 生成一封封面信时,只有正文会被填充为分支的描述,而主题则会被填充为占位符文本。

然而,用户可能希望以同样的方式自动填充封面信的主题。

教授 format-patch 接受 --cover-from-description 选项和相应的 format.coverFromDescription 配置,允许用户填充封面信的不同部分(现在包括主题)。

git config 文档 现在包括:

format.coverFromDescription

用于确定在格式化补丁时使用分支说明填充封面信的默认模式。

还有git format-patch命令:

--cover-from-description=<mode>

控制自动填充求职信的哪些部分将使用分支描述。

  • 如果 <mode>messagedefault,则求职信主题将填充占位符文本。
    求职信正文将填充分支的描述。当未指定配置或命令行选项时,这是默认模式。

  • 如果 <mode>subject,则分支描述的第一段将填充求职信主题。
    其余描述将填充求职信正文。

  • 如果 <mode>auto,如果分支描述的第一段大于100字节,则使用 message 模式,否则使用 subject 模式。

  • 如果 <mode>none,则求职信主题和正文都将填充占位符文本。


在求职信上,Git 2.37(2022年第三季度)解释道:

请查看提交4ec5008提交c2cd4b5提交e97d474提交afc8c92提交489ef3b(2022年5月12日)由Philippe Blain (phil-blain)完成。
(由Junio C Hamano -- gitster --提交3ce9483合并,日期为2022年5月25日)

MyFirstContribution:在封面信上添加独立部分

签署者:Philippe Blain

“使用git send-email(man)/准备邮件”部分包含了关于封面信目的的说明,但是“通过GitGitGadget发送补丁”部分缺少这一内容。

在“入门指南:补丁系列结构”标题下添加一个独立的“封面信”部分,解释封面信的用途,并起草教程中使用的“psuh”主题的封面信。

注:这里的“psuh”来自于:

在本教程中,我们将添加一个新命令,+git push+,简称为“Pony Saying 'Um, Hello”,这是一个功能,尽管在用户的日常工作流程中频繁调用,但一直未被实现。 MyFirstContribution现在包括在其手册页面中:
补丁系列的后续迭代在“PATCH”之处标记为“PATCH v2”,“PATCH v3”等。
例如,“[PATCH v2 1/3]”是第二次迭代中的三个补丁中的第一个补丁。
每个迭代都带有一个新的封面信(如上所示的“[PATCH v2 0/3]”),它本身是对上一个迭代的封面信的回复(下文会有更多介绍)。
注意:单个补丁主题使用“[PATCH]”,“[PATCH v2]”等,没有i/n编号(在上面的线程概述中,没有单个补丁主题出现)。

封面信

除了每个补丁的电子邮件之外,Git社区还期望您的补丁附带一封封面信。这是变更提交的重要组成部分,因为它高层次地解释了您试图做什么以及为什么,以比仅查看您的修补程序更明显的方式向社区解释。
您的封面信的标题应该简洁地涵盖整个主题分支的目的。它通常以命令语气书写,就像我们的提交消息标题一样。以下是我们将为我们的系列命名的方式:

添加'psuh'命令

封面信的正文用于向审阅者提供附加上下文。一定要解释您的修补程序本身无法清楚说明的任何内容,但请记住,由于封面信未记录在提交历史中,因此对于存储库历史的未来读者可能有用的任何内容也应包含在您的提交消息中。
这是“psuh”的示例正文:

我们的内部指标表明,许多用户正在尝试使用“git-psuh”命令,但发现它不可用并使用某些未知的解决方法代替。
以下少量的补丁添加了“psuh”命令,并在其上实现了一些方便的功能。
此补丁集是“MyFirstContribution”教程的一部分,不应合并。


0

你需要前往“存储库2”,也就是你想要从中创建补丁的存储库,并运行git-format-patch命令来创建补丁: git format-patch master --stdout > 补丁文件名

然后你需要进入“存储库1”,也就是你想要应用补丁的存储库: git apply 补丁文件名

有时候,仅仅检查一下补丁是否会引起问题也是很有用的: git apply --check 补丁文件名


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接