%poky; ] > The Yocto Project Open Source Development Environment
Using the Yocto Project in a Team Environment It might not be immediately clear how you can use the Yocto Project in a team environment, or scale it for a large team of developers. One of the strengths of the Yocto Project is that it is extremely flexible. Thus, you can adapt it to many different use cases and scenarios. However, these characteristics can cause a struggle if you are trying to create a working setup that scales across a large team. To help with these types of situations, this section presents some of the project's most successful experiences, practices, solutions, and available technologies that work well. Keep in mind, the information here is a starting point. You can build off it and customize it to fit any particular working environment and set of practices.
System Configurations Systems across a large team should meet the needs of two types of developers: those working on the contents of the operating system image itself and those developing applications. Regardless of the type of developer, their workstations must be both reasonably powerful and run Linux.
Application Development For developers who mainly do application level work on top of an existing software stack, the following list shows practices that work best. For information on using a Software Development Kit (SDK), see the Yocto Project Software Development Kit (SDK) Developer's Guide: Use a pre-built toolchain that contains the software stack itself. Then, develop the application code on top of the stack. This method works well for small numbers of relatively isolated applications. When possible, use the Yocto Project plug-in for the Eclipse IDE and SDK development practices. For more information, see the "Yocto Project Software Development Kit (SDK) Developer's Guide". Keep your cross-development toolchains updated. You can do this through provisioning either as new toolchain downloads or as updates through a package update mechanism using opkg to provide updates to an existing toolchain. The exact mechanics of how and when to do this are a question for local policy. Use multiple toolchains installed locally into different locations to allow development across versions.
Core System Development For core system development, it is often best to have the build system itself available on the developer workstations so developers can run their own builds and directly rebuild the software stack. You should keep the core system unchanged as much as possible and do your work in layers on top of the core system. Doing so gives you a greater level of portability when upgrading to new versions of the core system or Board Support Packages (BSPs). You can share layers amongst the developers of a particular project and contain the policy configuration that defines the project. Aside from the previous best practices, there exists a number of tips and tricks that can help speed up core development projects: Use a Shared State Cache (sstate) among groups of developers who are on a fast network. The best way to share sstate is through a Network File System (NFS) share. The first user to build a given component for the first time contributes that object to the sstate, while subsequent builds from other developers then reuse the object rather than rebuild it themselves. Although it is possible to use other protocols for the sstate such as HTTP and FTP, you should avoid these. Using HTTP limits the sstate to read-only and FTP provides poor performance. Have autobuilders contribute to the sstate pool similarly to how the developer workstations contribute. For information, see the "Autobuilders" section. Build stand-alone tarballs that contain "missing" system requirements if for some reason developer workstations do not meet minimum system requirements such as latest Python versions, chrpath, or other tools. You can install and relocate the tarball exactly as you would the usual cross-development toolchain so that all developers can meet minimum version requirements on most distributions. Use a small number of shared, high performance systems for testing purposes (e.g. dual, six-core Xeons with 24 Gbytes of RAM and plenty of disk space). Developers can use these systems for wider, more extensive testing while they continue to develop locally using their primary development system. Enable the PR Service when package feeds need to be incremental with continually increasing PR values. Typically, this situation occurs when you use or publish package feeds and use a shared state. You should enable the PR Service for all users who use the shared state pool. For more information on the PR Service, see the "Working With a PR Service".
Source Control Management (SCM) Keeping your Metadata and any software you are developing under the control of an SCM system that is compatible with the OpenEmbedded build system is advisable. Of the SCMs BitBake supports, the Yocto Project team strongly recommends using Git. Git is a distributed system that is easy to backup, allows you to work remotely, and then connects back to the infrastructure. For information about BitBake, see the BitBake User Manual. It is relatively easy to set up Git services and create infrastructure like http://git.yoctoproject.org, which is based on server software called gitolite with cgit being used to generate the web interface that lets you view the repositories. The gitolite software identifies users using SSH keys and allows branch-based access controls to repositories that you can control as little or as much as necessary. The setup of these services is beyond the scope of this manual. However, sites such as these exist that describe how to perform setup: Git documentation: Describes how to install gitolite on the server. The gitolite master index: All topics for gitolite. Interfaces, frontends, and tools: Documentation on how to create interfaces and frontends for Git.
Autobuilders Autobuilders are often the core of a development project. It is here that changes from individual developers are brought together and centrally tested and subsequent decisions about releases can be made. Autobuilders also allow for "continuous integration" style testing of software components and regression identification and tracking. See "Yocto Project Autobuilder" for more information and links to buildbot. The Yocto Project team has found this implementation works well in this role. A public example of this is the Yocto Project Autobuilders, which we use to test the overall health of the project. The features of this system are: Highlights when commits break the build. Populates an sstate cache from which developers can pull rather than requiring local builds. Allows commit hook triggers, which trigger builds when commits are made. Allows triggering of automated image booting and testing under the QuickEMUlator (QEMU). Supports incremental build testing and from-scratch builds. Shares output that allows developer testing and historical regression investigation. Creates output that can be used for releases. Allows scheduling of builds so that resources can be used efficiently.
Policies and Change Flow The Yocto Project itself uses a hierarchical structure and a pull model. Scripts exist to create and send pull requests (i.e. create-pull-request and send-pull-request). This model is in line with other open source projects where maintainers are responsible for specific areas of the project and a single maintainer handles the final "top-of-tree" merges. You can also use a more collective push model. The gitolite software supports both the push and pull models quite easily. As with any development environment, it is important to document the policy used as well as any main project guidelines so they are understood by everyone. It is also a good idea to have well structured commit messages, which are usually a part of a project's guidelines. Good commit messages are essential when looking back in time and trying to understand why changes were made. If you discover that changes are needed to the core layer of the project, it is worth sharing those with the community as soon as possible. Chances are if you have discovered the need for changes, someone else in the community needs them also.
Summary This section summarizes the key recommendations described in the previous sections: Use Git as the source control system. Maintain your Metadata in layers that make sense for your situation. See the "Understanding and Creating Layers" section for more information on layers. Separate the project's Metadata and code by using separate Git repositories. See the "Yocto Project Source Repositories" section for information on these repositories. See the "Getting Set Up" section for information on how to set up local Git repositories for related upstream Yocto Project Git repositories. Set up the directory for the shared state cache (SSTATE_DIR) where it makes sense. For example, set up the sstate cache on a system used by developers in the same organization and share the same source directories on their machines. Set up an Autobuilder and have it populate the sstate cache and source directories. The Yocto Project community encourages you to send patches to the project to fix bugs or add features. If you do submit patches, follow the project commit guidelines for writing good commit messages. See the "How to Submit a Change" section. Send changes to the core sooner than later as others are likely to run into the same issues. For some guidance on mailing lists to use, see the list in the "How to Submit a Change" section. For a description of the available mailing lists, see the "Mailing Lists" section in the Yocto Project Reference Manual.
Git The Yocto Project makes extensive use of Git, which is a free, open source distributed version control system. Git supports distributed development, non-linear development, and can handle large projects. It is best that you have some fundamental understanding of how Git tracks projects and how to work with Git if you are going to use the Yocto Project for development. This section provides a quick overview of how Git works and provides you with a summary of some essential Git commands. For more information on Git, see . If you need to download Git, go to .
Repositories, Tags, and Branches As mentioned earlier in the section "Yocto Project Source Repositories", the Yocto Project maintains source repositories at . If you look at this web-interface of the repositories, each item is a separate Git repository. Git repositories use branching techniques that track content change (not files) within a project (e.g. a new feature or updated documentation). Creating a tree-like structure based on project divergence allows for excellent historical information over the life of a project. This methodology also allows for an environment from which you can do lots of local experimentation on projects as you develop changes or new features. A Git repository represents all development efforts for a given project. For example, the Git repository poky contains all changes and developments for Poky over the course of its entire life. That means that all changes that make up all releases are captured. The repository maintains a complete history of changes. You can create a local copy of any repository by "cloning" it with the Git clone command. When you clone a Git repository, you end up with an identical copy of the repository on your development system. Once you have a local copy of a repository, you can take steps to develop locally. For examples on how to clone Git repositories, see the "Getting Set Up" section. It is important to understand that Git tracks content change and not files. Git uses "branches" to organize different development efforts. For example, the poky repository has several branches that include the current &DISTRO_NAME_NO_CAP; branch, the master branch, and many branches for past Yocto Project releases. You can see all the branches by going to and clicking on the [...] link beneath the "Branch" heading. Each of these branches represents a specific area of development. The master branch represents the current or most recent development. All other branches represent offshoots of the master branch. When you create a local copy of a Git repository, the copy has the same set of branches as the original. This means you can use Git to create a local working area (also called a branch) that tracks a specific development branch from the source Git repository. in other words, you can define your local Git environment to work on any development branch in the repository. To help illustrate, here is a set of commands that creates a local copy of the poky Git repository and then creates and checks out a local Git branch that tracks the Yocto Project &DISTRO; Release (&DISTRO_NAME;) development: $ cd ~ $ git clone git://git.yoctoproject.org/poky $ cd poky $ git checkout -b &DISTRO_NAME_NO_CAP; origin/&DISTRO_NAME_NO_CAP; In this example, the name of the top-level directory of your local Source Directory is "poky" and the name of that local working area (local branch) you just created and checked out is "&DISTRO_NAME_NO_CAP;". The files in your local repository now reflect the same files that are in the "&DISTRO_NAME_NO_CAP;" development branch of the Yocto Project's "poky" upstream repository. It is important to understand that when you create and checkout a local working branch based on a branch name, your local environment matches the "tip" of that development branch at the time you created your local branch, which could be different from the files at the time of a similarly named release. In other words, creating and checking out a local branch based on the "&DISTRO_NAME_NO_CAP;" branch name is not the same as cloning and checking out the "master" branch. Keep reading to see how you create a local snapshot of a Yocto Project Release. Git uses "tags" to mark specific changes in a repository. Typically, a tag is used to mark a special point such as the final change before a project is released. You can see the tags used with the poky Git repository by going to and clicking on the [...] link beneath the "Tag" heading. Some key tags are dizzy-12.0.0, fido-13.0.0, jethro-14.0.0, and &DISTRO_NAME_NO_CAP;-&POKYVERSION;. These tags represent Yocto Project releases. When you create a local copy of the Git repository, you also have access to all the tags. Similar to branches, you can create and checkout a local working Git branch based on a tag name. When you do this, you get a snapshot of the Git repository that reflects the state of the files when the change was made associated with that tag. The most common use is to checkout a working branch that matches a specific Yocto Project release. Here is an example: $ cd ~ $ git clone git://git.yoctoproject.org/poky $ cd poky $ git checkout -b my-&DISTRO_NAME_NO_CAP;-&POKYVERSION; &DISTRO_NAME_NO_CAP;-&POKYVERSION; In this example, the name of the top-level directory of your local Yocto Project Files Git repository is poky. And, the name of the local branch you have created and checked out is my-&DISTRO_NAME_NO_CAP;-&POKYVERSION;. The files in your repository now exactly match the Yocto Project &DISTRO; Release tag (&DISTRO_NAME_NO_CAP;-&POKYVERSION;). It is important to understand that when you create and checkout a local working branch based on a tag, your environment matches a specific point in time and not the entire development branch.
Basic Commands Git has an extensive set of commands that lets you manage changes and perform collaboration over the life of a project. Conveniently though, you can manage with a small set of basic operations and workflows once you understand the basic philosophy behind Git. You do not have to be an expert in Git to be functional. A good place to look for instruction on a minimal set of Git commands is here. If you need to download Git, you can do so here, although any reasonably current Linux distribution should already have an installable package for Git. If you do not know much about Git, you should educate yourself by visiting the links previously mentioned. The following list briefly describes some basic Git operations as a way to get started. As with any set of commands, this list (in most cases) simply shows the base command and omits the many arguments they support. See the Git documentation for complete descriptions and strategies on how to use these commands: git init: Initializes an empty Git repository. You cannot use Git commands unless you have a .git repository. git clone: Creates a local clone of a Git repository. During collaboration, this command allows you to create a local Git repository that is on equal footing with a fellow developer’s Git repository. git add: Stages updated file contents to the index that Git uses to track changes. You must stage all files that have changed before you can commit them. git commit: Creates a "commit" that documents the changes you made. Commits are used for historical purposes, for determining if a maintainer of a project will allow the change, and for ultimately pushing the change from your local Git repository into the project’s upstream (or master) repository. git status: Reports any modified files that possibly need to be staged and committed. git checkout branch-name: Changes your working branch. This command is analogous to "cd". git checkout –b working-branch: Creates a working branch on your local machine where you can isolate work. It is a good idea to use local branches when adding specific features or changes. This way if you do not like what you have done you can easily get rid of the work. git branch: Reports existing local branches and tells you the branch in which you are currently working. git branch -D branch-name: Deletes an existing local branch. You need to be in a local branch other than the one you are deleting in order to delete branch-name. git pull: Retrieves information from an upstream Git repository and places it in your local Git repository. You use this command to make sure you are synchronized with the repository from which you are basing changes (.e.g. the master branch). git push: Sends all your committed local changes to an upstream Git repository (e.g. a contribution repository). The maintainer of the project draws from these repositories when adding changes to the project’s master repository or other development branch. git merge: Combines or adds changes from one local branch of your repository with another branch. When you create a local Git repository, the default branch is named "master". A typical workflow is to create a temporary branch for isolated work, make and commit your changes, switch to your local master branch, merge the changes from the temporary branch into the local master branch, and then delete the temporary branch. git cherry-pick: Choose and apply specific commits from one branch into another branch. There are times when you might not be able to merge all the changes in one branch with another but need to pick out certain ones. gitk: Provides a GUI view of the branches and changes in your local Git repository. This command is a good way to graphically see where things have diverged in your local repository. git log: Reports a history of your changes to the repository. git diff: Displays line-by-line differences between your local working files and the same files in the upstream Git repository that your branch currently tracks.
Submitting a Defect Against the Yocto Project Use the Yocto Project implementation of Bugzilla to submit a defect (bug) against the Yocto Project. For additional information on this implementation of Bugzilla see the "Yocto Project Bugzilla" section in the Yocto Project Reference Manual. For more detail on any of the following steps, see the Yocto Project Bugzilla wiki page. Use the following general steps to submit a bug" Open the Yocto Project implementation of Bugzilla. Click "File a Bug" to enter a new bug. Choose the appropriate "Classification", "Product", and "Component" for which the bug was found. Bugs for the Yocto Project fall into one of several classifications, which in turn break down into several products and components. For example, for a bug against the meta-intel layer, you would choose "Build System, Metadata & Runtime", "BSPs", and "bsps-meta-intel", respectively. Choose the "Version" of the Yocto Project for which you found the bug (e.g. &DISTRO;). Determine and select the "Severity" of the bug. The severity indicates how the bug impacted your work. Choose the "Hardware" that the bug impacts. Choose the "Architecture" that the bug impacts. Choose a "Documentation change" item for the bug. Fixing a bug might or might not affect the Yocto Project documentation. If you are unsure of the impact to the documentation, select "Don't Know". Provide a brief "Summary" of the bug. Try to limit your summary to just a line or two and be sure to capture the essence of the bug. Provide a detailed "Description" of the bug. You should provide as much detail as you can about the context, behavior, output, and so forth that surrounds the bug. You can even attach supporting files for output from logs by using the "Add an attachment" button. Click the "Submit Bug" button submit the bug. A new Bugzilla number is assigned to the bug and the defect is logged in the bug tracking system. Once you file a bug, the bug is processed by the Yocto Project Bug Triage Team and further details concerning the bug are assigned (e.g. priority and owner). You are the "Submitter" of the bug and any further categorization, progress, or comments on the bug result in Bugzilla sending you an automated email concerning the particular change or progress to the bug.
How to Submit a Change Contributions to the Yocto Project and OpenEmbedded are very welcome. Because the system is extremely configurable and flexible, we recognize that developers will want to extend, configure or optimize it for their specific uses. You should send patches to the appropriate mailing list so that they can be reviewed and merged by the appropriate maintainer.
Overview The Yocto Project uses a mailing list and patch-based workflow that is similar to the Linux kernel but contains important differences. In general, a mailing list exists through which you can submit patches. The specific mailing list you need to use depends on the location of the code you are changing. Each component (e.g. layer) should have a README file that indicates where to send the changes and which process to follow. You can send the patch to the mailing list using whichever approach you feel comfortable with to generate the patch. Once sent, the patch is usually reviewed by the community at large. If somebody has concerns with the patch, they will usually voice their concern over the mailing list. If a patch does not receive any negative reviews, the maintainer of the affected layer typically takes the patch, tests it, and then based on successful testing, merges the patch. Specific to OpenEmbedded-Core, two commonly used testing trees exist: "ross/mut" branch: The "mut" (master-under-test) tree exists in the poky-contrib repository in the Yocto Project source repositories. "master-next" branch: This branch is part of the main "poky" repository in the Yocto Project source repositories. Maintainers use these branches to test submissions prior to merging patches. Thus, you can get an idea of the status of a patch based on whether the patch has been merged into one of these branches. This system is imperfect and patches can sometimes get lost in the flow. Asking about the status of a patch is reasonable if the patch has been idle for a while with no feedback. The Yocto Project does have plans to use Patchwork to track the status of patches and also to automatically preview patches. The following sections provide general instructions for both pushing changes upstream and for submitting changes as patches.
Submissions to Poky The "poky" repository, which is the Yocto Project's reference build environment, is a hybrid repository that contains several individual pieces (e.g. BitBake, OpenEmbedded-Core, meta-yocto, documentation, and so forth) built using the combo-layer tool. The upstream location used for submitting changes varies by component: Core Metadata: Send your patch to the openembedded-core mailing list. For example, a change to anything under the meta or scripts directories should be sent to this mailing list. BitBake: For changes to BitBake (i.e. anything under the bitbake directory), send your patch to the bitbake-devel mailing list. "meta-yocto-bsp" and "meta-poky" trees: These trees are part of the "meta-yocto" repository in the Yocto Project source repositories. Use the poky mailing list.
Submissions to Other Layers For changes to other layers hosted in the Yocto Project source repositories (i.e. yoctoproject.org), tools, and the Yocto Project documentation, use the Yocto Project general mailing list. Sometimes a layer's documentation specifies to use a particular mailing list. If so, use that list. For additional recipes that do not fit into the core Metadata, you should determine which layer the recipe should go into and submit the change in the manner recommended by the documentation (e.g. the README file) supplied with the layer. If in doubt, please ask on the Yocto general mailing list or on the openembedded-devel mailing list.
Patch Submission Details When submitting any change, you can check who you should be notifying. Use either of these methods to find out: Maintenance File: Examine the maintainers.inc file, which is located in the Source Directory at meta-poky/conf/distro/include, to see who is responsible for code. Search by File: Using Git, you can enter the following command to bring up a short list of all commits against a specific file: git shortlog -- filename Just provide the name of the file for which you are interested. The information returned is not ordered by history but does include a list of everyone who has committed grouped by name. From the list, you can see who is responsible for the bulk of the changes against the file. For a list of the Yocto Project and related mailing lists, see the "Mailing lists" section in the Yocto Project Reference Manual. When you send a patch, be sure to include a "Signed-off-by:" line in the same style as required by the Linux kernel. Adding this line signifies that you, the submitter, have agreed to the Developer's Certificate of Origin 1.1 as follows: Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. In a collaborative environment, it is necessary to have some sort of standard or method through which you submit changes. Otherwise, things could get quite chaotic. One general practice to follow is to make small, controlled changes. Keeping changes small and isolated aids review, makes merging/rebasing easier and keeps the change history clean should anyone need to refer to it in future. When you make a commit, you must follow certain standards established by the OpenEmbedded and Yocto Project development teams. For each commit, you must provide a single-line summary of the change and you should almost always provide a more detailed description of what you did (i.e. the body of the commit message). The only exceptions for not providing a detailed description would be if your change is a simple, self-explanatory change that needs no further description beyond the summary. Here are the guidelines for composing a commit message: Provide a single-line, short summary of the change. This summary is typically viewable in the "shortlist" of changes. Thus, providing something short and descriptive that gives the reader a summary of the change is useful when viewing a list of many commits. You should prefix this short description with the recipe name (if changing a recipe), or else with the short form path to the file being changed. For the body of the commit message, provide detailed information that describes what you changed, why you made the change, and the approach you used. It might also be helpful if you mention how you tested the change. Provide as much detail as you can in the body of the commit message. If the change addresses a specific bug or issue that is associated with a bug-tracking ID, include a reference to that ID in your detailed description. For example, the Yocto Project uses a specific convention for bug references - any commit that addresses a specific bug should use the following form for the detailed description: Fixes [YOCTO #bug-id] detailed description of change Where bug-id is replaced with the specific bug ID from the Yocto Project Bugzilla instance. You can find more guidance on creating well-formed commit messages at this OpenEmbedded wiki page: .
Using Scripts to Push a Change Upstream and Request a Pull The basic flow for pushing a change to an upstream "contrib" Git repository is as follows: Make your changes in your local Git repository. Stage your changes by using the git add command on each file you changed. Commit the change by using the git commit command. Be sure to provide a commit message that follows the project’s commit message standards as described earlier. Push the change to the upstream "contrib" repository by using the git push command. Notify the maintainer that you have pushed a change by making a pull request. The Yocto Project provides two scripts that conveniently let you generate and send pull requests to the Yocto Project. These scripts are create-pull-request and send-pull-request. You can find these scripts in the scripts directory within the Source Directory. Using these scripts correctly formats the requests without introducing any whitespace or HTML formatting. The maintainer that receives your patches needs to be able to save and apply them directly from your emails. Using these scripts is the preferred method for sending patches. For help on using these scripts, simply provide the -h argument as follows: $ poky/scripts/create-pull-request -h $ poky/scripts/send-pull-request -h You can find general Git information on how to push a change upstream in the Git Community Book.
Using Email to Submit a Patch You can submit patches without using the create-pull-request and send-pull-request scripts described in the previous section. However, keep in mind, the preferred method is to use the scripts. Depending on the components changed, you need to submit the email to a specific mailing list. For some guidance on which mailing list to use, see the list in the "How to Submit a Change" section. For a description of the available mailing lists, see the "Mailing Lists" section in the Yocto Project Reference Manual. Here is the general procedure on how to submit a patch through email without using the scripts: Make your changes in your local Git repository. Stage your changes by using the git add command on each file you changed. Commit the change by using the git commit --signoff command. Using the --signoff option identifies you as the person making the change and also satisfies the Developer's Certificate of Origin (DCO) shown earlier. When you form a commit, you must follow certain standards established by the Yocto Project development team. See the earlier section "How to Submit a Change" for Yocto Project commit message standards. Format the commit into an email message. To format commits, use the git format-patch command. When you provide the command, you must include a revision list or a number of patches as part of the command. For example, either of these two commands takes your most recent single commit and formats it as an email message in the current directory: $ git format-patch -1 or $ git format-patch HEAD~ After the command is run, the current directory contains a numbered .patch file for the commit. If you provide several commits as part of the command, the git format-patch command produces a series of numbered files in the current directory – one for each commit. If you have more than one patch, you should also use the --cover option with the command, which generates a cover letter as the first "patch" in the series. You can then edit the cover letter to provide a description for the series of patches. For information on the git format-patch command, see GIT_FORMAT_PATCH(1) displayed using the man git-format-patch command. If you are or will be a frequent contributor to the Yocto Project or to OpenEmbedded, you might consider requesting a contrib area and the necessary associated rights. Import the files into your mail client by using the git send-email command. In order to use git send-email, you must have the proper Git packages installed on your host. For Ubuntu, Debian, and Fedora the package is git-email. The git send-email command sends email by using a local or remote Mail Transport Agent (MTA) such as msmtp, sendmail, or through a direct smtp configuration in your Git ~/.gitconfig file. If you are submitting patches through email only, it is very important that you submit them without any whitespace or HTML formatting that either you or your mailer introduces. The maintainer that receives your patches needs to be able to save and apply them directly from your emails. A good way to verify that what you are sending will be applicable by the maintainer is to do a dry run and send them to yourself and then save and apply them as the maintainer would. The git send-email command is the preferred method for sending your patches since there is no risk of compromising whitespace in the body of the message, which can occur when you use your own mail client. The command also has several options that let you specify recipients and perform further editing of the email message. For information on how to use the git send-email command, see GIT-SEND-EMAIL(1) displayed using the man git-send-email command.