- 背景
- git apply vs git am
- 生成patch
- git apply使用
- git am使用
1、背景
假设有一个独立的插件项目,因为一些项目的变更,现在需要将其迁移到一个较大的项目中的子目录中。传统的方法可能包括使用 git cherry-pick 来选择性地应用提交,但这种方法并不能很好的处理子目录问题。 例如:项目A是目标仓库,项目B是子项目仓库,期望将项目B的commit同步到项目A,但是当直接使用cherry-pick你会发现,项目B中的文件会同步到light/src目录,而不是期望的extension/src里面,这样就不对了。相比之下,Git Apply 与 Git AM 提供了更加灵活和高效的方式来处理这种迁移。
项目A:
light/src/xxx
light/extension
light/extension/src/xxx
...
项目B:
extension/src/xxx
2、git apply vs git am
命令 | 是否应用补丁? | 是否创建提交? | 适用场景 |
---|---|---|---|
git apply | 是 | 否 | 在提交之前测试 git diff(即补丁)的效果。也可用于在构建前将补丁应用于第三方库。 |
git am | 是 | 是 | 从邮件或由 git format-patch 生成的文件中应用补丁。适用于协作和接受他人的贡献。 |
- 适用场景:
<font style="color:rgb(1, 1, 1);">git apply</font>
:主要用于测试<font style="color:rgb(1, 1, 1);">git diff</font>
(即补丁)在提交之前的效果。也可以用于在构建之前将补丁应用于第三方库。<font style="color:rgb(1, 1, 1);">git am</font>
:用于从邮件或由<font style="color:rgb(1, 1, 1);">git format-patch</font>
生成的文件中应用补丁。非常适用于协作和接受他人的贡献。
- 是否创建提交:
<font style="color:rgb(1, 1, 1);">git apply</font>
:只应用补丁,不创建提交。<font style="color:rgb(1, 1, 1);">git am</font>
:在应用补丁的同时,会创建提交。
而git apply与git am最根本的区别在于apply不会创建新的提交,即没有commit,只是应用patch,而git am会把commit带过来。所以git am不能使用git diff的patch,因为没有commit,而git apply可以使用git diff与git format-patch的patch,因为都包含了diff信息。
3、生成patch
生成patch可以用git diff与git format-patch,用法比较简单,以下给出几个示例。<font style="color:rgb(1, 1, 1);">git diff</font>
示例1:比较工作目录和暂存区之间的差异。
示例2:比较两个提交之间的差异:
git diff > changes.patch
git diff <commit1> <commit2>
<font style="color:rgb(1, 1, 1);">git format-patch</font>
示例1:获取最新的commit生成patch。
示例2:生成两个提交之间的补丁文件。
git format-patch -1 --stdout > changes.patch
可以通过指定:—stdout > changes.patch 将所有的patch合并为一个。
git format-patch <start_commit>..<end_commit>
git format-patch <start_commit>..<end_commit> --stdout > changes.patch
4、**<font style="color:rgb(130, 127, 196);">git apply</font>**
使用
不论是git apply还是git am在进行同步diff时,最好开启-3或—3way,当发生合并冲突事件,便可以看到diff信息。
可以看到当git apply时,出现了ours与theirs,ours 和 theirs 选项用于指定冲突解决策略。当在应用补丁的过程中遇到冲突时,Git 需要知道如何解决这些冲突。这些选项允许你指定使用当前分支 (ours) 或者应用的补丁 (theirs) 的更改来解决冲突。
5、git am使用
与git apply类似,但又有所不同,当使用-3或—3way后,下面的diff便是HEAD与commit。<font style="color:rgb(0, 0, 0);">git apply</font>
都可以做到diff同步功能,<font style="color:rgb(0, 0, 0);">git cherry-pick</font>
也可以做到,回到本文的背景,为何没有使用<font style="color:rgb(0, 0, 0);">git cherry-pick</font>
呢,那是因为涉及到子目录的迁移,而<font style="color:rgb(0, 0, 0);">git am</font>
与<font style="color:rgb(0, 0, 0);">git apply</font>
允许指定subdirectories,通过<font style="color:rgb(0, 0, 0);">--directory</font>
,完整命令:
git apply --3way --directory=extension changes.patch
git am --3way --directory=extension changes.patch