<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>https://wiki.uotan.cn/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=XiaoleGun</id>
	<title>Uotan Wiki · 刷机百科 - 用户贡献 [zh-cn]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.uotan.cn/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=XiaoleGun"/>
	<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=%E7%89%B9%E6%AE%8A:%E7%94%A8%E6%88%B7%E8%B4%A1%E7%8C%AE/XiaoleGun"/>
	<updated>2026-06-13T20:55:17Z</updated>
	<subtitle>用户贡献</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=%E4%B8%BA%E6%96%B0%E8%AE%BE%E5%A4%87%E7%BC%96%E5%86%99Recovery_device_tree&amp;diff=558</id>
		<title>为新设备编写Recovery device tree</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=%E4%B8%BA%E6%96%B0%E8%AE%BE%E5%A4%87%E7%BC%96%E5%86%99Recovery_device_tree&amp;diff=558"/>
		<updated>2024-02-20T08:37:18Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​fixup&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= 为新设备编写 Recovery 的设备树 =&lt;br /&gt;
作者: Dark(xiaoleGun)&lt;br /&gt;
&lt;br /&gt;
时间: 2024.2.20&lt;br /&gt;
&lt;br /&gt;
协作者:&lt;br /&gt;
&lt;br /&gt;
== 一些自序 ==&lt;br /&gt;
这篇教程中可能有些不对的地方，请各位指正，我也刚接触 Android 设备测开发两年，而且只有在节假日的时候有空一个人瞎捣鼓，为了&amp;lt;s&amp;gt;薅 mjw 羊毛&amp;lt;/s&amp;gt;，故写这篇教程，而且我个人更推荐 Aosp Recovery 刷写第三方 ROM，TWRP 可能多多少少有些问题。Root 之类的不需要 TWRP 也可以，可以找到原机 boot 使用 Magisk 进行修补，也可以使用 KernelSU。另外我的语文功底不是很好，写不出辞藻，只能是北方地道的大白话，见谅哈 🤣///&lt;br /&gt;
&lt;br /&gt;
== 准备工作 ==&lt;br /&gt;
1.一颗勇敢的、不怕困难的强大心脏。&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;s&amp;gt;两颗心好勇敢 -- Falling in love&amp;lt;/s&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
2.电脑配置:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!硬件&lt;br /&gt;
!需求&lt;br /&gt;
|-&lt;br /&gt;
|CPU&lt;br /&gt;
|四核或更多&lt;br /&gt;
|-&lt;br /&gt;
|内存&lt;br /&gt;
|8G 或更多&lt;br /&gt;
|-&lt;br /&gt;
|硬盘&lt;br /&gt;
|至少 80G 空余空间&lt;br /&gt;
|-&lt;br /&gt;
|系统&lt;br /&gt;
|WSL 或实体 Linux，建议 Debian 系&lt;br /&gt;
|}&lt;br /&gt;
3.足够的空闲时间。&lt;br /&gt;
&lt;br /&gt;
4.Vscode 和 🤏Linux 知识储备&lt;br /&gt;
&lt;br /&gt;
5.一台完好无损的新设备。&lt;br /&gt;
&lt;br /&gt;
6.设备原厂的 boot/recovery/vendor_boot 镜像。(推荐 recovery 分区，因为里面包含一些启动必须的.rc(run command)，如果没有该分区，寻找包含官方 recovery 内容的分区。值得注意的是部分设备 recovery 合并到了 boot 中，或是存在于 vendor_boot）&lt;br /&gt;
&lt;br /&gt;
7.查看自己的设备出厂 Android 版本并确定用途，是用于官方 ROM 还是第三方类原生。出厂版本为 9 及以上的可以使用 twrp-11 及以上分支，9 以下使用 twrp-9 分支。&lt;br /&gt;
&lt;br /&gt;
== 配置环境 ==&lt;br /&gt;
&lt;br /&gt;
=== 安装依赖 ===&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt-get install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev liblz4-tool libncurses5 libncurses5-dev libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev xattr openjdk-11-jdk jq android-sdk-libsparse-utils python3 python2 repo&lt;br /&gt;
&lt;br /&gt;
必要时可以阅读[https://source.android.com/source/using-repo?hl=zh-cn Git 和 Repo]&lt;br /&gt;
&lt;br /&gt;
=== 配置 Git 和 Repo ===&lt;br /&gt;
安装完依赖后，在终端执行。&lt;br /&gt;
 git config --global user.name &amp;quot;your username&amp;quot;&lt;br /&gt;
 git config --global user.email &amp;quot;your email&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== 同步 TWRP 源码 ===&lt;br /&gt;
在自己方便的地方，建立一个目录。&lt;br /&gt;
 mkdir twrp&lt;br /&gt;
 cd twrp&lt;br /&gt;
根据自己在准备工作中确定的分支同步相应的源码。&lt;br /&gt;
&lt;br /&gt;
==== TWRP-9 ====&lt;br /&gt;
 repo init --depth=1 -u &amp;lt;nowiki&amp;gt;https://github.com/minimal-manifest-twrp/platform_manifest_twrp_omni.git&amp;lt;/nowiki&amp;gt; -b twrp-9.0&lt;br /&gt;
 repo sync&lt;br /&gt;
&lt;br /&gt;
==== TWRP-11 ====&lt;br /&gt;
 repo init --depth=1 -u &amp;lt;nowiki&amp;gt;https://github.com/minimal-manifest-twrp/platform_manifest_twrp_aosp.git&amp;lt;/nowiki&amp;gt; -b twrp-11&lt;br /&gt;
 repo sync&lt;br /&gt;
&lt;br /&gt;
==== TWRP-12.1 ====&lt;br /&gt;
 repo init --depth=1 -u &amp;lt;nowiki&amp;gt;https://github.com/minimal-manifest-twrp/platform_manifest_twrp_aosp.git&amp;lt;/nowiki&amp;gt; -b twrp-12.1&lt;br /&gt;
 repo sync&lt;br /&gt;
&lt;br /&gt;
== 编写设备树 ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;最基本的开机部分我通过 Redmi K50 做示例，并选取 TWRP-12.1 分支。&lt;br /&gt;
&lt;br /&gt;
解密部分会单独成一个章节并分为高通和联发科。&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 获取资料 ===&lt;br /&gt;
小米设备一般可以在[https://xiaomirom.com Xiaomirom]中的线刷包获取 boot/recovery/vendor_boot 镜像，其它设备请自行寻找。&lt;br /&gt;
&lt;br /&gt;
==== 安装工具和依赖 ====&lt;br /&gt;
将准备工作中准备的 boot/recovery/vendor_boot 镜像解包，可以用任何工具，我这里使用[https://github.com/cfig/Android_boot_image_editor Android_boot_image_editor]按照自述文件进行依赖安装操作：&lt;br /&gt;
&lt;br /&gt;
===== Mac(Intel) =====&lt;br /&gt;
 brew install lz4 xz dtc openjdk@17&lt;br /&gt;
 echo 'export PATH=&amp;quot;/usr/local/opt/openjdk@17/bin:$PATH&amp;quot;' &amp;gt;&amp;gt; ~/.zshrc&lt;br /&gt;
 source ~/.zshrc&lt;br /&gt;
&lt;br /&gt;
===== Linux: =====&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-17-jdk gcc g++ python3 python-is-python3 p7zip-full android-sdk-libsparse-utils erofs-utils&lt;br /&gt;
&lt;br /&gt;
===== Common: =====&lt;br /&gt;
 git clone &amp;lt;nowiki&amp;gt;https://github.com/cfig/Android_boot_image_editor&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 cd Android_boot_image_editor&lt;br /&gt;
&lt;br /&gt;
==== 解包 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;请注意&amp;quot;/&amp;quot;表示或的意思，请不要误以为是一个东西。&lt;br /&gt;
&lt;br /&gt;
如果不确定分区寻找的是否正确，请尝试将可以的分区进行解包，并查看其ramdisk内是否包含recovery字样的文件&amp;lt;/blockquote&amp;gt;将你准备好的boot/recovery/vendor_boot复制到该目录，你可以使用 GUI 或者 CLI。如:&lt;br /&gt;
 cp &amp;lt;出厂boot/recovery/vendor_boot的绝对路径&amp;gt; boot/recovery/vendor_boot.img&lt;br /&gt;
 ./gradlew unpack&lt;br /&gt;
我这里以 Redmi K50 为例&lt;br /&gt;
 10:12:13.188 [main] INFO  cfig.bootimg.v3.VendorBoot -&lt;br /&gt;
                         Unpack Summary of vendor_boot.img&lt;br /&gt;
 ┌───────────────────────────────────────┬──────────────────────────────────────┐&lt;br /&gt;
 │What                                   │Where                                 │&lt;br /&gt;
 └───────────────────────────────────────┴──────────────────────────────────────┘&lt;br /&gt;
 ┌───────────────────────────────────────┬──────────────────────────────────────┐&lt;br /&gt;
 │image info                             │build/unzip_boot/vendor_boot.json     │&lt;br /&gt;
 ├───────────────────────────────────────┼──────────────────────────────────────┤&lt;br /&gt;
 │ramdisk                                │build/unzip_boot/ramdisk.img.lz4      │&lt;br /&gt;
 │-- PLATFORM ramdisk[1/1]               │build/unzip_boot/ramdisk.1.lz4        │&lt;br /&gt;
 │------- extracted rootfs               │build/unzip_boot/root.1               │&lt;br /&gt;
 ├───────────────────────────────────────┼──────────────────────────────────────┤&lt;br /&gt;
 │dtb                                    │build/unzip_boot/dtb                  │&lt;br /&gt;
 ├───────────────────────────────────────┼──────────────────────────────────────┤&lt;br /&gt;
 │AVB info                               │build/unzip_boot/vendor_boot.avb.json │&lt;br /&gt;
 │\-- signing key                        │NONE                                  │&lt;br /&gt;
 └───────────────────────────────────────┴──────────────────────────────────────┘&lt;br /&gt;
 10:12:13.213 [main] WARN  cfig.packable.PackableLauncher - 'unpack' sequence completed&lt;br /&gt;
 &lt;br /&gt;
 BUILD SUCCESSFUL in 2s&lt;br /&gt;
解包成功后终端会打印出以上信息，其中包含vendor_boot目录结构，我们只需要ramdisk里的部分内容就好了。&lt;br /&gt;
 ls build/unzip_boot/root.1 # 请根据自己的分区和设备判断ramdisk的命名，一般都直接是ramdisk&lt;br /&gt;
不出意外的话会输出以下内容&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/dump/bootedit   master ?  ls build/unzip_boot/root.1&lt;br /&gt;
 acct                         oem&lt;br /&gt;
 apex                         plat_file_contexts&lt;br /&gt;
 bin                          plat_property_contexts&lt;br /&gt;
 bugreports                   postinstall&lt;br /&gt;
 config                       proc&lt;br /&gt;
 d                            product&lt;br /&gt;
 data                         product_file_contexts&lt;br /&gt;
 data_mirror                  product_property_contexts&lt;br /&gt;
 debug_ramdisk                prop.default&lt;br /&gt;
 default.prop                 res&lt;br /&gt;
 dev                          sdcard&lt;br /&gt;
 etc                          second_stage_resources&lt;br /&gt;
 first_stage_ramdisk          sepolicy&lt;br /&gt;
 init                         storage&lt;br /&gt;
 init.recovery.hardware.rc    sys&lt;br /&gt;
 init.recovery.mt6895.rc      system&lt;br /&gt;
 lib                          system_ext&lt;br /&gt;
 linkerconfig                 system_ext_file_contexts&lt;br /&gt;
 miui.factoryreset.fstab      system_ext_property_contexts&lt;br /&gt;
 miui.factoryreset.rc         tmp&lt;br /&gt;
 mnt                          vendor&lt;br /&gt;
 odm                          vendor_dlkm&lt;br /&gt;
 odm_dlkm                     vendor_file_contexts&lt;br /&gt;
 odm_file_contexts            vendor_property_contexts&lt;br /&gt;
 odm_property_contexts&lt;br /&gt;
如果包含 init.recovery*的字样，恭喜你成功找到了正确的分区。将这个目录复制到一个自己方便的地方。&lt;br /&gt;
&lt;br /&gt;
至此资料已经大致齐全了，解密的资料会在解密章节来讲解如何获取。&lt;br /&gt;
&lt;br /&gt;
=== 初始化目录结构 ===&lt;br /&gt;
在 twrp 源码根目录输入&lt;br /&gt;
 mkdir -p device/vendor/codename&lt;br /&gt;
 mkdir -p device/vendor/codename/recovery/root&lt;br /&gt;
 cd device/vendor/codename&lt;br /&gt;
vendor指的是供应商，如 xiaomi、oneplus、huawei、vivo、realme。&lt;br /&gt;
&lt;br /&gt;
codename指的是设备代号，小米设备可以在[https://xiaomirom.com Xiaomirom]查询，其它设备自行查询亦或是在开发者选项勾选 USB 调试通过 adb 尝试获取。&lt;br /&gt;
 adb shell getprop ro.product.manufacturer # 供应商&lt;br /&gt;
 adb shell getprop ro.product.device # 设备代号&lt;br /&gt;
我的 Redmi K50 会打印以下信息&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/dump/bootedit   master ?  adb shell getprop ro.product.manufacturer&lt;br /&gt;
 Xiaomi # 无论打印出来的内容是大写还是小写，在目录结构中我们都采用小写&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/dump/bootedit   master ?  adb shell getprop ro.product.device&lt;br /&gt;
 rubens&lt;br /&gt;
我的 IQOO NEO5 Lite 会打印以下信息&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  adb shell getprop ro.product.manufacturer&lt;br /&gt;
 vivo&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  adb shell getprop ro.product.device&lt;br /&gt;
 PD2118&lt;br /&gt;
一般只要不是山寨机，小作坊出来的机子，用这两条命令应该是可以正确获取的。&lt;br /&gt;
&lt;br /&gt;
=== 初始化构建时必要的文件 ===&lt;br /&gt;
无论是 AOSP device tree 亦或是 TWRP device tree 都基本类似于以下结构。&lt;br /&gt;
 /&lt;br /&gt;
 ├── prebuilt           (存放kernel、dtb等预编译文件) # AOSP device tree若使用build kernel则没有该目录&lt;br /&gt;
 ├── recovery/root      (存放一些.rc和解密blobs) # 一般用于Recovery device tree&lt;br /&gt;
 ├── Android.mk         (Android构建系统首先会检查每个目录的Android.mk，里面包含一些判断，由它包括其所在目录中所有Makefile)&lt;br /&gt;
 ├── AndroidProducts.mk (声明产品的Makefile和lunch时可用的构建类型)&lt;br /&gt;
 ├── BoardConfig.mk     (板载配置文件，定义了主板必要的Flag)&lt;br /&gt;
 ├── device.mk          (声明设备所需的文件和模块)&lt;br /&gt;
 └── &amp;lt;ROM&amp;gt;_codename.mk  (声明产品特定信息，例如名称、品牌和型号，引用device.mk等) # ROM就比如lineage、arrow等，编译twrp就直接写twrp，twrp-9分支要写onmi&lt;br /&gt;
我们把这样的结构称为骨架树(skeleton tree)。&lt;br /&gt;
&lt;br /&gt;
接下来我们按照以上结构为自己的设备写一份 Recovery device tree。&lt;br /&gt;
&lt;br /&gt;
在终端使用touch命令创建必要的文件。&lt;br /&gt;
 touch Android.mk AndroidProducts.mk BoardConfig.mk device.mk twrp_rubens.mk&lt;br /&gt;
 ls .&lt;br /&gt;
不出意外的话会打印出以下信息&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  touch Android.mk AndroidProducts.mk BoardConfig.mk device.mk twrp_rubens.mk&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  ls .&lt;br /&gt;
 Android.mk         BoardConfig.mk     prebuilt           twrp_rubens.mk&lt;br /&gt;
 AndroidProducts.mk device.mk          recovery&lt;br /&gt;
可以下一步了~&lt;br /&gt;
&lt;br /&gt;
==== 初始 Android.mk 文件 ====&lt;br /&gt;
打开 Vscode 并打开设备树目录，你足够强也可以使用 nano、vim 编辑。&lt;br /&gt;
&lt;br /&gt;
选中 Android.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 LOCAL_PATH := $(call my-dir)&lt;br /&gt;
 &lt;br /&gt;
 ifeq ($(TARGET_DEVICE),codename)&lt;br /&gt;
 include $(call all-subdir-makefiles,$(LOCAL_PATH))&lt;br /&gt;
 endif&lt;br /&gt;
&lt;br /&gt;
* codename是需要你修改的部分&lt;br /&gt;
&lt;br /&gt;
我修改后是这样的&lt;br /&gt;
 LOCAL_PATH := $(call my-dir)&lt;br /&gt;
 &lt;br /&gt;
 ifeq ($(TARGET_DEVICE),rubens)&lt;br /&gt;
 include $(call all-subdir-makefiles,$(LOCAL_PATH))&lt;br /&gt;
 endif&lt;br /&gt;
&lt;br /&gt;
==== 初始 AndroidProducts.mk 文件 ====&lt;br /&gt;
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 PRODUCT_MAKEFILES := \&lt;br /&gt;
     $(LOCAL_DIR)/&amp;lt;ROM&amp;gt;_&amp;lt;codename&amp;gt;.mk&lt;br /&gt;
 &lt;br /&gt;
 COMMON_LUNCH_CHOICES := \&lt;br /&gt;
     &amp;lt;ROM&amp;gt;_&amp;lt;codename&amp;gt;-eng&lt;br /&gt;
我修改后是这样的&lt;br /&gt;
 PRODUCT_MAKEFILES := \&lt;br /&gt;
     $(LOCAL_DIR)/twrp_rubens.mk&lt;br /&gt;
 &lt;br /&gt;
 COMMON_LUNCH_CHOICES := \&lt;br /&gt;
     twrp_rubens-eng&lt;br /&gt;
&lt;br /&gt;
==== 初始 BoardConfig.mk 文件 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;将之前准备的ramdisk文件夹用新窗口打开 1.找到目录下的 prop.default 或含 prop 字样的文件。以下注释类似 ro.*.*的就是从 prop 中获取的 2.解包 boot/recovery/vendor_boot 的 json&lt;br /&gt;
&lt;br /&gt;
例如 build/unzip_boot/boot.json&amp;lt;/blockquote&amp;gt;选中 BoardConfig.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 DEVICE_PATH := device/vendor/codename&lt;br /&gt;
 &lt;br /&gt;
 # Architecture&lt;br /&gt;
 TARGET_ARCH := arm64 # ro.bionic.arch&lt;br /&gt;
 TARGET_ARCH_VARIANT := armv8-a # 64位默认变体&lt;br /&gt;
 TARGET_CPU_ABI := arm64-v8a # ro.vendor.product.cpu.abilist64 (至少在小米设备上没有找到ro.product.cpu.abilist)&lt;br /&gt;
 TARGET_CPU_ABI2 := # 64位留空&lt;br /&gt;
 TARGET_CPU_VARIANT := generic # 默认一般都是通用&lt;br /&gt;
 TARGET_CPU_VARIANT_RUNTIME := cortex-a55 # ro.bionic.cpu_variant&lt;br /&gt;
 &lt;br /&gt;
 TARGET_2ND_ARCH := arm # ro.bionic.2nd_arch&lt;br /&gt;
 TARGET_2ND_ARCH_VARIANT := $(TARGET_ARCH_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_ABI := armeabi-v7a # ro.vendor.product.cpu.abilist32第一个&lt;br /&gt;
 TARGET_2ND_CPU_ABI2 := armeabi # ro.vendor.product.cpu.abilist32第二个&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT_RUNTIME := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 &lt;br /&gt;
 # Assertation&lt;br /&gt;
 TARGET_OTA_ASSERT_DEVICE := rubens # codename&lt;br /&gt;
 &lt;br /&gt;
 # Bootloader&lt;br /&gt;
 TARGET_BOOTLOADER_BOARD_NAME := rubens # ro.product.board&lt;br /&gt;
 TARGET_NO_BOOTLOADER := true&lt;br /&gt;
 TARGET_USES_UEFI := true&lt;br /&gt;
 &lt;br /&gt;
 # Build Rule&lt;br /&gt;
 ALLOW_MISSING_DEPENDENCIES := true # 为了recovery不健全的依赖&lt;br /&gt;
 &lt;br /&gt;
 # Kernel - 注释会说明在boot/recovery/vendor_boot.json中对应的变量&lt;br /&gt;
 BOARD_BOOT_HEADER_VERSION := 4 # headerVersion&lt;br /&gt;
 BOARD_KERNEL_BASE := 0x3fff8000 # (kernelLoadAddr - 32KB) qcom设备base为0，且没有偏移(offset)&lt;br /&gt;
 BOARD_KERNEL_CMDLINE := bootopt=64S3,32N2,64N2 # cmdline&lt;br /&gt;
 BOARD_KERNEL_PAGESIZE := 4096 # pageSize&lt;br /&gt;
 BOARD_RAMDISK_OFFSET := 0x26f08000 # (ramdisk,loadAddr - BOARD_KERNEL_BASE)&lt;br /&gt;
 BOARD_KERNEL_TAGS_OFFSET := 0x07c88000 # (tagsLoadAddr - BOARD_KERNEL_BASE)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --ramdisk_offset $(BOARD_RAMDISK_OFFSET)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --tags_offset $(BOARD_KERNEL_TAGS_OFFSET)&lt;br /&gt;
 &lt;br /&gt;
 # Kernel - prebuilt&lt;br /&gt;
 TARGET_PREBUILT_KERNEL := $(DEVICE_PATH)/prebuilt/kernel # 预编译内核相对于android源码根目录的相对路径，vendor_boot机型不需要&lt;br /&gt;
 TARGET_PREBUILT_DTB := $(DEVICE_PATH)/prebuilt/dtb.img # 同上&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --dtb $(TARGET_PREBUILT_DTB)&lt;br /&gt;
 &lt;br /&gt;
 # Partitions&lt;br /&gt;
 BOARD_FLASH_BLOCK_SIZE := 262144 # (BOARD_KERNEL_PAGESIZE * 64)&lt;br /&gt;
 BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864 # boot/recovery/vendor_boot镜像的字节大小需原厂或手机完整提取出来的，不定义会报错&lt;br /&gt;
 BOARD_RECOVERYIMAGE_PARTITION_SIZE := 67108864 # 同上&lt;br /&gt;
 BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE := 67108864 # 同上&lt;br /&gt;
 BOARD_SYSTEMIMAGE_PARTITION_TYPE := ext4 # 分区类型，查看ramdisk中fstab定义的类型&lt;br /&gt;
 BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 TARGET_COPY_OUT_VENDOR := vendor # 定义vendor目录，例如copy专有blobs要用&lt;br /&gt;
 BOARD_SUPER_PARTITION_SIZE := 9126805504 # 可以通过blockdev --getsize64 /dev/block/bootdevice/by-name/super获取，需root，如果无法root可以直接使用这个值，不影响twrp启动，可以后续修正&lt;br /&gt;
 BOARD_SUPER_PARTITION_GROUPS := xiaomi_dynamic_partitions # xiaomi根据你获取资料的vendor替换，是一个动态分区组&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product system_ext odm vendor_dlkm odm_dlkm # 根据fstab内的定义，一般flag包含logical都属于动态分区组的一部分&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_SIZE := 9122611200 # (BOARD_SUPER_PARTITION_SIZE - 4MB)&lt;br /&gt;
 &lt;br /&gt;
 # Platform&lt;br /&gt;
 TARGET_BOARD_PLATFORM := mt6895 # ro.board.platform&lt;br /&gt;
 &lt;br /&gt;
 # Recovery - 基本通用的不影响启动&lt;br /&gt;
 BOARD_HAS_LARGE_FILESYSTEM := true&lt;br /&gt;
 TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888&lt;br /&gt;
 TARGET_USERIMAGES_USE_EXT4 := true&lt;br /&gt;
 TARGET_USERIMAGES_USE_F2FS := true&lt;br /&gt;
 &lt;br /&gt;
 # Treble&lt;br /&gt;
 BOARD_VNDK_VERSION := current # 声明VNDK版本&lt;br /&gt;
 &lt;br /&gt;
 # Vendor_boot recovery ramdisk&lt;br /&gt;
 BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true # 将recovery文件复制到vendor_boot&lt;br /&gt;
 &lt;br /&gt;
 # Boot recovery ramdisk&lt;br /&gt;
 #BOARD_USES_RECOVERY_AS_BOOT := true recovery ramdisk合并在boot中启用&lt;br /&gt;
 &lt;br /&gt;
 # Verified Boot&lt;br /&gt;
 BOARD_AVB_ENABLE := true&lt;br /&gt;
 BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flags 3&lt;br /&gt;
 &lt;br /&gt;
 # TWRP Configurations&lt;br /&gt;
 TW_DEFAULT_LANGUAGE := zh_CN # 默认为中文&lt;br /&gt;
 TW_EXTRA_LANGUAGES := true # 额外的语言&lt;br /&gt;
 TW_THEME := portrait_hdpi # 主题&lt;br /&gt;
 TW_INCLUDE_FASTBOOTD := true # 包括fastbootd，为动态分区&lt;br /&gt;
 &lt;br /&gt;
 # 其它flag还有很多，可以在https://xdaforums.com/t/twrp-flags-for-boardconfig-mk.3333970 查找，&lt;br /&gt;
 # 这篇文章也很老了，但我并不推荐twrp，所以flag我也不是很了解，多翻翻github:)&lt;br /&gt;
 &lt;br /&gt;
 # Debug&lt;br /&gt;
 TARGET_USES_LOGD := true # 调试flag&lt;br /&gt;
 TWRP_INCLUDE_LOGCAT := true&lt;br /&gt;
无注释版&lt;br /&gt;
 DEVICE_PATH := device/vendor/codename&lt;br /&gt;
 &lt;br /&gt;
 # Architecture&lt;br /&gt;
 TARGET_ARCH := arm64&lt;br /&gt;
 TARGET_ARCH_VARIANT := armv8-a&lt;br /&gt;
 TARGET_CPU_ABI := arm64-v8a&lt;br /&gt;
 TARGET_CPU_ABI2 :=&lt;br /&gt;
 TARGET_CPU_VARIANT := generic&lt;br /&gt;
 TARGET_CPU_VARIANT_RUNTIME := cortex-a55&lt;br /&gt;
 &lt;br /&gt;
 TARGET_2ND_ARCH := arm&lt;br /&gt;
 TARGET_2ND_ARCH_VARIANT := $(TARGET_ARCH_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_ABI := armeabi-v7a&lt;br /&gt;
 TARGET_2ND_CPU_ABI2 := armeabi&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT_RUNTIME := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 &lt;br /&gt;
 # Assertation&lt;br /&gt;
 TARGET_OTA_ASSERT_DEVICE := rubens&lt;br /&gt;
 &lt;br /&gt;
 # Bootloader&lt;br /&gt;
 TARGET_BOOTLOADER_BOARD_NAME := rubens&lt;br /&gt;
 TARGET_NO_BOOTLOADER := true&lt;br /&gt;
 TARGET_USES_UEFI := true&lt;br /&gt;
 &lt;br /&gt;
 # Build Rule&lt;br /&gt;
 ALLOW_MISSING_DEPENDENCIES := true&lt;br /&gt;
 &lt;br /&gt;
 # Kernel&lt;br /&gt;
 BOARD_BOOT_HEADER_VERSION := 4&lt;br /&gt;
 BOARD_KERNEL_BASE := 0x3fff8000&lt;br /&gt;
 BOARD_KERNEL_CMDLINE := bootopt=64S3,32N2,64N2&lt;br /&gt;
 BOARD_KERNEL_PAGESIZE := 4096&lt;br /&gt;
 BOARD_RAMDISK_OFFSET := 0x26f08000&lt;br /&gt;
 BOARD_KERNEL_TAGS_OFFSET := 0x07c88000&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --ramdisk_offset $(BOARD_RAMDISK_OFFSET)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --tags_offset $(BOARD_KERNEL_TAGS_OFFSET)&lt;br /&gt;
 BOARD_KERNEL_IMAGE_NAME := Image&lt;br /&gt;
 &lt;br /&gt;
 # Kernel - prebuilt&lt;br /&gt;
 TARGET_PREBUILT_DTB := $(DEVICE_PATH)/prebuilt/dtb.img&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --dtb $(TARGET_PREBUILT_DTB)&lt;br /&gt;
 &lt;br /&gt;
 # Partitions&lt;br /&gt;
 BOARD_FLASH_BLOCK_SIZE := 262144&lt;br /&gt;
 BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864&lt;br /&gt;
 BOARD_RECOVERYIMAGE_PARTITION_SIZE := 67108864&lt;br /&gt;
 BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE := 67108864&lt;br /&gt;
 BOARD_SYSTEMIMAGE_PARTITION_TYPE := ext4&lt;br /&gt;
 BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 TARGET_COPY_OUT_VENDOR := vendor&lt;br /&gt;
 BOARD_SUPER_PARTITION_SIZE := 9126805504&lt;br /&gt;
 BOARD_SUPER_PARTITION_GROUPS := xiaomi_dynamic_partitions&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product system_ext odm vendor_dlkm odm_dlkm&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_SIZE := 9122611200&lt;br /&gt;
 &lt;br /&gt;
 # Platform&lt;br /&gt;
 TARGET_BOARD_PLATFORM := mt6895&lt;br /&gt;
 &lt;br /&gt;
 # Recovery&lt;br /&gt;
 BOARD_HAS_LARGE_FILESYSTEM := true&lt;br /&gt;
 TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888&lt;br /&gt;
 TARGET_USERIMAGES_USE_EXT4 := true&lt;br /&gt;
 TARGET_USERIMAGES_USE_F2FS := true&lt;br /&gt;
 &lt;br /&gt;
 # Treble&lt;br /&gt;
 BOARD_VNDK_VERSION := current&lt;br /&gt;
 &lt;br /&gt;
 # Vendor_boot recovery ramdisk&lt;br /&gt;
 BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true&lt;br /&gt;
 &lt;br /&gt;
 # Boot recovery ramdisk&lt;br /&gt;
 #BOARD_USES_RECOVERY_AS_BOOT := true&lt;br /&gt;
 &lt;br /&gt;
 # Verified Boot&lt;br /&gt;
 BOARD_AVB_ENABLE := true&lt;br /&gt;
 BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flags 3&lt;br /&gt;
 &lt;br /&gt;
 # TWRP Configurations&lt;br /&gt;
 TW_DEFAULT_LANGUAGE := zh_CN&lt;br /&gt;
 TW_EXTRA_LANGUAGES := true&lt;br /&gt;
 TW_THEME := portrait_hdpi&lt;br /&gt;
 TW_INCLUDE_FASTBOOTD := true&lt;br /&gt;
 &lt;br /&gt;
 # Debug&lt;br /&gt;
 TARGET_USES_LOGD := true&lt;br /&gt;
 TWRP_INCLUDE_LOGCAT := true&lt;br /&gt;
这块写了好久我也不确定对不对，请各位指正，尤其是 Kernel 部分。&lt;br /&gt;
&lt;br /&gt;
==== 初始 device.mk 文件 ====&lt;br /&gt;
&lt;br /&gt;
* 准备好 prop.default&lt;br /&gt;
&lt;br /&gt;
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 DEVICE_PATH := device/xiaomi/rubens&lt;br /&gt;
 &lt;br /&gt;
 # API&lt;br /&gt;
 PRODUCT_SHIPPING_API_LEVEL := 31 # ro.board.first_api_level&lt;br /&gt;
 &lt;br /&gt;
 # A/B&lt;br /&gt;
 AB_OTA_UPDATER := true # 启用A/B无缝更新&lt;br /&gt;
 AB_OTA_PARTITIONS += \ # 定义A/B分区，参考fstab&lt;br /&gt;
     boot \&lt;br /&gt;
     dtbo \&lt;br /&gt;
     system \&lt;br /&gt;
     product \&lt;br /&gt;
     vendor \&lt;br /&gt;
     odm \&lt;br /&gt;
     odm_dlkm \&lt;br /&gt;
     vbmeta \&lt;br /&gt;
     vendor_boot \&lt;br /&gt;
     vendor_dlkm \&lt;br /&gt;
     vbmeta_system \&lt;br /&gt;
     vbmeta_vendor&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PACKAGES += \&lt;br /&gt;
     update_engine \&lt;br /&gt;
     update_engine_sideload \&lt;br /&gt;
     update_verifier \&lt;br /&gt;
     checkpoint_gc&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_system=true \&lt;br /&gt;
     POSTINSTALL_PATH_system=system/bin/mtk_plpath_utils \&lt;br /&gt;
     FILESYSTEM_TYPE_system=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_system=true&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_vendor=true \&lt;br /&gt;
     POSTINSTALL_PATH_vendor=bin/checkpoint_gc \&lt;br /&gt;
     FILESYSTEM_TYPE_vendor=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_vendor=true&lt;br /&gt;
 &lt;br /&gt;
 # Dynamic&lt;br /&gt;
 PRODUCT_USE_DYNAMIC_PARTITIONS := true # 动态分区&lt;br /&gt;
 &lt;br /&gt;
 # Soong namespaces&lt;br /&gt;
 PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH) # 命名空间&lt;br /&gt;
&lt;br /&gt;
* A/B 无缝更新部分高通和联发科不一样，联发科设备可以照抄，注意 system/bin/mtk_plpath_utils 就好。高通参考[https://github.com/sekaiacg/android_device_xiaomi_venus_TWRP/tree/android-13 venus twrp tree]，并且高通的[https://git.codelinaro.org/clo/la/platform/hardware/qcom/bootctrl bootctrl]和[https://git.codelinaro.org/clo/la/platform/vendor/qcom-opensource/recovery-ext gpt-utils]可以从 [[CLO]] 拿。&lt;br /&gt;
&lt;br /&gt;
无注释版&lt;br /&gt;
 PRODUCT_SHIPPING_API_LEVEL := 31&lt;br /&gt;
 &lt;br /&gt;
 # A/B&lt;br /&gt;
 AB_OTA_UPDATER := true&lt;br /&gt;
 AB_OTA_PARTITIONS += \&lt;br /&gt;
     boot \&lt;br /&gt;
     dtbo \&lt;br /&gt;
     system \&lt;br /&gt;
     product \&lt;br /&gt;
     vendor \&lt;br /&gt;
     odm \&lt;br /&gt;
     odm_dlkm \&lt;br /&gt;
     vbmeta \&lt;br /&gt;
     vendor_boot \&lt;br /&gt;
     vendor_dlkm \&lt;br /&gt;
     vbmeta_system \&lt;br /&gt;
     vbmeta_vendor&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PACKAGES += \&lt;br /&gt;
     update_engine \&lt;br /&gt;
     update_engine_sideload \&lt;br /&gt;
     update_verifier \&lt;br /&gt;
     checkpoint_gc&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_system=true \&lt;br /&gt;
     POSTINSTALL_PATH_system=system/bin/mtk_plpath_utils \&lt;br /&gt;
     FILESYSTEM_TYPE_system=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_system=true&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_vendor=true \&lt;br /&gt;
     POSTINSTALL_PATH_vendor=bin/checkpoint_gc \&lt;br /&gt;
     FILESYSTEM_TYPE_vendor=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_vendor=true&lt;br /&gt;
 &lt;br /&gt;
 # Dynamic&lt;br /&gt;
 PRODUCT_USE_DYNAMIC_PARTITIONS := true&lt;br /&gt;
 &lt;br /&gt;
 # Soong namespaces&lt;br /&gt;
 PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH)&lt;br /&gt;
&lt;br /&gt;
==== 初始 twrp_rubens.mk 文件 ====&lt;br /&gt;
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 # Inherit from common AOSP config&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk) # vab加载到vendor boot里使用&lt;br /&gt;
 &lt;br /&gt;
 # Inherit from TWRP product configuration&lt;br /&gt;
 $(call inherit-product, vendor/twrp/config/common.mk) # twrp-9分支改为onmi&lt;br /&gt;
 &lt;br /&gt;
 # Device specific configs&lt;br /&gt;
 $(call inherit-product, device/xiaomi/rubens/device.mk)&lt;br /&gt;
 &lt;br /&gt;
 # Device identifier&lt;br /&gt;
 PRODUCT_DEVICE := rubens # 设备型号&lt;br /&gt;
 PRODUCT_NAME := twrp_rubens # 设备名称&lt;br /&gt;
 PRODUCT_BRAND := Redmi # 自定义品牌，如果有&lt;br /&gt;
 PRODUCT_MODEL := 22041211AC # 产品最终用户可见名称&lt;br /&gt;
 PRODUCT_MANUFACTURER := Xiaomi # 制造商&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true # 对twrp启动vendor_boot支持&lt;br /&gt;
无注释版&lt;br /&gt;
 # Inherit from common AOSP config&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk) # vab加载到vendor boot里使用&lt;br /&gt;
 &lt;br /&gt;
 # Inherit from TWRP product configuration&lt;br /&gt;
 $(call inherit-product, vendor/twrp/config/common.mk)&lt;br /&gt;
 &lt;br /&gt;
 # Device specific configs&lt;br /&gt;
 $(call inherit-product, device/xiaomi/rubens/device.mk)&lt;br /&gt;
 &lt;br /&gt;
 # Device identifier&lt;br /&gt;
 PRODUCT_DEVICE := rubens&lt;br /&gt;
 PRODUCT_NAME := twrp_rubens&lt;br /&gt;
 PRODUCT_BRAND := Redmi&lt;br /&gt;
 PRODUCT_MODEL := 22041211AC&lt;br /&gt;
 PRODUCT_MANUFACTURER := Xiaomi&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true&lt;br /&gt;
&lt;br /&gt;
==== 初始 recovery 目录 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;拿出我们好久之前准备的 ramdisk 叭&amp;lt;/blockquote&amp;gt;通过tree命令我们可以查看 ramdisk 的树状图，可以很清晰的查看包含的文件&lt;br /&gt;
 ├── acct&lt;br /&gt;
 ├── apex&lt;br /&gt;
 ├── bin -&amp;gt; /system/bin&lt;br /&gt;
 ├── bugreports -&amp;gt; /data/user_de/0/com.android.shell/files/bugreports&lt;br /&gt;
 ├── config&lt;br /&gt;
 ├── d -&amp;gt; /sys/kernel/debug&lt;br /&gt;
 ├── data&lt;br /&gt;
 ├── data_mirror&lt;br /&gt;
 ├── debug_ramdisk&lt;br /&gt;
 ├── default.prop -&amp;gt; prop.default&lt;br /&gt;
 ├── dev&lt;br /&gt;
 ├── etc -&amp;gt; /system/etc&lt;br /&gt;
 ├── first_stage_ramdisk&lt;br /&gt;
 │   ├── fstab.emmc&lt;br /&gt;
 │   ├── fstab.mt6895&lt;br /&gt;
 │   └── system&lt;br /&gt;
 │       ├── bin&lt;br /&gt;
 │       │   ├── e2fsck&lt;br /&gt;
 │       │   ├── linker64&lt;br /&gt;
 │       │   ├── linker_asan64 -&amp;gt; linker64&lt;br /&gt;
 │       │   └── snapuserd&lt;br /&gt;
 │       └── lib64&lt;br /&gt;
 │           ├── ld-android.so&lt;br /&gt;
 │           ├── libbase.so&lt;br /&gt;
 │           ├── libc++.so&lt;br /&gt;
 │           ├── libc.so&lt;br /&gt;
 │           ├── libdl.so&lt;br /&gt;
 │           ├── libext2_blkid.so&lt;br /&gt;
 │           ├── libext2_com_err.so&lt;br /&gt;
 │           ├── libext2_e2p.so&lt;br /&gt;
 │           ├── libext2_quota.so&lt;br /&gt;
 │           ├── libext2_uuid.so&lt;br /&gt;
 │           ├── libext2fs.so&lt;br /&gt;
 │           ├── liblog.so&lt;br /&gt;
 │           ├── libm.so&lt;br /&gt;
 │           ├── libsparse.so&lt;br /&gt;
 │           └── libz.so&lt;br /&gt;
 ├── init -&amp;gt; /system/bin/init&lt;br /&gt;
 ├── init.recovery.hardware.rc&lt;br /&gt;
 ├── init.recovery.mt6895.rc&lt;br /&gt;
 └── 等等等等...省略大概1000个文件吧&lt;br /&gt;
&amp;lt;blockquote&amp;gt;因为避免教程时效性，我们尽可能选取 prebuilt 的办法，如 boot 和 mtk_plpath_utils 都采用预编译。&amp;lt;/blockquote&amp;gt;里面有很多文件是没用的，整理一下，对我们有用的只有这些&lt;br /&gt;
 .&lt;br /&gt;
 ├── first_stage_ramdisk&lt;br /&gt;
 │   ├── fstab.emmc&lt;br /&gt;
 │   └── fstab.mt6895&lt;br /&gt;
 ├── init.recovery.mt6895.rc&lt;br /&gt;
 ├── lib&lt;br /&gt;
 │   └── modules&lt;br /&gt;
 │       ├── 8250_mtk.ko&lt;br /&gt;
 │       ├── adapter_class.ko&lt;br /&gt;
 │       ├── adsp.ko&lt;br /&gt;
 │       ├── aee_aed.ko&lt;br /&gt;
 │       ├── aee_hangdet.ko&lt;br /&gt;
 │       ├── aee_rs.ko&lt;br /&gt;
 │       ├── blocktag.ko&lt;br /&gt;
 │       ├── bootprof.ko&lt;br /&gt;
 │       ├── bq28z610.ko&lt;br /&gt;
 │       ├── cache-parity.ko&lt;br /&gt;
 │       ├── cfg80211.ko&lt;br /&gt;
 │       ├── charger_class.ko&lt;br /&gt;
 │       └── 省略一百多个模块，这个目录里的东西全要&lt;br /&gt;
 └── system&lt;br /&gt;
     ├── bin&lt;br /&gt;
     │   └── mtk_plpath_utils&lt;br /&gt;
     ├── etc&lt;br /&gt;
     │   ├── init&lt;br /&gt;
     │   │   │── mtk-plpath-utils.rc&lt;br /&gt;
     │   │   └──hw&lt;br /&gt;
     │   │      └──init.rc&lt;br /&gt;
     │   ├── recovery.fstab&lt;br /&gt;
     │   ├── security&lt;br /&gt;
     │   │   └── otacerts.zip&lt;br /&gt;
     │   └── ueventd.rc&lt;br /&gt;
     └── lib64&lt;br /&gt;
         └── hw&lt;br /&gt;
             └── android.hardware.boot@1.0-impl-1.2-mtkimpl.so&lt;br /&gt;
将它们按照以下操作复制&lt;br /&gt;
&lt;br /&gt;
* first_stage_ramdisk --&amp;gt; recovery/root/first_stage_ramdisk&lt;br /&gt;
* init.recovery.mt6895.rc --&amp;gt; recovery/root/init.recovery.mt6895.rc&lt;br /&gt;
* lib --&amp;gt; recovery/root/lib&lt;br /&gt;
* system --&amp;gt; recovery/root/system (security 和 hw 文件夹里的内容作为备用，不要复制进去) 得到以下目录结构&lt;br /&gt;
&lt;br /&gt;
 .&lt;br /&gt;
 ├── Android.mk&lt;br /&gt;
 ├── AndroidProducts.mk&lt;br /&gt;
 ├── BoardConfig.mk&lt;br /&gt;
 ├── device.mk&lt;br /&gt;
 ├── prebuilt&lt;br /&gt;
 ├── recovery&lt;br /&gt;
 │   └── root&lt;br /&gt;
 │       ├── first_stage_ramdisk&lt;br /&gt;
 │       │   ├── fstab.emmc&lt;br /&gt;
 │       │   └── fstab.mt6895&lt;br /&gt;
 │       ├── init.recovery.mt6895.rc&lt;br /&gt;
 │       ├── lib&lt;br /&gt;
 │       │   └── modules&lt;br /&gt;
 │       │       ├── 8250_mtk.ko&lt;br /&gt;
 │       │       ├── adapter_class.ko&lt;br /&gt;
 │       │       ├── adsp.ko&lt;br /&gt;
 │       │       ├── aee_aed.ko&lt;br /&gt;
 │       │       ├── aee_hangdet.ko&lt;br /&gt;
 │       │       ├── aee_rs.ko&lt;br /&gt;
 │       │       ├── blocktag.ko&lt;br /&gt;
 │       │       └── 省略....&lt;br /&gt;
 │       └── system&lt;br /&gt;
 │           ├── bin&lt;br /&gt;
 │           │   └── mtk_plpath_utils&lt;br /&gt;
 │           ├── etc&lt;br /&gt;
 │           │   ├── recovery.fstab&lt;br /&gt;
 │           │   └── ueventd.rc&lt;br /&gt;
 │           └── lib64&lt;br /&gt;
 │               └── hw&lt;br /&gt;
 │                   └── android.hardware.boot@1.0-impl-1.2-mtkimpl.so&lt;br /&gt;
 └── twrp_rubens.mk&lt;br /&gt;
打开 init.recovery.mt6895.rc 添加&lt;br /&gt;
 on boot&lt;br /&gt;
     start health-hal-2-1&lt;br /&gt;
 &lt;br /&gt;
 on post-fs&lt;br /&gt;
     start boot-hal-1-2&lt;br /&gt;
例如&lt;br /&gt;
 on post-fs&lt;br /&gt;
     start boot-hal-1-2&lt;br /&gt;
 &lt;br /&gt;
 on init&lt;br /&gt;
     setprop sys.usb.configfs 1&lt;br /&gt;
     setprop sys.usb.controller &amp;quot;11201000.usb0&amp;quot;&lt;br /&gt;
     setprop sys.usb.ffs.aio_compat 1&lt;br /&gt;
 &lt;br /&gt;
 on fs &amp;amp;&amp;amp; property:ro.debuggable=0&lt;br /&gt;
     # distinguish USB shoulde connect or not, i.e. CDP vs SDP&lt;br /&gt;
     # set charging free due to it wait for USB activation&lt;br /&gt;
 &lt;br /&gt;
 on boot&lt;br /&gt;
     start health-hal-2-1&lt;br /&gt;
     exec u:r:update_engine:s0 root root -- /system/bin/mtk_plpath_utils&lt;br /&gt;
 &lt;br /&gt;
接下来可以开始编译咯~~&lt;br /&gt;
&lt;br /&gt;
==== 编译 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;编译前请检查注释是否全部删除&amp;lt;/blockquote&amp;gt;twrp 源码根目录执行&lt;br /&gt;
 . build/envsetup.sh&lt;br /&gt;
 lunch twrp_codename-eng # twrp-9为onmi&lt;br /&gt;
 mka vendorbootimage/bootimage/recoveryimage&lt;br /&gt;
不出意外的话一路绿灯，如果有报错的话请发邮箱至 1592501605@qq.com 咨询我&lt;br /&gt;
&lt;br /&gt;
产物在 out/target/product/codename/vendor_boot.img\boot.img\recovery.img&lt;br /&gt;
&lt;br /&gt;
手机重启到 fastboot 模式，使用 fastboot flash 刷写，例如&lt;br /&gt;
 fastboot flash vendor_boot /Users/xiaolegun/Downloads/vendor_boot.img&lt;br /&gt;
则输出&lt;br /&gt;
 ERROR: could not clear input pipe; result e0005000, ignoring...&lt;br /&gt;
 ERROR: could not clear output pipe; result e0005000, ignoring....&lt;br /&gt;
 Sending 'vendor_boot_a' (65536 KB)                 OKAY [  1.396s]&lt;br /&gt;
 Writing 'vendor_boot_a'                            OKAY [  0.167s]&lt;br /&gt;
 Finished. Total time: 1.625s&lt;br /&gt;
就可以重启按电源加音量上尝试了，我自己是一次点亮，但有 bug。&lt;br /&gt;
&lt;br /&gt;
==== 修 BUG ====&lt;br /&gt;
&lt;br /&gt;
===== 修复 USB =====&lt;br /&gt;
我看到 twrp 控制台有很多报错，第一步肯定是先获取日志，使用logcat命令获取，在此之前先使用adb devices检测一下设备 usb 是否工作正常。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~  adb devices          ✔  10208  10:05:31&lt;br /&gt;
 * daemon not running; starting now at tcp:5037&lt;br /&gt;
 * daemon started successfully&lt;br /&gt;
 List of devices attached&lt;br /&gt;
可以看到adb没有检测到设备，原因一般是 usb 的配置不对，但 usb 是好的。这时可以尝试关闭 mtp，再开启，如果电脑有反应，那么就可以继续下一步了。&lt;br /&gt;
&lt;br /&gt;
在设备树中的 recovery/root，创建 init.recovery.usb.rc 的文件&lt;br /&gt;
 touch recovery/root/init.recovery.usb.rc&lt;br /&gt;
并导入以下内容&lt;br /&gt;
 on property:sys.usb.config=mtp,adb&lt;br /&gt;
     start adbd&lt;br /&gt;
 &lt;br /&gt;
 on property:sys.usb.ffs.ready=1 &amp;amp;&amp;amp; property:sys.usb.config=mtp,adb&lt;br /&gt;
     write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration &amp;quot;mtp_adb&amp;quot;&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f3&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f4&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f5&lt;br /&gt;
     write /config/usb_gadget/g1/idVendor 0x18d1&lt;br /&gt;
     write /config/usb_gadget/g1/idProduct 0x2d08&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}&lt;br /&gt;
     setprop sys.usb.state ${sys.usb.config}&lt;br /&gt;
这是我从我维护的 MI 6X 的 device tree 拿过来的，可以在联发科设备上正常工作。这段 shell 的大致意思就是在 usb 配置节点写入 mtp 和 adb 同时工作的字符串，这样 adb 就能顺利工作了。&lt;br /&gt;
&lt;br /&gt;
此外打开原厂 init.rc 修正一下 usb 设备的 id&lt;br /&gt;
 # MIUI ADD: START&lt;br /&gt;
 import /init.recovery.hardware.rc&lt;br /&gt;
 import /miui.factoryreset.rc&lt;br /&gt;
 # END&lt;br /&gt;
 import /init.recovery.${ro.hardware}.rc&lt;br /&gt;
 &lt;br /&gt;
 ########### 省略一万字&lt;br /&gt;
 &lt;br /&gt;
 # MIUI ADD: START&lt;br /&gt;
 on property:sys.usb.config=mtp,adb &amp;amp;&amp;amp; property:sys.usb.configfs=0&lt;br /&gt;
     write /sys/class/android_usb/android0/enable 0&lt;br /&gt;
     write /sys/class/android_usb/android0/idVendor 2717&lt;br /&gt;
     write /sys/class/android_usb/android0/idProduct 904D&lt;br /&gt;
     write /sys/class/android_usb/android0/functions mtp,adb&lt;br /&gt;
     write /sys/class/android_usb/android0/enable 1&lt;br /&gt;
     setprop sys.usb.state  ${sys.usb.config}&lt;br /&gt;
 # END&lt;br /&gt;
将/sys/class/android_usb/android0/idVendor和write /sys/class/android_usb/android0/idProduct后面的 id 分别替换到/config/usb_gadget/g1/idVendor和/config/usb_gadget/g1/idProduct处理完就是这样的。&lt;br /&gt;
 on property:sys.usb.config=mtp,adb&lt;br /&gt;
     start adbd&lt;br /&gt;
 &lt;br /&gt;
 on property:sys.usb.ffs.ready=1 &amp;amp;&amp;amp; property:sys.usb.config=mtp,adb&lt;br /&gt;
     write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration &amp;quot;mtp_adb&amp;quot;&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f3&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f4&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f5&lt;br /&gt;
     write /config/usb_gadget/g1/idVendor 0x2717&lt;br /&gt;
     write /config/usb_gadget/g1/idProduct 0x904D&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}&lt;br /&gt;
     setprop sys.usb.state ${sys.usb.config}&lt;br /&gt;
接下来开机之后 adb 和 mtp 就能同时工作了。&lt;br /&gt;
&lt;br /&gt;
===== 修复 Resetprop =====&lt;br /&gt;
接下来就可以修复其它 bug 了，我看到控制台有一堆红色的报错:&lt;br /&gt;
 E:Unknown File System:'/mi_ext'&lt;br /&gt;
 E:Unable to override 'external_storage.projid.enabled' due to missing libresetprop&lt;br /&gt;
 挂载“/data”失败(Invalid argument)&lt;br /&gt;
这三个报错中第二个最好修，第一个次之，第三个与解密有关，放在另一个大章节讲。&lt;br /&gt;
&lt;br /&gt;
第二个报错只需要在 BoardConfig.mk 中添加&lt;br /&gt;
 # Tool&lt;br /&gt;
 TW_INCLUDE_RESETPROP := true&lt;br /&gt;
 TW_INCLUDE_LIBRESETPROP := true&lt;br /&gt;
不用编译测试直接秒杀&lt;br /&gt;
&lt;br /&gt;
===== 修复挂载 =====&lt;br /&gt;
 E:Unknown File System:'/mi_ext'&lt;br /&gt;
我们打开 recovery/root/system/etc 中的 recovery.fstab，发现里面有很多空格，我们先将它格式化一下，有实力的可以把后面的 flag 也对齐整理好。&lt;br /&gt;
&lt;br /&gt;
我比较没实力，简单格式化了一下，是这样的&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 341 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;command line&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 2&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot; 2&lt;br /&gt;
 # 173 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 system /system erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system /system ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 vendor /vendor erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor /vendor ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 mi_ext /mnt/vendor/mi_ext erofs ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 mi_ext /mnt/vendor/mi_ext ext4 ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 /mnt/vendor/mi_ext /mi_ext none ro,bind wait,nofail&lt;br /&gt;
 overlay /product/overlay overlay ro,lowerdir=/mnt/vendor/mi_ext/product/overlay/:/product/overlay check,nofail&lt;br /&gt;
 overlay /product/app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/app/:/product/app check,nofail&lt;br /&gt;
 overlay /product/priv-app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/priv-app/:/product/priv-app check,nofail&lt;br /&gt;
 overlay /product/lib overlay ro,lowerdir=/mnt/vendor/mi_ext/product/lib/:/product/lib check,nofail&lt;br /&gt;
 overlay /product/lib64 overlay ro,lowerdir=/mnt/vendor/mi_ext/product/lib64/:/product/lib64 check,nofail&lt;br /&gt;
 overlay /product/bin overlay ro,lowerdir=/mnt/vendor/mi_ext/product/bin/:/product/bin check,nofail&lt;br /&gt;
 overlay /product/framework overlay ro,lowerdir=/mnt/vendor/mi_ext/product/framework/:/product/framework check,nofail&lt;br /&gt;
 overlay /product/media overlay ro,lowerdir=/mnt/vendor/mi_ext/product/media/:/product/media check,nofail&lt;br /&gt;
 overlay /product/opcust overlay ro,lowerdir=/mnt/vendor/mi_ext/product/opcust/:/product/opcust check,nofail&lt;br /&gt;
 overlay /product/data-app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/data-app/:/product/data-app check,nofail&lt;br /&gt;
 overlay /product/etc/sysconfig overlay ro,lowerdir=/mnt/vendor/mi_ext/product/etc/sysconfig/:/product/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /product/etc/permissions overlay ro,lowerdir=/mnt/vendor/mi_ext/product/etc/permissions/:/product/etc/permissions check,nofail&lt;br /&gt;
 overlay /system/app overlay ro,lowerdir=/mnt/vendor/mi_ext/system/app/:/product/pangu/system/app/:/system/app check,nofail&lt;br /&gt;
 overlay /system/priv-app overlay ro,lowerdir=/mnt/vendor/mi_ext/system/priv-app/:/product/pangu/system/priv-app/:/system/priv-app check,nofail&lt;br /&gt;
 overlay /system/framework overlay ro,lowerdir=/product/pangu/system/framework/:/system/framework check,nofail&lt;br /&gt;
 overlay /system/etc/sysconfig overlay ro,lowerdir=/mnt/vendor/mi_ext/system/etc/sysconfig/:/system/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /system/etc/permissions overlay ro,lowerdir=/mnt/vendor/mi_ext/system/etc/permissions/:/product/pangu/system/etc/permissions/:/system/etc/permissions check,nofail&lt;br /&gt;
 system_ext /system_ext erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system_ext /system_ext ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 odm /odm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm /odm ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor_dlkm /vendor_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm_dlkm /odm_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,noflush_merge,fsync_mode=nobarrier,reserve_root=134217,resgid=1065,checkpoint_merge,gc_merge,inlinecrypt wait,check,formattable,quota,latemount,resize,reservedsize=128m,checkpoint=fs,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,fsverity&lt;br /&gt;
 /dev/block/by-name/rescue /cache ext4 noatime,nosuid,nodev,noauto_da_alloc,discard wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect1 /mnt/vendor/protect_f ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect2 /mnt/vendor/protect_s ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvdata /mnt/vendor/nvdata ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvcfg /mnt/vendor/nvcfg ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/persist /mnt/vendor/persist ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /devices/platform/soc/11240000.mmc* auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata&lt;br /&gt;
 /devices/platform/usb_xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /devices/platform/soc/11201000.usb0/11200000.xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /dev/block/by-name/frp /persistent emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/nvram /nvram emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/proinfo /proinfo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk /bootloader emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk2 /bootloader2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/para /para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/misc /misc emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot /boot emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_vendor /vbmeta_vendor emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_system /vbmeta_system emmc defaults first_stage_mount,nofail,slotselect,avb=vbmeta&lt;br /&gt;
 /dev/block/by-name/logo /logo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/expdb /expdb emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/seccfg /seccfg emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee1 /tee1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee2 /tee2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp1 /scp1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp2 /scp2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_1 /sspm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_2 /sspm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_1 /dpm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_2 /dpm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_1 /mcupm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_2 /mcupm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1img /md1img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1dsp /md1dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1arm7 /md1arm7 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md3img /md3img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz1 /gz1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz2 /gz2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/spmfw /spmfw emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/audio_dsp /audio_dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/pi_img /pi_img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot_para /boot_para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/odmdtbo /odmdtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dtbo /dtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/otp /otp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/vbmeta /vbmeta emmc defaults defaults&lt;br /&gt;
这里面有很多无用分区，我们在 twrp 中操作不到，但是我也是第一次适配 MTK 设备，所以不“瞎说”误人子弟了，先把 bug 修好。&lt;br /&gt;
&lt;br /&gt;
像 xiaomi 这样常见的挂载错误，我自己一般都是尝试把/mnt/vendor 使用 vscode 全部删除，让我们尝试一下。并且要把这一行删除，这行在我看来是重复定义（？而且也没指定分区格式。&lt;br /&gt;
 /mnt/vendor/mi_ext /mi_ext none ro,bind wait,nofail&lt;br /&gt;
整理完之后是这样的&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 341 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;command line&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 2&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot; 2&lt;br /&gt;
 # 173 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 system /system erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system /system ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 vendor /vendor erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor /vendor ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 mi_ext /mi_ext erofs ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 mi_ext /mi_ext ext4 ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 overlay /product/overlay overlay ro,lowerdir=/mi_ext/product/overlay/:/product/overlay check,nofail&lt;br /&gt;
 overlay /product/app overlay ro,lowerdir=/mi_ext/product/app/:/product/app check,nofail&lt;br /&gt;
 overlay /product/priv-app overlay ro,lowerdir=/mi_ext/product/priv-app/:/product/priv-app check,nofail&lt;br /&gt;
 overlay /product/lib overlay ro,lowerdir=/mi_ext/product/lib/:/product/lib check,nofail&lt;br /&gt;
 overlay /product/lib64 overlay ro,lowerdir=/mi_ext/product/lib64/:/product/lib64 check,nofail&lt;br /&gt;
 overlay /product/bin overlay ro,lowerdir=/mi_ext/product/bin/:/product/bin check,nofail&lt;br /&gt;
 overlay /product/framework overlay ro,lowerdir=/mi_ext/product/framework/:/product/framework check,nofail&lt;br /&gt;
 overlay /product/media overlay ro,lowerdir=/mi_ext/product/media/:/product/media check,nofail&lt;br /&gt;
 overlay /product/opcust overlay ro,lowerdir=/mi_ext/product/opcust/:/product/opcust check,nofail&lt;br /&gt;
 overlay /product/data-app overlay ro,lowerdir=/mi_ext/product/data-app/:/product/data-app check,nofail&lt;br /&gt;
 overlay /product/etc/sysconfig overlay ro,lowerdir=/mi_ext/product/etc/sysconfig/:/product/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /product/etc/permissions overlay ro,lowerdir=/mi_ext/product/etc/permissions/:/product/etc/permissions check,nofail&lt;br /&gt;
 overlay /system/app overlay ro,lowerdir=/mi_ext/system/app/:/product/pangu/system/app/:/system/app check,nofail&lt;br /&gt;
 overlay /system/priv-app overlay ro,lowerdir=/mi_ext/system/priv-app/:/product/pangu/system/priv-app/:/system/priv-app check,nofail&lt;br /&gt;
 overlay /system/framework overlay ro,lowerdir=/product/pangu/system/framework/:/system/framework check,nofail&lt;br /&gt;
 overlay /system/etc/sysconfig overlay ro,lowerdir=/mi_ext/system/etc/sysconfig/:/system/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /system/etc/permissions overlay ro,lowerdir=/mi_ext/system/etc/permissions/:/product/pangu/system/etc/permissions/:/system/etc/permissions check,nofail&lt;br /&gt;
 system_ext /system_ext erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system_ext /system_ext ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 odm /odm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm /odm ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor_dlkm /vendor_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm_dlkm /odm_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,noflush_merge,fsync_mode=nobarrier,reserve_root=134217,resgid=1065,checkpoint_merge,gc_merge,inlinecrypt wait,check,formattable,quota,latemount,resize,reservedsize=128m,checkpoint=fs,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,fsverity&lt;br /&gt;
 /dev/block/by-name/rescue /cache ext4 noatime,nosuid,nodev,noauto_da_alloc,discard wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect1 /protect_f ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect2 /protect_s ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvdata /nvdata ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvcfg /nvcfg ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/persist /persist ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /devices/platform/soc/11240000.mmc* auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata&lt;br /&gt;
 /devices/platform/usb_xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /devices/platform/soc/11201000.usb0/11200000.xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /dev/block/by-name/frp /persistent emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/nvram /nvram emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/proinfo /proinfo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk /bootloader emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk2 /bootloader2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/para /para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/misc /misc emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot /boot emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_vendor /vbmeta_vendor emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_system /vbmeta_system emmc defaults first_stage_mount,nofail,slotselect,avb=vbmeta&lt;br /&gt;
 /dev/block/by-name/logo /logo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/expdb /expdb emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/seccfg /seccfg emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee1 /tee1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee2 /tee2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp1 /scp1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp2 /scp2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_1 /sspm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_2 /sspm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_1 /dpm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_2 /dpm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_1 /mcupm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_2 /mcupm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1img /md1img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1dsp /md1dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1arm7 /md1arm7 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md3img /md3img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz1 /gz1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz2 /gz2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/spmfw /spmfw emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/audio_dsp /audio_dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/pi_img /pi_img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot_para /boot_para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/odmdtbo /odmdtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dtbo /dtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/otp /otp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/vbmeta /vbmeta emmc defaults defaults&lt;br /&gt;
让我们编译试一下，值得注意的是，twrp 每次更改最好删除 out 重新编译，不要使用如make installclean等命令，可能会开机黑屏或更改不生效。&lt;br /&gt;
&lt;br /&gt;
经过一分钟，编译好了，刷入，开机，启动！可以看见挂载成功被修好。&lt;br /&gt;
&lt;br /&gt;
===== 修复屏幕显示 =====&lt;br /&gt;
可以看到我们现在屏幕的顶部的时间被摄像头挖孔挡住了。我们使用两个偏移 Flag 来修复它。&lt;br /&gt;
&lt;br /&gt;
在 BoardConfig.mk 中，加入以下 flag&lt;br /&gt;
 TW_Y_OFFSET := 106 #导航栏向上&lt;br /&gt;
 TW_H_OFFSET := -106 #界面整体向下&lt;br /&gt;
&lt;br /&gt;
===== 修复振动 =====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;仅供参考，研究半天发现只有解密功能正常才能修振动，不然会冻屏！！！&lt;br /&gt;
&lt;br /&gt;
不一定正确，也不一定普遍，仅供指路&amp;lt;/blockquote&amp;gt;老设备一般都是正常的，不需要额外处理，新设备使用 aidl hal 需要我们自己处理一下让 service 正常工作。&lt;br /&gt;
&lt;br /&gt;
挂载 vendor，使用 twrp 的文件管理，在 vendor/etc/vintf/manifest 找到含有 vibrator 字样的文件。打开之后检查是否类似这样的文段&lt;br /&gt;
 &amp;lt;manifest version=&amp;quot;1.0&amp;quot; type=&amp;quot;device&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;hal format=&amp;quot;aidl&amp;quot; override=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
         &amp;lt;name&amp;gt;android.hardware.vibrator&amp;lt;/name&amp;gt;&lt;br /&gt;
         &amp;lt;fqname&amp;gt;IVibrator/vibratorfeature&amp;lt;/fqname&amp;gt;&lt;br /&gt;
     &amp;lt;/hal&amp;gt;&lt;br /&gt;
 &amp;lt;/manifest&amp;gt;&lt;br /&gt;
那恭喜你，找对了，我的文件名是&lt;br /&gt;
&lt;br /&gt;
vendor.xiaomi.hardware.vibratorfeature.service.xml&lt;br /&gt;
&lt;br /&gt;
将它使用adb pull放到电脑上自己方便的位置备用。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /vendor/etc/vintf/manifest/vendor.xiaomi.hardware.vibratorfeature.service.xml .&lt;br /&gt;
 /vendor/etc/vintf/manifest/vendor.xiao...ipped. 0.2 MB/s (1718 bytes in 0.009s)&lt;br /&gt;
不看扩展名，到 vendor/bin/hw/找到同名的 service 同样利用adb pull放电脑备用。比如我的叫&lt;br /&gt;
&lt;br /&gt;
vendor.xiaomi.hardware.vibratorfeature.service&lt;br /&gt;
&lt;br /&gt;
然后到 vendor/etc/init/找到同名.rc 文件，拉到电脑上，在里面加一条。并在定义 service 的最下面加上seclabel u:r:recovery:s0可以被 recovery 使用。&lt;br /&gt;
 on boot&lt;br /&gt;
     start service被定义的名字&lt;br /&gt;
例如&lt;br /&gt;
 on post-fs-data&lt;br /&gt;
     chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/f0_save&lt;br /&gt;
     chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/osc_save&lt;br /&gt;
     chown system system /sys/bus/i2c/drivers/aw8697_haptic/3-005a/osc_save&lt;br /&gt;
     # 省略一万字&lt;br /&gt;
 &lt;br /&gt;
 on boot&lt;br /&gt;
     start vibratorfeature-hal-service&lt;br /&gt;
 &lt;br /&gt;
 service vibratorfeature-hal-service /vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&lt;br /&gt;
     class hal&lt;br /&gt;
     user system&lt;br /&gt;
     group system input&lt;br /&gt;
     onrestart restart vibratorfeature&lt;br /&gt;
     seclabel u:r:recovery:s0&lt;br /&gt;
此外这种新设备在内核里还有振动模块需要加载，请到/vendor/modules/1.1/中寻找，例如我这台设备是haptic.ko，用 adb pull 拉取到电脑上，然后&lt;br /&gt;
&lt;br /&gt;
* haptic.ko --&amp;gt; recovery/root/vendor/modules/1.1&lt;br /&gt;
&lt;br /&gt;
至此所有必要的资料就准备好了。可能开机后仍然不工作，需要抓取 log 补缺失的 library，当然这是后话了。&lt;br /&gt;
&lt;br /&gt;
开干！&lt;br /&gt;
&lt;br /&gt;
在 BoardConfig.mk 中加入以下 flag&lt;br /&gt;
 TW_SUPPORT_INPUT_AIDL_HAPTICS := true&lt;br /&gt;
将备用文件按照以下操作复制&lt;br /&gt;
&lt;br /&gt;
* vendor.xiaomi.hardware.vibratorfeature.service.xml --&amp;gt; recovery/root/vendor/etc/vintf/manifest&lt;br /&gt;
* vendor.xiaomi.hardware.vibratorfeature.service --&amp;gt; recovery/root/vendor/bin/hw&lt;br /&gt;
* vendor.xiaomi.hardware.vibratorfeature.service.rc --&amp;gt; recovery/root/vendor/etc/init&lt;br /&gt;
&lt;br /&gt;
之后编译，刷入，开机，喜提冻屏......&lt;br /&gt;
&lt;br /&gt;
问题不大，使用adb logcat抓取日志&lt;br /&gt;
 adb logcat &amp;gt; log.log&lt;br /&gt;
打开 log，搜索F linker、linker、library、beginning of crash这几个关键词，我搜索第一个就出来了。&lt;br /&gt;
 F linker  : CANNOT LINK EXECUTABLE &amp;quot;/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&amp;quot;: library &amp;quot;android.hardware.vibrator-V1-ndk_platform.so&amp;quot; not found: needed by main executable&lt;br /&gt;
这段报错的意思就是vendor.xiaomi.hardware.vibratorfeature.service找不到android.hardware.vibrator-V1-ndk_platform.so这个库，所以无法正常工作。&lt;br /&gt;
&lt;br /&gt;
打开 BoardConfig.mk 加入以下 flag&lt;br /&gt;
 # Library&lt;br /&gt;
 TARGET_RECOVERY_DEVICE_MODULES += \&lt;br /&gt;
     android.hardware.vibrator-V1-ndk_platform.vendor&lt;br /&gt;
 &lt;br /&gt;
 TW_RECOVERY_ADDITIONAL_RELINK_LIBRARY_FILES += \&lt;br /&gt;
     $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.vibrator-V1-ndk_platform.so&lt;br /&gt;
再次编译尝试&lt;br /&gt;
&lt;br /&gt;
开机之后依然冻屏，继续抓 log，查找&lt;br /&gt;
 F linker  : CANNOT LINK EXECUTABLE &amp;quot;/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&amp;quot;: library &amp;quot;vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so&amp;quot; not found: needed by main executable&lt;br /&gt;
vendor.hardware.vibratorfeature字样和我们之前导入的文件长得差不多，一般都是供应商专有文件，所以去设备提取，路径在 vendor/lib64 里，虽然设备冻屏了，但我们可以用adb pull直接拉取到电脑。就像这样。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb shell mount /vendor&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /vendor/lib64/vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so .&lt;br /&gt;
 /vendor/lib64/vendor.hardware.vibratorfeature.IVi...led, 0 skipped. 14.7 MB/s (33552 bytes in 0.002s&lt;br /&gt;
将这个文件按照以下提示操作&lt;br /&gt;
&lt;br /&gt;
* vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so --&amp;gt; recovery/root/vendor/lib64&lt;br /&gt;
&lt;br /&gt;
继续编译测试&lt;br /&gt;
&lt;br /&gt;
还是冻屏，继续抓 log&lt;br /&gt;
 F linker  : CANNOT LINK EXECUTABLE &amp;quot;/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&amp;quot;: library &amp;quot;libtinyalsa.so&amp;quot; not found: needed by main executable&lt;br /&gt;
这个 library twrp 的源码中应该没有，去设备拿一个 prebuilt 吧&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb shell mount /system_root&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /system_root/system/lib64/libtinyalsa.so .&lt;br /&gt;
 /system_root/system/lib64/libtinyalsa.so: 1 file ...led, 0 skipped. 13.6 MB/s (45032 bytes in 0.003s&lt;br /&gt;
将这个文件按照以下提示操作&lt;br /&gt;
&lt;br /&gt;
* libtinyalsa.so --&amp;gt; recovery/root/system/lib64&lt;br /&gt;
&lt;br /&gt;
编译测试&lt;br /&gt;
&lt;br /&gt;
我艹了，还是冻屏，这次搜那几个关键词都搜不到了，搜vibrator看看这鬼东西报什么&lt;br /&gt;
 E vendor.xiaomi.hardware.vibratorfeature.service: fail to load lib : /vendor/lib64/libaachaptics.so&lt;br /&gt;
这次都直接给路径了，直接拿。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb shell mount /vendor&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /vendor/lib64/libaachaptics.so .&lt;br /&gt;
 /vendor/lib64/libaachaptics.so: 1 file pulled, 0 skipped. 15.8 MB/s (56232 bytes in 0.003s)&lt;br /&gt;
将这个文件按照以下提示操作&lt;br /&gt;
&lt;br /&gt;
* libaachaptics.so --&amp;gt; recovery/root/vendor/lib64&lt;br /&gt;
&lt;br /&gt;
至此应该没什么问题了，但是有个 flag 貌似要操作 data 内的东西，未解密会导致冻屏，所以等修完解密后再来修振动。&lt;br /&gt;
&lt;br /&gt;
==== 修复 CPU 温度 ====&lt;br /&gt;
使用adb shell + grep命令在手机节点里搜索 type 关键词。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~  adb shell 'grep &amp;quot;cp_master&amp;quot; /sys/class/thermal/*/type'&lt;br /&gt;
 /sys/class/thermal/thermal_zone54/type:cp_master&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~  adb shell 'grep &amp;quot;cpu&amp;quot; /sys/class/thermal/*/type'&lt;br /&gt;
 /sys/class/thermal/thermal_zone1/type:cpu_little1&lt;br /&gt;
 /sys/class/thermal/thermal_zone10/type:cpu_bigbig1&lt;br /&gt;
 /sys/class/thermal/thermal_zone11/type:cpu_big6&lt;br /&gt;
 /sys/class/thermal/thermal_zone12/type:cpu_bigbig2&lt;br /&gt;
 /sys/class/thermal/thermal_zone2/type:cpu_little2&lt;br /&gt;
 /sys/class/thermal/thermal_zone3/type:cpu_little3&lt;br /&gt;
 /sys/class/thermal/thermal_zone4/type:cpu_little4&lt;br /&gt;
 /sys/class/thermal/thermal_zone5/type:cpu_big1&lt;br /&gt;
 /sys/class/thermal/thermal_zone6/type:cpu_big2&lt;br /&gt;
 /sys/class/thermal/thermal_zone7/type:cpu_big3&lt;br /&gt;
 /sys/class/thermal/thermal_zone8/type:cpu_big4&lt;br /&gt;
 /sys/class/thermal/thermal_zone9/type:cpu_big5&lt;br /&gt;
我这里选用cp_master节点来读取温度。我的节点路径为/sys/class/thermal/thermal_zone54在后面添加 temp 来读取温度，你可以使用cat来检测节点是否可以正常读取温度&lt;br /&gt;
 adb shell 'cat /sys/class/thermal/thermal_zone54/temp'&lt;br /&gt;
如果返回如&lt;br /&gt;
 28000&lt;br /&gt;
这种类似的数值，那多半是没有问题的。&lt;br /&gt;
&lt;br /&gt;
我们在 BoardConfig.mk 中加入&lt;br /&gt;
 TW_CUSTOM_CPU_TEMP_PATH := &amp;quot;/sys/class/thermal/thermal_zone54/temp&amp;quot;&lt;br /&gt;
至此 cpu 温度就修复好了。&lt;br /&gt;
&lt;br /&gt;
== 后序 ==&lt;br /&gt;
这是我玩 Android 两年内第一次写关于 Android 的文章，内容和措辞可能不是很准确，再加上开学焦虑，租房因租金和房源不顺利，写的很乱，请各位指正。&lt;br /&gt;
&lt;br /&gt;
此外有什么不懂得，多翻github，善用github搜索，多看看大佬们是怎么解决的。&lt;br /&gt;
&lt;br /&gt;
解密等有空补，先补作业。&lt;br /&gt;
&lt;br /&gt;
== 参考资料 ==&lt;br /&gt;
[https://source.android.com/docs/setup/create/new-device?hl=zh-cn Google - 添加新设备]&lt;br /&gt;
&lt;br /&gt;
[https://source.android.com/docs/core/ota/ab?hl=zh-cn Google - A/B（无缝）系统更新]&lt;br /&gt;
&lt;br /&gt;
[https://blog.lynnrin.moe/posts/ROM-bringup-guide-prebuilt/#boardconfigmk Lynnrin - 快速上手 Android Custom ROM 适配 - Prebuilt Vendor]&lt;br /&gt;
&lt;br /&gt;
[https://source.android.com/docs/core/architecture/vintf?hl=zh-cn Google - 供应商接口对象]&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=%E4%B8%BA%E6%96%B0%E8%AE%BE%E5%A4%87%E7%BC%96%E5%86%99Recovery_device_tree&amp;diff=556</id>
		<title>为新设备编写Recovery device tree</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=%E4%B8%BA%E6%96%B0%E8%AE%BE%E5%A4%87%E7%BC%96%E5%86%99Recovery_device_tree&amp;diff=556"/>
		<updated>2024-02-20T06:27:13Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​fixup&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= 为新设备编写 Recovery 的设备树 =&lt;br /&gt;
作者: Dark(xiaoleGun)&lt;br /&gt;
&lt;br /&gt;
时间: 2024.2.20&lt;br /&gt;
&lt;br /&gt;
协作者:&lt;br /&gt;
&lt;br /&gt;
== 一些自序 ==&lt;br /&gt;
这篇教程中可能有些不对的地方，请各位指正，我也刚接触 Android 设备测开发两年，而且只有在节假日的时候有空一个人瞎捣鼓，为了&amp;lt;s&amp;gt;薅 mjw 羊毛&amp;lt;/s&amp;gt;，故写这篇教程，而且我个人更推荐 Aosp Recovery 刷写第三方 ROM，TWRP 可能多多少少有些问题。Root 之类的不需要 TWRP 也可以，可以找到原机 boot 使用 Magisk 进行修补，也可以使用 KernelSU。另外我的语文功底不是很好，写不出辞藻，只能是北方地道的大白话，见谅哈 🤣///&lt;br /&gt;
&lt;br /&gt;
== 准备工作 ==&lt;br /&gt;
1.一颗勇敢的、不怕困难的强大心脏。&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;s&amp;gt;两颗心好勇敢 -- Falling in love&amp;lt;/s&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
2.电脑配置:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!硬件&lt;br /&gt;
!需求&lt;br /&gt;
|-&lt;br /&gt;
|CPU&lt;br /&gt;
|四核或更多&lt;br /&gt;
|-&lt;br /&gt;
|内存&lt;br /&gt;
|8G 或更多&lt;br /&gt;
|-&lt;br /&gt;
|硬盘&lt;br /&gt;
|至少 80G 空余空间&lt;br /&gt;
|-&lt;br /&gt;
|系统&lt;br /&gt;
|WSL 或实体 Linux，建议 Debian 系&lt;br /&gt;
|}&lt;br /&gt;
3.足够的空闲时间。&lt;br /&gt;
&lt;br /&gt;
4.Vscode 和 🤏Linux 知识储备&lt;br /&gt;
&lt;br /&gt;
5.一台完好无损的新设备。&lt;br /&gt;
&lt;br /&gt;
6.设备原厂的 boot/recovery/vendor_boot 镜像。(推荐 recovery 分区，因为里面包含一些启动必须的.rc(run command)，如果没有该分区，寻找包含官方 recovery 内容的分区。值得注意的是部分设备 recovery 合并到了 boot 中，或是存在于 vendor_boot）&lt;br /&gt;
&lt;br /&gt;
7.查看自己的设备出厂 Android 版本并确定用途，是用于官方 ROM 还是第三方类原生。出厂版本为 9 及以上的可以使用 twrp-11 及以上分支，9 以下使用 twrp-9 分支。&lt;br /&gt;
&lt;br /&gt;
== 配置环境 ==&lt;br /&gt;
&lt;br /&gt;
=== 安装依赖 ===&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt-get install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev liblz4-tool libncurses5 libncurses5-dev libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev xattr openjdk-11-jdk jq android-sdk-libsparse-utils python3 python2 repo&lt;br /&gt;
&lt;br /&gt;
必要时可以阅读[https://source.android.com/source/using-repo?hl=zh-cn Git 和 Repo]&lt;br /&gt;
&lt;br /&gt;
=== 配置 Git 和 Repo ===&lt;br /&gt;
安装完依赖后，在终端执行。&lt;br /&gt;
 git config --global user.name &amp;quot;your username&amp;quot;&lt;br /&gt;
 git config --global user.email &amp;quot;your email&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== 同步 TWRP 源码 ===&lt;br /&gt;
在自己方便的地方，建立一个目录。&lt;br /&gt;
 mkdir twrp&lt;br /&gt;
 cd twrp&lt;br /&gt;
根据自己在准备工作中确定的分支同步相应的源码。&lt;br /&gt;
&lt;br /&gt;
==== TWRP-9 ====&lt;br /&gt;
 repo init --depth=1 -u &amp;lt;nowiki&amp;gt;https://github.com/minimal-manifest-twrp/platform_manifest_twrp_omni.git&amp;lt;/nowiki&amp;gt; -b twrp-9.0&lt;br /&gt;
 repo sync&lt;br /&gt;
&lt;br /&gt;
==== TWRP-11 ====&lt;br /&gt;
 repo init --depth=1 -u &amp;lt;nowiki&amp;gt;https://github.com/minimal-manifest-twrp/platform_manifest_twrp_aosp.git&amp;lt;/nowiki&amp;gt; -b twrp-11&lt;br /&gt;
 repo sync&lt;br /&gt;
&lt;br /&gt;
==== TWRP-12.1 ====&lt;br /&gt;
 repo init --depth=1 -u &amp;lt;nowiki&amp;gt;https://github.com/minimal-manifest-twrp/platform_manifest_twrp_aosp.git&amp;lt;/nowiki&amp;gt; -b twrp-12.1&lt;br /&gt;
 repo sync&lt;br /&gt;
&lt;br /&gt;
== 编写设备树 ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;最基本的开机部分我通过 Redmi K50 做示例，并选取 TWRP-12.1 分支。&lt;br /&gt;
&lt;br /&gt;
解密部分会单独成一个章节并分为高通和联发科。&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 获取资料 ===&lt;br /&gt;
小米设备一般可以在[https://xiaomirom.com Xiaomirom]中的线刷包获取 boot/recovery/vendor_boot 镜像，其它设备请自行寻找。&lt;br /&gt;
&lt;br /&gt;
==== 安装工具和依赖 ====&lt;br /&gt;
将准备工作中准备的 boot/recovery/vendor_boot 镜像解包，可以用任何工具，我这里使用[https://github.com/cfig/Android_boot_image_editor Android_boot_image_editor]按照自述文件进行依赖安装操作：&lt;br /&gt;
&lt;br /&gt;
===== Mac(Intel) =====&lt;br /&gt;
 brew install lz4 xz dtc openjdk@17&lt;br /&gt;
 echo 'export PATH=&amp;quot;/usr/local/opt/openjdk@17/bin:$PATH&amp;quot;' &amp;gt;&amp;gt; ~/.zshrc&lt;br /&gt;
 source ~/.zshrc&lt;br /&gt;
&lt;br /&gt;
===== Linux: =====&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-17-jdk gcc g++ python3 python-is-python3 p7zip-full android-sdk-libsparse-utils erofs-utils&lt;br /&gt;
&lt;br /&gt;
===== Common: =====&lt;br /&gt;
 git clone &amp;lt;nowiki&amp;gt;https://github.com/cfig/Android_boot_image_editor&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 cd Android_boot_image_editor&lt;br /&gt;
&lt;br /&gt;
==== 解包 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;请注意&amp;quot;/&amp;quot;表示或的意思，请不要误以为是一个东西。&lt;br /&gt;
&lt;br /&gt;
如果不确定分区寻找的是否正确，请尝试将可以的分区进行解包，并查看其ramdisk内是否包含recovery字样的文件&amp;lt;/blockquote&amp;gt;将你准备好的boot/recovery/vendor_boot复制到该目录，你可以使用 GUI 或者 CLI。如:&lt;br /&gt;
 cp &amp;lt;出厂boot/recovery/vendor_boot的绝对路径&amp;gt; boot/recovery/vendor_boot.img&lt;br /&gt;
 ./gradlew unpack&lt;br /&gt;
我这里以 Redmi K50 为例&lt;br /&gt;
 10:12:13.188 [main] INFO  cfig.bootimg.v3.VendorBoot -&lt;br /&gt;
                         Unpack Summary of vendor_boot.img&lt;br /&gt;
 ┌───────────────────────────────────────┬──────────────────────────────────────┐&lt;br /&gt;
 │What                                   │Where                                 │&lt;br /&gt;
 └───────────────────────────────────────┴──────────────────────────────────────┘&lt;br /&gt;
 ┌───────────────────────────────────────┬──────────────────────────────────────┐&lt;br /&gt;
 │image info                             │build/unzip_boot/vendor_boot.json     │&lt;br /&gt;
 ├───────────────────────────────────────┼──────────────────────────────────────┤&lt;br /&gt;
 │ramdisk                                │build/unzip_boot/ramdisk.img.lz4      │&lt;br /&gt;
 │-- PLATFORM ramdisk[1/1]               │build/unzip_boot/ramdisk.1.lz4        │&lt;br /&gt;
 │------- extracted rootfs               │build/unzip_boot/root.1               │&lt;br /&gt;
 ├───────────────────────────────────────┼──────────────────────────────────────┤&lt;br /&gt;
 │dtb                                    │build/unzip_boot/dtb                  │&lt;br /&gt;
 ├───────────────────────────────────────┼──────────────────────────────────────┤&lt;br /&gt;
 │AVB info                               │build/unzip_boot/vendor_boot.avb.json │&lt;br /&gt;
 │\-- signing key                        │NONE                                  │&lt;br /&gt;
 └───────────────────────────────────────┴──────────────────────────────────────┘&lt;br /&gt;
 10:12:13.213 [main] WARN  cfig.packable.PackableLauncher - 'unpack' sequence completed&lt;br /&gt;
 &lt;br /&gt;
 BUILD SUCCESSFUL in 2s&lt;br /&gt;
解包成功后终端会打印出以上信息，其中包含vendor_boot目录结构，我们只需要ramdisk里的部分内容就好了。&lt;br /&gt;
 ls build/unzip_boot/root.1 # 请根据自己的分区和设备判断ramdisk的命名，一般都直接是ramdisk&lt;br /&gt;
不出意外的话会输出以下内容&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/dump/bootedit   master ?  ls build/unzip_boot/root.1&lt;br /&gt;
 acct                         oem&lt;br /&gt;
 apex                         plat_file_contexts&lt;br /&gt;
 bin                          plat_property_contexts&lt;br /&gt;
 bugreports                   postinstall&lt;br /&gt;
 config                       proc&lt;br /&gt;
 d                            product&lt;br /&gt;
 data                         product_file_contexts&lt;br /&gt;
 data_mirror                  product_property_contexts&lt;br /&gt;
 debug_ramdisk                prop.default&lt;br /&gt;
 default.prop                 res&lt;br /&gt;
 dev                          sdcard&lt;br /&gt;
 etc                          second_stage_resources&lt;br /&gt;
 first_stage_ramdisk          sepolicy&lt;br /&gt;
 init                         storage&lt;br /&gt;
 init.recovery.hardware.rc    sys&lt;br /&gt;
 init.recovery.mt6895.rc      system&lt;br /&gt;
 lib                          system_ext&lt;br /&gt;
 linkerconfig                 system_ext_file_contexts&lt;br /&gt;
 miui.factoryreset.fstab      system_ext_property_contexts&lt;br /&gt;
 miui.factoryreset.rc         tmp&lt;br /&gt;
 mnt                          vendor&lt;br /&gt;
 odm                          vendor_dlkm&lt;br /&gt;
 odm_dlkm                     vendor_file_contexts&lt;br /&gt;
 odm_file_contexts            vendor_property_contexts&lt;br /&gt;
 odm_property_contexts&lt;br /&gt;
如果包含 init.recovery*的字样，恭喜你成功找到了正确的分区。将这个目录复制到一个自己方便的地方。&lt;br /&gt;
&lt;br /&gt;
至此资料已经大致齐全了，解密的资料会在解密章节来讲解如何获取。&lt;br /&gt;
&lt;br /&gt;
=== 初始化目录结构 ===&lt;br /&gt;
在 twrp 源码根目录输入&lt;br /&gt;
 mkdir -p device/vendor/codename&lt;br /&gt;
 mkdir -p device/vendor/codename/recovery/root&lt;br /&gt;
 cd device/vendor/codename&lt;br /&gt;
vendor指的是供应商，如 xiaomi、oneplus、huawei、vivo、realme。&lt;br /&gt;
&lt;br /&gt;
codename指的是设备代号，小米设备可以在[https://xiaomirom.com Xiaomirom]查询，其它设备自行查询亦或是在开发者选项勾选 USB 调试通过 adb 尝试获取。&lt;br /&gt;
 adb shell getprop ro.product.manufacturer # 供应商&lt;br /&gt;
 adb shell getprop ro.product.device # 设备代号&lt;br /&gt;
我的 Redmi K50 会打印以下信息&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/dump/bootedit   master ?  adb shell getprop ro.product.manufacturer&lt;br /&gt;
 Xiaomi # 无论打印出来的内容是大写还是小写，在目录结构中我们都采用小写&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/dump/bootedit   master ?  adb shell getprop ro.product.device&lt;br /&gt;
 rubens&lt;br /&gt;
我的 IQOO NEO5 Lite 会打印以下信息&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  adb shell getprop ro.product.manufacturer&lt;br /&gt;
 vivo&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  adb shell getprop ro.product.device&lt;br /&gt;
 PD2118&lt;br /&gt;
一般只要不是山寨机，小作坊出来的机子，用这两条命令应该是可以正确获取的。&lt;br /&gt;
&lt;br /&gt;
=== 初始化构建时必要的文件 ===&lt;br /&gt;
无论是 AOSP device tree 亦或是 TWRP device tree 都基本类似于以下结构。&lt;br /&gt;
 /&lt;br /&gt;
 ├── prebuilt           (存放kernel、dtb等预编译文件) # AOSP device tree若使用build kernel则没有该目录&lt;br /&gt;
 ├── recovery/root      (存放一些.rc和解密blobs) # 一般用于Recovery device tree&lt;br /&gt;
 ├── Android.mk         (Android构建系统首先会检查每个目录的Android.mk，里面包含一些判断，由它包括其所在目录中所有Makefile)&lt;br /&gt;
 ├── AndroidProducts.mk (声明产品的Makefile和lunch时可用的构建类型)&lt;br /&gt;
 ├── BoardConfig.mk     (板载配置文件，定义了主板必要的Flag)&lt;br /&gt;
 ├── device.mk          (声明设备所需的文件和模块)&lt;br /&gt;
 └── &amp;lt;ROM&amp;gt;_codename.mk  (声明产品特定信息，例如名称、品牌和型号，引用device.mk等) # ROM就比如lineage、arrow等，编译twrp就直接写twrp，twrp-9分支要写onmi&lt;br /&gt;
我们把这样的结构称为骨架树(skeleton tree)。&lt;br /&gt;
&lt;br /&gt;
接下来我们按照以上结构为自己的设备写一份 Recovery device tree。&lt;br /&gt;
&lt;br /&gt;
在终端使用touch命令创建必要的文件。&lt;br /&gt;
 touch Android.mk AndroidProducts.mk BoardConfig.mk device.mk twrp_rubens.mk&lt;br /&gt;
 ls .&lt;br /&gt;
不出意外的话会打印出以下信息&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  touch Android.mk AndroidProducts.mk BoardConfig.mk device.mk twrp_rubens.mk&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  ls .&lt;br /&gt;
 Android.mk         BoardConfig.mk     prebuilt           twrp_rubens.mk&lt;br /&gt;
 AndroidProducts.mk device.mk          recovery&lt;br /&gt;
可以下一步了~&lt;br /&gt;
&lt;br /&gt;
==== 初始 Android.mk 文件 ====&lt;br /&gt;
打开 Vscode 并打开设备树目录，你足够强也可以使用 nano、vim 编辑。&lt;br /&gt;
&lt;br /&gt;
选中 Android.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 LOCAL_PATH := $(call my-dir)&lt;br /&gt;
 &lt;br /&gt;
 ifeq ($(TARGET_DEVICE),codename)&lt;br /&gt;
 include $(call all-subdir-makefiles,$(LOCAL_PATH))&lt;br /&gt;
 endif&lt;br /&gt;
&lt;br /&gt;
* codename是需要你修改的部分&lt;br /&gt;
&lt;br /&gt;
我修改后是这样的&lt;br /&gt;
 LOCAL_PATH := $(call my-dir)&lt;br /&gt;
 &lt;br /&gt;
 ifeq ($(TARGET_DEVICE),rubens)&lt;br /&gt;
 include $(call all-subdir-makefiles,$(LOCAL_PATH))&lt;br /&gt;
 endif&lt;br /&gt;
&lt;br /&gt;
==== 初始 AndroidProducts.mk 文件 ====&lt;br /&gt;
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 PRODUCT_MAKEFILES := \&lt;br /&gt;
     $(LOCAL_DIR)/&amp;lt;ROM&amp;gt;_&amp;lt;codename&amp;gt;.mk&lt;br /&gt;
 &lt;br /&gt;
 COMMON_LUNCH_CHOICES := \&lt;br /&gt;
     &amp;lt;ROM&amp;gt;_&amp;lt;codename&amp;gt;-eng&lt;br /&gt;
我修改后是这样的&lt;br /&gt;
 PRODUCT_MAKEFILES := \&lt;br /&gt;
     $(LOCAL_DIR)/twrp_rubens.mk&lt;br /&gt;
 &lt;br /&gt;
 COMMON_LUNCH_CHOICES := \&lt;br /&gt;
     twrp_rubens-eng&lt;br /&gt;
&lt;br /&gt;
==== 初始 BoardConfig.mk 文件 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;将之前准备的ramdisk文件夹用新窗口打开 1.找到目录下的 prop.default 或含 prop 字样的文件。以下注释类似 ro.*.*的就是从 prop 中获取的 2.解包 boot/recovery/vendor_boot 的 json&lt;br /&gt;
&lt;br /&gt;
例如 build/unzip_boot/boot.json&amp;lt;/blockquote&amp;gt;选中 BoardConfig.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 DEVICE_PATH := device/vendor/codename&lt;br /&gt;
 &lt;br /&gt;
 # Architecture&lt;br /&gt;
 TARGET_ARCH := arm64 # ro.bionic.arch&lt;br /&gt;
 TARGET_ARCH_VARIANT := armv8-a # 64位默认变体&lt;br /&gt;
 TARGET_CPU_ABI := arm64-v8a # ro.vendor.product.cpu.abilist64 (至少在小米设备上没有找到ro.product.cpu.abilist)&lt;br /&gt;
 TARGET_CPU_ABI2 := # 64位留空&lt;br /&gt;
 TARGET_CPU_VARIANT := generic # 默认一般都是通用&lt;br /&gt;
 TARGET_CPU_VARIANT_RUNTIME := cortex-a55 # ro.bionic.cpu_variant&lt;br /&gt;
 &lt;br /&gt;
 TARGET_2ND_ARCH := arm # ro.bionic.2nd_arch&lt;br /&gt;
 TARGET_2ND_ARCH_VARIANT := $(TARGET_ARCH_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_ABI := armeabi-v7a # ro.vendor.product.cpu.abilist32第一个&lt;br /&gt;
 TARGET_2ND_CPU_ABI2 := armeabi # ro.vendor.product.cpu.abilist32第二个&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT_RUNTIME := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 &lt;br /&gt;
 # Assertation&lt;br /&gt;
 TARGET_OTA_ASSERT_DEVICE := rubens # codename&lt;br /&gt;
 &lt;br /&gt;
 # Bootloader&lt;br /&gt;
 TARGET_BOOTLOADER_BOARD_NAME := rubens # ro.product.board&lt;br /&gt;
 TARGET_NO_BOOTLOADER := true&lt;br /&gt;
 TARGET_USES_UEFI := true&lt;br /&gt;
 &lt;br /&gt;
 # Build Rule&lt;br /&gt;
 ALLOW_MISSING_DEPENDENCIES := true # 为了recovery不健全的依赖&lt;br /&gt;
 &lt;br /&gt;
 # Kernel - 注释会说明在boot/recovery/vendor_boot.json中对应的变量&lt;br /&gt;
 BOARD_BOOT_HEADER_VERSION := 4 # headerVersion&lt;br /&gt;
 BOARD_KERNEL_BASE := 0x3fff8000 # (kernelLoadAddr - 32KB) qcom设备base为0，且没有偏移(offset)&lt;br /&gt;
 BOARD_KERNEL_CMDLINE := bootopt=64S3,32N2,64N2 # cmdline&lt;br /&gt;
 BOARD_KERNEL_PAGESIZE := 4096 # pageSize&lt;br /&gt;
 BOARD_RAMDISK_OFFSET := 0x26f08000 # (ramdisk,loadAddr - BOARD_KERNEL_BASE)&lt;br /&gt;
 BOARD_KERNEL_TAGS_OFFSET := 0x07c88000 # (tagsLoadAddr - BOARD_KERNEL_BASE)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --ramdisk_offset $(BOARD_RAMDISK_OFFSET)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --tags_offset $(BOARD_KERNEL_TAGS_OFFSET)&lt;br /&gt;
 &lt;br /&gt;
 # Kernel - prebuilt&lt;br /&gt;
 TARGET_PREBUILT_KERNEL := $(DEVICE_PATH)/prebuilt/kernel # 预编译内核相对于android源码根目录的相对路径，vendor_boot机型不需要&lt;br /&gt;
 TARGET_PREBUILT_DTB := $(DEVICE_PATH)/prebuilt/dtb.img # 同上&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --dtb $(TARGET_PREBUILT_DTB)&lt;br /&gt;
 &lt;br /&gt;
 # Partitions&lt;br /&gt;
 BOARD_FLASH_BLOCK_SIZE := 262144 # (BOARD_KERNEL_PAGESIZE * 64)&lt;br /&gt;
 BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864 # boot/recovery/vendor_boot镜像的字节大小需原厂或手机完整提取出来的，不定义会报错&lt;br /&gt;
 BOARD_RECOVERYIMAGE_PARTITION_SIZE := 67108864 # 同上&lt;br /&gt;
 BOARD_VENDOR_ROOTIMAGE_PARTITION_SIZE := 67108864 # 同上&lt;br /&gt;
 BOARD_SYSTEMIMAGE_PARTITION_TYPE := ext4 # 分区类型，查看ramdisk中fstab定义的类型&lt;br /&gt;
 BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 TARGET_COPY_OUT_VENDOR := vendor # 定义vendor目录，例如copy专有blobs要用&lt;br /&gt;
 BOARD_SUPER_PARTITION_SIZE := 9126805504 # 可以通过blockdev --getsize64 /dev/block/bootdevice/by-name/super获取，需root，如果无法root可以直接使用这个值，不影响twrp启动，可以后续修正&lt;br /&gt;
 BOARD_SUPER_PARTITION_GROUPS := xiaomi_dynamic_partitions # xiaomi根据你获取资料的vendor替换，是一个动态分区组&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product system_ext odm vendor_dlkm odm_dlkm # 根据fstab内的定义，一般flag包含logical都属于动态分区组的一部分&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_SIZE := 9122611200 # (BOARD_SUPER_PARTITION_SIZE - 4MB)&lt;br /&gt;
 &lt;br /&gt;
 # Platform&lt;br /&gt;
 TARGET_BOARD_PLATFORM := mt6895 # ro.board.platform&lt;br /&gt;
 &lt;br /&gt;
 # Recovery - 基本通用的不影响启动&lt;br /&gt;
 BOARD_HAS_LARGE_FILESYSTEM := true&lt;br /&gt;
 TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888&lt;br /&gt;
 TARGET_USERIMAGES_USE_EXT4 := true&lt;br /&gt;
 TARGET_USERIMAGES_USE_F2FS := true&lt;br /&gt;
 &lt;br /&gt;
 # Treble&lt;br /&gt;
 BOARD_VNDK_VERSION := current # 声明VNDK版本&lt;br /&gt;
 &lt;br /&gt;
 # Vendor_boot recovery ramdisk&lt;br /&gt;
 BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true # 将recovery文件复制到vendor_boot&lt;br /&gt;
 &lt;br /&gt;
 # Boot recovery ramdisk&lt;br /&gt;
 #BOARD_USES_RECOVERY_AS_BOOT := true recovery ramdisk合并在boot中启用&lt;br /&gt;
 &lt;br /&gt;
 # Verified Boot&lt;br /&gt;
 BOARD_AVB_ENABLE := true&lt;br /&gt;
 BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flags 3&lt;br /&gt;
 &lt;br /&gt;
 # TWRP Configurations&lt;br /&gt;
 TW_DEFAULT_LANGUAGE := zh_CN # 默认为中文&lt;br /&gt;
 TW_EXTRA_LANGUAGES := true # 额外的语言&lt;br /&gt;
 TW_THEME := portrait_hdpi # 主题&lt;br /&gt;
 TW_INCLUDE_FASTBOOTD := true # 包括fastbootd，为动态分区&lt;br /&gt;
 &lt;br /&gt;
 # 其它flag还有很多，可以在https://xdaforums.com/t/twrp-flags-for-boardconfig-mk.3333970 查找，&lt;br /&gt;
 # 这篇文章也很老了，但我并不推荐twrp，所以flag我也不是很了解，多翻翻github:)&lt;br /&gt;
 &lt;br /&gt;
 # Debug&lt;br /&gt;
 TARGET_USES_LOGD := true # 调试flag&lt;br /&gt;
 TWRP_INCLUDE_LOGCAT := true&lt;br /&gt;
无注释版&lt;br /&gt;
 DEVICE_PATH := device/vendor/codename&lt;br /&gt;
 &lt;br /&gt;
 # Architecture&lt;br /&gt;
 TARGET_ARCH := arm64&lt;br /&gt;
 TARGET_ARCH_VARIANT := armv8-a&lt;br /&gt;
 TARGET_CPU_ABI := arm64-v8a&lt;br /&gt;
 TARGET_CPU_ABI2 :=&lt;br /&gt;
 TARGET_CPU_VARIANT := generic&lt;br /&gt;
 TARGET_CPU_VARIANT_RUNTIME := cortex-a55&lt;br /&gt;
 &lt;br /&gt;
 TARGET_2ND_ARCH := arm&lt;br /&gt;
 TARGET_2ND_ARCH_VARIANT := $(TARGET_ARCH_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_ABI := armeabi-v7a&lt;br /&gt;
 TARGET_2ND_CPU_ABI2 := armeabi&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT_RUNTIME := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 &lt;br /&gt;
 # Assertation&lt;br /&gt;
 TARGET_OTA_ASSERT_DEVICE := rubens&lt;br /&gt;
 &lt;br /&gt;
 # Bootloader&lt;br /&gt;
 TARGET_BOOTLOADER_BOARD_NAME := rubens&lt;br /&gt;
 TARGET_NO_BOOTLOADER := true&lt;br /&gt;
 TARGET_USES_UEFI := true&lt;br /&gt;
 &lt;br /&gt;
 # Build Rule&lt;br /&gt;
 ALLOW_MISSING_DEPENDENCIES := true&lt;br /&gt;
 &lt;br /&gt;
 # Kernel&lt;br /&gt;
 BOARD_BOOT_HEADER_VERSION := 4&lt;br /&gt;
 BOARD_KERNEL_BASE := 0x3fff8000&lt;br /&gt;
 BOARD_KERNEL_CMDLINE := bootopt=64S3,32N2,64N2&lt;br /&gt;
 BOARD_KERNEL_PAGESIZE := 4096&lt;br /&gt;
 BOARD_RAMDISK_OFFSET := 0x26f08000&lt;br /&gt;
 BOARD_KERNEL_TAGS_OFFSET := 0x07c88000&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --ramdisk_offset $(BOARD_RAMDISK_OFFSET)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --tags_offset $(BOARD_KERNEL_TAGS_OFFSET)&lt;br /&gt;
 BOARD_KERNEL_IMAGE_NAME := Image&lt;br /&gt;
 &lt;br /&gt;
 # Kernel - prebuilt&lt;br /&gt;
 TARGET_PREBUILT_DTB := $(DEVICE_PATH)/prebuilt/dtb.img&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --dtb $(TARGET_PREBUILT_DTB)&lt;br /&gt;
 &lt;br /&gt;
 # Partitions&lt;br /&gt;
 BOARD_FLASH_BLOCK_SIZE := 262144&lt;br /&gt;
 BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864&lt;br /&gt;
 BOARD_RECOVERYIMAGE_PARTITION_SIZE := 67108864&lt;br /&gt;
 BOARD_VENDOR_ROOTIMAGE_PARTITION_SIZE := 67108864&lt;br /&gt;
 BOARD_SYSTEMIMAGE_PARTITION_TYPE := ext4&lt;br /&gt;
 BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 TARGET_COPY_OUT_VENDOR := vendor&lt;br /&gt;
 BOARD_SUPER_PARTITION_SIZE := 9126805504&lt;br /&gt;
 BOARD_SUPER_PARTITION_GROUPS := xiaomi_dynamic_partitions&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product system_ext odm vendor_dlkm odm_dlkm&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_SIZE := 9122611200&lt;br /&gt;
 &lt;br /&gt;
 # Platform&lt;br /&gt;
 TARGET_BOARD_PLATFORM := mt6895&lt;br /&gt;
 &lt;br /&gt;
 # Recovery&lt;br /&gt;
 BOARD_HAS_LARGE_FILESYSTEM := true&lt;br /&gt;
 TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888&lt;br /&gt;
 TARGET_USERIMAGES_USE_EXT4 := true&lt;br /&gt;
 TARGET_USERIMAGES_USE_F2FS := true&lt;br /&gt;
 &lt;br /&gt;
 # Treble&lt;br /&gt;
 BOARD_VNDK_VERSION := current&lt;br /&gt;
 &lt;br /&gt;
 # Vendor_boot recovery ramdisk&lt;br /&gt;
 BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true&lt;br /&gt;
 &lt;br /&gt;
 # Boot recovery ramdisk&lt;br /&gt;
 #BOARD_USES_RECOVERY_AS_BOOT := true&lt;br /&gt;
 &lt;br /&gt;
 # Verified Boot&lt;br /&gt;
 BOARD_AVB_ENABLE := true&lt;br /&gt;
 BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flags 3&lt;br /&gt;
 &lt;br /&gt;
 # TWRP Configurations&lt;br /&gt;
 TW_DEFAULT_LANGUAGE := zh_CN&lt;br /&gt;
 TW_EXTRA_LANGUAGES := true&lt;br /&gt;
 TW_THEME := portrait_hdpi&lt;br /&gt;
 TW_INCLUDE_FASTBOOTD := true&lt;br /&gt;
 &lt;br /&gt;
 # Debug&lt;br /&gt;
 TARGET_USES_LOGD := true&lt;br /&gt;
 TWRP_INCLUDE_LOGCAT := true&lt;br /&gt;
这块写了好久我也不确定对不对，请各位指正，尤其是 Kernel 部分。&lt;br /&gt;
&lt;br /&gt;
==== 初始 device.mk 文件 ====&lt;br /&gt;
&lt;br /&gt;
* 准备好 prop.default&lt;br /&gt;
&lt;br /&gt;
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 DEVICE_PATH := device/xiaomi/rubens&lt;br /&gt;
 &lt;br /&gt;
 # API&lt;br /&gt;
 PRODUCT_SHIPPING_API_LEVEL := 31 # ro.board.first_api_level&lt;br /&gt;
 &lt;br /&gt;
 # A/B&lt;br /&gt;
 AB_OTA_UPDATER := true # 启用A/B无缝更新&lt;br /&gt;
 AB_OTA_PARTITIONS += \ # 定义A/B分区，参考fstab&lt;br /&gt;
     boot \&lt;br /&gt;
     dtbo \&lt;br /&gt;
     system \&lt;br /&gt;
     product \&lt;br /&gt;
     vendor \&lt;br /&gt;
     odm \&lt;br /&gt;
     odm_dlkm \&lt;br /&gt;
     vbmeta \&lt;br /&gt;
     vendor_boot \&lt;br /&gt;
     vendor_dlkm \&lt;br /&gt;
     vbmeta_system \&lt;br /&gt;
     vbmeta_vendor&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PACKAGES += \&lt;br /&gt;
     update_engine \&lt;br /&gt;
     update_engine_sideload \&lt;br /&gt;
     update_verifier \&lt;br /&gt;
     checkpoint_gc&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_system=true \&lt;br /&gt;
     POSTINSTALL_PATH_system=system/bin/mtk_plpath_utils \&lt;br /&gt;
     FILESYSTEM_TYPE_system=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_system=true&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_vendor=true \&lt;br /&gt;
     POSTINSTALL_PATH_vendor=bin/checkpoint_gc \&lt;br /&gt;
     FILESYSTEM_TYPE_vendor=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_vendor=true&lt;br /&gt;
 &lt;br /&gt;
 # Dynamic&lt;br /&gt;
 PRODUCT_USE_DYNAMIC_PARTITIONS := true # 动态分区&lt;br /&gt;
 &lt;br /&gt;
 # Soong namespaces&lt;br /&gt;
 PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH) # 命名空间&lt;br /&gt;
&lt;br /&gt;
* A/B 无缝更新部分高通和联发科不一样，联发科设备可以照抄，注意 system/bin/mtk_plpath_utils 就好。高通参考[https://github.com/sekaiacg/android_device_xiaomi_venus_TWRP/tree/android-13 venus twrp tree]，并且高通的[https://git.codelinaro.org/clo/la/platform/hardware/qcom/bootctrl bootctrl]和[https://git.codelinaro.org/clo/la/platform/vendor/qcom-opensource/recovery-ext gpt-utils]可以从 [[CLO]] 拿。&lt;br /&gt;
&lt;br /&gt;
无注释版&lt;br /&gt;
 PRODUCT_SHIPPING_API_LEVEL := 31&lt;br /&gt;
 &lt;br /&gt;
 # A/B&lt;br /&gt;
 AB_OTA_UPDATER := true&lt;br /&gt;
 AB_OTA_PARTITIONS += \&lt;br /&gt;
     boot \&lt;br /&gt;
     dtbo \&lt;br /&gt;
     system \&lt;br /&gt;
     product \&lt;br /&gt;
     vendor \&lt;br /&gt;
     odm \&lt;br /&gt;
     odm_dlkm \&lt;br /&gt;
     vbmeta \&lt;br /&gt;
     vendor_boot \&lt;br /&gt;
     vendor_dlkm \&lt;br /&gt;
     vbmeta_system \&lt;br /&gt;
     vbmeta_vendor&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PACKAGES += \&lt;br /&gt;
     update_engine \&lt;br /&gt;
     update_engine_sideload \&lt;br /&gt;
     update_verifier \&lt;br /&gt;
     checkpoint_gc&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_system=true \&lt;br /&gt;
     POSTINSTALL_PATH_system=system/bin/mtk_plpath_utils \&lt;br /&gt;
     FILESYSTEM_TYPE_system=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_system=true&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_vendor=true \&lt;br /&gt;
     POSTINSTALL_PATH_vendor=bin/checkpoint_gc \&lt;br /&gt;
     FILESYSTEM_TYPE_vendor=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_vendor=true&lt;br /&gt;
 &lt;br /&gt;
 # Dynamic&lt;br /&gt;
 PRODUCT_USE_DYNAMIC_PARTITIONS := true&lt;br /&gt;
 &lt;br /&gt;
 # Soong namespaces&lt;br /&gt;
 PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH)&lt;br /&gt;
&lt;br /&gt;
==== 初始 twrp_rubens.mk 文件 ====&lt;br /&gt;
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 # Inherit from common AOSP config&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk) # vab加载到vendor boot里使用&lt;br /&gt;
 &lt;br /&gt;
 # Inherit from TWRP product configuration&lt;br /&gt;
 $(call inherit-product, vendor/twrp/config/common.mk) # twrp-9分支改为onmi&lt;br /&gt;
 &lt;br /&gt;
 # Device specific configs&lt;br /&gt;
 $(call inherit-product, device/xiaomi/rubens/device.mk)&lt;br /&gt;
 &lt;br /&gt;
 # Device identifier&lt;br /&gt;
 PRODUCT_DEVICE := rubens # 设备型号&lt;br /&gt;
 PRODUCT_NAME := twrp_rubens # 设备名称&lt;br /&gt;
 PRODUCT_BRAND := Redmi # 自定义品牌，如果有&lt;br /&gt;
 PRODUCT_MODEL := 22041211AC # 产品最终用户可见名称&lt;br /&gt;
 PRODUCT_MANUFACTURER := Xiaomi # 制造商&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true # 对twrp启动vendor_boot支持&lt;br /&gt;
无注释版&lt;br /&gt;
 # Inherit from common AOSP config&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk) # vab加载到vendor boot里使用&lt;br /&gt;
 &lt;br /&gt;
 # Inherit from TWRP product configuration&lt;br /&gt;
 $(call inherit-product, vendor/twrp/config/common.mk)&lt;br /&gt;
 &lt;br /&gt;
 # Device specific configs&lt;br /&gt;
 $(call inherit-product, device/xiaomi/rubens/device.mk)&lt;br /&gt;
 &lt;br /&gt;
 # Device identifier&lt;br /&gt;
 PRODUCT_DEVICE := rubens&lt;br /&gt;
 PRODUCT_NAME := twrp_rubens&lt;br /&gt;
 PRODUCT_BRAND := Redmi&lt;br /&gt;
 PRODUCT_MODEL := 22041211AC&lt;br /&gt;
 PRODUCT_MANUFACTURER := Xiaomi&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true&lt;br /&gt;
&lt;br /&gt;
==== 初始 recovery 目录 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;拿出我们好久之前准备的 ramdisk 叭&amp;lt;/blockquote&amp;gt;通过tree命令我们可以查看 ramdisk 的树状图，可以很清晰的查看包含的文件&lt;br /&gt;
 ├── acct&lt;br /&gt;
 ├── apex&lt;br /&gt;
 ├── bin -&amp;gt; /system/bin&lt;br /&gt;
 ├── bugreports -&amp;gt; /data/user_de/0/com.android.shell/files/bugreports&lt;br /&gt;
 ├── config&lt;br /&gt;
 ├── d -&amp;gt; /sys/kernel/debug&lt;br /&gt;
 ├── data&lt;br /&gt;
 ├── data_mirror&lt;br /&gt;
 ├── debug_ramdisk&lt;br /&gt;
 ├── default.prop -&amp;gt; prop.default&lt;br /&gt;
 ├── dev&lt;br /&gt;
 ├── etc -&amp;gt; /system/etc&lt;br /&gt;
 ├── first_stage_ramdisk&lt;br /&gt;
 │   ├── fstab.emmc&lt;br /&gt;
 │   ├── fstab.mt6895&lt;br /&gt;
 │   └── system&lt;br /&gt;
 │       ├── bin&lt;br /&gt;
 │       │   ├── e2fsck&lt;br /&gt;
 │       │   ├── linker64&lt;br /&gt;
 │       │   ├── linker_asan64 -&amp;gt; linker64&lt;br /&gt;
 │       │   └── snapuserd&lt;br /&gt;
 │       └── lib64&lt;br /&gt;
 │           ├── ld-android.so&lt;br /&gt;
 │           ├── libbase.so&lt;br /&gt;
 │           ├── libc++.so&lt;br /&gt;
 │           ├── libc.so&lt;br /&gt;
 │           ├── libdl.so&lt;br /&gt;
 │           ├── libext2_blkid.so&lt;br /&gt;
 │           ├── libext2_com_err.so&lt;br /&gt;
 │           ├── libext2_e2p.so&lt;br /&gt;
 │           ├── libext2_quota.so&lt;br /&gt;
 │           ├── libext2_uuid.so&lt;br /&gt;
 │           ├── libext2fs.so&lt;br /&gt;
 │           ├── liblog.so&lt;br /&gt;
 │           ├── libm.so&lt;br /&gt;
 │           ├── libsparse.so&lt;br /&gt;
 │           └── libz.so&lt;br /&gt;
 ├── init -&amp;gt; /system/bin/init&lt;br /&gt;
 ├── init.recovery.hardware.rc&lt;br /&gt;
 ├── init.recovery.mt6895.rc&lt;br /&gt;
 └── 等等等等...省略大概1000个文件吧&lt;br /&gt;
&amp;lt;blockquote&amp;gt;因为避免教程时效性，我们尽可能选取 prebuilt 的办法，如 boot 和 mtk_plpath_utils 都采用预编译。&amp;lt;/blockquote&amp;gt;里面有很多文件是没用的，整理一下，对我们有用的只有这些&lt;br /&gt;
 .&lt;br /&gt;
 ├── first_stage_ramdisk&lt;br /&gt;
 │   ├── fstab.emmc&lt;br /&gt;
 │   └── fstab.mt6895&lt;br /&gt;
 ├── init.recovery.mt6895.rc&lt;br /&gt;
 ├── lib&lt;br /&gt;
 │   └── modules&lt;br /&gt;
 │       ├── 8250_mtk.ko&lt;br /&gt;
 │       ├── adapter_class.ko&lt;br /&gt;
 │       ├── adsp.ko&lt;br /&gt;
 │       ├── aee_aed.ko&lt;br /&gt;
 │       ├── aee_hangdet.ko&lt;br /&gt;
 │       ├── aee_rs.ko&lt;br /&gt;
 │       ├── blocktag.ko&lt;br /&gt;
 │       ├── bootprof.ko&lt;br /&gt;
 │       ├── bq28z610.ko&lt;br /&gt;
 │       ├── cache-parity.ko&lt;br /&gt;
 │       ├── cfg80211.ko&lt;br /&gt;
 │       ├── charger_class.ko&lt;br /&gt;
 │       └── 省略一百多个模块，这个目录里的东西全要&lt;br /&gt;
 └── system&lt;br /&gt;
     ├── bin&lt;br /&gt;
     │   └── mtk_plpath_utils&lt;br /&gt;
     ├── etc&lt;br /&gt;
     │   ├── init&lt;br /&gt;
     │   │   │── mtk-plpath-utils.rc&lt;br /&gt;
     │   │   └──hw&lt;br /&gt;
     │   │      └──init.rc&lt;br /&gt;
     │   ├── recovery.fstab&lt;br /&gt;
     │   ├── security&lt;br /&gt;
     │   │   └── otacerts.zip&lt;br /&gt;
     │   └── ueventd.rc&lt;br /&gt;
     └── lib64&lt;br /&gt;
         └── hw&lt;br /&gt;
             └── android.hardware.boot@1.0-impl-1.2-mtkimpl.so&lt;br /&gt;
将它们按照以下操作复制&lt;br /&gt;
&lt;br /&gt;
* first_stage_ramdisk --&amp;gt; recovery/root/first_stage_ramdisk&lt;br /&gt;
* init.recovery.mt6895.rc --&amp;gt; recovery/root/init.recovery.mt6895.rc&lt;br /&gt;
* lib --&amp;gt; recovery/root/lib&lt;br /&gt;
* system --&amp;gt; recovery/root/system (security 和 hw 文件夹里的内容作为备用，不要复制进去) 得到以下目录结构&lt;br /&gt;
&lt;br /&gt;
 .&lt;br /&gt;
 ├── Android.mk&lt;br /&gt;
 ├── AndroidProducts.mk&lt;br /&gt;
 ├── BoardConfig.mk&lt;br /&gt;
 ├── device.mk&lt;br /&gt;
 ├── prebuilt&lt;br /&gt;
 ├── recovery&lt;br /&gt;
 │   └── root&lt;br /&gt;
 │       ├── first_stage_ramdisk&lt;br /&gt;
 │       │   ├── fstab.emmc&lt;br /&gt;
 │       │   └── fstab.mt6895&lt;br /&gt;
 │       ├── init.recovery.mt6895.rc&lt;br /&gt;
 │       ├── lib&lt;br /&gt;
 │       │   └── modules&lt;br /&gt;
 │       │       ├── 8250_mtk.ko&lt;br /&gt;
 │       │       ├── adapter_class.ko&lt;br /&gt;
 │       │       ├── adsp.ko&lt;br /&gt;
 │       │       ├── aee_aed.ko&lt;br /&gt;
 │       │       ├── aee_hangdet.ko&lt;br /&gt;
 │       │       ├── aee_rs.ko&lt;br /&gt;
 │       │       ├── blocktag.ko&lt;br /&gt;
 │       │       └── 省略....&lt;br /&gt;
 │       └── system&lt;br /&gt;
 │           ├── bin&lt;br /&gt;
 │           │   └── mtk_plpath_utils&lt;br /&gt;
 │           ├── etc&lt;br /&gt;
 │           │   ├── recovery.fstab&lt;br /&gt;
 │           │   └── ueventd.rc&lt;br /&gt;
 │           └── lib64&lt;br /&gt;
 │               └── hw&lt;br /&gt;
 │                   └── android.hardware.boot@1.0-impl-1.2-mtkimpl.so&lt;br /&gt;
 └── twrp_rubens.mk&lt;br /&gt;
打开 init.recovery.mt6895.rc 添加&lt;br /&gt;
 on boot&lt;br /&gt;
     start health-hal-2-1&lt;br /&gt;
 &lt;br /&gt;
 on post-fs&lt;br /&gt;
     start boot-hal-1-2&lt;br /&gt;
例如&lt;br /&gt;
 on post-fs&lt;br /&gt;
     start boot-hal-1-2&lt;br /&gt;
 &lt;br /&gt;
 on init&lt;br /&gt;
     setprop sys.usb.configfs 1&lt;br /&gt;
     setprop sys.usb.controller &amp;quot;11201000.usb0&amp;quot;&lt;br /&gt;
     setprop sys.usb.ffs.aio_compat 1&lt;br /&gt;
 &lt;br /&gt;
 on fs &amp;amp;&amp;amp; property:ro.debuggable=0&lt;br /&gt;
     # distinguish USB shoulde connect or not, i.e. CDP vs SDP&lt;br /&gt;
     # set charging free due to it wait for USB activation&lt;br /&gt;
 &lt;br /&gt;
 on boot&lt;br /&gt;
     start health-hal-2-1&lt;br /&gt;
     exec u:r:update_engine:s0 root root -- /system/bin/mtk_plpath_utils&lt;br /&gt;
 &lt;br /&gt;
接下来可以开始编译咯~~&lt;br /&gt;
&lt;br /&gt;
==== 编译 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;编译前请检查注释是否全部删除&amp;lt;/blockquote&amp;gt;twrp 源码根目录执行&lt;br /&gt;
 . build/envsetup.sh&lt;br /&gt;
 lunch twrp_codename-eng # twrp-9为onmi&lt;br /&gt;
 mka vendorbootimage/bootimage/recoveryimage&lt;br /&gt;
不出意外的话一路绿灯，如果有报错的话请发邮箱至 1592501605@qq.com 咨询我&lt;br /&gt;
&lt;br /&gt;
产物在 out/target/product/codename/vendor_boot.img\boot.img\recovery.img&lt;br /&gt;
&lt;br /&gt;
手机重启到 fastboot 模式，使用 fastboot flash 刷写，例如&lt;br /&gt;
 fastboot flash vendor_boot /Users/xiaolegun/Downloads/vendor_boot.img&lt;br /&gt;
则输出&lt;br /&gt;
 ERROR: could not clear input pipe; result e0005000, ignoring...&lt;br /&gt;
 ERROR: could not clear output pipe; result e0005000, ignoring....&lt;br /&gt;
 Sending 'vendor_boot_a' (65536 KB)                 OKAY [  1.396s]&lt;br /&gt;
 Writing 'vendor_boot_a'                            OKAY [  0.167s]&lt;br /&gt;
 Finished. Total time: 1.625s&lt;br /&gt;
就可以重启按电源加音量上尝试了，我自己是一次点亮，但有 bug。&lt;br /&gt;
&lt;br /&gt;
==== 修 BUG ====&lt;br /&gt;
&lt;br /&gt;
===== 修复 USB =====&lt;br /&gt;
我看到 twrp 控制台有很多报错，第一步肯定是先获取日志，使用logcat命令获取，在此之前先使用adb devices检测一下设备 usb 是否工作正常。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~  adb devices          ✔  10208  10:05:31&lt;br /&gt;
 * daemon not running; starting now at tcp:5037&lt;br /&gt;
 * daemon started successfully&lt;br /&gt;
 List of devices attached&lt;br /&gt;
可以看到adb没有检测到设备，原因一般是 usb 的配置不对，但 usb 是好的。这时可以尝试关闭 mtp，再开启，如果电脑有反应，那么就可以继续下一步了。&lt;br /&gt;
&lt;br /&gt;
在设备树中的 recovery/root，创建 init.recovery.usb.rc 的文件&lt;br /&gt;
 touch recovery/root/init.recovery.usb.rc&lt;br /&gt;
并导入以下内容&lt;br /&gt;
 on property:sys.usb.config=mtp,adb&lt;br /&gt;
     start adbd&lt;br /&gt;
 &lt;br /&gt;
 on property:sys.usb.ffs.ready=1 &amp;amp;&amp;amp; property:sys.usb.config=mtp,adb&lt;br /&gt;
     write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration &amp;quot;mtp_adb&amp;quot;&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f3&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f4&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f5&lt;br /&gt;
     write /config/usb_gadget/g1/idVendor 0x18d1&lt;br /&gt;
     write /config/usb_gadget/g1/idProduct 0x2d08&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}&lt;br /&gt;
     setprop sys.usb.state ${sys.usb.config}&lt;br /&gt;
这是我从我维护的 MI 6X 的 device tree 拿过来的，可以在联发科设备上正常工作。这段 shell 的大致意思就是在 usb 配置节点写入 mtp 和 adb 同时工作的字符串，这样 adb 就能顺利工作了。&lt;br /&gt;
&lt;br /&gt;
此外打开原厂 init.rc 修正一下 usb 设备的 id&lt;br /&gt;
 # MIUI ADD: START&lt;br /&gt;
 import /init.recovery.hardware.rc&lt;br /&gt;
 import /miui.factoryreset.rc&lt;br /&gt;
 # END&lt;br /&gt;
 import /init.recovery.${ro.hardware}.rc&lt;br /&gt;
 &lt;br /&gt;
 ########### 省略一万字&lt;br /&gt;
 &lt;br /&gt;
 # MIUI ADD: START&lt;br /&gt;
 on property:sys.usb.config=mtp,adb &amp;amp;&amp;amp; property:sys.usb.configfs=0&lt;br /&gt;
     write /sys/class/android_usb/android0/enable 0&lt;br /&gt;
     write /sys/class/android_usb/android0/idVendor 2717&lt;br /&gt;
     write /sys/class/android_usb/android0/idProduct 904D&lt;br /&gt;
     write /sys/class/android_usb/android0/functions mtp,adb&lt;br /&gt;
     write /sys/class/android_usb/android0/enable 1&lt;br /&gt;
     setprop sys.usb.state  ${sys.usb.config}&lt;br /&gt;
 # END&lt;br /&gt;
将/sys/class/android_usb/android0/idVendor和write /sys/class/android_usb/android0/idProduct后面的 id 分别替换到/config/usb_gadget/g1/idVendor和/config/usb_gadget/g1/idProduct处理完就是这样的。&lt;br /&gt;
 on property:sys.usb.config=mtp,adb&lt;br /&gt;
     start adbd&lt;br /&gt;
 &lt;br /&gt;
 on property:sys.usb.ffs.ready=1 &amp;amp;&amp;amp; property:sys.usb.config=mtp,adb&lt;br /&gt;
     write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration &amp;quot;mtp_adb&amp;quot;&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f3&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f4&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f5&lt;br /&gt;
     write /config/usb_gadget/g1/idVendor 0x2717&lt;br /&gt;
     write /config/usb_gadget/g1/idProduct 0x904D&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}&lt;br /&gt;
     setprop sys.usb.state ${sys.usb.config}&lt;br /&gt;
接下来开机之后 adb 和 mtp 就能同时工作了。&lt;br /&gt;
&lt;br /&gt;
===== 修复 Resetprop =====&lt;br /&gt;
接下来就可以修复其它 bug 了，我看到控制台有一堆红色的报错:&lt;br /&gt;
 E:Unknown File System:'/mi_ext'&lt;br /&gt;
 E:Unable to override 'external_storage.projid.enabled' due to missing libresetprop&lt;br /&gt;
 挂载“/data”失败(Invalid argument)&lt;br /&gt;
这三个报错中第二个最好修，第一个次之，第三个与解密有关，放在另一个大章节讲。&lt;br /&gt;
&lt;br /&gt;
第二个报错只需要在 BoardConfig.mk 中添加&lt;br /&gt;
 # Tool&lt;br /&gt;
 TW_INCLUDE_RESETPROP := true&lt;br /&gt;
 TW_INCLUDE_LIBRESETPROP := true&lt;br /&gt;
不用编译测试直接秒杀&lt;br /&gt;
&lt;br /&gt;
===== 修复挂载 =====&lt;br /&gt;
 E:Unknown File System:'/mi_ext'&lt;br /&gt;
我们打开 recovery/root/system/etc 中的 recovery.fstab，发现里面有很多空格，我们先将它格式化一下，有实力的可以把后面的 flag 也对齐整理好。&lt;br /&gt;
&lt;br /&gt;
我比较没实力，简单格式化了一下，是这样的&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 341 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;command line&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 2&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot; 2&lt;br /&gt;
 # 173 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 system /system erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system /system ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 vendor /vendor erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor /vendor ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 mi_ext /mnt/vendor/mi_ext erofs ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 mi_ext /mnt/vendor/mi_ext ext4 ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 /mnt/vendor/mi_ext /mi_ext none ro,bind wait,nofail&lt;br /&gt;
 overlay /product/overlay overlay ro,lowerdir=/mnt/vendor/mi_ext/product/overlay/:/product/overlay check,nofail&lt;br /&gt;
 overlay /product/app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/app/:/product/app check,nofail&lt;br /&gt;
 overlay /product/priv-app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/priv-app/:/product/priv-app check,nofail&lt;br /&gt;
 overlay /product/lib overlay ro,lowerdir=/mnt/vendor/mi_ext/product/lib/:/product/lib check,nofail&lt;br /&gt;
 overlay /product/lib64 overlay ro,lowerdir=/mnt/vendor/mi_ext/product/lib64/:/product/lib64 check,nofail&lt;br /&gt;
 overlay /product/bin overlay ro,lowerdir=/mnt/vendor/mi_ext/product/bin/:/product/bin check,nofail&lt;br /&gt;
 overlay /product/framework overlay ro,lowerdir=/mnt/vendor/mi_ext/product/framework/:/product/framework check,nofail&lt;br /&gt;
 overlay /product/media overlay ro,lowerdir=/mnt/vendor/mi_ext/product/media/:/product/media check,nofail&lt;br /&gt;
 overlay /product/opcust overlay ro,lowerdir=/mnt/vendor/mi_ext/product/opcust/:/product/opcust check,nofail&lt;br /&gt;
 overlay /product/data-app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/data-app/:/product/data-app check,nofail&lt;br /&gt;
 overlay /product/etc/sysconfig overlay ro,lowerdir=/mnt/vendor/mi_ext/product/etc/sysconfig/:/product/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /product/etc/permissions overlay ro,lowerdir=/mnt/vendor/mi_ext/product/etc/permissions/:/product/etc/permissions check,nofail&lt;br /&gt;
 overlay /system/app overlay ro,lowerdir=/mnt/vendor/mi_ext/system/app/:/product/pangu/system/app/:/system/app check,nofail&lt;br /&gt;
 overlay /system/priv-app overlay ro,lowerdir=/mnt/vendor/mi_ext/system/priv-app/:/product/pangu/system/priv-app/:/system/priv-app check,nofail&lt;br /&gt;
 overlay /system/framework overlay ro,lowerdir=/product/pangu/system/framework/:/system/framework check,nofail&lt;br /&gt;
 overlay /system/etc/sysconfig overlay ro,lowerdir=/mnt/vendor/mi_ext/system/etc/sysconfig/:/system/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /system/etc/permissions overlay ro,lowerdir=/mnt/vendor/mi_ext/system/etc/permissions/:/product/pangu/system/etc/permissions/:/system/etc/permissions check,nofail&lt;br /&gt;
 system_ext /system_ext erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system_ext /system_ext ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 odm /odm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm /odm ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor_dlkm /vendor_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm_dlkm /odm_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,noflush_merge,fsync_mode=nobarrier,reserve_root=134217,resgid=1065,checkpoint_merge,gc_merge,inlinecrypt wait,check,formattable,quota,latemount,resize,reservedsize=128m,checkpoint=fs,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,fsverity&lt;br /&gt;
 /dev/block/by-name/rescue /cache ext4 noatime,nosuid,nodev,noauto_da_alloc,discard wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect1 /mnt/vendor/protect_f ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect2 /mnt/vendor/protect_s ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvdata /mnt/vendor/nvdata ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvcfg /mnt/vendor/nvcfg ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/persist /mnt/vendor/persist ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /devices/platform/soc/11240000.mmc* auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata&lt;br /&gt;
 /devices/platform/usb_xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /devices/platform/soc/11201000.usb0/11200000.xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /dev/block/by-name/frp /persistent emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/nvram /nvram emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/proinfo /proinfo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk /bootloader emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk2 /bootloader2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/para /para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/misc /misc emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot /boot emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_vendor /vbmeta_vendor emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_system /vbmeta_system emmc defaults first_stage_mount,nofail,slotselect,avb=vbmeta&lt;br /&gt;
 /dev/block/by-name/logo /logo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/expdb /expdb emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/seccfg /seccfg emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee1 /tee1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee2 /tee2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp1 /scp1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp2 /scp2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_1 /sspm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_2 /sspm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_1 /dpm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_2 /dpm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_1 /mcupm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_2 /mcupm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1img /md1img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1dsp /md1dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1arm7 /md1arm7 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md3img /md3img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz1 /gz1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz2 /gz2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/spmfw /spmfw emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/audio_dsp /audio_dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/pi_img /pi_img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot_para /boot_para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/odmdtbo /odmdtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dtbo /dtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/otp /otp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/vbmeta /vbmeta emmc defaults defaults&lt;br /&gt;
这里面有很多无用分区，我们在 twrp 中操作不到，但是我也是第一次适配 MTK 设备，所以不“瞎说”误人子弟了，先把 bug 修好。&lt;br /&gt;
&lt;br /&gt;
像 xiaomi 这样常见的挂载错误，我自己一般都是尝试把/mnt/vendor 使用 vscode 全部删除，让我们尝试一下。并且要把这一行删除，这行在我看来是重复定义（？而且也没指定分区格式。&lt;br /&gt;
 /mnt/vendor/mi_ext /mi_ext none ro,bind wait,nofail&lt;br /&gt;
整理完之后是这样的&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 341 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;command line&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 2&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot; 2&lt;br /&gt;
 # 173 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 system /system erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system /system ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 vendor /vendor erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor /vendor ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 mi_ext /mi_ext erofs ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 mi_ext /mi_ext ext4 ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 overlay /product/overlay overlay ro,lowerdir=/mi_ext/product/overlay/:/product/overlay check,nofail&lt;br /&gt;
 overlay /product/app overlay ro,lowerdir=/mi_ext/product/app/:/product/app check,nofail&lt;br /&gt;
 overlay /product/priv-app overlay ro,lowerdir=/mi_ext/product/priv-app/:/product/priv-app check,nofail&lt;br /&gt;
 overlay /product/lib overlay ro,lowerdir=/mi_ext/product/lib/:/product/lib check,nofail&lt;br /&gt;
 overlay /product/lib64 overlay ro,lowerdir=/mi_ext/product/lib64/:/product/lib64 check,nofail&lt;br /&gt;
 overlay /product/bin overlay ro,lowerdir=/mi_ext/product/bin/:/product/bin check,nofail&lt;br /&gt;
 overlay /product/framework overlay ro,lowerdir=/mi_ext/product/framework/:/product/framework check,nofail&lt;br /&gt;
 overlay /product/media overlay ro,lowerdir=/mi_ext/product/media/:/product/media check,nofail&lt;br /&gt;
 overlay /product/opcust overlay ro,lowerdir=/mi_ext/product/opcust/:/product/opcust check,nofail&lt;br /&gt;
 overlay /product/data-app overlay ro,lowerdir=/mi_ext/product/data-app/:/product/data-app check,nofail&lt;br /&gt;
 overlay /product/etc/sysconfig overlay ro,lowerdir=/mi_ext/product/etc/sysconfig/:/product/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /product/etc/permissions overlay ro,lowerdir=/mi_ext/product/etc/permissions/:/product/etc/permissions check,nofail&lt;br /&gt;
 overlay /system/app overlay ro,lowerdir=/mi_ext/system/app/:/product/pangu/system/app/:/system/app check,nofail&lt;br /&gt;
 overlay /system/priv-app overlay ro,lowerdir=/mi_ext/system/priv-app/:/product/pangu/system/priv-app/:/system/priv-app check,nofail&lt;br /&gt;
 overlay /system/framework overlay ro,lowerdir=/product/pangu/system/framework/:/system/framework check,nofail&lt;br /&gt;
 overlay /system/etc/sysconfig overlay ro,lowerdir=/mi_ext/system/etc/sysconfig/:/system/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /system/etc/permissions overlay ro,lowerdir=/mi_ext/system/etc/permissions/:/product/pangu/system/etc/permissions/:/system/etc/permissions check,nofail&lt;br /&gt;
 system_ext /system_ext erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system_ext /system_ext ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 odm /odm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm /odm ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor_dlkm /vendor_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm_dlkm /odm_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,noflush_merge,fsync_mode=nobarrier,reserve_root=134217,resgid=1065,checkpoint_merge,gc_merge,inlinecrypt wait,check,formattable,quota,latemount,resize,reservedsize=128m,checkpoint=fs,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,fsverity&lt;br /&gt;
 /dev/block/by-name/rescue /cache ext4 noatime,nosuid,nodev,noauto_da_alloc,discard wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect1 /protect_f ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect2 /protect_s ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvdata /nvdata ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvcfg /nvcfg ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/persist /persist ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /devices/platform/soc/11240000.mmc* auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata&lt;br /&gt;
 /devices/platform/usb_xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /devices/platform/soc/11201000.usb0/11200000.xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /dev/block/by-name/frp /persistent emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/nvram /nvram emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/proinfo /proinfo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk /bootloader emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk2 /bootloader2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/para /para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/misc /misc emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot /boot emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_vendor /vbmeta_vendor emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_system /vbmeta_system emmc defaults first_stage_mount,nofail,slotselect,avb=vbmeta&lt;br /&gt;
 /dev/block/by-name/logo /logo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/expdb /expdb emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/seccfg /seccfg emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee1 /tee1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee2 /tee2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp1 /scp1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp2 /scp2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_1 /sspm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_2 /sspm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_1 /dpm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_2 /dpm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_1 /mcupm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_2 /mcupm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1img /md1img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1dsp /md1dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1arm7 /md1arm7 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md3img /md3img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz1 /gz1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz2 /gz2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/spmfw /spmfw emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/audio_dsp /audio_dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/pi_img /pi_img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot_para /boot_para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/odmdtbo /odmdtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dtbo /dtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/otp /otp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/vbmeta /vbmeta emmc defaults defaults&lt;br /&gt;
让我们编译试一下，值得注意的是，twrp 每次更改最好删除 out 重新编译，不要使用如make installclean等命令，可能会开机黑屏或更改不生效。&lt;br /&gt;
&lt;br /&gt;
经过一分钟，编译好了，刷入，开机，启动！可以看见挂载成功被修好。&lt;br /&gt;
&lt;br /&gt;
===== 修复屏幕显示 =====&lt;br /&gt;
可以看到我们现在屏幕的顶部的时间被摄像头挖孔挡住了。我们使用两个偏移 Flag 来修复它。&lt;br /&gt;
&lt;br /&gt;
在 BoardConfig.mk 中，加入以下 flag&lt;br /&gt;
 TW_Y_OFFSET := 106 #导航栏向上&lt;br /&gt;
 TW_H_OFFSET := -106 #界面整体向下&lt;br /&gt;
&lt;br /&gt;
===== 修复振动 =====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;仅供参考，研究半天发现只有解密功能正常才能修振动，不然会冻屏！！！&lt;br /&gt;
&lt;br /&gt;
不一定正确，也不一定普遍，仅供指路&amp;lt;/blockquote&amp;gt;老设备一般都是正常的，不需要额外处理，新设备使用 aidl hal 需要我们自己处理一下让 service 正常工作。&lt;br /&gt;
&lt;br /&gt;
挂载 vendor，使用 twrp 的文件管理，在 vendor/etc/vintf/manifest 找到含有 vibrator 字样的文件。打开之后检查是否类似这样的文段&lt;br /&gt;
 &amp;lt;manifest version=&amp;quot;1.0&amp;quot; type=&amp;quot;device&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;hal format=&amp;quot;aidl&amp;quot; override=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
         &amp;lt;name&amp;gt;android.hardware.vibrator&amp;lt;/name&amp;gt;&lt;br /&gt;
         &amp;lt;fqname&amp;gt;IVibrator/vibratorfeature&amp;lt;/fqname&amp;gt;&lt;br /&gt;
     &amp;lt;/hal&amp;gt;&lt;br /&gt;
 &amp;lt;/manifest&amp;gt;&lt;br /&gt;
那恭喜你，找对了，我的文件名是&lt;br /&gt;
&lt;br /&gt;
vendor.xiaomi.hardware.vibratorfeature.service.xml&lt;br /&gt;
&lt;br /&gt;
将它使用adb pull放到电脑上自己方便的位置备用。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /vendor/etc/vintf/manifest/vendor.xiaomi.hardware.vibratorfeature.service.xml .&lt;br /&gt;
 /vendor/etc/vintf/manifest/vendor.xiao...ipped. 0.2 MB/s (1718 bytes in 0.009s)&lt;br /&gt;
不看扩展名，到 vendor/bin/hw/找到同名的 service 同样利用adb pull放电脑备用。比如我的叫&lt;br /&gt;
&lt;br /&gt;
vendor.xiaomi.hardware.vibratorfeature.service&lt;br /&gt;
&lt;br /&gt;
然后到 vendor/etc/init/找到同名.rc 文件，拉到电脑上，在里面加一条。并在定义 service 的最下面加上seclabel u:r:recovery:s0可以被 recovery 使用。&lt;br /&gt;
 on boot&lt;br /&gt;
     start service被定义的名字&lt;br /&gt;
例如&lt;br /&gt;
 on post-fs-data&lt;br /&gt;
     chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/f0_save&lt;br /&gt;
     chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/osc_save&lt;br /&gt;
     chown system system /sys/bus/i2c/drivers/aw8697_haptic/3-005a/osc_save&lt;br /&gt;
     # 省略一万字&lt;br /&gt;
 &lt;br /&gt;
 on boot&lt;br /&gt;
     start vibratorfeature-hal-service&lt;br /&gt;
 &lt;br /&gt;
 service vibratorfeature-hal-service /vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&lt;br /&gt;
     class hal&lt;br /&gt;
     user system&lt;br /&gt;
     group system input&lt;br /&gt;
     onrestart restart vibratorfeature&lt;br /&gt;
     seclabel u:r:recovery:s0&lt;br /&gt;
此外这种新设备在内核里还有振动模块需要加载，请到/vendor/modules/1.1/中寻找，例如我这台设备是haptic.ko，用 adb pull 拉取到电脑上，然后&lt;br /&gt;
&lt;br /&gt;
* haptic.ko --&amp;gt; recovery/root/vendor/modules/1.1&lt;br /&gt;
&lt;br /&gt;
至此所有必要的资料就准备好了。可能开机后仍然不工作，需要抓取 log 补缺失的 library，当然这是后话了。&lt;br /&gt;
&lt;br /&gt;
开干！&lt;br /&gt;
&lt;br /&gt;
在 BoardConfig.mk 中加入以下 flag&lt;br /&gt;
 TW_SUPPORT_INPUT_AIDL_HAPTICS := true&lt;br /&gt;
将备用文件按照以下操作复制&lt;br /&gt;
&lt;br /&gt;
* vendor.xiaomi.hardware.vibratorfeature.service.xml --&amp;gt; recovery/root/vendor/etc/vintf/manifest&lt;br /&gt;
* vendor.xiaomi.hardware.vibratorfeature.service --&amp;gt; recovery/root/vendor/bin/hw&lt;br /&gt;
* vendor.xiaomi.hardware.vibratorfeature.service.rc --&amp;gt; recovery/root/vendor/etc/init&lt;br /&gt;
&lt;br /&gt;
之后编译，刷入，开机，喜提冻屏......&lt;br /&gt;
&lt;br /&gt;
问题不大，使用adb logcat抓取日志&lt;br /&gt;
 adb logcat &amp;gt; log.log&lt;br /&gt;
打开 log，搜索F linker、linker、library、beginning of crash这几个关键词，我搜索第一个就出来了。&lt;br /&gt;
 F linker  : CANNOT LINK EXECUTABLE &amp;quot;/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&amp;quot;: library &amp;quot;android.hardware.vibrator-V1-ndk_platform.so&amp;quot; not found: needed by main executable&lt;br /&gt;
这段报错的意思就是vendor.xiaomi.hardware.vibratorfeature.service找不到android.hardware.vibrator-V1-ndk_platform.so这个库，所以无法正常工作。&lt;br /&gt;
&lt;br /&gt;
打开 BoardConfig.mk 加入以下 flag&lt;br /&gt;
 # Library&lt;br /&gt;
 TARGET_RECOVERY_DEVICE_MODULES += \&lt;br /&gt;
     android.hardware.vibrator-V1-ndk_platform.vendor&lt;br /&gt;
 &lt;br /&gt;
 TW_RECOVERY_ADDITIONAL_RELINK_LIBRARY_FILES += \&lt;br /&gt;
     $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.vibrator-V1-ndk_platform.so&lt;br /&gt;
再次编译尝试&lt;br /&gt;
&lt;br /&gt;
开机之后依然冻屏，继续抓 log，查找&lt;br /&gt;
 F linker  : CANNOT LINK EXECUTABLE &amp;quot;/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&amp;quot;: library &amp;quot;vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so&amp;quot; not found: needed by main executable&lt;br /&gt;
vendor.hardware.vibratorfeature字样和我们之前导入的文件长得差不多，一般都是供应商专有文件，所以去设备提取，路径在 vendor/lib64 里，虽然设备冻屏了，但我们可以用adb pull直接拉取到电脑。就像这样。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb shell mount /vendor&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /vendor/lib64/vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so .&lt;br /&gt;
 /vendor/lib64/vendor.hardware.vibratorfeature.IVi...led, 0 skipped. 14.7 MB/s (33552 bytes in 0.002s&lt;br /&gt;
将这个文件按照以下提示操作&lt;br /&gt;
&lt;br /&gt;
* vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so --&amp;gt; recovery/root/vendor/lib64&lt;br /&gt;
&lt;br /&gt;
继续编译测试&lt;br /&gt;
&lt;br /&gt;
还是冻屏，继续抓 log&lt;br /&gt;
 F linker  : CANNOT LINK EXECUTABLE &amp;quot;/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&amp;quot;: library &amp;quot;libtinyalsa.so&amp;quot; not found: needed by main executable&lt;br /&gt;
这个 library twrp 的源码中应该没有，去设备拿一个 prebuilt 吧&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb shell mount /system_root&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /system_root/system/lib64/libtinyalsa.so .&lt;br /&gt;
 /system_root/system/lib64/libtinyalsa.so: 1 file ...led, 0 skipped. 13.6 MB/s (45032 bytes in 0.003s&lt;br /&gt;
将这个文件按照以下提示操作&lt;br /&gt;
&lt;br /&gt;
* libtinyalsa.so --&amp;gt; recovery/root/system/lib64&lt;br /&gt;
&lt;br /&gt;
编译测试&lt;br /&gt;
&lt;br /&gt;
我艹了，还是冻屏，这次搜那几个关键词都搜不到了，搜vibrator看看这鬼东西报什么&lt;br /&gt;
 E vendor.xiaomi.hardware.vibratorfeature.service: fail to load lib : /vendor/lib64/libaachaptics.so&lt;br /&gt;
这次都直接给路径了，直接拿。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb shell mount /vendor&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /vendor/lib64/libaachaptics.so .&lt;br /&gt;
 /vendor/lib64/libaachaptics.so: 1 file pulled, 0 skipped. 15.8 MB/s (56232 bytes in 0.003s)&lt;br /&gt;
将这个文件按照以下提示操作&lt;br /&gt;
&lt;br /&gt;
* libaachaptics.so --&amp;gt; recovery/root/vendor/lib64&lt;br /&gt;
&lt;br /&gt;
至此应该没什么问题了，但是有个 flag 貌似要操作 data 内的东西，未解密会导致冻屏，所以等修完解密后再来修振动。&lt;br /&gt;
&lt;br /&gt;
==== 修复 CPU 温度 ====&lt;br /&gt;
使用adb shell + grep命令在手机节点里搜索 type 关键词。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~  adb shell 'grep &amp;quot;cp_master&amp;quot; /sys/class/thermal/*/type'&lt;br /&gt;
 /sys/class/thermal/thermal_zone54/type:cp_master&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~  adb shell 'grep &amp;quot;cpu&amp;quot; /sys/class/thermal/*/type'&lt;br /&gt;
 /sys/class/thermal/thermal_zone1/type:cpu_little1&lt;br /&gt;
 /sys/class/thermal/thermal_zone10/type:cpu_bigbig1&lt;br /&gt;
 /sys/class/thermal/thermal_zone11/type:cpu_big6&lt;br /&gt;
 /sys/class/thermal/thermal_zone12/type:cpu_bigbig2&lt;br /&gt;
 /sys/class/thermal/thermal_zone2/type:cpu_little2&lt;br /&gt;
 /sys/class/thermal/thermal_zone3/type:cpu_little3&lt;br /&gt;
 /sys/class/thermal/thermal_zone4/type:cpu_little4&lt;br /&gt;
 /sys/class/thermal/thermal_zone5/type:cpu_big1&lt;br /&gt;
 /sys/class/thermal/thermal_zone6/type:cpu_big2&lt;br /&gt;
 /sys/class/thermal/thermal_zone7/type:cpu_big3&lt;br /&gt;
 /sys/class/thermal/thermal_zone8/type:cpu_big4&lt;br /&gt;
 /sys/class/thermal/thermal_zone9/type:cpu_big5&lt;br /&gt;
我这里选用cp_master节点来读取温度。我的节点路径为/sys/class/thermal/thermal_zone54在后面添加 temp 来读取温度，你可以使用cat来检测节点是否可以正常读取温度&lt;br /&gt;
 adb shell 'cat /sys/class/thermal/thermal_zone54/temp'&lt;br /&gt;
如果返回如&lt;br /&gt;
 28000&lt;br /&gt;
这种类似的数值，那多半是没有问题的。&lt;br /&gt;
&lt;br /&gt;
我们在 BoardConfig.mk 中加入&lt;br /&gt;
 TW_CUSTOM_CPU_TEMP_PATH := &amp;quot;/sys/class/thermal/thermal_zone54/temp&amp;quot;&lt;br /&gt;
至此 cpu 温度就修复好了。&lt;br /&gt;
&lt;br /&gt;
== 后序 ==&lt;br /&gt;
这是我玩 Android 两年内第一次写关于 Android 的文章，内容和措辞可能不是很准确，再加上开学焦虑，租房因租金和房源不顺利，写的很乱，请各位指正。&lt;br /&gt;
&lt;br /&gt;
此外有什么不懂得，多翻github，善用github搜索，多看看大佬们是怎么解决的。&lt;br /&gt;
&lt;br /&gt;
解密等有空补，先补作业。&lt;br /&gt;
&lt;br /&gt;
== 参考资料 ==&lt;br /&gt;
[https://source.android.com/docs/setup/create/new-device?hl=zh-cn Google - 添加新设备]&lt;br /&gt;
&lt;br /&gt;
[https://source.android.com/docs/core/ota/ab?hl=zh-cn Google - A/B（无缝）系统更新]&lt;br /&gt;
&lt;br /&gt;
[https://blog.lynnrin.moe/posts/ROM-bringup-guide-prebuilt/#boardconfigmk Lynnrin - 快速上手 Android Custom ROM 适配 - Prebuilt Vendor]&lt;br /&gt;
&lt;br /&gt;
[https://source.android.com/docs/core/architecture/vintf?hl=zh-cn Google - 供应商接口对象]&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=%E4%B8%BA%E6%96%B0%E8%AE%BE%E5%A4%87%E7%BC%96%E5%86%99Recovery_device_tree&amp;diff=555</id>
		<title>为新设备编写Recovery device tree</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=%E4%B8%BA%E6%96%B0%E8%AE%BE%E5%A4%87%E7%BC%96%E5%86%99Recovery_device_tree&amp;diff=555"/>
		<updated>2024-02-20T06:11:03Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​fixup&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= 为新设备编写 Recovery 的设备树 =&lt;br /&gt;
作者: Dark(xiaoleGun)&lt;br /&gt;
&lt;br /&gt;
时间: 2024.2.20&lt;br /&gt;
&lt;br /&gt;
协作者:&lt;br /&gt;
&lt;br /&gt;
== 一些自序 ==&lt;br /&gt;
这篇教程中可能有些不对的地方，请各位指正，我也刚接触 Android 设备测开发两年，而且只有在节假日的时候有空一个人瞎捣鼓，为了&amp;lt;s&amp;gt;薅 mjw 羊毛&amp;lt;/s&amp;gt;，故写这篇教程，而且我个人更推荐 Aosp Recovery 刷写第三方 ROM，TWRP 可能多多少少有些问题。Root 之类的不需要 TWRP 也可以，可以找到原机 boot 使用 Magisk 进行修补，也可以使用 KernelSU。另外我的语文功底不是很好，写不出辞藻，只能是北方地道的大白话，见谅哈 🤣///&lt;br /&gt;
&lt;br /&gt;
== 准备工作 ==&lt;br /&gt;
1.一颗勇敢的、不怕困难的强大心脏。&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;s&amp;gt;两颗心好勇敢 -- Falling in love&amp;lt;/s&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
2.电脑配置:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!硬件&lt;br /&gt;
!需求&lt;br /&gt;
|-&lt;br /&gt;
|CPU&lt;br /&gt;
|四核或更多&lt;br /&gt;
|-&lt;br /&gt;
|内存&lt;br /&gt;
|8G 或更多&lt;br /&gt;
|-&lt;br /&gt;
|硬盘&lt;br /&gt;
|至少 80G 空余空间&lt;br /&gt;
|-&lt;br /&gt;
|系统&lt;br /&gt;
|WSL 或实体 Linux，建议 Debian 系&lt;br /&gt;
|}&lt;br /&gt;
3.足够的空闲时间。&lt;br /&gt;
&lt;br /&gt;
4.Vscode 和 🤏Linux 知识储备&lt;br /&gt;
&lt;br /&gt;
5.一台完好无损的新设备。&lt;br /&gt;
&lt;br /&gt;
6.设备原厂的 boot/recovery/vendor_boot 镜像。(推荐 recovery 分区，因为里面包含一些启动必须的.rc(run command)，如果没有该分区，寻找包含官方 recovery 内容的分区。值得注意的是部分设备 recovery 合并到了 boot 中，或是存在于 vendor_boot）&lt;br /&gt;
&lt;br /&gt;
7.查看自己的设备出厂 Android 版本并确定用途，是用于官方 ROM 还是第三方类原生。出厂版本为 9 及以上的可以使用 twrp-11 及以上分支，9 以下使用 twrp-9 分支。&lt;br /&gt;
&lt;br /&gt;
== 配置环境 ==&lt;br /&gt;
&lt;br /&gt;
=== 安装依赖 ===&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt-get install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev liblz4-tool libncurses5 libncurses5-dev libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev xattr openjdk-11-jdk jq android-sdk-libsparse-utils python3 python2 repo&lt;br /&gt;
&lt;br /&gt;
必要时可以阅读[https://source.android.com/source/using-repo?hl=zh-cn Git 和 Repo]&lt;br /&gt;
&lt;br /&gt;
=== 配置 Git 和 Repo ===&lt;br /&gt;
安装完依赖后，在终端执行。&lt;br /&gt;
 git config --global user.name &amp;quot;your username&amp;quot;&lt;br /&gt;
 git config --global user.email &amp;quot;your email&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== 同步 TWRP 源码 ===&lt;br /&gt;
在自己方便的地方，建立一个目录。&lt;br /&gt;
 mkdir twrp&lt;br /&gt;
 cd twrp&lt;br /&gt;
根据自己在准备工作中确定的分支同步相应的源码。&lt;br /&gt;
&lt;br /&gt;
==== TWRP-9 ====&lt;br /&gt;
 repo init --depth=1 -u &amp;lt;nowiki&amp;gt;https://github.com/minimal-manifest-twrp/platform_manifest_twrp_omni.git&amp;lt;/nowiki&amp;gt; -b twrp-9.0&lt;br /&gt;
 repo sync&lt;br /&gt;
&lt;br /&gt;
==== TWRP-11 ====&lt;br /&gt;
 repo init --depth=1 -u &amp;lt;nowiki&amp;gt;https://github.com/minimal-manifest-twrp/platform_manifest_twrp_aosp.git&amp;lt;/nowiki&amp;gt; -b twrp-11&lt;br /&gt;
 repo sync&lt;br /&gt;
&lt;br /&gt;
==== TWRP-12.1 ====&lt;br /&gt;
 repo init --depth=1 -u &amp;lt;nowiki&amp;gt;https://github.com/minimal-manifest-twrp/platform_manifest_twrp_aosp.git&amp;lt;/nowiki&amp;gt; -b twrp-12.1&lt;br /&gt;
 repo sync&lt;br /&gt;
&lt;br /&gt;
== 编写设备树 ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;最基本的开机部分我通过 Redmi K50 做示例，并选取 TWRP-12.1 分支。&lt;br /&gt;
&lt;br /&gt;
解密部分会单独成一个章节并分为高通和联发科。&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 获取资料 ===&lt;br /&gt;
小米设备一般可以在[https://xiaomirom.com Xiaomirom]中的线刷包获取 boot/recovery/vendor_boot 镜像，其它设备请自行寻找。&lt;br /&gt;
&lt;br /&gt;
==== 安装工具和依赖 ====&lt;br /&gt;
将准备工作中准备的 boot/recovery/vendor_boot 镜像解包，可以用任何工具，我这里使用[https://github.com/cfig/Android_boot_image_editor Android_boot_image_editor]按照自述文件进行依赖安装操作：&lt;br /&gt;
&lt;br /&gt;
===== Mac(Intel) =====&lt;br /&gt;
 brew install lz4 xz dtc openjdk@17&lt;br /&gt;
 echo 'export PATH=&amp;quot;/usr/local/opt/openjdk@17/bin:$PATH&amp;quot;' &amp;gt;&amp;gt; ~/.zshrc&lt;br /&gt;
 source ~/.zshrc&lt;br /&gt;
&lt;br /&gt;
===== Linux: =====&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-17-jdk gcc g++ python3 python-is-python3 p7zip-full android-sdk-libsparse-utils erofs-utils&lt;br /&gt;
&lt;br /&gt;
===== Common: =====&lt;br /&gt;
 git clone &amp;lt;nowiki&amp;gt;https://github.com/cfig/Android_boot_image_editor&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 cd Android_boot_image_editor&lt;br /&gt;
&lt;br /&gt;
==== 解包 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;请注意&amp;quot;/&amp;quot;表示或的意思，请不要误以为是一个东西。&lt;br /&gt;
&lt;br /&gt;
如果不确定分区寻找的是否正确，请尝试将可以的分区进行解包，并查看其ramdisk内是否包含recovery字样的文件&amp;lt;/blockquote&amp;gt;将你准备好的boot/recovery/vendor_boot复制到该目录，你可以使用 GUI 或者 CLI。如:&lt;br /&gt;
 cp &amp;lt;出厂boot/recovery/vendor_boot的绝对路径&amp;gt; boot/recovery/vendor_boot.img&lt;br /&gt;
 ./gradlew unpack&lt;br /&gt;
我这里以 Redmi K50 为例&lt;br /&gt;
 10:12:13.188 [main] INFO  cfig.bootimg.v3.VendorBoot -&lt;br /&gt;
                         Unpack Summary of vendor_boot.img&lt;br /&gt;
 ┌───────────────────────────────────────┬──────────────────────────────────────┐&lt;br /&gt;
 │What                                   │Where                                 │&lt;br /&gt;
 └───────────────────────────────────────┴──────────────────────────────────────┘&lt;br /&gt;
 ┌───────────────────────────────────────┬──────────────────────────────────────┐&lt;br /&gt;
 │image info                             │build/unzip_boot/vendor_boot.json     │&lt;br /&gt;
 ├───────────────────────────────────────┼──────────────────────────────────────┤&lt;br /&gt;
 │ramdisk                                │build/unzip_boot/ramdisk.img.lz4      │&lt;br /&gt;
 │-- PLATFORM ramdisk[1/1]               │build/unzip_boot/ramdisk.1.lz4        │&lt;br /&gt;
 │------- extracted rootfs               │build/unzip_boot/root.1               │&lt;br /&gt;
 ├───────────────────────────────────────┼──────────────────────────────────────┤&lt;br /&gt;
 │dtb                                    │build/unzip_boot/dtb                  │&lt;br /&gt;
 ├───────────────────────────────────────┼──────────────────────────────────────┤&lt;br /&gt;
 │AVB info                               │build/unzip_boot/vendor_boot.avb.json │&lt;br /&gt;
 │\-- signing key                        │NONE                                  │&lt;br /&gt;
 └───────────────────────────────────────┴──────────────────────────────────────┘&lt;br /&gt;
 10:12:13.213 [main] WARN  cfig.packable.PackableLauncher - 'unpack' sequence completed&lt;br /&gt;
 &lt;br /&gt;
 BUILD SUCCESSFUL in 2s&lt;br /&gt;
解包成功后终端会打印出以上信息，其中包含vendor_boot目录结构，我们只需要ramdisk里的部分内容就好了。&lt;br /&gt;
 ls build/unzip_boot/root.1 # 请根据自己的分区和设备判断ramdisk的命名，一般都直接是ramdisk&lt;br /&gt;
不出意外的话会输出以下内容&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/dump/bootedit   master ?  ls build/unzip_boot/root.1&lt;br /&gt;
 acct                         oem&lt;br /&gt;
 apex                         plat_file_contexts&lt;br /&gt;
 bin                          plat_property_contexts&lt;br /&gt;
 bugreports                   postinstall&lt;br /&gt;
 config                       proc&lt;br /&gt;
 d                            product&lt;br /&gt;
 data                         product_file_contexts&lt;br /&gt;
 data_mirror                  product_property_contexts&lt;br /&gt;
 debug_ramdisk                prop.default&lt;br /&gt;
 default.prop                 res&lt;br /&gt;
 dev                          sdcard&lt;br /&gt;
 etc                          second_stage_resources&lt;br /&gt;
 first_stage_ramdisk          sepolicy&lt;br /&gt;
 init                         storage&lt;br /&gt;
 init.recovery.hardware.rc    sys&lt;br /&gt;
 init.recovery.mt6895.rc      system&lt;br /&gt;
 lib                          system_ext&lt;br /&gt;
 linkerconfig                 system_ext_file_contexts&lt;br /&gt;
 miui.factoryreset.fstab      system_ext_property_contexts&lt;br /&gt;
 miui.factoryreset.rc         tmp&lt;br /&gt;
 mnt                          vendor&lt;br /&gt;
 odm                          vendor_dlkm&lt;br /&gt;
 odm_dlkm                     vendor_file_contexts&lt;br /&gt;
 odm_file_contexts            vendor_property_contexts&lt;br /&gt;
 odm_property_contexts&lt;br /&gt;
如果包含 init.recovery*的字样，恭喜你成功找到了正确的分区。将这个目录复制到一个自己方便的地方。&lt;br /&gt;
&lt;br /&gt;
至此资料已经大致齐全了，解密的资料会在解密章节来讲解如何获取。&lt;br /&gt;
&lt;br /&gt;
=== 初始化目录结构 ===&lt;br /&gt;
在 twrp 源码根目录输入&lt;br /&gt;
 mkdir -p device/vendor/codename&lt;br /&gt;
 mkdir -p device/vendor/codename/recovery/root&lt;br /&gt;
 cd device/vendor/codename&lt;br /&gt;
vendor指的是供应商，如 xiaomi、oneplus、huawei、vivo、realme。&lt;br /&gt;
&lt;br /&gt;
codename指的是设备代号，小米设备可以在[https://xiaomirom.com Xiaomirom]查询，其它设备自行查询亦或是在开发者选项勾选 USB 调试通过 adb 尝试获取。&lt;br /&gt;
 adb shell getprop ro.product.manufacturer # 供应商&lt;br /&gt;
 adb shell getprop ro.product.device # 设备代号&lt;br /&gt;
我的 Redmi K50 会打印以下信息&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/dump/bootedit   master ?  adb shell getprop ro.product.manufacturer&lt;br /&gt;
 Xiaomi # 无论打印出来的内容是大写还是小写，在目录结构中我们都采用小写&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/dump/bootedit   master ?  adb shell getprop ro.product.device&lt;br /&gt;
 rubens&lt;br /&gt;
我的 IQOO NEO5 Lite 会打印以下信息&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  adb shell getprop ro.product.manufacturer&lt;br /&gt;
 vivo&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  adb shell getprop ro.product.device&lt;br /&gt;
 PD2118&lt;br /&gt;
一般只要不是山寨机，小作坊出来的机子，用这两条命令应该是可以正确获取的。&lt;br /&gt;
&lt;br /&gt;
=== 初始化构建时必要的文件 ===&lt;br /&gt;
无论是 AOSP device tree 亦或是 TWRP device tree 都基本类似于以下结构。&lt;br /&gt;
 /&lt;br /&gt;
 ├── prebuilt           (存放kernel、dtb等预编译文件) # AOSP device tree若使用build kernel则没有该目录&lt;br /&gt;
 ├── recovery/root      (存放一些.rc和解密blobs) # 一般用于Recovery device tree&lt;br /&gt;
 ├── Android.mk         (Android构建系统首先会检查每个目录的Android.mk，里面包含一些判断，由它包括其所在目录中所有Makefile)&lt;br /&gt;
 ├── AndroidProducts.mk (声明产品的Makefile和lunch时可用的构建类型)&lt;br /&gt;
 ├── BoardConfig.mk     (板载配置文件，定义了主板必要的Flag)&lt;br /&gt;
 ├── device.mk          (声明设备所需的文件和模块)&lt;br /&gt;
 └── &amp;lt;ROM&amp;gt;_codename.mk  (声明产品特定信息，例如名称、品牌和型号，引用device.mk等) # ROM就比如lineage、arrow等，编译twrp就直接写twrp，twrp-9分支要写onmi&lt;br /&gt;
我们把这样的结构称为骨架树(skeleton tree)。&lt;br /&gt;
&lt;br /&gt;
接下来我们按照以上结构为自己的设备写一份 Recovery device tree。&lt;br /&gt;
&lt;br /&gt;
在终端使用touch命令创建必要的文件。&lt;br /&gt;
 touch Android.mk AndroidProducts.mk BoardConfig.mk device.mk twrp_rubens.mk&lt;br /&gt;
 ls .&lt;br /&gt;
不出意外的话会打印出以下信息&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  touch Android.mk AndroidProducts.mk BoardConfig.mk device.mk twrp_rubens.mk&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  ls .&lt;br /&gt;
 Android.mk         BoardConfig.mk     prebuilt           twrp_rubens.mk&lt;br /&gt;
 AndroidProducts.mk device.mk          recovery&lt;br /&gt;
可以下一步了~&lt;br /&gt;
&lt;br /&gt;
==== 初始 Android.mk 文件 ====&lt;br /&gt;
打开 Vscode 并打开设备树目录，你足够强也可以使用 nano、vim 编辑。&lt;br /&gt;
&lt;br /&gt;
选中 Android.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 LOCAL_PATH := $(call my-dir)&lt;br /&gt;
 &lt;br /&gt;
 ifeq ($(TARGET_DEVICE),codename)&lt;br /&gt;
 include $(call all-subdir-makefiles,$(LOCAL_PATH))&lt;br /&gt;
 endif&lt;br /&gt;
&lt;br /&gt;
* codename是需要你修改的部分&lt;br /&gt;
&lt;br /&gt;
我修改后是这样的&lt;br /&gt;
 LOCAL_PATH := $(call my-dir)&lt;br /&gt;
 &lt;br /&gt;
 ifeq ($(TARGET_DEVICE),rubens)&lt;br /&gt;
 include $(call all-subdir-makefiles,$(LOCAL_PATH))&lt;br /&gt;
 endif&lt;br /&gt;
&lt;br /&gt;
==== 初始 AndroidProducts.mk 文件 ====&lt;br /&gt;
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 PRODUCT_MAKEFILES := \&lt;br /&gt;
     $(LOCAL_DIR)/&amp;lt;ROM&amp;gt;_&amp;lt;codename&amp;gt;.mk&lt;br /&gt;
 &lt;br /&gt;
 COMMON_LUNCH_CHOICES := \&lt;br /&gt;
     &amp;lt;ROM&amp;gt;_&amp;lt;codename&amp;gt;-eng&lt;br /&gt;
我修改后是这样的&lt;br /&gt;
 PRODUCT_MAKEFILES := \&lt;br /&gt;
     $(LOCAL_DIR)/twrp_rubens.mk&lt;br /&gt;
 &lt;br /&gt;
 COMMON_LUNCH_CHOICES := \&lt;br /&gt;
     twrp_rubens-eng&lt;br /&gt;
&lt;br /&gt;
==== 初始 BoardConfig.mk 文件 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;将之前准备的ramdisk文件夹用新窗口打开 1.找到目录下的 prop.default 或含 prop 字样的文件。以下注释类似 ro.*.*的就是从 prop 中获取的 2.解包 boot/recovery/vendor_boot 的 json&lt;br /&gt;
&lt;br /&gt;
例如 build/unzip_boot/boot.json&amp;lt;/blockquote&amp;gt;选中 BoardConfig.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 DEVICE_PATH := device/vendor/codename&lt;br /&gt;
 &lt;br /&gt;
 # Architecture&lt;br /&gt;
 TARGET_ARCH := arm64 # ro.bionic.arch&lt;br /&gt;
 TARGET_ARCH_VARIANT := armv8-a # 64位默认变体&lt;br /&gt;
 TARGET_CPU_ABI := arm64-v8a # ro.vendor.product.cpu.abilist64 (至少在小米设备上没有找到ro.product.cpu.abilist)&lt;br /&gt;
 TARGET_CPU_ABI2 := # 64位留空&lt;br /&gt;
 TARGET_CPU_VARIANT := generic # 默认一般都是通用&lt;br /&gt;
 TARGET_CPU_VARIANT_RUNTIME := cortex-a55 # ro.bionic.cpu_variant&lt;br /&gt;
 &lt;br /&gt;
 TARGET_2ND_ARCH := arm # ro.bionic.2nd_arch&lt;br /&gt;
 TARGET_2ND_ARCH_VARIANT := $(TARGET_ARCH_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_ABI := armeabi-v7a # ro.vendor.product.cpu.abilist32第一个&lt;br /&gt;
 TARGET_2ND_CPU_ABI2 := armeabi # ro.vendor.product.cpu.abilist32第二个&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT_RUNTIME := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 &lt;br /&gt;
 # Assertation&lt;br /&gt;
 TARGET_OTA_ASSERT_DEVICE := rubens # codename&lt;br /&gt;
 &lt;br /&gt;
 # Bootloader&lt;br /&gt;
 TARGET_BOOTLOADER_BOARD_NAME := rubens # ro.product.board&lt;br /&gt;
 TARGET_NO_BOOTLOADER := true&lt;br /&gt;
 TARGET_USES_UEFI := true&lt;br /&gt;
 &lt;br /&gt;
 # Build Rule&lt;br /&gt;
 ALLOW_MISSING_DEPENDENCIES := true # 为了recovery不健全的依赖&lt;br /&gt;
 &lt;br /&gt;
 # Kernel - 注释会说明在boot/recovery/vendor_boot.json中对应的变量&lt;br /&gt;
 BOARD_BOOT_HEADER_VERSION := 4 # headerVersion&lt;br /&gt;
 BOARD_KERNEL_BASE := 0x3fff8000 # (kernelLoadAddr - 32KB) qcom设备base为0，且没有偏移(offset)&lt;br /&gt;
 BOARD_KERNEL_CMDLINE := bootopt=64S3,32N2,64N2 # cmdline&lt;br /&gt;
 BOARD_KERNEL_PAGESIZE := 4096 # pageSize&lt;br /&gt;
 BOARD_RAMDISK_OFFSET := 0x26f08000 # (ramdisk,loadAddr - BOARD_KERNEL_BASE)&lt;br /&gt;
 BOARD_KERNEL_TAGS_OFFSET := 0x07c88000 # (tagsLoadAddr - BOARD_KERNEL_BASE)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --ramdisk_offset $(BOARD_RAMDISK_OFFSET)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --tags_offset $(BOARD_KERNEL_TAGS_OFFSET)&lt;br /&gt;
 &lt;br /&gt;
 # Kernel - prebuilt&lt;br /&gt;
 TARGET_PREBUILT_KERNEL := $(DEVICE_PATH)/prebuilt/kernel # 预编译内核相对于android源码根目录的相对路径，vendor_boot机型不需要&lt;br /&gt;
 TARGET_PREBUILT_DTB := $(DEVICE_PATH)/prebuilt/dtb.img # 同上&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --dtb $(TARGET_PREBUILT_DTB)&lt;br /&gt;
 &lt;br /&gt;
 # Partitions&lt;br /&gt;
 BOARD_FLASH_BLOCK_SIZE := 262144 # (BOARD_KERNEL_PAGESIZE * 64)&lt;br /&gt;
 BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864 # boot/recovery/vendor_boot镜像的字节大小需原厂或手机完整提取出来的，不定义会报错&lt;br /&gt;
 BOARD_RECOVERYIMAGE_PARTITION_SIZE := 67108864 # 同上&lt;br /&gt;
 BOARD_VENDOR_ROOTIMAGE_PARTITION_SIZE := 67108864 # 同上&lt;br /&gt;
 BOARD_SYSTEMIMAGE_PARTITION_TYPE := ext4 # 分区类型，查看ramdisk中fstab定义的类型&lt;br /&gt;
 BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 TARGET_COPY_OUT_VENDOR := vendor # 定义vendor目录，例如copy专有blobs要用&lt;br /&gt;
 BOARD_SUPER_PARTITION_SIZE := 9126805504 # 可以通过blockdev --getsize64 /dev/block/bootdevice/by-name/super获取，需root，如果无法root可以直接使用这个值，不影响twrp启动，可以后续修正&lt;br /&gt;
 BOARD_SUPER_PARTITION_GROUPS := xiaomi_dynamic_partitions # xiaomi根据你获取资料的vendor替换，是一个动态分区组&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product system_ext odm vendor_dlkm odm_dlkm # 根据fstab内的定义，一般flag包含logical都属于动态分区组的一部分&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_SIZE := 9122611200 # (BOARD_SUPER_PARTITION_SIZE - 4MB)&lt;br /&gt;
 &lt;br /&gt;
 # Platform&lt;br /&gt;
 TARGET_BOARD_PLATFORM := mt6895 # ro.board.platform&lt;br /&gt;
 &lt;br /&gt;
 # Recovery - 基本通用的不影响启动&lt;br /&gt;
 BOARD_HAS_LARGE_FILESYSTEM := true&lt;br /&gt;
 TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888&lt;br /&gt;
 TARGET_USERIMAGES_USE_EXT4 := true&lt;br /&gt;
 TARGET_USERIMAGES_USE_F2FS := true&lt;br /&gt;
 &lt;br /&gt;
 # Treble&lt;br /&gt;
 BOARD_VNDK_VERSION := current # 声明VNDK版本&lt;br /&gt;
 &lt;br /&gt;
 # Vendor_boot recovery ramdisk&lt;br /&gt;
 BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true # 将recovery文件复制到vendor_boot&lt;br /&gt;
 &lt;br /&gt;
 # Boot recovery ramdisk&lt;br /&gt;
 #BOARD_USES_RECOVERY_AS_BOOT := true recovery ramdisk合并在boot中启用&lt;br /&gt;
 &lt;br /&gt;
 # Verified Boot&lt;br /&gt;
 BOARD_AVB_ENABLE := true&lt;br /&gt;
 BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flags 3&lt;br /&gt;
 &lt;br /&gt;
 # TWRP Configurations&lt;br /&gt;
 TW_DEFAULT_LANGUAGE := zh_CN # 默认为中文&lt;br /&gt;
 TW_EXTRA_LANGUAGES := true # 额外的语言&lt;br /&gt;
 TW_THEME := portrait_hdpi # 主题&lt;br /&gt;
 TW_INCLUDE_FASTBOOTD := true # 包括fastbootd，为动态分区&lt;br /&gt;
 &lt;br /&gt;
 # 其它flag还有很多，可以在https://xdaforums.com/t/twrp-flags-for-boardconfig-mk.3333970 查找，&lt;br /&gt;
 # 这篇文章也很老了，但我并不推荐twrp，所以flag我也不是很了解，多翻翻github:)&lt;br /&gt;
 &lt;br /&gt;
 # Debug&lt;br /&gt;
 TARGET_USES_LOGD := true # 调试flag&lt;br /&gt;
 TWRP_INCLUDE_LOGCAT := true&lt;br /&gt;
无注释版&lt;br /&gt;
 DEVICE_PATH := device/vendor/codename&lt;br /&gt;
 &lt;br /&gt;
 # Architecture&lt;br /&gt;
 TARGET_ARCH := arm64&lt;br /&gt;
 TARGET_ARCH_VARIANT := armv8-a&lt;br /&gt;
 TARGET_CPU_ABI := arm64-v8a&lt;br /&gt;
 TARGET_CPU_ABI2 :=&lt;br /&gt;
 TARGET_CPU_VARIANT := generic&lt;br /&gt;
 TARGET_CPU_VARIANT_RUNTIME := cortex-a55&lt;br /&gt;
 &lt;br /&gt;
 TARGET_2ND_ARCH := arm&lt;br /&gt;
 TARGET_2ND_ARCH_VARIANT := $(TARGET_ARCH_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_ABI := armeabi-v7a&lt;br /&gt;
 TARGET_2ND_CPU_ABI2 := armeabi&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT_RUNTIME := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 &lt;br /&gt;
 # Assertation&lt;br /&gt;
 TARGET_OTA_ASSERT_DEVICE := rubens&lt;br /&gt;
 &lt;br /&gt;
 # Bootloader&lt;br /&gt;
 TARGET_BOOTLOADER_BOARD_NAME := rubens&lt;br /&gt;
 TARGET_NO_BOOTLOADER := true&lt;br /&gt;
 TARGET_USES_UEFI := true&lt;br /&gt;
 &lt;br /&gt;
 # Build Rule&lt;br /&gt;
 ALLOW_MISSING_DEPENDENCIES := true&lt;br /&gt;
 &lt;br /&gt;
 # Kernel&lt;br /&gt;
 BOARD_BOOT_HEADER_VERSION := 4&lt;br /&gt;
 BOARD_KERNEL_BASE := 0x3fff8000&lt;br /&gt;
 BOARD_KERNEL_CMDLINE := bootopt=64S3,32N2,64N2&lt;br /&gt;
 BOARD_KERNEL_PAGESIZE := 4096&lt;br /&gt;
 BOARD_RAMDISK_OFFSET := 0x26f08000&lt;br /&gt;
 BOARD_KERNEL_TAGS_OFFSET := 0x07c88000&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --ramdisk_offset $(BOARD_RAMDISK_OFFSET)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --tags_offset $(BOARD_KERNEL_TAGS_OFFSET)&lt;br /&gt;
 BOARD_KERNEL_IMAGE_NAME := Image&lt;br /&gt;
 &lt;br /&gt;
 # Kernel - prebuilt&lt;br /&gt;
 TARGET_PREBUILT_DTB := $(DEVICE_PATH)/prebuilt/dtb.img&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --dtb $(TARGET_PREBUILT_DTB)&lt;br /&gt;
 &lt;br /&gt;
 # Partitions&lt;br /&gt;
 BOARD_FLASH_BLOCK_SIZE := 262144&lt;br /&gt;
 BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864&lt;br /&gt;
 BOARD_RECOVERYIMAGE_PARTITION_SIZE := 67108864&lt;br /&gt;
 BOARD_VENDOR_ROOTIMAGE_PARTITION_SIZE := 67108864&lt;br /&gt;
 BOARD_SYSTEMIMAGE_PARTITION_TYPE := ext4&lt;br /&gt;
 BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 TARGET_COPY_OUT_VENDOR := vendor&lt;br /&gt;
 BOARD_SUPER_PARTITION_SIZE := 9126805504&lt;br /&gt;
 BOARD_SUPER_PARTITION_GROUPS := xiaomi_dynamic_partitions&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product system_ext odm vendor_dlkm odm_dlkm&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_SIZE := 9122611200&lt;br /&gt;
 &lt;br /&gt;
 # Platform&lt;br /&gt;
 TARGET_BOARD_PLATFORM := mt6895&lt;br /&gt;
 &lt;br /&gt;
 # Recovery&lt;br /&gt;
 BOARD_HAS_LARGE_FILESYSTEM := true&lt;br /&gt;
 TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888&lt;br /&gt;
 TARGET_USERIMAGES_USE_EXT4 := true&lt;br /&gt;
 TARGET_USERIMAGES_USE_F2FS := true&lt;br /&gt;
 &lt;br /&gt;
 # Treble&lt;br /&gt;
 BOARD_VNDK_VERSION := current&lt;br /&gt;
 &lt;br /&gt;
 # Vendor_boot recovery ramdisk&lt;br /&gt;
 BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true&lt;br /&gt;
 &lt;br /&gt;
 # Boot recovery ramdisk&lt;br /&gt;
 #BOARD_USES_RECOVERY_AS_BOOT := true&lt;br /&gt;
 &lt;br /&gt;
 # Verified Boot&lt;br /&gt;
 BOARD_AVB_ENABLE := true&lt;br /&gt;
 BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flags 3&lt;br /&gt;
 &lt;br /&gt;
 # TWRP Configurations&lt;br /&gt;
 TW_DEFAULT_LANGUAGE := zh_CN&lt;br /&gt;
 TW_EXTRA_LANGUAGES := true&lt;br /&gt;
 TW_THEME := portrait_hdpi&lt;br /&gt;
 TW_INCLUDE_FASTBOOTD := true&lt;br /&gt;
 &lt;br /&gt;
 # Debug&lt;br /&gt;
 TARGET_USES_LOGD := true&lt;br /&gt;
 TWRP_INCLUDE_LOGCAT := true&lt;br /&gt;
这块写了好久我也不确定对不对，请各位指正，尤其是 Kernel 部分。&lt;br /&gt;
&lt;br /&gt;
==== 初始 device.mk 文件 ====&lt;br /&gt;
&lt;br /&gt;
* 准备好 prop.default&lt;br /&gt;
&lt;br /&gt;
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 DEVICE_PATH := device/xiaomi/rubens&lt;br /&gt;
 &lt;br /&gt;
 # API&lt;br /&gt;
 PRODUCT_SHIPPING_API_LEVEL := 31 # ro.board.first_api_level&lt;br /&gt;
 &lt;br /&gt;
 # A/B&lt;br /&gt;
 AB_OTA_UPDATER := true # 启用A/B无缝更新&lt;br /&gt;
 AB_OTA_PARTITIONS += \ # 定义A/B分区，参考fstab&lt;br /&gt;
     boot \&lt;br /&gt;
     dtbo \&lt;br /&gt;
     system \&lt;br /&gt;
     product \&lt;br /&gt;
     vendor \&lt;br /&gt;
     odm \&lt;br /&gt;
     odm_dlkm \&lt;br /&gt;
     vbmeta \&lt;br /&gt;
     vendor_boot \&lt;br /&gt;
     vendor_dlkm \&lt;br /&gt;
     vbmeta_system \&lt;br /&gt;
     vbmeta_vendor&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PACKAGES += \&lt;br /&gt;
     update_engine \&lt;br /&gt;
     update_engine_sideload \&lt;br /&gt;
     update_verifier \&lt;br /&gt;
     checkpoint_gc&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_system=true \&lt;br /&gt;
     POSTINSTALL_PATH_system=system/bin/mtk_plpath_utils \&lt;br /&gt;
     FILESYSTEM_TYPE_system=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_system=true&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_vendor=true \&lt;br /&gt;
     POSTINSTALL_PATH_vendor=bin/checkpoint_gc \&lt;br /&gt;
     FILESYSTEM_TYPE_vendor=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_vendor=true&lt;br /&gt;
 &lt;br /&gt;
 # Dynamic&lt;br /&gt;
 PRODUCT_USE_DYNAMIC_PARTITIONS := true # 动态分区&lt;br /&gt;
 &lt;br /&gt;
 # Soong namespaces&lt;br /&gt;
 PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH) # 命名空间&lt;br /&gt;
&lt;br /&gt;
* A/B 无缝更新部分高通和联发科不一样，联发科设备可以照抄，注意 system/bin/mtk_plpath_utils 就好。高通参考[https://github.com/sekaiacg/android_device_xiaomi_venus_TWRP/tree/android-13 venus twrp tree]，并且高通的[https://git.codelinaro.org/clo/la/platform/hardware/qcom/bootctrl bootctrl]和[https://git.codelinaro.org/clo/la/platform/vendor/qcom-opensource/recovery-ext gpt-utils]可以从 [[CLO]] 拿。&lt;br /&gt;
&lt;br /&gt;
无注释版&lt;br /&gt;
 PRODUCT_SHIPPING_API_LEVEL := 31&lt;br /&gt;
 &lt;br /&gt;
 # A/B&lt;br /&gt;
 AB_OTA_UPDATER := true&lt;br /&gt;
 AB_OTA_PARTITIONS += \&lt;br /&gt;
     boot \&lt;br /&gt;
     dtbo \&lt;br /&gt;
     system \&lt;br /&gt;
     product \&lt;br /&gt;
     vendor \&lt;br /&gt;
     odm \&lt;br /&gt;
     odm_dlkm \&lt;br /&gt;
     vbmeta \&lt;br /&gt;
     vendor_boot \&lt;br /&gt;
     vendor_dlkm \&lt;br /&gt;
     vbmeta_system \&lt;br /&gt;
     vbmeta_vendor&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PACKAGES += \&lt;br /&gt;
     update_engine \&lt;br /&gt;
     update_engine_sideload \&lt;br /&gt;
     update_verifier \&lt;br /&gt;
     checkpoint_gc&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_system=true \&lt;br /&gt;
     POSTINSTALL_PATH_system=system/bin/mtk_plpath_utils \&lt;br /&gt;
     FILESYSTEM_TYPE_system=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_system=true&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_vendor=true \&lt;br /&gt;
     POSTINSTALL_PATH_vendor=bin/checkpoint_gc \&lt;br /&gt;
     FILESYSTEM_TYPE_vendor=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_vendor=true&lt;br /&gt;
 &lt;br /&gt;
 # Dynamic&lt;br /&gt;
 PRODUCT_USE_DYNAMIC_PARTITIONS := true&lt;br /&gt;
 &lt;br /&gt;
 # Soong namespaces&lt;br /&gt;
 PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH)&lt;br /&gt;
&lt;br /&gt;
==== 初始 twrp_rubens.mk 文件 ====&lt;br /&gt;
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 # Inherit from common AOSP config&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk) # vab加载到vendor boot里使用&lt;br /&gt;
 &lt;br /&gt;
 # Inherit from TWRP product configuration&lt;br /&gt;
 $(call inherit-product, vendor/twrp/config/common.mk) # twrp-9分支改为onmi&lt;br /&gt;
 &lt;br /&gt;
 # Device specific configs&lt;br /&gt;
 $(call inherit-product, device/xiaomi/rubens/device.mk)&lt;br /&gt;
 &lt;br /&gt;
 # Device identifier&lt;br /&gt;
 PRODUCT_DEVICE := rubens # 设备型号&lt;br /&gt;
 PRODUCT_NAME := twrp_rubens # 设备名称&lt;br /&gt;
 PRODUCT_BRAND := Redmi # 自定义品牌，如果有&lt;br /&gt;
 PRODUCT_MODEL := 22041211AC # 产品最终用户可见名称&lt;br /&gt;
 PRODUCT_MANUFACTURER := Xiaomi # 制造商&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true # 对twrp启动vendor_boot支持&lt;br /&gt;
无注释版&lt;br /&gt;
 # Inherit from common AOSP config&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk) # vab加载到vendor boot里使用&lt;br /&gt;
 &lt;br /&gt;
 # Inherit from TWRP product configuration&lt;br /&gt;
 $(call inherit-product, vendor/twrp/config/common.mk)&lt;br /&gt;
 &lt;br /&gt;
 # Device specific configs&lt;br /&gt;
 $(call inherit-product, device/xiaomi/rubens/device.mk)&lt;br /&gt;
 &lt;br /&gt;
 # Device identifier&lt;br /&gt;
 PRODUCT_DEVICE := rubens&lt;br /&gt;
 PRODUCT_NAME := twrp_rubens&lt;br /&gt;
 PRODUCT_BRAND := Redmi&lt;br /&gt;
 PRODUCT_MODEL := 22041211AC&lt;br /&gt;
 PRODUCT_MANUFACTURER := Xiaomi&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true&lt;br /&gt;
&lt;br /&gt;
==== 初始 recovery 目录 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;拿出我们好久之前准备的 ramdisk 叭&amp;lt;/blockquote&amp;gt;通过tree命令我们可以查看 ramdisk 的树状图，可以很清晰的查看包含的文件&lt;br /&gt;
 ├── acct&lt;br /&gt;
 ├── apex&lt;br /&gt;
 ├── bin -&amp;gt; /system/bin&lt;br /&gt;
 ├── bugreports -&amp;gt; /data/user_de/0/com.android.shell/files/bugreports&lt;br /&gt;
 ├── config&lt;br /&gt;
 ├── d -&amp;gt; /sys/kernel/debug&lt;br /&gt;
 ├── data&lt;br /&gt;
 ├── data_mirror&lt;br /&gt;
 ├── debug_ramdisk&lt;br /&gt;
 ├── default.prop -&amp;gt; prop.default&lt;br /&gt;
 ├── dev&lt;br /&gt;
 ├── etc -&amp;gt; /system/etc&lt;br /&gt;
 ├── first_stage_ramdisk&lt;br /&gt;
 │   ├── fstab.emmc&lt;br /&gt;
 │   ├── fstab.mt6895&lt;br /&gt;
 │   └── system&lt;br /&gt;
 │       ├── bin&lt;br /&gt;
 │       │   ├── e2fsck&lt;br /&gt;
 │       │   ├── linker64&lt;br /&gt;
 │       │   ├── linker_asan64 -&amp;gt; linker64&lt;br /&gt;
 │       │   └── snapuserd&lt;br /&gt;
 │       └── lib64&lt;br /&gt;
 │           ├── ld-android.so&lt;br /&gt;
 │           ├── libbase.so&lt;br /&gt;
 │           ├── libc++.so&lt;br /&gt;
 │           ├── libc.so&lt;br /&gt;
 │           ├── libdl.so&lt;br /&gt;
 │           ├── libext2_blkid.so&lt;br /&gt;
 │           ├── libext2_com_err.so&lt;br /&gt;
 │           ├── libext2_e2p.so&lt;br /&gt;
 │           ├── libext2_quota.so&lt;br /&gt;
 │           ├── libext2_uuid.so&lt;br /&gt;
 │           ├── libext2fs.so&lt;br /&gt;
 │           ├── liblog.so&lt;br /&gt;
 │           ├── libm.so&lt;br /&gt;
 │           ├── libsparse.so&lt;br /&gt;
 │           └── libz.so&lt;br /&gt;
 ├── init -&amp;gt; /system/bin/init&lt;br /&gt;
 ├── init.recovery.hardware.rc&lt;br /&gt;
 ├── init.recovery.mt6895.rc&lt;br /&gt;
 └── 等等等等...省略大概1000个文件吧&lt;br /&gt;
&amp;lt;blockquote&amp;gt;因为避免教程时效性，我们尽可能选取 prebuilt 的办法，如 boot 和 mtk_plpath_utils 都采用预编译。&amp;lt;/blockquote&amp;gt;里面有很多文件是没用的，整理一下，对我们有用的只有这些&lt;br /&gt;
 .&lt;br /&gt;
 ├── first_stage_ramdisk&lt;br /&gt;
 │   ├── fstab.emmc&lt;br /&gt;
 │   └── fstab.mt6895&lt;br /&gt;
 ├── init.recovery.mt6895.rc&lt;br /&gt;
 ├── lib&lt;br /&gt;
 │   └── modules&lt;br /&gt;
 │       ├── 8250_mtk.ko&lt;br /&gt;
 │       ├── adapter_class.ko&lt;br /&gt;
 │       ├── adsp.ko&lt;br /&gt;
 │       ├── aee_aed.ko&lt;br /&gt;
 │       ├── aee_hangdet.ko&lt;br /&gt;
 │       ├── aee_rs.ko&lt;br /&gt;
 │       ├── blocktag.ko&lt;br /&gt;
 │       ├── bootprof.ko&lt;br /&gt;
 │       ├── bq28z610.ko&lt;br /&gt;
 │       ├── cache-parity.ko&lt;br /&gt;
 │       ├── cfg80211.ko&lt;br /&gt;
 │       ├── charger_class.ko&lt;br /&gt;
 │       └── 省略一百多个模块，这个目录里的东西全要&lt;br /&gt;
 └── system&lt;br /&gt;
     ├── bin&lt;br /&gt;
     │   └── mtk_plpath_utils&lt;br /&gt;
     ├── etc&lt;br /&gt;
     │   ├── init&lt;br /&gt;
     │   │   │── mtk-plpath-utils.rc&lt;br /&gt;
     │   │   └──hw&lt;br /&gt;
     │   │      └──init.rc&lt;br /&gt;
     │   ├── recovery.fstab&lt;br /&gt;
     │   ├── security&lt;br /&gt;
     │   │   └── otacerts.zip&lt;br /&gt;
     │   └── ueventd.rc&lt;br /&gt;
     └── lib64&lt;br /&gt;
         └── hw&lt;br /&gt;
             └── android.hardware.boot@1.0-impl-1.2-mtkimpl.so&lt;br /&gt;
将它们按照以下操作复制&lt;br /&gt;
&lt;br /&gt;
* first_stage_ramdisk --&amp;gt; recovery/root/first_stage_ramdisk&lt;br /&gt;
* init.recovery.mt6895.rc --&amp;gt; recovery/root/init.recovery.mt6895.rc&lt;br /&gt;
* lib --&amp;gt; recovery/root/lib&lt;br /&gt;
* system --&amp;gt; recovery/root/system (security 和 hw 文件夹里的内容作为备用，不要复制进去) 得到以下目录结构&lt;br /&gt;
&lt;br /&gt;
 .&lt;br /&gt;
 ├── Android.mk&lt;br /&gt;
 ├── AndroidProducts.mk&lt;br /&gt;
 ├── BoardConfig.mk&lt;br /&gt;
 ├── device.mk&lt;br /&gt;
 ├── prebuilt&lt;br /&gt;
 ├── recovery&lt;br /&gt;
 │   └── root&lt;br /&gt;
 │       ├── first_stage_ramdisk&lt;br /&gt;
 │       │   ├── fstab.emmc&lt;br /&gt;
 │       │   └── fstab.mt6895&lt;br /&gt;
 │       ├── init.recovery.mt6895.rc&lt;br /&gt;
 │       ├── lib&lt;br /&gt;
 │       │   └── modules&lt;br /&gt;
 │       │       ├── 8250_mtk.ko&lt;br /&gt;
 │       │       ├── adapter_class.ko&lt;br /&gt;
 │       │       ├── adsp.ko&lt;br /&gt;
 │       │       ├── aee_aed.ko&lt;br /&gt;
 │       │       ├── aee_hangdet.ko&lt;br /&gt;
 │       │       ├── aee_rs.ko&lt;br /&gt;
 │       │       ├── blocktag.ko&lt;br /&gt;
 │       │       └── 省略....&lt;br /&gt;
 │       └── system&lt;br /&gt;
 │           ├── bin&lt;br /&gt;
 │           │   └── mtk_plpath_utils&lt;br /&gt;
 │           ├── etc&lt;br /&gt;
 │           │   ├── recovery.fstab&lt;br /&gt;
 │           │   └── ueventd.rc&lt;br /&gt;
 │           └── lib64&lt;br /&gt;
 │               └── hw&lt;br /&gt;
 │                   └── android.hardware.boot@1.0-impl-1.2-mtkimpl.so&lt;br /&gt;
 └── twrp_rubens.mk&lt;br /&gt;
打开 init.recovery.mt6895.rc 添加&lt;br /&gt;
 on boot&lt;br /&gt;
     start health-hal-2-1&lt;br /&gt;
 &lt;br /&gt;
 on post-fs&lt;br /&gt;
     start boot-hal-1-2&lt;br /&gt;
例如&lt;br /&gt;
 on post-fs&lt;br /&gt;
     start boot-hal-1-2&lt;br /&gt;
 &lt;br /&gt;
 on init&lt;br /&gt;
     setprop sys.usb.configfs 1&lt;br /&gt;
     setprop sys.usb.controller &amp;quot;11201000.usb0&amp;quot;&lt;br /&gt;
     setprop sys.usb.ffs.aio_compat 1&lt;br /&gt;
 &lt;br /&gt;
 on fs &amp;amp;&amp;amp; property:ro.debuggable=0&lt;br /&gt;
     # distinguish USB shoulde connect or not, i.e. CDP vs SDP&lt;br /&gt;
     # set charging free due to it wait for USB activation&lt;br /&gt;
 &lt;br /&gt;
 on boot&lt;br /&gt;
     start health-hal-2-1&lt;br /&gt;
     exec u:r:update_engine:s0 root root -- /system/bin/mtk_plpath_utils&lt;br /&gt;
 &lt;br /&gt;
接下来可以开始编译咯~~&lt;br /&gt;
&lt;br /&gt;
==== 编译 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;编译前请检查注释是否全部删除&amp;lt;/blockquote&amp;gt;twrp 源码根目录执行&lt;br /&gt;
 . build/envsetup.sh&lt;br /&gt;
 lunch twrp_codename-eng # twrp-9为onmi&lt;br /&gt;
 mka vendorbootimg/bootimage/recoveryimage&lt;br /&gt;
不出意外的话一路绿灯，如果有报错的话请发邮箱至 1592501605@qq.com 咨询我&lt;br /&gt;
&lt;br /&gt;
产物在 out/target/product/codename/vendor_boot.img\boot.img\recovery.img&lt;br /&gt;
&lt;br /&gt;
手机重启到 fastboot 模式，使用 fastboot flash 刷写，例如&lt;br /&gt;
 fastboot flash vendor_boot /Users/xiaolegun/Downloads/vendor_boot.img&lt;br /&gt;
则输出&lt;br /&gt;
 ERROR: could not clear input pipe; result e0005000, ignoring...&lt;br /&gt;
 ERROR: could not clear output pipe; result e0005000, ignoring....&lt;br /&gt;
 Sending 'vendor_boot_a' (65536 KB)                 OKAY [  1.396s]&lt;br /&gt;
 Writing 'vendor_boot_a'                            OKAY [  0.167s]&lt;br /&gt;
 Finished. Total time: 1.625s&lt;br /&gt;
就可以重启按电源加音量上尝试了，我自己是一次点亮，但有 bug。&lt;br /&gt;
&lt;br /&gt;
==== 修 BUG ====&lt;br /&gt;
&lt;br /&gt;
===== 修复 USB =====&lt;br /&gt;
我看到 twrp 控制台有很多报错，第一步肯定是先获取日志，使用logcat命令获取，在此之前先使用adb devices检测一下设备 usb 是否工作正常。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~  adb devices          ✔  10208  10:05:31&lt;br /&gt;
 * daemon not running; starting now at tcp:5037&lt;br /&gt;
 * daemon started successfully&lt;br /&gt;
 List of devices attached&lt;br /&gt;
可以看到adb没有检测到设备，原因一般是 usb 的配置不对，但 usb 是好的。这时可以尝试关闭 mtp，再开启，如果电脑有反应，那么就可以继续下一步了。&lt;br /&gt;
&lt;br /&gt;
在设备树中的 recovery/root，创建 init.recovery.usb.rc 的文件&lt;br /&gt;
 touch recovery/root/init.recovery.usb.rc&lt;br /&gt;
并导入以下内容&lt;br /&gt;
 on property:sys.usb.config=mtp,adb&lt;br /&gt;
     start adbd&lt;br /&gt;
 &lt;br /&gt;
 on property:sys.usb.ffs.ready=1 &amp;amp;&amp;amp; property:sys.usb.config=mtp,adb&lt;br /&gt;
     write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration &amp;quot;mtp_adb&amp;quot;&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f3&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f4&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f5&lt;br /&gt;
     write /config/usb_gadget/g1/idVendor 0x18d1&lt;br /&gt;
     write /config/usb_gadget/g1/idProduct 0x2d08&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}&lt;br /&gt;
     setprop sys.usb.state ${sys.usb.config}&lt;br /&gt;
这是我从我维护的 MI 6X 的 device tree 拿过来的，可以在联发科设备上正常工作。这段 shell 的大致意思就是在 usb 配置节点写入 mtp 和 adb 同时工作的字符串，这样 adb 就能顺利工作了。&lt;br /&gt;
&lt;br /&gt;
此外打开原厂 init.rc 修正一下 usb 设备的 id&lt;br /&gt;
 # MIUI ADD: START&lt;br /&gt;
 import /init.recovery.hardware.rc&lt;br /&gt;
 import /miui.factoryreset.rc&lt;br /&gt;
 # END&lt;br /&gt;
 import /init.recovery.${ro.hardware}.rc&lt;br /&gt;
 &lt;br /&gt;
 ########### 省略一万字&lt;br /&gt;
 &lt;br /&gt;
 # MIUI ADD: START&lt;br /&gt;
 on property:sys.usb.config=mtp,adb &amp;amp;&amp;amp; property:sys.usb.configfs=0&lt;br /&gt;
     write /sys/class/android_usb/android0/enable 0&lt;br /&gt;
     write /sys/class/android_usb/android0/idVendor 2717&lt;br /&gt;
     write /sys/class/android_usb/android0/idProduct 904D&lt;br /&gt;
     write /sys/class/android_usb/android0/functions mtp,adb&lt;br /&gt;
     write /sys/class/android_usb/android0/enable 1&lt;br /&gt;
     setprop sys.usb.state  ${sys.usb.config}&lt;br /&gt;
 # END&lt;br /&gt;
将/sys/class/android_usb/android0/idVendor和write /sys/class/android_usb/android0/idProduct后面的 id 分别替换到/config/usb_gadget/g1/idVendor和/config/usb_gadget/g1/idProduct处理完就是这样的。&lt;br /&gt;
 on property:sys.usb.config=mtp,adb&lt;br /&gt;
     start adbd&lt;br /&gt;
 &lt;br /&gt;
 on property:sys.usb.ffs.ready=1 &amp;amp;&amp;amp; property:sys.usb.config=mtp,adb&lt;br /&gt;
     write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration &amp;quot;mtp_adb&amp;quot;&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f3&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f4&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f5&lt;br /&gt;
     write /config/usb_gadget/g1/idVendor 0x2717&lt;br /&gt;
     write /config/usb_gadget/g1/idProduct 0x904D&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}&lt;br /&gt;
     setprop sys.usb.state ${sys.usb.config}&lt;br /&gt;
接下来开机之后 adb 和 mtp 就能同时工作了。&lt;br /&gt;
&lt;br /&gt;
===== 修复 Resetprop =====&lt;br /&gt;
接下来就可以修复其它 bug 了，我看到控制台有一堆红色的报错:&lt;br /&gt;
 E:Unknown File System:'/mi_ext'&lt;br /&gt;
 E:Unable to override 'external_storage.projid.enabled' due to missing libresetprop&lt;br /&gt;
 挂载“/data”失败(Invalid argument)&lt;br /&gt;
这三个报错中第二个最好修，第一个次之，第三个与解密有关，放在另一个大章节讲。&lt;br /&gt;
&lt;br /&gt;
第二个报错只需要在 BoardConfig.mk 中添加&lt;br /&gt;
 # Tool&lt;br /&gt;
 TW_INCLUDE_RESETPROP := true&lt;br /&gt;
 TW_INCLUDE_LIBRESETPROP := true&lt;br /&gt;
不用编译测试直接秒杀&lt;br /&gt;
&lt;br /&gt;
===== 修复挂载 =====&lt;br /&gt;
 E:Unknown File System:'/mi_ext'&lt;br /&gt;
我们打开 recovery/root/system/etc 中的 recovery.fstab，发现里面有很多空格，我们先将它格式化一下，有实力的可以把后面的 flag 也对齐整理好。&lt;br /&gt;
&lt;br /&gt;
我比较没实力，简单格式化了一下，是这样的&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 341 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;command line&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 2&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot; 2&lt;br /&gt;
 # 173 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 system /system erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system /system ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 vendor /vendor erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor /vendor ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 mi_ext /mnt/vendor/mi_ext erofs ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 mi_ext /mnt/vendor/mi_ext ext4 ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 /mnt/vendor/mi_ext /mi_ext none ro,bind wait,nofail&lt;br /&gt;
 overlay /product/overlay overlay ro,lowerdir=/mnt/vendor/mi_ext/product/overlay/:/product/overlay check,nofail&lt;br /&gt;
 overlay /product/app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/app/:/product/app check,nofail&lt;br /&gt;
 overlay /product/priv-app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/priv-app/:/product/priv-app check,nofail&lt;br /&gt;
 overlay /product/lib overlay ro,lowerdir=/mnt/vendor/mi_ext/product/lib/:/product/lib check,nofail&lt;br /&gt;
 overlay /product/lib64 overlay ro,lowerdir=/mnt/vendor/mi_ext/product/lib64/:/product/lib64 check,nofail&lt;br /&gt;
 overlay /product/bin overlay ro,lowerdir=/mnt/vendor/mi_ext/product/bin/:/product/bin check,nofail&lt;br /&gt;
 overlay /product/framework overlay ro,lowerdir=/mnt/vendor/mi_ext/product/framework/:/product/framework check,nofail&lt;br /&gt;
 overlay /product/media overlay ro,lowerdir=/mnt/vendor/mi_ext/product/media/:/product/media check,nofail&lt;br /&gt;
 overlay /product/opcust overlay ro,lowerdir=/mnt/vendor/mi_ext/product/opcust/:/product/opcust check,nofail&lt;br /&gt;
 overlay /product/data-app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/data-app/:/product/data-app check,nofail&lt;br /&gt;
 overlay /product/etc/sysconfig overlay ro,lowerdir=/mnt/vendor/mi_ext/product/etc/sysconfig/:/product/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /product/etc/permissions overlay ro,lowerdir=/mnt/vendor/mi_ext/product/etc/permissions/:/product/etc/permissions check,nofail&lt;br /&gt;
 overlay /system/app overlay ro,lowerdir=/mnt/vendor/mi_ext/system/app/:/product/pangu/system/app/:/system/app check,nofail&lt;br /&gt;
 overlay /system/priv-app overlay ro,lowerdir=/mnt/vendor/mi_ext/system/priv-app/:/product/pangu/system/priv-app/:/system/priv-app check,nofail&lt;br /&gt;
 overlay /system/framework overlay ro,lowerdir=/product/pangu/system/framework/:/system/framework check,nofail&lt;br /&gt;
 overlay /system/etc/sysconfig overlay ro,lowerdir=/mnt/vendor/mi_ext/system/etc/sysconfig/:/system/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /system/etc/permissions overlay ro,lowerdir=/mnt/vendor/mi_ext/system/etc/permissions/:/product/pangu/system/etc/permissions/:/system/etc/permissions check,nofail&lt;br /&gt;
 system_ext /system_ext erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system_ext /system_ext ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 odm /odm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm /odm ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor_dlkm /vendor_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm_dlkm /odm_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,noflush_merge,fsync_mode=nobarrier,reserve_root=134217,resgid=1065,checkpoint_merge,gc_merge,inlinecrypt wait,check,formattable,quota,latemount,resize,reservedsize=128m,checkpoint=fs,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,fsverity&lt;br /&gt;
 /dev/block/by-name/rescue /cache ext4 noatime,nosuid,nodev,noauto_da_alloc,discard wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect1 /mnt/vendor/protect_f ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect2 /mnt/vendor/protect_s ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvdata /mnt/vendor/nvdata ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvcfg /mnt/vendor/nvcfg ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/persist /mnt/vendor/persist ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /devices/platform/soc/11240000.mmc* auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata&lt;br /&gt;
 /devices/platform/usb_xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /devices/platform/soc/11201000.usb0/11200000.xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /dev/block/by-name/frp /persistent emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/nvram /nvram emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/proinfo /proinfo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk /bootloader emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk2 /bootloader2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/para /para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/misc /misc emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot /boot emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_vendor /vbmeta_vendor emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_system /vbmeta_system emmc defaults first_stage_mount,nofail,slotselect,avb=vbmeta&lt;br /&gt;
 /dev/block/by-name/logo /logo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/expdb /expdb emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/seccfg /seccfg emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee1 /tee1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee2 /tee2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp1 /scp1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp2 /scp2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_1 /sspm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_2 /sspm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_1 /dpm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_2 /dpm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_1 /mcupm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_2 /mcupm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1img /md1img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1dsp /md1dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1arm7 /md1arm7 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md3img /md3img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz1 /gz1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz2 /gz2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/spmfw /spmfw emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/audio_dsp /audio_dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/pi_img /pi_img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot_para /boot_para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/odmdtbo /odmdtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dtbo /dtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/otp /otp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/vbmeta /vbmeta emmc defaults defaults&lt;br /&gt;
这里面有很多无用分区，我们在 twrp 中操作不到，但是我也是第一次适配 MTK 设备，所以不“瞎说”误人子弟了，先把 bug 修好。&lt;br /&gt;
&lt;br /&gt;
像 xiaomi 这样常见的挂载错误，我自己一般都是尝试把/mnt/vendor 使用 vscode 全部删除，让我们尝试一下。并且要把这一行删除，这行在我看来是重复定义（？而且也没指定分区格式。&lt;br /&gt;
 /mnt/vendor/mi_ext /mi_ext none ro,bind wait,nofail&lt;br /&gt;
整理完之后是这样的&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 341 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;command line&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 2&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot; 2&lt;br /&gt;
 # 173 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 system /system erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system /system ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 vendor /vendor erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor /vendor ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 mi_ext /mi_ext erofs ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 mi_ext /mi_ext ext4 ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 overlay /product/overlay overlay ro,lowerdir=/mi_ext/product/overlay/:/product/overlay check,nofail&lt;br /&gt;
 overlay /product/app overlay ro,lowerdir=/mi_ext/product/app/:/product/app check,nofail&lt;br /&gt;
 overlay /product/priv-app overlay ro,lowerdir=/mi_ext/product/priv-app/:/product/priv-app check,nofail&lt;br /&gt;
 overlay /product/lib overlay ro,lowerdir=/mi_ext/product/lib/:/product/lib check,nofail&lt;br /&gt;
 overlay /product/lib64 overlay ro,lowerdir=/mi_ext/product/lib64/:/product/lib64 check,nofail&lt;br /&gt;
 overlay /product/bin overlay ro,lowerdir=/mi_ext/product/bin/:/product/bin check,nofail&lt;br /&gt;
 overlay /product/framework overlay ro,lowerdir=/mi_ext/product/framework/:/product/framework check,nofail&lt;br /&gt;
 overlay /product/media overlay ro,lowerdir=/mi_ext/product/media/:/product/media check,nofail&lt;br /&gt;
 overlay /product/opcust overlay ro,lowerdir=/mi_ext/product/opcust/:/product/opcust check,nofail&lt;br /&gt;
 overlay /product/data-app overlay ro,lowerdir=/mi_ext/product/data-app/:/product/data-app check,nofail&lt;br /&gt;
 overlay /product/etc/sysconfig overlay ro,lowerdir=/mi_ext/product/etc/sysconfig/:/product/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /product/etc/permissions overlay ro,lowerdir=/mi_ext/product/etc/permissions/:/product/etc/permissions check,nofail&lt;br /&gt;
 overlay /system/app overlay ro,lowerdir=/mi_ext/system/app/:/product/pangu/system/app/:/system/app check,nofail&lt;br /&gt;
 overlay /system/priv-app overlay ro,lowerdir=/mi_ext/system/priv-app/:/product/pangu/system/priv-app/:/system/priv-app check,nofail&lt;br /&gt;
 overlay /system/framework overlay ro,lowerdir=/product/pangu/system/framework/:/system/framework check,nofail&lt;br /&gt;
 overlay /system/etc/sysconfig overlay ro,lowerdir=/mi_ext/system/etc/sysconfig/:/system/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /system/etc/permissions overlay ro,lowerdir=/mi_ext/system/etc/permissions/:/product/pangu/system/etc/permissions/:/system/etc/permissions check,nofail&lt;br /&gt;
 system_ext /system_ext erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system_ext /system_ext ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 odm /odm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm /odm ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor_dlkm /vendor_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm_dlkm /odm_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,noflush_merge,fsync_mode=nobarrier,reserve_root=134217,resgid=1065,checkpoint_merge,gc_merge,inlinecrypt wait,check,formattable,quota,latemount,resize,reservedsize=128m,checkpoint=fs,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,fsverity&lt;br /&gt;
 /dev/block/by-name/rescue /cache ext4 noatime,nosuid,nodev,noauto_da_alloc,discard wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect1 /protect_f ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect2 /protect_s ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvdata /nvdata ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvcfg /nvcfg ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/persist /persist ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /devices/platform/soc/11240000.mmc* auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata&lt;br /&gt;
 /devices/platform/usb_xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /devices/platform/soc/11201000.usb0/11200000.xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /dev/block/by-name/frp /persistent emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/nvram /nvram emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/proinfo /proinfo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk /bootloader emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk2 /bootloader2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/para /para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/misc /misc emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot /boot emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_vendor /vbmeta_vendor emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_system /vbmeta_system emmc defaults first_stage_mount,nofail,slotselect,avb=vbmeta&lt;br /&gt;
 /dev/block/by-name/logo /logo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/expdb /expdb emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/seccfg /seccfg emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee1 /tee1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee2 /tee2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp1 /scp1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp2 /scp2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_1 /sspm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_2 /sspm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_1 /dpm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_2 /dpm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_1 /mcupm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_2 /mcupm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1img /md1img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1dsp /md1dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1arm7 /md1arm7 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md3img /md3img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz1 /gz1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz2 /gz2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/spmfw /spmfw emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/audio_dsp /audio_dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/pi_img /pi_img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot_para /boot_para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/odmdtbo /odmdtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dtbo /dtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/otp /otp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/vbmeta /vbmeta emmc defaults defaults&lt;br /&gt;
让我们编译试一下，值得注意的是，twrp 每次更改最好删除 out 重新编译，不要使用如make installclean等命令，可能会开机黑屏或更改不生效。&lt;br /&gt;
&lt;br /&gt;
经过一分钟，编译好了，刷入，开机，启动！可以看见挂载成功被修好。&lt;br /&gt;
&lt;br /&gt;
===== 修复屏幕显示 =====&lt;br /&gt;
可以看到我们现在屏幕的顶部的时间被摄像头挖孔挡住了。我们使用两个偏移 Flag 来修复它。&lt;br /&gt;
&lt;br /&gt;
在 BoardConfig.mk 中，加入以下 flag&lt;br /&gt;
 TW_Y_OFFSET := 106 #导航栏向上&lt;br /&gt;
 TW_H_OFFSET := -106 #界面整体向下&lt;br /&gt;
&lt;br /&gt;
===== 修复振动 =====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;仅供参考，研究半天发现只有解密功能正常才能修振动，不然会冻屏！！！&lt;br /&gt;
&lt;br /&gt;
不一定正确，也不一定普遍，仅供指路&amp;lt;/blockquote&amp;gt;老设备一般都是正常的，不需要额外处理，新设备使用 aidl hal 需要我们自己处理一下让 service 正常工作。&lt;br /&gt;
&lt;br /&gt;
挂载 vendor，使用 twrp 的文件管理，在 vendor/etc/vintf/manifest 找到含有 vibrator 字样的文件。打开之后检查是否类似这样的文段&lt;br /&gt;
 &amp;lt;manifest version=&amp;quot;1.0&amp;quot; type=&amp;quot;device&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;hal format=&amp;quot;aidl&amp;quot; override=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
         &amp;lt;name&amp;gt;android.hardware.vibrator&amp;lt;/name&amp;gt;&lt;br /&gt;
         &amp;lt;fqname&amp;gt;IVibrator/vibratorfeature&amp;lt;/fqname&amp;gt;&lt;br /&gt;
     &amp;lt;/hal&amp;gt;&lt;br /&gt;
 &amp;lt;/manifest&amp;gt;&lt;br /&gt;
那恭喜你，找对了，我的文件名是&lt;br /&gt;
&lt;br /&gt;
vendor.xiaomi.hardware.vibratorfeature.service.xml&lt;br /&gt;
&lt;br /&gt;
将它使用adb pull放到电脑上自己方便的位置备用。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /vendor/etc/vintf/manifest/vendor.xiaomi.hardware.vibratorfeature.service.xml .&lt;br /&gt;
 /vendor/etc/vintf/manifest/vendor.xiao...ipped. 0.2 MB/s (1718 bytes in 0.009s)&lt;br /&gt;
不看扩展名，到 vendor/bin/hw/找到同名的 service 同样利用adb pull放电脑备用。比如我的叫&lt;br /&gt;
&lt;br /&gt;
vendor.xiaomi.hardware.vibratorfeature.service&lt;br /&gt;
&lt;br /&gt;
然后到 vendor/etc/init/找到同名.rc 文件，拉到电脑上，在里面加一条。并在定义 service 的最下面加上seclabel u:r:recovery:s0可以被 recovery 使用。&lt;br /&gt;
 on boot&lt;br /&gt;
     start service被定义的名字&lt;br /&gt;
例如&lt;br /&gt;
 on post-fs-data&lt;br /&gt;
     chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/f0_save&lt;br /&gt;
     chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/osc_save&lt;br /&gt;
     chown system system /sys/bus/i2c/drivers/aw8697_haptic/3-005a/osc_save&lt;br /&gt;
     # 省略一万字&lt;br /&gt;
 &lt;br /&gt;
 on boot&lt;br /&gt;
     start vibratorfeature-hal-service&lt;br /&gt;
 &lt;br /&gt;
 service vibratorfeature-hal-service /vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&lt;br /&gt;
     class hal&lt;br /&gt;
     user system&lt;br /&gt;
     group system input&lt;br /&gt;
     onrestart restart vibratorfeature&lt;br /&gt;
     seclabel u:r:recovery:s0&lt;br /&gt;
此外这种新设备在内核里还有振动模块需要加载，请到/vendor/modules/1.1/中寻找，例如我这台设备是haptic.ko，用 adb pull 拉取到电脑上，然后&lt;br /&gt;
&lt;br /&gt;
* haptic.ko --&amp;gt; recovery/root/vendor/modules/1.1&lt;br /&gt;
&lt;br /&gt;
至此所有必要的资料就准备好了。可能开机后仍然不工作，需要抓取 log 补缺失的 library，当然这是后话了。&lt;br /&gt;
&lt;br /&gt;
开干！&lt;br /&gt;
&lt;br /&gt;
在 BoardConfig.mk 中加入以下 flag&lt;br /&gt;
 TW_SUPPORT_INPUT_AIDL_HAPTICS := true&lt;br /&gt;
将备用文件按照以下操作复制&lt;br /&gt;
&lt;br /&gt;
* vendor.xiaomi.hardware.vibratorfeature.service.xml --&amp;gt; recovery/root/vendor/etc/vintf/manifest&lt;br /&gt;
* vendor.xiaomi.hardware.vibratorfeature.service --&amp;gt; recovery/root/vendor/bin/hw&lt;br /&gt;
* vendor.xiaomi.hardware.vibratorfeature.service.rc --&amp;gt; recovery/root/vendor/etc/init&lt;br /&gt;
&lt;br /&gt;
之后编译，刷入，开机，喜提冻屏......&lt;br /&gt;
&lt;br /&gt;
问题不大，使用adb logcat抓取日志&lt;br /&gt;
 adb logcat &amp;gt; log.log&lt;br /&gt;
打开 log，搜索F linker、linker、library、beginning of crash这几个关键词，我搜索第一个就出来了。&lt;br /&gt;
 F linker  : CANNOT LINK EXECUTABLE &amp;quot;/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&amp;quot;: library &amp;quot;android.hardware.vibrator-V1-ndk_platform.so&amp;quot; not found: needed by main executable&lt;br /&gt;
这段报错的意思就是vendor.xiaomi.hardware.vibratorfeature.service找不到android.hardware.vibrator-V1-ndk_platform.so这个库，所以无法正常工作。&lt;br /&gt;
&lt;br /&gt;
打开 BoardConfig.mk 加入以下 flag&lt;br /&gt;
 # Library&lt;br /&gt;
 TARGET_RECOVERY_DEVICE_MODULES += \&lt;br /&gt;
     android.hardware.vibrator-V1-ndk_platform.vendor&lt;br /&gt;
 &lt;br /&gt;
 TW_RECOVERY_ADDITIONAL_RELINK_LIBRARY_FILES += \&lt;br /&gt;
     $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.vibrator-V1-ndk_platform.so&lt;br /&gt;
再次编译尝试&lt;br /&gt;
&lt;br /&gt;
开机之后依然冻屏，继续抓 log，查找&lt;br /&gt;
 F linker  : CANNOT LINK EXECUTABLE &amp;quot;/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&amp;quot;: library &amp;quot;vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so&amp;quot; not found: needed by main executable&lt;br /&gt;
vendor.hardware.vibratorfeature字样和我们之前导入的文件长得差不多，一般都是供应商专有文件，所以去设备提取，路径在 vendor/lib64 里，虽然设备冻屏了，但我们可以用adb pull直接拉取到电脑。就像这样。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb shell mount /vendor&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /vendor/lib64/vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so .&lt;br /&gt;
 /vendor/lib64/vendor.hardware.vibratorfeature.IVi...led, 0 skipped. 14.7 MB/s (33552 bytes in 0.002s&lt;br /&gt;
将这个文件按照以下提示操作&lt;br /&gt;
&lt;br /&gt;
* vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so --&amp;gt; recovery/root/vendor/lib64&lt;br /&gt;
&lt;br /&gt;
继续编译测试&lt;br /&gt;
&lt;br /&gt;
还是冻屏，继续抓 log&lt;br /&gt;
 F linker  : CANNOT LINK EXECUTABLE &amp;quot;/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&amp;quot;: library &amp;quot;libtinyalsa.so&amp;quot; not found: needed by main executable&lt;br /&gt;
这个 library twrp 的源码中应该没有，去设备拿一个 prebuilt 吧&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb shell mount /system_root&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /system_root/system/lib64/libtinyalsa.so .&lt;br /&gt;
 /system_root/system/lib64/libtinyalsa.so: 1 file ...led, 0 skipped. 13.6 MB/s (45032 bytes in 0.003s&lt;br /&gt;
将这个文件按照以下提示操作&lt;br /&gt;
&lt;br /&gt;
* libtinyalsa.so --&amp;gt; recovery/root/system/lib64&lt;br /&gt;
&lt;br /&gt;
编译测试&lt;br /&gt;
&lt;br /&gt;
我艹了，还是冻屏，这次搜那几个关键词都搜不到了，搜vibrator看看这鬼东西报什么&lt;br /&gt;
 E vendor.xiaomi.hardware.vibratorfeature.service: fail to load lib : /vendor/lib64/libaachaptics.so&lt;br /&gt;
这次都直接给路径了，直接拿。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb shell mount /vendor&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /vendor/lib64/libaachaptics.so .&lt;br /&gt;
 /vendor/lib64/libaachaptics.so: 1 file pulled, 0 skipped. 15.8 MB/s (56232 bytes in 0.003s)&lt;br /&gt;
将这个文件按照以下提示操作&lt;br /&gt;
&lt;br /&gt;
* libaachaptics.so --&amp;gt; recovery/root/vendor/lib64&lt;br /&gt;
&lt;br /&gt;
至此应该没什么问题了，但是有个 flag 貌似要操作 data 内的东西，未解密会导致冻屏，所以等修完解密后再来修振动。&lt;br /&gt;
&lt;br /&gt;
==== 修复 CPU 温度 ====&lt;br /&gt;
使用adb shell + grep命令在手机节点里搜索 type 关键词。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~  adb shell 'grep &amp;quot;cp_master&amp;quot; /sys/class/thermal/*/type'&lt;br /&gt;
 /sys/class/thermal/thermal_zone54/type:cp_master&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~  adb shell 'grep &amp;quot;cpu&amp;quot; /sys/class/thermal/*/type'&lt;br /&gt;
 /sys/class/thermal/thermal_zone1/type:cpu_little1&lt;br /&gt;
 /sys/class/thermal/thermal_zone10/type:cpu_bigbig1&lt;br /&gt;
 /sys/class/thermal/thermal_zone11/type:cpu_big6&lt;br /&gt;
 /sys/class/thermal/thermal_zone12/type:cpu_bigbig2&lt;br /&gt;
 /sys/class/thermal/thermal_zone2/type:cpu_little2&lt;br /&gt;
 /sys/class/thermal/thermal_zone3/type:cpu_little3&lt;br /&gt;
 /sys/class/thermal/thermal_zone4/type:cpu_little4&lt;br /&gt;
 /sys/class/thermal/thermal_zone5/type:cpu_big1&lt;br /&gt;
 /sys/class/thermal/thermal_zone6/type:cpu_big2&lt;br /&gt;
 /sys/class/thermal/thermal_zone7/type:cpu_big3&lt;br /&gt;
 /sys/class/thermal/thermal_zone8/type:cpu_big4&lt;br /&gt;
 /sys/class/thermal/thermal_zone9/type:cpu_big5&lt;br /&gt;
我这里选用cp_master节点来读取温度。我的节点路径为/sys/class/thermal/thermal_zone54在后面添加 temp 来读取温度，你可以使用cat来检测节点是否可以正常读取温度&lt;br /&gt;
 adb shell 'cat /sys/class/thermal/thermal_zone54/temp'&lt;br /&gt;
如果返回如&lt;br /&gt;
 28000&lt;br /&gt;
这种类似的数值，那多半是没有问题的。&lt;br /&gt;
&lt;br /&gt;
我们在 BoardConfig.mk 中加入&lt;br /&gt;
 TW_CUSTOM_CPU_TEMP_PATH := &amp;quot;/sys/class/thermal/thermal_zone54/temp&amp;quot;&lt;br /&gt;
至此 cpu 温度就修复好了。&lt;br /&gt;
&lt;br /&gt;
== 后序 ==&lt;br /&gt;
这是我玩 Android 两年内第一次写关于 Android 的文章，内容和措辞可能不是很准确，再加上开学焦虑，租房因租金和房源不顺利，写的很乱，请各位指正。&lt;br /&gt;
&lt;br /&gt;
此外有什么不懂得，多翻github，善用github搜索，多看看大佬们是怎么解决的。&lt;br /&gt;
&lt;br /&gt;
解密等有空补，先补作业。&lt;br /&gt;
&lt;br /&gt;
== 参考资料 ==&lt;br /&gt;
[https://source.android.com/docs/setup/create/new-device?hl=zh-cn Google - 添加新设备]&lt;br /&gt;
&lt;br /&gt;
[https://source.android.com/docs/core/ota/ab?hl=zh-cn Google - A/B（无缝）系统更新]&lt;br /&gt;
&lt;br /&gt;
[https://blog.lynnrin.moe/posts/ROM-bringup-guide-prebuilt/#boardconfigmk Lynnrin - 快速上手 Android Custom ROM 适配 - Prebuilt Vendor]&lt;br /&gt;
&lt;br /&gt;
[https://source.android.com/docs/core/architecture/vintf?hl=zh-cn Google - 供应商接口对象]&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=Super_Empty&amp;diff=554</id>
		<title>Super Empty</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=Super_Empty&amp;diff=554"/>
		<updated>2024-02-20T04:09:49Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​修正&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Super empty =&lt;br /&gt;
&lt;br /&gt;
== 简介 ==&lt;br /&gt;
它是任何动态分区设备在系统构建时可选的产物。它一个定义了动态分区信息的空镜像。它的主要作用是为设备提供一个初始的分区表。&lt;br /&gt;
&lt;br /&gt;
对原生动态分区来说&lt;br /&gt;
&lt;br /&gt;
它自身包含了对逻辑分区的映射信息及逻辑分区大小。可以用于清除或更新super分区，比如后期重新分区逻辑分区大小。&lt;br /&gt;
&lt;br /&gt;
对改造动态分区来说&lt;br /&gt;
&lt;br /&gt;
它定义了维护者定义的设备自身分区和分区大小，将它们合并成一个大的“super”供刷入第三方ROM使用，甚至可以让老旧设备运行DSU。并且针对这类设备它的意义远不止类原生，对PT(Project Treble)也有帮助，有经验的维护者可以通过改造动态分区的方式让用户无需扩容即可体验深度定制UI。&lt;br /&gt;
&lt;br /&gt;
== 使用方法 ==&lt;br /&gt;
=== 原生动态分区 ===&lt;br /&gt;
 fastboot wipe-super super_empty.img的绝对路径&lt;br /&gt;
&lt;br /&gt;
=== 改造动态分区 ===&lt;br /&gt;
==== 类原生 ====&lt;br /&gt;
以我个人维护的小米6X(wayne)为例&lt;br /&gt;
&lt;br /&gt;
1.设备重启至fastboot&lt;br /&gt;
&lt;br /&gt;
2.连接电脑&lt;br /&gt;
&lt;br /&gt;
3.准备最新版本的adb工具包和维护者提供的super_empty.img和ROM包&lt;br /&gt;
&lt;br /&gt;
4.打开命令行进入工具包目录，输入fastboot wipe-super super_empty.img的绝对路径&lt;br /&gt;
&lt;br /&gt;
5.刷写完毕后继续刷入维护者提供的Recovery，fastboot flash recovery recovery.img的绝对路径&lt;br /&gt;
&lt;br /&gt;
6.重启设备至recovery&lt;br /&gt;
&lt;br /&gt;
7.选择格式化data(format data)&lt;br /&gt;
&lt;br /&gt;
8.连接电脑，使用adb sideload刷入ROM，adb sideload ROM包绝对路径&lt;br /&gt;
&lt;br /&gt;
==== GSI ====&lt;br /&gt;
改造动态分区之后，使用Aosp recovery或TWRP的fastbootd，刷入system分区，即可不需扩容也能使用上超过system物理空间大小的镜像。&lt;br /&gt;
&lt;br /&gt;
== 对开发者的一些帮助 ==&lt;br /&gt;
[https://github.com/jjpprrrr/device%20xiaomi%20sdm845-common/commits/thirteen 改造动态分区的commit(2022年9月22日)]&lt;br /&gt;
&lt;br /&gt;
对于在Mac上正常刷写super_empty在win或linux下不能正常刷写的情况，请检查device tree内定义的数值是否百分之一百匹配。&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=%E4%B8%BA%E6%96%B0%E8%AE%BE%E5%A4%87%E7%BC%96%E5%86%99Recovery_device_tree&amp;diff=550</id>
		<title>为新设备编写Recovery device tree</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=%E4%B8%BA%E6%96%B0%E8%AE%BE%E5%A4%87%E7%BC%96%E5%86%99Recovery_device_tree&amp;diff=550"/>
		<updated>2024-02-20T02:53:49Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​更正代码高亮格式&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= 为新设备编写 Recovery 的设备树 =&lt;br /&gt;
作者: Dark(xiaoleGun)&lt;br /&gt;
&lt;br /&gt;
时间: 2024.2.20&lt;br /&gt;
&lt;br /&gt;
协作者:&lt;br /&gt;
&lt;br /&gt;
== 一些自序 ==&lt;br /&gt;
这篇教程中可能有些不对的地方，请各位指正，我也刚接触 Android 设备测开发两年，而且只有在节假日的时候有空一个人瞎捣鼓，为了&amp;lt;s&amp;gt;薅 mjw 羊毛&amp;lt;/s&amp;gt;，故写这篇教程，而且我个人更推荐 Aosp Recovery 刷写第三方 ROM，TWRP 可能多多少少有些问题。Root 之类的不需要 TWRP 也可以，可以找到原机 boot 使用 Magisk 进行修补，也可以使用 KernelSU。另外我的语文功底不是很好，写不出辞藻，只能是北方地道的大白话，见谅哈 🤣///&lt;br /&gt;
&lt;br /&gt;
== 准备工作 ==&lt;br /&gt;
1.一颗勇敢的、不怕困难的强大心脏。&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;s&amp;gt;两颗心好勇敢 -- Falling in love&amp;lt;/s&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
2.电脑配置:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!硬件&lt;br /&gt;
!需求&lt;br /&gt;
|-&lt;br /&gt;
|CPU&lt;br /&gt;
|四核或更多&lt;br /&gt;
|-&lt;br /&gt;
|内存&lt;br /&gt;
|8G 或更多&lt;br /&gt;
|-&lt;br /&gt;
|硬盘&lt;br /&gt;
|至少 80G 空余空间&lt;br /&gt;
|-&lt;br /&gt;
|系统&lt;br /&gt;
|WSL 或实体 Linux，建议 Debian 系&lt;br /&gt;
|}&lt;br /&gt;
3.足够的空闲时间。&lt;br /&gt;
&lt;br /&gt;
4.Vscode 和 🤏Linux 知识储备&lt;br /&gt;
&lt;br /&gt;
5.一台完好无损的新设备。&lt;br /&gt;
&lt;br /&gt;
6.设备原厂的 boot/recovery/vendor_boot 镜像。(推荐 recovery 分区，因为里面包含一些启动必须的.rc(run command)，如果没有该分区，寻找包含官方 recovery 内容的分区。值得注意的是部分设备 recovery 合并到了 boot 中，或是存在于 vendor_boot）&lt;br /&gt;
&lt;br /&gt;
7.查看自己的设备出厂 Android 版本并确定用途，是用于官方 ROM 还是第三方类原生。出厂版本为 9 及以上的可以使用 twrp-11 及以上分支，9 以下使用 twrp-9 分支。&lt;br /&gt;
&lt;br /&gt;
== 配置环境 ==&lt;br /&gt;
&lt;br /&gt;
=== 安装依赖 ===&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt-get install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev liblz4-tool libncurses5 libncurses5-dev libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev xattr openjdk-11-jdk jq android-sdk-libsparse-utils python3 python2 repo&lt;br /&gt;
&lt;br /&gt;
必要时可以阅读[https://source.android.com/source/using-repo?hl=zh-cn Git 和 Repo]&lt;br /&gt;
&lt;br /&gt;
=== 配置 Git 和 Repo ===&lt;br /&gt;
安装完依赖后，在终端执行。&lt;br /&gt;
 git config --global user.name &amp;quot;your username&amp;quot;&lt;br /&gt;
 git config --global user.email &amp;quot;your email&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== 同步 TWRP 源码 ===&lt;br /&gt;
在自己方便的地方，建立一个目录。&lt;br /&gt;
 mkdir twrp&lt;br /&gt;
 cd twrp&lt;br /&gt;
根据自己在准备工作中确定的分支同步相应的源码。&lt;br /&gt;
&lt;br /&gt;
==== TWRP-9 ====&lt;br /&gt;
 repo init --depth=1 -u &amp;lt;nowiki&amp;gt;https://github.com/minimal-manifest-twrp/platform_manifest_twrp_omni.git&amp;lt;/nowiki&amp;gt; -b twrp-9.0&lt;br /&gt;
 repo sync&lt;br /&gt;
&lt;br /&gt;
==== TWRP-11 ====&lt;br /&gt;
 repo init --depth=1 -u &amp;lt;nowiki&amp;gt;https://github.com/minimal-manifest-twrp/platform_manifest_twrp_aosp.git&amp;lt;/nowiki&amp;gt; -b twrp-11&lt;br /&gt;
 repo sync&lt;br /&gt;
&lt;br /&gt;
==== TWRP-12.1 ====&lt;br /&gt;
 repo init --depth=1 -u &amp;lt;nowiki&amp;gt;https://github.com/minimal-manifest-twrp/platform_manifest_twrp_aosp.git&amp;lt;/nowiki&amp;gt; -b twrp-12.1&lt;br /&gt;
 repo sync&lt;br /&gt;
&lt;br /&gt;
== 编写设备树 ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;最基本的开机部分我通过 Redmi K50 做示例，并选取 TWRP-12.1 分支。&lt;br /&gt;
&lt;br /&gt;
解密部分会单独成一个章节并分为高通和联发科。&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 获取资料 ===&lt;br /&gt;
小米设备一般可以在[https://xiaomirom.com Xiaomirom]中的线刷包获取 boot/recovery/vendor_boot 镜像，其它设备请自行寻找。&lt;br /&gt;
&lt;br /&gt;
==== 安装工具和依赖 ====&lt;br /&gt;
将准备工作中准备的 boot/recovery/vendor_boot 镜像解包，可以用任何工具，我这里使用[https://github.com/cfig/Android_boot_image_editor Android_boot_image_editor]按照自述文件进行依赖安装操作：&lt;br /&gt;
&lt;br /&gt;
===== Mac(Intel) =====&lt;br /&gt;
 brew install lz4 xz dtc openjdk@17&lt;br /&gt;
 echo 'export PATH=&amp;quot;/usr/local/opt/openjdk@17/bin:$PATH&amp;quot;' &amp;gt;&amp;gt; ~/.zshrc&lt;br /&gt;
 source ~/.zshrc&lt;br /&gt;
&lt;br /&gt;
===== Linux: =====&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-17-jdk gcc g++ python3 python-is-python3 p7zip-full android-sdk-libsparse-utils erofs-utils&lt;br /&gt;
&lt;br /&gt;
===== Common: =====&lt;br /&gt;
 git clone &amp;lt;nowiki&amp;gt;https://github.com/cfig/Android_boot_image_editor&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 cd Android_boot_image_editor&lt;br /&gt;
&lt;br /&gt;
==== 解包 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;请注意&amp;quot;/&amp;quot;表示或的意思，请不要误以为是一个东西。&lt;br /&gt;
&lt;br /&gt;
如果不确定分区寻找的是否正确，请尝试将可以的分区进行解包，并查看其ramdisk内是否包含recovery字样的文件&amp;lt;/blockquote&amp;gt;将你准备好的boot/recovery/vendor_boot复制到该目录，你可以使用 GUI 或者 CLI。如:&lt;br /&gt;
 cp &amp;lt;出厂boot/recovery/vendor_boot的绝对路径&amp;gt; boot/recovery/vendor_boot.img&lt;br /&gt;
 ./gradlew unpack&lt;br /&gt;
我这里以 Redmi K50 为例&lt;br /&gt;
 10:12:13.188 [main] INFO  cfig.bootimg.v3.VendorBoot -&lt;br /&gt;
                         Unpack Summary of vendor_boot.img&lt;br /&gt;
 ┌───────────────────────────────────────┬──────────────────────────────────────┐&lt;br /&gt;
 │What                                   │Where                                 │&lt;br /&gt;
 └───────────────────────────────────────┴──────────────────────────────────────┘&lt;br /&gt;
 ┌───────────────────────────────────────┬──────────────────────────────────────┐&lt;br /&gt;
 │image info                             │build/unzip_boot/vendor_boot.json     │&lt;br /&gt;
 ├───────────────────────────────────────┼──────────────────────────────────────┤&lt;br /&gt;
 │ramdisk                                │build/unzip_boot/ramdisk.img.lz4      │&lt;br /&gt;
 │-- PLATFORM ramdisk[1/1]               │build/unzip_boot/ramdisk.1.lz4        │&lt;br /&gt;
 │------- extracted rootfs               │build/unzip_boot/root.1               │&lt;br /&gt;
 ├───────────────────────────────────────┼──────────────────────────────────────┤&lt;br /&gt;
 │dtb                                    │build/unzip_boot/dtb                  │&lt;br /&gt;
 ├───────────────────────────────────────┼──────────────────────────────────────┤&lt;br /&gt;
 │AVB info                               │build/unzip_boot/vendor_boot.avb.json │&lt;br /&gt;
 │\-- signing key                        │NONE                                  │&lt;br /&gt;
 └───────────────────────────────────────┴──────────────────────────────────────┘&lt;br /&gt;
 10:12:13.213 [main] WARN  cfig.packable.PackableLauncher - 'unpack' sequence completed&lt;br /&gt;
 &lt;br /&gt;
 BUILD SUCCESSFUL in 2s&lt;br /&gt;
解包成功后终端会打印出以上信息，其中包含vendor_boot目录结构，我们只需要ramdisk里的部分内容就好了。&lt;br /&gt;
 ls build/unzip_boot/root.1 # 请根据自己的分区和设备判断ramdisk的命名，一般都直接是ramdisk&lt;br /&gt;
不出意外的话会输出以下内容&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/dump/bootedit   master ?  ls build/unzip_boot/root.1&lt;br /&gt;
 acct                         oem&lt;br /&gt;
 apex                         plat_file_contexts&lt;br /&gt;
 bin                          plat_property_contexts&lt;br /&gt;
 bugreports                   postinstall&lt;br /&gt;
 config                       proc&lt;br /&gt;
 d                            product&lt;br /&gt;
 data                         product_file_contexts&lt;br /&gt;
 data_mirror                  product_property_contexts&lt;br /&gt;
 debug_ramdisk                prop.default&lt;br /&gt;
 default.prop                 res&lt;br /&gt;
 dev                          sdcard&lt;br /&gt;
 etc                          second_stage_resources&lt;br /&gt;
 first_stage_ramdisk          sepolicy&lt;br /&gt;
 init                         storage&lt;br /&gt;
 init.recovery.hardware.rc    sys&lt;br /&gt;
 init.recovery.mt6895.rc      system&lt;br /&gt;
 lib                          system_ext&lt;br /&gt;
 linkerconfig                 system_ext_file_contexts&lt;br /&gt;
 miui.factoryreset.fstab      system_ext_property_contexts&lt;br /&gt;
 miui.factoryreset.rc         tmp&lt;br /&gt;
 mnt                          vendor&lt;br /&gt;
 odm                          vendor_dlkm&lt;br /&gt;
 odm_dlkm                     vendor_file_contexts&lt;br /&gt;
 odm_file_contexts            vendor_property_contexts&lt;br /&gt;
 odm_property_contexts&lt;br /&gt;
如果包含 init.recovery*的字样，恭喜你成功找到了正确的分区。将这个目录复制到一个自己方便的地方。&lt;br /&gt;
&lt;br /&gt;
至此资料已经大致齐全了，解密的资料会在解密章节来讲解如何获取。&lt;br /&gt;
&lt;br /&gt;
=== 初始化目录结构 ===&lt;br /&gt;
在 twrp 源码根目录输入&lt;br /&gt;
 mkdir -p device/vendor/codename&lt;br /&gt;
 mkdir -p device/vendor/codename/recovery/root&lt;br /&gt;
 cd device/vendor/codename&lt;br /&gt;
vendor指的是供应商，如 xiaomi、oneplus、huawei、vivo、realme。&lt;br /&gt;
&lt;br /&gt;
codename指的是设备代号，小米设备可以在[https://xiaomirom.com Xiaomirom]查询，其它设备自行查询亦或是在开发者选项勾选 USB 调试通过 adb 尝试获取。&lt;br /&gt;
 adb shell getprop ro.product.manufacturer # 供应商&lt;br /&gt;
 adb shell getprop ro.product.device # 设备代号&lt;br /&gt;
我的 Redmi K50 会打印以下信息&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/dump/bootedit   master ?  adb shell getprop ro.product.manufacturer&lt;br /&gt;
 Xiaomi # 无论打印出来的内容是大写还是小写，在目录结构中我们都采用小写&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/dump/bootedit   master ?  adb shell getprop ro.product.device&lt;br /&gt;
 rubens&lt;br /&gt;
我的 IQOO NEO5 Lite 会打印以下信息&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  adb shell getprop ro.product.manufacturer&lt;br /&gt;
 vivo&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  adb shell getprop ro.product.device&lt;br /&gt;
 PD2118&lt;br /&gt;
一般只要不是山寨机，小作坊出来的机子，用这两条命令应该是可以正确获取的。&lt;br /&gt;
&lt;br /&gt;
=== 初始化构建时必要的文件 ===&lt;br /&gt;
无论是 AOSP device tree 亦或是 TWRP device tree 都基本类似于以下结构。&lt;br /&gt;
 /&lt;br /&gt;
 ├── prebuilt           (存放kernel、dtb等预编译文件) # AOSP device tree若使用build kernel则没有该目录&lt;br /&gt;
 ├── recovery/root      (存放一些.rc和解密blobs) # 一般用于Recovery device tree&lt;br /&gt;
 ├── Android.mk         (Android构建系统首先会检查每个目录的Android.mk，里面包含一些判断，由它包括其所在目录中所有Makefile)&lt;br /&gt;
 ├── AndroidProducts.mk (声明产品的Makefile和lunch时可用的构建类型)&lt;br /&gt;
 ├── BoardConfig.mk     (板载配置文件，定义了主板必要的Flag)&lt;br /&gt;
 ├── device.mk          (声明设备所需的文件和模块)&lt;br /&gt;
 └── &amp;lt;ROM&amp;gt;_codename.mk  (声明产品特定信息，例如名称、品牌和型号，引用device.mk等) # ROM就比如lineage、arrow等，编译twrp就直接写twrp，twrp-9分支要写onmi&lt;br /&gt;
我们把这样的结构称为骨架树(skeleton tree)。&lt;br /&gt;
&lt;br /&gt;
接下来我们按照以上结构为自己的设备写一份 Recovery device tree。&lt;br /&gt;
&lt;br /&gt;
在终端使用touch命令创建必要的文件。&lt;br /&gt;
 touch Android.mk AndroidProducts.mk BoardConfig.mk device.mk twrp_rubens.mk&lt;br /&gt;
 ls .&lt;br /&gt;
不出意外的话会打印出以下信息&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  touch Android.mk AndroidProducts.mk BoardConfig.mk device.mk twrp_rubens.mk&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  ls .&lt;br /&gt;
 Android.mk         BoardConfig.mk     prebuilt           twrp_rubens.mk&lt;br /&gt;
 AndroidProducts.mk device.mk          recovery&lt;br /&gt;
可以下一步了~&lt;br /&gt;
&lt;br /&gt;
==== 初始 Android.mk 文件 ====&lt;br /&gt;
打开 Vscode 并打开设备树目录，你足够强也可以使用 nano、vim 编辑。&lt;br /&gt;
&lt;br /&gt;
选中 Android.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 LOCAL_PATH := $(call my-dir)&lt;br /&gt;
 &lt;br /&gt;
 ifeq ($(TARGET_DEVICE),codename)&lt;br /&gt;
 include $(call all-subdir-makefiles,$(LOCAL_PATH))&lt;br /&gt;
 endif&lt;br /&gt;
&lt;br /&gt;
* codename是需要你修改的部分&lt;br /&gt;
&lt;br /&gt;
我修改后是这样的&lt;br /&gt;
 LOCAL_PATH := $(call my-dir)&lt;br /&gt;
 &lt;br /&gt;
 ifeq ($(TARGET_DEVICE),rubens)&lt;br /&gt;
 include $(call all-subdir-makefiles,$(LOCAL_PATH))&lt;br /&gt;
 endif&lt;br /&gt;
&lt;br /&gt;
==== 初始 AndroidProducts.mk 文件 ====&lt;br /&gt;
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 PRODUCT_MAKEFILES := \&lt;br /&gt;
     $(LOCAL_DIR)/&amp;lt;ROM&amp;gt;_&amp;lt;codename&amp;gt;.mk&lt;br /&gt;
 &lt;br /&gt;
 COMMON_LUNCH_CHOICES := \&lt;br /&gt;
     &amp;lt;ROM&amp;gt;_&amp;lt;codename&amp;gt;-eng&lt;br /&gt;
我修改后是这样的&lt;br /&gt;
 PRODUCT_MAKEFILES := \&lt;br /&gt;
     $(LOCAL_DIR)/twrp_rubens.mk&lt;br /&gt;
 &lt;br /&gt;
 COMMON_LUNCH_CHOICES := \&lt;br /&gt;
     twrp_rubens-eng&lt;br /&gt;
&lt;br /&gt;
==== 初始 BoardConfig.mk 文件 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;将之前准备的ramdisk文件夹用新窗口打开 1.找到目录下的 prop.default 或含 prop 字样的文件。以下注释类似 ro.*.*的就是从 prop 中获取的 2.解包 boot/recovery/vendor_boot 的 json&lt;br /&gt;
&lt;br /&gt;
例如 build/unzip_boot/boot.json&amp;lt;/blockquote&amp;gt;选中 BoardConfig.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 DEVICE_PATH := device/vendor/codename&lt;br /&gt;
 &lt;br /&gt;
 # Architecture&lt;br /&gt;
 TARGET_ARCH := arm64 # ro.bionic.arch&lt;br /&gt;
 TARGET_ARCH_VARIANT := armv8-a # 64位默认变体&lt;br /&gt;
 TARGET_CPU_ABI := arm64-v8a # ro.vendor.product.cpu.abilist64 (至少在小米设备上没有找到ro.product.cpu.abilist)&lt;br /&gt;
 TARGET_CPU_ABI2 := # 64位留空&lt;br /&gt;
 TARGET_CPU_VARIANT := generic # 默认一般都是通用&lt;br /&gt;
 TARGET_CPU_VARIANT_RUNTIME := cortex-a55 # ro.bionic.cpu_variant&lt;br /&gt;
 &lt;br /&gt;
 TARGET_2ND_ARCH := arm # ro.bionic.2nd_arch&lt;br /&gt;
 TARGET_2ND_ARCH_VARIANT := $(TARGET_ARCH_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_ABI := armeabi-v7a # ro.vendor.product.cpu.abilist32第一个&lt;br /&gt;
 TARGET_2ND_CPU_ABI2 := armeabi # ro.vendor.product.cpu.abilist32第二个&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT_RUNTIME := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 &lt;br /&gt;
 # Assertation&lt;br /&gt;
 TARGET_OTA_ASSERT_DEVICE := rubens # codename&lt;br /&gt;
 &lt;br /&gt;
 # Bootloader&lt;br /&gt;
 TARGET_BOOTLOADER_BOARD_NAME := rubens # ro.product.board&lt;br /&gt;
 TARGET_NO_BOOTLOADER := true&lt;br /&gt;
 TARGET_USES_UEFI := true&lt;br /&gt;
 &lt;br /&gt;
 # Build Rule&lt;br /&gt;
 ALLOW_MISSING_DEPENDENCIES := true # 为了recovery不健全的依赖&lt;br /&gt;
 &lt;br /&gt;
 # Kernel - 注释会说明在boot/recovery/vendor_boot.json中对应的变量&lt;br /&gt;
 BOARD_BOOTIMG_HEADER_VERSION := 4 # headerVersion&lt;br /&gt;
 BOARD_KERNEL_BASE := 0x3fff8000 # (kernelLoadAddr - 32KB) qcom设备base为0，且没有偏移(offset)&lt;br /&gt;
 BOARD_KERNEL_CMDLINE := bootopt=64S3,32N2,64N2 # cmdline&lt;br /&gt;
 BOARD_KERNEL_PAGESIZE := 4096 # pageSize&lt;br /&gt;
 BOARD_RAMDISK_OFFSET := 0x26f08000 # (ramdisk,loadAddr - BOARD_KERNEL_BASE)&lt;br /&gt;
 BOARD_KERNEL_TAGS_OFFSET := 0x07c88000 # (tagsLoadAddr - BOARD_KERNEL_BASE)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOTIMG_HEADER_VERSION)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --ramdisk_offset $(BOARD_RAMDISK_OFFSET)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --tags_offset $(BOARD_KERNEL_TAGS_OFFSET)&lt;br /&gt;
 &lt;br /&gt;
 # Kernel - prebuilt&lt;br /&gt;
 TARGET_PREBUILT_KERNEL := $(DEVICE_PATH)/prebuilt/kernel # 预编译内核相对于android源码根目录的相对路径，vendor_boot机型不需要&lt;br /&gt;
 TARGET_PREBUILT_DTB := $(DEVICE_PATH)/prebuilt/dtb.img # 同上&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --dtb $(TARGET_PREBUILT_DTB)&lt;br /&gt;
 &lt;br /&gt;
 # Partitions&lt;br /&gt;
 BOARD_FLASH_BLOCK_SIZE := 262144 # (BOARD_KERNEL_PAGESIZE * 64)&lt;br /&gt;
 BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864 # boot/recovery/vendor_boot镜像的字节大小需原厂或手机完整提取出来的，不定义会报错&lt;br /&gt;
 BOARD_RECOVERYIMAGE_PARTITION_SIZE := 67108864 # 同上&lt;br /&gt;
 BOARD_VENDOR_ROOTIMAGE_PARTITION_SIZE := 67108864 # 同上&lt;br /&gt;
 BOARD_SYSTEMIMAGE_PARTITION_TYPE := ext4 # 分区类型，查看ramdisk中fstab定义的类型&lt;br /&gt;
 BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 TARGET_COPY_OUT_VENDOR := vendor # 定义vendor目录，例如copy专有blobs要用&lt;br /&gt;
 BOARD_SUPER_PARTITION_SIZE := 9126805504 # 可以通过blockdev --getsize64 /dev/block/bootdevice/by-name/super获取，需root，如果无法root可以直接使用这个值，不影响twrp启动，可以后续修正&lt;br /&gt;
 BOARD_SUPER_PARTITION_GROUPS := xiaomi_dynamic_partitions # xiaomi根据你获取资料的vendor替换，是一个动态分区组&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product system_ext odm vendor_dlkm odm_dlkm # 根据fstab内的定义，一般flag包含logical都属于动态分区组的一部分&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_SIZE := 9122611200 # (BOARD_SUPER_PARTITION_SIZE - 4MB)&lt;br /&gt;
 &lt;br /&gt;
 # Platform&lt;br /&gt;
 TARGET_BOARD_PLATFORM := mt6895 # ro.board.platform&lt;br /&gt;
 &lt;br /&gt;
 # Recovery - 基本通用的不影响启动&lt;br /&gt;
 BOARD_HAS_LARGE_FILESYSTEM := true&lt;br /&gt;
 TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888&lt;br /&gt;
 TARGET_USERIMAGES_USE_EXT4 := true&lt;br /&gt;
 TARGET_USERIMAGES_USE_F2FS := true&lt;br /&gt;
 &lt;br /&gt;
 # Treble&lt;br /&gt;
 BOARD_VNDK_VERSION := current # 声明VNDK版本&lt;br /&gt;
 &lt;br /&gt;
 # Vendor_boot recovery ramdisk&lt;br /&gt;
 BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true # 将recovery文件复制到vendor_boot&lt;br /&gt;
 &lt;br /&gt;
 # Boot recovery ramdisk&lt;br /&gt;
 #BOARD_USES_RECOVERY_AS_BOOT := true recovery ramdisk合并在boot中启用&lt;br /&gt;
 &lt;br /&gt;
 # Verified Boot&lt;br /&gt;
 BOARD_AVB_ENABLE := true&lt;br /&gt;
 BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flags 3&lt;br /&gt;
 &lt;br /&gt;
 # TWRP Configurations&lt;br /&gt;
 TW_DEFAULT_LANGUAGE := zh_CN # 默认为中文&lt;br /&gt;
 TW_EXTRA_LANGUAGES := true # 额外的语言&lt;br /&gt;
 TW_THEME := portrait_hdpi # 主题&lt;br /&gt;
 TW_INCLUDE_FASTBOOTD := true # 包括fastbootd，为动态分区&lt;br /&gt;
 &lt;br /&gt;
 # 其它flag还有很多，可以在https://xdaforums.com/t/twrp-flags-for-boardconfig-mk.3333970 查找，&lt;br /&gt;
 # 这篇文章也很老了，但我并不推荐twrp，所以flag我也不是很了解，多翻翻github:)&lt;br /&gt;
 &lt;br /&gt;
 # Debug&lt;br /&gt;
 TARGET_USES_LOGD := true # 调试flag&lt;br /&gt;
 TWRP_INCLUDE_LOGCAT := true&lt;br /&gt;
无注释版&lt;br /&gt;
 DEVICE_PATH := device/vendor/codename&lt;br /&gt;
 &lt;br /&gt;
 # Architecture&lt;br /&gt;
 TARGET_ARCH := arm64&lt;br /&gt;
 TARGET_ARCH_VARIANT := armv8-a&lt;br /&gt;
 TARGET_CPU_ABI := arm64-v8a&lt;br /&gt;
 TARGET_CPU_ABI2 :=&lt;br /&gt;
 TARGET_CPU_VARIANT := generic&lt;br /&gt;
 TARGET_CPU_VARIANT_RUNTIME := cortex-a55&lt;br /&gt;
 &lt;br /&gt;
 TARGET_2ND_ARCH := arm&lt;br /&gt;
 TARGET_2ND_ARCH_VARIANT := $(TARGET_ARCH_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_ABI := armeabi-v7a&lt;br /&gt;
 TARGET_2ND_CPU_ABI2 := armeabi&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT_RUNTIME := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 &lt;br /&gt;
 # Assertation&lt;br /&gt;
 TARGET_OTA_ASSERT_DEVICE := rubens&lt;br /&gt;
 &lt;br /&gt;
 # Bootloader&lt;br /&gt;
 TARGET_BOOTLOADER_BOARD_NAME := rubens&lt;br /&gt;
 TARGET_NO_BOOTLOADER := true&lt;br /&gt;
 TARGET_USES_UEFI := true&lt;br /&gt;
 &lt;br /&gt;
 # Build Rule&lt;br /&gt;
 ALLOW_MISSING_DEPENDENCIES := true&lt;br /&gt;
 &lt;br /&gt;
 # Kernel&lt;br /&gt;
 BOARD_BOOT_HEADER_VERSION := 4&lt;br /&gt;
 BOARD_KERNEL_BASE := 0x3fff8000&lt;br /&gt;
 BOARD_KERNEL_CMDLINE := bootopt=64S3,32N2,64N2&lt;br /&gt;
 BOARD_KERNEL_PAGESIZE := 4096&lt;br /&gt;
 BOARD_RAMDISK_OFFSET := 0x26f08000&lt;br /&gt;
 BOARD_KERNEL_TAGS_OFFSET := 0x07c88000&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --ramdisk_offset $(BOARD_RAMDISK_OFFSET)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --tags_offset $(BOARD_KERNEL_TAGS_OFFSET)&lt;br /&gt;
 BOARD_KERNEL_IMAGE_NAME := Image&lt;br /&gt;
 &lt;br /&gt;
 # Kernel - prebuilt&lt;br /&gt;
 TARGET_PREBUILT_DTB := $(DEVICE_PATH)/prebuilt/dtb.img&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --dtb $(TARGET_PREBUILT_DTB)&lt;br /&gt;
 &lt;br /&gt;
 # Partitions&lt;br /&gt;
 BOARD_FLASH_BLOCK_SIZE := 262144&lt;br /&gt;
 BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864&lt;br /&gt;
 BOARD_RECOVERYIMAGE_PARTITION_SIZE := 67108864&lt;br /&gt;
 BOARD_VENDOR_ROOTIMAGE_PARTITION_SIZE := 67108864&lt;br /&gt;
 BOARD_SYSTEMIMAGE_PARTITION_TYPE := ext4&lt;br /&gt;
 BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 TARGET_COPY_OUT_VENDOR := vendor&lt;br /&gt;
 BOARD_SUPER_PARTITION_SIZE := 9126805504&lt;br /&gt;
 BOARD_SUPER_PARTITION_GROUPS := xiaomi_dynamic_partitions&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product system_ext odm vendor_dlkm odm_dlkm&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_SIZE := 9122611200&lt;br /&gt;
 &lt;br /&gt;
 # Platform&lt;br /&gt;
 TARGET_BOARD_PLATFORM := mt6895&lt;br /&gt;
 &lt;br /&gt;
 # Recovery&lt;br /&gt;
 BOARD_HAS_LARGE_FILESYSTEM := true&lt;br /&gt;
 TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888&lt;br /&gt;
 TARGET_USERIMAGES_USE_EXT4 := true&lt;br /&gt;
 TARGET_USERIMAGES_USE_F2FS := true&lt;br /&gt;
 &lt;br /&gt;
 # Treble&lt;br /&gt;
 BOARD_VNDK_VERSION := current&lt;br /&gt;
 &lt;br /&gt;
 # Vendor_boot recovery ramdisk&lt;br /&gt;
 BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true&lt;br /&gt;
 &lt;br /&gt;
 # Boot recovery ramdisk&lt;br /&gt;
 #BOARD_USES_RECOVERY_AS_BOOT := true&lt;br /&gt;
 &lt;br /&gt;
 # Verified Boot&lt;br /&gt;
 BOARD_AVB_ENABLE := true&lt;br /&gt;
 BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flags 3&lt;br /&gt;
 &lt;br /&gt;
 # TWRP Configurations&lt;br /&gt;
 TW_DEFAULT_LANGUAGE := zh_CN&lt;br /&gt;
 TW_EXTRA_LANGUAGES := true&lt;br /&gt;
 TW_THEME := portrait_hdpi&lt;br /&gt;
 TW_INCLUDE_FASTBOOTD := true&lt;br /&gt;
 &lt;br /&gt;
 # Debug&lt;br /&gt;
 TARGET_USES_LOGD := true&lt;br /&gt;
 TWRP_INCLUDE_LOGCAT := true&lt;br /&gt;
这块写了好久我也不确定对不对，请各位指正，尤其是 Kernel 部分。&lt;br /&gt;
&lt;br /&gt;
==== 初始 device.mk 文件 ====&lt;br /&gt;
&lt;br /&gt;
* 准备好 prop.default&lt;br /&gt;
&lt;br /&gt;
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 DEVICE_PATH := device/xiaomi/rubens&lt;br /&gt;
 &lt;br /&gt;
 # API&lt;br /&gt;
 PRODUCT_SHIPPING_API_LEVEL := 31 # ro.board.first_api_level&lt;br /&gt;
 &lt;br /&gt;
 # A/B&lt;br /&gt;
 AB_OTA_UPDATER := true # 启用A/B无缝更新&lt;br /&gt;
 AB_OTA_PARTITIONS += \ # 定义A/B分区，参考fstab&lt;br /&gt;
     boot \&lt;br /&gt;
     dtbo \&lt;br /&gt;
     system \&lt;br /&gt;
     product \&lt;br /&gt;
     vendor \&lt;br /&gt;
     odm \&lt;br /&gt;
     odm_dlkm \&lt;br /&gt;
     vbmeta \&lt;br /&gt;
     vendor_boot \&lt;br /&gt;
     vendor_dlkm \&lt;br /&gt;
     vbmeta_system \&lt;br /&gt;
     vbmeta_vendor&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PACKAGES += \&lt;br /&gt;
     update_engine \&lt;br /&gt;
     update_engine_sideload \&lt;br /&gt;
     update_verifier \&lt;br /&gt;
     checkpoint_gc&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_system=true \&lt;br /&gt;
     POSTINSTALL_PATH_system=system/bin/mtk_plpath_utils \&lt;br /&gt;
     FILESYSTEM_TYPE_system=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_system=true&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_vendor=true \&lt;br /&gt;
     POSTINSTALL_PATH_vendor=bin/checkpoint_gc \&lt;br /&gt;
     FILESYSTEM_TYPE_vendor=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_vendor=true&lt;br /&gt;
 &lt;br /&gt;
 # Dynamic&lt;br /&gt;
 PRODUCT_USE_DYNAMIC_PARTITIONS := true # 动态分区&lt;br /&gt;
 &lt;br /&gt;
 # Soong namespaces&lt;br /&gt;
 PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH) # 命名空间&lt;br /&gt;
&lt;br /&gt;
* A/B 无缝更新部分高通和联发科不一样，联发科设备可以照抄，注意 system/bin/mtk_plpath_utils 就好。高通参考[https://github.com/sekaiacg/android_device_xiaomi_venus_TWRP/tree/android-13 venus twrp tree]，并且高通的[https://git.codelinaro.org/clo/la/platform/hardware/qcom/bootctrl bootctrl]和[https://git.codelinaro.org/clo/la/platform/vendor/qcom-opensource/recovery-ext gpt-utils]可以从 CLO 拿。&lt;br /&gt;
&lt;br /&gt;
无注释版&lt;br /&gt;
 PRODUCT_SHIPPING_API_LEVEL := 31&lt;br /&gt;
 &lt;br /&gt;
 # A/B&lt;br /&gt;
 AB_OTA_UPDATER := true&lt;br /&gt;
 AB_OTA_PARTITIONS += \&lt;br /&gt;
     boot \&lt;br /&gt;
     dtbo \&lt;br /&gt;
     system \&lt;br /&gt;
     product \&lt;br /&gt;
     vendor \&lt;br /&gt;
     odm \&lt;br /&gt;
     odm_dlkm \&lt;br /&gt;
     vbmeta \&lt;br /&gt;
     vendor_boot \&lt;br /&gt;
     vendor_dlkm \&lt;br /&gt;
     vbmeta_system \&lt;br /&gt;
     vbmeta_vendor&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PACKAGES += \&lt;br /&gt;
     update_engine \&lt;br /&gt;
     update_engine_sideload \&lt;br /&gt;
     update_verifier \&lt;br /&gt;
     checkpoint_gc&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_system=true \&lt;br /&gt;
     POSTINSTALL_PATH_system=system/bin/mtk_plpath_utils \&lt;br /&gt;
     FILESYSTEM_TYPE_system=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_system=true&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_vendor=true \&lt;br /&gt;
     POSTINSTALL_PATH_vendor=bin/checkpoint_gc \&lt;br /&gt;
     FILESYSTEM_TYPE_vendor=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_vendor=true&lt;br /&gt;
 &lt;br /&gt;
 # Dynamic&lt;br /&gt;
 PRODUCT_USE_DYNAMIC_PARTITIONS := true&lt;br /&gt;
 &lt;br /&gt;
 # Soong namespaces&lt;br /&gt;
 PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH)&lt;br /&gt;
&lt;br /&gt;
==== 初始 twrp_rubens.mk 文件 ====&lt;br /&gt;
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 # Inherit from common AOSP config&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk) # vab加载到vendor boot里使用&lt;br /&gt;
 &lt;br /&gt;
 # Inherit from TWRP product configuration&lt;br /&gt;
 $(call inherit-product, vendor/twrp/config/common.mk) # twrp-9分支改为onmi&lt;br /&gt;
 &lt;br /&gt;
 # Device specific configs&lt;br /&gt;
 $(call inherit-product, device/xiaomi/rubens/device.mk)&lt;br /&gt;
 &lt;br /&gt;
 # Device identifier&lt;br /&gt;
 PRODUCT_DEVICE := rubens # 设备型号&lt;br /&gt;
 PRODUCT_NAME := twrp_rubens # 设备名称&lt;br /&gt;
 PRODUCT_BRAND := Redmi # 自定义品牌，如果有&lt;br /&gt;
 PRODUCT_MODEL := 22041211AC # 产品最终用户可见名称&lt;br /&gt;
 PRODUCT_MANUFACTURER := Xiaomi # 制造商&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true # 对twrp启动vendor_boot支持&lt;br /&gt;
无注释版&lt;br /&gt;
 # Inherit from common AOSP config&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk) # vab加载到vendor boot里使用&lt;br /&gt;
 &lt;br /&gt;
 # Inherit from TWRP product configuration&lt;br /&gt;
 $(call inherit-product, vendor/twrp/config/common.mk)&lt;br /&gt;
 &lt;br /&gt;
 # Device specific configs&lt;br /&gt;
 $(call inherit-product, device/xiaomi/rubens/device.mk)&lt;br /&gt;
 &lt;br /&gt;
 # Device identifier&lt;br /&gt;
 PRODUCT_DEVICE := rubens&lt;br /&gt;
 PRODUCT_NAME := twrp_rubens&lt;br /&gt;
 PRODUCT_BRAND := Redmi&lt;br /&gt;
 PRODUCT_MODEL := 22041211AC&lt;br /&gt;
 PRODUCT_MANUFACTURER := Xiaomi&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true&lt;br /&gt;
&lt;br /&gt;
==== 初始 recovery 目录 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;拿出我们好久之前准备的 ramdisk 叭&amp;lt;/blockquote&amp;gt;通过tree命令我们可以查看 ramdisk 的树状图，可以很清晰的查看包含的文件&lt;br /&gt;
 ├── acct&lt;br /&gt;
 ├── apex&lt;br /&gt;
 ├── bin -&amp;gt; /system/bin&lt;br /&gt;
 ├── bugreports -&amp;gt; /data/user_de/0/com.android.shell/files/bugreports&lt;br /&gt;
 ├── config&lt;br /&gt;
 ├── d -&amp;gt; /sys/kernel/debug&lt;br /&gt;
 ├── data&lt;br /&gt;
 ├── data_mirror&lt;br /&gt;
 ├── debug_ramdisk&lt;br /&gt;
 ├── default.prop -&amp;gt; prop.default&lt;br /&gt;
 ├── dev&lt;br /&gt;
 ├── etc -&amp;gt; /system/etc&lt;br /&gt;
 ├── first_stage_ramdisk&lt;br /&gt;
 │   ├── fstab.emmc&lt;br /&gt;
 │   ├── fstab.mt6895&lt;br /&gt;
 │   └── system&lt;br /&gt;
 │       ├── bin&lt;br /&gt;
 │       │   ├── e2fsck&lt;br /&gt;
 │       │   ├── linker64&lt;br /&gt;
 │       │   ├── linker_asan64 -&amp;gt; linker64&lt;br /&gt;
 │       │   └── snapuserd&lt;br /&gt;
 │       └── lib64&lt;br /&gt;
 │           ├── ld-android.so&lt;br /&gt;
 │           ├── libbase.so&lt;br /&gt;
 │           ├── libc++.so&lt;br /&gt;
 │           ├── libc.so&lt;br /&gt;
 │           ├── libdl.so&lt;br /&gt;
 │           ├── libext2_blkid.so&lt;br /&gt;
 │           ├── libext2_com_err.so&lt;br /&gt;
 │           ├── libext2_e2p.so&lt;br /&gt;
 │           ├── libext2_quota.so&lt;br /&gt;
 │           ├── libext2_uuid.so&lt;br /&gt;
 │           ├── libext2fs.so&lt;br /&gt;
 │           ├── liblog.so&lt;br /&gt;
 │           ├── libm.so&lt;br /&gt;
 │           ├── libsparse.so&lt;br /&gt;
 │           └── libz.so&lt;br /&gt;
 ├── init -&amp;gt; /system/bin/init&lt;br /&gt;
 ├── init.recovery.hardware.rc&lt;br /&gt;
 ├── init.recovery.mt6895.rc&lt;br /&gt;
 └── 等等等等...省略大概1000个文件吧&lt;br /&gt;
&amp;lt;blockquote&amp;gt;因为避免教程时效性，我们尽可能选取 prebuilt 的办法，如 boot 和 mtk_plpath_utils 都采用预编译。&amp;lt;/blockquote&amp;gt;里面有很多文件是没用的，整理一下，对我们有用的只有这些&lt;br /&gt;
 .&lt;br /&gt;
 ├── first_stage_ramdisk&lt;br /&gt;
 │   ├── fstab.emmc&lt;br /&gt;
 │   └── fstab.mt6895&lt;br /&gt;
 ├── init.recovery.mt6895.rc&lt;br /&gt;
 ├── lib&lt;br /&gt;
 │   └── modules&lt;br /&gt;
 │       ├── 8250_mtk.ko&lt;br /&gt;
 │       ├── adapter_class.ko&lt;br /&gt;
 │       ├── adsp.ko&lt;br /&gt;
 │       ├── aee_aed.ko&lt;br /&gt;
 │       ├── aee_hangdet.ko&lt;br /&gt;
 │       ├── aee_rs.ko&lt;br /&gt;
 │       ├── blocktag.ko&lt;br /&gt;
 │       ├── bootprof.ko&lt;br /&gt;
 │       ├── bq28z610.ko&lt;br /&gt;
 │       ├── cache-parity.ko&lt;br /&gt;
 │       ├── cfg80211.ko&lt;br /&gt;
 │       ├── charger_class.ko&lt;br /&gt;
 │       └── 省略一百多个模块，这个目录里的东西全要&lt;br /&gt;
 └── system&lt;br /&gt;
     ├── bin&lt;br /&gt;
     │   └── mtk_plpath_utils&lt;br /&gt;
     ├── etc&lt;br /&gt;
     │   ├── init&lt;br /&gt;
     │   │   │── mtk-plpath-utils.rc&lt;br /&gt;
     │   │   └──hw&lt;br /&gt;
     │   │      └──init.rc&lt;br /&gt;
     │   ├── recovery.fstab&lt;br /&gt;
     │   ├── security&lt;br /&gt;
     │   │   └── otacerts.zip&lt;br /&gt;
     │   └── ueventd.rc&lt;br /&gt;
     └── lib64&lt;br /&gt;
         └── hw&lt;br /&gt;
             └── android.hardware.boot@1.0-impl-1.2-mtkimpl.so&lt;br /&gt;
将它们按照以下操作复制&lt;br /&gt;
&lt;br /&gt;
* first_stage_ramdisk --&amp;gt; recovery/root/first_stage_ramdisk&lt;br /&gt;
* init.recovery.mt6895.rc --&amp;gt; recovery/root/init.recovery.mt6895.rc&lt;br /&gt;
* lib --&amp;gt; recovery/root/lib&lt;br /&gt;
* system --&amp;gt; recovery/root/system (security 和 hw 文件夹里的内容作为备用，不要复制进去) 得到以下目录结构&lt;br /&gt;
&lt;br /&gt;
 .&lt;br /&gt;
 ├── Android.mk&lt;br /&gt;
 ├── AndroidProducts.mk&lt;br /&gt;
 ├── BoardConfig.mk&lt;br /&gt;
 ├── device.mk&lt;br /&gt;
 ├── prebuilt&lt;br /&gt;
 ├── recovery&lt;br /&gt;
 │   └── root&lt;br /&gt;
 │       ├── first_stage_ramdisk&lt;br /&gt;
 │       │   ├── fstab.emmc&lt;br /&gt;
 │       │   └── fstab.mt6895&lt;br /&gt;
 │       ├── init.recovery.mt6895.rc&lt;br /&gt;
 │       ├── lib&lt;br /&gt;
 │       │   └── modules&lt;br /&gt;
 │       │       ├── 8250_mtk.ko&lt;br /&gt;
 │       │       ├── adapter_class.ko&lt;br /&gt;
 │       │       ├── adsp.ko&lt;br /&gt;
 │       │       ├── aee_aed.ko&lt;br /&gt;
 │       │       ├── aee_hangdet.ko&lt;br /&gt;
 │       │       ├── aee_rs.ko&lt;br /&gt;
 │       │       ├── blocktag.ko&lt;br /&gt;
 │       │       └── 省略....&lt;br /&gt;
 │       └── system&lt;br /&gt;
 │           ├── bin&lt;br /&gt;
 │           │   └── mtk_plpath_utils&lt;br /&gt;
 │           ├── etc&lt;br /&gt;
 │           │   ├── recovery.fstab&lt;br /&gt;
 │           │   └── ueventd.rc&lt;br /&gt;
 │           └── lib64&lt;br /&gt;
 │               └── hw&lt;br /&gt;
 │                   └── android.hardware.boot@1.0-impl-1.2-mtkimpl.so&lt;br /&gt;
 └── twrp_rubens.mk&lt;br /&gt;
打开 init.recovery.mt6895.rc 添加&lt;br /&gt;
 on boot&lt;br /&gt;
     start health-hal-2-1&lt;br /&gt;
 &lt;br /&gt;
 on post-fs&lt;br /&gt;
     start boot-hal-1-2&lt;br /&gt;
例如&lt;br /&gt;
 on post-fs&lt;br /&gt;
     start boot-hal-1-2&lt;br /&gt;
 &lt;br /&gt;
 on init&lt;br /&gt;
     setprop sys.usb.configfs 1&lt;br /&gt;
     setprop sys.usb.controller &amp;quot;11201000.usb0&amp;quot;&lt;br /&gt;
     setprop sys.usb.ffs.aio_compat 1&lt;br /&gt;
 &lt;br /&gt;
 on fs &amp;amp;&amp;amp; property:ro.debuggable=0&lt;br /&gt;
     # distinguish USB shoulde connect or not, i.e. CDP vs SDP&lt;br /&gt;
     # set charging free due to it wait for USB activation&lt;br /&gt;
 &lt;br /&gt;
 on boot&lt;br /&gt;
     start health-hal-2-1&lt;br /&gt;
     exec u:r:update_engine:s0 root root -- /system/bin/mtk_plpath_utils&lt;br /&gt;
 &lt;br /&gt;
接下来可以开始编译咯~~&lt;br /&gt;
&lt;br /&gt;
==== 编译 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;编译前请检查注释是否全部删除&amp;lt;/blockquote&amp;gt;twrp 源码根目录执行&lt;br /&gt;
 . build/envsetup.sh&lt;br /&gt;
 lunch twrp_codename-eng # twrp-9为onmi&lt;br /&gt;
 mka vendorbootimg/bootimage/recoveryimage&lt;br /&gt;
不出意外的话一路绿灯，如果有报错的话请发邮箱至 1592501605@qq.com 咨询我&lt;br /&gt;
&lt;br /&gt;
产物在 out/target/product/codename/vendor_boot.img\boot.img\recovery.img&lt;br /&gt;
&lt;br /&gt;
手机重启到 fastboot 模式，使用 fastboot flash 刷写，例如&lt;br /&gt;
 fastboot flash vendor_boot /Users/xiaolegun/Downloads/vendor_boot.img&lt;br /&gt;
则输出&lt;br /&gt;
 ERROR: could not clear input pipe; result e0005000, ignoring...&lt;br /&gt;
 ERROR: could not clear output pipe; result e0005000, ignoring....&lt;br /&gt;
 Sending 'vendor_boot_a' (65536 KB)                 OKAY [  1.396s]&lt;br /&gt;
 Writing 'vendor_boot_a'                            OKAY [  0.167s]&lt;br /&gt;
 Finished. Total time: 1.625s&lt;br /&gt;
就可以重启按电源加音量上尝试了，我自己是一次点亮，但有 bug。&lt;br /&gt;
&lt;br /&gt;
==== 修 BUG ====&lt;br /&gt;
&lt;br /&gt;
===== 修复 USB =====&lt;br /&gt;
我看到 twrp 控制台有很多报错，第一步肯定是先获取日志，使用logcat命令获取，在此之前先使用adb devices检测一下设备 usb 是否工作正常。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~  adb devices          ✔  10208  10:05:31&lt;br /&gt;
 * daemon not running; starting now at tcp:5037&lt;br /&gt;
 * daemon started successfully&lt;br /&gt;
 List of devices attached&lt;br /&gt;
可以看到adb没有检测到设备，原因一般是 usb 的配置不对，但 usb 是好的。这时可以尝试关闭 mtp，再开启，如果电脑有反应，那么就可以继续下一步了。&lt;br /&gt;
&lt;br /&gt;
在设备树中的 recovery/root，创建 init.recovery.usb.rc 的文件&lt;br /&gt;
 touch recovery/root/init.recovery.usb.rc&lt;br /&gt;
并导入以下内容&lt;br /&gt;
 on property:sys.usb.config=mtp,adb&lt;br /&gt;
     start adbd&lt;br /&gt;
 &lt;br /&gt;
 on property:sys.usb.ffs.ready=1 &amp;amp;&amp;amp; property:sys.usb.config=mtp,adb&lt;br /&gt;
     write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration &amp;quot;mtp_adb&amp;quot;&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f3&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f4&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f5&lt;br /&gt;
     write /config/usb_gadget/g1/idVendor 0x18d1&lt;br /&gt;
     write /config/usb_gadget/g1/idProduct 0x2d08&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}&lt;br /&gt;
     setprop sys.usb.state ${sys.usb.config}&lt;br /&gt;
这是我从我维护的 MI 6X 的 device tree 拿过来的，可以在联发科设备上正常工作。这段 shell 的大致意思就是在 usb 配置节点写入 mtp 和 adb 同时工作的字符串，这样 adb 就能顺利工作了。&lt;br /&gt;
&lt;br /&gt;
此外打开原厂 init.rc 修正一下 usb 设备的 id&lt;br /&gt;
 # MIUI ADD: START&lt;br /&gt;
 import /init.recovery.hardware.rc&lt;br /&gt;
 import /miui.factoryreset.rc&lt;br /&gt;
 # END&lt;br /&gt;
 import /init.recovery.${ro.hardware}.rc&lt;br /&gt;
 &lt;br /&gt;
 ########### 省略一万字&lt;br /&gt;
 &lt;br /&gt;
 # MIUI ADD: START&lt;br /&gt;
 on property:sys.usb.config=mtp,adb &amp;amp;&amp;amp; property:sys.usb.configfs=0&lt;br /&gt;
     write /sys/class/android_usb/android0/enable 0&lt;br /&gt;
     write /sys/class/android_usb/android0/idVendor 2717&lt;br /&gt;
     write /sys/class/android_usb/android0/idProduct 904D&lt;br /&gt;
     write /sys/class/android_usb/android0/functions mtp,adb&lt;br /&gt;
     write /sys/class/android_usb/android0/enable 1&lt;br /&gt;
     setprop sys.usb.state  ${sys.usb.config}&lt;br /&gt;
 # END&lt;br /&gt;
将/sys/class/android_usb/android0/idVendor和write /sys/class/android_usb/android0/idProduct后面的 id 分别替换到/config/usb_gadget/g1/idVendor和/config/usb_gadget/g1/idProduct处理完就是这样的。&lt;br /&gt;
 on property:sys.usb.config=mtp,adb&lt;br /&gt;
     start adbd&lt;br /&gt;
 &lt;br /&gt;
 on property:sys.usb.ffs.ready=1 &amp;amp;&amp;amp; property:sys.usb.config=mtp,adb&lt;br /&gt;
     write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration &amp;quot;mtp_adb&amp;quot;&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f3&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f4&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f5&lt;br /&gt;
     write /config/usb_gadget/g1/idVendor 0x2717&lt;br /&gt;
     write /config/usb_gadget/g1/idProduct 0x904D&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}&lt;br /&gt;
     setprop sys.usb.state ${sys.usb.config}&lt;br /&gt;
接下来开机之后 adb 和 mtp 就能同时工作了。&lt;br /&gt;
&lt;br /&gt;
===== 修复 Resetprop =====&lt;br /&gt;
接下来就可以修复其它 bug 了，我看到控制台有一堆红色的报错:&lt;br /&gt;
 E:Unknown File System:'/mi_ext'&lt;br /&gt;
 E:Unable to override 'external_storage.projid.enabled' due to missing libresetprop&lt;br /&gt;
 挂载“/data”失败(Invalid argument)&lt;br /&gt;
这三个报错中第二个最好修，第一个次之，第三个与解密有关，放在另一个大章节讲。&lt;br /&gt;
&lt;br /&gt;
第二个报错只需要在 BoardConfig.mk 中添加&lt;br /&gt;
 # Tool&lt;br /&gt;
 TW_INCLUDE_RESETPROP := true&lt;br /&gt;
 TW_INCLUDE_LIBRESETPROP := true&lt;br /&gt;
不用编译测试直接秒杀&lt;br /&gt;
&lt;br /&gt;
===== 修复挂载 =====&lt;br /&gt;
 E:Unknown File System:'/mi_ext'&lt;br /&gt;
我们打开 recovery/root/system/etc 中的 recovery.fstab，发现里面有很多空格，我们先将它格式化一下，有实力的可以把后面的 flag 也对齐整理好。&lt;br /&gt;
&lt;br /&gt;
我比较没实力，简单格式化了一下，是这样的&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 341 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;command line&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 2&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot; 2&lt;br /&gt;
 # 173 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 system /system erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system /system ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 vendor /vendor erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor /vendor ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 mi_ext /mnt/vendor/mi_ext erofs ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 mi_ext /mnt/vendor/mi_ext ext4 ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 /mnt/vendor/mi_ext /mi_ext none ro,bind wait,nofail&lt;br /&gt;
 overlay /product/overlay overlay ro,lowerdir=/mnt/vendor/mi_ext/product/overlay/:/product/overlay check,nofail&lt;br /&gt;
 overlay /product/app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/app/:/product/app check,nofail&lt;br /&gt;
 overlay /product/priv-app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/priv-app/:/product/priv-app check,nofail&lt;br /&gt;
 overlay /product/lib overlay ro,lowerdir=/mnt/vendor/mi_ext/product/lib/:/product/lib check,nofail&lt;br /&gt;
 overlay /product/lib64 overlay ro,lowerdir=/mnt/vendor/mi_ext/product/lib64/:/product/lib64 check,nofail&lt;br /&gt;
 overlay /product/bin overlay ro,lowerdir=/mnt/vendor/mi_ext/product/bin/:/product/bin check,nofail&lt;br /&gt;
 overlay /product/framework overlay ro,lowerdir=/mnt/vendor/mi_ext/product/framework/:/product/framework check,nofail&lt;br /&gt;
 overlay /product/media overlay ro,lowerdir=/mnt/vendor/mi_ext/product/media/:/product/media check,nofail&lt;br /&gt;
 overlay /product/opcust overlay ro,lowerdir=/mnt/vendor/mi_ext/product/opcust/:/product/opcust check,nofail&lt;br /&gt;
 overlay /product/data-app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/data-app/:/product/data-app check,nofail&lt;br /&gt;
 overlay /product/etc/sysconfig overlay ro,lowerdir=/mnt/vendor/mi_ext/product/etc/sysconfig/:/product/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /product/etc/permissions overlay ro,lowerdir=/mnt/vendor/mi_ext/product/etc/permissions/:/product/etc/permissions check,nofail&lt;br /&gt;
 overlay /system/app overlay ro,lowerdir=/mnt/vendor/mi_ext/system/app/:/product/pangu/system/app/:/system/app check,nofail&lt;br /&gt;
 overlay /system/priv-app overlay ro,lowerdir=/mnt/vendor/mi_ext/system/priv-app/:/product/pangu/system/priv-app/:/system/priv-app check,nofail&lt;br /&gt;
 overlay /system/framework overlay ro,lowerdir=/product/pangu/system/framework/:/system/framework check,nofail&lt;br /&gt;
 overlay /system/etc/sysconfig overlay ro,lowerdir=/mnt/vendor/mi_ext/system/etc/sysconfig/:/system/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /system/etc/permissions overlay ro,lowerdir=/mnt/vendor/mi_ext/system/etc/permissions/:/product/pangu/system/etc/permissions/:/system/etc/permissions check,nofail&lt;br /&gt;
 system_ext /system_ext erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system_ext /system_ext ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 odm /odm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm /odm ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor_dlkm /vendor_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm_dlkm /odm_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,noflush_merge,fsync_mode=nobarrier,reserve_root=134217,resgid=1065,checkpoint_merge,gc_merge,inlinecrypt wait,check,formattable,quota,latemount,resize,reservedsize=128m,checkpoint=fs,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,fsverity&lt;br /&gt;
 /dev/block/by-name/rescue /cache ext4 noatime,nosuid,nodev,noauto_da_alloc,discard wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect1 /mnt/vendor/protect_f ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect2 /mnt/vendor/protect_s ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvdata /mnt/vendor/nvdata ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvcfg /mnt/vendor/nvcfg ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/persist /mnt/vendor/persist ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /devices/platform/soc/11240000.mmc* auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata&lt;br /&gt;
 /devices/platform/usb_xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /devices/platform/soc/11201000.usb0/11200000.xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /dev/block/by-name/frp /persistent emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/nvram /nvram emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/proinfo /proinfo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk /bootloader emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk2 /bootloader2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/para /para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/misc /misc emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot /boot emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_vendor /vbmeta_vendor emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_system /vbmeta_system emmc defaults first_stage_mount,nofail,slotselect,avb=vbmeta&lt;br /&gt;
 /dev/block/by-name/logo /logo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/expdb /expdb emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/seccfg /seccfg emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee1 /tee1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee2 /tee2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp1 /scp1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp2 /scp2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_1 /sspm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_2 /sspm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_1 /dpm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_2 /dpm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_1 /mcupm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_2 /mcupm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1img /md1img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1dsp /md1dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1arm7 /md1arm7 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md3img /md3img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz1 /gz1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz2 /gz2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/spmfw /spmfw emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/audio_dsp /audio_dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/pi_img /pi_img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot_para /boot_para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/odmdtbo /odmdtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dtbo /dtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/otp /otp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/vbmeta /vbmeta emmc defaults defaults&lt;br /&gt;
这里面有很多无用分区，我们在 twrp 中操作不到，但是我也是第一次适配 MTK 设备，所以不“瞎说”误人子弟了，先把 bug 修好。&lt;br /&gt;
&lt;br /&gt;
像 xiaomi 这样常见的挂载错误，我自己一般都是尝试把/mnt/vendor 使用 vscode 全部删除，让我们尝试一下。并且要把这一行删除，这行在我看来是重复定义（？而且也没指定分区格式。&lt;br /&gt;
 /mnt/vendor/mi_ext /mi_ext none ro,bind wait,nofail&lt;br /&gt;
整理完之后是这样的&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 341 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;command line&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 2&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot; 2&lt;br /&gt;
 # 173 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 system /system erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system /system ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 vendor /vendor erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor /vendor ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 mi_ext /mi_ext erofs ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 mi_ext /mi_ext ext4 ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 overlay /product/overlay overlay ro,lowerdir=/mi_ext/product/overlay/:/product/overlay check,nofail&lt;br /&gt;
 overlay /product/app overlay ro,lowerdir=/mi_ext/product/app/:/product/app check,nofail&lt;br /&gt;
 overlay /product/priv-app overlay ro,lowerdir=/mi_ext/product/priv-app/:/product/priv-app check,nofail&lt;br /&gt;
 overlay /product/lib overlay ro,lowerdir=/mi_ext/product/lib/:/product/lib check,nofail&lt;br /&gt;
 overlay /product/lib64 overlay ro,lowerdir=/mi_ext/product/lib64/:/product/lib64 check,nofail&lt;br /&gt;
 overlay /product/bin overlay ro,lowerdir=/mi_ext/product/bin/:/product/bin check,nofail&lt;br /&gt;
 overlay /product/framework overlay ro,lowerdir=/mi_ext/product/framework/:/product/framework check,nofail&lt;br /&gt;
 overlay /product/media overlay ro,lowerdir=/mi_ext/product/media/:/product/media check,nofail&lt;br /&gt;
 overlay /product/opcust overlay ro,lowerdir=/mi_ext/product/opcust/:/product/opcust check,nofail&lt;br /&gt;
 overlay /product/data-app overlay ro,lowerdir=/mi_ext/product/data-app/:/product/data-app check,nofail&lt;br /&gt;
 overlay /product/etc/sysconfig overlay ro,lowerdir=/mi_ext/product/etc/sysconfig/:/product/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /product/etc/permissions overlay ro,lowerdir=/mi_ext/product/etc/permissions/:/product/etc/permissions check,nofail&lt;br /&gt;
 overlay /system/app overlay ro,lowerdir=/mi_ext/system/app/:/product/pangu/system/app/:/system/app check,nofail&lt;br /&gt;
 overlay /system/priv-app overlay ro,lowerdir=/mi_ext/system/priv-app/:/product/pangu/system/priv-app/:/system/priv-app check,nofail&lt;br /&gt;
 overlay /system/framework overlay ro,lowerdir=/product/pangu/system/framework/:/system/framework check,nofail&lt;br /&gt;
 overlay /system/etc/sysconfig overlay ro,lowerdir=/mi_ext/system/etc/sysconfig/:/system/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /system/etc/permissions overlay ro,lowerdir=/mi_ext/system/etc/permissions/:/product/pangu/system/etc/permissions/:/system/etc/permissions check,nofail&lt;br /&gt;
 system_ext /system_ext erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system_ext /system_ext ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 odm /odm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm /odm ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor_dlkm /vendor_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm_dlkm /odm_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,noflush_merge,fsync_mode=nobarrier,reserve_root=134217,resgid=1065,checkpoint_merge,gc_merge,inlinecrypt wait,check,formattable,quota,latemount,resize,reservedsize=128m,checkpoint=fs,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,fsverity&lt;br /&gt;
 /dev/block/by-name/rescue /cache ext4 noatime,nosuid,nodev,noauto_da_alloc,discard wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect1 /protect_f ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect2 /protect_s ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvdata /nvdata ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvcfg /nvcfg ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/persist /persist ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /devices/platform/soc/11240000.mmc* auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata&lt;br /&gt;
 /devices/platform/usb_xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /devices/platform/soc/11201000.usb0/11200000.xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /dev/block/by-name/frp /persistent emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/nvram /nvram emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/proinfo /proinfo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk /bootloader emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk2 /bootloader2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/para /para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/misc /misc emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot /boot emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_vendor /vbmeta_vendor emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_system /vbmeta_system emmc defaults first_stage_mount,nofail,slotselect,avb=vbmeta&lt;br /&gt;
 /dev/block/by-name/logo /logo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/expdb /expdb emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/seccfg /seccfg emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee1 /tee1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee2 /tee2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp1 /scp1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp2 /scp2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_1 /sspm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_2 /sspm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_1 /dpm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_2 /dpm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_1 /mcupm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_2 /mcupm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1img /md1img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1dsp /md1dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1arm7 /md1arm7 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md3img /md3img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz1 /gz1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz2 /gz2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/spmfw /spmfw emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/audio_dsp /audio_dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/pi_img /pi_img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot_para /boot_para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/odmdtbo /odmdtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dtbo /dtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/otp /otp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/vbmeta /vbmeta emmc defaults defaults&lt;br /&gt;
让我们编译试一下，值得注意的是，twrp 每次更改最好删除 out 重新编译，不要使用如make installclean等命令，可能会开机黑屏或更改不生效。&lt;br /&gt;
&lt;br /&gt;
经过一分钟，编译好了，刷入，开机，启动！可以看见挂载成功被修好。&lt;br /&gt;
&lt;br /&gt;
===== 修复屏幕显示 =====&lt;br /&gt;
可以看到我们现在屏幕的顶部的时间被摄像头挖孔挡住了。我们使用两个偏移 Flag 来修复它。&lt;br /&gt;
&lt;br /&gt;
在 BoardConfig.mk 中，加入以下 flag&lt;br /&gt;
 TW_Y_OFFSET := 106 #导航栏向上&lt;br /&gt;
 TW_H_OFFSET := -106 #界面整体向下&lt;br /&gt;
&lt;br /&gt;
===== 修复振动 =====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;仅供参考，研究半天发现只有解密功能正常才能修振动，不然会冻屏！！！&lt;br /&gt;
&lt;br /&gt;
不一定正确，也不一定普遍，仅供指路&amp;lt;/blockquote&amp;gt;老设备一般都是正常的，不需要额外处理，新设备使用 aidl hal 需要我们自己处理一下让 service 正常工作。&lt;br /&gt;
&lt;br /&gt;
挂载 vendor，使用 twrp 的文件管理，在 vendor/etc/vintf/manifest 找到含有 vibrator 字样的文件。打开之后检查是否类似这样的文段&lt;br /&gt;
 &amp;lt;manifest version=&amp;quot;1.0&amp;quot; type=&amp;quot;device&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;hal format=&amp;quot;aidl&amp;quot; override=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
         &amp;lt;name&amp;gt;android.hardware.vibrator&amp;lt;/name&amp;gt;&lt;br /&gt;
         &amp;lt;fqname&amp;gt;IVibrator/vibratorfeature&amp;lt;/fqname&amp;gt;&lt;br /&gt;
     &amp;lt;/hal&amp;gt;&lt;br /&gt;
 &amp;lt;/manifest&amp;gt;&lt;br /&gt;
那恭喜你，找对了，我的文件名是&lt;br /&gt;
&lt;br /&gt;
vendor.xiaomi.hardware.vibratorfeature.service.xml&lt;br /&gt;
&lt;br /&gt;
将它使用adb pull放到电脑上自己方便的位置备用。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /vendor/etc/vintf/manifest/vendor.xiaomi.hardware.vibratorfeature.service.xml .&lt;br /&gt;
 /vendor/etc/vintf/manifest/vendor.xiao...ipped. 0.2 MB/s (1718 bytes in 0.009s)&lt;br /&gt;
不看扩展名，到 vendor/bin/hw/找到同名的 service 同样利用adb pull放电脑备用。比如我的叫&lt;br /&gt;
&lt;br /&gt;
vendor.xiaomi.hardware.vibratorfeature.service&lt;br /&gt;
&lt;br /&gt;
然后到 vendor/etc/init/找到同名.rc 文件，拉到电脑上，在里面加一条。并在定义 service 的最下面加上seclabel u:r:recovery:s0可以被 recovery 使用。&lt;br /&gt;
 on boot&lt;br /&gt;
     start service被定义的名字&lt;br /&gt;
例如&lt;br /&gt;
 on post-fs-data&lt;br /&gt;
     chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/f0_save&lt;br /&gt;
     chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/osc_save&lt;br /&gt;
     chown system system /sys/bus/i2c/drivers/aw8697_haptic/3-005a/osc_save&lt;br /&gt;
     # 省略一万字&lt;br /&gt;
 &lt;br /&gt;
 on boot&lt;br /&gt;
     start vibratorfeature-hal-service&lt;br /&gt;
 &lt;br /&gt;
 service vibratorfeature-hal-service /vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&lt;br /&gt;
     class hal&lt;br /&gt;
     user system&lt;br /&gt;
     group system input&lt;br /&gt;
     onrestart restart vibratorfeature&lt;br /&gt;
     seclabel u:r:recovery:s0&lt;br /&gt;
此外这种新设备在内核里还有振动模块需要加载，请到/vendor/modules/1.1/中寻找，例如我这台设备是haptic.ko，用 adb pull 拉取到电脑上，然后&lt;br /&gt;
&lt;br /&gt;
* haptic.ko --&amp;gt; recovery/root/vendor/modules/1.1&lt;br /&gt;
&lt;br /&gt;
至此所有必要的资料就准备好了。可能开机后仍然不工作，需要抓取 log 补缺失的 library，当然这是后话了。&lt;br /&gt;
&lt;br /&gt;
开干！&lt;br /&gt;
&lt;br /&gt;
在 BoardConfig.mk 中加入以下 flag&lt;br /&gt;
 TW_SUPPORT_INPUT_AIDL_HAPTICS := true&lt;br /&gt;
将备用文件按照以下操作复制&lt;br /&gt;
&lt;br /&gt;
* vendor.xiaomi.hardware.vibratorfeature.service.xml --&amp;gt; recovery/root/vendor/etc/vintf/manifest&lt;br /&gt;
* vendor.xiaomi.hardware.vibratorfeature.service --&amp;gt; recovery/root/vendor/bin/hw&lt;br /&gt;
* vendor.xiaomi.hardware.vibratorfeature.service.rc --&amp;gt; recovery/root/vendor/etc/init&lt;br /&gt;
&lt;br /&gt;
之后编译，刷入，开机，喜提冻屏......&lt;br /&gt;
&lt;br /&gt;
问题不大，使用adb logcat抓取日志&lt;br /&gt;
 adb logcat &amp;gt; log.log&lt;br /&gt;
打开 log，搜索F linker、linker、library、beginning of crash这几个关键词，我搜索第一个就出来了。&lt;br /&gt;
 F linker  : CANNOT LINK EXECUTABLE &amp;quot;/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&amp;quot;: library &amp;quot;android.hardware.vibrator-V1-ndk_platform.so&amp;quot; not found: needed by main executable&lt;br /&gt;
这段报错的意思就是vendor.xiaomi.hardware.vibratorfeature.service找不到android.hardware.vibrator-V1-ndk_platform.so这个库，所以无法正常工作。&lt;br /&gt;
&lt;br /&gt;
打开 BoardConfig.mk 加入以下 flag&lt;br /&gt;
 # Library&lt;br /&gt;
 TARGET_RECOVERY_DEVICE_MODULES += \&lt;br /&gt;
     android.hardware.vibrator-V1-ndk_platform.vendor&lt;br /&gt;
 &lt;br /&gt;
 TW_RECOVERY_ADDITIONAL_RELINK_LIBRARY_FILES += \&lt;br /&gt;
     $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.vibrator-V1-ndk_platform.so&lt;br /&gt;
再次编译尝试&lt;br /&gt;
&lt;br /&gt;
开机之后依然冻屏，继续抓 log，查找&lt;br /&gt;
 F linker  : CANNOT LINK EXECUTABLE &amp;quot;/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&amp;quot;: library &amp;quot;vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so&amp;quot; not found: needed by main executable&lt;br /&gt;
vendor.hardware.vibratorfeature字样和我们之前导入的文件长得差不多，一般都是供应商专有文件，所以去设备提取，路径在 vendor/lib64 里，虽然设备冻屏了，但我们可以用adb pull直接拉取到电脑。就像这样。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb shell mount /vendor&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /vendor/lib64/vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so .&lt;br /&gt;
 /vendor/lib64/vendor.hardware.vibratorfeature.IVi...led, 0 skipped. 14.7 MB/s (33552 bytes in 0.002s&lt;br /&gt;
将这个文件按照以下提示操作&lt;br /&gt;
&lt;br /&gt;
* vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so --&amp;gt; recovery/root/vendor/lib64&lt;br /&gt;
&lt;br /&gt;
继续编译测试&lt;br /&gt;
&lt;br /&gt;
还是冻屏，继续抓 log&lt;br /&gt;
 F linker  : CANNOT LINK EXECUTABLE &amp;quot;/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&amp;quot;: library &amp;quot;libtinyalsa.so&amp;quot; not found: needed by main executable&lt;br /&gt;
这个 library twrp 的源码中应该没有，去设备拿一个 prebuilt 吧&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb shell mount /system_root&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /system_root/system/lib64/libtinyalsa.so .&lt;br /&gt;
 /system_root/system/lib64/libtinyalsa.so: 1 file ...led, 0 skipped. 13.6 MB/s (45032 bytes in 0.003s&lt;br /&gt;
将这个文件按照以下提示操作&lt;br /&gt;
&lt;br /&gt;
* libtinyalsa.so --&amp;gt; recovery/root/system/lib64&lt;br /&gt;
&lt;br /&gt;
编译测试&lt;br /&gt;
&lt;br /&gt;
我艹了，还是冻屏，这次搜那几个关键词都搜不到了，搜vibrator看看这鬼东西报什么&lt;br /&gt;
 E vendor.xiaomi.hardware.vibratorfeature.service: fail to load lib : /vendor/lib64/libaachaptics.so&lt;br /&gt;
这次都直接给路径了，直接拿。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb shell mount /vendor&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /vendor/lib64/libaachaptics.so .&lt;br /&gt;
 /vendor/lib64/libaachaptics.so: 1 file pulled, 0 skipped. 15.8 MB/s (56232 bytes in 0.003s)&lt;br /&gt;
将这个文件按照以下提示操作&lt;br /&gt;
&lt;br /&gt;
* libaachaptics.so --&amp;gt; recovery/root/vendor/lib64&lt;br /&gt;
&lt;br /&gt;
至此应该没什么问题了，但是有个 flag 貌似要操作 data 内的东西，未解密会导致冻屏，所以等修完解密后再来修振动。&lt;br /&gt;
&lt;br /&gt;
==== 修复 CPU 温度 ====&lt;br /&gt;
使用adb shell + grep命令在手机节点里搜索 type 关键词。&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~  adb shell 'grep &amp;quot;cp_master&amp;quot; /sys/class/thermal/*/type'&lt;br /&gt;
 /sys/class/thermal/thermal_zone54/type:cp_master&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~  adb shell 'grep &amp;quot;cpu&amp;quot; /sys/class/thermal/*/type'&lt;br /&gt;
 /sys/class/thermal/thermal_zone1/type:cpu_little1&lt;br /&gt;
 /sys/class/thermal/thermal_zone10/type:cpu_bigbig1&lt;br /&gt;
 /sys/class/thermal/thermal_zone11/type:cpu_big6&lt;br /&gt;
 /sys/class/thermal/thermal_zone12/type:cpu_bigbig2&lt;br /&gt;
 /sys/class/thermal/thermal_zone2/type:cpu_little2&lt;br /&gt;
 /sys/class/thermal/thermal_zone3/type:cpu_little3&lt;br /&gt;
 /sys/class/thermal/thermal_zone4/type:cpu_little4&lt;br /&gt;
 /sys/class/thermal/thermal_zone5/type:cpu_big1&lt;br /&gt;
 /sys/class/thermal/thermal_zone6/type:cpu_big2&lt;br /&gt;
 /sys/class/thermal/thermal_zone7/type:cpu_big3&lt;br /&gt;
 /sys/class/thermal/thermal_zone8/type:cpu_big4&lt;br /&gt;
 /sys/class/thermal/thermal_zone9/type:cpu_big5&lt;br /&gt;
我这里选用cp_master节点来读取温度。我的节点路径为/sys/class/thermal/thermal_zone54在后面添加 temp 来读取温度，你可以使用cat来检测节点是否可以正常读取温度&lt;br /&gt;
 adb shell 'cat /sys/class/thermal/thermal_zone54/temp'&lt;br /&gt;
如果返回如&lt;br /&gt;
 28000&lt;br /&gt;
这种类似的数值，那多半是没有问题的。&lt;br /&gt;
&lt;br /&gt;
我们在 BoardConfig.mk 中加入&lt;br /&gt;
 TW_CUSTOM_CPU_TEMP_PATH := &amp;quot;/sys/class/thermal/thermal_zone54/temp&amp;quot;&lt;br /&gt;
至此 cpu 温度就修复好了。&lt;br /&gt;
&lt;br /&gt;
== 后序 ==&lt;br /&gt;
这是我玩 Android 两年内第一次写关于 Android 的文章，内容和措辞可能不是很准确，再加上开学焦虑，租房因租金和房源不顺利，写的很乱，请各位指正。&lt;br /&gt;
&lt;br /&gt;
此外有什么不懂得，多翻github，善用github搜索，多看看大佬们是怎么解决的。&lt;br /&gt;
&lt;br /&gt;
解密等有空补，先补作业。&lt;br /&gt;
&lt;br /&gt;
== 参考资料 ==&lt;br /&gt;
[https://source.android.com/docs/setup/create/new-device?hl=zh-cn Google - 添加新设备]&lt;br /&gt;
&lt;br /&gt;
[https://source.android.com/docs/core/ota/ab?hl=zh-cn Google - A/B（无缝）系统更新]&lt;br /&gt;
&lt;br /&gt;
[https://blog.lynnrin.moe/posts/ROM-bringup-guide-prebuilt/#boardconfigmk Lynnrin - 快速上手 Android Custom ROM 适配 - Prebuilt Vendor]&lt;br /&gt;
&lt;br /&gt;
[https://source.android.com/docs/core/architecture/vintf?hl=zh-cn Google - 供应商接口对象]&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=%E4%B8%BA%E6%96%B0%E8%AE%BE%E5%A4%87%E7%BC%96%E5%86%99Recovery_device_tree&amp;diff=549</id>
		<title>为新设备编写Recovery device tree</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=%E4%B8%BA%E6%96%B0%E8%AE%BE%E5%A4%87%E7%BC%96%E5%86%99Recovery_device_tree&amp;diff=549"/>
		<updated>2024-02-20T02:46:05Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​初始页面&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= 为新设备编写 Recovery 的设备树 =&lt;br /&gt;
作者: Dark(xiaoleGun)&lt;br /&gt;
&lt;br /&gt;
时间: 2024.2.20&lt;br /&gt;
&lt;br /&gt;
协作者:&lt;br /&gt;
&lt;br /&gt;
== 一些自序 ==&lt;br /&gt;
这篇教程中可能有些不对的地方，请各位指正，我也刚接触 Android 设备测开发两年，而且只有在节假日的时候有空一个人瞎捣鼓，为了&amp;lt;s&amp;gt;薅 mjw 羊毛&amp;lt;/s&amp;gt;，故写这篇教程，而且我个人更推荐 Aosp Recovery 刷写第三方 ROM，TWRP 可能多多少少有些问题。Root 之类的不需要 TWRP 也可以，可以找到原机 boot 使用 Magisk 进行修补，也可以使用 KernelSU。另外我的语文功底不是很好，写不出辞藻，只能是北方地道的大白话，见谅哈 🤣///&lt;br /&gt;
&lt;br /&gt;
== 准备工作 ==&lt;br /&gt;
1.一颗勇敢的、不怕困难的强大心脏。&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;s&amp;gt;两颗心好勇敢 -- Falling in love&amp;lt;/s&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
2.电脑配置:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!硬件&lt;br /&gt;
!需求&lt;br /&gt;
|-&lt;br /&gt;
|CPU&lt;br /&gt;
|四核或更多&lt;br /&gt;
|-&lt;br /&gt;
|内存&lt;br /&gt;
|8G 或更多&lt;br /&gt;
|-&lt;br /&gt;
|硬盘&lt;br /&gt;
|至少 80G 空余空间&lt;br /&gt;
|-&lt;br /&gt;
|系统&lt;br /&gt;
|WSL 或实体 Linux，建议 Debian 系&lt;br /&gt;
|}&lt;br /&gt;
3.足够的空闲时间。&lt;br /&gt;
&lt;br /&gt;
4.Vscode 和 🤏Linux 知识储备&lt;br /&gt;
&lt;br /&gt;
5.一台完好无损的新设备。&lt;br /&gt;
&lt;br /&gt;
6.设备原厂的 boot/recovery/vendor_boot 镜像。(推荐 recovery 分区，因为里面包含一些启动必须的.rc(run command)，如果没有该分区，寻找包含官方 recovery 内容的分区。值得注意的是部分设备 recovery 合并到了 boot 中，或是存在于 vendor_boot）&lt;br /&gt;
&lt;br /&gt;
7.查看自己的设备出厂 Android 版本并确定用途，是用于官方 ROM 还是第三方类原生。出厂版本为 9 及以上的可以使用 twrp-11 及以上分支，9 以下使用 twrp-9 分支。&lt;br /&gt;
&lt;br /&gt;
== 配置环境 ==&lt;br /&gt;
&lt;br /&gt;
=== 安装依赖 ===&lt;br /&gt;
 &amp;lt;code&amp;gt;sudo apt update&lt;br /&gt;
 sudo apt-get install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev liblz4-tool libncurses5 libncurses5-dev libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev xattr openjdk-11-jdk jq android-sdk-libsparse-utils python3 python2 repo&amp;lt;/code&amp;gt;&lt;br /&gt;
必要时可以阅读[https://source.android.com/source/using-repo?hl=zh-cn Git 和 Repo]&lt;br /&gt;
&lt;br /&gt;
=== 配置 Git 和 Repo ===&lt;br /&gt;
安装完依赖后，在终端执行。&lt;br /&gt;
 &amp;lt;code&amp;gt;git config --global user.name &amp;quot;your username&amp;quot;&lt;br /&gt;
 git config --global user.email &amp;quot;your email&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 同步 TWRP 源码 ===&lt;br /&gt;
在自己方便的地方，建立一个目录。&lt;br /&gt;
 &amp;lt;code&amp;gt;mkdir twrp&lt;br /&gt;
 cd twrp&amp;lt;/code&amp;gt;&lt;br /&gt;
根据自己在准备工作中确定的分支同步相应的源码。&lt;br /&gt;
&lt;br /&gt;
==== TWRP-9 ====&lt;br /&gt;
 &amp;lt;code&amp;gt;repo init --depth=1 -u &amp;lt;nowiki&amp;gt;https://github.com/minimal-manifest-twrp/platform_manifest_twrp_omni.git&amp;lt;/nowiki&amp;gt; -b twrp-9.0&lt;br /&gt;
 repo sync&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== TWRP-11 ====&lt;br /&gt;
 &amp;lt;code&amp;gt;repo init --depth=1 -u &amp;lt;nowiki&amp;gt;https://github.com/minimal-manifest-twrp/platform_manifest_twrp_aosp.git&amp;lt;/nowiki&amp;gt; -b twrp-11&lt;br /&gt;
 repo sync&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== TWRP-12.1 ====&lt;br /&gt;
 &amp;lt;code&amp;gt;repo init --depth=1 -u &amp;lt;nowiki&amp;gt;https://github.com/minimal-manifest-twrp/platform_manifest_twrp_aosp.git&amp;lt;/nowiki&amp;gt; -b twrp-12.1&lt;br /&gt;
 repo sync&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 编写设备树 ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;最基本的开机部分我通过 Redmi K50 做示例，并选取 TWRP-12.1 分支。&lt;br /&gt;
&lt;br /&gt;
解密部分会单独成一个章节并分为高通和联发科。&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 获取资料 ===&lt;br /&gt;
小米设备一般可以在[https://xiaomirom.com Xiaomirom]中的线刷包获取 boot/recovery/vendor_boot 镜像，其它设备请自行寻找。&lt;br /&gt;
&lt;br /&gt;
==== 安装工具和依赖 ====&lt;br /&gt;
将准备工作中准备的 boot/recovery/vendor_boot 镜像解包，可以用任何工具，我这里使用[https://github.com/cfig/Android_boot_image_editor Android_boot_image_editor]按照自述文件进行依赖安装操作：&lt;br /&gt;
&lt;br /&gt;
===== Mac(Intel) =====&lt;br /&gt;
 &amp;lt;code&amp;gt;brew install lz4 xz dtc openjdk@17&lt;br /&gt;
 echo 'export PATH=&amp;quot;/usr/local/opt/openjdk@17/bin:$PATH&amp;quot;' &amp;gt;&amp;gt; ~/.zshrc&lt;br /&gt;
 source ~/.zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Linux: =====&lt;br /&gt;
 &amp;lt;code&amp;gt;sudo apt update&lt;br /&gt;
 sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-17-jdk gcc g++ python3 python-is-python3 p7zip-full android-sdk-libsparse-utils erofs-utils&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Common: =====&lt;br /&gt;
 &amp;lt;code&amp;gt;git clone &amp;lt;nowiki&amp;gt;https://github.com/cfig/Android_boot_image_editor&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 cd Android_boot_image_editor&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 解包 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;请注意&amp;quot;/&amp;quot;表示或的意思，请不要误以为是一个东西。&lt;br /&gt;
&lt;br /&gt;
如果不确定分区寻找的是否正确，请尝试将可以的分区进行解包，并查看其&amp;lt;code&amp;gt;ramdisk&amp;lt;/code&amp;gt;内是否包含&amp;lt;code&amp;gt;recovery&amp;lt;/code&amp;gt;字样的文件&amp;lt;/blockquote&amp;gt;将你准备好的&amp;lt;code&amp;gt;boot&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;recovery&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;vendor_boot&amp;lt;/code&amp;gt;复制到该目录，你可以使用 GUI 或者 CLI。如:&lt;br /&gt;
 &amp;lt;code&amp;gt;cp &amp;lt;出厂boot/recovery/vendor_boot的绝对路径&amp;gt; boot/recovery/vendor_boot.img&lt;br /&gt;
 ./gradlew unpack&amp;lt;/code&amp;gt;&lt;br /&gt;
我这里以 Redmi K50 为例&lt;br /&gt;
 &amp;lt;code&amp;gt;10:12:13.188 [main] INFO  cfig.bootimg.v3.VendorBoot -&lt;br /&gt;
                         Unpack Summary of vendor_boot.img&lt;br /&gt;
 ┌───────────────────────────────────────┬──────────────────────────────────────┐&lt;br /&gt;
 │What                                   │Where                                 │&lt;br /&gt;
 └───────────────────────────────────────┴──────────────────────────────────────┘&lt;br /&gt;
 ┌───────────────────────────────────────┬──────────────────────────────────────┐&lt;br /&gt;
 │image info                             │build/unzip_boot/vendor_boot.json     │&lt;br /&gt;
 ├───────────────────────────────────────┼──────────────────────────────────────┤&lt;br /&gt;
 │ramdisk                                │build/unzip_boot/ramdisk.img.lz4      │&lt;br /&gt;
 │-- PLATFORM ramdisk[1/1]               │build/unzip_boot/ramdisk.1.lz4        │&lt;br /&gt;
 │------- extracted rootfs               │build/unzip_boot/root.1               │&lt;br /&gt;
 ├───────────────────────────────────────┼──────────────────────────────────────┤&lt;br /&gt;
 │dtb                                    │build/unzip_boot/dtb                  │&lt;br /&gt;
 ├───────────────────────────────────────┼──────────────────────────────────────┤&lt;br /&gt;
 │AVB info                               │build/unzip_boot/vendor_boot.avb.json │&lt;br /&gt;
 │\-- signing key                        │NONE                                  │&lt;br /&gt;
 └───────────────────────────────────────┴──────────────────────────────────────┘&lt;br /&gt;
 10:12:13.213 [main] WARN  cfig.packable.PackableLauncher - 'unpack' sequence completed&lt;br /&gt;
 &lt;br /&gt;
 BUILD SUCCESSFUL in 2s&amp;lt;/code&amp;gt;&lt;br /&gt;
解包成功后终端会打印出以上信息，其中包含&amp;lt;code&amp;gt;vendor_boot&amp;lt;/code&amp;gt;目录结构，我们只需要&amp;lt;code&amp;gt;ramdisk&amp;lt;/code&amp;gt;里的部分内容就好了。&lt;br /&gt;
 &amp;lt;code&amp;gt;ls build/unzip_boot/root.1 # 请根据自己的分区和设备判断ramdisk的命名，一般都直接是ramdisk&amp;lt;/code&amp;gt;&lt;br /&gt;
不出意外的话会输出以下内容&lt;br /&gt;
 &amp;lt;code&amp;gt;xiaolegun@xiaoleGundeMac-Pro  ~/github/dump/bootedit   master ?  ls build/unzip_boot/root.1&lt;br /&gt;
 acct                         oem&lt;br /&gt;
 apex                         plat_file_contexts&lt;br /&gt;
 bin                          plat_property_contexts&lt;br /&gt;
 bugreports                   postinstall&lt;br /&gt;
 config                       proc&lt;br /&gt;
 d                            product&lt;br /&gt;
 data                         product_file_contexts&lt;br /&gt;
 data_mirror                  product_property_contexts&lt;br /&gt;
 debug_ramdisk                prop.default&lt;br /&gt;
 default.prop                 res&lt;br /&gt;
 dev                          sdcard&lt;br /&gt;
 etc                          second_stage_resources&lt;br /&gt;
 first_stage_ramdisk          sepolicy&lt;br /&gt;
 init                         storage&lt;br /&gt;
 init.recovery.hardware.rc    sys&lt;br /&gt;
 init.recovery.mt6895.rc      system&lt;br /&gt;
 lib                          system_ext&lt;br /&gt;
 linkerconfig                 system_ext_file_contexts&lt;br /&gt;
 miui.factoryreset.fstab      system_ext_property_contexts&lt;br /&gt;
 miui.factoryreset.rc         tmp&lt;br /&gt;
 mnt                          vendor&lt;br /&gt;
 odm                          vendor_dlkm&lt;br /&gt;
 odm_dlkm                     vendor_file_contexts&lt;br /&gt;
 odm_file_contexts            vendor_property_contexts&lt;br /&gt;
 odm_property_contexts&amp;lt;/code&amp;gt;&lt;br /&gt;
如果包含 init.recovery*的字样，恭喜你成功找到了正确的分区。将这个目录复制到一个自己方便的地方。&lt;br /&gt;
&lt;br /&gt;
至此资料已经大致齐全了，解密的资料会在解密章节来讲解如何获取。&lt;br /&gt;
&lt;br /&gt;
=== 初始化目录结构 ===&lt;br /&gt;
在 twrp 源码根目录输入&lt;br /&gt;
 &amp;lt;code&amp;gt;mkdir -p device/vendor/codename&lt;br /&gt;
 mkdir -p device/vendor/codename/recovery/root&lt;br /&gt;
 cd device/vendor/codename&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;vendor&amp;lt;/code&amp;gt;指的是供应商，如 xiaomi、oneplus、huawei、vivo、realme。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;codename&amp;lt;/code&amp;gt;指的是设备代号，小米设备可以在[https://xiaomirom.com Xiaomirom]查询，其它设备自行查询亦或是在开发者选项勾选 USB 调试通过 adb 尝试获取。&lt;br /&gt;
 &amp;lt;code&amp;gt;adb shell getprop ro.product.manufacturer # 供应商&lt;br /&gt;
 adb shell getprop ro.product.device # 设备代号&amp;lt;/code&amp;gt;&lt;br /&gt;
我的 Redmi K50 会打印以下信息&lt;br /&gt;
 &amp;lt;code&amp;gt;xiaolegun@xiaoleGundeMac-Pro  ~/github/dump/bootedit   master ?  adb shell getprop ro.product.manufacturer&lt;br /&gt;
 Xiaomi # 无论打印出来的内容是大写还是小写，在目录结构中我们都采用小写&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/dump/bootedit   master ?  adb shell getprop ro.product.device&lt;br /&gt;
 rubens&amp;lt;/code&amp;gt;&lt;br /&gt;
我的 IQOO NEO5 Lite 会打印以下信息&lt;br /&gt;
 &amp;lt;code&amp;gt;xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  adb shell getprop ro.product.manufacturer&lt;br /&gt;
 vivo&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  adb shell getprop ro.product.device&lt;br /&gt;
 PD2118&amp;lt;/code&amp;gt;&lt;br /&gt;
一般只要不是山寨机，小作坊出来的机子，用这两条命令应该是可以正确获取的。&lt;br /&gt;
&lt;br /&gt;
=== 初始化构建时必要的文件 ===&lt;br /&gt;
无论是 AOSP device tree 亦或是 TWRP device tree 都基本类似于以下结构。&lt;br /&gt;
 &amp;lt;code&amp;gt;/&lt;br /&gt;
 ├── prebuilt           (存放kernel、dtb等预编译文件) # AOSP device tree若使用build kernel则没有该目录&lt;br /&gt;
 ├── recovery/root      (存放一些.rc和解密blobs) # 一般用于Recovery device tree&lt;br /&gt;
 ├── Android.mk         (Android构建系统首先会检查每个目录的Android.mk，里面包含一些判断，由它包括其所在目录中所有Makefile)&lt;br /&gt;
 ├── AndroidProducts.mk (声明产品的Makefile和lunch时可用的构建类型)&lt;br /&gt;
 ├── BoardConfig.mk     (板载配置文件，定义了主板必要的Flag)&lt;br /&gt;
 ├── device.mk          (声明设备所需的文件和模块)&lt;br /&gt;
 └── &amp;lt;ROM&amp;gt;_codename.mk  (声明产品特定信息，例如名称、品牌和型号，引用device.mk等) # ROM就比如lineage、arrow等，编译twrp就直接写twrp，twrp-9分支要写onmi&amp;lt;/code&amp;gt;&lt;br /&gt;
我们把这样的结构称为骨架树(skeleton tree)。&lt;br /&gt;
&lt;br /&gt;
接下来我们按照以上结构为自己的设备写一份 Recovery device tree。&lt;br /&gt;
&lt;br /&gt;
在终端使用&amp;lt;code&amp;gt;touch&amp;lt;/code&amp;gt;命令创建必要的文件。&lt;br /&gt;
 &amp;lt;code&amp;gt;touch Android.mk AndroidProducts.mk BoardConfig.mk device.mk twrp_rubens.mk&lt;br /&gt;
 ls .&amp;lt;/code&amp;gt;&lt;br /&gt;
不出意外的话会打印出以下信息&lt;br /&gt;
 &amp;lt;code&amp;gt;xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  touch Android.mk AndroidProducts.mk BoardConfig.mk device.mk twrp_rubens.mk&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/tmp/device/xiaomi/rubens  ls .&lt;br /&gt;
 Android.mk         BoardConfig.mk     prebuilt           twrp_rubens.mk&lt;br /&gt;
 AndroidProducts.mk device.mk          recovery&amp;lt;/code&amp;gt;&lt;br /&gt;
可以下一步了~&lt;br /&gt;
&lt;br /&gt;
==== 初始 Android.mk 文件 ====&lt;br /&gt;
打开 Vscode 并打开设备树目录，你足够强也可以使用 nano、vim 编辑。&lt;br /&gt;
&lt;br /&gt;
选中 Android.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 &amp;lt;code&amp;gt;LOCAL_PATH := $(call my-dir)&lt;br /&gt;
 &lt;br /&gt;
 ifeq ($(TARGET_DEVICE),codename)&lt;br /&gt;
 include $(call all-subdir-makefiles,$(LOCAL_PATH))&lt;br /&gt;
 endif&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;codename&amp;lt;/code&amp;gt;是需要你修改的部分&lt;br /&gt;
&lt;br /&gt;
我修改后是这样的&lt;br /&gt;
 &amp;lt;code&amp;gt;LOCAL_PATH := $(call my-dir)&lt;br /&gt;
 &lt;br /&gt;
 ifeq ($(TARGET_DEVICE),rubens)&lt;br /&gt;
 include $(call all-subdir-makefiles,$(LOCAL_PATH))&lt;br /&gt;
 endif&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 初始 AndroidProducts.mk 文件 ====&lt;br /&gt;
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 &amp;lt;code&amp;gt;PRODUCT_MAKEFILES := \&lt;br /&gt;
     $(LOCAL_DIR)/&amp;lt;ROM&amp;gt;_&amp;lt;codename&amp;gt;.mk&lt;br /&gt;
 &lt;br /&gt;
 COMMON_LUNCH_CHOICES := \&lt;br /&gt;
     &amp;lt;ROM&amp;gt;_&amp;lt;codename&amp;gt;-eng&amp;lt;/code&amp;gt;&lt;br /&gt;
我修改后是这样的&lt;br /&gt;
 &amp;lt;code&amp;gt;PRODUCT_MAKEFILES := \&lt;br /&gt;
     $(LOCAL_DIR)/twrp_rubens.mk&lt;br /&gt;
 &lt;br /&gt;
 COMMON_LUNCH_CHOICES := \&lt;br /&gt;
     twrp_rubens-eng&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 初始 BoardConfig.mk 文件 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;将之前准备的&amp;lt;code&amp;gt;ramdisk&amp;lt;/code&amp;gt;文件夹用新窗口打开 1.找到目录下的 prop.default 或含 prop 字样的文件。以下注释类似 ro.*.*的就是从 prop 中获取的 2.解包 boot/recovery/vendor_boot 的 json&lt;br /&gt;
&lt;br /&gt;
例如 build/unzip_boot/boot.json&amp;lt;/blockquote&amp;gt;选中 BoardConfig.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 &amp;lt;code&amp;gt;DEVICE_PATH := device/vendor/codename&lt;br /&gt;
 &lt;br /&gt;
 # Architecture&lt;br /&gt;
 TARGET_ARCH := arm64 # ro.bionic.arch&lt;br /&gt;
 TARGET_ARCH_VARIANT := armv8-a # 64位默认变体&lt;br /&gt;
 TARGET_CPU_ABI := arm64-v8a # ro.vendor.product.cpu.abilist64 (至少在小米设备上没有找到ro.product.cpu.abilist)&lt;br /&gt;
 TARGET_CPU_ABI2 := # 64位留空&lt;br /&gt;
 TARGET_CPU_VARIANT := generic # 默认一般都是通用&lt;br /&gt;
 TARGET_CPU_VARIANT_RUNTIME := cortex-a55 # ro.bionic.cpu_variant&lt;br /&gt;
 &lt;br /&gt;
 TARGET_2ND_ARCH := arm # ro.bionic.2nd_arch&lt;br /&gt;
 TARGET_2ND_ARCH_VARIANT := $(TARGET_ARCH_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_ABI := armeabi-v7a # ro.vendor.product.cpu.abilist32第一个&lt;br /&gt;
 TARGET_2ND_CPU_ABI2 := armeabi # ro.vendor.product.cpu.abilist32第二个&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT_RUNTIME := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 &lt;br /&gt;
 # Assertation&lt;br /&gt;
 TARGET_OTA_ASSERT_DEVICE := rubens # codename&lt;br /&gt;
 &lt;br /&gt;
 # Bootloader&lt;br /&gt;
 TARGET_BOOTLOADER_BOARD_NAME := rubens # ro.product.board&lt;br /&gt;
 TARGET_NO_BOOTLOADER := true&lt;br /&gt;
 TARGET_USES_UEFI := true&lt;br /&gt;
 &lt;br /&gt;
 # Build Rule&lt;br /&gt;
 ALLOW_MISSING_DEPENDENCIES := true # 为了recovery不健全的依赖&lt;br /&gt;
 &lt;br /&gt;
 # Kernel - 注释会说明在boot/recovery/vendor_boot.json中对应的变量&lt;br /&gt;
 BOARD_BOOTIMG_HEADER_VERSION := 4 # headerVersion&lt;br /&gt;
 BOARD_KERNEL_BASE := 0x3fff8000 # (kernelLoadAddr - 32KB) qcom设备base为0，且没有偏移(offset)&lt;br /&gt;
 BOARD_KERNEL_CMDLINE := bootopt=64S3,32N2,64N2 # cmdline&lt;br /&gt;
 BOARD_KERNEL_PAGESIZE := 4096 # pageSize&lt;br /&gt;
 BOARD_RAMDISK_OFFSET := 0x26f08000 # (ramdisk,loadAddr - BOARD_KERNEL_BASE)&lt;br /&gt;
 BOARD_KERNEL_TAGS_OFFSET := 0x07c88000 # (tagsLoadAddr - BOARD_KERNEL_BASE)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOTIMG_HEADER_VERSION)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --ramdisk_offset $(BOARD_RAMDISK_OFFSET)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --tags_offset $(BOARD_KERNEL_TAGS_OFFSET)&lt;br /&gt;
 &lt;br /&gt;
 # Kernel - prebuilt&lt;br /&gt;
 TARGET_PREBUILT_KERNEL := $(DEVICE_PATH)/prebuilt/kernel # 预编译内核相对于android源码根目录的相对路径，vendor_boot机型不需要&lt;br /&gt;
 TARGET_PREBUILT_DTB := $(DEVICE_PATH)/prebuilt/dtb.img # 同上&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --dtb $(TARGET_PREBUILT_DTB)&lt;br /&gt;
 &lt;br /&gt;
 # Partitions&lt;br /&gt;
 BOARD_FLASH_BLOCK_SIZE := 262144 # (BOARD_KERNEL_PAGESIZE * 64)&lt;br /&gt;
 BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864 # boot/recovery/vendor_boot镜像的字节大小需原厂或手机完整提取出来的，不定义会报错&lt;br /&gt;
 BOARD_RECOVERYIMAGE_PARTITION_SIZE := 67108864 # 同上&lt;br /&gt;
 BOARD_VENDOR_ROOTIMAGE_PARTITION_SIZE := 67108864 # 同上&lt;br /&gt;
 BOARD_SYSTEMIMAGE_PARTITION_TYPE := ext4 # 分区类型，查看ramdisk中fstab定义的类型&lt;br /&gt;
 BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 TARGET_COPY_OUT_VENDOR := vendor # 定义vendor目录，例如copy专有blobs要用&lt;br /&gt;
 BOARD_SUPER_PARTITION_SIZE := 9126805504 # 可以通过blockdev --getsize64 /dev/block/bootdevice/by-name/super获取，需root，如果无法root可以直接使用这个值，不影响twrp启动，可以后续修正&lt;br /&gt;
 BOARD_SUPER_PARTITION_GROUPS := xiaomi_dynamic_partitions # xiaomi根据你获取资料的vendor替换，是一个动态分区组&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product system_ext odm vendor_dlkm odm_dlkm # 根据fstab内的定义，一般flag包含logical都属于动态分区组的一部分&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_SIZE := 9122611200 # (BOARD_SUPER_PARTITION_SIZE - 4MB)&lt;br /&gt;
 &lt;br /&gt;
 # Platform&lt;br /&gt;
 TARGET_BOARD_PLATFORM := mt6895 # ro.board.platform&lt;br /&gt;
 &lt;br /&gt;
 # Recovery - 基本通用的不影响启动&lt;br /&gt;
 BOARD_HAS_LARGE_FILESYSTEM := true&lt;br /&gt;
 TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888&lt;br /&gt;
 TARGET_USERIMAGES_USE_EXT4 := true&lt;br /&gt;
 TARGET_USERIMAGES_USE_F2FS := true&lt;br /&gt;
 &lt;br /&gt;
 # Treble&lt;br /&gt;
 BOARD_VNDK_VERSION := current # 声明VNDK版本&lt;br /&gt;
 &lt;br /&gt;
 # Vendor_boot recovery ramdisk&lt;br /&gt;
 BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true # 将recovery文件复制到vendor_boot&lt;br /&gt;
 &lt;br /&gt;
 # Boot recovery ramdisk&lt;br /&gt;
 #BOARD_USES_RECOVERY_AS_BOOT := true recovery ramdisk合并在boot中启用&lt;br /&gt;
 &lt;br /&gt;
 # Verified Boot&lt;br /&gt;
 BOARD_AVB_ENABLE := true&lt;br /&gt;
 BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flags 3&lt;br /&gt;
 &lt;br /&gt;
 # TWRP Configurations&lt;br /&gt;
 TW_DEFAULT_LANGUAGE := zh_CN # 默认为中文&lt;br /&gt;
 TW_EXTRA_LANGUAGES := true # 额外的语言&lt;br /&gt;
 TW_THEME := portrait_hdpi # 主题&lt;br /&gt;
 TW_INCLUDE_FASTBOOTD := true # 包括fastbootd，为动态分区&lt;br /&gt;
 &lt;br /&gt;
 # 其它flag还有很多，可以在https://xdaforums.com/t/twrp-flags-for-boardconfig-mk.3333970 查找，&lt;br /&gt;
 # 这篇文章也很老了，但我并不推荐twrp，所以flag我也不是很了解，多翻翻github:)&lt;br /&gt;
 &lt;br /&gt;
 # Debug&lt;br /&gt;
 TARGET_USES_LOGD := true # 调试flag&lt;br /&gt;
 TWRP_INCLUDE_LOGCAT := true&amp;lt;/code&amp;gt;&lt;br /&gt;
无注释版&lt;br /&gt;
 &amp;lt;code&amp;gt;DEVICE_PATH := device/vendor/codename&lt;br /&gt;
 &lt;br /&gt;
 # Architecture&lt;br /&gt;
 TARGET_ARCH := arm64&lt;br /&gt;
 TARGET_ARCH_VARIANT := armv8-a&lt;br /&gt;
 TARGET_CPU_ABI := arm64-v8a&lt;br /&gt;
 TARGET_CPU_ABI2 :=&lt;br /&gt;
 TARGET_CPU_VARIANT := generic&lt;br /&gt;
 TARGET_CPU_VARIANT_RUNTIME := cortex-a55&lt;br /&gt;
 &lt;br /&gt;
 TARGET_2ND_ARCH := arm&lt;br /&gt;
 TARGET_2ND_ARCH_VARIANT := $(TARGET_ARCH_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_ABI := armeabi-v7a&lt;br /&gt;
 TARGET_2ND_CPU_ABI2 := armeabi&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 TARGET_2ND_CPU_VARIANT_RUNTIME := $(TARGET_CPU_VARIANT)&lt;br /&gt;
 &lt;br /&gt;
 # Assertation&lt;br /&gt;
 TARGET_OTA_ASSERT_DEVICE := rubens&lt;br /&gt;
 &lt;br /&gt;
 # Bootloader&lt;br /&gt;
 TARGET_BOOTLOADER_BOARD_NAME := rubens&lt;br /&gt;
 TARGET_NO_BOOTLOADER := true&lt;br /&gt;
 TARGET_USES_UEFI := true&lt;br /&gt;
 &lt;br /&gt;
 # Build Rule&lt;br /&gt;
 ALLOW_MISSING_DEPENDENCIES := true&lt;br /&gt;
 &lt;br /&gt;
 # Kernel&lt;br /&gt;
 BOARD_BOOT_HEADER_VERSION := 4&lt;br /&gt;
 BOARD_KERNEL_BASE := 0x3fff8000&lt;br /&gt;
 BOARD_KERNEL_CMDLINE := bootopt=64S3,32N2,64N2&lt;br /&gt;
 BOARD_KERNEL_PAGESIZE := 4096&lt;br /&gt;
 BOARD_RAMDISK_OFFSET := 0x26f08000&lt;br /&gt;
 BOARD_KERNEL_TAGS_OFFSET := 0x07c88000&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --ramdisk_offset $(BOARD_RAMDISK_OFFSET)&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --tags_offset $(BOARD_KERNEL_TAGS_OFFSET)&lt;br /&gt;
 BOARD_KERNEL_IMAGE_NAME := Image&lt;br /&gt;
 &lt;br /&gt;
 # Kernel - prebuilt&lt;br /&gt;
 TARGET_PREBUILT_DTB := $(DEVICE_PATH)/prebuilt/dtb.img&lt;br /&gt;
 BOARD_MKBOOTIMG_ARGS += --dtb $(TARGET_PREBUILT_DTB)&lt;br /&gt;
 &lt;br /&gt;
 # Partitions&lt;br /&gt;
 BOARD_FLASH_BLOCK_SIZE := 262144&lt;br /&gt;
 BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864&lt;br /&gt;
 BOARD_RECOVERYIMAGE_PARTITION_SIZE := 67108864&lt;br /&gt;
 BOARD_VENDOR_ROOTIMAGE_PARTITION_SIZE := 67108864&lt;br /&gt;
 BOARD_SYSTEMIMAGE_PARTITION_TYPE := ext4&lt;br /&gt;
 BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4&lt;br /&gt;
 TARGET_COPY_OUT_VENDOR := vendor&lt;br /&gt;
 BOARD_SUPER_PARTITION_SIZE := 9126805504&lt;br /&gt;
 BOARD_SUPER_PARTITION_GROUPS := xiaomi_dynamic_partitions&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product system_ext odm vendor_dlkm odm_dlkm&lt;br /&gt;
 BOARD_XIAOMI_DYNAMIC_PARTITIONS_SIZE := 9122611200&lt;br /&gt;
 &lt;br /&gt;
 # Platform&lt;br /&gt;
 TARGET_BOARD_PLATFORM := mt6895&lt;br /&gt;
 &lt;br /&gt;
 # Recovery&lt;br /&gt;
 BOARD_HAS_LARGE_FILESYSTEM := true&lt;br /&gt;
 TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888&lt;br /&gt;
 TARGET_USERIMAGES_USE_EXT4 := true&lt;br /&gt;
 TARGET_USERIMAGES_USE_F2FS := true&lt;br /&gt;
 &lt;br /&gt;
 # Treble&lt;br /&gt;
 BOARD_VNDK_VERSION := current&lt;br /&gt;
 &lt;br /&gt;
 # Vendor_boot recovery ramdisk&lt;br /&gt;
 BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true&lt;br /&gt;
 &lt;br /&gt;
 # Boot recovery ramdisk&lt;br /&gt;
 #BOARD_USES_RECOVERY_AS_BOOT := true&lt;br /&gt;
 &lt;br /&gt;
 # Verified Boot&lt;br /&gt;
 BOARD_AVB_ENABLE := true&lt;br /&gt;
 BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flags 3&lt;br /&gt;
 &lt;br /&gt;
 # TWRP Configurations&lt;br /&gt;
 TW_DEFAULT_LANGUAGE := zh_CN&lt;br /&gt;
 TW_EXTRA_LANGUAGES := true&lt;br /&gt;
 TW_THEME := portrait_hdpi&lt;br /&gt;
 TW_INCLUDE_FASTBOOTD := true&lt;br /&gt;
 &lt;br /&gt;
 # Debug&lt;br /&gt;
 TARGET_USES_LOGD := true&lt;br /&gt;
 TWRP_INCLUDE_LOGCAT := true&amp;lt;/code&amp;gt;&lt;br /&gt;
这块写了好久我也不确定对不对，请各位指正，尤其是 Kernel 部分。&lt;br /&gt;
&lt;br /&gt;
==== 初始 device.mk 文件 ====&lt;br /&gt;
&lt;br /&gt;
* 准备好 prop.default&lt;br /&gt;
&lt;br /&gt;
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 &amp;lt;code&amp;gt;DEVICE_PATH := device/xiaomi/rubens&lt;br /&gt;
 &lt;br /&gt;
 # API&lt;br /&gt;
 PRODUCT_SHIPPING_API_LEVEL := 31 # ro.board.first_api_level&lt;br /&gt;
 &lt;br /&gt;
 # A/B&lt;br /&gt;
 AB_OTA_UPDATER := true # 启用A/B无缝更新&lt;br /&gt;
 AB_OTA_PARTITIONS += \ # 定义A/B分区，参考fstab&lt;br /&gt;
     boot \&lt;br /&gt;
     dtbo \&lt;br /&gt;
     system \&lt;br /&gt;
     product \&lt;br /&gt;
     vendor \&lt;br /&gt;
     odm \&lt;br /&gt;
     odm_dlkm \&lt;br /&gt;
     vbmeta \&lt;br /&gt;
     vendor_boot \&lt;br /&gt;
     vendor_dlkm \&lt;br /&gt;
     vbmeta_system \&lt;br /&gt;
     vbmeta_vendor&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PACKAGES += \&lt;br /&gt;
     update_engine \&lt;br /&gt;
     update_engine_sideload \&lt;br /&gt;
     update_verifier \&lt;br /&gt;
     checkpoint_gc&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_system=true \&lt;br /&gt;
     POSTINSTALL_PATH_system=system/bin/mtk_plpath_utils \&lt;br /&gt;
     FILESYSTEM_TYPE_system=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_system=true&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_vendor=true \&lt;br /&gt;
     POSTINSTALL_PATH_vendor=bin/checkpoint_gc \&lt;br /&gt;
     FILESYSTEM_TYPE_vendor=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_vendor=true&lt;br /&gt;
 &lt;br /&gt;
 # Dynamic&lt;br /&gt;
 PRODUCT_USE_DYNAMIC_PARTITIONS := true # 动态分区&lt;br /&gt;
 &lt;br /&gt;
 # Soong namespaces&lt;br /&gt;
 PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH) # 命名空间&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* A/B 无缝更新部分高通和联发科不一样，联发科设备可以照抄，注意 system/bin/mtk_plpath_utils 就好。高通参考[https://github.com/sekaiacg/android_device_xiaomi_venus_TWRP/tree/android-13 venus twrp tree]，并且高通的[https://git.codelinaro.org/clo/la/platform/hardware/qcom/bootctrl bootctrl]和[https://git.codelinaro.org/clo/la/platform/vendor/qcom-opensource/recovery-ext gpt-utils]可以从 CLO 拿。&lt;br /&gt;
&lt;br /&gt;
无注释版&lt;br /&gt;
 &amp;lt;code&amp;gt;PRODUCT_SHIPPING_API_LEVEL := 31&lt;br /&gt;
 &lt;br /&gt;
 # A/B&lt;br /&gt;
 AB_OTA_UPDATER := true&lt;br /&gt;
 AB_OTA_PARTITIONS += \&lt;br /&gt;
     boot \&lt;br /&gt;
     dtbo \&lt;br /&gt;
     system \&lt;br /&gt;
     product \&lt;br /&gt;
     vendor \&lt;br /&gt;
     odm \&lt;br /&gt;
     odm_dlkm \&lt;br /&gt;
     vbmeta \&lt;br /&gt;
     vendor_boot \&lt;br /&gt;
     vendor_dlkm \&lt;br /&gt;
     vbmeta_system \&lt;br /&gt;
     vbmeta_vendor&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PACKAGES += \&lt;br /&gt;
     update_engine \&lt;br /&gt;
     update_engine_sideload \&lt;br /&gt;
     update_verifier \&lt;br /&gt;
     checkpoint_gc&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_system=true \&lt;br /&gt;
     POSTINSTALL_PATH_system=system/bin/mtk_plpath_utils \&lt;br /&gt;
     FILESYSTEM_TYPE_system=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_system=true&lt;br /&gt;
 &lt;br /&gt;
 AB_OTA_POSTINSTALL_CONFIG += \&lt;br /&gt;
     RUN_POSTINSTALL_vendor=true \&lt;br /&gt;
     POSTINSTALL_PATH_vendor=bin/checkpoint_gc \&lt;br /&gt;
     FILESYSTEM_TYPE_vendor=ext4 \&lt;br /&gt;
     POSTINSTALL_OPTIONAL_vendor=true&lt;br /&gt;
 &lt;br /&gt;
 # Dynamic&lt;br /&gt;
 PRODUCT_USE_DYNAMIC_PARTITIONS := true&lt;br /&gt;
 &lt;br /&gt;
 # Soong namespaces&lt;br /&gt;
 PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 初始 twrp_rubens.mk 文件 ====&lt;br /&gt;
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容&lt;br /&gt;
 &amp;lt;code&amp;gt;# Inherit from common AOSP config&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk) # vab加载到vendor boot里使用&lt;br /&gt;
 &lt;br /&gt;
 # Inherit from TWRP product configuration&lt;br /&gt;
 $(call inherit-product, vendor/twrp/config/common.mk) # twrp-9分支改为onmi&lt;br /&gt;
 &lt;br /&gt;
 # Device specific configs&lt;br /&gt;
 $(call inherit-product, device/xiaomi/rubens/device.mk)&lt;br /&gt;
 &lt;br /&gt;
 # Device identifier&lt;br /&gt;
 PRODUCT_DEVICE := rubens # 设备型号&lt;br /&gt;
 PRODUCT_NAME := twrp_rubens # 设备名称&lt;br /&gt;
 PRODUCT_BRAND := Redmi # 自定义品牌，如果有&lt;br /&gt;
 PRODUCT_MODEL := 22041211AC # 产品最终用户可见名称&lt;br /&gt;
 PRODUCT_MANUFACTURER := Xiaomi # 制造商&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true # 对twrp启动vendor_boot支持&amp;lt;/code&amp;gt;&lt;br /&gt;
无注释版&lt;br /&gt;
 &amp;lt;code&amp;gt;# Inherit from common AOSP config&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)&lt;br /&gt;
 $(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk) # vab加载到vendor boot里使用&lt;br /&gt;
 &lt;br /&gt;
 # Inherit from TWRP product configuration&lt;br /&gt;
 $(call inherit-product, vendor/twrp/config/common.mk)&lt;br /&gt;
 &lt;br /&gt;
 # Device specific configs&lt;br /&gt;
 $(call inherit-product, device/xiaomi/rubens/device.mk)&lt;br /&gt;
 &lt;br /&gt;
 # Device identifier&lt;br /&gt;
 PRODUCT_DEVICE := rubens&lt;br /&gt;
 PRODUCT_NAME := twrp_rubens&lt;br /&gt;
 PRODUCT_BRAND := Redmi&lt;br /&gt;
 PRODUCT_MODEL := 22041211AC&lt;br /&gt;
 PRODUCT_MANUFACTURER := Xiaomi&lt;br /&gt;
 &lt;br /&gt;
 PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 初始 recovery 目录 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;拿出我们好久之前准备的 ramdisk 叭&amp;lt;/blockquote&amp;gt;通过&amp;lt;code&amp;gt;tree&amp;lt;/code&amp;gt;命令我们可以查看 ramdisk 的树状图，可以很清晰的查看包含的文件&lt;br /&gt;
 &amp;lt;code&amp;gt;├── acct&lt;br /&gt;
 ├── apex&lt;br /&gt;
 ├── bin -&amp;gt; /system/bin&lt;br /&gt;
 ├── bugreports -&amp;gt; /data/user_de/0/com.android.shell/files/bugreports&lt;br /&gt;
 ├── config&lt;br /&gt;
 ├── d -&amp;gt; /sys/kernel/debug&lt;br /&gt;
 ├── data&lt;br /&gt;
 ├── data_mirror&lt;br /&gt;
 ├── debug_ramdisk&lt;br /&gt;
 ├── default.prop -&amp;gt; prop.default&lt;br /&gt;
 ├── dev&lt;br /&gt;
 ├── etc -&amp;gt; /system/etc&lt;br /&gt;
 ├── first_stage_ramdisk&lt;br /&gt;
 │   ├── fstab.emmc&lt;br /&gt;
 │   ├── fstab.mt6895&lt;br /&gt;
 │   └── system&lt;br /&gt;
 │       ├── bin&lt;br /&gt;
 │       │   ├── e2fsck&lt;br /&gt;
 │       │   ├── linker64&lt;br /&gt;
 │       │   ├── linker_asan64 -&amp;gt; linker64&lt;br /&gt;
 │       │   └── snapuserd&lt;br /&gt;
 │       └── lib64&lt;br /&gt;
 │           ├── ld-android.so&lt;br /&gt;
 │           ├── libbase.so&lt;br /&gt;
 │           ├── libc++.so&lt;br /&gt;
 │           ├── libc.so&lt;br /&gt;
 │           ├── libdl.so&lt;br /&gt;
 │           ├── libext2_blkid.so&lt;br /&gt;
 │           ├── libext2_com_err.so&lt;br /&gt;
 │           ├── libext2_e2p.so&lt;br /&gt;
 │           ├── libext2_quota.so&lt;br /&gt;
 │           ├── libext2_uuid.so&lt;br /&gt;
 │           ├── libext2fs.so&lt;br /&gt;
 │           ├── liblog.so&lt;br /&gt;
 │           ├── libm.so&lt;br /&gt;
 │           ├── libsparse.so&lt;br /&gt;
 │           └── libz.so&lt;br /&gt;
 ├── init -&amp;gt; /system/bin/init&lt;br /&gt;
 ├── init.recovery.hardware.rc&lt;br /&gt;
 ├── init.recovery.mt6895.rc&lt;br /&gt;
 └── 等等等等...省略大概1000个文件吧&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;因为避免教程时效性，我们尽可能选取 prebuilt 的办法，如 boot 和 mtk_plpath_utils 都采用预编译。&amp;lt;/blockquote&amp;gt;里面有很多文件是没用的，整理一下，对我们有用的只有这些&lt;br /&gt;
 &amp;lt;code&amp;gt;.&lt;br /&gt;
 ├── first_stage_ramdisk&lt;br /&gt;
 │   ├── fstab.emmc&lt;br /&gt;
 │   └── fstab.mt6895&lt;br /&gt;
 ├── init.recovery.mt6895.rc&lt;br /&gt;
 ├── lib&lt;br /&gt;
 │   └── modules&lt;br /&gt;
 │       ├── 8250_mtk.ko&lt;br /&gt;
 │       ├── adapter_class.ko&lt;br /&gt;
 │       ├── adsp.ko&lt;br /&gt;
 │       ├── aee_aed.ko&lt;br /&gt;
 │       ├── aee_hangdet.ko&lt;br /&gt;
 │       ├── aee_rs.ko&lt;br /&gt;
 │       ├── blocktag.ko&lt;br /&gt;
 │       ├── bootprof.ko&lt;br /&gt;
 │       ├── bq28z610.ko&lt;br /&gt;
 │       ├── cache-parity.ko&lt;br /&gt;
 │       ├── cfg80211.ko&lt;br /&gt;
 │       ├── charger_class.ko&lt;br /&gt;
 │       └── 省略一百多个模块，这个目录里的东西全要&lt;br /&gt;
 └── system&lt;br /&gt;
     ├── bin&lt;br /&gt;
     │   └── mtk_plpath_utils&lt;br /&gt;
     ├── etc&lt;br /&gt;
     │   ├── init&lt;br /&gt;
     │   │   │── mtk-plpath-utils.rc&lt;br /&gt;
     │   │   └──hw&lt;br /&gt;
     │   │      └──init.rc&lt;br /&gt;
     │   ├── recovery.fstab&lt;br /&gt;
     │   ├── security&lt;br /&gt;
     │   │   └── otacerts.zip&lt;br /&gt;
     │   └── ueventd.rc&lt;br /&gt;
     └── lib64&lt;br /&gt;
         └── hw&lt;br /&gt;
             └── android.hardware.boot@1.0-impl-1.2-mtkimpl.so&amp;lt;/code&amp;gt;&lt;br /&gt;
将它们按照以下操作复制&lt;br /&gt;
&lt;br /&gt;
* first_stage_ramdisk --&amp;gt; recovery/root/first_stage_ramdisk&lt;br /&gt;
* init.recovery.mt6895.rc --&amp;gt; recovery/root/init.recovery.mt6895.rc&lt;br /&gt;
* lib --&amp;gt; recovery/root/lib&lt;br /&gt;
* system --&amp;gt; recovery/root/system (security 和 hw 文件夹里的内容作为备用，不要复制进去) 得到以下目录结构&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;code&amp;gt;.&lt;br /&gt;
 ├── Android.mk&lt;br /&gt;
 ├── AndroidProducts.mk&lt;br /&gt;
 ├── BoardConfig.mk&lt;br /&gt;
 ├── device.mk&lt;br /&gt;
 ├── prebuilt&lt;br /&gt;
 ├── recovery&lt;br /&gt;
 │   └── root&lt;br /&gt;
 │       ├── first_stage_ramdisk&lt;br /&gt;
 │       │   ├── fstab.emmc&lt;br /&gt;
 │       │   └── fstab.mt6895&lt;br /&gt;
 │       ├── init.recovery.mt6895.rc&lt;br /&gt;
 │       ├── lib&lt;br /&gt;
 │       │   └── modules&lt;br /&gt;
 │       │       ├── 8250_mtk.ko&lt;br /&gt;
 │       │       ├── adapter_class.ko&lt;br /&gt;
 │       │       ├── adsp.ko&lt;br /&gt;
 │       │       ├── aee_aed.ko&lt;br /&gt;
 │       │       ├── aee_hangdet.ko&lt;br /&gt;
 │       │       ├── aee_rs.ko&lt;br /&gt;
 │       │       ├── blocktag.ko&lt;br /&gt;
 │       │       └── 省略....&lt;br /&gt;
 │       └── system&lt;br /&gt;
 │           ├── bin&lt;br /&gt;
 │           │   └── mtk_plpath_utils&lt;br /&gt;
 │           ├── etc&lt;br /&gt;
 │           │   ├── recovery.fstab&lt;br /&gt;
 │           │   └── ueventd.rc&lt;br /&gt;
 │           └── lib64&lt;br /&gt;
 │               └── hw&lt;br /&gt;
 │                   └── android.hardware.boot@1.0-impl-1.2-mtkimpl.so&lt;br /&gt;
 └── twrp_rubens.mk&amp;lt;/code&amp;gt;&lt;br /&gt;
打开 init.recovery.mt6895.rc 添加&lt;br /&gt;
 &amp;lt;code&amp;gt;on boot&lt;br /&gt;
     start health-hal-2-1&lt;br /&gt;
 &lt;br /&gt;
 on post-fs&lt;br /&gt;
     start boot-hal-1-2&amp;lt;/code&amp;gt;&lt;br /&gt;
例如&lt;br /&gt;
 &amp;lt;code&amp;gt;on post-fs&lt;br /&gt;
     start boot-hal-1-2&lt;br /&gt;
 &lt;br /&gt;
 on init&lt;br /&gt;
     setprop sys.usb.configfs 1&lt;br /&gt;
     setprop sys.usb.controller &amp;quot;11201000.usb0&amp;quot;&lt;br /&gt;
     setprop sys.usb.ffs.aio_compat 1&lt;br /&gt;
 &lt;br /&gt;
 on fs &amp;amp;&amp;amp; property:ro.debuggable=0&lt;br /&gt;
     # distinguish USB shoulde connect or not, i.e. CDP vs SDP&lt;br /&gt;
     # set charging free due to it wait for USB activation&lt;br /&gt;
 &lt;br /&gt;
 on boot&lt;br /&gt;
     start health-hal-2-1&lt;br /&gt;
     exec u:r:update_engine:s0 root root -- /system/bin/mtk_plpath_utils&amp;lt;/code&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
接下来可以开始编译咯~~&lt;br /&gt;
&lt;br /&gt;
==== 编译 ====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;编译前请检查注释是否全部删除&amp;lt;/blockquote&amp;gt;twrp 源码根目录执行&lt;br /&gt;
 &amp;lt;code&amp;gt;. build/envsetup.sh&lt;br /&gt;
 lunch twrp_codename-eng # twrp-9为onmi&lt;br /&gt;
 mka vendorbootimg/bootimage/recoveryimage&amp;lt;/code&amp;gt;&lt;br /&gt;
不出意外的话一路绿灯，如果有报错的话请发邮箱至 1592501605@qq.com 咨询我&lt;br /&gt;
&lt;br /&gt;
产物在 &amp;lt;code&amp;gt;out/target/product/codename/vendor_boot.img\boot.img\recovery.img&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
手机重启到 fastboot 模式，使用 fastboot flash 刷写，例如&lt;br /&gt;
 &amp;lt;code&amp;gt;fastboot flash vendor_boot /Users/xiaolegun/Downloads/vendor_boot.img&amp;lt;/code&amp;gt;&lt;br /&gt;
则输出&lt;br /&gt;
 &amp;lt;code&amp;gt;ERROR: could not clear input pipe; result e0005000, ignoring...&lt;br /&gt;
 ERROR: could not clear output pipe; result e0005000, ignoring....&lt;br /&gt;
 Sending 'vendor_boot_a' (65536 KB)                 OKAY [  1.396s]&lt;br /&gt;
 Writing 'vendor_boot_a'                            OKAY [  0.167s]&lt;br /&gt;
 Finished. Total time: 1.625s&amp;lt;/code&amp;gt;&lt;br /&gt;
就可以重启按电源加音量上尝试了，我自己是一次点亮，但有 bug。&lt;br /&gt;
&lt;br /&gt;
==== 修 BUG ====&lt;br /&gt;
&lt;br /&gt;
===== 修复 USB =====&lt;br /&gt;
我看到 twrp 控制台有很多报错，第一步肯定是先获取日志，使用&amp;lt;code&amp;gt;logcat&amp;lt;/code&amp;gt;命令获取，在此之前先使用&amp;lt;code&amp;gt;adb devices&amp;lt;/code&amp;gt;检测一下设备 usb 是否工作正常。&lt;br /&gt;
 &amp;lt;code&amp;gt;xiaolegun@xiaoleGundeMac-Pro  ~  adb devices          ✔  10208  10:05:31&lt;br /&gt;
 * daemon not running; starting now at tcp:5037&lt;br /&gt;
 * daemon started successfully&lt;br /&gt;
 List of devices attached&amp;lt;/code&amp;gt;&lt;br /&gt;
可以看到&amp;lt;code&amp;gt;adb&amp;lt;/code&amp;gt;没有检测到设备，原因一般是 usb 的配置不对，但 usb 是好的。这时可以尝试关闭 mtp，再开启，如果电脑有反应，那么就可以继续下一步了。&lt;br /&gt;
&lt;br /&gt;
在设备树中的 recovery/root，创建 init.recovery.usb.rc 的文件&lt;br /&gt;
 &amp;lt;code&amp;gt;touch recovery/root/init.recovery.usb.rc&amp;lt;/code&amp;gt;&lt;br /&gt;
并导入以下内容&lt;br /&gt;
 &amp;lt;code&amp;gt;on property:sys.usb.config=mtp,adb&lt;br /&gt;
     start adbd&lt;br /&gt;
 &lt;br /&gt;
 on property:sys.usb.ffs.ready=1 &amp;amp;&amp;amp; property:sys.usb.config=mtp,adb&lt;br /&gt;
     write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration &amp;quot;mtp_adb&amp;quot;&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f3&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f4&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f5&lt;br /&gt;
     write /config/usb_gadget/g1/idVendor 0x18d1&lt;br /&gt;
     write /config/usb_gadget/g1/idProduct 0x2d08&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}&lt;br /&gt;
     setprop sys.usb.state ${sys.usb.config}&amp;lt;/code&amp;gt;&lt;br /&gt;
这是我从我维护的 MI 6X 的 device tree 拿过来的，可以在联发科设备上正常工作。这段 shell 的大致意思就是在 usb 配置节点写入 mtp 和 adb 同时工作的字符串，这样 adb 就能顺利工作了。&lt;br /&gt;
&lt;br /&gt;
此外打开原厂 init.rc 修正一下 usb 设备的 id&lt;br /&gt;
 &amp;lt;code&amp;gt;# MIUI ADD: START&lt;br /&gt;
 import /init.recovery.hardware.rc&lt;br /&gt;
 import /miui.factoryreset.rc&lt;br /&gt;
 # END&lt;br /&gt;
 import /init.recovery.${ro.hardware}.rc&lt;br /&gt;
 &lt;br /&gt;
 ########### 省略一万字&lt;br /&gt;
 &lt;br /&gt;
 # MIUI ADD: START&lt;br /&gt;
 on property:sys.usb.config=mtp,adb &amp;amp;&amp;amp; property:sys.usb.configfs=0&lt;br /&gt;
     write /sys/class/android_usb/android0/enable 0&lt;br /&gt;
     write /sys/class/android_usb/android0/idVendor 2717&lt;br /&gt;
     write /sys/class/android_usb/android0/idProduct 904D&lt;br /&gt;
     write /sys/class/android_usb/android0/functions mtp,adb&lt;br /&gt;
     write /sys/class/android_usb/android0/enable 1&lt;br /&gt;
     setprop sys.usb.state  ${sys.usb.config}&lt;br /&gt;
 # END&amp;lt;/code&amp;gt;&lt;br /&gt;
将&amp;lt;code&amp;gt;/sys/class/android_usb/android0/idVendor&amp;lt;/code&amp;gt;和&amp;lt;code&amp;gt;write /sys/class/android_usb/android0/idProduct&amp;lt;/code&amp;gt;后面的 id 分别替换到&amp;lt;code&amp;gt;/config/usb_gadget/g1/idVendor&amp;lt;/code&amp;gt;和&amp;lt;code&amp;gt;/config/usb_gadget/g1/idProduct&amp;lt;/code&amp;gt;处理完就是这样的。&lt;br /&gt;
 &amp;lt;code&amp;gt;on property:sys.usb.config=mtp,adb&lt;br /&gt;
     start adbd&lt;br /&gt;
 &lt;br /&gt;
 on property:sys.usb.ffs.ready=1 &amp;amp;&amp;amp; property:sys.usb.config=mtp,adb&lt;br /&gt;
     write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration &amp;quot;mtp_adb&amp;quot;&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f3&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f4&lt;br /&gt;
     rm /config/usb_gadget/g1/configs/b.1/f5&lt;br /&gt;
     write /config/usb_gadget/g1/idVendor 0x2717&lt;br /&gt;
     write /config/usb_gadget/g1/idProduct 0x904D&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1&lt;br /&gt;
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2&lt;br /&gt;
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}&lt;br /&gt;
     setprop sys.usb.state ${sys.usb.config}&amp;lt;/code&amp;gt;&lt;br /&gt;
接下来开机之后 adb 和 mtp 就能同时工作了。&lt;br /&gt;
&lt;br /&gt;
===== 修复 Resetprop =====&lt;br /&gt;
接下来就可以修复其它 bug 了，我看到控制台有一堆红色的报错:&lt;br /&gt;
 &amp;lt;code&amp;gt;E:Unknown File System:'/mi_ext'&lt;br /&gt;
 E:Unable to override 'external_storage.projid.enabled' due to missing libresetprop&lt;br /&gt;
 挂载“/data”失败(Invalid argument)&amp;lt;/code&amp;gt;&lt;br /&gt;
这三个报错中第二个最好修，第一个次之，第三个与解密有关，放在另一个大章节讲。&lt;br /&gt;
&lt;br /&gt;
第二个报错只需要在 BoardConfig.mk 中添加&lt;br /&gt;
 &amp;lt;code&amp;gt;# Tool&lt;br /&gt;
 TW_INCLUDE_RESETPROP := true&lt;br /&gt;
 TW_INCLUDE_LIBRESETPROP := true&amp;lt;/code&amp;gt;&lt;br /&gt;
不用编译测试直接秒杀&lt;br /&gt;
&lt;br /&gt;
===== 修复挂载 =====&lt;br /&gt;
 &amp;lt;code&amp;gt;E:Unknown File System:'/mi_ext'&amp;lt;/code&amp;gt;&lt;br /&gt;
我们打开 recovery/root/system/etc 中的 recovery.fstab，发现里面有很多空格，我们先将它格式化一下，有实力的可以把后面的 flag 也对齐整理好。&lt;br /&gt;
&lt;br /&gt;
我比较没实力，简单格式化了一下，是这样的&lt;br /&gt;
 &amp;lt;code&amp;gt;# 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 341 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;command line&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 2&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot; 2&lt;br /&gt;
 # 173 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 system /system erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system /system ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 vendor /vendor erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor /vendor ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 mi_ext /mnt/vendor/mi_ext erofs ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 mi_ext /mnt/vendor/mi_ext ext4 ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 /mnt/vendor/mi_ext /mi_ext none ro,bind wait,nofail&lt;br /&gt;
 overlay /product/overlay overlay ro,lowerdir=/mnt/vendor/mi_ext/product/overlay/:/product/overlay check,nofail&lt;br /&gt;
 overlay /product/app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/app/:/product/app check,nofail&lt;br /&gt;
 overlay /product/priv-app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/priv-app/:/product/priv-app check,nofail&lt;br /&gt;
 overlay /product/lib overlay ro,lowerdir=/mnt/vendor/mi_ext/product/lib/:/product/lib check,nofail&lt;br /&gt;
 overlay /product/lib64 overlay ro,lowerdir=/mnt/vendor/mi_ext/product/lib64/:/product/lib64 check,nofail&lt;br /&gt;
 overlay /product/bin overlay ro,lowerdir=/mnt/vendor/mi_ext/product/bin/:/product/bin check,nofail&lt;br /&gt;
 overlay /product/framework overlay ro,lowerdir=/mnt/vendor/mi_ext/product/framework/:/product/framework check,nofail&lt;br /&gt;
 overlay /product/media overlay ro,lowerdir=/mnt/vendor/mi_ext/product/media/:/product/media check,nofail&lt;br /&gt;
 overlay /product/opcust overlay ro,lowerdir=/mnt/vendor/mi_ext/product/opcust/:/product/opcust check,nofail&lt;br /&gt;
 overlay /product/data-app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/data-app/:/product/data-app check,nofail&lt;br /&gt;
 overlay /product/etc/sysconfig overlay ro,lowerdir=/mnt/vendor/mi_ext/product/etc/sysconfig/:/product/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /product/etc/permissions overlay ro,lowerdir=/mnt/vendor/mi_ext/product/etc/permissions/:/product/etc/permissions check,nofail&lt;br /&gt;
 overlay /system/app overlay ro,lowerdir=/mnt/vendor/mi_ext/system/app/:/product/pangu/system/app/:/system/app check,nofail&lt;br /&gt;
 overlay /system/priv-app overlay ro,lowerdir=/mnt/vendor/mi_ext/system/priv-app/:/product/pangu/system/priv-app/:/system/priv-app check,nofail&lt;br /&gt;
 overlay /system/framework overlay ro,lowerdir=/product/pangu/system/framework/:/system/framework check,nofail&lt;br /&gt;
 overlay /system/etc/sysconfig overlay ro,lowerdir=/mnt/vendor/mi_ext/system/etc/sysconfig/:/system/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /system/etc/permissions overlay ro,lowerdir=/mnt/vendor/mi_ext/system/etc/permissions/:/product/pangu/system/etc/permissions/:/system/etc/permissions check,nofail&lt;br /&gt;
 system_ext /system_ext erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system_ext /system_ext ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 odm /odm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm /odm ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor_dlkm /vendor_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm_dlkm /odm_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,noflush_merge,fsync_mode=nobarrier,reserve_root=134217,resgid=1065,checkpoint_merge,gc_merge,inlinecrypt wait,check,formattable,quota,latemount,resize,reservedsize=128m,checkpoint=fs,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,fsverity&lt;br /&gt;
 /dev/block/by-name/rescue /cache ext4 noatime,nosuid,nodev,noauto_da_alloc,discard wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect1 /mnt/vendor/protect_f ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect2 /mnt/vendor/protect_s ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvdata /mnt/vendor/nvdata ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvcfg /mnt/vendor/nvcfg ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/persist /mnt/vendor/persist ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /devices/platform/soc/11240000.mmc* auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata&lt;br /&gt;
 /devices/platform/usb_xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /devices/platform/soc/11201000.usb0/11200000.xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /dev/block/by-name/frp /persistent emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/nvram /nvram emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/proinfo /proinfo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk /bootloader emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk2 /bootloader2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/para /para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/misc /misc emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot /boot emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_vendor /vbmeta_vendor emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_system /vbmeta_system emmc defaults first_stage_mount,nofail,slotselect,avb=vbmeta&lt;br /&gt;
 /dev/block/by-name/logo /logo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/expdb /expdb emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/seccfg /seccfg emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee1 /tee1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee2 /tee2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp1 /scp1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp2 /scp2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_1 /sspm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_2 /sspm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_1 /dpm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_2 /dpm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_1 /mcupm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_2 /mcupm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1img /md1img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1dsp /md1dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1arm7 /md1arm7 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md3img /md3img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz1 /gz1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz2 /gz2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/spmfw /spmfw emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/audio_dsp /audio_dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/pi_img /pi_img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot_para /boot_para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/odmdtbo /odmdtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dtbo /dtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/otp /otp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/vbmeta /vbmeta emmc defaults defaults&amp;lt;/code&amp;gt;&lt;br /&gt;
这里面有很多无用分区，我们在 twrp 中操作不到，但是我也是第一次适配 MTK 设备，所以不“瞎说”误人子弟了，先把 bug 修好。&lt;br /&gt;
&lt;br /&gt;
像 xiaomi 这样常见的挂载错误，我自己一般都是尝试把/mnt/vendor 使用 vscode 全部删除，让我们尝试一下。并且要把这一行删除，这行在我看来是重复定义（？而且也没指定分区格式。&lt;br /&gt;
 &amp;lt;code&amp;gt;/mnt/vendor/mi_ext /mi_ext none ro,bind wait,nofail&amp;lt;/code&amp;gt;&lt;br /&gt;
整理完之后是这样的&lt;br /&gt;
 &amp;lt;code&amp;gt;# 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 341 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 3&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;command line&amp;gt;&amp;quot; 1&lt;br /&gt;
 # 1 &amp;quot;&amp;lt;built-in&amp;gt;&amp;quot; 2&lt;br /&gt;
 # 1 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot; 2&lt;br /&gt;
 # 173 &amp;quot;vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895&amp;quot;&lt;br /&gt;
 system /system erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system /system ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 vendor /vendor erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor /vendor ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 product /product ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 mi_ext /mi_ext erofs ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 mi_ext /mi_ext ext4 ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail&lt;br /&gt;
 overlay /product/overlay overlay ro,lowerdir=/mi_ext/product/overlay/:/product/overlay check,nofail&lt;br /&gt;
 overlay /product/app overlay ro,lowerdir=/mi_ext/product/app/:/product/app check,nofail&lt;br /&gt;
 overlay /product/priv-app overlay ro,lowerdir=/mi_ext/product/priv-app/:/product/priv-app check,nofail&lt;br /&gt;
 overlay /product/lib overlay ro,lowerdir=/mi_ext/product/lib/:/product/lib check,nofail&lt;br /&gt;
 overlay /product/lib64 overlay ro,lowerdir=/mi_ext/product/lib64/:/product/lib64 check,nofail&lt;br /&gt;
 overlay /product/bin overlay ro,lowerdir=/mi_ext/product/bin/:/product/bin check,nofail&lt;br /&gt;
 overlay /product/framework overlay ro,lowerdir=/mi_ext/product/framework/:/product/framework check,nofail&lt;br /&gt;
 overlay /product/media overlay ro,lowerdir=/mi_ext/product/media/:/product/media check,nofail&lt;br /&gt;
 overlay /product/opcust overlay ro,lowerdir=/mi_ext/product/opcust/:/product/opcust check,nofail&lt;br /&gt;
 overlay /product/data-app overlay ro,lowerdir=/mi_ext/product/data-app/:/product/data-app check,nofail&lt;br /&gt;
 overlay /product/etc/sysconfig overlay ro,lowerdir=/mi_ext/product/etc/sysconfig/:/product/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /product/etc/permissions overlay ro,lowerdir=/mi_ext/product/etc/permissions/:/product/etc/permissions check,nofail&lt;br /&gt;
 overlay /system/app overlay ro,lowerdir=/mi_ext/system/app/:/product/pangu/system/app/:/system/app check,nofail&lt;br /&gt;
 overlay /system/priv-app overlay ro,lowerdir=/mi_ext/system/priv-app/:/product/pangu/system/priv-app/:/system/priv-app check,nofail&lt;br /&gt;
 overlay /system/framework overlay ro,lowerdir=/product/pangu/system/framework/:/system/framework check,nofail&lt;br /&gt;
 overlay /system/etc/sysconfig overlay ro,lowerdir=/mi_ext/system/etc/sysconfig/:/system/etc/sysconfig check,nofail&lt;br /&gt;
 overlay /system/etc/permissions overlay ro,lowerdir=/mi_ext/system/etc/permissions/:/product/pangu/system/etc/permissions/:/system/etc/permissions check,nofail&lt;br /&gt;
 system_ext /system_ext erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 system_ext /system_ext ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey&lt;br /&gt;
 odm /odm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm /odm ext4 ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 vendor_dlkm /vendor_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 odm_dlkm /odm_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable,first_stage_mount&lt;br /&gt;
 /dev/block/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,noflush_merge,fsync_mode=nobarrier,reserve_root=134217,resgid=1065,checkpoint_merge,gc_merge,inlinecrypt wait,check,formattable,quota,latemount,resize,reservedsize=128m,checkpoint=fs,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,fsverity&lt;br /&gt;
 /dev/block/by-name/rescue /cache ext4 noatime,nosuid,nodev,noauto_da_alloc,discard wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect1 /protect_f ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/protect2 /protect_s ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvdata /nvdata ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/nvcfg /nvcfg ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /dev/block/by-name/persist /persist ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable&lt;br /&gt;
 /devices/platform/soc/11240000.mmc* auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata&lt;br /&gt;
 /devices/platform/usb_xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /devices/platform/soc/11201000.usb0/11200000.xhci* auto vfat defaults voldmanaged=usbotg:auto&lt;br /&gt;
 /dev/block/by-name/frp /persistent emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/nvram /nvram emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/proinfo /proinfo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk /bootloader emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/lk2 /bootloader2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/para /para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/misc /misc emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot /boot emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_vendor /vbmeta_vendor emmc defaults first_stage_mount,nofail,slotselect&lt;br /&gt;
 /dev/block/by-name/vbmeta_system /vbmeta_system emmc defaults first_stage_mount,nofail,slotselect,avb=vbmeta&lt;br /&gt;
 /dev/block/by-name/logo /logo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/expdb /expdb emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/seccfg /seccfg emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee1 /tee1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/tee2 /tee2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp1 /scp1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/scp2 /scp2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_1 /sspm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/sspm_2 /sspm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_1 /dpm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dpm_2 /dpm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_1 /mcupm_1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/mcupm_2 /mcupm_2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1img /md1img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1dsp /md1dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md1arm7 /md1arm7 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/md3img /md3img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz1 /gz1 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/gz2 /gz2 emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/spmfw /spmfw emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/audio_dsp /audio_dsp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/pi_img /pi_img emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/boot_para /boot_para emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/odmdtbo /odmdtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/dtbo /dtbo emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/otp /otp emmc defaults defaults&lt;br /&gt;
 /dev/block/by-name/vbmeta /vbmeta emmc defaults defaults&amp;lt;/code&amp;gt;&lt;br /&gt;
让我们编译试一下，值得注意的是，twrp 每次更改最好删除 out 重新编译，不要使用如&amp;lt;code&amp;gt;make installclean&amp;lt;/code&amp;gt;等命令，可能会开机黑屏或更改不生效。&lt;br /&gt;
&lt;br /&gt;
经过一分钟，编译好了，刷入，开机，启动！可以看见挂载成功被修好。&lt;br /&gt;
&lt;br /&gt;
===== 修复屏幕显示 =====&lt;br /&gt;
可以看到我们现在屏幕的顶部的时间被摄像头挖孔挡住了。我们使用两个偏移 Flag 来修复它。&lt;br /&gt;
&lt;br /&gt;
在 BoardConfig.mk 中，加入以下 flag&lt;br /&gt;
 &amp;lt;code&amp;gt;TW_Y_OFFSET := 106 #导航栏向上&lt;br /&gt;
 TW_H_OFFSET := -106 #界面整体向下&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== 修复振动 =====&lt;br /&gt;
&amp;lt;blockquote&amp;gt;仅供参考，研究半天发现只有解密功能正常才能修振动，不然会冻屏！！！&lt;br /&gt;
&lt;br /&gt;
不一定正确，也不一定普遍，仅供指路&amp;lt;/blockquote&amp;gt;老设备一般都是正常的，不需要额外处理，新设备使用 aidl hal 需要我们自己处理一下让 service 正常工作。&lt;br /&gt;
&lt;br /&gt;
挂载 vendor，使用 twrp 的文件管理，在 vendor/etc/vintf/manifest 找到含有 vibrator 字样的文件。打开之后检查是否类似这样的文段&lt;br /&gt;
 &amp;lt;code&amp;gt;&amp;lt;manifest version=&amp;quot;1.0&amp;quot; type=&amp;quot;device&amp;quot;&amp;gt;&lt;br /&gt;
     &amp;lt;hal format=&amp;quot;aidl&amp;quot; override=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;
         &amp;lt;name&amp;gt;android.hardware.vibrator&amp;lt;/name&amp;gt;&lt;br /&gt;
         &amp;lt;fqname&amp;gt;IVibrator/vibratorfeature&amp;lt;/fqname&amp;gt;&lt;br /&gt;
     &amp;lt;/hal&amp;gt;&lt;br /&gt;
 &amp;lt;/manifest&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
那恭喜你，找对了，我的文件名是&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;vendor.xiaomi.hardware.vibratorfeature.service.xml&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
将它使用&amp;lt;code&amp;gt;adb pull&amp;lt;/code&amp;gt;放到电脑上自己方便的位置备用。&lt;br /&gt;
 &amp;lt;code&amp;gt;xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /vendor/etc/vintf/manifest/vendor.xiaomi.hardware.vibratorfeature.service.xml .&lt;br /&gt;
 /vendor/etc/vintf/manifest/vendor.xiao...ipped. 0.2 MB/s (1718 bytes in 0.009s)&amp;lt;/code&amp;gt;&lt;br /&gt;
不看扩展名，到 vendor/bin/hw/找到同名的 service 同样利用&amp;lt;code&amp;gt;adb pull&amp;lt;/code&amp;gt;放电脑备用。比如我的叫&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;vendor.xiaomi.hardware.vibratorfeature.service&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
然后到 vendor/etc/init/找到同名.rc 文件，拉到电脑上，在里面加一条。并在定义 service 的最下面加上&amp;lt;code&amp;gt;seclabel u:r:recovery:s0&amp;lt;/code&amp;gt;可以被 recovery 使用。&lt;br /&gt;
 &amp;lt;code&amp;gt;on boot&lt;br /&gt;
     start service被定义的名字&amp;lt;/code&amp;gt;&lt;br /&gt;
例如&lt;br /&gt;
 &amp;lt;code&amp;gt;on post-fs-data&lt;br /&gt;
     chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/f0_save&lt;br /&gt;
     chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/osc_save&lt;br /&gt;
     chown system system /sys/bus/i2c/drivers/aw8697_haptic/3-005a/osc_save&lt;br /&gt;
     # 省略一万字&lt;br /&gt;
 &lt;br /&gt;
 on boot&lt;br /&gt;
     start vibratorfeature-hal-service&lt;br /&gt;
 &lt;br /&gt;
 service vibratorfeature-hal-service /vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&lt;br /&gt;
     class hal&lt;br /&gt;
     user system&lt;br /&gt;
     group system input&lt;br /&gt;
     onrestart restart vibratorfeature&lt;br /&gt;
     seclabel u:r:recovery:s0&amp;lt;/code&amp;gt;&lt;br /&gt;
此外这种新设备在内核里还有振动模块需要加载，请到/vendor/modules/1.1/中寻找，例如我这台设备是&amp;lt;code&amp;gt;haptic.ko&amp;lt;/code&amp;gt;，用 adb pull 拉取到电脑上，然后&lt;br /&gt;
&lt;br /&gt;
* haptic.ko --&amp;gt; recovery/root/vendor/modules/1.1&lt;br /&gt;
&lt;br /&gt;
至此所有必要的资料就准备好了。可能开机后仍然不工作，需要抓取 log 补缺失的 library，当然这是后话了。&lt;br /&gt;
&lt;br /&gt;
开干！&lt;br /&gt;
&lt;br /&gt;
在 BoardConfig.mk 中加入以下 flag&lt;br /&gt;
 &amp;lt;code&amp;gt;TW_SUPPORT_INPUT_AIDL_HAPTICS := true&amp;lt;/code&amp;gt;&lt;br /&gt;
将备用文件按照以下操作复制&lt;br /&gt;
&lt;br /&gt;
* vendor.xiaomi.hardware.vibratorfeature.service.xml --&amp;gt; recovery/root/vendor/etc/vintf/manifest&lt;br /&gt;
* vendor.xiaomi.hardware.vibratorfeature.service --&amp;gt; recovery/root/vendor/bin/hw&lt;br /&gt;
* vendor.xiaomi.hardware.vibratorfeature.service.rc --&amp;gt; recovery/root/vendor/etc/init&lt;br /&gt;
&lt;br /&gt;
之后编译，刷入，开机，喜提冻屏......&lt;br /&gt;
&lt;br /&gt;
问题不大，使用&amp;lt;code&amp;gt;adb logcat&amp;lt;/code&amp;gt;抓取日志&lt;br /&gt;
 &amp;lt;code&amp;gt;adb logcat &amp;gt; log.log&amp;lt;/code&amp;gt;&lt;br /&gt;
打开 log，搜索&amp;lt;code&amp;gt;F linker&amp;lt;/code&amp;gt;、&amp;lt;code&amp;gt;linker&amp;lt;/code&amp;gt;、&amp;lt;code&amp;gt;library&amp;lt;/code&amp;gt;、&amp;lt;code&amp;gt;beginning of crash&amp;lt;/code&amp;gt;这几个关键词，我搜索第一个就出来了。&lt;br /&gt;
 &amp;lt;code&amp;gt;F linker  : CANNOT LINK EXECUTABLE &amp;quot;/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&amp;quot;: library &amp;quot;android.hardware.vibrator-V1-ndk_platform.so&amp;quot; not found: needed by main executable&amp;lt;/code&amp;gt;&lt;br /&gt;
这段报错的意思就是&amp;lt;code&amp;gt;vendor.xiaomi.hardware.vibratorfeature.service&amp;lt;/code&amp;gt;找不到&amp;lt;code&amp;gt;android.hardware.vibrator-V1-ndk_platform.so&amp;lt;/code&amp;gt;这个库，所以无法正常工作。&lt;br /&gt;
&lt;br /&gt;
打开 BoardConfig.mk 加入以下 flag&lt;br /&gt;
 &amp;lt;code&amp;gt;# Library&lt;br /&gt;
 TARGET_RECOVERY_DEVICE_MODULES += \&lt;br /&gt;
     android.hardware.vibrator-V1-ndk_platform.vendor&lt;br /&gt;
 &lt;br /&gt;
 TW_RECOVERY_ADDITIONAL_RELINK_LIBRARY_FILES += \&lt;br /&gt;
     $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.vibrator-V1-ndk_platform.so&amp;lt;/code&amp;gt;&lt;br /&gt;
再次编译尝试&lt;br /&gt;
&lt;br /&gt;
开机之后依然冻屏，继续抓 log，查找&lt;br /&gt;
 &amp;lt;code&amp;gt;F linker  : CANNOT LINK EXECUTABLE &amp;quot;/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&amp;quot;: library &amp;quot;vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so&amp;quot; not found: needed by main executable&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;vendor.hardware.vibratorfeature&amp;lt;/code&amp;gt;字样和我们之前导入的文件长得差不多，一般都是供应商专有文件，所以去设备提取，路径在 vendor/lib64 里，虽然设备冻屏了，但我们可以用&amp;lt;code&amp;gt;adb pull&amp;lt;/code&amp;gt;直接拉取到电脑。就像这样。&lt;br /&gt;
 &amp;lt;code&amp;gt;xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb shell mount /vendor&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /vendor/lib64/vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so .&lt;br /&gt;
 /vendor/lib64/vendor.hardware.vibratorfeature.IVi...led, 0 skipped. 14.7 MB/s (33552 bytes in 0.002s&amp;lt;/code&amp;gt;&lt;br /&gt;
将这个文件按照以下提示操作&lt;br /&gt;
&lt;br /&gt;
* vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so --&amp;gt; recovery/root/vendor/lib64&lt;br /&gt;
&lt;br /&gt;
继续编译测试&lt;br /&gt;
&lt;br /&gt;
还是冻屏，继续抓 log&lt;br /&gt;
 &amp;lt;code&amp;gt;F linker  : CANNOT LINK EXECUTABLE &amp;quot;/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service&amp;quot;: library &amp;quot;libtinyalsa.so&amp;quot; not found: needed by main executable&amp;lt;/code&amp;gt;&lt;br /&gt;
这个 library twrp 的源码中应该没有，去设备拿一个 prebuilt 吧&lt;br /&gt;
 &amp;lt;code&amp;gt;xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb shell mount /system_root&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /system_root/system/lib64/libtinyalsa.so .&lt;br /&gt;
 /system_root/system/lib64/libtinyalsa.so: 1 file ...led, 0 skipped. 13.6 MB/s (45032 bytes in 0.003s&amp;lt;/code&amp;gt;&lt;br /&gt;
将这个文件按照以下提示操作&lt;br /&gt;
&lt;br /&gt;
* libtinyalsa.so --&amp;gt; recovery/root/system/lib64&lt;br /&gt;
&lt;br /&gt;
编译测试&lt;br /&gt;
&lt;br /&gt;
我艹了，还是冻屏，这次搜那几个关键词都搜不到了，搜&amp;lt;code&amp;gt;vibrator&amp;lt;/code&amp;gt;看看这鬼东西报什么&lt;br /&gt;
 &amp;lt;code&amp;gt;E vendor.xiaomi.hardware.vibratorfeature.service: fail to load lib : /vendor/lib64/libaachaptics.so&amp;lt;/code&amp;gt;&lt;br /&gt;
这次都直接给路径了，直接拿。&lt;br /&gt;
 &amp;lt;code&amp;gt;xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb shell mount /vendor&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~/github/$/mjw  adb pull /vendor/lib64/libaachaptics.so .&lt;br /&gt;
 /vendor/lib64/libaachaptics.so: 1 file pulled, 0 skipped. 15.8 MB/s (56232 bytes in 0.003s)&amp;lt;/code&amp;gt;&lt;br /&gt;
将这个文件按照以下提示操作&lt;br /&gt;
&lt;br /&gt;
* libaachaptics.so --&amp;gt; recovery/root/vendor/lib64&lt;br /&gt;
&lt;br /&gt;
至此应该没什么问题了，但是有个 flag 貌似要操作 data 内的东西，未解密会导致冻屏，所以等修完解密后再来修振动。&lt;br /&gt;
&lt;br /&gt;
==== 修复 CPU 温度 ====&lt;br /&gt;
使用&amp;lt;code&amp;gt;adb shell&amp;lt;/code&amp;gt; + &amp;lt;code&amp;gt;grep&amp;lt;/code&amp;gt;命令在手机节点里搜索 type 关键词。&lt;br /&gt;
 &amp;lt;code&amp;gt;xiaolegun@xiaoleGundeMac-Pro  ~  adb shell 'grep &amp;quot;cp_master&amp;quot; /sys/class/thermal/*/type'&lt;br /&gt;
 /sys/class/thermal/thermal_zone54/type:cp_master&lt;br /&gt;
 xiaolegun@xiaoleGundeMac-Pro  ~  adb shell 'grep &amp;quot;cpu&amp;quot; /sys/class/thermal/*/type'&lt;br /&gt;
 /sys/class/thermal/thermal_zone1/type:cpu_little1&lt;br /&gt;
 /sys/class/thermal/thermal_zone10/type:cpu_bigbig1&lt;br /&gt;
 /sys/class/thermal/thermal_zone11/type:cpu_big6&lt;br /&gt;
 /sys/class/thermal/thermal_zone12/type:cpu_bigbig2&lt;br /&gt;
 /sys/class/thermal/thermal_zone2/type:cpu_little2&lt;br /&gt;
 /sys/class/thermal/thermal_zone3/type:cpu_little3&lt;br /&gt;
 /sys/class/thermal/thermal_zone4/type:cpu_little4&lt;br /&gt;
 /sys/class/thermal/thermal_zone5/type:cpu_big1&lt;br /&gt;
 /sys/class/thermal/thermal_zone6/type:cpu_big2&lt;br /&gt;
 /sys/class/thermal/thermal_zone7/type:cpu_big3&lt;br /&gt;
 /sys/class/thermal/thermal_zone8/type:cpu_big4&lt;br /&gt;
 /sys/class/thermal/thermal_zone9/type:cpu_big5&amp;lt;/code&amp;gt;&lt;br /&gt;
我这里选用&amp;lt;code&amp;gt;cp_master&amp;lt;/code&amp;gt;节点来读取温度。我的节点路径为&amp;lt;code&amp;gt;/sys/class/thermal/thermal_zone54&amp;lt;/code&amp;gt;在后面添加 temp 来读取温度，你可以使用&amp;lt;code&amp;gt;cat&amp;lt;/code&amp;gt;来检测节点是否可以正常读取温度&lt;br /&gt;
 &amp;lt;code&amp;gt;adb shell 'cat /sys/class/thermal/thermal_zone54/temp'&amp;lt;/code&amp;gt;&lt;br /&gt;
如果返回如&lt;br /&gt;
 &amp;lt;code&amp;gt;28000&amp;lt;/code&amp;gt;&lt;br /&gt;
这种类似的数值，那多半是没有问题的。&lt;br /&gt;
&lt;br /&gt;
我们在 BoardConfig.mk 中加入&lt;br /&gt;
 &amp;lt;code&amp;gt;TW_CUSTOM_CPU_TEMP_PATH := &amp;quot;/sys/class/thermal/thermal_zone54/temp&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
至此 cpu 温度就修复好了。&lt;br /&gt;
&lt;br /&gt;
== 后序 ==&lt;br /&gt;
这是我玩 Android 两年内第一次写关于 Android 的文章，内容和措辞可能不是很准确，再加上开学焦虑，租房因租金和房源不顺利，写的很乱，请各位指正。&lt;br /&gt;
&lt;br /&gt;
此外有什么不懂得，多翻github，善用github搜索，多看看大佬们是怎么解决的。&lt;br /&gt;
&lt;br /&gt;
解密等有空补，先补作业。&lt;br /&gt;
&lt;br /&gt;
== 参考资料 ==&lt;br /&gt;
[https://source.android.com/docs/setup/create/new-device?hl=zh-cn Google - 添加新设备]&lt;br /&gt;
&lt;br /&gt;
[https://source.android.com/docs/core/ota/ab?hl=zh-cn Google - A/B（无缝）系统更新]&lt;br /&gt;
&lt;br /&gt;
[https://blog.lynnrin.moe/posts/ROM-bringup-guide-prebuilt/#boardconfigmk Lynnrin - 快速上手 Android Custom ROM 适配 - Prebuilt Vendor]&lt;br /&gt;
&lt;br /&gt;
[https://source.android.com/docs/core/architecture/vintf?hl=zh-cn Google - 供应商接口对象]&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=532</id>
		<title>首页</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=532"/>
		<updated>2024-02-17T13:53:42Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​fixup super empty&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= 欢迎来到 &amp;lt;span style=&amp;quot;display: inline-block; vertical-align: middle; padding-bottom: 11px;&amp;quot;&amp;gt;[[文件:Uotan Wiki.png|120px]]&amp;lt;/span&amp;gt; · 刷机百科 =&lt;br /&gt;
&lt;br /&gt;
'''我们致力于打造一个更适合国人使用、更贴近刷机本身的玩机知识站点'''&lt;br /&gt;
&lt;br /&gt;
'''本站现有{{NUMBEROFUSERS}}名用户，{{NUMBEROFEDITS}}次编辑，{{NUMBEROFARTICLES}}篇条目，{{NUMBEROFACTIVEUSERS}}位活跃编辑者。'''&lt;br /&gt;
== 刷机入门 ==&lt;br /&gt;
# [[ADB与Fastboot|ADB 与 Fastboot]]&lt;br /&gt;
# [[解锁Bootloader|解锁 Bootloader]]&lt;br /&gt;
# [[刷入第三方Recovery|刷入第三方 Recovery]]&lt;br /&gt;
# [[获取Root权限|获取 Root 权限]]&lt;br /&gt;
# [[Miflash线刷|MiFlash 线刷]]&lt;br /&gt;
&lt;br /&gt;
== 进阶内容 ==&lt;br /&gt;
# [[使用柚坛工具箱进行线刷]]&lt;br /&gt;
# [[ADB SideLoad]]&lt;br /&gt;
# [[Fastboot Update]]&lt;br /&gt;
# [[Fastboot 命令]]&lt;br /&gt;
# [[刷入任意单独镜像]]&lt;br /&gt;
# [[9008深度刷机|9008 深度刷机]]&lt;br /&gt;
# [[MTK Flashtool深度刷机|MTK Flashtool 深度刷机]]&lt;br /&gt;
# [[提取分区]]&lt;br /&gt;
# [[修改分区]]&lt;br /&gt;
# [[QCN]]&lt;br /&gt;
# [[Super_Empty|Super empty]]&lt;br /&gt;
&lt;br /&gt;
== 系统修改 ==&lt;br /&gt;
# [[ADB命令|ADB 命令]]&lt;br /&gt;
# [[Magisk模块|Magisk 模块]]&lt;br /&gt;
# [[LsPosed 模块|LSPosed 模块]]&lt;br /&gt;
# [[KSU 模块]]&lt;br /&gt;
# [[修改教程|修改方案]]&lt;br /&gt;
&lt;br /&gt;
== Mindows工具箱 ==&lt;br /&gt;
# [[为手机刷入Windows|为手机刷入 Windows]]&lt;br /&gt;
# [[更新驱动程序]]&lt;br /&gt;
# [[重新安装Windows|重新安装 Windows]]&lt;br /&gt;
# [[一些常见问题及其解决方案]]&lt;br /&gt;
&lt;br /&gt;
== 高级内容 ==&lt;br /&gt;
# [[Android 分区详解]]&lt;br /&gt;
# [[GKI 内核]]&lt;br /&gt;
# [[如何解包 Android ROM]]&lt;br /&gt;
# [[如何打包 Android ROM]]&lt;br /&gt;
# [[如何从源码构建 TWRP Recovery]]&lt;br /&gt;
# [[如何从源码构建 Android ROM]]&lt;br /&gt;
# [[使用edl.py|使用 edl.py]]&lt;br /&gt;
# [[为手机安装Linux|为手机安装 Linux]]&lt;br /&gt;
# [[Git使用教程]]&lt;br /&gt;
# [[Android内核编译入门]]&lt;br /&gt;
# [[为新设备编写Recovery device tree]]&lt;br /&gt;
# [[为新设备编写类原生device tree]]&lt;br /&gt;
&lt;br /&gt;
== 知名玩机博主 ==&lt;br /&gt;
# [[极客湾Geekerwan]]&lt;br /&gt;
# [[小白测评]]&lt;br /&gt;
# [[微积分WekiHome]]&lt;br /&gt;
# [[晨钟酱Official]]&lt;br /&gt;
# [[江灵夏草]]&lt;br /&gt;
# [[柚坛UOTAN]]&lt;br /&gt;
# [[派大宝UI]]&lt;br /&gt;
# [[我可以等你十年]]&lt;br /&gt;
# [[某贼]]&lt;br /&gt;
# [[凡生TalkING]]&lt;br /&gt;
&lt;br /&gt;
== 知名良心开发者 ==&lt;br /&gt;
# [[暮间雾]]&lt;br /&gt;
# [[某贼]]&lt;br /&gt;
# [[Amktiao]]&lt;br /&gt;
# [[小太阳ACA]]&lt;br /&gt;
# [[hellobbn]]&lt;br /&gt;
&lt;br /&gt;
== 更多词条 ==&lt;br /&gt;
# [[设备代号收录集合]]&lt;br /&gt;
# [[通用系统镜像]]&lt;br /&gt;
# [[AOSP]]&lt;br /&gt;
# [[Linux mainlining]]&lt;br /&gt;
# [[Windows on arm|WOA (Windows on arm)]]&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=531</id>
		<title>首页</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=%E9%A6%96%E9%A1%B5&amp;diff=531"/>
		<updated>2024-02-17T13:52:17Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​添加制作recovery dt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= 欢迎来到 &amp;lt;span style=&amp;quot;display: inline-block; vertical-align: middle; padding-bottom: 11px;&amp;quot;&amp;gt;[[文件:Uotan Wiki.png|120px]]&amp;lt;/span&amp;gt; · 刷机百科 =&lt;br /&gt;
&lt;br /&gt;
'''我们致力于打造一个更适合国人使用、更贴近刷机本身的玩机知识站点'''&lt;br /&gt;
&lt;br /&gt;
'''本站现有{{NUMBEROFUSERS}}名用户，{{NUMBEROFEDITS}}次编辑，{{NUMBEROFARTICLES}}篇条目，{{NUMBEROFACTIVEUSERS}}位活跃编辑者。'''&lt;br /&gt;
== 刷机入门 ==&lt;br /&gt;
# [[ADB与Fastboot|ADB 与 Fastboot]]&lt;br /&gt;
# [[解锁Bootloader|解锁 Bootloader]]&lt;br /&gt;
# [[刷入第三方Recovery|刷入第三方 Recovery]]&lt;br /&gt;
# [[获取Root权限|获取 Root 权限]]&lt;br /&gt;
# [[Miflash线刷|MiFlash 线刷]]&lt;br /&gt;
&lt;br /&gt;
== 进阶内容 ==&lt;br /&gt;
# [[使用柚坛工具箱进行线刷]]&lt;br /&gt;
# [[ADB SideLoad]]&lt;br /&gt;
# [[Fastboot Update]]&lt;br /&gt;
# [[Fastboot 命令]]&lt;br /&gt;
# [[刷入任意单独镜像]]&lt;br /&gt;
# [[9008深度刷机|9008 深度刷机]]&lt;br /&gt;
# [[MTK Flashtool深度刷机|MTK Flashtool 深度刷机]]&lt;br /&gt;
# [[提取分区]]&lt;br /&gt;
# [[修改分区]]&lt;br /&gt;
# [[QCN]]&lt;br /&gt;
# [[Super empty]]&lt;br /&gt;
&lt;br /&gt;
== 系统修改 ==&lt;br /&gt;
# [[ADB命令|ADB 命令]]&lt;br /&gt;
# [[Magisk模块|Magisk 模块]]&lt;br /&gt;
# [[LsPosed 模块|LSPosed 模块]]&lt;br /&gt;
# [[KSU 模块]]&lt;br /&gt;
# [[修改教程|修改方案]]&lt;br /&gt;
&lt;br /&gt;
== Mindows工具箱 ==&lt;br /&gt;
# [[为手机刷入Windows|为手机刷入 Windows]]&lt;br /&gt;
# [[更新驱动程序]]&lt;br /&gt;
# [[重新安装Windows|重新安装 Windows]]&lt;br /&gt;
# [[一些常见问题及其解决方案]]&lt;br /&gt;
&lt;br /&gt;
== 高级内容 ==&lt;br /&gt;
# [[Android 分区详解]]&lt;br /&gt;
# [[GKI 内核]]&lt;br /&gt;
# [[如何解包 Android ROM]]&lt;br /&gt;
# [[如何打包 Android ROM]]&lt;br /&gt;
# [[如何从源码构建 TWRP Recovery]]&lt;br /&gt;
# [[如何从源码构建 Android ROM]]&lt;br /&gt;
# [[使用edl.py|使用 edl.py]]&lt;br /&gt;
# [[为手机安装Linux|为手机安装 Linux]]&lt;br /&gt;
# [[Git使用教程]]&lt;br /&gt;
# [[Android内核编译入门]]&lt;br /&gt;
# [[为新设备编写Recovery device tree]]&lt;br /&gt;
# [[为新设备编写类原生device tree]]&lt;br /&gt;
&lt;br /&gt;
== 知名玩机博主 ==&lt;br /&gt;
# [[极客湾Geekerwan]]&lt;br /&gt;
# [[小白测评]]&lt;br /&gt;
# [[微积分WekiHome]]&lt;br /&gt;
# [[晨钟酱Official]]&lt;br /&gt;
# [[江灵夏草]]&lt;br /&gt;
# [[柚坛UOTAN]]&lt;br /&gt;
# [[派大宝UI]]&lt;br /&gt;
# [[我可以等你十年]]&lt;br /&gt;
# [[某贼]]&lt;br /&gt;
# [[凡生TalkING]]&lt;br /&gt;
&lt;br /&gt;
== 知名良心开发者 ==&lt;br /&gt;
# [[暮间雾]]&lt;br /&gt;
# [[某贼]]&lt;br /&gt;
# [[Amktiao]]&lt;br /&gt;
# [[小太阳ACA]]&lt;br /&gt;
# [[hellobbn]]&lt;br /&gt;
&lt;br /&gt;
== 更多词条 ==&lt;br /&gt;
# [[设备代号收录集合]]&lt;br /&gt;
# [[通用系统镜像]]&lt;br /&gt;
# [[AOSP]]&lt;br /&gt;
# [[Linux mainlining]]&lt;br /&gt;
# [[Windows on arm|WOA (Windows on arm)]]&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=%E8%AE%BE%E5%A4%87%E4%BB%A3%E5%8F%B7%E6%94%B6%E5%BD%95%E9%9B%86%E5%90%88&amp;diff=524</id>
		<title>设备代号收录集合</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=%E8%AE%BE%E5%A4%87%E4%BB%A3%E5%8F%B7%E6%94%B6%E5%BD%95%E9%9B%86%E5%90%88&amp;diff=524"/>
		<updated>2024-02-17T11:09:58Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​添加Nothing Phone&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;目前设备代号收录表格&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== 小米/红米：（按发布时间排序） ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|机型设备&lt;br /&gt;
|代号名称&lt;br /&gt;
|发布时间&lt;br /&gt;
|-&lt;br /&gt;
|红米Note13 4G NFC&lt;br /&gt;
|sapphiren&lt;br /&gt;
|2024/1/15&lt;br /&gt;
|-&lt;br /&gt;
|红米Note13  4G&lt;br /&gt;
|sapphire&lt;br /&gt;
|2024/1/15&lt;br /&gt;
|-&lt;br /&gt;
|红米13R 5G / 红米13C 5G&lt;br /&gt;
|air&lt;br /&gt;
|2023/12/8&lt;br /&gt;
|-&lt;br /&gt;
|红米K70E  / POCO X6 Pro 5G&lt;br /&gt;
|duchamp&lt;br /&gt;
|2023/11/29&lt;br /&gt;
|-&lt;br /&gt;
|红米K70 Pro&lt;br /&gt;
|manet&lt;br /&gt;
|2023/11/29&lt;br /&gt;
|-&lt;br /&gt;
|红米K70&lt;br /&gt;
|vermeer&lt;br /&gt;
|2023/11/29&lt;br /&gt;
|-&lt;br /&gt;
|红米13C / POCO C65&lt;br /&gt;
|gale&lt;br /&gt;
|2023/11/10&lt;br /&gt;
|-&lt;br /&gt;
|小米14  Pro&lt;br /&gt;
|shennong&lt;br /&gt;
|2023/10/26&lt;br /&gt;
|-&lt;br /&gt;
|小米14&lt;br /&gt;
|houji&lt;br /&gt;
|2023/10/26&lt;br /&gt;
|-&lt;br /&gt;
|小米13T&lt;br /&gt;
|aristotle&lt;br /&gt;
|2023/9/26&lt;br /&gt;
|-&lt;br /&gt;
|红米Note13 Pro 4G / POCO X6&lt;br /&gt;
|garnet&lt;br /&gt;
|2023/9/21&lt;br /&gt;
|-&lt;br /&gt;
|红米Note13  5G / 13R Pro&lt;br /&gt;
|gold&lt;br /&gt;
|2023/9/21&lt;br /&gt;
|-&lt;br /&gt;
|红米Note13 Pro 5G / Pro+ 5G&lt;br /&gt;
|zircon&lt;br /&gt;
|2023/9/21&lt;br /&gt;
|-&lt;br /&gt;
|红米平板SE&lt;br /&gt;
|xun&lt;br /&gt;
|2023/8/15&lt;br /&gt;
|-&lt;br /&gt;
|小米MIX Fold 3&lt;br /&gt;
|babylon&lt;br /&gt;
|2023/8/14&lt;br /&gt;
|-&lt;br /&gt;
|红米K60  至尊版 / 小米13T Pro&lt;br /&gt;
|corot&lt;br /&gt;
|2023/8/14&lt;br /&gt;
|-&lt;br /&gt;
|小米平板6 Max&lt;br /&gt;
|yudi&lt;br /&gt;
|2023/8/14&lt;br /&gt;
|-&lt;br /&gt;
|POCO  M6 Pro 4G&lt;br /&gt;
|emerald&lt;br /&gt;
|2023/8/5&lt;br /&gt;
|-&lt;br /&gt;
|红米Note12R / POCO M6 Pro 5G /  红米12 5G&lt;br /&gt;
|sky&lt;br /&gt;
|2023/6/23&lt;br /&gt;
|-&lt;br /&gt;
|红米12&lt;br /&gt;
|fire&lt;br /&gt;
|2023/6/3&lt;br /&gt;
|-&lt;br /&gt;
|红米Note12T Pro&lt;br /&gt;
|pearl&lt;br /&gt;
|2023/5/29&lt;br /&gt;
|-&lt;br /&gt;
|小米CIVI3&lt;br /&gt;
|yuechu&lt;br /&gt;
|2023/5/25&lt;br /&gt;
|-&lt;br /&gt;
|红米Note12S&lt;br /&gt;
|sea&lt;br /&gt;
|2023/4/26&lt;br /&gt;
|-&lt;br /&gt;
|小米13  Ultra&lt;br /&gt;
|ishtar&lt;br /&gt;
|2023/4/18&lt;br /&gt;
|-&lt;br /&gt;
|小米平板6 Pro&lt;br /&gt;
|liuqin&lt;br /&gt;
|2023/4/18&lt;br /&gt;
|-&lt;br /&gt;
|小米平板6&lt;br /&gt;
|pipa&lt;br /&gt;
|2023/4/18&lt;br /&gt;
|-&lt;br /&gt;
|红米Note12 Pro 4G&lt;br /&gt;
|sweet_k6a&lt;br /&gt;
|2023/4/11&lt;br /&gt;
|-&lt;br /&gt;
|红米Note12  4G NFC&lt;br /&gt;
|topaz&lt;br /&gt;
|2023/3/30&lt;br /&gt;
|-&lt;br /&gt;
|红米Note12 4G&lt;br /&gt;
|tapas&lt;br /&gt;
|2023/3/30&lt;br /&gt;
|-&lt;br /&gt;
|红米Note12  Turbo / POCO F5 5G&lt;br /&gt;
|marble&lt;br /&gt;
|2023/3/28&lt;br /&gt;
|-&lt;br /&gt;
|POCO C51 / 红米A2 / A2+&lt;br /&gt;
|water&lt;br /&gt;
|2023/3/24&lt;br /&gt;
|-&lt;br /&gt;
|红米12C  / POCO C55&lt;br /&gt;
|earth&lt;br /&gt;
|2022/12/31&lt;br /&gt;
|-&lt;br /&gt;
|红米Note12 Pro 极速版 / POCO X5 Pro  5G&lt;br /&gt;
|redwood&lt;br /&gt;
|2022/12/27&lt;br /&gt;
|-&lt;br /&gt;
|红米K60E&lt;br /&gt;
|rembrandt&lt;br /&gt;
|2022/12/27&lt;br /&gt;
|-&lt;br /&gt;
|红米K60 Pro&lt;br /&gt;
|socrates&lt;br /&gt;
|2022/12/27&lt;br /&gt;
|-&lt;br /&gt;
|红米K60  / POCO F5 Pro&lt;br /&gt;
|mondrian&lt;br /&gt;
|2022/12/27&lt;br /&gt;
|-&lt;br /&gt;
|小米13 Pro&lt;br /&gt;
|nuwa&lt;br /&gt;
|2022/12/12&lt;br /&gt;
|-&lt;br /&gt;
|小米13&lt;br /&gt;
|fuxi&lt;br /&gt;
|2022/12/12&lt;br /&gt;
|-&lt;br /&gt;
|POCO X5 5G&lt;br /&gt;
|moonstone&lt;br /&gt;
|2022/11/20&lt;br /&gt;
|-&lt;br /&gt;
|红米Note12  5G / 红米Note12R Pro&lt;br /&gt;
|sunstone&lt;br /&gt;
|2022/10/27&lt;br /&gt;
|-&lt;br /&gt;
|红米Note12 Pro&lt;br /&gt;
|ruby&lt;br /&gt;
|2022/10/27&lt;br /&gt;
|-&lt;br /&gt;
|小米12T&lt;br /&gt;
|plato&lt;br /&gt;
|2022/10/4&lt;br /&gt;
|-&lt;br /&gt;
|红米平板&lt;br /&gt;
|yunluo&lt;br /&gt;
|2022/10/4&lt;br /&gt;
|-&lt;br /&gt;
|小米CIVI  2 / 小米13 Lite&lt;br /&gt;
|ziyi&lt;br /&gt;
|2022/9/27&lt;br /&gt;
|-&lt;br /&gt;
|POCO C50 / 红米A1&lt;br /&gt;
|ice&lt;br /&gt;
|2022/9/15&lt;br /&gt;
|-&lt;br /&gt;
|POCO  M5S&lt;br /&gt;
|rosemary_p&lt;br /&gt;
|2022/9/5&lt;br /&gt;
|-&lt;br /&gt;
|POCO M5 / 红米11 Prime 4G&lt;br /&gt;
|rock&lt;br /&gt;
|2022/9/5&lt;br /&gt;
|-&lt;br /&gt;
|小米平板5  Pro 12.4&lt;br /&gt;
|dagu&lt;br /&gt;
|2022/8/11&lt;br /&gt;
|-&lt;br /&gt;
|红米K50 至尊版 / 小米12T Pro&lt;br /&gt;
|diting&lt;br /&gt;
|2022/8/11&lt;br /&gt;
|-&lt;br /&gt;
|小米MIX  Fold 2&lt;br /&gt;
|zizhan&lt;br /&gt;
|2022/8/11&lt;br /&gt;
|-&lt;br /&gt;
|小米12S&lt;br /&gt;
|mayfly&lt;br /&gt;
|2022/7/4&lt;br /&gt;
|-&lt;br /&gt;
|小米12S  Ultra&lt;br /&gt;
|thor&lt;br /&gt;
|2022/7/4&lt;br /&gt;
|-&lt;br /&gt;
|小米12S Pro&lt;br /&gt;
|unicorn&lt;br /&gt;
|2022/7/4&lt;br /&gt;
|-&lt;br /&gt;
|小米12  Pro 天玑版&lt;br /&gt;
|daumier&lt;br /&gt;
|2022/7/4&lt;br /&gt;
|-&lt;br /&gt;
|小米12 Lite&lt;br /&gt;
|taoyao&lt;br /&gt;
|2022/7/4&lt;br /&gt;
|-&lt;br /&gt;
|POCO  C40&lt;br /&gt;
|frost&lt;br /&gt;
|2022/6/17&lt;br /&gt;
|-&lt;br /&gt;
|红米Note11T Pro / Pro+ / POCO X4  GT / Pro / 红米K50i / Pro&lt;br /&gt;
|xaga&lt;br /&gt;
|2022/5/24&lt;br /&gt;
|-&lt;br /&gt;
|小米CIVI  1S&lt;br /&gt;
|zijin&lt;br /&gt;
|2022/4/21&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 10T&lt;br /&gt;
|lilac&lt;br /&gt;
|2022/4/14&lt;br /&gt;
|-&lt;br /&gt;
|红米10A&lt;br /&gt;
|dandelion&lt;br /&gt;
|2022/3/29&lt;br /&gt;
|-&lt;br /&gt;
|红米10C&lt;br /&gt;
|fog&lt;br /&gt;
|2022/3/17&lt;br /&gt;
|-&lt;br /&gt;
|红米K50&lt;br /&gt;
|rubens&lt;br /&gt;
|2022/3/17&lt;br /&gt;
|-&lt;br /&gt;
|红米K50 Pro&lt;br /&gt;
|matisse&lt;br /&gt;
|2022/3/17&lt;br /&gt;
|-&lt;br /&gt;
|红米K40S  / POCO F4&lt;br /&gt;
|munch&lt;br /&gt;
|2022/3/17&lt;br /&gt;
|-&lt;br /&gt;
|红米Note11 Pro&lt;br /&gt;
|viva&lt;br /&gt;
|2022/3/7&lt;br /&gt;
|-&lt;br /&gt;
|红米Note11R&lt;br /&gt;
|lightcm&lt;br /&gt;
|2022/3/7&lt;br /&gt;
|-&lt;br /&gt;
|红米Note11E / POCO M4 5G / 红米10  Prime+ 5G&lt;br /&gt;
|light&lt;br /&gt;
|2022/3/7&lt;br /&gt;
|-&lt;br /&gt;
|红米K50  电竞版 / POCO F4 GT&lt;br /&gt;
|ingres&lt;br /&gt;
|2022/2/16&lt;br /&gt;
|-&lt;br /&gt;
|红米Note11 NFC&lt;br /&gt;
|spesn&lt;br /&gt;
|2022/2/7&lt;br /&gt;
|-&lt;br /&gt;
|红米Note11&lt;br /&gt;
|spes&lt;br /&gt;
|2022/2/7&lt;br /&gt;
|-&lt;br /&gt;
|红米Note11E Pro / 红米Note11 Pro 5G&lt;br /&gt;
|veux&lt;br /&gt;
|2022/1/26&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  11S 5G&lt;br /&gt;
|opal&lt;br /&gt;
|2022/1/26&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 11S / POCO M4 Pro 4G&lt;br /&gt;
|fleur&lt;br /&gt;
|2022/1/26&lt;br /&gt;
|-&lt;br /&gt;
|小米12  Pro&lt;br /&gt;
|zeus&lt;br /&gt;
|2021/12/28&lt;br /&gt;
|-&lt;br /&gt;
|小米12X&lt;br /&gt;
|psyche&lt;br /&gt;
|2021/12/28&lt;br /&gt;
|-&lt;br /&gt;
|小米12&lt;br /&gt;
|cupid&lt;br /&gt;
|2021/12/28&lt;br /&gt;
|-&lt;br /&gt;
|POCO M4 Pro 5G&lt;br /&gt;
|evergreen&lt;br /&gt;
|2021/11/9&lt;br /&gt;
|-&lt;br /&gt;
|红米Note11  Pro / Pro+&lt;br /&gt;
|pissarro&lt;br /&gt;
|2021/10/28&lt;br /&gt;
|-&lt;br /&gt;
|红米Note11 5G&lt;br /&gt;
|evergo&lt;br /&gt;
|2021/10/28&lt;br /&gt;
|-&lt;br /&gt;
|红米Note11  4G&lt;br /&gt;
|selenes&lt;br /&gt;
|2021/10/28&lt;br /&gt;
|-&lt;br /&gt;
|小米CIVI&lt;br /&gt;
|mona&lt;br /&gt;
|2021/9/27&lt;br /&gt;
|-&lt;br /&gt;
|小米11青春活力版&lt;br /&gt;
|lisa&lt;br /&gt;
|2021/9/15&lt;br /&gt;
|-&lt;br /&gt;
|小米11T&lt;br /&gt;
|agate&lt;br /&gt;
|2021/9/15&lt;br /&gt;
|-&lt;br /&gt;
|小米11T  Pro&lt;br /&gt;
|vili&lt;br /&gt;
|2021/9/15&lt;br /&gt;
|-&lt;br /&gt;
|红米10&lt;br /&gt;
|selene&lt;br /&gt;
|2021/8/19&lt;br /&gt;
|-&lt;br /&gt;
|小米MIX4&lt;br /&gt;
|odin&lt;br /&gt;
|2021/8/10&lt;br /&gt;
|-&lt;br /&gt;
|小米平板5 Pro (WiFi)&lt;br /&gt;
|elish&lt;br /&gt;
|2021/8/10&lt;br /&gt;
|-&lt;br /&gt;
|小米平板5  Pro (5G)&lt;br /&gt;
|enuma&lt;br /&gt;
|2021/8/10&lt;br /&gt;
|-&lt;br /&gt;
|小米平板5&lt;br /&gt;
|nabu&lt;br /&gt;
|2021/8/10&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  10 Pro (China) / POCO X3 GT&lt;br /&gt;
|chopin&lt;br /&gt;
|2021/5/26&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 10 (China) / POCO M3 Pro  / 红米Note 11 SE&lt;br /&gt;
|camellia&lt;br /&gt;
|2021/5/26&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  8 (21年款)&lt;br /&gt;
|biloba&lt;br /&gt;
|2021/5/24&lt;br /&gt;
|-&lt;br /&gt;
|红米K40 游戏增强版 / POCO F3 GT&lt;br /&gt;
|ares&lt;br /&gt;
|2021/4/27&lt;br /&gt;
|-&lt;br /&gt;
|小米MIX  Fold&lt;br /&gt;
|cetus&lt;br /&gt;
|2021/3/29&lt;br /&gt;
|-&lt;br /&gt;
|小米11 青春版&lt;br /&gt;
|renoir&lt;br /&gt;
|2021/3/29&lt;br /&gt;
|-&lt;br /&gt;
|小米11  Pro / Ultra&lt;br /&gt;
|star&lt;br /&gt;
|2021/3/29&lt;br /&gt;
|-&lt;br /&gt;
|小米11 Lite&lt;br /&gt;
|courbet&lt;br /&gt;
|2021/3/29&lt;br /&gt;
|-&lt;br /&gt;
|POCO  X3 Pro&lt;br /&gt;
|vayu&lt;br /&gt;
|2021/3/22&lt;br /&gt;
|-&lt;br /&gt;
|小米10S&lt;br /&gt;
|thyme&lt;br /&gt;
|2021/3/10&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  10 Pro&lt;br /&gt;
|sweet&lt;br /&gt;
|2021/3/4&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 10 5G&lt;br /&gt;
|camellian&lt;br /&gt;
|2021/3/4&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  10S&lt;br /&gt;
|rosemary&lt;br /&gt;
|2021/3/4&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 10&lt;br /&gt;
|mojito&lt;br /&gt;
|2021/3/4&lt;br /&gt;
|-&lt;br /&gt;
|红米K40  Pro / Pro+ / 小米11i / 小米11X Pro&lt;br /&gt;
|haydn&lt;br /&gt;
|2021/2/25&lt;br /&gt;
|-&lt;br /&gt;
|红米K40 / POCO F3&lt;br /&gt;
|alioth&lt;br /&gt;
|2021/2/25&lt;br /&gt;
|-&lt;br /&gt;
|小米11&lt;br /&gt;
|venus&lt;br /&gt;
|2020/12/28&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 9T 5G&lt;br /&gt;
|cannong&lt;br /&gt;
|2020/12/1&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  9 Pro 5G / 小米10T Lite&lt;br /&gt;
|gauguin&lt;br /&gt;
|2020/11/26&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 9 5G&lt;br /&gt;
|cannon&lt;br /&gt;
|2020/11/26&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  9 4G / 红米9T&lt;br /&gt;
|lime&lt;br /&gt;
|2020/11/26&lt;br /&gt;
|-&lt;br /&gt;
|POCO M3&lt;br /&gt;
|citrus&lt;br /&gt;
|2020/11/24&lt;br /&gt;
|-&lt;br /&gt;
|红米K30S  至尊纪念版 / 小米10T / 10T Pro&lt;br /&gt;
|apollo&lt;br /&gt;
|2020/10/27&lt;br /&gt;
|-&lt;br /&gt;
|POCO C3&lt;br /&gt;
|angelicain&lt;br /&gt;
|2020/10/6&lt;br /&gt;
|-&lt;br /&gt;
|POCO  M2&lt;br /&gt;
|shiva&lt;br /&gt;
|2020/9/8&lt;br /&gt;
|-&lt;br /&gt;
|POCO X3 NFC&lt;br /&gt;
|surya&lt;br /&gt;
|2020/9/7&lt;br /&gt;
|-&lt;br /&gt;
|红米9C  NFC&lt;br /&gt;
|angelican&lt;br /&gt;
|2020/8/31&lt;br /&gt;
|-&lt;br /&gt;
|红米9 (India)&lt;br /&gt;
|cattail&lt;br /&gt;
|2020/8/27&lt;br /&gt;
|-&lt;br /&gt;
|小米10  至尊纪念版&lt;br /&gt;
|cas&lt;br /&gt;
|2020/8/11&lt;br /&gt;
|-&lt;br /&gt;
|红米K30 至尊纪念版&lt;br /&gt;
|cezanne&lt;br /&gt;
|2020/8/11&lt;br /&gt;
|-&lt;br /&gt;
|POCO  M2 Pro&lt;br /&gt;
|gram&lt;br /&gt;
|2020/7/7&lt;br /&gt;
|-&lt;br /&gt;
|红米9A / 9AT&lt;br /&gt;
|dandelion&lt;br /&gt;
|2020/6/30&lt;br /&gt;
|-&lt;br /&gt;
|红米9C&lt;br /&gt;
|angelica&lt;br /&gt;
|2020/6/30&lt;br /&gt;
|-&lt;br /&gt;
|红米9&lt;br /&gt;
|lancelot&lt;br /&gt;
|2020/6/15&lt;br /&gt;
|-&lt;br /&gt;
|小米Note10  Lite&lt;br /&gt;
|toco&lt;br /&gt;
|2020/5/30&lt;br /&gt;
|-&lt;br /&gt;
|红米10X Pro&lt;br /&gt;
|bomb&lt;br /&gt;
|2020/5/26&lt;br /&gt;
|-&lt;br /&gt;
|红米10X  5G&lt;br /&gt;
|atom&lt;br /&gt;
|2020/5/26&lt;br /&gt;
|-&lt;br /&gt;
|红米K30i 5G&lt;br /&gt;
|picasso_48m&lt;br /&gt;
|2020/5/26&lt;br /&gt;
|-&lt;br /&gt;
|红米10X  4G / 红米Note 9&lt;br /&gt;
|merlin&lt;br /&gt;
|2020/4/30&lt;br /&gt;
|-&lt;br /&gt;
|小米10 青春版&lt;br /&gt;
|vangogh&lt;br /&gt;
|2020/4/27&lt;br /&gt;
|-&lt;br /&gt;
|小米10  Lite&lt;br /&gt;
|monet&lt;br /&gt;
|2020/3/27&lt;br /&gt;
|-&lt;br /&gt;
|红米K30 Pro / 变焦版 / POCO F2 Pro&lt;br /&gt;
|lmi&lt;br /&gt;
|2020/3/24&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  9 Pro Max&lt;br /&gt;
|excalibur&lt;br /&gt;
|2020/3/12&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 9S / Pro (India)&lt;br /&gt;
|curtana&lt;br /&gt;
|2020/3/12&lt;br /&gt;
|-&lt;br /&gt;
|红米Note9  Pro&lt;br /&gt;
|joyeuse&lt;br /&gt;
|2020/3/12&lt;br /&gt;
|-&lt;br /&gt;
|小米10 Pro&lt;br /&gt;
|cmi&lt;br /&gt;
|2020/2/13&lt;br /&gt;
|-&lt;br /&gt;
|小米10&lt;br /&gt;
|umi&lt;br /&gt;
|2020/2/13&lt;br /&gt;
|-&lt;br /&gt;
|红米8A Pro / 红米8A Dual&lt;br /&gt;
|olivewood&lt;br /&gt;
|2020/2/11&lt;br /&gt;
|-&lt;br /&gt;
|POCO  X2 印度版&lt;br /&gt;
|phoenixin&lt;br /&gt;
|2020/2/4&lt;br /&gt;
|-&lt;br /&gt;
|红米K30 5G&lt;br /&gt;
|picasso&lt;br /&gt;
|2019/12/10&lt;br /&gt;
|-&lt;br /&gt;
|红米K30  4G / POCO X2&lt;br /&gt;
|phoenix&lt;br /&gt;
|2019/12/10&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 8T&lt;br /&gt;
|willow&lt;br /&gt;
|2019/11/6&lt;br /&gt;
|-&lt;br /&gt;
|小米CC9  Pro / 小米Note 10&lt;br /&gt;
|tucana&lt;br /&gt;
|2019/11/6&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 8 Pro 印度版&lt;br /&gt;
|begoniain&lt;br /&gt;
|2019/10/21&lt;br /&gt;
|-&lt;br /&gt;
|红米8&lt;br /&gt;
|olive&lt;br /&gt;
|2019/10/9&lt;br /&gt;
|-&lt;br /&gt;
|红米8A&lt;br /&gt;
|olivelite&lt;br /&gt;
|2019/9/25&lt;br /&gt;
|-&lt;br /&gt;
|小米9  Pro 5G&lt;br /&gt;
|crux&lt;br /&gt;
|2019/9/24&lt;br /&gt;
|-&lt;br /&gt;
|红米K20 Pro 尊享版&lt;br /&gt;
|raphaels&lt;br /&gt;
|2019/9/19&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  8 Pro&lt;br /&gt;
|begonia&lt;br /&gt;
|2019/8/29&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 8&lt;br /&gt;
|ginkgo&lt;br /&gt;
|2019/8/29&lt;br /&gt;
|-&lt;br /&gt;
|小米A3&lt;br /&gt;
|laurel&lt;br /&gt;
|2019/7/17&lt;br /&gt;
|-&lt;br /&gt;
|小米CC9e&lt;br /&gt;
|laurus&lt;br /&gt;
|2019/7/2&lt;br /&gt;
|-&lt;br /&gt;
|小米CC9  / 小米9 Lite&lt;br /&gt;
|pyxis&lt;br /&gt;
|2019/7/2&lt;br /&gt;
|-&lt;br /&gt;
|小米CC9 美图定制版&lt;br /&gt;
|vela&lt;br /&gt;
|2019/7/2&lt;br /&gt;
|-&lt;br /&gt;
|红米K20  / 小米9T 印度版&lt;br /&gt;
|davinciin&lt;br /&gt;
|2019/6/12&lt;br /&gt;
|-&lt;br /&gt;
|红米K20 / 小米9T&lt;br /&gt;
|davinci&lt;br /&gt;
|2019/5/28&lt;br /&gt;
|-&lt;br /&gt;
|红米K20  Pro / 小米9T Pro&lt;br /&gt;
|raphael&lt;br /&gt;
|2019/5/28&lt;br /&gt;
|-&lt;br /&gt;
|红米K20 Pro 印度版&lt;br /&gt;
|raphaelin&lt;br /&gt;
|2019/5/28&lt;br /&gt;
|-&lt;br /&gt;
|红米7A&lt;br /&gt;
|pine&lt;br /&gt;
|2019/5/22&lt;br /&gt;
|-&lt;br /&gt;
|红米Y3&lt;br /&gt;
|onc&lt;br /&gt;
|2019/4/24&lt;br /&gt;
|-&lt;br /&gt;
|红米7&lt;br /&gt;
|onclite&lt;br /&gt;
|2019/3/18&lt;br /&gt;
|-&lt;br /&gt;
|小米MIX 3 5G&lt;br /&gt;
|andromeda&lt;br /&gt;
|2019/2/24&lt;br /&gt;
|-&lt;br /&gt;
|小米9&lt;br /&gt;
|cepheus&lt;br /&gt;
|2019/2/20&lt;br /&gt;
|-&lt;br /&gt;
|小米9 SE&lt;br /&gt;
|grus&lt;br /&gt;
|2019/2/20&lt;br /&gt;
|-&lt;br /&gt;
|红米Go&lt;br /&gt;
|tiare&lt;br /&gt;
|2019/1/29&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 7&lt;br /&gt;
|lavender&lt;br /&gt;
|2019/1/10&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  7 Pro&lt;br /&gt;
|violet&lt;br /&gt;
|2019/1/10&lt;br /&gt;
|-&lt;br /&gt;
|小米Play&lt;br /&gt;
|lotus&lt;br /&gt;
|2018/12/24&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  6 Pro&lt;br /&gt;
|tulip&lt;br /&gt;
|2018/11/22&lt;br /&gt;
|-&lt;br /&gt;
|小米MIX 3&lt;br /&gt;
|perseus&lt;br /&gt;
|2018/10/25&lt;br /&gt;
|-&lt;br /&gt;
|小米8  Lite&lt;br /&gt;
|platina&lt;br /&gt;
|2018/9/19&lt;br /&gt;
|-&lt;br /&gt;
|红米6 Pro&lt;br /&gt;
|sakura&lt;br /&gt;
|2018/9/5&lt;br /&gt;
|-&lt;br /&gt;
|POCO  F1&lt;br /&gt;
|beryllium&lt;br /&gt;
|2018/8/22&lt;br /&gt;
|-&lt;br /&gt;
|小米平板4/Plus&lt;br /&gt;
|clover&lt;br /&gt;
|2018/8/14&lt;br /&gt;
|-&lt;br /&gt;
|小米A2  Lite&lt;br /&gt;
|daisy&lt;br /&gt;
|2018/7/24&lt;br /&gt;
|-&lt;br /&gt;
|小米A2&lt;br /&gt;
|jasmine&lt;br /&gt;
|2018/7/24&lt;br /&gt;
|-&lt;br /&gt;
|小米Max  3&lt;br /&gt;
|nitrogen&lt;br /&gt;
|2018/7/19&lt;br /&gt;
|-&lt;br /&gt;
|红米6A&lt;br /&gt;
|cactus&lt;br /&gt;
|2018/6/12&lt;br /&gt;
|-&lt;br /&gt;
|红米6&lt;br /&gt;
|cereus&lt;br /&gt;
|2018/6/12&lt;br /&gt;
|-&lt;br /&gt;
|小米8&lt;br /&gt;
|dipper&lt;br /&gt;
|2018/5/31&lt;br /&gt;
|-&lt;br /&gt;
|小米8  Pro 屏幕指纹版&lt;br /&gt;
|equuleus&lt;br /&gt;
|2018/5/31&lt;br /&gt;
|-&lt;br /&gt;
|小米8 SE&lt;br /&gt;
|sirius&lt;br /&gt;
|2018/5/31&lt;br /&gt;
|-&lt;br /&gt;
|小米8  透明探索版&lt;br /&gt;
|ursa&lt;br /&gt;
|2018/5/31&lt;br /&gt;
|-&lt;br /&gt;
|红米S2 / 红米Y2&lt;br /&gt;
|ysl&lt;br /&gt;
|2018/5/10&lt;br /&gt;
|-&lt;br /&gt;
|小米6X&lt;br /&gt;
|wayne&lt;br /&gt;
|2018/4/25&lt;br /&gt;
|-&lt;br /&gt;
|小米MIX 2S&lt;br /&gt;
|polaris&lt;br /&gt;
|2018/3/27&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  5 / Pro&lt;br /&gt;
|whyred&lt;br /&gt;
|2018/2/14&lt;br /&gt;
|-&lt;br /&gt;
|红米5&lt;br /&gt;
|rosy&lt;br /&gt;
|2017/12/7&lt;br /&gt;
|-&lt;br /&gt;
|红米5  Plus&lt;br /&gt;
|vince&lt;br /&gt;
|2017/12/7&lt;br /&gt;
|-&lt;br /&gt;
|红米5A&lt;br /&gt;
|riva&lt;br /&gt;
|2017/10/20&lt;br /&gt;
|-&lt;br /&gt;
|小米MIX  2&lt;br /&gt;
|chiron&lt;br /&gt;
|2017/9/11&lt;br /&gt;
|-&lt;br /&gt;
|小米Note 3&lt;br /&gt;
|jason&lt;br /&gt;
|2017/9/11&lt;br /&gt;
|-&lt;br /&gt;
|小米A1&lt;br /&gt;
|tissot&lt;br /&gt;
|2017/9/5&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 5A 高配版&lt;br /&gt;
|ugg&lt;br /&gt;
|2017/8/21&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  5A 标准版&lt;br /&gt;
|ugglite&lt;br /&gt;
|2017/8/21&lt;br /&gt;
|-&lt;br /&gt;
|小米5X&lt;br /&gt;
|tiffany&lt;br /&gt;
|2017/7/26&lt;br /&gt;
|-&lt;br /&gt;
|小米Max  2&lt;br /&gt;
|oxygen&lt;br /&gt;
|2017/5/25&lt;br /&gt;
|-&lt;br /&gt;
|小米6&lt;br /&gt;
|sagit&lt;br /&gt;
|2017/4/19&lt;br /&gt;
|-&lt;br /&gt;
|小米平板3&lt;br /&gt;
|cappu&lt;br /&gt;
|2017/4/6&lt;br /&gt;
|-&lt;br /&gt;
|小米5C&lt;br /&gt;
|meri&lt;br /&gt;
|2017/2/28&lt;br /&gt;
|-&lt;br /&gt;
|红米4X&lt;br /&gt;
|santoni&lt;br /&gt;
|2017/2/28&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 4X 高通版&lt;br /&gt;
|mido&lt;br /&gt;
|2017/1/19&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  4 联发科版&lt;br /&gt;
|nikel&lt;br /&gt;
|2017/1/19&lt;br /&gt;
|-&lt;br /&gt;
|红米4 高配版&lt;br /&gt;
|markw&lt;br /&gt;
|2016/11/4&lt;br /&gt;
|-&lt;br /&gt;
|红米4  标准版&lt;br /&gt;
|prada&lt;br /&gt;
|2016/11/4&lt;br /&gt;
|-&lt;br /&gt;
|红米4A&lt;br /&gt;
|rolex&lt;br /&gt;
|2016/11/4&lt;br /&gt;
|-&lt;br /&gt;
|小米MIX&lt;br /&gt;
|lithium&lt;br /&gt;
|2016/10/25&lt;br /&gt;
|-&lt;br /&gt;
|小米Note 2&lt;br /&gt;
|scorpio&lt;br /&gt;
|2016/10/25&lt;br /&gt;
|-&lt;br /&gt;
|小米5S&lt;br /&gt;
|capricorn&lt;br /&gt;
|2016/9/27&lt;br /&gt;
|-&lt;br /&gt;
|小米5S Plus&lt;br /&gt;
|natrium&lt;br /&gt;
|2016/9/27&lt;br /&gt;
|-&lt;br /&gt;
|红米Pro&lt;br /&gt;
|omega&lt;br /&gt;
|2016/7/27&lt;br /&gt;
|-&lt;br /&gt;
|红米3S&lt;br /&gt;
|land&lt;br /&gt;
|2016/6/15&lt;br /&gt;
|-&lt;br /&gt;
|小米Max  高配版&lt;br /&gt;
|helium&lt;br /&gt;
|2016/6/1&lt;br /&gt;
|-&lt;br /&gt;
|小米Max 标准版&lt;br /&gt;
|hydrogen&lt;br /&gt;
|2016/5/10&lt;br /&gt;
|-&lt;br /&gt;
|小米4S&lt;br /&gt;
|aqua&lt;br /&gt;
|2016/2/24&lt;br /&gt;
|-&lt;br /&gt;
|小米5&lt;br /&gt;
|gemini&lt;br /&gt;
|2016/2/24&lt;br /&gt;
|-&lt;br /&gt;
|红米3  / Pro&lt;br /&gt;
|ido&lt;br /&gt;
|2016/1/10&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 3 台湾特别版&lt;br /&gt;
|kate&lt;br /&gt;
|2015/11/25&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  3 全网通版&lt;br /&gt;
|kenzo&lt;br /&gt;
|2015/11/25&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 3 双网通版&lt;br /&gt;
|hennessy&lt;br /&gt;
|2015/11/24&lt;br /&gt;
|-&lt;br /&gt;
|小米平板2&lt;br /&gt;
|latte&lt;br /&gt;
|2015/11/24&lt;br /&gt;
|-&lt;br /&gt;
|小米4C&lt;br /&gt;
|libra&lt;br /&gt;
|2015/9/22&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  2&lt;br /&gt;
|hermes&lt;br /&gt;
|2015/8/13&lt;br /&gt;
|-&lt;br /&gt;
|小米4i&lt;br /&gt;
|ferrari&lt;br /&gt;
|2015/4/23&lt;br /&gt;
|-&lt;br /&gt;
|红米2A  标准版&lt;br /&gt;
|lte26007&lt;br /&gt;
|2015/3/1&lt;br /&gt;
|-&lt;br /&gt;
|小米Note 顶配版&lt;br /&gt;
|leo&lt;br /&gt;
|2015/1/15&lt;br /&gt;
|-&lt;br /&gt;
|小米Note  双网通 / 全网通&lt;br /&gt;
|virgo&lt;br /&gt;
|2015/1/15&lt;br /&gt;
|-&lt;br /&gt;
|红米手机2 增强版&lt;br /&gt;
|wt86047&lt;br /&gt;
|2015/1/4&lt;br /&gt;
|-&lt;br /&gt;
|红米手机2&lt;br /&gt;
|wt88047&lt;br /&gt;
|2015/1/4&lt;br /&gt;
|-&lt;br /&gt;
|红米Note 4G单卡版&lt;br /&gt;
|dior&lt;br /&gt;
|2014/8/12&lt;br /&gt;
|-&lt;br /&gt;
|红米Note  4G双卡版&lt;br /&gt;
|gucci&lt;br /&gt;
|2014/8/12&lt;br /&gt;
|-&lt;br /&gt;
|小米3 / 小米4&lt;br /&gt;
|cancro&lt;br /&gt;
|2014/7/22&lt;br /&gt;
|-&lt;br /&gt;
|红米手机1S&lt;br /&gt;
|armani&lt;br /&gt;
|2014/7/16&lt;br /&gt;
|-&lt;br /&gt;
|红米手机1S 移动3G版&lt;br /&gt;
|HM2014011&lt;br /&gt;
|2014/7/16&lt;br /&gt;
|-&lt;br /&gt;
|红米手机1S  移动4G版&lt;br /&gt;
|HM2014501&lt;br /&gt;
|2014/7/16&lt;br /&gt;
|-&lt;br /&gt;
|小米平板1&lt;br /&gt;
|mocha&lt;br /&gt;
|2014/5/15&lt;br /&gt;
|-&lt;br /&gt;
|红米Note&lt;br /&gt;
|lcsh92&lt;br /&gt;
|2014/3/20&lt;br /&gt;
|-&lt;br /&gt;
|小米2A&lt;br /&gt;
|taurus&lt;br /&gt;
|2013/10/24&lt;br /&gt;
|-&lt;br /&gt;
|小米3  移动版&lt;br /&gt;
|pisces&lt;br /&gt;
|2013/9/5&lt;br /&gt;
|-&lt;br /&gt;
|红米手机&lt;br /&gt;
|HM2013023&lt;br /&gt;
|2013/7/12&lt;br /&gt;
|-&lt;br /&gt;
|小米2S&lt;br /&gt;
|aries&lt;br /&gt;
|2013/6/17&lt;br /&gt;
|-&lt;br /&gt;
|小米1S&lt;br /&gt;
|mione&lt;br /&gt;
|2012/8/23&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Nothing Phone ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!机型设备&lt;br /&gt;
!机型型号&lt;br /&gt;
!机型代号&lt;br /&gt;
!发布时间&lt;br /&gt;
|-&lt;br /&gt;
|Nothing Phone (2) &lt;br /&gt;
|A065/AIN065(India)&lt;br /&gt;
|Pong&lt;br /&gt;
|2023/07/12&lt;br /&gt;
|-&lt;br /&gt;
|Nothing Phone (1)&lt;br /&gt;
|A603&lt;br /&gt;
|Spacewar&lt;br /&gt;
|2022/7/12&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=523</id>
		<title>Git使用教程</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=523"/>
		<updated>2024-02-17T10:46:31Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​补充参考资料&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Git的由来： ===&lt;br /&gt;
Git是一个开源的分布式版本控制系统，可以有效、高速地处理从很小到非常大的项目版本管理，也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper。&lt;br /&gt;
&lt;br /&gt;
=== 常见的代码托管平台： ===&lt;br /&gt;
[https://github.com Github]&lt;br /&gt;
&lt;br /&gt;
[https://gitlab.com Gitlab]&lt;br /&gt;
&lt;br /&gt;
[https://gitee.com Gitee]&lt;br /&gt;
&lt;br /&gt;
=== Git 常见命令: ===&lt;br /&gt;
&lt;br /&gt;
==== git init ====&lt;br /&gt;
在本地目录中初始化一个新的Git仓库&lt;br /&gt;
&lt;br /&gt;
==== git config ====&lt;br /&gt;
用于配置用户的信息以及其他设置,在使用git之前您必须完成以下步骤。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.name &amp;quot;your username&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.email &amp;quot;your email&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
更改默认编辑器&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global core.editor nano&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git clone ====&lt;br /&gt;
用于将远程仓库的代码克隆到本地，以下是命令中各个参数的含义：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;url&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆某个地址(url)的仓库，远程仓库的地址可以是本地的目录，也可以是例如github,giteee,gitlab一类的代码托管平台&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;--depth=&amp;lt;number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆仓库并且保留number条提交历史，number在此处即表达我们克隆的深度。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;-b &amp;lt;branch&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆指定分支下的仓库内容&lt;br /&gt;
&lt;br /&gt;
例如我们要克隆&amp;lt;code&amp;gt;LineageOS&amp;lt;/code&amp;gt;的内核源码，指定&amp;lt;code&amp;gt;lineage-21&amp;lt;/code&amp;gt;分支，且仅保留最近一个提交，则需要输入:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git clone -b lineage-21 &amp;lt;nowiki&amp;gt;https://github.com/LineageOS/android_kernel_xiaomi_sdm845&amp;lt;/nowiki&amp;gt; --depth=1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git add ====&lt;br /&gt;
添加某个文件，或者目录到暂存区，用于告诉git你需要将哪些文件的更改包含在下一次的提交(commit)之中添加一个或者多个文件到暂存区之中&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [file1] [file2]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加指定目录(文件)到暂存区，包括子目录：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [dir]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加当前目录下的所有文件到暂存区：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add .&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git status ====&lt;br /&gt;
查看当前仓库的状态，此时git会在你的终端输出以下内容&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;em style=&amp;quot;color: gray;&amp;quot;&amp;gt;此处演示为英文，如果您的git终端输出为中文也是同理的&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
On branch master&lt;br /&gt;
No commits yet&lt;br /&gt;
Changes to be committed:  &lt;br /&gt;
&lt;br /&gt;
(use “git rm --cached &amp;lt;file&amp;gt;...” to unstage)       &lt;br /&gt;
new file:   makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
输出内容分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
您目前所在的分支&lt;br /&gt;
目前的提交&lt;br /&gt;
需要更改的内容&lt;br /&gt;
新增的文件&lt;br /&gt;
修改的文件&lt;br /&gt;
删除的文件&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git commit ====&lt;br /&gt;
用于将暂存区我们保存的更改文件添加到本地仓库，并且会生成一条提交（commit）&lt;br /&gt;
&lt;br /&gt;
提交暂存区的更改到本地仓库&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -m &amp;quot;message&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[注] message 可以是你的备注信息&lt;br /&gt;
&lt;br /&gt;
提交暂存区中的指定文件到本地仓库&lt;br /&gt;
&lt;br /&gt;
如果你没有使用上述&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令暂存你的修改文件，可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -a&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
进行直接提交&lt;br /&gt;
&lt;br /&gt;
==== git checkout ====&lt;br /&gt;
&lt;br /&gt;
* 用于分支切换&lt;br /&gt;
&lt;br /&gt;
切换分支：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如在您的仓库中有这几个分支：&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-&amp;gt; master (Default)&lt;br /&gt;
   backup&lt;br /&gt;
   test&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
您当前处于 master 分支，如果想要切换到test分支，我们可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 用于检出文件&lt;br /&gt;
将指定的文件恢复到最新的提交状态，撤销你对其的更改&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout -- &amp;lt;file&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git push ====&lt;br /&gt;
用于将本地的分支版本上传到远程仓库并进行合并&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push &amp;lt;remote-host-name&amp;gt; &amp;lt;local-branch-name&amp;gt;:&amp;lt;remote-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
remote-host-name:远程主机名&lt;br /&gt;
&lt;br /&gt;
local-branch-name:本地分支名&lt;br /&gt;
&lt;br /&gt;
例如，当你的远程主机名为origin ，本地分支名为master，远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master:master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如，当你的rhost名为origin 本地分支名为master远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
本地和远程分支名相同，上述命令可以简写为：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当你的远程版本与本地版本有差异，无法直接push时，你可以使用--force 参数来进行强制推送&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push --force origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
--force 此处可以直接简单化为 -f &lt;br /&gt;
&lt;br /&gt;
如果你想要删除主机内的某个分支，你可以使用--delete参数&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin --delete &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git diff ====&lt;br /&gt;
用于比较当前工作区与上一个版本之间的差异&lt;br /&gt;
&lt;br /&gt;
例如：（此处仅做不恰当举例，Makefile不是这样乱写的）&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
diff --git a/makefile b/makefile&lt;br /&gt;
&lt;br /&gt;
index fbb8c85..d65c7eb 100644&lt;br /&gt;
&lt;br /&gt;
--- a/makefile&lt;br /&gt;
&lt;br /&gt;
+++ b/makefile&lt;br /&gt;
&lt;br /&gt;
@@ -1 +1,2 @@&lt;br /&gt;
&lt;br /&gt;
114514&lt;br /&gt;
&lt;br /&gt;
+1919180&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git log ====&lt;br /&gt;
用于查看提交的历史&lt;br /&gt;
&lt;br /&gt;
例如当你进行一次提交之后，执行 &amp;lt;code&amp;gt;git log&amp;lt;/code&amp;gt;终端会输出&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit 3a5b0d12f471418b13f2baf5e9e4c112a5e804a8 (HEAD -&amp;gt; master)&lt;br /&gt;
&lt;br /&gt;
Author: luluzzy &amp;lt;1054438588@qq.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Date:   Thu Feb 15 21:28:47 2024 +0800&lt;br /&gt;
&lt;br /&gt;
    initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这些输出分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit sha1 hash:   针对你这个提交的 commit id&lt;br /&gt;
Author: commit      作者名称   &amp;lt;you@example.com&amp;gt;&lt;br /&gt;
Date: commit        日期&lt;br /&gt;
commit:             名称&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
关于sha1_hash的介绍请看这里&amp;lt;ref&amp;gt;生成这个hash值，它是对那个commit是Git仓库中内容和头信息Header的一个校验和checksum。Linux kernel开创者和Git的开发者——Linus说，Git使用了sha1并非是为了安全性，而是为了数据的完整性；它可以保证，在很多年后，你重新checkout某个commit时，一定是它多年前的当时的状态，完全一摸一样，完全值得信任。在Git中，根据commit的sha1值40个十六进制数字进行了简单的划分目录，以前2位数字作为目录名，其下面是剩余38位数字组成的一个文件名&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当有多次提交之后，如果我们想要翻之前的提交历史，难免会因为终端输出的内容过多而难以查看翻阅&lt;br /&gt;
&lt;br /&gt;
此时我们可以使用&amp;lt;code&amp;gt;--online&amp;lt;/code&amp;gt;参数来简化输出，此时仅会输出: sha1哈希值 + commit的名称&lt;br /&gt;
&lt;br /&gt;
例如&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
347595d (HEAD -&amp;gt; master) modify makefile&lt;br /&gt;
&lt;br /&gt;
3a5b0d1 initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git cherry-pick ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
cherry-pick (遴选) 和它的名称一样，挑选一个我们需要的 commit 进行操作。它可以用于将在其他分支上的 commit 修改，移植到当前的分支。&lt;br /&gt;
&lt;br /&gt;
如果我们想在我们正在开发的版本上，添加一个其他版本中的功能代码。就可以使用 cherry-pick ，将这个功能相关的 commit 提取出来，合入该版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick &amp;lt;commit-id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
当我们执行完 &amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;操作之后，会自动生成一个&amp;lt;code&amp;gt;commit&amp;lt;/code&amp;gt;以及对应新的&amp;lt;code&amp;gt;commit-id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在顺利的情况下我们可以直接通过，但如果遇到代码等因为变量名，写法等不同的情况，&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;大概率会报错，此时我们需要进行报错处理。&lt;br /&gt;
&lt;br /&gt;
第一种方案是手动修改&lt;br /&gt;
&lt;br /&gt;
我们可以先使用&amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt;检查当前遴选时冲突的文件&lt;br /&gt;
&lt;br /&gt;
然后 &amp;lt;code&amp;gt;git checkout --ours filename&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
然后按照提交的修改内容进行手动修改&lt;br /&gt;
&lt;br /&gt;
随后使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令将文件重新加入暂存区&lt;br /&gt;
&lt;br /&gt;
再使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --continue&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
命令让 cherrypick 操作继续执行。&lt;br /&gt;
&lt;br /&gt;
第二种方案是直接退出&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;进程，一般适用于冲突文件实在太多了难以按照方案一处理的情况。&lt;br /&gt;
&lt;br /&gt;
需要注意的是，如果您当前正在遴选的提交在该分支已经存在也会冲突，在这种情况下，您需要解决冲突并手动解决问题。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --abort&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git fetch ====&lt;br /&gt;
git fetch 命令用于从远程获取仓库。&lt;br /&gt;
&lt;br /&gt;
==== git merge ====&lt;br /&gt;
&amp;lt;code&amp;gt;git merge&amp;lt;/code&amp;gt;是用来把分叉的提交历史放回到一起(合并)的方式。&lt;br /&gt;
&lt;br /&gt;
git merge命令用来将你之前使用git branch命令创建的分支以及在此分支上独立开发的内容整合为一个分支。&lt;br /&gt;
&lt;br /&gt;
本&lt;br /&gt;
&lt;br /&gt;
==== git pull ====&lt;br /&gt;
用于从远程获取代码并合并本地的版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull&amp;lt;/code&amp;gt;其实就是&amp;lt;code&amp;gt;git fetch&amp;lt;/code&amp;gt;和&amp;lt;code&amp;gt;git merge FETCH_HEAD&amp;lt;/code&amp;gt; 的简写。&lt;br /&gt;
&lt;br /&gt;
格式如下：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull &amp;lt;remote-host-name&amp;gt; &amp;lt;remote-branch-name&amp;gt;:&amp;lt;local-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git rebase ====&lt;br /&gt;
用于需要修改历史上某一项commit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git rebase -i HEAD~&amp;lt;commit number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
commit number就是从头部往前数的commit数量。执行后会弹出你在git config内配置的编辑器，若未配置则是默认，vim居多。然后就可以看见一堆commit前面有pick字样。可以将pick替换为你想要的操作。&lt;br /&gt;
有以下操作：&lt;br /&gt;
&lt;br /&gt;
1.edit，顾名思义编辑此commit，替换完保存后请修改内容，使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;或vscode，github desktop将修改文件添加到暂存区，之后命令行执行&amp;lt;code&amp;gt;git commit --amend&amp;lt;/code&amp;gt;这样commit就修改成了&lt;br /&gt;
&lt;br /&gt;
2.squash，合并几个提交，确认一个父提交，将要合并的commit，从下向上替换字符串，会从下向上合并(方位指的是&amp;lt;code&amp;gt;git rebase&amp;lt;/code&amp;gt;后弹出的编辑器)&lt;br /&gt;
&lt;br /&gt;
3.drop，需要移除的commit&lt;br /&gt;
&lt;br /&gt;
==== git subtree ====&lt;br /&gt;
子树，在Android开发中多用于Kernel侧更改，如跟踪audio模块等&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree add --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果需要更新远程库时&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree pull --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git submodule ====&lt;br /&gt;
&lt;br /&gt;
===== 子模块功能的概述 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在自己的Github仓库里加入别人的github仓库，作为自己仓库的子仓库(即submodule)。&lt;br /&gt;
&lt;br /&gt;
为什么我们会需要使用子模块？当我们维护一个项目时有可能遇到以下情况，例如维护某款机型的KernelSU内核，我们需要将KernelSU导入至我们的内核源码中，如果我们直接clone进去容易带来一个问题，如果KernelSU更新了怎么办？此时我们便可以使用子模块来解决这个问题&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在git仓库里存放别人仓库的url，作为自己的子模块，其核心内容是在Git仓库里面加入一个&amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;文件，里面会记录各个submodule的名字，路径，以及对应链接。&lt;br /&gt;
&lt;br /&gt;
===== 加入子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule add &amp;lt;url&amp;gt; &amp;lt;path&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
此时 &amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;内会自动生成以下内容&lt;br /&gt;
&lt;br /&gt;
[submodule &amp;quot;xxx&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
path = xxx&lt;br /&gt;
&lt;br /&gt;
url = xxx&lt;br /&gt;
&lt;br /&gt;
===== 初始化子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule init&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== 更新子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule update&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Git进阶 ===&lt;br /&gt;
&lt;br /&gt;
==== GPG key ====&lt;br /&gt;
&lt;br /&gt;
===== 简介 =====&lt;br /&gt;
平时在Github上摸鱼的时候，是不是经常能看见如下图所示，有一个绿色的&amp;quot;Verified&amp;quot;字样，看着很酷，实际上这是为了确保commit为开发者本人所写的进行的GPG签名。&lt;br /&gt;
[[文件:Github GPG sign.png|居中]]&lt;br /&gt;
因为Git的默认机制，任何人都可以通过你的邮箱和用户名创建虚假的commit，甚至你名气很大的话可以“栽赃陷害”你。如果你是某高校计算机专业的同学亦或是对计算机抱有很大的兴趣，乐意为开源社区提供“资源”，那么我建议你设置GPG sign。未来是不可预知的，人人都可能成为巨佬。&lt;br /&gt;
&lt;br /&gt;
===== 使用 =====&lt;br /&gt;
因为我只在Mac环境下配置过GPG，Windows只是打游戏用，所以用的少，Linux/类Unix可以参考一下。其它系统等待他人补充......&lt;br /&gt;
&lt;br /&gt;
====== Mac ======&lt;br /&gt;
Mac默认是不带GPG的，需要通过第三方软件包安装器Homebrew进行安装，首先先安装Homebrew，如已安装可以跳过。&lt;br /&gt;
&lt;br /&gt;
编辑器限制原因不能使用默认标题进行分步了，故使用1、2、3等小数字代替。&lt;br /&gt;
&lt;br /&gt;
安装Homebrew&lt;br /&gt;
&lt;br /&gt;
在安装之前需要从系统信息中查看芯片为Intel/M系列&lt;br /&gt;
&lt;br /&gt;
Intel使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/bin/zsh -c &amp;quot;$(curl -fsSL &amp;lt;nowiki&amp;gt;https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh&amp;lt;/nowiki&amp;gt;)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Intel按照脚本提示，选源，输密码，回车一路绿灯就好了，如果这都不会......可能你不是很适合开发，因为该脚本是国内开发者编写的，中文和一键化安装都集齐了。&lt;br /&gt;
&lt;br /&gt;
M系列使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/bin/zsh -c &amp;quot;$(curl -fsSL https://gitee.com/huwei1024/HomebrewCN/raw/master/Homebrew.sh)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
并且因为M系列系统结构发生改变，包安装位置不在是以前的/usr/local/，而是在/opt/homebrew，所以要将配置文件里的环境变量改过来。&lt;br /&gt;
&lt;br /&gt;
1.首先进入根目录&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cd ~&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.创建.zshrc文件&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;touch .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3.打开文件进行编辑&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;open -e .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4.如果有旧的环境就修改，没有就新增&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;export PATH=&amp;quot;/opt/homebrew/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
export PATH=&amp;quot;/opt/homebrew/sbin:$PATH&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5.保存&lt;br /&gt;
&lt;br /&gt;
使用command + s&lt;br /&gt;
&lt;br /&gt;
6.生效环境变量&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;source .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
7、测试&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;brew -v&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
若终端顺利打印出brew的版本，那么就安装成功了！&lt;br /&gt;
&lt;br /&gt;
注：本人没有使用过M系列设备，该教程在知乎上找到的&lt;br /&gt;
&lt;br /&gt;
使用Homebrew安装GPG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;brew install gnupg pinentry-mac&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.34.48.png|居中]]&lt;br /&gt;
&lt;br /&gt;
为GPG添加环境变量，否则在签名的时候会发生报错（使用bash请自行替换配置文件）&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;echo &amp;quot;export GPG_TTY=$(tty)&amp;quot; &amp;gt;&amp;gt; ~/.zshrc&lt;br /&gt;
source ~/.zshrc&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
生成一个GPG keys&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gpg --full-generate-key&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.45.51.png|居中]]&lt;br /&gt;
&lt;br /&gt;
默认使用的是ECC，我使用的是RSA，按照自己喜好，或从百度搜索非对称和对称加密算法之间的区别，这里只做使用方法的介绍，不做赘述。&lt;br /&gt;
&lt;br /&gt;
然后添写密钥长度和使用有效期，这里建议选择长期，并做备份，一辈子用一个就够了。&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.46.06.png|居中]]&lt;br /&gt;
[[文件:截屏2024-02-17 17.46.35.png|居中]]&lt;br /&gt;
&lt;br /&gt;
个人信息按照Github信息填写，真实姓名对应Username。填写完毕按回车输入O即可生成密钥。不出意外的话会弹出Gui窗口让你设置密钥密码，强烈建设设置一个较为复杂的密码，并牢记，当然也可以不设置。&lt;br /&gt;
&lt;br /&gt;
使用GPG对Git的commit和tag进行签名&lt;br /&gt;
&lt;br /&gt;
先为Git定义GPG二进制所在地&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global gpg.program $(which gpg)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
查看GPG keys ID&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gpg --list-secret-keys --keyid-format=long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如图所示RSA/后面紧跟的一串就是GPG keys ID&lt;br /&gt;
[[文件:截屏2024-02-17 17.57.01.png|居中]]&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.signingkey &amp;quot;GPG key ID&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
为Git设置全局commit和tag签名&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global commit.gpgsign true&lt;br /&gt;
&lt;br /&gt;
git config --global tag.gpgSign true&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
参见本文“在Github配置GPG keys”部分开启下一步操作&lt;br /&gt;
&lt;br /&gt;
接下来就可以愉快的编写程序了~&lt;br /&gt;
&lt;br /&gt;
======在Github配置GPG keys======&lt;br /&gt;
在终端输入&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gpg --armor --export &amp;quot;GPG key ID&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
将输出的内容从-----BEGIN PGP PUBLIC KEY BLOCK-----到-----END PGP PUBLIC KEY BLOCK-----，包含它们都复制下来。&lt;br /&gt;
&lt;br /&gt;
打开Github网页，并登录自己的账号。按照下述操作依次执行。&lt;br /&gt;
&lt;br /&gt;
头像--&amp;gt;Setting--&amp;gt;SSH and GPG keys--&amp;gt;New GPG key&lt;br /&gt;
&lt;br /&gt;
标题自己怎么舒服怎么来，将第一步复制的内容全部粘贴然后保存起来，这样Github就能识别到你commit中包含的GPG sign的信息了，你就可以在commit history或release等页面看到绿色的签名后的标志了。&lt;br /&gt;
&lt;br /&gt;
==== SSH key ====&lt;br /&gt;
可以通过生成SSH key，并保存在Github等托管平台上实现免密Push，这也是官方推荐的方法，过去输入用户名/密码的方式早已被抛弃。&lt;br /&gt;
&lt;br /&gt;
===== 生成Key =====&lt;br /&gt;
1.打开终端并输入 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ls ~/.ssh&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
检查是否已经存在了SSH密钥。如果你看到包含id_rsa等文件，说明你已经有了SSH key，可以跳过第 2 步和第 3 步。&lt;br /&gt;
&lt;br /&gt;
2.输入，生成新的SSH密钥。你可以直接按回车键使用默认的文件路径和空密码，也可以自己设置。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ssh-keygen -t rsa -b 4096 -C &amp;quot;your_email@example.com&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4.在终端输入或使用文本编辑器打开，并复制所有内容&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;vim ~/.ssh/id_rsa.pub&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5.打开Github网页，并登录自己的账号。按照下述操作依次执行。&lt;br /&gt;
&lt;br /&gt;
头像--&amp;gt;Setting--&amp;gt;SSH and GPG keys--&amp;gt;New SSH key&lt;br /&gt;
&lt;br /&gt;
自己起个标题名并粘贴4步中所有内容，保存，接下来你可以免密对Github上的repo进行操作了。&lt;br /&gt;
&lt;br /&gt;
==== 参考资料： ====&lt;br /&gt;
[1] 百度百科 -- Git：&amp;lt;nowiki&amp;gt;https://baike.baidu.com/item/GIT/12647237?fr=ge_ala&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[2] 菜鸟教程 -- Git基本操作：&amp;lt;nowiki&amp;gt;https://www.runoob.com/git/git-basic-operations.html&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[3] CSDN -- git merge 使用简介: &amp;lt;nowiki&amp;gt;https://blog.csdn.net/All_In_gzx_cc/article/details/125482617&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[4] 知乎 -- MAC 安装 homebrew 国内镜像: &amp;lt;nowiki&amp;gt;https://zhuanlan.zhihu.com/p/547898033&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[5] Github -- Generating a new GPG key: &amp;lt;nowiki&amp;gt;https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[6] Github -- Adding a GPG key to your GitHub account: &amp;lt;nowiki&amp;gt;https://docs.github.com/en/authentication/managing-commit-signature-verification/adding-a-gpg-key-to-your-github-account&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[7] Github -- Generating a new SSH key and adding it to the ssh-agent: &amp;lt;nowiki&amp;gt;https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[8] Github -- Adding a new SSH key to your GitHub account: &amp;lt;nowiki&amp;gt;https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=522</id>
		<title>Git使用教程</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=522"/>
		<updated>2024-02-17T10:42:20Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​添加SSH key&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Git的由来： ===&lt;br /&gt;
Git是一个开源的分布式版本控制系统，可以有效、高速地处理从很小到非常大的项目版本管理，也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper。&lt;br /&gt;
&lt;br /&gt;
=== 常见的代码托管平台： ===&lt;br /&gt;
[https://github.com Github]&lt;br /&gt;
&lt;br /&gt;
[https://gitlab.com Gitlab]&lt;br /&gt;
&lt;br /&gt;
[https://gitee.com Gitee]&lt;br /&gt;
&lt;br /&gt;
=== Git 常见命令: ===&lt;br /&gt;
&lt;br /&gt;
==== git init ====&lt;br /&gt;
在本地目录中初始化一个新的Git仓库&lt;br /&gt;
&lt;br /&gt;
==== git config ====&lt;br /&gt;
用于配置用户的信息以及其他设置,在使用git之前您必须完成以下步骤。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.name &amp;quot;your username&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.email &amp;quot;your email&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
更改默认编辑器&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global core.editor nano&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git clone ====&lt;br /&gt;
用于将远程仓库的代码克隆到本地，以下是命令中各个参数的含义：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;url&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆某个地址(url)的仓库，远程仓库的地址可以是本地的目录，也可以是例如github,giteee,gitlab一类的代码托管平台&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;--depth=&amp;lt;number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆仓库并且保留number条提交历史，number在此处即表达我们克隆的深度。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;-b &amp;lt;branch&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆指定分支下的仓库内容&lt;br /&gt;
&lt;br /&gt;
例如我们要克隆&amp;lt;code&amp;gt;LineageOS&amp;lt;/code&amp;gt;的内核源码，指定&amp;lt;code&amp;gt;lineage-21&amp;lt;/code&amp;gt;分支，且仅保留最近一个提交，则需要输入:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git clone -b lineage-21 &amp;lt;nowiki&amp;gt;https://github.com/LineageOS/android_kernel_xiaomi_sdm845&amp;lt;/nowiki&amp;gt; --depth=1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git add ====&lt;br /&gt;
添加某个文件，或者目录到暂存区，用于告诉git你需要将哪些文件的更改包含在下一次的提交(commit)之中添加一个或者多个文件到暂存区之中&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [file1] [file2]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加指定目录(文件)到暂存区，包括子目录：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [dir]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加当前目录下的所有文件到暂存区：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add .&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git status ====&lt;br /&gt;
查看当前仓库的状态，此时git会在你的终端输出以下内容&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;em style=&amp;quot;color: gray;&amp;quot;&amp;gt;此处演示为英文，如果您的git终端输出为中文也是同理的&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
On branch master&lt;br /&gt;
No commits yet&lt;br /&gt;
Changes to be committed:  &lt;br /&gt;
&lt;br /&gt;
(use “git rm --cached &amp;lt;file&amp;gt;...” to unstage)       &lt;br /&gt;
new file:   makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
输出内容分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
您目前所在的分支&lt;br /&gt;
目前的提交&lt;br /&gt;
需要更改的内容&lt;br /&gt;
新增的文件&lt;br /&gt;
修改的文件&lt;br /&gt;
删除的文件&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git commit ====&lt;br /&gt;
用于将暂存区我们保存的更改文件添加到本地仓库，并且会生成一条提交（commit）&lt;br /&gt;
&lt;br /&gt;
提交暂存区的更改到本地仓库&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -m &amp;quot;message&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[注] message 可以是你的备注信息&lt;br /&gt;
&lt;br /&gt;
提交暂存区中的指定文件到本地仓库&lt;br /&gt;
&lt;br /&gt;
如果你没有使用上述&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令暂存你的修改文件，可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -a&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
进行直接提交&lt;br /&gt;
&lt;br /&gt;
==== git checkout ====&lt;br /&gt;
&lt;br /&gt;
* 用于分支切换&lt;br /&gt;
&lt;br /&gt;
切换分支：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如在您的仓库中有这几个分支：&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-&amp;gt; master (Default)&lt;br /&gt;
   backup&lt;br /&gt;
   test&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
您当前处于 master 分支，如果想要切换到test分支，我们可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 用于检出文件&lt;br /&gt;
将指定的文件恢复到最新的提交状态，撤销你对其的更改&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout -- &amp;lt;file&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git push ====&lt;br /&gt;
用于将本地的分支版本上传到远程仓库并进行合并&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push &amp;lt;remote-host-name&amp;gt; &amp;lt;local-branch-name&amp;gt;:&amp;lt;remote-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
remote-host-name:远程主机名&lt;br /&gt;
&lt;br /&gt;
local-branch-name:本地分支名&lt;br /&gt;
&lt;br /&gt;
例如，当你的远程主机名为origin ，本地分支名为master，远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master:master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如，当你的rhost名为origin 本地分支名为master远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
本地和远程分支名相同，上述命令可以简写为：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当你的远程版本与本地版本有差异，无法直接push时，你可以使用--force 参数来进行强制推送&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push --force origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
--force 此处可以直接简单化为 -f &lt;br /&gt;
&lt;br /&gt;
如果你想要删除主机内的某个分支，你可以使用--delete参数&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin --delete &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git diff ====&lt;br /&gt;
用于比较当前工作区与上一个版本之间的差异&lt;br /&gt;
&lt;br /&gt;
例如：（此处仅做不恰当举例，Makefile不是这样乱写的）&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
diff --git a/makefile b/makefile&lt;br /&gt;
&lt;br /&gt;
index fbb8c85..d65c7eb 100644&lt;br /&gt;
&lt;br /&gt;
--- a/makefile&lt;br /&gt;
&lt;br /&gt;
+++ b/makefile&lt;br /&gt;
&lt;br /&gt;
@@ -1 +1,2 @@&lt;br /&gt;
&lt;br /&gt;
114514&lt;br /&gt;
&lt;br /&gt;
+1919180&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git log ====&lt;br /&gt;
用于查看提交的历史&lt;br /&gt;
&lt;br /&gt;
例如当你进行一次提交之后，执行 &amp;lt;code&amp;gt;git log&amp;lt;/code&amp;gt;终端会输出&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit 3a5b0d12f471418b13f2baf5e9e4c112a5e804a8 (HEAD -&amp;gt; master)&lt;br /&gt;
&lt;br /&gt;
Author: luluzzy &amp;lt;1054438588@qq.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Date:   Thu Feb 15 21:28:47 2024 +0800&lt;br /&gt;
&lt;br /&gt;
    initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这些输出分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit sha1 hash:   针对你这个提交的 commit id&lt;br /&gt;
Author: commit      作者名称   &amp;lt;you@example.com&amp;gt;&lt;br /&gt;
Date: commit        日期&lt;br /&gt;
commit:             名称&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
关于sha1_hash的介绍请看这里&amp;lt;ref&amp;gt;生成这个hash值，它是对那个commit是Git仓库中内容和头信息Header的一个校验和checksum。Linux kernel开创者和Git的开发者——Linus说，Git使用了sha1并非是为了安全性，而是为了数据的完整性；它可以保证，在很多年后，你重新checkout某个commit时，一定是它多年前的当时的状态，完全一摸一样，完全值得信任。在Git中，根据commit的sha1值40个十六进制数字进行了简单的划分目录，以前2位数字作为目录名，其下面是剩余38位数字组成的一个文件名&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当有多次提交之后，如果我们想要翻之前的提交历史，难免会因为终端输出的内容过多而难以查看翻阅&lt;br /&gt;
&lt;br /&gt;
此时我们可以使用&amp;lt;code&amp;gt;--online&amp;lt;/code&amp;gt;参数来简化输出，此时仅会输出: sha1哈希值 + commit的名称&lt;br /&gt;
&lt;br /&gt;
例如&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
347595d (HEAD -&amp;gt; master) modify makefile&lt;br /&gt;
&lt;br /&gt;
3a5b0d1 initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git cherry-pick ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
cherry-pick (遴选) 和它的名称一样，挑选一个我们需要的 commit 进行操作。它可以用于将在其他分支上的 commit 修改，移植到当前的分支。&lt;br /&gt;
&lt;br /&gt;
如果我们想在我们正在开发的版本上，添加一个其他版本中的功能代码。就可以使用 cherry-pick ，将这个功能相关的 commit 提取出来，合入该版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick &amp;lt;commit-id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
当我们执行完 &amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;操作之后，会自动生成一个&amp;lt;code&amp;gt;commit&amp;lt;/code&amp;gt;以及对应新的&amp;lt;code&amp;gt;commit-id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在顺利的情况下我们可以直接通过，但如果遇到代码等因为变量名，写法等不同的情况，&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;大概率会报错，此时我们需要进行报错处理。&lt;br /&gt;
&lt;br /&gt;
第一种方案是手动修改&lt;br /&gt;
&lt;br /&gt;
我们可以先使用&amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt;检查当前遴选时冲突的文件&lt;br /&gt;
&lt;br /&gt;
然后 &amp;lt;code&amp;gt;git checkout --ours filename&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
然后按照提交的修改内容进行手动修改&lt;br /&gt;
&lt;br /&gt;
随后使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令将文件重新加入暂存区&lt;br /&gt;
&lt;br /&gt;
再使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --continue&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
命令让 cherrypick 操作继续执行。&lt;br /&gt;
&lt;br /&gt;
第二种方案是直接退出&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;进程，一般适用于冲突文件实在太多了难以按照方案一处理的情况。&lt;br /&gt;
&lt;br /&gt;
需要注意的是，如果您当前正在遴选的提交在该分支已经存在也会冲突，在这种情况下，您需要解决冲突并手动解决问题。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --abort&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git fetch ====&lt;br /&gt;
git fetch 命令用于从远程获取仓库。&lt;br /&gt;
&lt;br /&gt;
==== git merge ====&lt;br /&gt;
&amp;lt;code&amp;gt;git merge&amp;lt;/code&amp;gt;是用来把分叉的提交历史放回到一起(合并)的方式。&lt;br /&gt;
&lt;br /&gt;
git merge命令用来将你之前使用git branch命令创建的分支以及在此分支上独立开发的内容整合为一个分支。&lt;br /&gt;
&lt;br /&gt;
本&lt;br /&gt;
&lt;br /&gt;
==== git pull ====&lt;br /&gt;
用于从远程获取代码并合并本地的版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull&amp;lt;/code&amp;gt;其实就是&amp;lt;code&amp;gt;git fetch&amp;lt;/code&amp;gt;和&amp;lt;code&amp;gt;git merge FETCH_HEAD&amp;lt;/code&amp;gt; 的简写。&lt;br /&gt;
&lt;br /&gt;
格式如下：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull &amp;lt;remote-host-name&amp;gt; &amp;lt;remote-branch-name&amp;gt;:&amp;lt;local-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git rebase ====&lt;br /&gt;
用于需要修改历史上某一项commit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git rebase -i HEAD~&amp;lt;commit number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
commit number就是从头部往前数的commit数量。执行后会弹出你在git config内配置的编辑器，若未配置则是默认，vim居多。然后就可以看见一堆commit前面有pick字样。可以将pick替换为你想要的操作。&lt;br /&gt;
有以下操作：&lt;br /&gt;
&lt;br /&gt;
1.edit，顾名思义编辑此commit，替换完保存后请修改内容，使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;或vscode，github desktop将修改文件添加到暂存区，之后命令行执行&amp;lt;code&amp;gt;git commit --amend&amp;lt;/code&amp;gt;这样commit就修改成了&lt;br /&gt;
&lt;br /&gt;
2.squash，合并几个提交，确认一个父提交，将要合并的commit，从下向上替换字符串，会从下向上合并(方位指的是&amp;lt;code&amp;gt;git rebase&amp;lt;/code&amp;gt;后弹出的编辑器)&lt;br /&gt;
&lt;br /&gt;
3.drop，需要移除的commit&lt;br /&gt;
&lt;br /&gt;
==== git subtree ====&lt;br /&gt;
子树，在Android开发中多用于Kernel侧更改，如跟踪audio模块等&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree add --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果需要更新远程库时&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree pull --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git submodule ====&lt;br /&gt;
&lt;br /&gt;
===== 子模块功能的概述 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在自己的Github仓库里加入别人的github仓库，作为自己仓库的子仓库(即submodule)。&lt;br /&gt;
&lt;br /&gt;
为什么我们会需要使用子模块？当我们维护一个项目时有可能遇到以下情况，例如维护某款机型的KernelSU内核，我们需要将KernelSU导入至我们的内核源码中，如果我们直接clone进去容易带来一个问题，如果KernelSU更新了怎么办？此时我们便可以使用子模块来解决这个问题&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在git仓库里存放别人仓库的url，作为自己的子模块，其核心内容是在Git仓库里面加入一个&amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;文件，里面会记录各个submodule的名字，路径，以及对应链接。&lt;br /&gt;
&lt;br /&gt;
===== 加入子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule add &amp;lt;url&amp;gt; &amp;lt;path&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
此时 &amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;内会自动生成以下内容&lt;br /&gt;
&lt;br /&gt;
[submodule &amp;quot;xxx&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
path = xxx&lt;br /&gt;
&lt;br /&gt;
url = xxx&lt;br /&gt;
&lt;br /&gt;
===== 初始化子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule init&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== 更新子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule update&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Git进阶 ===&lt;br /&gt;
&lt;br /&gt;
==== GPG key ====&lt;br /&gt;
&lt;br /&gt;
===== 简介 =====&lt;br /&gt;
平时在Github上摸鱼的时候，是不是经常能看见如下图所示，有一个绿色的&amp;quot;Verified&amp;quot;字样，看着很酷，实际上这是为了确保commit为开发者本人所写的进行的GPG签名。&lt;br /&gt;
[[文件:Github GPG sign.png|居中]]&lt;br /&gt;
因为Git的默认机制，任何人都可以通过你的邮箱和用户名创建虚假的commit，甚至你名气很大的话可以“栽赃陷害”你。如果你是某高校计算机专业的同学亦或是对计算机抱有很大的兴趣，乐意为开源社区提供“资源”，那么我建议你设置GPG sign。未来是不可预知的，人人都可能成为巨佬。&lt;br /&gt;
&lt;br /&gt;
===== 使用 =====&lt;br /&gt;
因为我只在Mac环境下配置过GPG，Windows只是打游戏用，所以用的少，Linux/类Unix可以参考一下。其它系统等待他人补充......&lt;br /&gt;
&lt;br /&gt;
====== Mac ======&lt;br /&gt;
Mac默认是不带GPG的，需要通过第三方软件包安装器Homebrew进行安装，首先先安装Homebrew，如已安装可以跳过。&lt;br /&gt;
&lt;br /&gt;
编辑器限制原因不能使用默认标题进行分步了，故使用1、2、3等小数字代替。&lt;br /&gt;
&lt;br /&gt;
安装Homebrew&lt;br /&gt;
&lt;br /&gt;
在安装之前需要从系统信息中查看芯片为Intel/M系列&lt;br /&gt;
&lt;br /&gt;
Intel使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/bin/zsh -c &amp;quot;$(curl -fsSL &amp;lt;nowiki&amp;gt;https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh&amp;lt;/nowiki&amp;gt;)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Intel按照脚本提示，选源，输密码，回车一路绿灯就好了，如果这都不会......可能你不是很适合开发，因为该脚本是国内开发者编写的，中文和一键化安装都集齐了。&lt;br /&gt;
&lt;br /&gt;
M系列使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/bin/zsh -c &amp;quot;$(curl -fsSL https://gitee.com/huwei1024/HomebrewCN/raw/master/Homebrew.sh)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
并且因为M系列系统结构发生改变，包安装位置不在是以前的/usr/local/，而是在/opt/homebrew，所以要将配置文件里的环境变量改过来。&lt;br /&gt;
&lt;br /&gt;
1.首先进入根目录&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cd ~&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.创建.zshrc文件&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;touch .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3.打开文件进行编辑&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;open -e .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4.如果有旧的环境就修改，没有就新增&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;export PATH=&amp;quot;/opt/homebrew/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
export PATH=&amp;quot;/opt/homebrew/sbin:$PATH&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5.保存&lt;br /&gt;
&lt;br /&gt;
使用command + s&lt;br /&gt;
&lt;br /&gt;
6.生效环境变量&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;source .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
7、测试&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;brew -v&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
若终端顺利打印出brew的版本，那么就安装成功了！&lt;br /&gt;
&lt;br /&gt;
注：本人没有使用过M系列设备，该教程在知乎上找到的&lt;br /&gt;
&lt;br /&gt;
使用Homebrew安装GPG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;brew install gnupg pinentry-mac&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.34.48.png|居中]]&lt;br /&gt;
&lt;br /&gt;
为GPG添加环境变量，否则在签名的时候会发生报错（使用bash请自行替换配置文件）&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;echo &amp;quot;export GPG_TTY=$(tty)&amp;quot; &amp;gt;&amp;gt; ~/.zshrc&lt;br /&gt;
source ~/.zshrc&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
生成一个GPG keys&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gpg --full-generate-key&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.45.51.png|居中]]&lt;br /&gt;
&lt;br /&gt;
默认使用的是ECC，我使用的是RSA，按照自己喜好，或从百度搜索非对称和对称加密算法之间的区别，这里只做使用方法的介绍，不做赘述。&lt;br /&gt;
&lt;br /&gt;
然后添写密钥长度和使用有效期，这里建议选择长期，并做备份，一辈子用一个就够了。&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.46.06.png|居中]]&lt;br /&gt;
[[文件:截屏2024-02-17 17.46.35.png|居中]]&lt;br /&gt;
&lt;br /&gt;
个人信息按照Github信息填写，真实姓名对应Username。填写完毕按回车输入O即可生成密钥。不出意外的话会弹出Gui窗口让你设置密钥密码，强烈建设设置一个较为复杂的密码，并牢记，当然也可以不设置。&lt;br /&gt;
&lt;br /&gt;
使用GPG对Git的commit和tag进行签名&lt;br /&gt;
&lt;br /&gt;
先为Git定义GPG二进制所在地&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global gpg.program $(which gpg)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
查看GPG keys ID&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gpg --list-secret-keys --keyid-format=long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如图所示RSA/后面紧跟的一串就是GPG keys ID&lt;br /&gt;
[[文件:截屏2024-02-17 17.57.01.png|居中]]&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.signingkey &amp;quot;GPG key ID&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
为Git设置全局commit和tag签名&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global commit.gpgsign true&lt;br /&gt;
&lt;br /&gt;
git config --global tag.gpgSign true&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
参见本文“在Github配置GPG keys”部分开启下一步操作&lt;br /&gt;
&lt;br /&gt;
接下来就可以愉快的编写程序了~&lt;br /&gt;
&lt;br /&gt;
======在Github配置GPG keys======&lt;br /&gt;
在终端输入&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gpg --armor --export &amp;quot;GPG key ID&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
将输出的内容从-----BEGIN PGP PUBLIC KEY BLOCK-----到-----END PGP PUBLIC KEY BLOCK-----，包含它们都复制下来。&lt;br /&gt;
&lt;br /&gt;
打开Github网页，并登录自己的账号。按照下述操作依次执行。&lt;br /&gt;
&lt;br /&gt;
头像--&amp;gt;Setting--&amp;gt;SSH and GPG keys--&amp;gt;New GPG key&lt;br /&gt;
&lt;br /&gt;
标题自己怎么舒服怎么来，将第一步复制的内容全部粘贴然后保存起来，这样Github就能识别到你commit中包含的GPG sign的信息了，你就可以在commit history或release等页面看到绿色的签名后的标志了。&lt;br /&gt;
&lt;br /&gt;
==== SSH key ====&lt;br /&gt;
可以通过生成SSH key，并保存在Github等托管平台上实现免密Push，这也是官方推荐的方法，过去输入用户名/密码的方式早已被抛弃。&lt;br /&gt;
&lt;br /&gt;
===== 生成Key =====&lt;br /&gt;
1.打开终端并输入 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ls ~/.ssh&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
检查是否已经存在了SSH密钥。如果你看到包含id_rsa等文件，说明你已经有了SSH key，可以跳过第 2 步和第 3 步。&lt;br /&gt;
&lt;br /&gt;
2.输入，生成新的SSH密钥。你可以直接按回车键使用默认的文件路径和空密码，也可以自己设置。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ssh-keygen -t rsa -b 4096 -C &amp;quot;your_email@example.com&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4.在终端输入或使用文本编辑器打开，并复制所有内容&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;vim ~/.ssh/id_rsa.pub&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5.打开Github网页，并登录自己的账号。按照下述操作依次执行。&lt;br /&gt;
&lt;br /&gt;
头像--&amp;gt;Setting--&amp;gt;SSH and GPG keys--&amp;gt;New SSH key&lt;br /&gt;
&lt;br /&gt;
自己起个标题名并粘贴4步中所有内容，保存，接下来你可以免密对Github上的repo进行操作了。&lt;br /&gt;
&lt;br /&gt;
==== 参考资料： ====&lt;br /&gt;
[1] 百度百科 -- Git：&amp;lt;nowiki&amp;gt;https://baike.baidu.com/item/GIT/12647237?fr=ge_ala&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[2] 菜鸟教程 -- Git基本操作：&amp;lt;nowiki&amp;gt;https://www.runoob.com/git/git-basic-operations.html&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[3] CSDN -- git merge 使用简介: &amp;lt;nowiki&amp;gt;https://blog.csdn.net/All_In_gzx_cc/article/details/125482617&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[4] 知乎 -- MAC 安装 homebrew 国内镜像: &amp;lt;nowiki&amp;gt;https://zhuanlan.zhihu.com/p/547898033&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[5] Github -- Generating a new GPG key : &amp;lt;nowiki&amp;gt;https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=521</id>
		<title>Git使用教程</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=521"/>
		<updated>2024-02-17T10:29:57Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​/* 添加参考资料 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Git的由来： ===&lt;br /&gt;
Git是一个开源的分布式版本控制系统，可以有效、高速地处理从很小到非常大的项目版本管理，也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper。&lt;br /&gt;
&lt;br /&gt;
=== 常见的代码托管平台： ===&lt;br /&gt;
[https://github.com Github]&lt;br /&gt;
&lt;br /&gt;
[https://gitlab.com Gitlab]&lt;br /&gt;
&lt;br /&gt;
[https://gitee.com Gitee]&lt;br /&gt;
&lt;br /&gt;
=== Git 常见命令: ===&lt;br /&gt;
&lt;br /&gt;
==== git init ====&lt;br /&gt;
在本地目录中初始化一个新的Git仓库&lt;br /&gt;
&lt;br /&gt;
==== git config ====&lt;br /&gt;
用于配置用户的信息以及其他设置,在使用git之前您必须完成以下步骤。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.name &amp;quot;your username&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.email &amp;quot;your email&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
更改默认编辑器&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global core.editor nano&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git clone ====&lt;br /&gt;
用于将远程仓库的代码克隆到本地，以下是命令中各个参数的含义：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;url&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆某个地址(url)的仓库，远程仓库的地址可以是本地的目录，也可以是例如github,giteee,gitlab一类的代码托管平台&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;--depth=&amp;lt;number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆仓库并且保留number条提交历史，number在此处即表达我们克隆的深度。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;-b &amp;lt;branch&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆指定分支下的仓库内容&lt;br /&gt;
&lt;br /&gt;
例如我们要克隆&amp;lt;code&amp;gt;LineageOS&amp;lt;/code&amp;gt;的内核源码，指定&amp;lt;code&amp;gt;lineage-21&amp;lt;/code&amp;gt;分支，且仅保留最近一个提交，则需要输入:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git clone -b lineage-21 &amp;lt;nowiki&amp;gt;https://github.com/LineageOS/android_kernel_xiaomi_sdm845&amp;lt;/nowiki&amp;gt; --depth=1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git add ====&lt;br /&gt;
添加某个文件，或者目录到暂存区，用于告诉git你需要将哪些文件的更改包含在下一次的提交(commit)之中添加一个或者多个文件到暂存区之中&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [file1] [file2]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加指定目录(文件)到暂存区，包括子目录：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [dir]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加当前目录下的所有文件到暂存区：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add .&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git status ====&lt;br /&gt;
查看当前仓库的状态，此时git会在你的终端输出以下内容&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;em style=&amp;quot;color: gray;&amp;quot;&amp;gt;此处演示为英文，如果您的git终端输出为中文也是同理的&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
On branch master&lt;br /&gt;
No commits yet&lt;br /&gt;
Changes to be committed:  &lt;br /&gt;
&lt;br /&gt;
(use “git rm --cached &amp;lt;file&amp;gt;...” to unstage)       &lt;br /&gt;
new file:   makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
输出内容分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
您目前所在的分支&lt;br /&gt;
目前的提交&lt;br /&gt;
需要更改的内容&lt;br /&gt;
新增的文件&lt;br /&gt;
修改的文件&lt;br /&gt;
删除的文件&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git commit ====&lt;br /&gt;
用于将暂存区我们保存的更改文件添加到本地仓库，并且会生成一条提交（commit）&lt;br /&gt;
&lt;br /&gt;
提交暂存区的更改到本地仓库&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -m &amp;quot;message&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[注] message 可以是你的备注信息&lt;br /&gt;
&lt;br /&gt;
提交暂存区中的指定文件到本地仓库&lt;br /&gt;
&lt;br /&gt;
如果你没有使用上述&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令暂存你的修改文件，可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -a&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
进行直接提交&lt;br /&gt;
&lt;br /&gt;
==== git checkout ====&lt;br /&gt;
&lt;br /&gt;
* 用于分支切换&lt;br /&gt;
&lt;br /&gt;
切换分支：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如在您的仓库中有这几个分支：&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-&amp;gt; master (Default)&lt;br /&gt;
   backup&lt;br /&gt;
   test&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
您当前处于 master 分支，如果想要切换到test分支，我们可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 用于检出文件&lt;br /&gt;
将指定的文件恢复到最新的提交状态，撤销你对其的更改&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout -- &amp;lt;file&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git push ====&lt;br /&gt;
用于将本地的分支版本上传到远程仓库并进行合并&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push &amp;lt;remote-host-name&amp;gt; &amp;lt;local-branch-name&amp;gt;:&amp;lt;remote-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
remote-host-name:远程主机名&lt;br /&gt;
&lt;br /&gt;
local-branch-name:本地分支名&lt;br /&gt;
&lt;br /&gt;
例如，当你的远程主机名为origin ，本地分支名为master，远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master:master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如，当你的rhost名为origin 本地分支名为master远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
本地和远程分支名相同，上述命令可以简写为：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当你的远程版本与本地版本有差异，无法直接push时，你可以使用--force 参数来进行强制推送&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push --force origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
--force 此处可以直接简单化为 -f &lt;br /&gt;
&lt;br /&gt;
如果你想要删除主机内的某个分支，你可以使用--delete参数&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin --delete &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git diff ====&lt;br /&gt;
用于比较当前工作区与上一个版本之间的差异&lt;br /&gt;
&lt;br /&gt;
例如：（此处仅做不恰当举例，Makefile不是这样乱写的）&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
diff --git a/makefile b/makefile&lt;br /&gt;
&lt;br /&gt;
index fbb8c85..d65c7eb 100644&lt;br /&gt;
&lt;br /&gt;
--- a/makefile&lt;br /&gt;
&lt;br /&gt;
+++ b/makefile&lt;br /&gt;
&lt;br /&gt;
@@ -1 +1,2 @@&lt;br /&gt;
&lt;br /&gt;
114514&lt;br /&gt;
&lt;br /&gt;
+1919180&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git log ====&lt;br /&gt;
用于查看提交的历史&lt;br /&gt;
&lt;br /&gt;
例如当你进行一次提交之后，执行 &amp;lt;code&amp;gt;git log&amp;lt;/code&amp;gt;终端会输出&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit 3a5b0d12f471418b13f2baf5e9e4c112a5e804a8 (HEAD -&amp;gt; master)&lt;br /&gt;
&lt;br /&gt;
Author: luluzzy &amp;lt;1054438588@qq.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Date:   Thu Feb 15 21:28:47 2024 +0800&lt;br /&gt;
&lt;br /&gt;
    initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这些输出分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit sha1 hash:   针对你这个提交的 commit id&lt;br /&gt;
Author: commit      作者名称   &amp;lt;you@example.com&amp;gt;&lt;br /&gt;
Date: commit        日期&lt;br /&gt;
commit:             名称&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
关于sha1_hash的介绍请看这里&amp;lt;ref&amp;gt;生成这个hash值，它是对那个commit是Git仓库中内容和头信息Header的一个校验和checksum。Linux kernel开创者和Git的开发者——Linus说，Git使用了sha1并非是为了安全性，而是为了数据的完整性；它可以保证，在很多年后，你重新checkout某个commit时，一定是它多年前的当时的状态，完全一摸一样，完全值得信任。在Git中，根据commit的sha1值40个十六进制数字进行了简单的划分目录，以前2位数字作为目录名，其下面是剩余38位数字组成的一个文件名&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当有多次提交之后，如果我们想要翻之前的提交历史，难免会因为终端输出的内容过多而难以查看翻阅&lt;br /&gt;
&lt;br /&gt;
此时我们可以使用&amp;lt;code&amp;gt;--online&amp;lt;/code&amp;gt;参数来简化输出，此时仅会输出: sha1哈希值 + commit的名称&lt;br /&gt;
&lt;br /&gt;
例如&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
347595d (HEAD -&amp;gt; master) modify makefile&lt;br /&gt;
&lt;br /&gt;
3a5b0d1 initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git cherry-pick ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
cherry-pick (遴选) 和它的名称一样，挑选一个我们需要的 commit 进行操作。它可以用于将在其他分支上的 commit 修改，移植到当前的分支。&lt;br /&gt;
&lt;br /&gt;
如果我们想在我们正在开发的版本上，添加一个其他版本中的功能代码。就可以使用 cherry-pick ，将这个功能相关的 commit 提取出来，合入该版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick &amp;lt;commit-id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
当我们执行完 &amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;操作之后，会自动生成一个&amp;lt;code&amp;gt;commit&amp;lt;/code&amp;gt;以及对应新的&amp;lt;code&amp;gt;commit-id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在顺利的情况下我们可以直接通过，但如果遇到代码等因为变量名，写法等不同的情况，&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;大概率会报错，此时我们需要进行报错处理。&lt;br /&gt;
&lt;br /&gt;
第一种方案是手动修改&lt;br /&gt;
&lt;br /&gt;
我们可以先使用&amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt;检查当前遴选时冲突的文件&lt;br /&gt;
&lt;br /&gt;
然后 &amp;lt;code&amp;gt;git checkout --ours filename&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
然后按照提交的修改内容进行手动修改&lt;br /&gt;
&lt;br /&gt;
随后使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令将文件重新加入暂存区&lt;br /&gt;
&lt;br /&gt;
再使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --continue&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
命令让 cherrypick 操作继续执行。&lt;br /&gt;
&lt;br /&gt;
第二种方案是直接退出&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;进程，一般适用于冲突文件实在太多了难以按照方案一处理的情况。&lt;br /&gt;
&lt;br /&gt;
需要注意的是，如果您当前正在遴选的提交在该分支已经存在也会冲突，在这种情况下，您需要解决冲突并手动解决问题。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --abort&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git fetch ====&lt;br /&gt;
git fetch 命令用于从远程获取仓库。&lt;br /&gt;
&lt;br /&gt;
==== git merge ====&lt;br /&gt;
&amp;lt;code&amp;gt;git merge&amp;lt;/code&amp;gt;是用来把分叉的提交历史放回到一起(合并)的方式。&lt;br /&gt;
&lt;br /&gt;
git merge命令用来将你之前使用git branch命令创建的分支以及在此分支上独立开发的内容整合为一个分支。&lt;br /&gt;
&lt;br /&gt;
本&lt;br /&gt;
&lt;br /&gt;
==== git pull ====&lt;br /&gt;
用于从远程获取代码并合并本地的版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull&amp;lt;/code&amp;gt;其实就是&amp;lt;code&amp;gt;git fetch&amp;lt;/code&amp;gt;和&amp;lt;code&amp;gt;git merge FETCH_HEAD&amp;lt;/code&amp;gt; 的简写。&lt;br /&gt;
&lt;br /&gt;
格式如下：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull &amp;lt;remote-host-name&amp;gt; &amp;lt;remote-branch-name&amp;gt;:&amp;lt;local-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git rebase ====&lt;br /&gt;
用于需要修改历史上某一项commit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git rebase -i HEAD~&amp;lt;commit number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
commit number就是从头部往前数的commit数量。执行后会弹出你在git config内配置的编辑器，若未配置则是默认，vim居多。然后就可以看见一堆commit前面有pick字样。可以将pick替换为你想要的操作。&lt;br /&gt;
有以下操作：&lt;br /&gt;
&lt;br /&gt;
1.edit，顾名思义编辑此commit，替换完保存后请修改内容，使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;或vscode，github desktop将修改文件添加到暂存区，之后命令行执行&amp;lt;code&amp;gt;git commit --amend&amp;lt;/code&amp;gt;这样commit就修改成了&lt;br /&gt;
&lt;br /&gt;
2.squash，合并几个提交，确认一个父提交，将要合并的commit，从下向上替换字符串，会从下向上合并(方位指的是&amp;lt;code&amp;gt;git rebase&amp;lt;/code&amp;gt;后弹出的编辑器)&lt;br /&gt;
&lt;br /&gt;
3.drop，需要移除的commit&lt;br /&gt;
&lt;br /&gt;
==== git subtree ====&lt;br /&gt;
子树，在Android开发中多用于Kernel侧更改，如跟踪audio模块等&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree add --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果需要更新远程库时&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree pull --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git submodule ====&lt;br /&gt;
&lt;br /&gt;
===== 子模块功能的概述 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在自己的Github仓库里加入别人的github仓库，作为自己仓库的子仓库(即submodule)。&lt;br /&gt;
&lt;br /&gt;
为什么我们会需要使用子模块？当我们维护一个项目时有可能遇到以下情况，例如维护某款机型的KernelSU内核，我们需要将KernelSU导入至我们的内核源码中，如果我们直接clone进去容易带来一个问题，如果KernelSU更新了怎么办？此时我们便可以使用子模块来解决这个问题&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在git仓库里存放别人仓库的url，作为自己的子模块，其核心内容是在Git仓库里面加入一个&amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;文件，里面会记录各个submodule的名字，路径，以及对应链接。&lt;br /&gt;
&lt;br /&gt;
===== 加入子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule add &amp;lt;url&amp;gt; &amp;lt;path&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
此时 &amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;内会自动生成以下内容&lt;br /&gt;
&lt;br /&gt;
[submodule &amp;quot;xxx&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
path = xxx&lt;br /&gt;
&lt;br /&gt;
url = xxx&lt;br /&gt;
&lt;br /&gt;
===== 初始化子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule init&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== 更新子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule update&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Git进阶 ===&lt;br /&gt;
&lt;br /&gt;
==== GPG key ====&lt;br /&gt;
&lt;br /&gt;
===== 简介 =====&lt;br /&gt;
平时在Github上摸鱼的时候，是不是经常能看见如下图所示，有一个绿色的&amp;quot;Verified&amp;quot;字样，看着很酷，实际上这是为了确保commit为开发者本人所写的进行的GPG签名。&lt;br /&gt;
[[文件:Github GPG sign.png|居中]]&lt;br /&gt;
因为Git的默认机制，任何人都可以通过你的邮箱和用户名创建虚假的commit，甚至你名气很大的话可以“栽赃陷害”你。如果你是某高校计算机专业的同学亦或是对计算机抱有很大的兴趣，乐意为开源社区提供“资源”，那么我建议你设置GPG sign。未来是不可预知的，人人都可能成为巨佬。&lt;br /&gt;
&lt;br /&gt;
===== 使用 =====&lt;br /&gt;
因为我只在Mac环境下配置过GPG，Windows只是打游戏用，所以用的少，Linux/类Unix可以参考一下。其它系统等待他人补充......&lt;br /&gt;
&lt;br /&gt;
====== Mac ======&lt;br /&gt;
Mac默认是不带GPG的，需要通过第三方软件包安装器Homebrew进行安装，首先先安装Homebrew，如已安装可以跳过。&lt;br /&gt;
&lt;br /&gt;
编辑器限制原因不能使用默认标题进行分步了，故使用1、2、3等小数字代替。&lt;br /&gt;
&lt;br /&gt;
安装Homebrew&lt;br /&gt;
&lt;br /&gt;
在安装之前需要从系统信息中查看芯片为Intel/M系列&lt;br /&gt;
&lt;br /&gt;
Intel使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/bin/zsh -c &amp;quot;$(curl -fsSL &amp;lt;nowiki&amp;gt;https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh&amp;lt;/nowiki&amp;gt;)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Intel按照脚本提示，选源，输密码，回车一路绿灯就好了，如果这都不会......可能你不是很适合开发，因为该脚本是国内开发者编写的，中文和一键化安装都集齐了。&lt;br /&gt;
&lt;br /&gt;
M系列使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/bin/zsh -c &amp;quot;$(curl -fsSL https://gitee.com/huwei1024/HomebrewCN/raw/master/Homebrew.sh)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
并且因为M系列系统结构发生改变，包安装位置不在是以前的/usr/local/，而是在/opt/homebrew，所以要将配置文件里的环境变量改过来。&lt;br /&gt;
&lt;br /&gt;
1.首先进入根目录&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cd ~&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.创建.zshrc文件&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;touch .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3.打开文件进行编辑&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;open -e .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4.如果有旧的环境就修改，没有就新增&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;export PATH=&amp;quot;/opt/homebrew/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
export PATH=&amp;quot;/opt/homebrew/sbin:$PATH&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5.保存&lt;br /&gt;
&lt;br /&gt;
使用command + s&lt;br /&gt;
&lt;br /&gt;
6.生效环境变量&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;source .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
7、测试&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;brew -v&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
若终端顺利打印出brew的版本，那么就安装成功了！&lt;br /&gt;
&lt;br /&gt;
注：本人没有使用过M系列设备，该教程在知乎上找到的&lt;br /&gt;
&lt;br /&gt;
使用Homebrew安装GPG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;brew install gnupg pinentry-mac&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.34.48.png|居中]]&lt;br /&gt;
&lt;br /&gt;
为GPG添加环境变量，否则在签名的时候会发生报错（使用bash请自行替换配置文件）&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;echo &amp;quot;export GPG_TTY=$(tty)&amp;quot; &amp;gt;&amp;gt; ~/.zshrc&lt;br /&gt;
source ~/.zshrc&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
生成一个GPG keys&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gpg --full-generate-key&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.45.51.png|居中]]&lt;br /&gt;
&lt;br /&gt;
默认使用的是ECC，我使用的是RSA，按照自己喜好，或从百度搜索非对称和对称加密算法之间的区别，这里只做使用方法的介绍，不做赘述。&lt;br /&gt;
&lt;br /&gt;
然后添写密钥长度和使用有效期，这里建议选择长期，并做备份，一辈子用一个就够了。&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.46.06.png|居中]]&lt;br /&gt;
[[文件:截屏2024-02-17 17.46.35.png|居中]]&lt;br /&gt;
&lt;br /&gt;
个人信息按照Github信息填写，真实姓名对应Username。填写完毕按回车输入O即可生成密钥。不出意外的话会弹出Gui窗口让你设置密钥密码，强烈建设设置一个较为复杂的密码，并牢记，当然也可以不设置。&lt;br /&gt;
&lt;br /&gt;
使用GPG对Git的commit和tag进行签名&lt;br /&gt;
&lt;br /&gt;
先为Git定义GPG二进制所在地&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global gpg.program $(which gpg)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
查看GPG keys ID&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gpg --list-secret-keys --keyid-format=long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如图所示RSA/后面紧跟的一串就是GPG keys ID&lt;br /&gt;
[[文件:截屏2024-02-17 17.57.01.png|居中]]&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.signingkey &amp;quot;GPG key ID&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
为Git设置全局commit和tag签名&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global commit.gpgsign true&lt;br /&gt;
&lt;br /&gt;
git config --global tag.gpgSign true&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
参见本文“在Github配置GPG keys”部分开启下一步操作&lt;br /&gt;
&lt;br /&gt;
接下来就可以愉快的编写程序了~&lt;br /&gt;
&lt;br /&gt;
======在Github配置GPG keys======&lt;br /&gt;
在终端输入&lt;br /&gt;
&lt;br /&gt;
gpg --armor --export &amp;quot;GPG key ID&amp;quot;&lt;br /&gt;
&lt;br /&gt;
将输出的内容从-----BEGIN PGP PUBLIC KEY BLOCK-----到-----END PGP PUBLIC KEY BLOCK-----，包含它们都复制下来。&lt;br /&gt;
&lt;br /&gt;
打开Github网页，并登录自己的账号。按照下述操作依次执行。&lt;br /&gt;
头像--&amp;gt;Setting--&amp;gt;SSH and GPG keys--&amp;gt;New GPG key，标题自己怎么舒服怎么来，将第一步复制的内容全部粘贴然后保存起来，这样Github就能识别到你commit中包含的GPG sign的信息了，你就可以在commit history或release等页面看到绿色的签名后的标志了。&lt;br /&gt;
&lt;br /&gt;
==== 参考资料： ====&lt;br /&gt;
[1] 百度百科 -- Git：&amp;lt;nowiki&amp;gt;https://baike.baidu.com/item/GIT/12647237?fr=ge_ala&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[2] 菜鸟教程 -- Git基本操作：&amp;lt;nowiki&amp;gt;https://www.runoob.com/git/git-basic-operations.html&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[3] CSDN -- git merge 使用简介: &amp;lt;nowiki&amp;gt;https://blog.csdn.net/All_In_gzx_cc/article/details/125482617&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[4] 知乎 -- MAC 安装 homebrew 国内镜像: &amp;lt;nowiki&amp;gt;https://zhuanlan.zhihu.com/p/547898033&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[5] Github -- Generating a new GPG key : &amp;lt;nowiki&amp;gt;https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=520</id>
		<title>Git使用教程</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=520"/>
		<updated>2024-02-17T10:27:58Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​/* Mac */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Git的由来： ===&lt;br /&gt;
Git是一个开源的分布式版本控制系统，可以有效、高速地处理从很小到非常大的项目版本管理，也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper。&lt;br /&gt;
&lt;br /&gt;
=== 常见的代码托管平台： ===&lt;br /&gt;
[https://github.com Github]&lt;br /&gt;
&lt;br /&gt;
[https://gitlab.com Gitlab]&lt;br /&gt;
&lt;br /&gt;
[https://gitee.com Gitee]&lt;br /&gt;
&lt;br /&gt;
=== Git 常见命令: ===&lt;br /&gt;
&lt;br /&gt;
==== git init ====&lt;br /&gt;
在本地目录中初始化一个新的Git仓库&lt;br /&gt;
&lt;br /&gt;
==== git config ====&lt;br /&gt;
用于配置用户的信息以及其他设置,在使用git之前您必须完成以下步骤。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.name &amp;quot;your username&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.email &amp;quot;your email&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
更改默认编辑器&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global core.editor nano&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git clone ====&lt;br /&gt;
用于将远程仓库的代码克隆到本地，以下是命令中各个参数的含义：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;url&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆某个地址(url)的仓库，远程仓库的地址可以是本地的目录，也可以是例如github,giteee,gitlab一类的代码托管平台&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;--depth=&amp;lt;number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆仓库并且保留number条提交历史，number在此处即表达我们克隆的深度。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;-b &amp;lt;branch&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆指定分支下的仓库内容&lt;br /&gt;
&lt;br /&gt;
例如我们要克隆&amp;lt;code&amp;gt;LineageOS&amp;lt;/code&amp;gt;的内核源码，指定&amp;lt;code&amp;gt;lineage-21&amp;lt;/code&amp;gt;分支，且仅保留最近一个提交，则需要输入:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git clone -b lineage-21 &amp;lt;nowiki&amp;gt;https://github.com/LineageOS/android_kernel_xiaomi_sdm845&amp;lt;/nowiki&amp;gt; --depth=1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git add ====&lt;br /&gt;
添加某个文件，或者目录到暂存区，用于告诉git你需要将哪些文件的更改包含在下一次的提交(commit)之中添加一个或者多个文件到暂存区之中&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [file1] [file2]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加指定目录(文件)到暂存区，包括子目录：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [dir]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加当前目录下的所有文件到暂存区：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add .&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git status ====&lt;br /&gt;
查看当前仓库的状态，此时git会在你的终端输出以下内容&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;em style=&amp;quot;color: gray;&amp;quot;&amp;gt;此处演示为英文，如果您的git终端输出为中文也是同理的&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
On branch master&lt;br /&gt;
No commits yet&lt;br /&gt;
Changes to be committed:  &lt;br /&gt;
&lt;br /&gt;
(use “git rm --cached &amp;lt;file&amp;gt;...” to unstage)       &lt;br /&gt;
new file:   makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
输出内容分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
您目前所在的分支&lt;br /&gt;
目前的提交&lt;br /&gt;
需要更改的内容&lt;br /&gt;
新增的文件&lt;br /&gt;
修改的文件&lt;br /&gt;
删除的文件&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git commit ====&lt;br /&gt;
用于将暂存区我们保存的更改文件添加到本地仓库，并且会生成一条提交（commit）&lt;br /&gt;
&lt;br /&gt;
提交暂存区的更改到本地仓库&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -m &amp;quot;message&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[注] message 可以是你的备注信息&lt;br /&gt;
&lt;br /&gt;
提交暂存区中的指定文件到本地仓库&lt;br /&gt;
&lt;br /&gt;
如果你没有使用上述&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令暂存你的修改文件，可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -a&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
进行直接提交&lt;br /&gt;
&lt;br /&gt;
==== git checkout ====&lt;br /&gt;
&lt;br /&gt;
* 用于分支切换&lt;br /&gt;
&lt;br /&gt;
切换分支：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如在您的仓库中有这几个分支：&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-&amp;gt; master (Default)&lt;br /&gt;
   backup&lt;br /&gt;
   test&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
您当前处于 master 分支，如果想要切换到test分支，我们可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 用于检出文件&lt;br /&gt;
将指定的文件恢复到最新的提交状态，撤销你对其的更改&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout -- &amp;lt;file&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git push ====&lt;br /&gt;
用于将本地的分支版本上传到远程仓库并进行合并&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push &amp;lt;remote-host-name&amp;gt; &amp;lt;local-branch-name&amp;gt;:&amp;lt;remote-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
remote-host-name:远程主机名&lt;br /&gt;
&lt;br /&gt;
local-branch-name:本地分支名&lt;br /&gt;
&lt;br /&gt;
例如，当你的远程主机名为origin ，本地分支名为master，远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master:master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如，当你的rhost名为origin 本地分支名为master远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
本地和远程分支名相同，上述命令可以简写为：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当你的远程版本与本地版本有差异，无法直接push时，你可以使用--force 参数来进行强制推送&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push --force origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
--force 此处可以直接简单化为 -f &lt;br /&gt;
&lt;br /&gt;
如果你想要删除主机内的某个分支，你可以使用--delete参数&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin --delete &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git diff ====&lt;br /&gt;
用于比较当前工作区与上一个版本之间的差异&lt;br /&gt;
&lt;br /&gt;
例如：（此处仅做不恰当举例，Makefile不是这样乱写的）&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
diff --git a/makefile b/makefile&lt;br /&gt;
&lt;br /&gt;
index fbb8c85..d65c7eb 100644&lt;br /&gt;
&lt;br /&gt;
--- a/makefile&lt;br /&gt;
&lt;br /&gt;
+++ b/makefile&lt;br /&gt;
&lt;br /&gt;
@@ -1 +1,2 @@&lt;br /&gt;
&lt;br /&gt;
114514&lt;br /&gt;
&lt;br /&gt;
+1919180&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git log ====&lt;br /&gt;
用于查看提交的历史&lt;br /&gt;
&lt;br /&gt;
例如当你进行一次提交之后，执行 &amp;lt;code&amp;gt;git log&amp;lt;/code&amp;gt;终端会输出&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit 3a5b0d12f471418b13f2baf5e9e4c112a5e804a8 (HEAD -&amp;gt; master)&lt;br /&gt;
&lt;br /&gt;
Author: luluzzy &amp;lt;1054438588@qq.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Date:   Thu Feb 15 21:28:47 2024 +0800&lt;br /&gt;
&lt;br /&gt;
    initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这些输出分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit sha1 hash:   针对你这个提交的 commit id&lt;br /&gt;
Author: commit      作者名称   &amp;lt;you@example.com&amp;gt;&lt;br /&gt;
Date: commit        日期&lt;br /&gt;
commit:             名称&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
关于sha1_hash的介绍请看这里&amp;lt;ref&amp;gt;生成这个hash值，它是对那个commit是Git仓库中内容和头信息Header的一个校验和checksum。Linux kernel开创者和Git的开发者——Linus说，Git使用了sha1并非是为了安全性，而是为了数据的完整性；它可以保证，在很多年后，你重新checkout某个commit时，一定是它多年前的当时的状态，完全一摸一样，完全值得信任。在Git中，根据commit的sha1值40个十六进制数字进行了简单的划分目录，以前2位数字作为目录名，其下面是剩余38位数字组成的一个文件名&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当有多次提交之后，如果我们想要翻之前的提交历史，难免会因为终端输出的内容过多而难以查看翻阅&lt;br /&gt;
&lt;br /&gt;
此时我们可以使用&amp;lt;code&amp;gt;--online&amp;lt;/code&amp;gt;参数来简化输出，此时仅会输出: sha1哈希值 + commit的名称&lt;br /&gt;
&lt;br /&gt;
例如&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
347595d (HEAD -&amp;gt; master) modify makefile&lt;br /&gt;
&lt;br /&gt;
3a5b0d1 initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git cherry-pick ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
cherry-pick (遴选) 和它的名称一样，挑选一个我们需要的 commit 进行操作。它可以用于将在其他分支上的 commit 修改，移植到当前的分支。&lt;br /&gt;
&lt;br /&gt;
如果我们想在我们正在开发的版本上，添加一个其他版本中的功能代码。就可以使用 cherry-pick ，将这个功能相关的 commit 提取出来，合入该版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick &amp;lt;commit-id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
当我们执行完 &amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;操作之后，会自动生成一个&amp;lt;code&amp;gt;commit&amp;lt;/code&amp;gt;以及对应新的&amp;lt;code&amp;gt;commit-id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在顺利的情况下我们可以直接通过，但如果遇到代码等因为变量名，写法等不同的情况，&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;大概率会报错，此时我们需要进行报错处理。&lt;br /&gt;
&lt;br /&gt;
第一种方案是手动修改&lt;br /&gt;
&lt;br /&gt;
我们可以先使用&amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt;检查当前遴选时冲突的文件&lt;br /&gt;
&lt;br /&gt;
然后 &amp;lt;code&amp;gt;git checkout --ours filename&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
然后按照提交的修改内容进行手动修改&lt;br /&gt;
&lt;br /&gt;
随后使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令将文件重新加入暂存区&lt;br /&gt;
&lt;br /&gt;
再使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --continue&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
命令让 cherrypick 操作继续执行。&lt;br /&gt;
&lt;br /&gt;
第二种方案是直接退出&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;进程，一般适用于冲突文件实在太多了难以按照方案一处理的情况。&lt;br /&gt;
&lt;br /&gt;
需要注意的是，如果您当前正在遴选的提交在该分支已经存在也会冲突，在这种情况下，您需要解决冲突并手动解决问题。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --abort&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git fetch ====&lt;br /&gt;
git fetch 命令用于从远程获取仓库。&lt;br /&gt;
&lt;br /&gt;
==== git merge ====&lt;br /&gt;
&amp;lt;code&amp;gt;git merge&amp;lt;/code&amp;gt;是用来把分叉的提交历史放回到一起(合并)的方式。&lt;br /&gt;
&lt;br /&gt;
git merge命令用来将你之前使用git branch命令创建的分支以及在此分支上独立开发的内容整合为一个分支。&lt;br /&gt;
&lt;br /&gt;
本&lt;br /&gt;
&lt;br /&gt;
==== git pull ====&lt;br /&gt;
用于从远程获取代码并合并本地的版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull&amp;lt;/code&amp;gt;其实就是&amp;lt;code&amp;gt;git fetch&amp;lt;/code&amp;gt;和&amp;lt;code&amp;gt;git merge FETCH_HEAD&amp;lt;/code&amp;gt; 的简写。&lt;br /&gt;
&lt;br /&gt;
格式如下：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull &amp;lt;remote-host-name&amp;gt; &amp;lt;remote-branch-name&amp;gt;:&amp;lt;local-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git rebase ====&lt;br /&gt;
用于需要修改历史上某一项commit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git rebase -i HEAD~&amp;lt;commit number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
commit number就是从头部往前数的commit数量。执行后会弹出你在git config内配置的编辑器，若未配置则是默认，vim居多。然后就可以看见一堆commit前面有pick字样。可以将pick替换为你想要的操作。&lt;br /&gt;
有以下操作：&lt;br /&gt;
&lt;br /&gt;
1.edit，顾名思义编辑此commit，替换完保存后请修改内容，使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;或vscode，github desktop将修改文件添加到暂存区，之后命令行执行&amp;lt;code&amp;gt;git commit --amend&amp;lt;/code&amp;gt;这样commit就修改成了&lt;br /&gt;
&lt;br /&gt;
2.squash，合并几个提交，确认一个父提交，将要合并的commit，从下向上替换字符串，会从下向上合并(方位指的是&amp;lt;code&amp;gt;git rebase&amp;lt;/code&amp;gt;后弹出的编辑器)&lt;br /&gt;
&lt;br /&gt;
3.drop，需要移除的commit&lt;br /&gt;
&lt;br /&gt;
==== git subtree ====&lt;br /&gt;
子树，在Android开发中多用于Kernel侧更改，如跟踪audio模块等&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree add --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果需要更新远程库时&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree pull --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git submodule ====&lt;br /&gt;
&lt;br /&gt;
===== 子模块功能的概述 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在自己的Github仓库里加入别人的github仓库，作为自己仓库的子仓库(即submodule)。&lt;br /&gt;
&lt;br /&gt;
为什么我们会需要使用子模块？当我们维护一个项目时有可能遇到以下情况，例如维护某款机型的KernelSU内核，我们需要将KernelSU导入至我们的内核源码中，如果我们直接clone进去容易带来一个问题，如果KernelSU更新了怎么办？此时我们便可以使用子模块来解决这个问题&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在git仓库里存放别人仓库的url，作为自己的子模块，其核心内容是在Git仓库里面加入一个&amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;文件，里面会记录各个submodule的名字，路径，以及对应链接。&lt;br /&gt;
&lt;br /&gt;
===== 加入子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule add &amp;lt;url&amp;gt; &amp;lt;path&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
此时 &amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;内会自动生成以下内容&lt;br /&gt;
&lt;br /&gt;
[submodule &amp;quot;xxx&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
path = xxx&lt;br /&gt;
&lt;br /&gt;
url = xxx&lt;br /&gt;
&lt;br /&gt;
===== 初始化子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule init&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== 更新子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule update&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Git进阶 ===&lt;br /&gt;
&lt;br /&gt;
==== GPG key ====&lt;br /&gt;
&lt;br /&gt;
===== 简介 =====&lt;br /&gt;
平时在Github上摸鱼的时候，是不是经常能看见如下图所示，有一个绿色的&amp;quot;Verified&amp;quot;字样，看着很酷，实际上这是为了确保commit为开发者本人所写的进行的GPG签名。&lt;br /&gt;
[[文件:Github GPG sign.png|居中]]&lt;br /&gt;
因为Git的默认机制，任何人都可以通过你的邮箱和用户名创建虚假的commit，甚至你名气很大的话可以“栽赃陷害”你。如果你是某高校计算机专业的同学亦或是对计算机抱有很大的兴趣，乐意为开源社区提供“资源”，那么我建议你设置GPG sign。未来是不可预知的，人人都可能成为巨佬。&lt;br /&gt;
&lt;br /&gt;
===== 使用 =====&lt;br /&gt;
因为我只在Mac环境下配置过GPG，Windows只是打游戏用，所以用的少，Linux/类Unix可以参考一下。其它系统等待他人补充......&lt;br /&gt;
&lt;br /&gt;
====== Mac ======&lt;br /&gt;
Mac默认是不带GPG的，需要通过第三方软件包安装器Homebrew进行安装，首先先安装Homebrew，如已安装可以跳过。&lt;br /&gt;
&lt;br /&gt;
编辑器限制原因不能使用默认标题进行分步了，故使用1、2、3等小数字代替。&lt;br /&gt;
&lt;br /&gt;
安装Homebrew&lt;br /&gt;
&lt;br /&gt;
在安装之前需要从系统信息中查看芯片为Intel/M系列&lt;br /&gt;
&lt;br /&gt;
Intel使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/bin/zsh -c &amp;quot;$(curl -fsSL &amp;lt;nowiki&amp;gt;https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh&amp;lt;/nowiki&amp;gt;)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Intel按照脚本提示，选源，输密码，回车一路绿灯就好了，如果这都不会......可能你不是很适合开发，因为该脚本是国内开发者编写的，中文和一键化安装都集齐了。&lt;br /&gt;
&lt;br /&gt;
M系列使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/bin/zsh -c &amp;quot;$(curl -fsSL https://gitee.com/huwei1024/HomebrewCN/raw/master/Homebrew.sh)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
并且因为M系列系统结构发生改变，包安装位置不在是以前的/usr/local/，而是在/opt/homebrew，所以要将配置文件里的环境变量改过来。&lt;br /&gt;
&lt;br /&gt;
1.首先进入根目录&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cd ~&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.创建.zshrc文件&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;touch .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3.打开文件进行编辑&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;open -e .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4.如果有旧的环境就修改，没有就新增&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;export PATH=&amp;quot;/opt/homebrew/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
export PATH=&amp;quot;/opt/homebrew/sbin:$PATH&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5.保存&lt;br /&gt;
&lt;br /&gt;
使用command + s&lt;br /&gt;
&lt;br /&gt;
6.生效环境变量&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;source .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
7、测试&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;brew -v&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
若终端顺利打印出brew的版本，那么就安装成功了！&lt;br /&gt;
&lt;br /&gt;
注：本人没有使用过M系列设备，该教程在知乎上找到的&lt;br /&gt;
&lt;br /&gt;
使用Homebrew安装GPG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;brew install gnupg pinentry-mac&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.34.48.png|居中]]&lt;br /&gt;
&lt;br /&gt;
为GPG添加环境变量，否则在签名的时候会发生报错（使用bash请自行替换配置文件）&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;echo &amp;quot;export GPG_TTY=$(tty)&amp;quot; &amp;gt;&amp;gt; ~/.zshrc&lt;br /&gt;
source ~/.zshrc&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
生成一个GPG keys&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gpg --full-generate-key&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.45.51.png|居中]]&lt;br /&gt;
&lt;br /&gt;
默认使用的是ECC，我使用的是RSA，按照自己喜好，或从百度搜索非对称和对称加密算法之间的区别，这里只做使用方法的介绍，不做赘述。&lt;br /&gt;
&lt;br /&gt;
然后添写密钥长度和使用有效期，这里建议选择长期，并做备份，一辈子用一个就够了。&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.46.06.png|居中]]&lt;br /&gt;
[[文件:截屏2024-02-17 17.46.35.png|居中]]&lt;br /&gt;
&lt;br /&gt;
个人信息按照Github信息填写，真实姓名对应Username。填写完毕按回车输入O即可生成密钥。不出意外的话会弹出Gui窗口让你设置密钥密码，强烈建设设置一个较为复杂的密码，并牢记，当然也可以不设置。&lt;br /&gt;
&lt;br /&gt;
使用GPG对Git的commit和tag进行签名&lt;br /&gt;
&lt;br /&gt;
先为Git定义GPG二进制所在地&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global gpg.program $(which gpg)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
查看GPG keys ID&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gpg --list-secret-keys --keyid-format=long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如图所示RSA/后面紧跟的一串就是GPG keys ID&lt;br /&gt;
[[文件:截屏2024-02-17 17.57.01.png|居中]]&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.signingkey &amp;quot;GPG key ID&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
为Git设置全局commit和tag签名&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global commit.gpgsign true&lt;br /&gt;
&lt;br /&gt;
git config --global tag.gpgSign true&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
参见本文“在Github配置GPG keys”部分开启下一步操作&lt;br /&gt;
&lt;br /&gt;
接下来就可以愉快的编写程序了~&lt;br /&gt;
&lt;br /&gt;
======在Github配置GPG keys======&lt;br /&gt;
在终端输入&lt;br /&gt;
&lt;br /&gt;
gpg --armor --export &amp;quot;GPG key ID&amp;quot;&lt;br /&gt;
&lt;br /&gt;
将输出的内容从-----BEGIN PGP PUBLIC KEY BLOCK-----到-----END PGP PUBLIC KEY BLOCK-----，包含它们都复制下来。&lt;br /&gt;
&lt;br /&gt;
打开Github网页，并登录自己的账号。按照下述操作依次执行。&lt;br /&gt;
头像--&amp;gt;Setting--&amp;gt;SSH and GPG keys--&amp;gt;New GPG key，标题自己怎么舒服怎么来，将第一步复制的内容全部粘贴然后保存起来，这样Github就能识别到你commit中包含的GPG sign的信息了，你就可以在commit history或release等页面看到绿色的签名后的标志了。&lt;br /&gt;
&lt;br /&gt;
==== 参考资料： ====&lt;br /&gt;
[1] 百度百科 -- Git：&amp;lt;nowiki&amp;gt;https://baike.baidu.com/item/GIT/12647237?fr=ge_ala&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[2] 菜鸟教程 -- Git基本操作：&amp;lt;nowiki&amp;gt;https://www.runoob.com/git/git-basic-operations.html&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[3] CSDN -- git merge 使用简介: &amp;lt;nowiki&amp;gt;https://blog.csdn.net/All_In_gzx_cc/article/details/125482617&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[3] 知乎 -- MAC 安装 homebrew 国内镜像: &amp;lt;nowiki&amp;gt;https://zhuanlan.zhihu.com/p/547898033&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=519</id>
		<title>Git使用教程</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=519"/>
		<updated>2024-02-17T10:25:01Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​补充GPG key&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Git的由来： ===&lt;br /&gt;
Git是一个开源的分布式版本控制系统，可以有效、高速地处理从很小到非常大的项目版本管理，也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper。&lt;br /&gt;
&lt;br /&gt;
=== 常见的代码托管平台： ===&lt;br /&gt;
[https://github.com Github]&lt;br /&gt;
&lt;br /&gt;
[https://gitlab.com Gitlab]&lt;br /&gt;
&lt;br /&gt;
[https://gitee.com Gitee]&lt;br /&gt;
&lt;br /&gt;
=== Git 常见命令: ===&lt;br /&gt;
&lt;br /&gt;
==== git init ====&lt;br /&gt;
在本地目录中初始化一个新的Git仓库&lt;br /&gt;
&lt;br /&gt;
==== git config ====&lt;br /&gt;
用于配置用户的信息以及其他设置,在使用git之前您必须完成以下步骤。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.name &amp;quot;your username&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.email &amp;quot;your email&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
更改默认编辑器&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global core.editor nano&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git clone ====&lt;br /&gt;
用于将远程仓库的代码克隆到本地，以下是命令中各个参数的含义：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;url&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆某个地址(url)的仓库，远程仓库的地址可以是本地的目录，也可以是例如github,giteee,gitlab一类的代码托管平台&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;--depth=&amp;lt;number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆仓库并且保留number条提交历史，number在此处即表达我们克隆的深度。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;-b &amp;lt;branch&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆指定分支下的仓库内容&lt;br /&gt;
&lt;br /&gt;
例如我们要克隆&amp;lt;code&amp;gt;LineageOS&amp;lt;/code&amp;gt;的内核源码，指定&amp;lt;code&amp;gt;lineage-21&amp;lt;/code&amp;gt;分支，且仅保留最近一个提交，则需要输入:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git clone -b lineage-21 &amp;lt;nowiki&amp;gt;https://github.com/LineageOS/android_kernel_xiaomi_sdm845&amp;lt;/nowiki&amp;gt; --depth=1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git add ====&lt;br /&gt;
添加某个文件，或者目录到暂存区，用于告诉git你需要将哪些文件的更改包含在下一次的提交(commit)之中添加一个或者多个文件到暂存区之中&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [file1] [file2]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加指定目录(文件)到暂存区，包括子目录：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [dir]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加当前目录下的所有文件到暂存区：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add .&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git status ====&lt;br /&gt;
查看当前仓库的状态，此时git会在你的终端输出以下内容&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;em style=&amp;quot;color: gray;&amp;quot;&amp;gt;此处演示为英文，如果您的git终端输出为中文也是同理的&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
On branch master&lt;br /&gt;
No commits yet&lt;br /&gt;
Changes to be committed:  &lt;br /&gt;
&lt;br /&gt;
(use “git rm --cached &amp;lt;file&amp;gt;...” to unstage)       &lt;br /&gt;
new file:   makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
输出内容分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
您目前所在的分支&lt;br /&gt;
目前的提交&lt;br /&gt;
需要更改的内容&lt;br /&gt;
新增的文件&lt;br /&gt;
修改的文件&lt;br /&gt;
删除的文件&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git commit ====&lt;br /&gt;
用于将暂存区我们保存的更改文件添加到本地仓库，并且会生成一条提交（commit）&lt;br /&gt;
&lt;br /&gt;
提交暂存区的更改到本地仓库&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -m &amp;quot;message&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[注] message 可以是你的备注信息&lt;br /&gt;
&lt;br /&gt;
提交暂存区中的指定文件到本地仓库&lt;br /&gt;
&lt;br /&gt;
如果你没有使用上述&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令暂存你的修改文件，可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -a&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
进行直接提交&lt;br /&gt;
&lt;br /&gt;
==== git checkout ====&lt;br /&gt;
&lt;br /&gt;
* 用于分支切换&lt;br /&gt;
&lt;br /&gt;
切换分支：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如在您的仓库中有这几个分支：&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-&amp;gt; master (Default)&lt;br /&gt;
   backup&lt;br /&gt;
   test&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
您当前处于 master 分支，如果想要切换到test分支，我们可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 用于检出文件&lt;br /&gt;
将指定的文件恢复到最新的提交状态，撤销你对其的更改&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout -- &amp;lt;file&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git push ====&lt;br /&gt;
用于将本地的分支版本上传到远程仓库并进行合并&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push &amp;lt;remote-host-name&amp;gt; &amp;lt;local-branch-name&amp;gt;:&amp;lt;remote-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
remote-host-name:远程主机名&lt;br /&gt;
&lt;br /&gt;
local-branch-name:本地分支名&lt;br /&gt;
&lt;br /&gt;
例如，当你的远程主机名为origin ，本地分支名为master，远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master:master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如，当你的rhost名为origin 本地分支名为master远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
本地和远程分支名相同，上述命令可以简写为：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当你的远程版本与本地版本有差异，无法直接push时，你可以使用--force 参数来进行强制推送&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push --force origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
--force 此处可以直接简单化为 -f &lt;br /&gt;
&lt;br /&gt;
如果你想要删除主机内的某个分支，你可以使用--delete参数&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin --delete &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git diff ====&lt;br /&gt;
用于比较当前工作区与上一个版本之间的差异&lt;br /&gt;
&lt;br /&gt;
例如：（此处仅做不恰当举例，Makefile不是这样乱写的）&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
diff --git a/makefile b/makefile&lt;br /&gt;
&lt;br /&gt;
index fbb8c85..d65c7eb 100644&lt;br /&gt;
&lt;br /&gt;
--- a/makefile&lt;br /&gt;
&lt;br /&gt;
+++ b/makefile&lt;br /&gt;
&lt;br /&gt;
@@ -1 +1,2 @@&lt;br /&gt;
&lt;br /&gt;
114514&lt;br /&gt;
&lt;br /&gt;
+1919180&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git log ====&lt;br /&gt;
用于查看提交的历史&lt;br /&gt;
&lt;br /&gt;
例如当你进行一次提交之后，执行 &amp;lt;code&amp;gt;git log&amp;lt;/code&amp;gt;终端会输出&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit 3a5b0d12f471418b13f2baf5e9e4c112a5e804a8 (HEAD -&amp;gt; master)&lt;br /&gt;
&lt;br /&gt;
Author: luluzzy &amp;lt;1054438588@qq.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Date:   Thu Feb 15 21:28:47 2024 +0800&lt;br /&gt;
&lt;br /&gt;
    initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这些输出分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit sha1 hash:   针对你这个提交的 commit id&lt;br /&gt;
Author: commit      作者名称   &amp;lt;you@example.com&amp;gt;&lt;br /&gt;
Date: commit        日期&lt;br /&gt;
commit:             名称&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
关于sha1_hash的介绍请看这里&amp;lt;ref&amp;gt;生成这个hash值，它是对那个commit是Git仓库中内容和头信息Header的一个校验和checksum。Linux kernel开创者和Git的开发者——Linus说，Git使用了sha1并非是为了安全性，而是为了数据的完整性；它可以保证，在很多年后，你重新checkout某个commit时，一定是它多年前的当时的状态，完全一摸一样，完全值得信任。在Git中，根据commit的sha1值40个十六进制数字进行了简单的划分目录，以前2位数字作为目录名，其下面是剩余38位数字组成的一个文件名&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当有多次提交之后，如果我们想要翻之前的提交历史，难免会因为终端输出的内容过多而难以查看翻阅&lt;br /&gt;
&lt;br /&gt;
此时我们可以使用&amp;lt;code&amp;gt;--online&amp;lt;/code&amp;gt;参数来简化输出，此时仅会输出: sha1哈希值 + commit的名称&lt;br /&gt;
&lt;br /&gt;
例如&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
347595d (HEAD -&amp;gt; master) modify makefile&lt;br /&gt;
&lt;br /&gt;
3a5b0d1 initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git cherry-pick ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
cherry-pick (遴选) 和它的名称一样，挑选一个我们需要的 commit 进行操作。它可以用于将在其他分支上的 commit 修改，移植到当前的分支。&lt;br /&gt;
&lt;br /&gt;
如果我们想在我们正在开发的版本上，添加一个其他版本中的功能代码。就可以使用 cherry-pick ，将这个功能相关的 commit 提取出来，合入该版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick &amp;lt;commit-id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
当我们执行完 &amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;操作之后，会自动生成一个&amp;lt;code&amp;gt;commit&amp;lt;/code&amp;gt;以及对应新的&amp;lt;code&amp;gt;commit-id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在顺利的情况下我们可以直接通过，但如果遇到代码等因为变量名，写法等不同的情况，&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;大概率会报错，此时我们需要进行报错处理。&lt;br /&gt;
&lt;br /&gt;
第一种方案是手动修改&lt;br /&gt;
&lt;br /&gt;
我们可以先使用&amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt;检查当前遴选时冲突的文件&lt;br /&gt;
&lt;br /&gt;
然后 &amp;lt;code&amp;gt;git checkout --ours filename&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
然后按照提交的修改内容进行手动修改&lt;br /&gt;
&lt;br /&gt;
随后使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令将文件重新加入暂存区&lt;br /&gt;
&lt;br /&gt;
再使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --continue&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
命令让 cherrypick 操作继续执行。&lt;br /&gt;
&lt;br /&gt;
第二种方案是直接退出&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;进程，一般适用于冲突文件实在太多了难以按照方案一处理的情况。&lt;br /&gt;
&lt;br /&gt;
需要注意的是，如果您当前正在遴选的提交在该分支已经存在也会冲突，在这种情况下，您需要解决冲突并手动解决问题。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --abort&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git fetch ====&lt;br /&gt;
git fetch 命令用于从远程获取仓库。&lt;br /&gt;
&lt;br /&gt;
==== git merge ====&lt;br /&gt;
&amp;lt;code&amp;gt;git merge&amp;lt;/code&amp;gt;是用来把分叉的提交历史放回到一起(合并)的方式。&lt;br /&gt;
&lt;br /&gt;
git merge命令用来将你之前使用git branch命令创建的分支以及在此分支上独立开发的内容整合为一个分支。&lt;br /&gt;
&lt;br /&gt;
本&lt;br /&gt;
&lt;br /&gt;
==== git pull ====&lt;br /&gt;
用于从远程获取代码并合并本地的版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull&amp;lt;/code&amp;gt;其实就是&amp;lt;code&amp;gt;git fetch&amp;lt;/code&amp;gt;和&amp;lt;code&amp;gt;git merge FETCH_HEAD&amp;lt;/code&amp;gt; 的简写。&lt;br /&gt;
&lt;br /&gt;
格式如下：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull &amp;lt;remote-host-name&amp;gt; &amp;lt;remote-branch-name&amp;gt;:&amp;lt;local-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git rebase ====&lt;br /&gt;
用于需要修改历史上某一项commit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git rebase -i HEAD~&amp;lt;commit number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
commit number就是从头部往前数的commit数量。执行后会弹出你在git config内配置的编辑器，若未配置则是默认，vim居多。然后就可以看见一堆commit前面有pick字样。可以将pick替换为你想要的操作。&lt;br /&gt;
有以下操作：&lt;br /&gt;
&lt;br /&gt;
1.edit，顾名思义编辑此commit，替换完保存后请修改内容，使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;或vscode，github desktop将修改文件添加到暂存区，之后命令行执行&amp;lt;code&amp;gt;git commit --amend&amp;lt;/code&amp;gt;这样commit就修改成了&lt;br /&gt;
&lt;br /&gt;
2.squash，合并几个提交，确认一个父提交，将要合并的commit，从下向上替换字符串，会从下向上合并(方位指的是&amp;lt;code&amp;gt;git rebase&amp;lt;/code&amp;gt;后弹出的编辑器)&lt;br /&gt;
&lt;br /&gt;
3.drop，需要移除的commit&lt;br /&gt;
&lt;br /&gt;
==== git subtree ====&lt;br /&gt;
子树，在Android开发中多用于Kernel侧更改，如跟踪audio模块等&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree add --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果需要更新远程库时&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree pull --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git submodule ====&lt;br /&gt;
&lt;br /&gt;
===== 子模块功能的概述 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在自己的Github仓库里加入别人的github仓库，作为自己仓库的子仓库(即submodule)。&lt;br /&gt;
&lt;br /&gt;
为什么我们会需要使用子模块？当我们维护一个项目时有可能遇到以下情况，例如维护某款机型的KernelSU内核，我们需要将KernelSU导入至我们的内核源码中，如果我们直接clone进去容易带来一个问题，如果KernelSU更新了怎么办？此时我们便可以使用子模块来解决这个问题&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在git仓库里存放别人仓库的url，作为自己的子模块，其核心内容是在Git仓库里面加入一个&amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;文件，里面会记录各个submodule的名字，路径，以及对应链接。&lt;br /&gt;
&lt;br /&gt;
===== 加入子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule add &amp;lt;url&amp;gt; &amp;lt;path&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
此时 &amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;内会自动生成以下内容&lt;br /&gt;
&lt;br /&gt;
[submodule &amp;quot;xxx&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
path = xxx&lt;br /&gt;
&lt;br /&gt;
url = xxx&lt;br /&gt;
&lt;br /&gt;
===== 初始化子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule init&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== 更新子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule update&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Git进阶 ===&lt;br /&gt;
&lt;br /&gt;
==== GPG key ====&lt;br /&gt;
&lt;br /&gt;
===== 简介 =====&lt;br /&gt;
平时在Github上摸鱼的时候，是不是经常能看见如下图所示，有一个绿色的&amp;quot;Verified&amp;quot;字样，看着很酷，实际上这是为了确保commit为开发者本人所写的进行的GPG签名。&lt;br /&gt;
[[文件:Github GPG sign.png|居中]]&lt;br /&gt;
因为Git的默认机制，任何人都可以通过你的邮箱和用户名创建虚假的commit，甚至你名气很大的话可以“栽赃陷害”你。如果你是某高校计算机专业的同学亦或是对计算机抱有很大的兴趣，乐意为开源社区提供“资源”，那么我建议你设置GPG sign。未来是不可预知的，人人都可能成为巨佬。&lt;br /&gt;
&lt;br /&gt;
===== 使用 =====&lt;br /&gt;
因为我只在Mac环境下配置过GPG，Windows只是打游戏用，所以用的少，Linux/类Unix可以参考一下。其它系统等待他人补充......&lt;br /&gt;
&lt;br /&gt;
====== Mac ======&lt;br /&gt;
Mac默认是不带GPG的，需要通过第三方软件包安装器Homebrew进行安装，首先先安装Homebrew，如已安装可以跳过。&lt;br /&gt;
&lt;br /&gt;
编辑器限制原因不能使用默认标题进行分步了，故使用1、2、3等小数字代替。&lt;br /&gt;
&lt;br /&gt;
安装Homebrew&lt;br /&gt;
&lt;br /&gt;
在安装之前需要从系统信息中查看芯片为Intel/M系列&lt;br /&gt;
&lt;br /&gt;
Intel使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/bin/zsh -c &amp;quot;$(curl -fsSL &amp;lt;nowiki&amp;gt;https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh&amp;lt;/nowiki&amp;gt;)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Intel按照脚本提示，选源，输密码，回车一路绿灯就好了，如果这都不会......可能你不是很适合开发，因为该脚本是国内开发者编写的，中文和一键化安装都集齐了。&lt;br /&gt;
&lt;br /&gt;
M系列使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/bin/zsh -c &amp;quot;$(curl -fsSL https://gitee.com/huwei1024/HomebrewCN/raw/master/Homebrew.sh)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
并且因为M系列系统结构发生改变，包安装位置不在是以前的/usr/local/，而是在/opt/homebrew，所以要将配置文件里的环境变量改过来。&lt;br /&gt;
&lt;br /&gt;
1.首先进入根目录&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cd ~&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.创建.zshrc文件&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;touch .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3.打开文件进行编辑&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;open -e .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4.如果有旧的环境就修改，没有就新增&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;export PATH=&amp;quot;/opt/homebrew/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
export PATH=&amp;quot;/opt/homebrew/sbin:$PATH&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5.保存&lt;br /&gt;
&lt;br /&gt;
使用command + s&lt;br /&gt;
&lt;br /&gt;
6.生效环境变量&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;source .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
7、测试&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;brew -v&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
若终端顺利打印出brew的版本，那么就安装成功了！&lt;br /&gt;
&lt;br /&gt;
注：本人没有使用过M系列设备，该教程在知乎上找到的&lt;br /&gt;
&lt;br /&gt;
使用Homebrew安装GPG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;brew install gnupg pinentry-mac&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.34.48.png|居中]]&lt;br /&gt;
&lt;br /&gt;
为GPG添加环境变量，否则在签名的时候会发生报错（使用bash请自行替换配置文件）&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;echo &amp;quot;export GPG_TTY=$(tty)&amp;quot; &amp;gt;&amp;gt; ~/.zshrc&lt;br /&gt;
source ~/.zshrc&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
生成一个GPG keys&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gpg --full-generate-key&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.45.51.png|居中]]&lt;br /&gt;
&lt;br /&gt;
默认使用的是ECC，我使用的是RSA，按照自己喜好，或从百度搜索非对称和对称加密算法之间的区别，这里只做使用方法的介绍，不做赘述。&lt;br /&gt;
&lt;br /&gt;
然后添写密钥长度和使用有效期，这里建议选择长期，并做备份，一辈子用一个就够了。&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.46.06.png|居中]]&lt;br /&gt;
[[文件:截屏2024-02-17 17.46.35.png|居中]]&lt;br /&gt;
&lt;br /&gt;
个人信息按照Github信息填写，真实姓名对应Username。填写完毕按回车输入O即可生成密钥。不出意外的话会弹出Gui窗口让你设置密钥密码，强烈建设设置一个较为复杂的密码，并牢记，当然也可以不设置。&lt;br /&gt;
&lt;br /&gt;
使用GPG对Git的commit和tag进行签名&lt;br /&gt;
&lt;br /&gt;
先为Git定义GPG二进制所在地&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global gpg.program $(which gpg)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
查看GPG keys ID&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gpg --list-secret-keys --keyid-format=long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如图所示RSA/后面紧跟的一串就是GPG keys ID&lt;br /&gt;
[[文件:截屏2024-02-17 17.57.01.png|居中]]&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.signingkey &amp;quot;GPG key ID&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
为Git设置全局commit和tag签名&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global commit.gpgsign true&lt;br /&gt;
&lt;br /&gt;
git config --global tag.gpgSign true&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
参见&lt;br /&gt;
&lt;br /&gt;
接下来就可以愉快的编写程序了~&lt;br /&gt;
&lt;br /&gt;
======在Github配置GPG keys======&lt;br /&gt;
在终端输入&lt;br /&gt;
&lt;br /&gt;
gpg --armor --export &amp;quot;GPG key ID&amp;quot;&lt;br /&gt;
&lt;br /&gt;
将输出的内容从-----BEGIN PGP PUBLIC KEY BLOCK-----到-----END PGP PUBLIC KEY BLOCK-----，包含它们都复制下来。&lt;br /&gt;
&lt;br /&gt;
打开Github网页，并登录自己的账号。按照下述操作依次执行。&lt;br /&gt;
头像--&amp;gt;Setting--&amp;gt;SSH and GPG keys--&amp;gt;New GPG key，标题自己怎么舒服怎么来，将第一步复制的内容全部粘贴然后保存起来，这样Github就能识别到你commit中包含的GPG sign的信息了，你就可以在commit history或release等页面看到绿色的签名后的标志了。&lt;br /&gt;
&lt;br /&gt;
==== 参考资料： ====&lt;br /&gt;
[1] 百度百科 -- Git：&amp;lt;nowiki&amp;gt;https://baike.baidu.com/item/GIT/12647237?fr=ge_ala&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[2] 菜鸟教程 -- Git基本操作：&amp;lt;nowiki&amp;gt;https://www.runoob.com/git/git-basic-operations.html&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[3] CSDN -- git merge 使用简介: &amp;lt;nowiki&amp;gt;https://blog.csdn.net/All_In_gzx_cc/article/details/125482617&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[3] 知乎 -- MAC 安装 homebrew 国内镜像: &amp;lt;nowiki&amp;gt;https://zhuanlan.zhihu.com/p/547898033&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=518</id>
		<title>Git使用教程</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=518"/>
		<updated>2024-02-17T10:00:14Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​添加GPG key&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Git的由来： ===&lt;br /&gt;
Git是一个开源的分布式版本控制系统，可以有效、高速地处理从很小到非常大的项目版本管理，也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper。&lt;br /&gt;
&lt;br /&gt;
=== 常见的代码托管平台： ===&lt;br /&gt;
[https://github.com Github]&lt;br /&gt;
&lt;br /&gt;
[https://gitlab.com Gitlab]&lt;br /&gt;
&lt;br /&gt;
[https://gitee.com Gitee]&lt;br /&gt;
&lt;br /&gt;
=== Git 常见命令: ===&lt;br /&gt;
&lt;br /&gt;
==== git init ====&lt;br /&gt;
在本地目录中初始化一个新的Git仓库&lt;br /&gt;
&lt;br /&gt;
==== git config ====&lt;br /&gt;
用于配置用户的信息以及其他设置,在使用git之前您必须完成以下步骤。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.name &amp;quot;your username&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.email &amp;quot;your email&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
更改默认编辑器&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global core.editor nano&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git clone ====&lt;br /&gt;
用于将远程仓库的代码克隆到本地，以下是命令中各个参数的含义：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;url&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆某个地址(url)的仓库，远程仓库的地址可以是本地的目录，也可以是例如github,giteee,gitlab一类的代码托管平台&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;--depth=&amp;lt;number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆仓库并且保留number条提交历史，number在此处即表达我们克隆的深度。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;-b &amp;lt;branch&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆指定分支下的仓库内容&lt;br /&gt;
&lt;br /&gt;
例如我们要克隆&amp;lt;code&amp;gt;LineageOS&amp;lt;/code&amp;gt;的内核源码，指定&amp;lt;code&amp;gt;lineage-21&amp;lt;/code&amp;gt;分支，且仅保留最近一个提交，则需要输入:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git clone -b lineage-21 &amp;lt;nowiki&amp;gt;https://github.com/LineageOS/android_kernel_xiaomi_sdm845&amp;lt;/nowiki&amp;gt; --depth=1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git add ====&lt;br /&gt;
添加某个文件，或者目录到暂存区，用于告诉git你需要将哪些文件的更改包含在下一次的提交(commit)之中添加一个或者多个文件到暂存区之中&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [file1] [file2]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加指定目录(文件)到暂存区，包括子目录：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [dir]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加当前目录下的所有文件到暂存区：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add .&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git status ====&lt;br /&gt;
查看当前仓库的状态，此时git会在你的终端输出以下内容&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;em style=&amp;quot;color: gray;&amp;quot;&amp;gt;此处演示为英文，如果您的git终端输出为中文也是同理的&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
On branch master&lt;br /&gt;
No commits yet&lt;br /&gt;
Changes to be committed:  &lt;br /&gt;
&lt;br /&gt;
(use “git rm --cached &amp;lt;file&amp;gt;...” to unstage)       &lt;br /&gt;
new file:   makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
输出内容分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
您目前所在的分支&lt;br /&gt;
目前的提交&lt;br /&gt;
需要更改的内容&lt;br /&gt;
新增的文件&lt;br /&gt;
修改的文件&lt;br /&gt;
删除的文件&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git commit ====&lt;br /&gt;
用于将暂存区我们保存的更改文件添加到本地仓库，并且会生成一条提交（commit）&lt;br /&gt;
&lt;br /&gt;
提交暂存区的更改到本地仓库&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -m &amp;quot;message&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[注] message 可以是你的备注信息&lt;br /&gt;
&lt;br /&gt;
提交暂存区中的指定文件到本地仓库&lt;br /&gt;
&lt;br /&gt;
如果你没有使用上述&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令暂存你的修改文件，可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -a&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
进行直接提交&lt;br /&gt;
&lt;br /&gt;
==== git checkout ====&lt;br /&gt;
&lt;br /&gt;
* 用于分支切换&lt;br /&gt;
&lt;br /&gt;
切换分支：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如在您的仓库中有这几个分支：&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-&amp;gt; master (Default)&lt;br /&gt;
   backup&lt;br /&gt;
   test&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
您当前处于 master 分支，如果想要切换到test分支，我们可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 用于检出文件&lt;br /&gt;
将指定的文件恢复到最新的提交状态，撤销你对其的更改&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout -- &amp;lt;file&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git push ====&lt;br /&gt;
用于将本地的分支版本上传到远程仓库并进行合并&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push &amp;lt;remote-host-name&amp;gt; &amp;lt;local-branch-name&amp;gt;:&amp;lt;remote-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
remote-host-name:远程主机名&lt;br /&gt;
&lt;br /&gt;
local-branch-name:本地分支名&lt;br /&gt;
&lt;br /&gt;
例如，当你的远程主机名为origin ，本地分支名为master，远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master:master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如，当你的rhost名为origin 本地分支名为master远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
本地和远程分支名相同，上述命令可以简写为：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当你的远程版本与本地版本有差异，无法直接push时，你可以使用--force 参数来进行强制推送&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push --force origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
--force 此处可以直接简单化为 -f &lt;br /&gt;
&lt;br /&gt;
如果你想要删除主机内的某个分支，你可以使用--delete参数&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin --delete &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git diff ====&lt;br /&gt;
用于比较当前工作区与上一个版本之间的差异&lt;br /&gt;
&lt;br /&gt;
例如：（此处仅做不恰当举例，Makefile不是这样乱写的）&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
diff --git a/makefile b/makefile&lt;br /&gt;
&lt;br /&gt;
index fbb8c85..d65c7eb 100644&lt;br /&gt;
&lt;br /&gt;
--- a/makefile&lt;br /&gt;
&lt;br /&gt;
+++ b/makefile&lt;br /&gt;
&lt;br /&gt;
@@ -1 +1,2 @@&lt;br /&gt;
&lt;br /&gt;
114514&lt;br /&gt;
&lt;br /&gt;
+1919180&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git log ====&lt;br /&gt;
用于查看提交的历史&lt;br /&gt;
&lt;br /&gt;
例如当你进行一次提交之后，执行 &amp;lt;code&amp;gt;git log&amp;lt;/code&amp;gt;终端会输出&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit 3a5b0d12f471418b13f2baf5e9e4c112a5e804a8 (HEAD -&amp;gt; master)&lt;br /&gt;
&lt;br /&gt;
Author: luluzzy &amp;lt;1054438588@qq.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Date:   Thu Feb 15 21:28:47 2024 +0800&lt;br /&gt;
&lt;br /&gt;
    initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这些输出分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit sha1 hash:   针对你这个提交的 commit id&lt;br /&gt;
Author: commit      作者名称   &amp;lt;you@example.com&amp;gt;&lt;br /&gt;
Date: commit        日期&lt;br /&gt;
commit:             名称&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
关于sha1_hash的介绍请看这里&amp;lt;ref&amp;gt;生成这个hash值，它是对那个commit是Git仓库中内容和头信息Header的一个校验和checksum。Linux kernel开创者和Git的开发者——Linus说，Git使用了sha1并非是为了安全性，而是为了数据的完整性；它可以保证，在很多年后，你重新checkout某个commit时，一定是它多年前的当时的状态，完全一摸一样，完全值得信任。在Git中，根据commit的sha1值40个十六进制数字进行了简单的划分目录，以前2位数字作为目录名，其下面是剩余38位数字组成的一个文件名&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当有多次提交之后，如果我们想要翻之前的提交历史，难免会因为终端输出的内容过多而难以查看翻阅&lt;br /&gt;
&lt;br /&gt;
此时我们可以使用&amp;lt;code&amp;gt;--online&amp;lt;/code&amp;gt;参数来简化输出，此时仅会输出: sha1哈希值 + commit的名称&lt;br /&gt;
&lt;br /&gt;
例如&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
347595d (HEAD -&amp;gt; master) modify makefile&lt;br /&gt;
&lt;br /&gt;
3a5b0d1 initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git cherry-pick ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
cherry-pick (遴选) 和它的名称一样，挑选一个我们需要的 commit 进行操作。它可以用于将在其他分支上的 commit 修改，移植到当前的分支。&lt;br /&gt;
&lt;br /&gt;
如果我们想在我们正在开发的版本上，添加一个其他版本中的功能代码。就可以使用 cherry-pick ，将这个功能相关的 commit 提取出来，合入该版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick &amp;lt;commit-id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
当我们执行完 &amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;操作之后，会自动生成一个&amp;lt;code&amp;gt;commit&amp;lt;/code&amp;gt;以及对应新的&amp;lt;code&amp;gt;commit-id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在顺利的情况下我们可以直接通过，但如果遇到代码等因为变量名，写法等不同的情况，&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;大概率会报错，此时我们需要进行报错处理。&lt;br /&gt;
&lt;br /&gt;
第一种方案是手动修改&lt;br /&gt;
&lt;br /&gt;
我们可以先使用&amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt;检查当前遴选时冲突的文件&lt;br /&gt;
&lt;br /&gt;
然后 &amp;lt;code&amp;gt;git checkout --ours filename&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
然后按照提交的修改内容进行手动修改&lt;br /&gt;
&lt;br /&gt;
随后使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令将文件重新加入暂存区&lt;br /&gt;
&lt;br /&gt;
再使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --continue&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
命令让 cherrypick 操作继续执行。&lt;br /&gt;
&lt;br /&gt;
第二种方案是直接退出&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;进程，一般适用于冲突文件实在太多了难以按照方案一处理的情况。&lt;br /&gt;
&lt;br /&gt;
需要注意的是，如果您当前正在遴选的提交在该分支已经存在也会冲突，在这种情况下，您需要解决冲突并手动解决问题。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --abort&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git fetch ====&lt;br /&gt;
git fetch 命令用于从远程获取仓库。&lt;br /&gt;
&lt;br /&gt;
==== git merge ====&lt;br /&gt;
&amp;lt;code&amp;gt;git merge&amp;lt;/code&amp;gt;是用来把分叉的提交历史放回到一起(合并)的方式。&lt;br /&gt;
&lt;br /&gt;
git merge命令用来将你之前使用git branch命令创建的分支以及在此分支上独立开发的内容整合为一个分支。&lt;br /&gt;
&lt;br /&gt;
本&lt;br /&gt;
&lt;br /&gt;
==== git pull ====&lt;br /&gt;
用于从远程获取代码并合并本地的版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull&amp;lt;/code&amp;gt;其实就是&amp;lt;code&amp;gt;git fetch&amp;lt;/code&amp;gt;和&amp;lt;code&amp;gt;git merge FETCH_HEAD&amp;lt;/code&amp;gt; 的简写。&lt;br /&gt;
&lt;br /&gt;
格式如下：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull &amp;lt;remote-host-name&amp;gt; &amp;lt;remote-branch-name&amp;gt;:&amp;lt;local-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git rebase ====&lt;br /&gt;
用于需要修改历史上某一项commit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git rebase -i HEAD~&amp;lt;commit number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
commit number就是从头部往前数的commit数量。执行后会弹出你在git config内配置的编辑器，若未配置则是默认，vim居多。然后就可以看见一堆commit前面有pick字样。可以将pick替换为你想要的操作。&lt;br /&gt;
有以下操作：&lt;br /&gt;
&lt;br /&gt;
1.edit，顾名思义编辑此commit，替换完保存后请修改内容，使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;或vscode，github desktop将修改文件添加到暂存区，之后命令行执行&amp;lt;code&amp;gt;git commit --amend&amp;lt;/code&amp;gt;这样commit就修改成了&lt;br /&gt;
&lt;br /&gt;
2.squash，合并几个提交，确认一个父提交，将要合并的commit，从下向上替换字符串，会从下向上合并(方位指的是&amp;lt;code&amp;gt;git rebase&amp;lt;/code&amp;gt;后弹出的编辑器)&lt;br /&gt;
&lt;br /&gt;
3.drop，需要移除的commit&lt;br /&gt;
&lt;br /&gt;
==== git subtree ====&lt;br /&gt;
子树，在Android开发中多用于Kernel侧更改，如跟踪audio模块等&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree add --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果需要更新远程库时&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree pull --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git submodule ====&lt;br /&gt;
&lt;br /&gt;
===== 子模块功能的概述 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在自己的Github仓库里加入别人的github仓库，作为自己仓库的子仓库(即submodule)。&lt;br /&gt;
&lt;br /&gt;
为什么我们会需要使用子模块？当我们维护一个项目时有可能遇到以下情况，例如维护某款机型的KernelSU内核，我们需要将KernelSU导入至我们的内核源码中，如果我们直接clone进去容易带来一个问题，如果KernelSU更新了怎么办？此时我们便可以使用子模块来解决这个问题&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在git仓库里存放别人仓库的url，作为自己的子模块，其核心内容是在Git仓库里面加入一个&amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;文件，里面会记录各个submodule的名字，路径，以及对应链接。&lt;br /&gt;
&lt;br /&gt;
===== 加入子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule add &amp;lt;url&amp;gt; &amp;lt;path&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
此时 &amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;内会自动生成以下内容&lt;br /&gt;
&lt;br /&gt;
[submodule &amp;quot;xxx&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
path = xxx&lt;br /&gt;
&lt;br /&gt;
url = xxx&lt;br /&gt;
&lt;br /&gt;
===== 初始化子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule init&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== 更新子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule update&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Git进阶 ===&lt;br /&gt;
&lt;br /&gt;
==== GPG key ====&lt;br /&gt;
&lt;br /&gt;
===== 简介 =====&lt;br /&gt;
平时在Github上摸鱼的时候，是不是经常能看见如下图所示，有一个绿色的&amp;quot;Verified&amp;quot;字样，看着很酷，实际上这是为了确保commit为开发者本人所写的进行的GPG签名。&lt;br /&gt;
[[文件:Github GPG sign.png|居中]]&lt;br /&gt;
因为Git的默认机制，任何人都可以通过你的邮箱和用户名创建虚假的commit，甚至你名气很大的话可以“栽赃陷害”你。如果你是某高校计算机专业的同学亦或是对计算机抱有很大的兴趣，乐意为开源社区提供“资源”，那么我建议你设置GPG sign。未来是不可预知的，人人都可能成为巨佬。&lt;br /&gt;
&lt;br /&gt;
===== 使用 =====&lt;br /&gt;
因为我只在Mac环境下配置过GPG，Windows只是打游戏用，所以用的少，Linux/类Unix可以参考一下。其它系统等待他人补充......&lt;br /&gt;
&lt;br /&gt;
====== Mac ======&lt;br /&gt;
Mac默认是不带GPG的，需要通过第三方软件包安装器Homebrew进行安装，首先先安装Homebrew，如已安装可以跳过。&lt;br /&gt;
&lt;br /&gt;
编辑器限制原因不能使用默认标题进行分步了，故使用1、2、3等小数字代替。&lt;br /&gt;
&lt;br /&gt;
安装Homebrew&lt;br /&gt;
&lt;br /&gt;
在安装之前需要从系统信息中查看芯片为Intel/M系列&lt;br /&gt;
&lt;br /&gt;
Intel使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/bin/zsh -c &amp;quot;$(curl -fsSL &amp;lt;nowiki&amp;gt;https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh&amp;lt;/nowiki&amp;gt;)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Intel按照脚本提示，选源，输密码，回车一路绿灯就好了，如果这都不会......可能你不是很适合开发，因为该脚本是国内开发者编写的，中文和一键化安装都集齐了。&lt;br /&gt;
&lt;br /&gt;
M系列使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;/bin/zsh -c &amp;quot;$(curl -fsSL https://gitee.com/huwei1024/HomebrewCN/raw/master/Homebrew.sh)&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
并且因为M系列系统结构发生改变，包安装位置不在是以前的/usr/local/，而是在/opt/homebrew，所以要将配置文件里的环境变量改过来。&lt;br /&gt;
&lt;br /&gt;
1.首先进入根目录&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cd ~&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2.创建.zshrc文件&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;touch .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3.打开文件进行编辑&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;open -e .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4.如果有旧的环境就修改，没有就新增&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;export PATH=&amp;quot;/opt/homebrew/bin:$PATH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
export PATH=&amp;quot;/opt/homebrew/sbin:$PATH&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5.保存&lt;br /&gt;
&lt;br /&gt;
使用command + s&lt;br /&gt;
&lt;br /&gt;
6.生效环境变量&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;source .zshrc&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
7、测试&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;brew -v&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
若终端顺利打印出brew的版本，那么就安装成功了！&lt;br /&gt;
&lt;br /&gt;
注：本人没有使用过M系列设备，该教程在知乎上找到的&lt;br /&gt;
&lt;br /&gt;
使用Homebrew安装GPG&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;brew install gnupg pinentry-mac&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.34.48.png|居中]]&lt;br /&gt;
&lt;br /&gt;
生成一个GPG keys&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gpg --full-generate-key&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.45.51.png|居中]]&lt;br /&gt;
&lt;br /&gt;
默认使用的是ECC，我使用的是RSA，按照自己喜好，或从百度搜索非对称和对称加密算法之间的区别，这里只做使用方法的介绍，不做赘述。&lt;br /&gt;
&lt;br /&gt;
然后添写密钥长度和使用有效期，这里建议选择长期，并做备份，一辈子用一个就够了。&lt;br /&gt;
&lt;br /&gt;
[[文件:截屏2024-02-17 17.46.06.png|居中]]&lt;br /&gt;
[[文件:截屏2024-02-17 17.46.35.png|居中]]&lt;br /&gt;
&lt;br /&gt;
个人信息按照Github信息填写，真实姓名对应Username。填写完毕按回车输入O即可生成密钥。不出意外的话会弹出Gui窗口让你设置密钥密码，强烈建设设置一个较为复杂的密码，并牢记，当然也可以不设置。&lt;br /&gt;
&lt;br /&gt;
使用GPG对Git的commit和tag进行签名&lt;br /&gt;
&lt;br /&gt;
先为Git定义GPG二进制所在地&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global gpg.program $(which gpg)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
查看GPG keys ID&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gpg --list-secret-keys --keyid-format=long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如图所示RSA/后面紧跟的一串就是GPG keys ID&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.signingkey &amp;quot;GPG key ID&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 参考资料： ====&lt;br /&gt;
[1] 百度百科 -- Git：&amp;lt;nowiki&amp;gt;https://baike.baidu.com/item/GIT/12647237?fr=ge_ala&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[2] 菜鸟教程 -- Git基本操作：&amp;lt;nowiki&amp;gt;https://www.runoob.com/git/git-basic-operations.html&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[3] CSDN -- git merge 使用简介: &amp;lt;nowiki&amp;gt;https://blog.csdn.net/All_In_gzx_cc/article/details/125482617&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[3] 知乎 -- MAC 安装 homebrew 国内镜像: &amp;lt;nowiki&amp;gt;https://zhuanlan.zhihu.com/p/547898033&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=%E6%96%87%E4%BB%B6:%E6%88%AA%E5%B1%8F2024-02-17_17.57.01.png&amp;diff=517</id>
		<title>文件:截屏2024-02-17 17.57.01.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=%E6%96%87%E4%BB%B6:%E6%88%AA%E5%B1%8F2024-02-17_17.57.01.png&amp;diff=517"/>
		<updated>2024-02-17T09:57:26Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;截屏2024-02-17 17.57.01&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=%E6%96%87%E4%BB%B6:%E6%88%AA%E5%B1%8F2024-02-17_17.46.35.png&amp;diff=516</id>
		<title>文件:截屏2024-02-17 17.46.35.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=%E6%96%87%E4%BB%B6:%E6%88%AA%E5%B1%8F2024-02-17_17.46.35.png&amp;diff=516"/>
		<updated>2024-02-17T09:49:24Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;截屏2024-02-17 17.46.35&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=%E6%96%87%E4%BB%B6:%E6%88%AA%E5%B1%8F2024-02-17_17.46.06.png&amp;diff=515</id>
		<title>文件:截屏2024-02-17 17.46.06.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=%E6%96%87%E4%BB%B6:%E6%88%AA%E5%B1%8F2024-02-17_17.46.06.png&amp;diff=515"/>
		<updated>2024-02-17T09:48:57Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;截屏2024-02-17 17.46.06&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=%E6%96%87%E4%BB%B6:%E6%88%AA%E5%B1%8F2024-02-17_17.45.51.png&amp;diff=514</id>
		<title>文件:截屏2024-02-17 17.45.51.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=%E6%96%87%E4%BB%B6:%E6%88%AA%E5%B1%8F2024-02-17_17.45.51.png&amp;diff=514"/>
		<updated>2024-02-17T09:47:35Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;截屏2024-02-17 17.45.51&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=%E6%96%87%E4%BB%B6:%E6%88%AA%E5%B1%8F2024-02-17_17.34.48.png&amp;diff=513</id>
		<title>文件:截屏2024-02-17 17.34.48.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=%E6%96%87%E4%BB%B6:%E6%88%AA%E5%B1%8F2024-02-17_17.34.48.png&amp;diff=513"/>
		<updated>2024-02-17T09:35:10Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;截屏2024-02-17 17.34.48&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=%E6%96%87%E4%BB%B6:Github_GPG_sign.png&amp;diff=512</id>
		<title>文件:Github GPG sign.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=%E6%96%87%E4%BB%B6:Github_GPG_sign.png&amp;diff=512"/>
		<updated>2024-02-17T09:10:17Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Github GPG sign&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=511</id>
		<title>Git使用教程</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=511"/>
		<updated>2024-02-17T08:59:32Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​fixup: 添加修改默认编辑器命令&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Git的由来： ===&lt;br /&gt;
Git是一个开源的分布式版本控制系统，可以有效、高速地处理从很小到非常大的项目版本管理，也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper。&lt;br /&gt;
&lt;br /&gt;
=== 常见的代码托管平台： ===&lt;br /&gt;
[https://github.com Github]&lt;br /&gt;
&lt;br /&gt;
[https://gitlab.com Gitlab]&lt;br /&gt;
&lt;br /&gt;
[https://gitee.com Gitee]&lt;br /&gt;
&lt;br /&gt;
=== Git 常见命令: ===&lt;br /&gt;
&lt;br /&gt;
==== git init ====&lt;br /&gt;
在本地目录中初始化一个新的Git仓库&lt;br /&gt;
&lt;br /&gt;
==== git config ====&lt;br /&gt;
用于配置用户的信息以及其他设置,在使用git之前您必须完成以下步骤。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.name &amp;quot;your username&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.email &amp;quot;your email&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
更改默认编辑器&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global core.editor nano&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git clone ====&lt;br /&gt;
用于将远程仓库的代码克隆到本地，以下是命令中各个参数的含义：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;url&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆某个地址(url)的仓库，远程仓库的地址可以是本地的目录，也可以是例如github,giteee,gitlab一类的代码托管平台&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;--depth=&amp;lt;number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆仓库并且保留number条提交历史，number在此处即表达我们克隆的深度。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;-b &amp;lt;branch&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆指定分支下的仓库内容&lt;br /&gt;
&lt;br /&gt;
例如我们要克隆&amp;lt;code&amp;gt;LineageOS&amp;lt;/code&amp;gt;的内核源码，指定&amp;lt;code&amp;gt;lineage-21&amp;lt;/code&amp;gt;分支，且仅保留最近一个提交，则需要输入:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git clone -b lineage-21 &amp;lt;nowiki&amp;gt;https://github.com/LineageOS/android_kernel_xiaomi_sdm845&amp;lt;/nowiki&amp;gt; --depth=1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git add ====&lt;br /&gt;
添加某个文件，或者目录到暂存区，用于告诉git你需要将哪些文件的更改包含在下一次的提交(commit)之中添加一个或者多个文件到暂存区之中&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [file1] [file2]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加指定目录(文件)到暂存区，包括子目录：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [dir]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加当前目录下的所有文件到暂存区：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add .&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git status ====&lt;br /&gt;
查看当前仓库的状态，此时git会在你的终端输出以下内容&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;em style=&amp;quot;color: gray;&amp;quot;&amp;gt;此处演示为英文，如果您的git终端输出为中文也是同理的&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
On branch master&lt;br /&gt;
No commits yet&lt;br /&gt;
Changes to be committed:  &lt;br /&gt;
&lt;br /&gt;
(use “git rm --cached &amp;lt;file&amp;gt;...” to unstage)       &lt;br /&gt;
new file:   makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
输出内容分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
您目前所在的分支&lt;br /&gt;
目前的提交&lt;br /&gt;
需要更改的内容&lt;br /&gt;
新增的文件&lt;br /&gt;
修改的文件&lt;br /&gt;
删除的文件&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git commit ====&lt;br /&gt;
用于将暂存区我们保存的更改文件添加到本地仓库，并且会生成一条提交（commit）&lt;br /&gt;
&lt;br /&gt;
提交暂存区的更改到本地仓库&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -m &amp;quot;message&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[注] message 可以是你的备注信息&lt;br /&gt;
&lt;br /&gt;
提交暂存区中的指定文件到本地仓库&lt;br /&gt;
&lt;br /&gt;
如果你没有使用上述&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令暂存你的修改文件，可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -a&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
进行直接提交&lt;br /&gt;
&lt;br /&gt;
==== git checkout ====&lt;br /&gt;
&lt;br /&gt;
* 用于分支切换&lt;br /&gt;
&lt;br /&gt;
切换分支：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如在您的仓库中有这几个分支：&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-&amp;gt; master (Default)&lt;br /&gt;
   backup&lt;br /&gt;
   test&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
您当前处于 master 分支，如果想要切换到test分支，我们可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 用于检出文件&lt;br /&gt;
将指定的文件恢复到最新的提交状态，撤销你对其的更改&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout -- &amp;lt;file&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git push ====&lt;br /&gt;
用于将本地的分支版本上传到远程仓库并进行合并&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push &amp;lt;remote-host-name&amp;gt; &amp;lt;local-branch-name&amp;gt;:&amp;lt;remote-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
remote-host-name:远程主机名&lt;br /&gt;
&lt;br /&gt;
local-branch-name:本地分支名&lt;br /&gt;
&lt;br /&gt;
例如，当你的远程主机名为origin ，本地分支名为master，远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master:master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如，当你的rhost名为origin 本地分支名为master远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
本地和远程分支名相同，上述命令可以简写为：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当你的远程版本与本地版本有差异，无法直接push时，你可以使用--force 参数来进行强制推送&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push --force origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
--force 此处可以直接简单化为 -f &lt;br /&gt;
&lt;br /&gt;
如果你想要删除主机内的某个分支，你可以使用--delete参数&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin --delete &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git diff ====&lt;br /&gt;
用于比较当前工作区与上一个版本之间的差异&lt;br /&gt;
&lt;br /&gt;
例如：（此处仅做不恰当举例，Makefile不是这样乱写的）&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
diff --git a/makefile b/makefile&lt;br /&gt;
&lt;br /&gt;
index fbb8c85..d65c7eb 100644&lt;br /&gt;
&lt;br /&gt;
--- a/makefile&lt;br /&gt;
&lt;br /&gt;
+++ b/makefile&lt;br /&gt;
&lt;br /&gt;
@@ -1 +1,2 @@&lt;br /&gt;
&lt;br /&gt;
114514&lt;br /&gt;
&lt;br /&gt;
+1919180&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git log ====&lt;br /&gt;
用于查看提交的历史&lt;br /&gt;
&lt;br /&gt;
例如当你进行一次提交之后，执行 &amp;lt;code&amp;gt;git log&amp;lt;/code&amp;gt;终端会输出&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit 3a5b0d12f471418b13f2baf5e9e4c112a5e804a8 (HEAD -&amp;gt; master)&lt;br /&gt;
&lt;br /&gt;
Author: luluzzy &amp;lt;1054438588@qq.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Date:   Thu Feb 15 21:28:47 2024 +0800&lt;br /&gt;
&lt;br /&gt;
    initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这些输出分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit sha1 hash:   针对你这个提交的 commit id&lt;br /&gt;
Author: commit      作者名称   &amp;lt;you@example.com&amp;gt;&lt;br /&gt;
Date: commit        日期&lt;br /&gt;
commit:             名称&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
关于sha1_hash的介绍请看这里&amp;lt;ref&amp;gt;生成这个hash值，它是对那个commit是Git仓库中内容和头信息Header的一个校验和checksum。Linux kernel开创者和Git的开发者——Linus说，Git使用了sha1并非是为了安全性，而是为了数据的完整性；它可以保证，在很多年后，你重新checkout某个commit时，一定是它多年前的当时的状态，完全一摸一样，完全值得信任。在Git中，根据commit的sha1值40个十六进制数字进行了简单的划分目录，以前2位数字作为目录名，其下面是剩余38位数字组成的一个文件名&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当有多次提交之后，如果我们想要翻之前的提交历史，难免会因为终端输出的内容过多而难以查看翻阅&lt;br /&gt;
&lt;br /&gt;
此时我们可以使用&amp;lt;code&amp;gt;--online&amp;lt;/code&amp;gt;参数来简化输出，此时仅会输出: sha1哈希值 + commit的名称&lt;br /&gt;
&lt;br /&gt;
例如&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
347595d (HEAD -&amp;gt; master) modify makefile&lt;br /&gt;
&lt;br /&gt;
3a5b0d1 initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git cherry-pick ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
cherry-pick (遴选) 和它的名称一样，挑选一个我们需要的 commit 进行操作。它可以用于将在其他分支上的 commit 修改，移植到当前的分支。&lt;br /&gt;
&lt;br /&gt;
如果我们想在我们正在开发的版本上，添加一个其他版本中的功能代码。就可以使用 cherry-pick ，将这个功能相关的 commit 提取出来，合入该版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick &amp;lt;commit-id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
当我们执行完 &amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;操作之后，会自动生成一个&amp;lt;code&amp;gt;commit&amp;lt;/code&amp;gt;以及对应新的&amp;lt;code&amp;gt;commit-id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在顺利的情况下我们可以直接通过，但如果遇到代码等因为变量名，写法等不同的情况，&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;大概率会报错，此时我们需要进行报错处理。&lt;br /&gt;
&lt;br /&gt;
第一种方案是手动修改&lt;br /&gt;
&lt;br /&gt;
我们可以先使用&amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt;检查当前遴选时冲突的文件&lt;br /&gt;
&lt;br /&gt;
然后 &amp;lt;code&amp;gt;git checkout --ours filename&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
然后按照提交的修改内容进行手动修改&lt;br /&gt;
&lt;br /&gt;
随后使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令将文件重新加入暂存区&lt;br /&gt;
&lt;br /&gt;
再使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --continue&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
命令让 cherrypick 操作继续执行。&lt;br /&gt;
&lt;br /&gt;
第二种方案是直接退出&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;进程，一般适用于冲突文件实在太多了难以按照方案一处理的情况。&lt;br /&gt;
&lt;br /&gt;
需要注意的是，如果您当前正在遴选的提交在该分支已经存在也会冲突，在这种情况下，您需要解决冲突并手动解决问题。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --abort&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git fetch ====&lt;br /&gt;
git fetch 命令用于从远程获取仓库。&lt;br /&gt;
&lt;br /&gt;
==== git merge ====&lt;br /&gt;
&amp;lt;code&amp;gt;git merge&amp;lt;/code&amp;gt;是用来把分叉的提交历史放回到一起(合并)的方式。&lt;br /&gt;
&lt;br /&gt;
git merge命令用来将你之前使用git branch命令创建的分支以及在此分支上独立开发的内容整合为一个分支。&lt;br /&gt;
&lt;br /&gt;
本&lt;br /&gt;
&lt;br /&gt;
==== git pull ====&lt;br /&gt;
用于从远程获取代码并合并本地的版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull&amp;lt;/code&amp;gt;其实就是&amp;lt;code&amp;gt;git fetch&amp;lt;/code&amp;gt;和&amp;lt;code&amp;gt;git merge FETCH_HEAD&amp;lt;/code&amp;gt; 的简写。&lt;br /&gt;
&lt;br /&gt;
格式如下：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull &amp;lt;remote-host-name&amp;gt; &amp;lt;remote-branch-name&amp;gt;:&amp;lt;local-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git rebase ====&lt;br /&gt;
用于需要修改历史上某一项commit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git rebase -i HEAD~&amp;lt;commit number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
commit number就是从头部往前数的commit数量。执行后会弹出你在git config内配置的编辑器，若未配置则是默认，vim居多。然后就可以看见一堆commit前面有pick字样。可以将pick替换为你想要的操作。&lt;br /&gt;
有以下操作：&lt;br /&gt;
&lt;br /&gt;
1.edit，顾名思义编辑此commit，替换完保存后请修改内容，使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;或vscode，github desktop将修改文件添加到暂存区，之后命令行执行&amp;lt;code&amp;gt;git commit --amend&amp;lt;/code&amp;gt;这样commit就修改成了&lt;br /&gt;
&lt;br /&gt;
2.squash，合并几个提交，确认一个父提交，将要合并的commit，从下向上替换字符串，会从下向上合并(方位指的是&amp;lt;code&amp;gt;git rebase&amp;lt;/code&amp;gt;后弹出的编辑器)&lt;br /&gt;
&lt;br /&gt;
3.drop，需要移除的commit&lt;br /&gt;
&lt;br /&gt;
==== git subtree ====&lt;br /&gt;
子树，在Android开发中多用于Kernel侧更改，如跟踪audio模块等&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree add --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果需要更新远程库时&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree pull --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git submodule ====&lt;br /&gt;
&lt;br /&gt;
===== 子模块功能的概述 =====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在自己的Github仓库里加入别人的github仓库，作为自己仓库的子仓库(即submodule)。&lt;br /&gt;
&lt;br /&gt;
为什么我们会需要使用子模块？当我们维护一个项目时有可能遇到以下情况，例如维护某款机型的KernelSU内核，我们需要将KernelSU导入至我们的内核源码中，如果我们直接clone进去容易带来一个问题，如果KernelSU更新了怎么办？此时我们便可以使用子模块来解决这个问题&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在git仓库里存放别人仓库的url，作为自己的子模块，其核心内容是在Git仓库里面加入一个&amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;文件，里面会记录各个submodule的名字，路径，以及对应链接。&lt;br /&gt;
&lt;br /&gt;
===== 加入子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule add &amp;lt;url&amp;gt; &amp;lt;path&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
此时 &amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;内会自动生成以下内容&lt;br /&gt;
&lt;br /&gt;
[submodule &amp;quot;xxx&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
path = xxx&lt;br /&gt;
&lt;br /&gt;
url = xxx&lt;br /&gt;
&lt;br /&gt;
===== 初始化子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule init&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== 更新子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule update&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 参考资料： ====&lt;br /&gt;
[1] 百度百科 -- Git：&amp;lt;nowiki&amp;gt;https://baike.baidu.com/item/GIT/12647237?fr=ge_ala&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[2] 菜鸟教程 -- Git基本操作：&amp;lt;nowiki&amp;gt;https://www.runoob.com/git/git-basic-operations.html&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[3] CSDN -- git merge 使用简介: &amp;lt;nowiki&amp;gt;https://blog.csdn.net/All_In_gzx_cc/article/details/125482617&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=510</id>
		<title>Git使用教程</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=510"/>
		<updated>2024-02-17T08:58:53Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​添加更改默认编辑器的命令&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Git的由来： ===&lt;br /&gt;
Git是一个开源的分布式版本控制系统，可以有效、高速地处理从很小到非常大的项目版本管理，也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper。&lt;br /&gt;
&lt;br /&gt;
=== 常见的代码托管平台： ===&lt;br /&gt;
[https://github.com Github]&lt;br /&gt;
&lt;br /&gt;
[https://gitlab.com Gitlab]&lt;br /&gt;
&lt;br /&gt;
[https://gitee.com Gitee]&lt;br /&gt;
&lt;br /&gt;
=== Git 常见命令: ===&lt;br /&gt;
&lt;br /&gt;
==== git init ====&lt;br /&gt;
在本地目录中初始化一个新的Git仓库&lt;br /&gt;
&lt;br /&gt;
==== git config ====&lt;br /&gt;
用于配置用户的信息以及其他设置,在使用git之前您必须完成以下步骤。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.name &amp;quot;your username&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.email &amp;quot;your email&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
更改默认编辑器&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global core.editor nano&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git clone ====&lt;br /&gt;
用于将远程仓库的代码克隆到本地，以下是命令中各个参数的含义：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;url&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆某个地址(url)的仓库，远程仓库的地址可以是本地的目录，也可以是例如github,giteee,gitlab一类的代码托管平台&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;--depth=&amp;lt;number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆仓库并且保留number条提交历史，number在此处即表达我们克隆的深度。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;-b &amp;lt;branch&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆指定分支下的仓库内容&lt;br /&gt;
&lt;br /&gt;
例如我们要克隆&amp;lt;code&amp;gt;LineageOS&amp;lt;/code&amp;gt;的内核源码，指定&amp;lt;code&amp;gt;lineage-21&amp;lt;/code&amp;gt;分支，且仅保留最近一个提交，则需要输入:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git clone -b lineage-21 &amp;lt;nowiki&amp;gt;https://github.com/LineageOS/android_kernel_xiaomi_sdm845&amp;lt;/nowiki&amp;gt; --depth=1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git add ====&lt;br /&gt;
添加某个文件，或者目录到暂存区，用于告诉git你需要将哪些文件的更改包含在下一次的提交(commit)之中添加一个或者多个文件到暂存区之中&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [file1] [file2]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加指定目录(文件)到暂存区，包括子目录：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [dir]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加当前目录下的所有文件到暂存区：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add .&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git status ====&lt;br /&gt;
查看当前仓库的状态，此时git会在你的终端输出以下内容&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;em style=&amp;quot;color: gray;&amp;quot;&amp;gt;此处演示为英文，如果您的git终端输出为中文也是同理的&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
On branch master&lt;br /&gt;
No commits yet&lt;br /&gt;
Changes to be committed:  &lt;br /&gt;
&lt;br /&gt;
(use “git rm --cached &amp;lt;file&amp;gt;...” to unstage)       &lt;br /&gt;
new file:   makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
输出内容分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
您目前所在的分支&lt;br /&gt;
目前的提交&lt;br /&gt;
需要更改的内容&lt;br /&gt;
新增的文件&lt;br /&gt;
修改的文件&lt;br /&gt;
删除的文件&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git commit ====&lt;br /&gt;
用于将暂存区我们保存的更改文件添加到本地仓库，并且会生成一条提交（commit）&lt;br /&gt;
&lt;br /&gt;
提交暂存区的更改到本地仓库&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -m &amp;quot;message&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[注] message 可以是你的备注信息&lt;br /&gt;
&lt;br /&gt;
提交暂存区中的指定文件到本地仓库&lt;br /&gt;
&lt;br /&gt;
如果你没有使用上述&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令暂存你的修改文件，可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -a&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
进行直接提交&lt;br /&gt;
&lt;br /&gt;
==== git checkout ====&lt;br /&gt;
&lt;br /&gt;
* 用于分支切换&lt;br /&gt;
&lt;br /&gt;
切换分支：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如在您的仓库中有这几个分支：&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-&amp;gt; master (Default)&lt;br /&gt;
   backup&lt;br /&gt;
   test&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
您当前处于 master 分支，如果想要切换到test分支，我们可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 用于检出文件&lt;br /&gt;
将指定的文件恢复到最新的提交状态，撤销你对其的更改&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout -- &amp;lt;file&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git push ====&lt;br /&gt;
用于将本地的分支版本上传到远程仓库并进行合并&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push &amp;lt;remote-host-name&amp;gt; &amp;lt;local-branch-name&amp;gt;:&amp;lt;remote-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
remote-host-name:远程主机名&lt;br /&gt;
&lt;br /&gt;
local-branch-name:本地分支名&lt;br /&gt;
&lt;br /&gt;
例如，当你的远程主机名为origin ，本地分支名为master，远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master:master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如，当你的rhost名为origin 本地分支名为master远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
本地和远程分支名相同，上述命令可以简写为：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当你的远程版本与本地版本有差异，无法直接push时，你可以使用--force 参数来进行强制推送&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push --force origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
--force 此处可以直接简单化为 -f &lt;br /&gt;
&lt;br /&gt;
如果你想要删除主机内的某个分支，你可以使用--delete参数&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin --delete &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git diff ====&lt;br /&gt;
用于比较当前工作区与上一个版本之间的差异&lt;br /&gt;
&lt;br /&gt;
例如：（此处仅做不恰当举例，Makefile不是这样乱写的）&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
diff --git a/makefile b/makefile&lt;br /&gt;
&lt;br /&gt;
index fbb8c85..d65c7eb 100644&lt;br /&gt;
&lt;br /&gt;
--- a/makefile&lt;br /&gt;
&lt;br /&gt;
+++ b/makefile&lt;br /&gt;
&lt;br /&gt;
@@ -1 +1,2 @@&lt;br /&gt;
&lt;br /&gt;
114514&lt;br /&gt;
&lt;br /&gt;
+1919180&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git log ====&lt;br /&gt;
用于查看提交的历史&lt;br /&gt;
&lt;br /&gt;
例如当你进行一次提交之后，执行 &amp;lt;code&amp;gt;git log&amp;lt;/code&amp;gt;终端会输出&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit 3a5b0d12f471418b13f2baf5e9e4c112a5e804a8 (HEAD -&amp;gt; master)&lt;br /&gt;
&lt;br /&gt;
Author: luluzzy &amp;lt;1054438588@qq.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Date:   Thu Feb 15 21:28:47 2024 +0800&lt;br /&gt;
&lt;br /&gt;
    initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这些输出分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit sha1 hash:   针对你这个提交的 commit id&lt;br /&gt;
Author: commit      作者名称   &amp;lt;you@example.com&amp;gt;&lt;br /&gt;
Date: commit        日期&lt;br /&gt;
commit:             名称&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
关于sha1_hash的介绍请看这里&amp;lt;ref&amp;gt;生成这个hash值，它是对那个commit是Git仓库中内容和头信息Header的一个校验和checksum。Linux kernel开创者和Git的开发者——Linus说，Git使用了sha1并非是为了安全性，而是为了数据的完整性；它可以保证，在很多年后，你重新checkout某个commit时，一定是它多年前的当时的状态，完全一摸一样，完全值得信任。在Git中，根据commit的sha1值40个十六进制数字进行了简单的划分目录，以前2位数字作为目录名，其下面是剩余38位数字组成的一个文件名&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当有多次提交之后，如果我们想要翻之前的提交历史，难免会因为终端输出的内容过多而难以查看翻阅&lt;br /&gt;
&lt;br /&gt;
此时我们可以使用&amp;lt;code&amp;gt;--online&amp;lt;/code&amp;gt;参数来简化输出，此时仅会输出: sha1哈希值 + commit的名称&lt;br /&gt;
&lt;br /&gt;
例如&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
347595d (HEAD -&amp;gt; master) modify makefile&lt;br /&gt;
&lt;br /&gt;
3a5b0d1 initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git cherry-pick ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
cherry-pick (遴选) 和它的名称一样，挑选一个我们需要的 commit 进行操作。它可以用于将在其他分支上的 commit 修改，移植到当前的分支。&lt;br /&gt;
&lt;br /&gt;
如果我们想在我们正在开发的版本上，添加一个其他版本中的功能代码。就可以使用 cherry-pick ，将这个功能相关的 commit 提取出来，合入该版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick &amp;lt;commit-id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
当我们执行完 &amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;操作之后，会自动生成一个&amp;lt;code&amp;gt;commit&amp;lt;/code&amp;gt;以及对应新的&amp;lt;code&amp;gt;commit-id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在顺利的情况下我们可以直接通过，但如果遇到代码等因为变量名，写法等不同的情况，&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;大概率会报错，此时我们需要进行报错处理。&lt;br /&gt;
&lt;br /&gt;
第一种方案是手动修改&lt;br /&gt;
&lt;br /&gt;
我们可以先使用&amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt;检查当前遴选时冲突的文件&lt;br /&gt;
&lt;br /&gt;
然后 &amp;lt;code&amp;gt;git checkout --ours filename&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
然后按照提交的修改内容进行手动修改&lt;br /&gt;
&lt;br /&gt;
随后使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令将文件重新加入暂存区&lt;br /&gt;
&lt;br /&gt;
再使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --continue&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
命令让 cherrypick 操作继续执行。&lt;br /&gt;
&lt;br /&gt;
第二种方案是直接退出&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;进程，一般适用于冲突文件实在太多了难以按照方案一处理的情况。&lt;br /&gt;
&lt;br /&gt;
需要注意的是，如果您当前正在遴选的提交在该分支已经存在也会冲突，在这种情况下，您需要解决冲突并手动解决问题。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --abort&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git fetch ====&lt;br /&gt;
git fetch 命令用于从远程获取仓库。&lt;br /&gt;
&lt;br /&gt;
==== git merge ====&lt;br /&gt;
&amp;lt;code&amp;gt;git merge&amp;lt;/code&amp;gt;是用来把分叉的提交历史放回到一起(合并)的方式。&lt;br /&gt;
&lt;br /&gt;
git merge命令用来将你之前使用git branch命令创建的分支以及在此分支上独立开发的内容整合为一个分支。&lt;br /&gt;
&lt;br /&gt;
本&lt;br /&gt;
&lt;br /&gt;
==== git pull ====&lt;br /&gt;
用于从远程获取代码并合并本地的版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull&amp;lt;/code&amp;gt;其实就是&amp;lt;code&amp;gt;git fetch&amp;lt;/code&amp;gt;和&amp;lt;code&amp;gt;git merge FETCH_HEAD&amp;lt;/code&amp;gt; 的简写。&lt;br /&gt;
&lt;br /&gt;
格式如下：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull &amp;lt;remote-host-name&amp;gt; &amp;lt;remote-branch-name&amp;gt;:&amp;lt;local-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git rebase ====&lt;br /&gt;
用于需要修改历史上某一项commit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git rebase -i HEAD~&amp;lt;commit number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
commit number就是从头部往前数的commit数量。执行后会弹出你在git config内配置的编辑器，若未配置则是默认，vim居多。然后就可以看见一堆commit前面有pick字样。可以将pick替换为你想要的操作。&lt;br /&gt;
有以下操作：&lt;br /&gt;
&lt;br /&gt;
1.edit，顾名思义编辑此commit，替换完保存后请修改内容，使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;或vscode，github desktop将修改文件添加到暂存区，之后命令行执行&amp;lt;code&amp;gt;git commit --amend&amp;lt;/code&amp;gt;这样commit就修改成了&lt;br /&gt;
&lt;br /&gt;
2.squash，合并几个提交，确认一个父提交，将要合并的commit，从下向上替换字符串，会从下向上合并(方位指的是&amp;lt;code&amp;gt;git rebase&amp;lt;/code&amp;gt;后弹出的编辑器)&lt;br /&gt;
&lt;br /&gt;
3.drop，需要移除的commit&lt;br /&gt;
&lt;br /&gt;
==== git subtree ====&lt;br /&gt;
子树，在Android开发中多用于Kernel侧更改，如跟踪audio模块等&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree add --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果需要更新远程库时&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree pull --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git submodule ====&lt;br /&gt;
&lt;br /&gt;
===== 子模块功能的概述 =====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在自己的Github仓库里加入别人的github仓库，作为自己仓库的子仓库(即submodule)。&lt;br /&gt;
&lt;br /&gt;
为什么我们会需要使用子模块？当我们维护一个项目时有可能遇到以下情况，例如维护某款机型的KernelSU内核，我们需要将KernelSU导入至我们的内核源码中，如果我们直接clone进去容易带来一个问题，如果KernelSU更新了怎么办？此时我们便可以使用子模块来解决这个问题&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule&amp;lt;/code&amp;gt;允许在git仓库里存放别人仓库的url，作为自己的子模块，其核心内容是在Git仓库里面加入一个&amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;文件，里面会记录各个submodule的名字，路径，以及对应链接。&lt;br /&gt;
&lt;br /&gt;
===== 加入子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule add &amp;lt;url&amp;gt; &amp;lt;path&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
此时 &amp;lt;code&amp;gt;.gitmodules&amp;lt;/code&amp;gt;内会自动生成以下内容&lt;br /&gt;
&lt;br /&gt;
[submodule &amp;quot;xxx&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
path = xxx&lt;br /&gt;
&lt;br /&gt;
url = xxx&lt;br /&gt;
&lt;br /&gt;
===== 初始化子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule init&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== 更新子模块 =====&lt;br /&gt;
&amp;lt;code&amp;gt;git submodule update&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 参考资料： ====&lt;br /&gt;
[1] 百度百科 -- Git：&amp;lt;nowiki&amp;gt;https://baike.baidu.com/item/GIT/12647237?fr=ge_ala&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[2] 菜鸟教程 -- Git基本操作：&amp;lt;nowiki&amp;gt;https://www.runoob.com/git/git-basic-operations.html&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[3] CSDN -- git merge 使用简介: &amp;lt;nowiki&amp;gt;https://blog.csdn.net/All_In_gzx_cc/article/details/125482617&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=485</id>
		<title>Git使用教程</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=485"/>
		<updated>2024-02-16T11:46:52Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​添加subtree&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Git的由来： ===&lt;br /&gt;
Git是一个开源的分布式版本控制系统，可以有效、高速地处理从很小到非常大的项目版本管理，也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper。&lt;br /&gt;
&lt;br /&gt;
=== 常见的代码托管平台： ===&lt;br /&gt;
[https://github.com Github]&lt;br /&gt;
&lt;br /&gt;
[https://gitlab.com Gitlab]&lt;br /&gt;
&lt;br /&gt;
[https://gitee.com Gitee]&lt;br /&gt;
&lt;br /&gt;
=== Git 常见命令: ===&lt;br /&gt;
&lt;br /&gt;
==== git init ====&lt;br /&gt;
在本地目录中初始化一个新的Git仓库&lt;br /&gt;
&lt;br /&gt;
==== git config ====&lt;br /&gt;
用于配置用户的信息以及其他设置,在使用git之前您必须完成以下步骤。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.name &amp;quot;your username&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.email &amp;quot;your email&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git clone ====&lt;br /&gt;
用于将远程仓库的代码克隆到本地，以下是命令中各个参数的含义：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;url&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆某个地址(url)的仓库，远程仓库的地址可以是本地的目录，也可以是例如github,giteee,gitlab一类的代码托管平台&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;--depth=&amp;lt;number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆仓库并且保留number条提交历史，number在此处即表达我们克隆的深度。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;-b &amp;lt;branch&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆指定分支下的仓库内容&lt;br /&gt;
&lt;br /&gt;
例如我们要克隆&amp;lt;code&amp;gt;LineageOS&amp;lt;/code&amp;gt;的内核源码，指定&amp;lt;code&amp;gt;lineage-21&amp;lt;/code&amp;gt;分支，且仅保留最近一个提交，则需要输入:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git clone -b lineage-21 &amp;lt;nowiki&amp;gt;https://github.com/LineageOS/android_kernel_xiaomi_sdm845&amp;lt;/nowiki&amp;gt; --depth=1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git add ====&lt;br /&gt;
添加某个文件，或者目录到暂存区，用于告诉git你需要将哪些文件的更改包含在下一次的提交(commit)之中添加一个或者多个文件到暂存区之中&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [file1] [file2]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加指定目录(文件)到暂存区，包括子目录：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [dir]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加当前目录下的所有文件到暂存区：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add .&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git status ====&lt;br /&gt;
查看当前仓库的状态，此时git会在你的终端输出以下内容&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;em style=&amp;quot;color: gray;&amp;quot;&amp;gt;此处演示为英文，如果您的git终端输出为中文也是同理的&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
On branch master&lt;br /&gt;
No commits yet&lt;br /&gt;
Changes to be committed:  &lt;br /&gt;
&lt;br /&gt;
(use “git rm --cached &amp;lt;file&amp;gt;...” to unstage)       &lt;br /&gt;
new file:   makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
输出内容分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
您目前所在的分支&lt;br /&gt;
目前的提交&lt;br /&gt;
需要更改的内容&lt;br /&gt;
新增的文件&lt;br /&gt;
修改的文件&lt;br /&gt;
删除的文件&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git commit ====&lt;br /&gt;
用于将暂存区我们保存的更改文件添加到本地仓库，并且会生成一条提交（commit）&lt;br /&gt;
&lt;br /&gt;
提交暂存区的更改到本地仓库&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -m &amp;quot;message&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[注] message 可以是你的备注信息&lt;br /&gt;
&lt;br /&gt;
提交暂存区中的指定文件到本地仓库&lt;br /&gt;
&lt;br /&gt;
如果你没有使用上述&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令暂存你的修改文件，可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -a&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
进行直接提交&lt;br /&gt;
&lt;br /&gt;
==== git checkout ====&lt;br /&gt;
&lt;br /&gt;
* 用于分支切换&lt;br /&gt;
&lt;br /&gt;
切换分支：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如在您的仓库中有这几个分支：&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-&amp;gt; master (Default)&lt;br /&gt;
   backup&lt;br /&gt;
   test&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
您当前处于 master 分支，如果想要切换到test分支，我们可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 用于检出文件&lt;br /&gt;
将指定的文件恢复到最新的提交状态，撤销你对其的更改&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout -- &amp;lt;file&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git push ====&lt;br /&gt;
用于将本地的分支版本上传到远程仓库并进行合并&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push &amp;lt;remote-host-name&amp;gt; &amp;lt;local-branch-name&amp;gt;:&amp;lt;remote-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
remote-host-name:远程主机名&lt;br /&gt;
&lt;br /&gt;
local-branch-name:本地分支名&lt;br /&gt;
&lt;br /&gt;
例如，当你的远程主机名为origin ，本地分支名为master，远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master:master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如，当你的rhost名为origin 本地分支名为master远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
本地和远程分支名相同，上述命令可以简写为：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当你的远程版本与本地版本有差异，无法直接push时，你可以使用--force 参数来进行强制推送&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push --force origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
--force 此处可以直接简单化为 -f &lt;br /&gt;
&lt;br /&gt;
如果你想要删除主机内的某个分支，你可以使用--delete参数&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin --delete &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git diff ====&lt;br /&gt;
用于比较当前工作区与上一个版本之间的差异&lt;br /&gt;
&lt;br /&gt;
例如：（此处仅做不恰当举例，Makefile不是这样乱写的）&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
diff --git a/makefile b/makefile&lt;br /&gt;
&lt;br /&gt;
index fbb8c85..d65c7eb 100644&lt;br /&gt;
&lt;br /&gt;
--- a/makefile&lt;br /&gt;
&lt;br /&gt;
+++ b/makefile&lt;br /&gt;
&lt;br /&gt;
@@ -1 +1,2 @@&lt;br /&gt;
&lt;br /&gt;
114514&lt;br /&gt;
&lt;br /&gt;
+1919180&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git log ====&lt;br /&gt;
用于查看提交的历史&lt;br /&gt;
&lt;br /&gt;
例如当你进行一次提交之后，执行 &amp;lt;code&amp;gt;git log&amp;lt;/code&amp;gt;终端会输出&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit 3a5b0d12f471418b13f2baf5e9e4c112a5e804a8 (HEAD -&amp;gt; master)&lt;br /&gt;
&lt;br /&gt;
Author: luluzzy &amp;lt;1054438588@qq.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Date:   Thu Feb 15 21:28:47 2024 +0800&lt;br /&gt;
&lt;br /&gt;
    initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这些输出分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit sha1 hash:   针对你这个提交的 commit id&lt;br /&gt;
Author: commit      作者名称   &amp;lt;you@example.com&amp;gt;&lt;br /&gt;
Date: commit        日期&lt;br /&gt;
commit:             名称&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
关于sha1_hash的介绍请看这里&amp;lt;ref&amp;gt;生成这个hash值，它是对那个commit是Git仓库中内容和头信息Header的一个校验和checksum。Linux kernel开创者和Git的开发者——Linus说，Git使用了sha1并非是为了安全性，而是为了数据的完整性；它可以保证，在很多年后，你重新checkout某个commit时，一定是它多年前的当时的状态，完全一摸一样，完全值得信任。在Git中，根据commit的sha1值40个十六进制数字进行了简单的划分目录，以前2位数字作为目录名，其下面是剩余38位数字组成的一个文件名&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当有多次提交之后，如果我们想要翻之前的提交历史，难免会因为终端输出的内容过多而难以查看翻阅&lt;br /&gt;
&lt;br /&gt;
此时我们可以使用&amp;lt;code&amp;gt;--online&amp;lt;/code&amp;gt;参数来简化输出，此时仅会输出: sha1哈希值 + commit的名称&lt;br /&gt;
&lt;br /&gt;
例如&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
347595d (HEAD -&amp;gt; master) modify makefile&lt;br /&gt;
&lt;br /&gt;
3a5b0d1 initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git cherry-pick ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
cherry-pick (遴选) 和它的名称一样，挑选一个我们需要的 commit 进行操作。它可以用于将在其他分支上的 commit 修改，移植到当前的分支。&lt;br /&gt;
&lt;br /&gt;
如果我们想在我们正在开发的版本上，添加一个其他版本中的功能代码。就可以使用 cherry-pick ，将这个功能相关的 commit 提取出来，合入该版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick &amp;lt;commit-id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
当我们执行完 &amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;操作之后，会自动生成一个&amp;lt;code&amp;gt;commit&amp;lt;/code&amp;gt;以及对应新的&amp;lt;code&amp;gt;commit-id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在顺利的情况下我们可以直接通过，但如果遇到代码等因为变量名，写法等不同的情况，&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;大概率会报错，此时我们需要进行报错处理。&lt;br /&gt;
&lt;br /&gt;
第一种方案是手动修改&lt;br /&gt;
&lt;br /&gt;
我们可以先使用&amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt;检查当前遴选时冲突的文件&lt;br /&gt;
&lt;br /&gt;
然后 &amp;lt;code&amp;gt;git checkout --ours filename&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
然后按照提交的修改内容进行手动修改&lt;br /&gt;
&lt;br /&gt;
随后使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令将文件重新加入暂存区&lt;br /&gt;
&lt;br /&gt;
再使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --continue&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
命令让 cherrypick 操作继续执行。&lt;br /&gt;
&lt;br /&gt;
第二种方案是直接退出&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;进程，一般适用于冲突文件实在太多了难以按照方案一处理的情况。&lt;br /&gt;
&lt;br /&gt;
需要注意的是，如果您当前正在遴选的提交在该分支已经存在也会冲突，在这种情况下，您需要解决冲突并手动解决问题。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --abort&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git fetch ====&lt;br /&gt;
git fetch 命令用于从远程获取仓库。&lt;br /&gt;
&lt;br /&gt;
==== git merge ====&lt;br /&gt;
&amp;lt;code&amp;gt;git merge&amp;lt;/code&amp;gt;是用来把分叉的提交历史放回到一起(合并)的方式。&lt;br /&gt;
&lt;br /&gt;
git merge命令用来将你之前使用git branch命令创建的分支以及在此分支上独立开发的内容整合为一个分支。&lt;br /&gt;
&lt;br /&gt;
本&lt;br /&gt;
&lt;br /&gt;
==== git pull ====&lt;br /&gt;
用于从远程获取代码并合并本地的版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull&amp;lt;/code&amp;gt;其实就是&amp;lt;code&amp;gt;git fetch&amp;lt;/code&amp;gt;和&amp;lt;code&amp;gt;git merge FETCH_HEAD&amp;lt;/code&amp;gt; 的简写。&lt;br /&gt;
&lt;br /&gt;
格式如下：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull &amp;lt;remote-host-name&amp;gt; &amp;lt;remote-branch-name&amp;gt;:&amp;lt;local-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git rebase ====&lt;br /&gt;
用于需要修改历史上某一项commit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git rebase -i HEAD~&amp;lt;commit number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
commit number就是从头部往前数的commit数量。执行后会弹出你在git config内配置的编辑器，若未配置则是默认，vim居多。然后就可以看见一堆commit前面有pick字样。可以将pick替换为你想要的操作。&lt;br /&gt;
有以下操作：&lt;br /&gt;
&lt;br /&gt;
1.edit，顾名思义编辑此commit，替换完保存后请修改内容，使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;或vscode，github desktop将修改文件添加到暂存区，之后命令行执行&amp;lt;code&amp;gt;git commit --amend&amp;lt;/code&amp;gt;这样commit就修改成了&lt;br /&gt;
&lt;br /&gt;
2.squash，合并几个提交，确认一个父提交，将要合并的commit，从下向上替换字符串，会从下向上合并(方位指的是&amp;lt;code&amp;gt;git rebase&amp;lt;/code&amp;gt;后弹出的编辑器)&lt;br /&gt;
&lt;br /&gt;
3.drop，需要移除的commit&lt;br /&gt;
&lt;br /&gt;
=== git subtree ===&lt;br /&gt;
子树，在Android开发中多用于Kernel侧更改，如跟踪audio模块等&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree add --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
如果需要更新远程库时&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git subtree pull --prefix=&amp;lt;目录&amp;gt; &amp;lt;仓库地址&amp;gt; &amp;lt;远程分支&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 参考资料： ====&lt;br /&gt;
[1] 百度百科 -- Git：&amp;lt;nowiki&amp;gt;https://baike.baidu.com/item/GIT/12647237?fr=ge_ala&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[2] 菜鸟教程 -- Git基本操作：&amp;lt;nowiki&amp;gt;https://www.runoob.com/git/git-basic-operations.html&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[3] CSDN -- git merge 使用简介: &amp;lt;nowiki&amp;gt;https://blog.csdn.net/All_In_gzx_cc/article/details/125482617&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=484</id>
		<title>Git使用教程</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=484"/>
		<updated>2024-02-16T11:42:39Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​添加换行&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Git的由来： ===&lt;br /&gt;
Git是一个开源的分布式版本控制系统，可以有效、高速地处理从很小到非常大的项目版本管理，也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper。&lt;br /&gt;
&lt;br /&gt;
=== 常见的代码托管平台： ===&lt;br /&gt;
[https://github.com Github]&lt;br /&gt;
&lt;br /&gt;
[https://gitlab.com Gitlab]&lt;br /&gt;
&lt;br /&gt;
[https://gitee.com Gitee]&lt;br /&gt;
&lt;br /&gt;
=== Git 常见命令: ===&lt;br /&gt;
&lt;br /&gt;
==== git init ====&lt;br /&gt;
在本地目录中初始化一个新的Git仓库&lt;br /&gt;
&lt;br /&gt;
==== git config ====&lt;br /&gt;
用于配置用户的信息以及其他设置,在使用git之前您必须完成以下步骤。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.name &amp;quot;your username&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.email &amp;quot;your email&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git clone ====&lt;br /&gt;
用于将远程仓库的代码克隆到本地，以下是命令中各个参数的含义：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;url&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆某个地址(url)的仓库，远程仓库的地址可以是本地的目录，也可以是例如github,giteee,gitlab一类的代码托管平台&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;--depth=&amp;lt;number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆仓库并且保留number条提交历史，number在此处即表达我们克隆的深度。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;-b &amp;lt;branch&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆指定分支下的仓库内容&lt;br /&gt;
&lt;br /&gt;
例如我们要克隆&amp;lt;code&amp;gt;LineageOS&amp;lt;/code&amp;gt;的内核源码，指定&amp;lt;code&amp;gt;lineage-21&amp;lt;/code&amp;gt;分支，且仅保留最近一个提交，则需要输入:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git clone -b lineage-21 &amp;lt;nowiki&amp;gt;https://github.com/LineageOS/android_kernel_xiaomi_sdm845&amp;lt;/nowiki&amp;gt; --depth=1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git add ====&lt;br /&gt;
添加某个文件，或者目录到暂存区，用于告诉git你需要将哪些文件的更改包含在下一次的提交(commit)之中添加一个或者多个文件到暂存区之中&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [file1] [file2]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加指定目录(文件)到暂存区，包括子目录：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [dir]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加当前目录下的所有文件到暂存区：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add .&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git status ====&lt;br /&gt;
查看当前仓库的状态，此时git会在你的终端输出以下内容&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;em style=&amp;quot;color: gray;&amp;quot;&amp;gt;此处演示为英文，如果您的git终端输出为中文也是同理的&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
On branch master&lt;br /&gt;
No commits yet&lt;br /&gt;
Changes to be committed:  &lt;br /&gt;
&lt;br /&gt;
(use “git rm --cached &amp;lt;file&amp;gt;...” to unstage)       &lt;br /&gt;
new file:   makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
输出内容分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
您目前所在的分支&lt;br /&gt;
目前的提交&lt;br /&gt;
需要更改的内容&lt;br /&gt;
新增的文件&lt;br /&gt;
修改的文件&lt;br /&gt;
删除的文件&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git commit ====&lt;br /&gt;
用于将暂存区我们保存的更改文件添加到本地仓库，并且会生成一条提交（commit）&lt;br /&gt;
&lt;br /&gt;
提交暂存区的更改到本地仓库&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -m &amp;quot;message&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[注] message 可以是你的备注信息&lt;br /&gt;
&lt;br /&gt;
提交暂存区中的指定文件到本地仓库&lt;br /&gt;
&lt;br /&gt;
如果你没有使用上述&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令暂存你的修改文件，可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -a&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
进行直接提交&lt;br /&gt;
&lt;br /&gt;
==== git checkout ====&lt;br /&gt;
&lt;br /&gt;
* 用于分支切换&lt;br /&gt;
&lt;br /&gt;
切换分支：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如在您的仓库中有这几个分支：&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-&amp;gt; master (Default)&lt;br /&gt;
   backup&lt;br /&gt;
   test&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
您当前处于 master 分支，如果想要切换到test分支，我们可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 用于检出文件&lt;br /&gt;
将指定的文件恢复到最新的提交状态，撤销你对其的更改&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout -- &amp;lt;file&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git push ====&lt;br /&gt;
用于将本地的分支版本上传到远程仓库并进行合并&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push &amp;lt;remote-host-name&amp;gt; &amp;lt;local-branch-name&amp;gt;:&amp;lt;remote-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
remote-host-name:远程主机名&lt;br /&gt;
&lt;br /&gt;
local-branch-name:本地分支名&lt;br /&gt;
&lt;br /&gt;
例如，当你的远程主机名为origin ，本地分支名为master，远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master:master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如，当你的rhost名为origin 本地分支名为master远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
本地和远程分支名相同，上述命令可以简写为：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当你的远程版本与本地版本有差异，无法直接push时，你可以使用--force 参数来进行强制推送&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push --force origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
--force 此处可以直接简单化为 -f &lt;br /&gt;
&lt;br /&gt;
如果你想要删除主机内的某个分支，你可以使用--delete参数&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin --delete &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git diff ====&lt;br /&gt;
用于比较当前工作区与上一个版本之间的差异&lt;br /&gt;
&lt;br /&gt;
例如：（此处仅做不恰当举例，Makefile不是这样乱写的）&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
diff --git a/makefile b/makefile&lt;br /&gt;
&lt;br /&gt;
index fbb8c85..d65c7eb 100644&lt;br /&gt;
&lt;br /&gt;
--- a/makefile&lt;br /&gt;
&lt;br /&gt;
+++ b/makefile&lt;br /&gt;
&lt;br /&gt;
@@ -1 +1,2 @@&lt;br /&gt;
&lt;br /&gt;
114514&lt;br /&gt;
&lt;br /&gt;
+1919180&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git log ====&lt;br /&gt;
用于查看提交的历史&lt;br /&gt;
&lt;br /&gt;
例如当你进行一次提交之后，执行 &amp;lt;code&amp;gt;git log&amp;lt;/code&amp;gt;终端会输出&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit 3a5b0d12f471418b13f2baf5e9e4c112a5e804a8 (HEAD -&amp;gt; master)&lt;br /&gt;
&lt;br /&gt;
Author: luluzzy &amp;lt;1054438588@qq.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Date:   Thu Feb 15 21:28:47 2024 +0800&lt;br /&gt;
&lt;br /&gt;
    initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这些输出分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit sha1 hash:   针对你这个提交的 commit id&lt;br /&gt;
Author: commit      作者名称   &amp;lt;you@example.com&amp;gt;&lt;br /&gt;
Date: commit        日期&lt;br /&gt;
commit:             名称&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
关于sha1_hash的介绍请看这里&amp;lt;ref&amp;gt;生成这个hash值，它是对那个commit是Git仓库中内容和头信息Header的一个校验和checksum。Linux kernel开创者和Git的开发者——Linus说，Git使用了sha1并非是为了安全性，而是为了数据的完整性；它可以保证，在很多年后，你重新checkout某个commit时，一定是它多年前的当时的状态，完全一摸一样，完全值得信任。在Git中，根据commit的sha1值40个十六进制数字进行了简单的划分目录，以前2位数字作为目录名，其下面是剩余38位数字组成的一个文件名&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当有多次提交之后，如果我们想要翻之前的提交历史，难免会因为终端输出的内容过多而难以查看翻阅&lt;br /&gt;
&lt;br /&gt;
此时我们可以使用&amp;lt;code&amp;gt;--online&amp;lt;/code&amp;gt;参数来简化输出，此时仅会输出: sha1哈希值 + commit的名称&lt;br /&gt;
&lt;br /&gt;
例如&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
347595d (HEAD -&amp;gt; master) modify makefile&lt;br /&gt;
&lt;br /&gt;
3a5b0d1 initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git cherry-pick ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
cherry-pick (遴选) 和它的名称一样，挑选一个我们需要的 commit 进行操作。它可以用于将在其他分支上的 commit 修改，移植到当前的分支。&lt;br /&gt;
&lt;br /&gt;
如果我们想在我们正在开发的版本上，添加一个其他版本中的功能代码。就可以使用 cherry-pick ，将这个功能相关的 commit 提取出来，合入该版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick &amp;lt;commit-id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
当我们执行完 &amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;操作之后，会自动生成一个&amp;lt;code&amp;gt;commit&amp;lt;/code&amp;gt;以及对应新的&amp;lt;code&amp;gt;commit-id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在顺利的情况下我们可以直接通过，但如果遇到代码等因为变量名，写法等不同的情况，&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;大概率会报错，此时我们需要进行报错处理。&lt;br /&gt;
&lt;br /&gt;
第一种方案是手动修改&lt;br /&gt;
&lt;br /&gt;
我们可以先使用&amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt;检查当前遴选时冲突的文件&lt;br /&gt;
&lt;br /&gt;
然后 &amp;lt;code&amp;gt;git checkout --ours filename&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
然后按照提交的修改内容进行手动修改&lt;br /&gt;
&lt;br /&gt;
随后使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令将文件重新加入暂存区&lt;br /&gt;
&lt;br /&gt;
再使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --continue&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
命令让 cherrypick 操作继续执行。&lt;br /&gt;
&lt;br /&gt;
第二种方案是直接退出&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;进程，一般适用于冲突文件实在太多了难以按照方案一处理的情况。&lt;br /&gt;
&lt;br /&gt;
需要注意的是，如果您当前正在遴选的提交在该分支已经存在也会冲突，在这种情况下，您需要解决冲突并手动解决问题。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --abort&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git fetch ====&lt;br /&gt;
git fetch 命令用于从远程获取仓库。&lt;br /&gt;
&lt;br /&gt;
==== git merge ====&lt;br /&gt;
&amp;lt;code&amp;gt;git merge&amp;lt;/code&amp;gt;是用来把分叉的提交历史放回到一起(合并)的方式。&lt;br /&gt;
&lt;br /&gt;
git merge命令用来将你之前使用git branch命令创建的分支以及在此分支上独立开发的内容整合为一个分支。&lt;br /&gt;
&lt;br /&gt;
本&lt;br /&gt;
&lt;br /&gt;
==== git pull ====&lt;br /&gt;
用于从远程获取代码并合并本地的版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull&amp;lt;/code&amp;gt;其实就是&amp;lt;code&amp;gt;git fetch&amp;lt;/code&amp;gt;和&amp;lt;code&amp;gt;git merge FETCH_HEAD&amp;lt;/code&amp;gt; 的简写。&lt;br /&gt;
&lt;br /&gt;
格式如下：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull &amp;lt;remote-host-name&amp;gt; &amp;lt;remote-branch-name&amp;gt;:&amp;lt;local-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git rebase ====&lt;br /&gt;
用于需要修改历史上某一项commit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git rebase -i HEAD~&amp;lt;commit number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
commit number就是从头部往前数的commit数量。执行后会弹出你在git config内配置的编辑器，若未配置则是默认，vim居多。然后就可以看见一堆commit前面有pick字样。可以将pick替换为你想要的操作。&lt;br /&gt;
有以下操作：&lt;br /&gt;
&lt;br /&gt;
1.edit，顾名思义编辑此commit，替换完保存后请修改内容，使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;或vscode，github desktop将修改文件添加到暂存区，之后命令行执行&amp;lt;code&amp;gt;git commit --amend&amp;lt;/code&amp;gt;这样commit就修改成了&lt;br /&gt;
&lt;br /&gt;
2.squash，合并几个提交，确认一个父提交，将要合并的commit，从下向上替换字符串，会从下向上合并(方位指的是&amp;lt;code&amp;gt;git rebase&amp;lt;/code&amp;gt;后弹出的编辑器)&lt;br /&gt;
&lt;br /&gt;
3.drop，需要移除的commit&lt;br /&gt;
&lt;br /&gt;
==== 参考资料： ====&lt;br /&gt;
[1] 百度百科 -- Git：&amp;lt;nowiki&amp;gt;https://baike.baidu.com/item/GIT/12647237?fr=ge_ala&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[2] 菜鸟教程 -- Git基本操作：&amp;lt;nowiki&amp;gt;https://www.runoob.com/git/git-basic-operations.html&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[3] CSDN -- git merge 使用简介: &amp;lt;nowiki&amp;gt;https://blog.csdn.net/All_In_gzx_cc/article/details/125482617&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=483</id>
		<title>Git使用教程</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=Git%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B&amp;diff=483"/>
		<updated>2024-02-16T11:42:10Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​添加git rebase&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Git的由来： ===&lt;br /&gt;
Git是一个开源的分布式版本控制系统，可以有效、高速地处理从很小到非常大的项目版本管理，也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper。&lt;br /&gt;
&lt;br /&gt;
=== 常见的代码托管平台： ===&lt;br /&gt;
[https://github.com Github]&lt;br /&gt;
&lt;br /&gt;
[https://gitlab.com Gitlab]&lt;br /&gt;
&lt;br /&gt;
[https://gitee.com Gitee]&lt;br /&gt;
&lt;br /&gt;
=== Git 常见命令: ===&lt;br /&gt;
&lt;br /&gt;
==== git init ====&lt;br /&gt;
在本地目录中初始化一个新的Git仓库&lt;br /&gt;
&lt;br /&gt;
==== git config ====&lt;br /&gt;
用于配置用户的信息以及其他设置,在使用git之前您必须完成以下步骤。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.name &amp;quot;your username&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git config --global user.email &amp;quot;your email&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git clone ====&lt;br /&gt;
用于将远程仓库的代码克隆到本地，以下是命令中各个参数的含义：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;url&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆某个地址(url)的仓库，远程仓库的地址可以是本地的目录，也可以是例如github,giteee,gitlab一类的代码托管平台&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;--depth=&amp;lt;number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆仓库并且保留number条提交历史，number在此处即表达我们克隆的深度。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;-b &amp;lt;branch&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
克隆指定分支下的仓库内容&lt;br /&gt;
&lt;br /&gt;
例如我们要克隆&amp;lt;code&amp;gt;LineageOS&amp;lt;/code&amp;gt;的内核源码，指定&amp;lt;code&amp;gt;lineage-21&amp;lt;/code&amp;gt;分支，且仅保留最近一个提交，则需要输入:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git clone -b lineage-21 &amp;lt;nowiki&amp;gt;https://github.com/LineageOS/android_kernel_xiaomi_sdm845&amp;lt;/nowiki&amp;gt; --depth=1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git add ====&lt;br /&gt;
添加某个文件，或者目录到暂存区，用于告诉git你需要将哪些文件的更改包含在下一次的提交(commit)之中添加一个或者多个文件到暂存区之中&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [file1] [file2]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加指定目录(文件)到暂存区，包括子目录：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add [dir]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
添加当前目录下的所有文件到暂存区：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git add .&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git status ====&lt;br /&gt;
查看当前仓库的状态，此时git会在你的终端输出以下内容&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;em style=&amp;quot;color: gray;&amp;quot;&amp;gt;此处演示为英文，如果您的git终端输出为中文也是同理的&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
On branch master&lt;br /&gt;
No commits yet&lt;br /&gt;
Changes to be committed:  &lt;br /&gt;
&lt;br /&gt;
(use “git rm --cached &amp;lt;file&amp;gt;...” to unstage)       &lt;br /&gt;
new file:   makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
输出内容分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
您目前所在的分支&lt;br /&gt;
目前的提交&lt;br /&gt;
需要更改的内容&lt;br /&gt;
新增的文件&lt;br /&gt;
修改的文件&lt;br /&gt;
删除的文件&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git commit ====&lt;br /&gt;
用于将暂存区我们保存的更改文件添加到本地仓库，并且会生成一条提交（commit）&lt;br /&gt;
&lt;br /&gt;
提交暂存区的更改到本地仓库&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -m &amp;quot;message&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[注] message 可以是你的备注信息&lt;br /&gt;
&lt;br /&gt;
提交暂存区中的指定文件到本地仓库&lt;br /&gt;
&lt;br /&gt;
如果你没有使用上述&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令暂存你的修改文件，可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git commit -a&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
进行直接提交&lt;br /&gt;
&lt;br /&gt;
==== git checkout ====&lt;br /&gt;
&lt;br /&gt;
* 用于分支切换&lt;br /&gt;
&lt;br /&gt;
切换分支：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如在您的仓库中有这几个分支：&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-&amp;gt; master (Default)&lt;br /&gt;
   backup&lt;br /&gt;
   test&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
您当前处于 master 分支，如果想要切换到test分支，我们可以使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout test&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* 用于检出文件&lt;br /&gt;
将指定的文件恢复到最新的提交状态，撤销你对其的更改&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git checkout -- &amp;lt;file&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git push ====&lt;br /&gt;
用于将本地的分支版本上传到远程仓库并进行合并&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push &amp;lt;remote-host-name&amp;gt; &amp;lt;local-branch-name&amp;gt;:&amp;lt;remote-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
remote-host-name:远程主机名&lt;br /&gt;
&lt;br /&gt;
local-branch-name:本地分支名&lt;br /&gt;
&lt;br /&gt;
例如，当你的远程主机名为origin ，本地分支名为master，远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master:master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
例如，当你的rhost名为origin 本地分支名为master远程分支名为master时：&lt;br /&gt;
&lt;br /&gt;
本地和远程分支名相同，上述命令可以简写为：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当你的远程版本与本地版本有差异，无法直接push时，你可以使用--force 参数来进行强制推送&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push --force origin master&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
--force 此处可以直接简单化为 -f &lt;br /&gt;
&lt;br /&gt;
如果你想要删除主机内的某个分支，你可以使用--delete参数&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git push origin --delete &amp;lt;branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git diff ====&lt;br /&gt;
用于比较当前工作区与上一个版本之间的差异&lt;br /&gt;
&lt;br /&gt;
例如：（此处仅做不恰当举例，Makefile不是这样乱写的）&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
diff --git a/makefile b/makefile&lt;br /&gt;
&lt;br /&gt;
index fbb8c85..d65c7eb 100644&lt;br /&gt;
&lt;br /&gt;
--- a/makefile&lt;br /&gt;
&lt;br /&gt;
+++ b/makefile&lt;br /&gt;
&lt;br /&gt;
@@ -1 +1,2 @@&lt;br /&gt;
&lt;br /&gt;
114514&lt;br /&gt;
&lt;br /&gt;
+1919180&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git log ====&lt;br /&gt;
用于查看提交的历史&lt;br /&gt;
&lt;br /&gt;
例如当你进行一次提交之后，执行 &amp;lt;code&amp;gt;git log&amp;lt;/code&amp;gt;终端会输出&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit 3a5b0d12f471418b13f2baf5e9e4c112a5e804a8 (HEAD -&amp;gt; master)&lt;br /&gt;
&lt;br /&gt;
Author: luluzzy &amp;lt;1054438588@qq.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Date:   Thu Feb 15 21:28:47 2024 +0800&lt;br /&gt;
&lt;br /&gt;
    initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
这些输出分别为&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
commit sha1 hash:   针对你这个提交的 commit id&lt;br /&gt;
Author: commit      作者名称   &amp;lt;you@example.com&amp;gt;&lt;br /&gt;
Date: commit        日期&lt;br /&gt;
commit:             名称&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
关于sha1_hash的介绍请看这里&amp;lt;ref&amp;gt;生成这个hash值，它是对那个commit是Git仓库中内容和头信息Header的一个校验和checksum。Linux kernel开创者和Git的开发者——Linus说，Git使用了sha1并非是为了安全性，而是为了数据的完整性；它可以保证，在很多年后，你重新checkout某个commit时，一定是它多年前的当时的状态，完全一摸一样，完全值得信任。在Git中，根据commit的sha1值40个十六进制数字进行了简单的划分目录，以前2位数字作为目录名，其下面是剩余38位数字组成的一个文件名&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
当有多次提交之后，如果我们想要翻之前的提交历史，难免会因为终端输出的内容过多而难以查看翻阅&lt;br /&gt;
&lt;br /&gt;
此时我们可以使用&amp;lt;code&amp;gt;--online&amp;lt;/code&amp;gt;参数来简化输出，此时仅会输出: sha1哈希值 + commit的名称&lt;br /&gt;
&lt;br /&gt;
例如&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
347595d (HEAD -&amp;gt; master) modify makefile&lt;br /&gt;
&lt;br /&gt;
3a5b0d1 initial commit: add makefile&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git cherry-pick ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
cherry-pick (遴选) 和它的名称一样，挑选一个我们需要的 commit 进行操作。它可以用于将在其他分支上的 commit 修改，移植到当前的分支。&lt;br /&gt;
&lt;br /&gt;
如果我们想在我们正在开发的版本上，添加一个其他版本中的功能代码。就可以使用 cherry-pick ，将这个功能相关的 commit 提取出来，合入该版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick &amp;lt;commit-id&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
当我们执行完 &amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;操作之后，会自动生成一个&amp;lt;code&amp;gt;commit&amp;lt;/code&amp;gt;以及对应新的&amp;lt;code&amp;gt;commit-id&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
在顺利的情况下我们可以直接通过，但如果遇到代码等因为变量名，写法等不同的情况，&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;大概率会报错，此时我们需要进行报错处理。&lt;br /&gt;
&lt;br /&gt;
第一种方案是手动修改&lt;br /&gt;
&lt;br /&gt;
我们可以先使用&amp;lt;code&amp;gt;git status&amp;lt;/code&amp;gt;检查当前遴选时冲突的文件&lt;br /&gt;
&lt;br /&gt;
然后 &amp;lt;code&amp;gt;git checkout --ours filename&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
然后按照提交的修改内容进行手动修改&lt;br /&gt;
&lt;br /&gt;
随后使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;命令将文件重新加入暂存区&lt;br /&gt;
&lt;br /&gt;
再使用&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --continue&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
命令让 cherrypick 操作继续执行。&lt;br /&gt;
&lt;br /&gt;
第二种方案是直接退出&amp;lt;code&amp;gt;cherry-pick&amp;lt;/code&amp;gt;进程，一般适用于冲突文件实在太多了难以按照方案一处理的情况。&lt;br /&gt;
&lt;br /&gt;
需要注意的是，如果您当前正在遴选的提交在该分支已经存在也会冲突，在这种情况下，您需要解决冲突并手动解决问题。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git cherry-pick --abort&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git fetch ====&lt;br /&gt;
git fetch 命令用于从远程获取仓库。&lt;br /&gt;
&lt;br /&gt;
==== git merge ====&lt;br /&gt;
&amp;lt;code&amp;gt;git merge&amp;lt;/code&amp;gt;是用来把分叉的提交历史放回到一起(合并)的方式。&lt;br /&gt;
&lt;br /&gt;
git merge命令用来将你之前使用git branch命令创建的分支以及在此分支上独立开发的内容整合为一个分支。&lt;br /&gt;
&lt;br /&gt;
本&lt;br /&gt;
&lt;br /&gt;
==== git pull ====&lt;br /&gt;
用于从远程获取代码并合并本地的版本。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull&amp;lt;/code&amp;gt;其实就是&amp;lt;code&amp;gt;git fetch&amp;lt;/code&amp;gt;和&amp;lt;code&amp;gt;git merge FETCH_HEAD&amp;lt;/code&amp;gt; 的简写。&lt;br /&gt;
&lt;br /&gt;
格式如下：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git pull &amp;lt;remote-host-name&amp;gt; &amp;lt;remote-branch-name&amp;gt;:&amp;lt;local-branch-name&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== git rebase ====&lt;br /&gt;
用于需要修改历史上某一项commit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;git rebase -i HEAD~&amp;lt;commit number&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
commit number就是从头部往前数的commit数量。执行后会弹出你在git config内配置的编辑器，若未配置则是默认，vim居多。然后就可以看见一堆commit前面有pick字样。可以将pick替换为你想要的操作。&lt;br /&gt;
有以下操作：&lt;br /&gt;
&lt;br /&gt;
1.edit，顾名思义编辑此commit，替换完保存后请修改内容，使用&amp;lt;code&amp;gt;git add&amp;lt;/code&amp;gt;或vscode，github desktop将修改文件添加到暂存区，之后命令行执行&amp;lt;code&amp;gt;git commit --amend&amp;lt;/code&amp;gt;这样commit就修改成了&lt;br /&gt;
2.squash，合并几个提交，确认一个父提交，将要合并的commit，从下向上替换字符串，会从下向上合并(方位指的是&amp;lt;code&amp;gt;git rebase&amp;lt;/code&amp;gt;后弹出的编辑器)&lt;br /&gt;
3.drop，需要移除的commit&lt;br /&gt;
&lt;br /&gt;
==== 参考资料： ====&lt;br /&gt;
[1] 百度百科 -- Git：&amp;lt;nowiki&amp;gt;https://baike.baidu.com/item/GIT/12647237?fr=ge_ala&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[2] 菜鸟教程 -- Git基本操作：&amp;lt;nowiki&amp;gt;https://www.runoob.com/git/git-basic-operations.html&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[3] CSDN -- git merge 使用简介: &amp;lt;nowiki&amp;gt;https://blog.csdn.net/All_In_gzx_cc/article/details/125482617&amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=Super_Empty&amp;diff=480</id>
		<title>Super Empty</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=Super_Empty&amp;diff=480"/>
		<updated>2024-02-16T11:27:22Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Super empty =&lt;br /&gt;
&lt;br /&gt;
== 简介 ==&lt;br /&gt;
它是某个老设备改造动态分区后的产物，是一个定义了改造动态分区信息的空镜像，由设备维护者提供刷入。&lt;br /&gt;
其中定义了维护者定义的设备自身分区和分区大小，将它们合并成一个大的“super”供刷入第三方ROM使用，甚至可以让老旧设备运行DSU。&lt;br /&gt;
它的意义远不止类原生，对PT(Project Treble)也有帮助，有经验的维护者可以通过改造动态分区的方式让用户无需扩容即可体验深度定制UI&lt;br /&gt;
&lt;br /&gt;
== 为什么会有它？ ==&lt;br /&gt;
因为部分老旧的机型空间分配不均匀，vendor甚至和system一样大。随着Android版本的迭代，增加的新功能越来越多，对系统空间占用也越来越高，所以部分设备需要通过这种方式改造成动态分区。&lt;br /&gt;
&lt;br /&gt;
== 使用方法 ==&lt;br /&gt;
以我个人维护的小米6X(wayne)为例&lt;br /&gt;
1.设备重启至fastboot&lt;br /&gt;
&lt;br /&gt;
2.连接电脑&lt;br /&gt;
&lt;br /&gt;
3.准备最新版本的adb工具包和维护者提供的super_empty.img和ROM包&lt;br /&gt;
&lt;br /&gt;
4.打开命令行进入工具包目录，输入fastboot wipe-super super_empty.img的绝对路径&lt;br /&gt;
&lt;br /&gt;
5.刷写完毕后继续刷入维护者提供的Recovery，fastboot flash recovery recovery.img的绝对路径&lt;br /&gt;
&lt;br /&gt;
6.重启设备至recovery&lt;br /&gt;
&lt;br /&gt;
7.选择格式化data(format data)&lt;br /&gt;
&lt;br /&gt;
8.连接电脑，使用adb sideload刷入ROM，adb sideload ROM包绝对路径&lt;br /&gt;
&lt;br /&gt;
== 对开发者的一些帮助 ==&lt;br /&gt;
[https://github.com/jjpprrrr/device%20xiaomi%20sdm845-common/commits/thirteen 改造动态分区的commit(2022年9月22日)]&lt;br /&gt;
&lt;br /&gt;
对于在Mac上正常刷写super_empty在win或linux下不能正常刷写的情况，请检查device tree内定义的数值是否百分之一百匹配。&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
	<entry>
		<id>https://wiki.uotan.cn/index.php?title=Super_Empty&amp;diff=479</id>
		<title>Super Empty</title>
		<link rel="alternate" type="text/html" href="https://wiki.uotan.cn/index.php?title=Super_Empty&amp;diff=479"/>
		<updated>2024-02-16T11:26:02Z</updated>

		<summary type="html">&lt;p&gt;XiaoleGun：​创建页面，内容为“# Super empty  ## 简介 它是某个老设备改造动态分区后的产物，是一个定义了改造动态分区信息的空镜像，由设备维护者提供刷入。 其中定义了维护者定义的设备自身分区和分区大小，将它们合并成一个大的“super”供刷入第三方ROM使用，甚至可以让老旧设备运行DSU。 它的意义远不止类原生，对PT(Project Treble)也有帮助，有经验的维护者可以通过改造动态…”&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;# Super empty&lt;br /&gt;
&lt;br /&gt;
## 简介&lt;br /&gt;
它是某个老设备改造动态分区后的产物，是一个定义了改造动态分区信息的空镜像，由设备维护者提供刷入。&lt;br /&gt;
其中定义了维护者定义的设备自身分区和分区大小，将它们合并成一个大的“super”供刷入第三方ROM使用，甚至可以让老旧设备运行DSU。&lt;br /&gt;
它的意义远不止类原生，对PT(Project Treble)也有帮助，有经验的维护者可以通过改造动态分区的方式让用户无需扩容即可体验深度定制UI&lt;br /&gt;
&lt;br /&gt;
## 为什么会有它？&lt;br /&gt;
因为部分老旧的机型空间分配不均匀，vendor甚至和system一样大。随着Android版本的迭代，增加的新功能越来越多，对系统空间占用也越来越高，所以部分设备需要通过这种方式改造成动态分区。&lt;br /&gt;
&lt;br /&gt;
## 使用方法&lt;br /&gt;
以我个人维护的小米6X(wayne)为例&lt;br /&gt;
1.设备重启至fastboot&lt;br /&gt;
&lt;br /&gt;
2.连接电脑&lt;br /&gt;
&lt;br /&gt;
3.准备最新版本的adb工具包和维护者提供的super_empty.img和ROM包&lt;br /&gt;
&lt;br /&gt;
4.打开命令行进入工具包目录，输入fastboot wipe-super super_empty.img的绝对路径&lt;br /&gt;
&lt;br /&gt;
5.刷写完毕后继续刷入维护者提供的Recovery，fastboot flash recovery recovery.img的绝对路径&lt;br /&gt;
&lt;br /&gt;
6.重启设备至recovery&lt;br /&gt;
&lt;br /&gt;
7.选择格式化data(format data)&lt;br /&gt;
&lt;br /&gt;
8.连接电脑，使用adb sideload刷入ROM，adb sideload ROM包绝对路径&lt;br /&gt;
&lt;br /&gt;
## 对开发者的一些帮助&lt;br /&gt;
[https://github.com/jjpprrrr/device%20xiaomi%20sdm845-common/commits/thirteen 改造动态分区的commit(2022年9月22日)]&lt;br /&gt;
&lt;br /&gt;
对于在Mac上正常刷写super_empty在win或linux下不能正常刷写的情况，请检查device tree内定义的数值是否百分之一百匹配。&lt;/div&gt;</summary>
		<author><name>XiaoleGun</name></author>
	</entry>
</feed>