安卓源代码和仓库 - 获取代码时到底发生了什么

27

我曾经遇到很多关于使用repo获取Android源代码的最小方面或有关repo的非常广泛的定义的简短问题,因此在使用repo时并不真正理解发生了什么。我正在按照Android源网站上的指示进行操作。我在我的repodir中执行所有操作,因此所有文件的提及都是相对于此目录。

初始化和同步repo:

repo init -u https://android.googlesource.com/platform/manifest
repo sync

完成后,我的文件夹中充满了安卓类型的文件夹(bionicbootable等等),还有一个隐藏的.repo文件夹。值得注意的是,有一个名为ics-mr1的文件夹与特定版本相关,并且它包含我repodir里大部分相同的文件夹。

拉取特定的分支:

repo init -u https://android.googlesource.com/platform/manifest -b gingerbread
repo sync

这个过程相对较快,我看到的主要变化是现在有一个名为gingerbread的文件夹(所有原始文件夹似乎仍然存在)。

现在我尝试这个操作,但需要很长时间:

repo init -u https://android.googlesource.com/platform/manifest -b android_4.2.2_r1
repo sync

之后,它仍然包含相同的 gingerbreadics-mr1,以及一些新的随机文件夹(例如 abi),但没有任何看起来是那个新版本的东西。

问题

从这个结果来看,我真的不明白我的操作究竟在做什么,以及如何实现我想要的结果。

我该如何获得整个源代码库 master 的本地版本,并正确地在分支之间进行更改?目前的方式似乎是错误的,因为分支更改后剩下的文件似乎是不合理的。

此外,是否有有效的方法可以同时拥有多个分支的本地副本,以便我可以比较每个分支的组件(显然不需要每次都重新下载它们)?

我在提出这些问题时存在理解上的巨大漏洞(我未能找到清晰一致的信息),因此任何关于答案额外的信息都将对理解实际正在发生的事情非常有价值。

1个回答

32

repo init

由于你显得相当精明,你知道 repo 只是一个 Python 脚本吧?你可以阅读它以了解其工作原理。虽然我没有完整地阅读过它,但基本上它包装了 git 并提供了在多个 git 存储库之间工作的支持。其主要思想是有一个清单文件,指定了不同版本的 Android 的需求。当你使用 repo init 带参数时,它会查看需要克隆哪些 git 存储库,你已经同步了哪些 git 存储库以及一旦获取了合适的存储库,需要获取哪些分支。然后它处理将所有受其管理的存储库保持在适当的分支上。把 repo 视为标准 git 工作流程的另一层(我假设你熟悉)。

第一次使用 repo 时,要获取主分支,你需要使用

repo init -u https://android.googlesource.com/platform/manifest

接下来,您需要从服务器同步所有文件:

repo sync

这将把您当前的工作目录更新到您下载的清单主版本所指定的确切状态。 如果要检出不同版本的AOSP,则可以使用:

repo init -b version_name

这会将清单更新为包含有关所需Android版本的信息的清单(也称为分支)。

别忘了同步。

要切换到另一个清单分支,可以在现有客户端中使用 repo init -b otherbranch。 但是,由于这只更新清单,因此需要随后运行 repo sync(或repo sync -d)才能更新工作目录文件。

你可能觉得正在经历的行为很奇怪,因为你可能不习惯使用容易覆盖本地状态的系统。 在使用 git 时,你不应该在相同的目录下多次进行init。 另一种选择是为每个项目创建新目录。 .repo 目录的目的是存储与当前 repo 设置相关的所有信息(也像 .git 目录一样)。 实际上,运行repo init会执行以下许多操作:

  1. 从指定的URL下载清单。
  2. 尝试打开或创建 .repo 目录。
  3. 确保已设置好 GPG 密钥。
  4. 克隆指定的分支(如果未指定,则默认为 REPO_REV)。
  5. 验证它。
  6. 为每个项目检出适当的分支。

我认为克隆操作会覆盖 .repo 文件夹中的信息。 第一条命令运行后需要很长时间的原因是:

repo init -u https://android.googlesource.com/platform/manifest
repo sync

这是因为它需要下载许多千兆字节的信息。现在,从master分支转到gingerbread仓库只需删除大约68个提交,这可以非常快速地完成。

$ repo init -u https://android.googlesource.com/platform/manifest -b gingerbread
$ repo sync
...
.repo/manifests/: discarding 68 commits
...

重新切换至 android_4.2.2_r1 意味着 repo 必须重新下载那些提交所需的所有信息,并更新所有被引用项目上的当前分支。这将需要很长时间,repo 正在以处理时间来交换磁盘使用。

真的吗?

现在,这提出了一个问题:如果您想同时比较两个 repo 分支怎么办?这很困难,因为当您执行 repo init && repo sync 后,您会失去之前正在查看的旧信息。答案是复制相关信息,然后再次执行 repo init && repo sync。这将变得非常麻烦-幸运的是,如果您有足够的磁盘空间,repo 提供了一种加快此过程的方法。

使事情更快的一种策略是在 workspace/master 目录中创建一个本地镜像。然后,在一个新目录中从镜像中检出您想要的分支,例如 workspace/gingerbread。现在,您可以通过转到适当的目录来轻松切换分支。

在本地镜像 AOSP:

cd workspace
mkdir master && cd master
repo init --mirror

执行此命令将使存储库在本地机器上镜像远程服务器。然后,当您想要切换到一个新分支时,您可以:

mkdir ../gingerbread && cd ../gingerbread
repo init -b version_name --reference=../master

结果是一个工作空间,其中包含一个包含镜像的文件夹和一个包含参考镜像尽可能的姜饼分支的文件夹。
另一个选项是简单地初始化和同步您想要的分支,然后将文件夹复制到另一个位置,并使用该副本再次初始化和同步。Repo 应该只下载丢失的部分。
其他 Repo 用途:除了 init 外,repo 还提供了对传递命令(如 branch)到给定清单中所有不同 git 存储库的支持,这样在处理代码时就无需担心。它还通过使将本地更改提交到 Gerrit 代码审查系统变得容易来促进协作。我不确定将 AOSP 分区为多个 git 存储库的官方原因是什么,但我想这是为了管理版本控制的扩展性问题以及保持项目的稳健和容错性(如果有人破坏一个 git 存储库,它不会摧毁整个 AOSP)。此外,有必要提供一种供供应商回馈源代码并让他们管理自己的 git 存储库的方式,这些存储库可以简单地与/注册到一个总体清单中,这很合理。我没有按行回答你的问题,但希望我提供了一些背景。

1
太棒了,伙计。非常感谢,这正是我在寻找的。我原本认为自己所做的不是正确的概念,现在有了这些信息,我知道了确切的原因。如果你能点赞两次就好了... - btalb
1
@BT 在进一步探索后,我更新了我的回答。我之前的措辞和理解并不完全准确。 - dcow
更好的是,尤其是关于镜像人的部分。我已经断断续续地尝试着理解并让repo工作了一年多,因为找不到任何有用的信息而放弃。这个答案单独就提供给我比我在那段时间里找到的所有信息都更加清晰和有价值的信息和理解。我会尝试解决关闭问题的混乱。 - btalb
1
@BT 我在 Meta 上问过了(http://meta.stackexchange.com/questions/175727/question-about-googles-repo-tool-filed-as-off-topic)。请参考。 - dcow
1
repo-script 相对于 git-submodules 有哪些优势?这是在进行比较吗? - CAMOBAP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接