The pr_* family of functions is designed to make working with GitHub pull requests (PRs) as painless as possible for both contributors and package maintainers. They are designed to support the Git and GitHub best practices described in Happy Git and GitHub for the useR.

To use the pr_* functions, your project must be a Git repo and have one of these GitHub remote configurations:

  • "ours": You can push to the GitHub remote configured as origin and it's not a fork.

  • "fork": You can push to the GitHub remote configured as origin, it's a fork, and its parent is configured as upstream. origin points to your personal copy and upstream points to the source repo.

"Ours" and "fork" are two of several GitHub remote configurations examined in Common remote setups in Happy Git.

The pr_* functions also use your Git/GitHub credentials to carry out various remote operations. See below for more.

pr_init(branch)

pr_resume(branch = NULL)

pr_fetch(number)

pr_push()

pr_pull()

pr_merge_main()

pr_sync()

pr_view()

pr_pause()

pr_finish(number = NULL)

Arguments

branch

branch name. Should usually consist of lower case letters, numbers, and -.

number

Number of PR to fetch.

Git/GitHub credentials

The pr_* functions interact with GitHub both as a conventional Git remote and via the REST API. Therefore, your credentials must be discoverable. Which credentials do we mean?

  • A GitHub personal access token (PAT) must be configured as the GITHUB_PAT environment variable. create_github_token() helps you do this. This PAT allows usethis to call the GitHub API on your behalf. If you use HTTPS remotes, the PAT is also used for Git operations, such as git push. That means the PAT is the only credential you need! This is why HTTPS + PAT is highly recommended for anyone new to Git and GitHub and PRs.

  • If you use SSH remotes, your SSH keys must also be discoverable, in addition to your PAT. The public key must be added to your GitHub account.

Usethis uses the gert package for Git operations (https://docs.ropensci.org/gert) and gert, in turn, relies on the credentials package (https://docs.ropensci.org/credentials/) for auth. If you have credential problems, focus your troubleshooting on getting the credentials package to find your credentials. Its introductory vignette is an excellent place to learn more: https://cran.r-project.org/web/packages/credentials/vignettes/intro.html.

If the pr_* functions need to configure a new remote, its transport protocol (HTTPS vs SSH) is determined by the protocol used for origin.

For contributors

To contribute to a package, first use create_from_github("OWNER/REPO", fork = TRUE) to fork the source repository, and then check out a local copy.

Next use pr_init() to create a branch for your PR. It is best practice to never make commits to the master (or default) branch of a fork, because you do not own it. A pull request should always come from a feature branch. It will be much easier to pull upstream changes from the fork parent if you only allow yourself to work in feature branches. It is also much easier for a maintainer to explore and extend your PR if you create a feature branch.

Work locally, in your branch, making changes to files, and committing your work. Once you're ready to create the PR, run pr_push() to push your local branch to GitHub, and open a webpage that lets you initiate the PR (or draft PR).

To learn more about the process of making a pull request, read the Pull Request Helpers vignette.

If you are lucky, your PR will be perfect, and the maintainer will accept it. You can then run pr_finish() to delete your PR branch. In most cases, however, the maintainer will ask you to make some changes. Make the changes, then run pr_push() to update your PR.

It's also possible that the maintainer will contribute some code to your PR: to get those changes back onto your computer, run pr_pull(). It can also happen that other changes have occurred in the package since you first created your PR. You might need to merge the master (or default) branch into your PR branch. Do that by running pr_merge_main(): this makes sure that your PR is compatible with the primary repo's main line of development. Both pr_pull() and pr_merge_main() can result in merge conflicts, so be prepared to resolve before continuing.

For maintainers

To download a PR locally so that you can experiment with it, run pr_fetch(<pr_number>). If you make changes, run pr_push() to push them back to GitHub. After you have merged the PR, run pr_finish() to delete the local branch and remove the remote associated with the contributor's fork.

Overview of all the functions

  • pr_init(): Does a preparatory pull from the primary repo, to get a good start point. Creates and checks out a new branch. Nothing is pushed to or created on GitHub. That only happens upon the first pr_push().

  • pr_resume(): Resume work on a PR by switching to its existing branch and pulling any updates from GitHub.

  • pr_fetch(): Checks out a PR on the primary repo for local exploration. This can cause a new remote to be configured and a new local branch to be created. The local branch is configured to track its remote counterpart. pr_fetch() puts a maintainer in a position where they can push changes into an external PR via pr_push().

  • pr_push(): The first time it's called, a PR branch is pushed to origin and you're taken to a webpage where a new PR (or draft PR) can be created. This also sets up the local branch to track its remote counterpart. Subsequent calls to pr_push() make sure the local branch has all the remote changes and, if so, pushes local changes, thereby updating the PR.

  • pr_pull(): Pulls changes from the local branch's remote tracking branch. If a maintainer has extended your PR, this is how you bring those changes back into your local work.

  • pr_merge_main(): Pulls changes from the master branch of the primary repo into the current local branch. This can be used when the local branch is master or when it's a PR branch.

  • pr_sync() = pr_pull() + pr_merge_main() + pr_push(). In words, grab any remote changes in the PR and merge then into your local work. Then merge in any changes from master of the primary repo. Finally, push the result of all this back into the PR.

  • pr_pause(): Makes sure you're up-to-date with any remote changes in the PR. Then switches back to master and pulls from the primary repo.

  • pr_view(): Visits the PR associated with a branch in the browser. usethis records this URL in git config of the local repo.

  • pr_finish(): If number is given, first does pr_fetch(number). It's assumed the current branch is the PR branch of interest. First, makes sure there are no unpushed local changes. Switches back to master and pulls changes from the primary repo. If the PR has been merged and user has permission, deletes the remote branch. Deletes the PR branch. If the PR came from an external fork, the corresponding remote is deleted, provided it's not in use by any other local branches.

Examples

if (FALSE) { pr_fetch(123) }