diff --git a/_bookdown.yml b/_bookdown.yml index ed45244d..f3c58c40 100644 --- a/_bookdown.yml +++ b/_bookdown.yml @@ -40,6 +40,10 @@ rmd_files: [ "git-branches.Rmd", "git-remotes.Rmd", + "remote-scenarios-intro.Rmd", + "remote-scenarios-supported.Rmd", + "remote-scenarios-unsupported.Rmd", + "workflows-intro.Rmd", "workflows-repeated-amend.Rmd", "workflows-push-rejected.Rmd", diff --git a/img/fork-no-upstream.png b/img/fork-no-upstream.png new file mode 100644 index 00000000..8fd031ca Binary files /dev/null and b/img/fork-no-upstream.png differ diff --git a/img/fork-ours.png b/img/fork-ours.png new file mode 100644 index 00000000..32b16d70 Binary files /dev/null and b/img/fork-ours.png differ diff --git a/img/fork-them.png b/img/fork-them.png new file mode 100644 index 00000000..6f81c913 Binary files /dev/null and b/img/fork-them.png differ diff --git a/img/no_github.png b/img/no_github.png new file mode 100644 index 00000000..adc3312d Binary files /dev/null and b/img/no_github.png differ diff --git a/img/ours-them.png b/img/ours-them.png new file mode 100644 index 00000000..e54fcfcd Binary files /dev/null and b/img/ours-them.png differ diff --git a/img/ours-you.png b/img/ours-you.png new file mode 100644 index 00000000..8c4b78f3 Binary files /dev/null and b/img/ours-you.png differ diff --git a/img/theirs.png b/img/theirs.png new file mode 100644 index 00000000..565d9cf8 Binary files /dev/null and b/img/theirs.png differ diff --git a/packages.bib b/packages.bib index fe19ef15..18825926 100644 --- a/packages.bib +++ b/packages.bib @@ -3,27 +3,65 @@ @Manual{R-base author = {{R Core Team}}, organization = {R Foundation for Statistical Computing}, address = {Vienna, Austria}, - year = {2019}, + year = {2020}, url = {https://www.R-project.org/}, } @Manual{R-bookdown, title = {bookdown: Authoring Books and Technical Documents with R Markdown}, author = {Yihui Xie}, - year = {2019}, - note = {R package version 0.12}, + year = {2020}, + note = {R package version 0.19}, url = {https://CRAN.R-project.org/package=bookdown}, } @Manual{R-knitr, title = {knitr: A General-Purpose Package for Dynamic Report Generation in R}, author = {Yihui Xie}, - year = {2019}, - note = {R package version 1.24}, + year = {2020}, + note = {R package version 1.28}, url = {https://CRAN.R-project.org/package=knitr}, } @Manual{R-rmarkdown, title = {rmarkdown: Dynamic Documents for R}, author = {JJ Allaire and Yihui Xie and Jonathan McPherson and Javier Luraschi and Kevin Ushey and Aron Atkins and Hadley Wickham and Joe Cheng and Winston Chang and Richard Iannone}, - year = {2019}, - note = {R package version 1.15}, + year = {2020}, + note = {R package version 2.2}, url = {https://CRAN.R-project.org/package=rmarkdown}, } +@Book{bookdown2016, + title = {bookdown: Authoring Books and Technical Documents with {R} Markdown}, + author = {Yihui Xie}, + publisher = {Chapman and Hall/CRC}, + address = {Boca Raton, Florida}, + year = {2016}, + note = {ISBN 978-1138700109}, + url = {https://github.com/rstudio/bookdown}, +} +@Book{knitr2015, + title = {Dynamic Documents with {R} and knitr}, + author = {Yihui Xie}, + publisher = {Chapman and Hall/CRC}, + address = {Boca Raton, Florida}, + year = {2015}, + edition = {2nd}, + note = {ISBN 978-1498716963}, + url = {https://yihui.org/knitr/}, +} +@InCollection{knitr2014, + booktitle = {Implementing Reproducible Computational Research}, + editor = {Victoria Stodden and Friedrich Leisch and Roger D. Peng}, + title = {knitr: A Comprehensive Tool for Reproducible Research in {R}}, + author = {Yihui Xie}, + publisher = {Chapman and Hall/CRC}, + year = {2014}, + note = {ISBN 978-1466561595}, + url = {http://www.crcpress.com/product/isbn/9781466561595}, +} +@Book{rmarkdown2018, + title = {R Markdown: The Definitive Guide}, + author = {Yihui Xie and J.J. Allaire and Garrett Grolemund}, + publisher = {Chapman and Hall/CRC}, + address = {Boca Raton, Florida}, + year = {2018}, + note = {ISBN 9781138359338}, + url = {https://bookdown.org/yihui/rmarkdown}, +} diff --git a/remote-scenarios-intro.Rmd b/remote-scenarios-intro.Rmd new file mode 100644 index 00000000..fbd6aa4f --- /dev/null +++ b/remote-scenarios-intro.Rmd @@ -0,0 +1,9 @@ +# (PART) Remote scenarios {-} + +# Git remote setups {#remote-scenarios-intro .unnumbered} + +The previous part ended with some basics about [Git remotes](#git-remotes), such as how to define or rename one. Recall that a Git remote is another copy of the repo, usually living elsewhere (hence the term "remote"), that you can pull changes from or push changes to. Remotes are the foundation for all collaborative Git work. + +But knowing the mechanics of how to add or rename a remote does little good if you don't know *why* or *when* to do it. Luckily, we have very strong opinions about how you should set up your remotes, all motivated by getting you prepared for smooth, happy collaborative work. + +In this part we describe various remote setups that are common (for better or worse) and what they are good for (or what's wrong with them and how to fix). diff --git a/remote-scenarios-supported.Rmd b/remote-scenarios-supported.Rmd new file mode 100644 index 00000000..0180ed68 --- /dev/null +++ b/remote-scenarios-supported.Rmd @@ -0,0 +1,123 @@ +# Supported remote setups {#supported} + +We only consider a very constrained set of remotes here: + +* The remote is on GitHub, e.g. its URL looks something like `https://github.com/OWNER/REPO.git` or `git@github.com:OWNER/REPO.git`. +* The remote is named `origin` or `upstream`. These may not be the most evocative names in the world, but they are the most common choices. + +If you use a different host or different remote names, you should still be able to translate these examples to your setting. + +Along the way we note how these setups relate to the usethis package, i.e. how usethis can help you get into a favorable setup or how a favorable setup unlocks the full power of usethis. Many of these operations require that you have configured a GitHub personal access token. If you don't use usethis, feel free to ignore these asides. *2020-06 note: this currently refers to features in a development version of usethis. These features are not in v1.6.1 = the current CRAN version.* + +## No GitHub + +As a starting point, consider a local Git repo that is not yet connected to GitHub. + +```{r no_github, echo = FALSE, out.width = "60%"} +knitr::include_graphics("img/no_github.png") +``` + +This is not very exciting, but sets the stage for what's to come. We introduce the icon we use for a Git repo, which looks like a stack of coins or a barrel. This one is blue, which indicates you have write permission. + +`usethis::use_git()` can create this setup in a local project, i.e. it initializes a Git repo. usethis describes this setup as "no_github". + +## Ours (more specifically, mine) + +A common next step is to associate a local repo with a copy on GitHub, owned by you. + +```{r ours-you, echo = FALSE, out.width = "60%"} +knitr::include_graphics("img/ours-you.png") +``` + +A remote named `origin` is configured and you have permission to push to (and pull from) `origin`. The `origin` remote on GitHub is what we'll call a **primary** repo, meaning it is not a fork (or copy) of anything else on GitHub. + +`usethis::use_github()` can create this setup from a local repository, as long as you have configured a `GITHUB_PAT`. usethis describes this setup as "ours". + +## Ours + +Here is a variation on "ours" that is equivalent in practice. + +```{r ours-them, echo = FALSE, out.width = "60%"} +knitr::include_graphics("img/ours-them.png") +``` + +A remote named `origin` is configured and you can push to (and pull from) `origin`. As abvoe, `origin` is a **primary** repo, meaning it is not a fork (or copy) of anything else on GitHub. The `origin` remote is, however, not owned by you. Instead it's owned by another GitHub user or organisation. + +How does this happen? + +1. The primary repo is owned by an organisation and your role in this organisation confers enough power to create or push to a repo. +2. The owner of the primary repo has added you, specifically, as a collaborator to this specific repo. + +Way to get here with usethis: + +* GitHub repo exists first: `usethis::create_from_github("OWNER/REPO", fork = FALSE)`. +* Local repo exists first: `usethis::use_github(organisation = "OWNER")`. + +usethis describes this setup as "ours". + +## Theirs + +This is a setup that many people get themselves into, when it's not actually what they need. It's not broken *per se*, but it's limiting. + +```{r theirs, echo = FALSE, out.width = "60%"} +knitr::include_graphics("img/theirs.png") +``` + +You cannot push to the primary repo, which is configured as the `origin` remote. (This is indicated by the orange color of `origin` and the greyed out, dashed "push" arrow.) The primary repo is read-only for you. + +If you are taking a repo for a quick test drive, this configuration is fine. But there is no way to get changes back into the primary repo, since you cannot push to it and you haven't created a fork, which is necessary for a pull request. + +How does this happen? + +* Cloning the primary repo, either via `git clone` in the shell or through a Git client, such as RStudio. +* Calling `usethis::create_from_github()` when you haven't configured a GitHub personal access token, which forces `fork = FALSE`, because we can't create a fork. + +usethis describes this setup as "theirs". + +What if you do want to make a pull request? In hindsight, you should have done *fork-and-clone* instead of *clone*. If you've made no changes or they're easy to save somewhere temporarily, just start over with a fork-and-clone workflow (see below) and re-introduce your changes. It is also possible to preserve your work in a branch, fork the primary repo, re-configure your remotes, and get back on track. But this is much easier to goof up. + +## Fork (of theirs) + +This is an ideal setup for making a pull request and generally following the development of a primary repo owned by someone else. + +```{r fork-them, echo = FALSE, out.width = "60%"} +knitr::include_graphics("img/fork-them.png") +``` + +This shows a successful "fork-and-clone". Your local repo can pull changes from the primary repo, which is configured as `upstream`, which you cannot push to. You can push to your fork, which is configured as `origin`, and from there you can make a pull request back to the primary repo. + +How do we get here? + +`usethis::create_from_github("OWNER/REPO", fork = TRUE)` can create this setup, as long as you have configured a `GITHUB_PAT`. usethis describes this setup as "fork". + +## Fork (of ours) + +This is a less common variation on the fork setup. + +```{r fork-ours, echo = FALSE, out.width = "60%"} +knitr::include_graphics("img/fork-ours.png") +``` + +In this case, you have permission to push to the primary repo, but you elect to create a personal fork anyway. Certain projects favor this approach and it offers maximum development flexibility for advanced users. However, most users are better-served by the simpler "ours" setup in this case. + +`usethis::create_from_github("OWNER/REPO", fork = TRUE)` can create this setup, as long as you have configured a `GITHUB_PAT`. usethis describes this setup as "fork". + +## Fork (salvageable) + +Here is one last fork setup that's sub-optimal, but it can be salvaged. + +```{r fork-no-upstream, echo = FALSE, out.width = "60%"} +knitr::include_graphics("img/fork-no-upstream.png") +``` + +This is what happens when you do fork-and-clone and you *only* do fork-and-clone. What's missing is a connection back to the primary repo. + +How does this happen? + +* Cloning your own fork, either via `git clone` in the shell or through a Git client, such as RStudio. And then stopping here. + +If you only plan to make one pull request, this setup is fine. When the exchange is done, delete your local repo and your fork and move on with your life. You can always re-fork in the future. But if your pull request stays open for a while or if you plan to make repeated contributions, you'll need to pull ongoing developments in the primary repo into your local copy. + +You can add the primary repo as `upstream` in the shell or with `usethis::use_git_remote()`. Next time you do fork-and-clone, consider using `usethis::create_from_github(fork = TRUE)` instead. In addition to configuring the necessary remotes, `create_from_github()` implements other config that is favorable for making pull requests. + +Even if `upstream` is not (yet) configured, usethis still describes this setup as "fork". diff --git a/remote-scenarios-unsupported.Rmd b/remote-scenarios-unsupported.Rmd new file mode 100644 index 00000000..551075ca --- /dev/null +++ b/remote-scenarios-unsupported.Rmd @@ -0,0 +1,10 @@ +# Unsupported remote setups {#unsupported} + +Just like the previous section about more favorable setups, we only consider a very constrained set of remotes: + +* The remote is on GitHub. +* The remote is named `origin` or `upstream`. + +This section exists as counterpoint to the previous. Here we provide more details on remote setups that usethis can't work with and suggest improvements. *2020-06 note: this currently refers to features in a development version of usethis. These features are not in v1.6.1 = the current CRAN version.* + +*section coming soon*