使用 diff 和 apply 命令在 GIT 中创建和应用补丁

举报
Tiamo_T 发表于 2022/09/08 16:35:06 2022/09/08
【摘要】 在 GIT 中创建补丁是共享您尚未准备好推送到项目公共分支的更改的好方法。 为了更好地理解我们将如何创建补丁,让我们首先讨论一下 GIT 存储是如何变化的。

在 GIT 中创建补丁是共享您尚未准备好推送到项目公共分支的更改的好方法。

为了更好地理解我们将如何创建补丁,让我们首先讨论一下 GIT 存储是如何变化的。

如果您是 GIT 新手,请安装 git 并从官方GIT 介绍文章中快速入门。

第一次将文件提交到 GIT 中的项目时,会存储一个副本。对于之后的所有提交,GIT 本质上存储了指令,告诉它如何将项目的先前版本转换为新提交的版本。

在 GIT 中,这些指令称为“diffs”。每当您签出一个分支时,GIT 基本上都会从项目的原始状态开始,并按顺序应用所有这些差异,以达到所需的状态。

现在知道 GIT 如何存储提交,很容易看出补丁文件将只是补丁将跨越的每个提交的差异的串联。

对于我们的示例,假设以下情况:我们有一个具有 2 个分支的简单项目:主分支和实验分支。

$ git log --oneline --all
  * b36f227 (experimental) third commit -- added file3
  * f39ebe8 second commit -- added file2
  * 04a26e5 (HEAD, master) first commit -- committed file1

Master 目前处于第一次提交,而实验性是 2 次提交。在每次提交中,我分别添加了一个名为 file1、file2 和 file3 的文件。这是每个分支的当前状态:


在 master 上,我们只有 file1:

$ git status
On branch master
nothing to commit, working directory clean

$ ls
file1

在实验阶段,我们拥有所有 3 个文件:

$ git status
On branch experimental
nothing to commit, working directory clean

$ ls
file1 file2 file3

在本教程中,我们将解释如何在实验分支上创建更改补丁并将它们应用到主分支。

创建 GIT 补丁

我们将使用 git diff 命令创建差异输出,然后将其重定向到文件中。我们将使用的 diff 命令的形式如下:

git diff from-commit to-commit > output-file

在哪里:

  • from-commit – 我们希望补丁开始的点。(在我们的例子中,实验与主人不同的点)
  • to-commit - 补丁将涵盖直到并包括这一点的更改。(在我们的例子中,最近的实验性提交)
  • output-file – 补丁会写在这里

注意:如果省略了 from-commit 或 to-commit,它们将被假定为 HEAD

我们通过它们唯一的哈希来指定这两个提交。通常,您只需指定足够的提交哈希以确保其唯一性(4 个字符可能会做到这一点)。

$ git diff 04a2 b36f > patch.diff

$ ls
patch.diff file1      file2      file3

从上面的输出中可以看到,补丁文件已经创建。

在这种特殊情况下,我们想要创建整个分支的补丁,我们可以让 GIT 为我们做一些工作。我们可以让 GIT 使用 git merge-base 命令确定我们的实验分支与主分支的分歧点:

git diff $(git merge-base <public branch> <experimental branch>) > <output file>

git merge-base 将确定 2 个分支之间最近的常见提交。还要注意这次我们是如何省略的。它将默认为 HEAD,并且由于实验分支签出,HEAD 将是实验分支的最新提交。

$ git diff $(git merge-base master experimental) > anotherPatch.diff

$ ls
anotherPatch.diff patch.diff  file1  file2  file3

同样,补丁文件已创建。这些补丁文件是相同的。

应用 GIT 补丁

一旦制作了补丁文件,应用它就很容易了。确保您签出的分支是您要应用补丁的分支(在我们的例子中是 master)。然后你可以使用 git apply 命令应用补丁: git apply

$ git status
On branch master
... (rest of output omitted) ...

$ ls
anotherPatch.diff patch.diff  file1

$ git apply patch.diff

$ ls
anotherPatch.diff patch.diff  file1  file2  file3

来自实验分支的更改现在已在 master 上复制。

警告:虽然以这种方式应用补丁会完全复制内容,但不会复制任何提交历史记录。这意味着即使您创建的补丁跨越了多个提交,它也会在应用时显示为一组更改。您将失去关于如何分解提交的知识以及每个提交的消息。让我们比较两个分支的提交历史:

在实验中,我们有 3 次提交,每一次都有一个有意义的提交信息。

$ git branch
  * experimental
    master
$ git log --oneline
  b36f227 third commit -- added file3
  f39ebe8 second commit -- added file2
  04a26e5 first commit -- committed file1

但是,我们的补丁只是将实际更改应用于主分支。

$ git branch
  experimental
  * master
$ git log --oneline
  04a26e5 first commit -- committed file1

应用补丁并没有提交更改,也没有带来与这些更改相关的任何提交历史记录。在 GIT 中使用补丁时请注意这一点。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。