docs: Add full PR example to contributing guide

Add a full example of creating a PR including explaining how to rebase,
squash commits and force push to include review changes.

Fixes #66.

Signed-off-by: James O. D. Hunt <james.o.hunt@intel.com>
This commit is contained in:
James O. D. Hunt 2019-01-14 12:02:30 +00:00
parent 34ae157369
commit 7229ad7f2f

View File

@ -7,6 +7,8 @@
* [Before starting work on a PR](#before-starting-work-on-a-pr) * [Before starting work on a PR](#before-starting-work-on-a-pr)
* [Before submitting a PR](#before-submitting-a-pr) * [Before submitting a PR](#before-submitting-a-pr)
* [Normal PR workflow](#normal-pr-workflow) * [Normal PR workflow](#normal-pr-workflow)
* [First PR example](#first-pr-example)
* [Updating your PR based on review comments](#updating-your-pr-based-on-review-comments)
* [Assisted PR workflow](#assisted-pr-workflow) * [Assisted PR workflow](#assisted-pr-workflow)
* [Re-vendor PRs](#re-vendor-prs) * [Re-vendor PRs](#re-vendor-prs)
* [Stable branch backports](#stable-branch-backports) * [Stable branch backports](#stable-branch-backports)
@ -120,14 +122,364 @@ rework your branch. You should rework any relevant information from the GitHub
comment section into your patch set because your patches are documented in the comment section into your patch set because your patches are documented in the
Git log, not the comment section. Git log, not the comment section.
For more information on GitHub "force push" workflows see "[Why and how to
correctly amend GitHub pull
requests](http://blog.adamspiers.org/2015/03/24/why-and-how-to-correctly-amend-github-pull-requests/)".
Your PR can contain more than one patch. Use as many patches as necessary to Your PR can contain more than one patch. Use as many patches as necessary to
implement the request. Each PR should only cover one topic. If you mix up implement the request. Each PR should only cover one topic. If you mix up
different items in your patches or PR, they will likely need to be reworked. different items in your patches or PR, they will likely need to be reworked.
#### First PR example
This section guides you through the process to create your first PR. We will
create a branch and in that branch we will change *this document*, which lives
in the Kata Containers community repository:
- https://github.com/kata-containers/community
This is the official location for this repository and is referred to as the
"upstream" repository.
> **Note:** This section assumes no previous `git(1)` setup or knowledge.
- Create a free GitHub account
To raise PRs and create issues, you must have a GitHub account.
- Basic Git setup
First, install the `git` package for your distribution. Second, tell Git
your name and email address, if you haven't already, so they can be recorded
in your commits.
```sh
$ git config --global user.email "you@example.com"
$ git config --global user.name "Your Name"
```
> **Note:** The email address you specify here must match your primary GitHub email address.
- Create your own copy of the repository
Click "fork" to create "your copy" of the repository you want to change on
https://github.com/kata-containers/community. This is an exact copy of the
upstream repository located at
`https://github.com/${your-github-username}/community` on the GitHub server. You
can make changes on this copy as we move through the example.
- Prepare your environment
> **Note:**: Most of the
> [Kata Containers repositories](https://github.com/kata-containers)
> contain code written in the
> [Go language (golang)](https://golang.org/). Go requires all code to be put
> inside the directory specified by the `$GOPATH` variable. Since this example PR
> is not using golang you do not need to
> [install golang](https://github.com/kata-containers/documentation/blob/master/Developer-Guide.md#requirements-to-build-individual-components).
> However it still makes sense to put the code in the standard location.
```sh
$ export GOPATH=${GOPATH:-$HOME/go}
$ mkdir -p "$GOPATH"
```
> **Note:** The code above is safe to run whether you have golang installed
> or not.
> For further details on golang, refer to the
> [requirements section of the Kata Developer Guide](https://github.com/kata-containers/documentation/blob/master/Developer-Guide.md#requirements-to-build-individual-components).
- [Clone the upstream repository](https://help.github.com/articles/cloning-a-repository):
"Cloning" is a term that means to create a *local copy* of a Git repository
that generally lives on a remote server.
```sh
$ dir="$GOPATH/src/github.com/kata-containers"
$ mkdir -p "$dir"
$ cd "$dir"
$ git clone https://github.com/kata-containers/community
$ cd community
```
> **Note:** The previous Git command:
>
> - Creates a *local copy* of the upstream repository and switches to the
> `master` *branch*.
> - Creates an "alias" (name) for the upstream repository URL called `origin`.
There are now *three* copies of the repository (all *exactly* the same):
- The original upstream one (https://github.com/kata-containers/community)
You do not (and cannot) make changes to this repository. PRs are a way of
allowing the project developers and administrators to review your work and
decide if they want to add your work to the upstream branch.
> **Note:** Don't worry - even if you make a mistake,
> you *cannot* do any damage to this repository.
- Your fork (`https://github.com/${your-github-username}/community`) on GitHub
This is where you send or upload (`git push`) your PR branches.
- Your *local copy* of the upstream repository
(https://github.com/kata-containers/community)
This is where you actually make changes to your private copy of the
repository.
- [Setup a "git remote"](https://help.github.com/articles/configuring-a-remote-for-a-fork):
"What happened to my fork?". The following demonstrates where your fork is
and how you use it.
Recall that your fork on the GitHub server is an *exact copy* of the
upstream repository that also lives on the GitHub server. That might not be
true moving forward because PRs are constantly merged into the upstream
repository. This means your fork will be out of date because it will not
contain the latest changes in the upstream repository. The same
problem also affects your local copy of the upstream repository.
The way you keep your local copy up to date is to run `git pull`
periodically. This command downloads all the latest changes from "another
repository" into your local repository.
You might ask how Git knows which repository to pull changes from. Simply,
it defaults to pull from the repository you `git clone`'d in previous steps.
In Git terminology that default repository is given two names:
- The URL for the default upstream repository is called the `origin`.
- The local branch that Git puts the copy of the upstream repository into is
called `master`.
If you run `git push`, Git will try to upload any of your local changes
into the default repository (i.e. the `origin`). This will not work because
the `origin` is the upstream repository that you do not have permission to
change.
You need to tell Git that your changes should be uploaded to your fork on
the GitHub server when you `git push` This is done by adding what is called
a "remote":
```sh
$ user="your-github-username"
$ git remote add github https://github.com/${user}/community
```
> **Note:** The previous command adds an alias (name) for the URL of the
> fork you created on the GitHub server. This makes using the fork easier.
- Create a new "topic branch" to do your work on:
```sh
$ git checkout -b fix-doc-bugs
```
> **Warning:** *Never* make changes directly to the `master` branch -
> *always* create a new "topic branch" for PR work.
- Make some changes
In this example we modify the file you are reading:
```sh
$ $EDITOR CONTRIBUTING.md
```
- Commit your changes to the current (`fix-doc-bugs`) branch and make sure you
use the correct [patch format](#patch-format):
```sh
$ git commit -as
```
- Push your local `fix-doc-bugs` branch to your remote fork:
The following command uploads your changes to *your fork on the GitHub server*:
```sh
$ git push -u github
```
> **Note:** The `-u` option tells `git` to "link" your local clone with your
> remote fork so that it will know from now on that the local repository and
> the remote fork refer to "the same" upstream repository. Strictly, you
> only need to use this option the first time you call `git push` for a new
> clone.
- Create the PR:
- Browse to https://github.com/kata-containers/community.
- Click the "Compare & pull request" button that appears.
- Click the "Create pull request" button.
> **Note:** You do not need to change any of the defaults on this page.
The following is a summary of the components and terms we covered in this section:
| Thing | Description | Summary |
|-|-|-|
| https://github.com/kata-containers/community | Official repository URL. | upstream |
| `https://github.com/${your-github-username}/community` | URL of your remote copy of the official repository. | fork |
| `$GOPATH/src/github.com/kata-containers/community` | Location of your local copy of the repository. | checkout or clone |
| `master` | Local *branch* containing a copy of the upstream. | `master` branch |
| `origin` | The "remote" name for the official repository. | `origin` remote |
| `github` | The "remote" name for your remote fork. | `github` remote |
| `fix-doc-bugs` | Local *branch* containing your PR changes. | `fix-doc-bugs` branch |
You have setup your Git environment to do the following:
| Branch | Operation | Description |
|-|-|-|
| `master` | `git pull` | Downloads changes from the `origin` remote (upstream repository) into the local `master` branch |
| `fix-doc-bugs` | `git push` | Uploads changes from your local PR branch to your fork on the GitHub server |
##### Updating your PR based on review comments
Let's say you received some review feedback that asked you to make some
changes to your PR. You have updated your local branch and committed those
review changes by creating three commits. There are now four commits in your
local branch: the original commit you created for the PR and three other
commits you created to apply the review changes to your branch. Your branch
now looks something like this:
```sh
$ git log master.. --oneline --decorate=no
4928d57 docs: Fix typos and fold long lines
829c6c8 apply review feedback changes
7c9b1b2 remove blank lines
60e2b2b doh - missed one
```
> **Note:** The `git log` command compares your current branch (`fix-doc-bugs`)
> with the `master` branch and lists all the commmits, one per line.
Since all four commits are related to *the same change* to fix spelling mistakes
and break long lines up into shorter lines, it makes sense to combine all four
commits into a *single commit* on your PR. To do this, complete the following
steps:
- Update your branch
You need to ensure your local copy of the upstream branch contains the
latest changes.
- Rebase your changes against the `master` branch
This operation might seem scary, but it is the way Git allows you to merge
all of your changes together.
- Squash all the commits together
"Squashing" means to combine all your commits into a single commit. All the
changes you made are saved and associated with a single commit, rather than
being spread across four commits.
- Force-push the newly updated branch to your fork on GitHub
This updates your PR with your new (*single*) commit.
Taking each step in turn:
- Update your branch
First, update the `master` branch in your local copy of the upstream
repository:
```sh
$ cd $GOPATH/src/github.com/kata-containers/community
$ git checkout master
$ git pull
```
The previous command downloads all the latest changes from the upstream
repository and adds them to your *local copy*.
Now, switch back to your PR branch:
```sh
$ git checkout fix-doc-bugs
```
- Start the rebase operation
```sh
$ git rebase -i master
```
As an example, your editor window could appear as follows:
```
pick 2e335ac docs: Fix typos and fold long lines
pick 6d6deb0 apply review feedback changes
pick 23bc01d remove blank lines
pick 3a4ba3f doh - missed one
```
- In your editor, read the comments at the bottom of the screen. Next, without
modifying the first line (`pick 2e335ac docs: Fix typos and fold long
lines`), change the "`pick`" at the start of all the other lines to
"`squash`".
As an example, your editor window could appear as follows:
```
pick 2e335ac docs: Fix typos and fold long lines
squash 6d6deb0 apply review feedback changes
squash 23bc01d remove blank lines
squash 3a4ba3f doh - missed one
```
Next, save and quit the editor window and Git puts you *back* into your
editor. Now, instead of showing you all the one line commit summaries, you
will see all the commit *messages*. These messages are descriptions for all the
commits you created. At this point you can modify the file as you wish. Once
you save and exit the editor, Git uses whatever is left in the file as the
commit message for your "squashed' commit.
If you followed the example [first PR](#first-pr-example),
your first commit ("`2e335ac docs: Fix typos and fold long lines`")
is already in the [correct format](#patch-format). You keep the text for
your first commit and delete everything else in the editor window and update
if appropriate based on the review feedback.
Save the file and quit the editor. Once this operation completes, the four
commits will have been converted into a single new commit. Check this by
running the `git log` command again:
```sh
$ git log master.. --oneline --decorate=no
3ea3aef docs: Fix typo
```
- Force push your updated local `fix-doc-bugs` branch to your remote fork:
```sh
$ git push -f github
```
> **Notes:**
>
> - Not only does this command upload your changes to your fork, it also
> includes the *latest upstream changes* to your fork since you
> ran `git pull` in the master branch and then merged those changes into
> your PR branch. This is exactly what you want as your fork is now "up to
> date" with the upstream repository.
>
> - The `-f` option is a "force push". Since you created a new commit using
> `git rebase`, you must "overwrite" the old copy of your branch in your
> fork on GitHub. This is similar to saving a file in your editor because
> you are overwriting the old version you no longer want. GitHub
> recommends a force push to handle an update to your PR. This also means
> you do not have to create a new PR on GitHub because a force push
> effectively re-uses the initial PR you raised and includes your latest
> changes.
>
> For more information on GitHub "force push" workflows see "[Why and how to
> correctly amend GitHub pull
> requests](http://blog.adamspiers.org/2015/03/24/why-and-how-to-correctly-amend-github-pull-requests/)".
Your PR is now updated on GitHub. To ensure team member are aware of this,
leave a message on the PR stating something like, "review feedback applied".
Then, the team is notified and able to re-review your PR more quickly.
### Assisted PR workflow ### Assisted PR workflow
If your PR is deemed useful but you are struggling to update it based on If your PR is deemed useful but you are struggling to update it based on