We wrote this document because many Googlers do not use GitHub on a daily basis. If you are an experienced GitHub contributor much of the information here will be familiar to you, feel free to skip it. If you are new to GitHub or have not used it in a while and want a refresher this might be useful.
In this project we use the (more or less) standard GitHub workflow:
You create a fork of google-cloud-cpp. You can think of a "fork" as a full copy of the original repository, including all its history and branches. Then clone that fork into your workstation:
git clone git@github.com:YOUR-USER-NAME/google-cloud-cpp.git
This creates a second copy of the original repository, with all its history and branches. You can create new branches in this copy, change the history of branches (you can, but don't!), and generally do all the version control things you may be used to. Note that these local changes do not affect either of the previous two copies.
The cloned repo that you created in the previous step will have its origin
set to your forked repo. You should now tell git about the main upstream
repo,
which you'll use to pull commits made by others in order to keep your local repo
and fork up to date.
git remote add upstream git@github.com:googleapis/google-cloud-cpp.git
git remote -v # Should show 'origin' (your fork) and 'upstream' (main repo)
To pull new commits from upstream
into your local repo and
sync your fork you can do the following:
git checkout main
git pull --ff-only upstream main
git push # Pushes new commits up to your fork on GitHub
⚠️ you probably want to do this periodically, and almost certainly before starting any new branches. Keeping your default branch (akamain
) in sync is important to make your pull requests easy to review.
Changes to the main repository must go through a review by one of the project owners (even project owners have their code reviewed by a peer). To submit your change for review you need to create a pull request. Typically you start by:
- Picking an existing GitHub bug to work on.
- Create a new branch for each feature (or bug fix).
git checkout main git checkout -b my-feature-branch git push -u origin my-feature-branch # Tells fork on GitHub about new branch # make your changes git push
- And then submit a pull-request to merge your branch
into
googleapis/google-cloud-cpp
. - Your reviewers may ask questions, suggest improvements or alternatives. You
address those by either answering the questions in the review or
adding more commits to your branch and
git push
-ing those commits to your fork.
Eventually the reviewers accept your changes, and they are merged into the
main
branch. We use "squash commits", where all your commits become a single
commit into the default branch. A project owner needs to merge your changes,
if you are a project owner, the expectation is that you will perform the merge
operation, and update the commit comments to something readable.
The previous steps described a happy case for a PR (hopefully for most PRs), where no build failures or conflicts are detected in the PR. The next two sections explain what to do when things are not so rosy.
From time to time your pull request may have conflicts with the destination
branch (likely main
). If so, we request that you rebase
your branch instead of merging. The reviews can become very confusing if you
merge during a pull request. You should first ensure that your main
branch has all the latest commits by syncing your fork (see above), then do
the following:
git checkout my-feature-branch
git rebase main
git push --force-with-lease
If there are conflicts, the git rebase
command will show you the conflicts.
These will not be automatically resolved, if they were, git rebase
would not
have required human intervention! You will need to edit the code to resolve
these conflicts, potentially git add
or git rm
files as needed. Once the
conflicts are resolved you git add
the files to indicate the conflict
resolution is complete, and then continue the rebase with:
git rebase --continue
If there are multiple commits in your PR this process runs for each commit.
If you are a Googler, when you submit your pull request a number (about 50 at last count) of builds start automatically. For non-Googlers, a project owner needs to kickoff these builds for you.
We run so many builds because we need to test the libraries under as many compilers, platforms, and configurations as possible. Our customers will not necessarily use the same environment as we do to build and run these libraries.
There is a completely separate guide explaining how to run these builds locally in case one fails. It's also a good idea to run some of these builds locally, before sending a PR, to verify that your change (likely) works. Running the following builds locally should identify most common issues:
ci/cloudbuild/build.sh -t checkers-pr
ci/cloudbuild/build.sh -t clang-tidy-pr
ci/cloudbuild/build.sh -t asan-pr
In general, most of the builds for Linux can be reproduced locally using the
build name as an argument to build.sh
.