使用 diff 和 apply 命令在 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 中使用补丁时请注意这一点。
- 点赞
- 收藏
- 关注作者
评论(0)