This page contains detailed information about west’s multiple repository model,
manifest files, and the
west manifest command. For API documentation on the
west.manifest module, see west.manifest. For a more general
introduction and command overview, see Multiple Repository Management.
West’s view of the repositories in a west workspace, and their history, looks like the following figure (though some parts of this example are specific to upstream Zephyr’s use of west):
The history of the manifest repository is the line of Git commits which is “floating” on top of the gray plane. Parent commits point to child commits using solid arrows. The plane below contains the Git commit history of the repositories in the workspace, with each project repository boxed in by a rectangle. Parent/child commit relationships in each repository are also shown with solid arrows.
The commits in the manifest repository (again, for upstream Zephyr this is the zephyr repository itself) each have a manifest file. The manifest file in each commit specifies the corresponding commits which it expects in each of the project repositories. This relationship is shown using dotted line arrows in the diagram. Each dotted line arrow points from a commit in the manifest repository to a corresponding commit in a project repository.
Notice the following important details:
Projects can be added (like
P1between manifest repository commits
E) and removed (
P2between the same manifest repository commits)
Project and manifest repository histories don’t have to move forwards or backwards together:
P2stays the same from
A → B, as do
F → G.
P3moves forward from
A → B.
P3moves backward from
C → D.
One use for moving backward in project history is to “revert” a regression by going back to a revision before it was introduced.
Project repository commits can be “skipped”:
P3moves forward multiple commits in its history from
B → C.
In the above diagram, no project repository has two revisions “at the same time”: every manifest file refers to exactly one commit in the projects it cares about. This can be relaxed by using a branch name as a manifest revision, at the cost of being able to bisect manifest repository history.
A west manifest is a YAML file named
west.yml. Manifests have a
manifest section with some subsections, like this:
manifest: defaults: # default project attributes (optional) remotes: # short names for project URLs (optional) projects: # a list of projects managed by west (mandatory) self: # configuration related to the manifest repository itself, # i.e. the repository containing west.yml (optional) version: <schema-version> # optional
In YAML terms, the manifest file contains a mapping, with a
key. Any other keys and their contents are ignored (west v0.5 also required a
west key, but this is ignored starting with v0.6).
There are four subsections:
self. In YAML terms, the value of the
manifest key is also a mapping,
with these “subsections” as keys. Only
projects is mandatory: this is the
list of repositories managed by west and their metadata.
We’ll cover the
projects subsections in detail first.
remotes subsection contains a sequence which specifies the base URLs
where projects can be fetched from. Each sequence element has a name and a “URL
base”. These are used to form the complete fetch URL for each project. For
manifest: # ... remotes: - name: remote1 url-base: https://git.example.com/base1 - name: remote2 url-base: https://git.example.com/base2
Above, two remotes are given, with names
remote2. Their URL
bases are respectively
https://git.example.com/base2. You can use SSH URL bases as well; for
example, you might use
remote1 supported Git
over SSH as well. Anything acceptable to Git will work.
projects subsection contains a sequence describing the project
repositories in the west workspace. Every project has a unique name. You can
specify what Git remote URLs to use when cloning and fetching the projects,
what revisions to track, and where the project should be stored on the local
Here is an example. We’ll assume the
remotes given above.
manifest: # [... same remotes as above...] projects: - name: proj1 remote: remote1 path: extra/project-1 - name: proj2 repo-path: my-path remote: remote2 revision: v1.3 - name: proj3 url: https://github.com/user/project-three revision: abcde413a111
In this manifest:
remote1, so its Git fetch URL is
https://git.example.com/base1/proj1. The remote
url-baseis appended with a
/and the project
nameto form the URL.
Locally, this project will be cloned at path
extra/project-1relative to the west workspace’s root directory, since it has an explicit
pathattribute with this value.
Since the project has no
masteris used by default. The current tip of this branch will be fetched and checked out as a detached
HEADwhen west next updates this project.
repo-path, so its fetch URL is
repo-pathattribute, if present, overrides the default
namewhen forming the fetch URL.
Since the project has no
nameis used by default. It will be cloned into a directory named
proj2. The commit pointed to by the
v1.3tag will be checked out when west updates the project.
proj3has an explicit
url, so it will be fetched from
Its local path defaults to its name,
abcde413a111will be checked out when it is next updated.
The list of project keys and their usage follows. Sometimes we’ll refer to the
defaults subsection; it will be described next.
name: Mandatory. the name of the project. The name cannot be one of the reserved values “west” or “manifest”. The name must be unique in the manifest file.
url: Mandatory (one of the two, but not both).
If the project has a
remote, that remote’s
url-basewill be combined with the project’s
repo-path, if it has one) to form the fetch URL instead.
If the project has a
url, that’s the complete fetch URL for the remote Git repository.
If the project has neither, the
defaultssection must specify a
remote, which will be used as the the project’s remote. Otherwise, the manifest is invalid.
repo-path: Optional. If given, this is concatenated on to the remote’s
url-baseinstead of the project’s
nameto form its fetch URL. Projects may not have both
revision: Optional. The Git revision that
west updateshould check out. This will be checked out as a detached HEAD by default, to avoid conflicting with local branch names. If not given, the
revisionvalue from the
defaultssubsection will be used if present.
A project revision can be a branch, tag, or SHA. The default
masterif not otherwise specified.
path: Optional. Relative path specifying where to clone the repository locally, relative to the top directory in the west workspace. If missing, the project’s
nameis used as a directory name.
clone-depth: Optional. If given, a positive integer which creates a shallow history in the cloned repository limited to the given number of commits. This can only be used if the
revisionis a branch or tag.
west-commands: Optional. If given, a relative path to a YAML file within the project which describes additional west commands provided by that project. This file is named
west-commands.ymlby convention. See Extensions for details.
import: Optional. If
true, imports projects from manifest files in the given repository into the current manifest. See Manifest Imports for more details.
defaults subsection can provide default values for project
attributes. In particular, the default remote name and revision can be
specified here. Another way to write the same manifest we have been describing
so far using
manifest: defaults: remote: remote1 revision: v1.3 remotes: - name: remote1 url-base: https://git.example.com/base1 - name: remote2 url-base: https://git.example.com/base2 projects: - name: proj1 path: extra/project-1 revision: master - name: proj2 repo-path: my-path remote: remote2 - name: proj3 url: https://github.com/user/project-three revision: abcde413a111
self subsection can be used to control the behavior of the
manifest repository itself. Its value is a map with the following keys:
path: Optional. The path to clone the manifest repository into, relative to the west workspace’s root directory. If not given, the basename of the path component in the manifest repository URL will be used by default. For example, if the URL is
https://git.example.com/project-repo, the manifest repository would be cloned to the directory
west-commands: Optional. This is analogous to the same key in a project sequence element.
import: Optional. This is also analogous to the
projectskey, but allows importing projects from other files in the manifest repository. See Manifest Imports.
As an example, let’s consider this snippet from the zephyr repository’s
manifest: # ... self: path: zephyr west-commands: scripts/west-commands.yml
This ensures that the zephyr repository is cloned into path
as explained above that would have happened anyway if cloning from the default
https://github.com/zephyrproject-rtos/zephyr. Since the
zephyr repository does contain extension commands, its
self entry declares
the location of the corresponding
west-commands.yml relative to the
version subsection can be used to mark the lowest version of the
manifest file schema that can parse this file’s data:
manifest: version: 0.7 # marks that this manifest uses features available in west 0.7 and # up, like manifest imports
The pykwalify schema
manifest-schema.yml in the west source code
repository is used to validate the manifest section. The current manifest
version is 0.7, which corresponds to west version 0.7. This is the only
value this field can currently take.
If a later version of west, say version
21.0, includes changes to the
manifest schema that cannot be parsed by west 0.7, then setting
21.0 will cause west to print an error when attempting to parse the manifest
You can use the
import key briefly described above to include projects from
other manifest files in your
west.yml. This key can be either a
self section attribute:
manifest: projects: - name: some-project import: ... self: import: ...
You can use a “self: import:” to load additional files from the repository
west.yml. You can use a “project: … import:” to load
additional files defined in that project’s Git history.
West resolves the final manifest from individual manifest files in this order:
imported files in
imported files in
During resolution, west ignores projects which have already been defined in
other files. For example, a project named
foo in your
makes west ignore other projects named
foo imported from your
import key can be a boolean, path, mapping, or sequence. We’ll describe
these in order, using examples:
A more formal description of how this works is last, after the examples.
If you’re using this feature and find west’s behavior confusing, try resolving your manifest to see the final results after imports are done.
This is the easiest way to use
true as a
projects attribute, west imports projects
west.yml file in that project’s root directory. If it’s
false or missing, it has no effect. For example, this manifest would import
west.yml from the
p1 git repository at revision
manifest: # ... projects: - name: p1 revision: v1.0 import: true # Import west.yml from p1's v1.0 git tag - name: p2 import: false # Nothing is imported from p2. - name: p3 # Nothing is imported from p3 either.
It’s an error to set
import to either
self, like this:
manifest: # ... self: import: true # Error
Example 1.1: Downstream of a Zephyr release¶
You have a source code repository you want to use with Zephyr v1.14.1 LTS. You want to maintain the whole thing using west. You don’t want to modify any of the mainline repositories.
In other words, the west workspace you want looks like this:
my-downstream ├── .west # west directory ├── zephyr # mainline zephyr repository ├── modules # modules from mainline zephyr │ ├── hal │ └── [...other directories..] ├── [ ... other projects ...] # other mainline repositories └── my-repo # your downstream repository ├── west.yml └── [...other files..]
You can do this with the following
# my-repo/west.yml: manifest: remotes: - name: zephyrproject-rtos url-base: https://github.com/zephyrproject-rtos projects: - name: zephyr remote: zephyrproject-rtos revision: v1.14.1 import: true
You can then create the workspace on your computer like this, assuming
my-repo is hosted at
west init -m https://git.example.com/my-repo my-downstream cd my-downstream west update
my-downstream/my-repo will be cloned.
west update, all of the projects defined in the
west.yml at revision
v1.14.1 will be cloned into
my-downstream as well.
You can add and commit any code to
my-repo you please at this point,
including your own Zephyr applications, drivers, etc. See Application Development.
Example 1.2: “Rolling release” Zephyr downstream¶
This is similar to Example 1.1: Downstream of a Zephyr release, except we’ll use
master for the zephyr repository:
# my-repo/west.yml: manifest: remotes: - name: zephyrproject-rtos url-base: https://github.com/zephyrproject-rtos projects: - name: zephyr remote: zephyrproject-rtos revision: master import: true
You can create the workspace in the same way:
west init -m https://git.example.com/my-repo my-downstream cd my-downstream west update
This time, whenever you run
west update, the special manifest-rev branch in the
zephyr repository will be updated to
point at a newly fetched
master branch tip from the URL
The contents of
zephyr/west.yml at the new
manifest-rev will then
be used to import projects from Zephyr. This lets you stay up to date with the
latest changes in the Zephyr project. The cost is that running
will not produce reproducible results, since the remote
master branch can
change every time you run it.
It’s also important to understand that west ignores your working tree’s
zephyr/west.yml entirely when resolving imports. West always uses the
contents of imported manifests as they were committed to the latest
manifest-rev when importing from a project.
You can only import manifest from the file system if they are in your manifest repository’s working tree. See Example 2.2: Downstream with directory of manifest files for an example.
Example 1.3: Downstream of a Zephyr release, with module fork¶
This manifest is similar to the one in Example 1.1: Downstream of a Zephyr release, except it:
is a downstream of Zephyr 2.0
includes a downstream fork of the
modules/hal/nordicmodule which was included in that release
# my-repo/west.yml: manifest: remotes: - name: zephyrproject-rtos url-base: https://github.com/zephyrproject-rtos - name: my-remote url-base: https://git.example.com projects: - name: hal_nordic remote: my-remote revision: my-sha path: modules/hal/nordic - name: zephyr remote: zephyrproject-rtos revision: v2.0.0 import: true # subset of zephyr/west.yml contents at v2.0.0: manifest: defaults: remote: zephyrproject-rtos remotes: - name: zephyrproject-rtos url-base: https://github.com/zephyrproject-rtos projects: # ... - name: hal_nordic path: modules/hal/nordic revision: another-sha
With this manifest file, the project named
is cloned from
is updated to commit
west update, instead of the mainline commit
In other words, when your top-level manifest defines a project, like
hal_nordic, west will ignore any other definition it finds later on while
This does mean you have to copy the
path: modules/hal/nordic value into
my-repo/west.yml when defining
hal_nordic there. The value from
zephyr/west.yml is ignored entirely. See Resolving Manifests
for troubleshooting advice if this gets confusing in practice.
When you run
west update, west will:
manifest-revto point at the
locally check out the
v2.0.0revisions for all zephyr projects except
import value can also be a relative path to a manifest file or a
directory containing manifest files. The path is relative to the root directory
self repository the
import key appears in.
Here is an example:
manifest: projects: - name: project-1 revision: v1.0 import: west.yml - name: project-2 revision: master import: p2-manifests self: import: submanifests
This will import the following:
the contents of
manifest-rev, which points at tag
any YAML files in the directory tree
project-2/p2-manifestsat the latest
master, as fetched by
west update, sorted by file name
YAML files in
submanifestsin your manifest repository, as they appear on your file system, sorted by file name
projects imports get data from Git using
self imports get data from your file system. This is because as usual, west
leaves version control for your manifest repository up to you.
Example 2.1: Downstream of a Zephyr release with explicit path¶
This is an explicit way to write an equivalent manifest to the one in Example 1.1: Downstream of a Zephyr release.
manifest: remotes: - name: zephyrproject-rtos url-base: https://github.com/zephyrproject-rtos projects: - name: zephyr remote: zephyrproject-rtos revision: v1.14.1 import: west.yml
import: west.yml means to use the file
zephyr project. This example is contrived, but shows the idea.
This can be useful in practice when the name of the manifest file you want to
import is not
Example 2.2: Downstream with directory of manifest files¶
Your Zephyr downstream has a lot of additional repositories. So many, in fact, that you want to split them up into multiple manifest files, but keep track of them all in a single manifest repository, like this:
my-repo/ ├── submanifests │ ├── 01-libraries.yml │ ├── 02-vendor-hals.yml │ └── 03-applications.yml └── west.yml
You want to add all the files in
my-repo/submanifests to the main
my-repo/west.yml, in addition to projects in
zephyr/west.yml. You want to track the latest mainline master
instead of using a fixed revision.
# my-repo/west.yml: manifest: remotes: - name: zephyrproject-rtos url-base: https://github.com/zephyrproject-rtos projects: - name: zephyr remote: zephyrproject-rtos import: true self: import: submanifests
Manifest files are imported in this order during resolution:
.yml file names are prefixed with numbers in this example to
make sure they are imported in the specified order.
You can pick arbitrary names. West sorts files in a directory by name before importing.
Notice how the manifests in
submanifests are imported before
zephyr/west.yml. In general, an
self section is processed before the manifest files in
and the main manifest file.
This means projects defined in
my-repo/submanifests take highest
precedence. For example, if
the project by the same name in
zephyr/west.yml is simply ignored. As
usual, see Resolving Manifests for troubleshooting advice.
This may seem strange, but it allows you to redefine projects “after the fact”, as we’ll see in the next example.
Example 2.3: Continuous Integration overrides¶
Your continuous integration system needs to fetch and test multiple repositories in your west workspace from a developer’s forks instead of your mainline development trees, to see if the changes all work well together.
Starting with Example 2.2: Downstream with directory of manifest files, the CI scripts add a
my-repo/submanifests, with these contents:
# my-repo/submanifests/00-ci.yml: manifest: projects: - name: a-vendor-hal url: https://github.com/a-developer/hal revision: a-pull-request-branch - name: an-application url: https://github.com/a-developer/application revision: another-pull-request-branch
The CI scripts run
west update after generating this file in
my-repo/submanifests. The projects defined in
higher precedence than other definitions in
because the name
00-ci.yml comes before the other file names.
west update always checks out the developer’s branches in the
an-application, even if those same
projects are also defined elsewhere.
import key can also contain a mapping with the following keys:
file: Optional. The name of the manifest file or directory to import. This defaults to
west.ymlif not present.
name-whitelist: Optional. If present, a name or sequence of project names to include.
path-whitelist: Optional. If present, a path or sequence of project paths to match against. This is a shell-style globbing pattern, currently implemented with pathlib. Note that this means case sensitivity is platform specific.
name-blacklist: Optional. Like
name-whitelist, but contains project names to exclude rather than include.
path-blacklist: Optional. Like
path-whitelist, but contains project paths to exclude rather than include.
Whitelists override blacklists if both are given. For example, if a project is blacklisted by path, then whitelisted by name, it will still be imported.
Example 3.1: Downstream with name whitelist¶
Here is a pair of manifest files, representing a mainline and a
downstream. The downstream doesn’t want to use all the mainline
projects, however. We’ll assume the mainline
# mainline west.yml: manifest: projects: - name: mainline-app path: examples/app url: https://git.example.com/mainline/app - name: lib path: libraries/lib url: https://git.example.com/mainline/lib - name: lib2 path: libraries/lib2 url: https://git.example.com/mainline/lib2 # downstream west.yml: manifest: projects: - name: mainline url: https://git.example.com/mainline/manifest import: name-whitelist: - mainline-app - lib2 - name: downstream-app url: https://git.example.com/downstream/app - name: lib3 path: libraries/lib3 url: https://git.example.com/downstream/lib3
An equivalent manifest in a single file would be:
manifest: projects: - name: mainline url: https://git.example.com/mainline/manifest - name: downstream-app url: https://git.example.com/downstream/app - name: lib3 path: libraries/lib3 url: https://git.example.com/downstream/lib3 - name: mainline-app path: examples/app url: https://git.example.com/mainline/app - name: lib2 path: libraries/lib2 url: https://git.example.com/mainline/lib2
If a whitelist had not been used, the
lib project from the mainline
manifest would have been imported.
Example 3.2: Downstream with path whitelist¶
Here is an example showing how to whitelist mainline’s libraries only,
# mainline west.yml: manifest: projects: - name: app path: examples/app url: https://git.example.com/mainline/app - name: lib path: libraries/lib url: https://git.example.com/mainline/lib - name: lib2 path: libraries/lib2 url: https://git.example.com/mainline/lib2 # downstream west.yml: manifest: projects: - name: mainline url: https://git.example.com/mainline/manifest import: path-whitelist: libraries/* - name: app url: https://git.example.com/downstream/app - name: lib3 path: libraries/lib3 url: https://git.example.com/downstream/lib3
An equivalent manifest in a single file would be:
manifest: projects: - name: lib path: libraries/lib url: https://git.example.com/mainline/lib - name: lib2 path: libraries/lib2 url: https://git.example.com/mainline/lib2 - name: mainline url: https://git.example.com/mainline/manifest - name: app url: https://git.example.com/downstream/app - name: lib3 path: libraries/lib3 url: https://git.example.com/downstream/lib3
Example 3.3: Downstream with path blacklist¶
Here’s an example showing how to blacklist all vendor HALs from mainline by common path prefix in the workspace, add your own version for the chip you’re targeting, and keep everything else.
# mainline west.yml: manifest: defaults: remote: mainline remotes: - name: mainline url-base: https://git.example.com/mainline projects: - name: app - name: lib path: libraries/lib - name: lib2 path: libraries/lib2 - name: hal_foo path: modules/hals/foo - name: hal_bar path: modules/hals/bar - name: hal_baz path: modules/hals/baz # downstream west.yml: manifest: projects: - name: mainline url: https://git.example.com/mainline/manifest import: path-blacklist: modules/hals/* - name: hal_foo path: modules/hals/foo url: https://git.example.com/downstream/hal_foo
An equivalent manifest in a single file would be:
manifest: defaults: remote: mainline remotes: - name: mainline url-base: https://git.example.com/mainline projects: - name: app - name: lib path: libraries/lib - name: lib2 path: libraries/lib2 - name: mainline repo-path: https://git.example.com/mainline/manifest - name: hal_foo path: modules/hals/foo url: https://git.example.com/downstream/hal_foo
import key can also contain a sequence of files, directories,
Example 4.1: Downstream with sequence of manifest files¶
This example manifest is equivalent to the manifest in Example 2.2: Downstream with directory of manifest files, with a sequence of explicitly named files.
# my-repo/west.yml: manifest: projects: - name: zephyr url: https://github.com/zephyrproject-rtos/zephyr import: west.yml self: import: - submanifests/01-libraries.yml - submanifests/02-vendor-hals.yml - submanifests/03-applications.yml
Example 4.2: Import order illustration¶
This more complicated example shows the order that west imports manifest files:
# my-repo/west.yml manifest: # ... projects: - name: my-library - name: my-app - name: zephyr import: true - name: another-manifest-repo import: submanifests self: import: - submanifests/libraries.yml - submanifests/vendor-hals.yml - submanifests/applications.yml defaults: remote: my-remote
For this example, west resolves imports in this order:
the listed files in
my-repo/submanifestsare first, in the order they occur (e.g.
applications.yml, since this is a sequence of files), since the
self: import:is always imported first
my-repo/west.ymlis next (with projects
my-libraryetc. as long as they weren’t already defined somewhere in
zephyr/west.ymlis after that, since that’s the first
importkey in the
another-manifest-repo/submanifestsare last (sorted by file name), since that’s the final project
This section describes how west imports a manifest file a bit more formally.
A west manifest’s
self sections can have
# Top-level west.yml. manifest: # ... projects: - name: foo revision: rev-1 import: import-1 - name: bar revision: rev-2 import: import-2 # ... - name: baz revision: rev-N import: import-N self: import: self-import
Import keys are optional. If any of
import-1, ..., import-N are missing,
west will not import additional manifest data from that project. If
self-import is missing, no additional files in the manifest repository
(beyond the top-level west.yml) are imported.
The ultimate outcome of resolving manifest imports is a final list of projects,
which is produced by combining the
projects defined in the top-level file
with those defined in imported files. Importing is done in this order:
self-importare imported first.
The top-level manifest file’s
projectsare added in next.
import-N, are imported in that order.
This process recurses if necessary.
Projects are identified by name. If the same name occurs in multiple manifests,
the first definition is used, and subsequent definitions are ignored. For
import-1 contains a project named
bar, that is ignored,
because the top-level
west.yml has already defined a project by that
The contents of files named by
import-N are imported
from Git at the latest
manifest-rev revisions in their projects. These
revisions can be updated to the values
rev-N by running
west update. If any
manifest-rev reference is missing or out of date,
west update also fetches project data from the remote fetch URL and updates
Also note that all imported manifests, from the root manifest to the repository
which defines a project
P, must be up to date in order for west to update
P itself. For example, this means
west update P would update
manifest-rev in the
baz project if
as well as updating the
manifest-rev branch in the local git clone of
P. Confusingly, the update of
baz may result in the removal of
baz/west.yml, which would cause
west update P to fail with an
For this reason, it’s usually best to run plain
west update to avoid errors
if you use manifest imports. By default, west won’t fetch any project data over
the network if a project’s revision is a SHA or tag which is already available
locally, so updating the extra projects shouldn’t take too much time unless
it’s really needed. See the documentation for the update.fetch configuration option for more information.
If an imported manifest file has a
west-commands: definition in its
self: section, the extension commands defined there are added to the set of
available extensions at the time the manifest is imported. They will thus take
precedence over any extension commands with the same names added later on.
When an individual
import key refers to multiple manifest files, they are
processed in this order:
If the value is a relative path naming a directory (or a map whose
fileis a directory), the manifest files it contains are processed in lexicographic order – i.e., sorted by file name.
If the value is a sequence, its elements are recursively imported in the order they appear.
west manifest command can be used to manipulate manifest files.
It takes an action, and action-specific arguments.
The following sections describe each action and provides a basic signature for
simple uses. Run
west manifest --help for full details on all options.
--resolve action outputs a single manifest file equivalent to your
current manifest and all its imported manifests:
west manifest --resolve [-o outfile]
The main use for this action is to see the “final” manifest contents after
To print detailed information about each imported manifest file and how
projects are handled during manifest resolution, set the maximum verbosity
west -v manifest --resolve
--freeze action outputs a frozen manifest:
west manifest --freeze [-o outfile]
A “frozen” manifest is a manifest file where every project’s revision is a SHA.
You can use
--freeze to produce a frozen manifest that’s equivalent to your
current manifest file. The
-o option specifies an output file; if not
given, standard output is used.