背景介绍

我们在日常的开发中, 涉及对第三方源码的修改或在需要将自己的改动给到其他同事时,经常需要将改动打patch后进行处理.
这时候我们常直接使用diff命令生成patch文件, 然后通过patch进行打对应的patch文件. 详细的使用请看这篇博客中的说明: Linux下生成patch和打patch

然后这种直接使用diff和patch的方式,并不是最优解. 这里会更加建议使用git提供的format-patch 进行patch文件的生成以及通过am进行patch文件的打入. 接下来的示例代码会展示其更优的点

如何使用 git format-patch 和git am
使用git format-patch 生成patch文件

下面以往libchrome这一代码仓库进行文件修改,然后生成patch为例.

➜  libchrome git:(master)ls
Android.bp  build     BUILD.IGNORE  crypto  device  libchrome_tools  MODULE_LICENSE_BSD  NOTICE  soong    testrunner.cc  ui
base        BUILD.gn  components    dbus    ipc     METADATA         mojo                OWNERS  testing  third_party
➜  libchrome git:(master)

如上所示, 时libchrome的一个仓库.
然后我修改了顶层目录中的文件Android.bp, 改动如下:

diff --git a/Android.bp b/Android.bp
index 45392653e..4874aaad0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -38,6 +38,7 @@ package {
 // to attach the license to, and including a comment whether the files may be
 // used in the current project.
 // See: http://go/android-license-faq
+// git format-patch test
 license {
     name: "external_libchrome_license",
     visibility: [":__subpackages__"],
(END)

然后将该改动提交, 操作如下:

➜  libchrome git:(master)git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   Android.bp

no changes added to commit (use "git add" and/or "git commit -a")
➜  libchrome git:(master)git add .
➜  libchrome git:(master)git commit -m "feat: test"
[master bad02e32d] feat: test
 1 file changed, 1 insertion(+)

然后通过git log 查看对应提交的commit id

commit bad02e32d47a8ea82b2bcb02b5e8950f23f61623 (HEAD -> master)
Author: laixiaoqiang <laixiaoqiang@xxxx.com>
Date:   Mon Nov 22 19:49:42 2021 +0800

    feat: test

commit 06d255220dedb1f7058899536fd120bde5e6d904 (tag: android-s-v2-preview-1, origin/master, origin/android-s-v2-preview-1, origin/HEAD)
Merge: 121235bfa 902749c7e
Author: Paul Duffin <paulduffin@google.com>
Date:   Wed Jul 14 23:25:04 2021 +0000

    Stop using deprecated functionality for managing path deps am: 62d44c8c10 am: 902749c7e2
    
    Original change: https://android-review.googlesource.com/c/platform/external/libchrome/+/1761028
    
    Change-Id: Iffea5fa594c77bfae52c2f348a70d6c34dd77a8b

如上图可以得到commit bad02e32d47a8ea82b2bcb02b5e8950f23f61623为我们需要打包为patch的提交.
最后使用git format-patch 命令生成patch文件.

➜  libchrome git:(master) git format-patch bad02e32d47a8ea82b2bcb02b5e8950f23f61623 -1 
0001-feat-test.patch
➜  libchrome git:(master)cat 0001-feat-test.patch 
From bad02e32d47a8ea82b2bcb02b5e8950f23f61623 Mon Sep 17 00:00:00 2001
From: laixiaoqiang <laixiaoqiang@xiaomi.com>
Date: Mon, 22 Nov 2021 19:49:42 +0800
Subject: [PATCH] feat: test

---
 Android.bp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Android.bp b/Android.bp
index 45392653e..4874aaad0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -38,6 +38,7 @@ package {
 // to attach the license to, and including a comment whether the files may be
 // used in the current project.
 // See: http://go/android-license-faq
+// git format-patch test
 license {
     name: "external_libchrome_license",
     visibility: [":__subpackages__"],
-- 
2.17.1

如上所示有以下几点需要注意:

  1. 使用的命令:
git format-patch bad02e32d47a8ea82b2bcb02b5e8950f23f61623 -1 
   commit id后面跟着的参数-1 指的是当前仅是需要将bad02e32d47a8ea82b2bcb02b5e8950f23f61623这一commit生成patch文件.
  1. 通过 0001-feat-test.patch可以看出, format-patch生成的patch文件有一个有优点是在于记录修改者等git提交信息,以及文件的格式我们更加的熟悉.

那对于这种方式生从的patch文件我们该如何使用呢?
ehh 那让我们先reset bad02e32d47a8ea82b2bcb02b5e8950f23f61623 这一提交,然后进行接下来的演示.

➜  libchrome git:(master)git reset --hard 06d255220dedb1f7058899536fd120bde5e6d904
HEAD is now at 06d255220 Stop using deprecated functionality for managing path deps am: 62d44c8c10 am: 902749c7e2

使用git am命令打对应的patch文件0001-feat-test.patch

➜  libchrome git:(master)git am 0001-feat-test.patch 
Applying: feat: test
➜  libchrome git:(master)

然后通过git log 命令, 可以看到如下提交:

commit 01d340a508c16c4e262bb24c67f991a63db62df1 (HEAD -> master)
Author: laixiaoqiang <laixiaoqiang@xxx.com>
Date:   Mon Nov 22 19:49:42 2021 +0800

    feat: test

commit 06d255220dedb1f7058899536fd120bde5e6d904 (tag: android-s-v2-preview-1, origin/master, origin/android-s-v2-preview-1, origin/HEAD)

可以看出git am 直接将0001-feat-test.patch打入并自动生成提交.
如果只是想生效改动而不需要直接提交代码,可以使用git apply 替代.

➜  libchrome git:(master)git apply 0001-feat-test.patch
➜  libchrome git:(master)git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   Android.bp
补充说明

另外当需要将多个提交生成patch文件,可以使用如下命令,
例如:
libchrom这一代码仓库, 需要将
88c7d5c272925d8f27366ed239a4f46ae00ceb16
f00850730180e5cb6c0b74e58ba9aaab17545b57
生成patch文件.

commit 88c7d5c272925d8f27366ed239a4f46ae00ceb16
Author: Inseob Kim <inseob@google.com>
Date:   Mon Jun 14 12:57:12 2021 +0900

    Add ramdisk_available to init_first_stage's deps
    
    Bug: 187196593
    Test: boot
    Change-Id: I7436b8dd11ca747459d442b3d754c5367a9eb721
    Merged-In: I7436b8dd11ca747459d442b3d754c5367a9eb721

commit f00850730180e5cb6c0b74e58ba9aaab17545b57
Merge: 39896b6f1 ab0b0fa5c
Author: Inseob Kim <inseob@google.com>
Date:   Fri Jun 18 18:14:50 2021 +0000

    Add ramdisk_available to init_first_stage's deps am: 35abebfab5 am: ab0b0fa5c5
    
    Original change: https://android-review.googlesource.com/c/platform/external/libchrome/+/1736238
    
    Change-Id: Ibd8746381ce4518a0195bc70e1cf35406ff3c2c7

commit ab0b0fa5c5b0ecfa6d7f60da3e7b153c4337d4c4
Merge: 6f365e25e 35abebfab
Author: Inseob Kim <inseob@google.com>
Date:   Fri Jun 18 17:57:25 2021 +0000

    Add ramdisk_available to init_first_stage's deps am: 35abebfab5
    
    Original change: https://android-review.googlesource.com/c/platform/external/libchrome/+/1736238
    
    Change-Id: I36a066ceb149a2f6ac00ee81ae8f7fd9742d505e

执行命令如下:

➜  libchrome git:(master)git format-patch ab0b0fa5c5b0ecfa6d7f60da3e7b153c4337d4c4..88c7d5c272925d8f27366ed239a4f46ae00ceb16
0001-Add-ramdisk_available-to-init_first_stage-s-deps.patch
➜  libchrome git:(master) ✗ 
➜  libchrome git:(master)ls
0001-Add-ramdisk_available-to-init_first_stage-s-deps.patch  Android.bp  build     BUILD.IGNORE  crypto  device  libchrome_tools  MODULE_LICENSE_BSD  NOTICE  soong    testrunner.cc  ui
0001-feat-test.patch                                         base        BUILD.gn  components    dbus    ipc     METADATA         mojo                OWNERS  testing  third_party
➜  libchrome git:(master)

可以看出执行该命令后生从了如下两个patch文件, 也就是该两个commit对应的patch.

0001-Add-ramdisk_available-to-init_first_stage-s-deps.patch
0001-feat-test.patch

ehh 这里是两个patch?? 该怎么一次性打入呢?
可以执行如下命令:

git am *.patch // *.patch 需要是patch文件的所在路径

最后需要补充说明的是,git format-patch/ git am 在平台适配时的代码移植时使用比较高效,另外需要注意与bundle/cherry-pick的差异.

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐