├── .github ├── .gitignore └── workflows │ └── bookdown.yaml ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── README.md ├── _bookdown.yml ├── _output.yml ├── appendix.Rmd ├── book.bib ├── child-clone-a-github-repo.Rmd ├── child-create-a-github-repo.Rmd ├── child-the-end-of-repo-setup.Rmd ├── comic-relief.Rmd ├── connect-can-rstudio-use-git.Rmd ├── connect-git-github.Rmd ├── connect-https-pat.Rmd ├── connect-intro.Rmd ├── connect-rstudio-git-github.Rmd ├── connect-ssh-keys.Rmd ├── connect-troubleshooting.Rmd ├── contributors.Rmd ├── ga_script.html ├── git-basics.Rmd ├── git-branches.Rmd ├── git-commands.Rmd ├── git-intro.Rmd ├── git-refs.Rmd ├── git-remotes.Rmd ├── happy-git-with-r.Rproj ├── img ├── 2018-01-15_bash-windows-services-for-linux.png ├── 2018-01-15_command-prompt.png ├── 2018-01-15_git-bash.png ├── 2018-01-15_power-shell.png ├── 2019-01-git-windows-administrator.png ├── 2019-01_git_bash_windows.png ├── 440px-Bash_screenshot.png ├── _combine-github-configs.R ├── clone-theirs.png ├── clone-yours.png ├── command-line-git-screenshot.png ├── commit-diff-sha-tag.png ├── fork-and-clone.jpeg ├── fork-and-clone.png ├── fork-no-upstream-sad.jpeg ├── fork-ours.jpeg ├── fork-them-pull-request.jpeg ├── fork-them.jpeg ├── fork-triangle-happy.png ├── fork.png ├── fork_upstream_is_not_origin_parent.jpeg ├── git-bash-as-rstudio-terminal.png ├── git-fork-new-project-push-pull-request.png ├── git-fork-update.jpg ├── git-therapy.jpg ├── git-via-ssh-or-https-github-api.png ├── github-https-or-ssh-url-annotated.png ├── github-https-url.png ├── github-pull-push.jpeg ├── github-screenshot-copy-the-full-sha.png ├── github-ssh-url.png ├── gitkraken-pkgdown-screenshot.png ├── gitkraken-screenshot-copy-commit-sha.png ├── maybe_fork.jpeg ├── maybe_ours_or_theirs.jpeg ├── new-personal-access-token-screenshot.png ├── new-project-github-first.jpeg ├── no-github.jpeg ├── ours-them.jpeg ├── ours-you.jpeg ├── pat-kills-both-birds.jpeg ├── pull-push-yours.png ├── refs-branches-and-HEAD-1.jpeg ├── refs-branches-and-HEAD-2.jpeg ├── refs-only-branches.jpeg ├── refs-only-shas.jpeg ├── refs-relative.jpeg ├── refs-tag.jpeg ├── rstudio-new-branch.png ├── screenshots │ ├── github-commit-listing.png │ ├── github-link-to-commits.png │ ├── github-repo-search.png │ └── github-specific-file.png ├── six-configs.png ├── sourcetree-screenshot.png ├── terminal_mac.png ├── terminal_mac_search.png ├── theirs.jpeg ├── updating_a_git_fork.pdf ├── updating_a_git_fork.png ├── use_github.jpeg ├── watch-me-diff-watch-me-rebase-smaller.png └── windows-rstudio-git-executable-screenshot.png ├── index.Rmd ├── install-git-client.Rmd ├── install-git.Rmd ├── install-github-acct.Rmd ├── install-intro.Rmd ├── install-introduce-self-git.Rmd ├── install-r-rstudio.Rmd ├── notes-bookdown-cheat-sheet.Rmd ├── notes-classroom-overview.Rmd ├── notes-ideas.Rmd ├── notes-intro.Rmd ├── overview.Rmd ├── packages.bib ├── preamble.tex ├── process-github-config-diagrams-for-happy-git.R ├── prompt-burn-it-all-down.Rmd ├── prompt-clone.Rmd ├── prompt-fork-pr-bingo.Rmd ├── prompt-practice-resets.Rmd ├── prompt-search-github.Rmd ├── references.Rmd ├── remote-setups-common.Rmd ├── remote-setups-equivocal.Rmd ├── remote-setups-intro.Rmd ├── render-r-script-demo.md ├── shell.Rmd ├── style.css ├── toc.css ├── usage-existing-project-github-first.Rmd ├── usage-existing-project-github-last.Rmd ├── usage-intro.Rmd ├── usage-new-project-github-first.Rmd ├── usage-r-script-and-github.Rmd ├── usage-rmd-and-github.Rmd ├── workflows-explore-extend-pull-request.Rmd ├── workflows-fork-and-clone.Rmd ├── workflows-intro.Rmd ├── workflows-make-github-repo-browsable.Rmd ├── workflows-pull.Rmd ├── workflows-push-rejected.Rmd ├── workflows-repeated-amend.Rmd ├── workflows-see-the-past.Rmd ├── workflows-upstream-changes-into-fork.Rmd └── workshops.Rmd /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/bookdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | schedule: 9 | # run every day at 11 PM 10 | - cron: '0 23 * * *' 11 | workflow_dispatch: 12 | 13 | name: bookdown.yaml 14 | 15 | permissions: read-all 16 | 17 | jobs: 18 | bookdown: 19 | runs-on: ubuntu-latest 20 | # Only restrict concurrency for non-PR jobs 21 | concurrency: 22 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} 23 | env: 24 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 25 | isExtPR: ${{ github.event.pull_request.head.repo.fork == true }} 26 | permissions: 27 | contents: write 28 | steps: 29 | - uses: actions/checkout@v4 30 | 31 | - uses: r-lib/actions/setup-pandoc@v2 32 | 33 | - uses: r-lib/actions/setup-r@v2 34 | with: 35 | use-public-rspm: true 36 | 37 | - uses: r-lib/actions/setup-r-dependencies@v2 38 | 39 | - name: Cache bookdown results 40 | uses: actions/cache@v4 41 | with: 42 | path: _bookdown_files 43 | key: bookdown-${{ hashFiles('**/*Rmd') }} 44 | restore-keys: bookdown- 45 | 46 | - name: Configure Git user 47 | run: | 48 | git config --local user.name "$GITHUB_ACTOR" 49 | git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com" 50 | 51 | - name: Build site 52 | run: bookdown::render_book("index.Rmd", quiet = TRUE) 53 | shell: Rscript {0} 54 | 55 | - name: Deploy to Netlify 56 | if: contains(env.isExtPR, 'false') 57 | id: netlify-deploy 58 | uses: nwtgck/actions-netlify@v3.0 59 | with: 60 | publish-dir: './_book' 61 | production-branch: main 62 | github-token: ${{ secrets.GITHUB_TOKEN }} 63 | deploy-message: 64 | 'Deploy from GHA: ${{ github.event.pull_request.title || github.event.head_commit.message }} (${{ github.sha }})' 65 | # these all default to 'true' 66 | enable-pull-request-comment: false 67 | enable-commit-comment: false 68 | # enable-commit-status: true 69 | #o verwrites-pull-request-comment: true 70 | env: 71 | NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} 72 | NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} 73 | timeout-minutes: 1 74 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | README.html 5 | _book 6 | _bookdown_files 7 | render-r-script-demo.html 8 | happygitwithr.rds 9 | .netlify 10 | .Rbuildignore 11 | img/github-configs 12 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: happygitwithr 2 | Title: Happy Git and GitHub for the useR 3 | Version: 0.1 4 | Authors@R: 5 | person("Jennifer", "Bryan", , "jenny@rstudio.com", role = c("aut", "cre"), 6 | comment = c(ORCID = "0000-0002-6983-2759")) 7 | Description: This is not a package, but we just use this file to declare 8 | the dependencies of the site. 9 | URL: https://happygitwithr.com 10 | Imports: 11 | bookdown, 12 | bslib, 13 | downlit (>= 0.4.1.9000), 14 | fs, 15 | glue, 16 | readr, 17 | sessioninfo, 18 | xml2 19 | Encoding: UTF-8 20 | Remotes: 21 | r-lib/downlit 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This work is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/4.0/. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Rendered product: 2 | 3 | 4 | [![bookdown](https://github.com/jennybc/happy-git-with-r/actions/workflows/bookdown.yaml/badge.svg)](https://github.com/jennybc/happy-git-with-r/actions/workflows/bookdown.yaml) 5 | [![Netlify Status](https://api.netlify.com/api/v1/badges/4e9fea2e-d99c-484e-be1a-9d8605393f4e/deploy-status)](https://app.netlify.com/sites/happygitwithr/deploys) 6 | Creative Commons License 7 | 8 | -------------------------------------------------------------------------------- /_bookdown.yml: -------------------------------------------------------------------------------- 1 | book_filename: "happygitwithr" 2 | language: 3 | ui: 4 | chapter_name: "Chapter " 5 | delete_merged_file: true 6 | new_session: true 7 | 8 | rmd_files: [ 9 | "index.Rmd", 10 | 11 | "overview.Rmd", 12 | "contributors.Rmd", 13 | "workshops.Rmd", 14 | 15 | "install-intro.Rmd", 16 | "install-github-acct.Rmd", 17 | "install-r-rstudio.Rmd", 18 | "install-git.Rmd", 19 | "install-introduce-self-git.Rmd", 20 | "install-git-client.Rmd", 21 | 22 | "connect-intro.Rmd", 23 | "connect-https-pat.Rmd", 24 | "connect-ssh-keys.Rmd", 25 | "connect-git-github.Rmd", 26 | "connect-rstudio-git-github.Rmd", 27 | "connect-can-rstudio-use-git.Rmd", 28 | "connect-troubleshooting.Rmd", 29 | 30 | "usage-intro.Rmd", 31 | "usage-new-project-github-first.Rmd", 32 | "usage-existing-project-github-first.Rmd", 33 | "usage-existing-project-github-last.Rmd", 34 | "usage-rmd-and-github.Rmd", 35 | "usage-r-script-and-github.Rmd", 36 | 37 | "git-intro.Rmd", 38 | "git-basics.Rmd", 39 | "git-commands.Rmd", 40 | "git-branches.Rmd", 41 | "git-remotes.Rmd", 42 | "git-refs.Rmd", 43 | 44 | "remote-setups-intro.Rmd", 45 | "remote-setups-common.Rmd", 46 | "remote-setups-equivocal.Rmd", 47 | 48 | "workflows-intro.Rmd", 49 | "workflows-repeated-amend.Rmd", 50 | "workflows-push-rejected.Rmd", 51 | "workflows-pull.Rmd", 52 | "workflows-see-the-past.Rmd", 53 | "workflows-fork-and-clone.Rmd", 54 | "workflows-upstream-changes-into-fork.Rmd", 55 | "workflows-explore-extend-pull-request.Rmd", 56 | "workflows-make-github-repo-browsable.Rmd", 57 | 58 | "prompt-clone.Rmd", 59 | "prompt-fork-pr-bingo.Rmd", 60 | "prompt-burn-it-all-down.Rmd", 61 | "prompt-practice-resets.Rmd", 62 | "prompt-search-github.Rmd", 63 | 64 | "notes-intro.Rmd", 65 | "notes-classroom-overview.Rmd", 66 | "notes-ideas.Rmd", 67 | "notes-bookdown-cheat-sheet.Rmd", 68 | 69 | "appendix.Rmd", 70 | "shell.Rmd", 71 | "comic-relief.Rmd", 72 | 73 | "references.Rmd" 74 | ] 75 | -------------------------------------------------------------------------------- /_output.yml: -------------------------------------------------------------------------------- 1 | bookdown::bs4_book: 2 | theme: 3 | primary: "#4D6F8D" 4 | repo: 5 | base: https://github.com/jennybc/happy-git-with-r 6 | branch: main 7 | includes: 8 | in_header: [ga_script.html] 9 | bookdown::gitbook: 10 | includes: 11 | in_header: [ga_script.html] 12 | css: style.css 13 | split_bib: FALSE 14 | config: 15 | sharing: 16 | github: yes 17 | facebook: false 18 | twitter: false 19 | download: false 20 | toc: 21 | collapse: section 22 | before: | 23 |
  • Happy Git and GitHub for the useR
  • 24 | after: | 25 |
  • Published with bookdown
  • 26 | edit: https://github.com/jennybc/happy-git-with-r/edit/main/%s 27 | -------------------------------------------------------------------------------- /appendix.Rmd: -------------------------------------------------------------------------------- 1 | # (APPENDIX) Appendix {-} 2 | -------------------------------------------------------------------------------- /book.bib: -------------------------------------------------------------------------------- 1 | @Book{knitr-book, 2 | title = {Dynamic Documents with {R} and knitr}, 3 | author = {Yihui Xie}, 4 | publisher = {Chapman and Hall/CRC}, 5 | address = {Boca Raton, Florida}, 6 | year = {2015}, 7 | edition = {2nd}, 8 | note = {ISBN 978-1498716963}, 9 | url = {http://yihui.name/knitr/}, 10 | } 11 | 12 | @Article{Ram2013, 13 | author="Ram, Karthik", 14 | title="Git can facilitate greater reproducibility and increased transparency in science", 15 | journal="Source Code for Biology and Medicine", 16 | year="2013", 17 | volume="8", 18 | number="1", 19 | pages="7", 20 | abstract="Reproducibility is the hallmark of good science. Maintaining a high degree of transparency in scientific reporting is essential not just for gaining trust and credibility within the scientific community but also for facilitating the development of new ideas. Sharing data and computer code associated with publications is becoming increasingly common, motivated partly in response to data deposition requirements from journals and mandates from funders. Despite this increase in transparency, it is still difficult to reproduce or build upon the findings of most scientific publications without access to a more complete workflow.", 21 | issn="1751-0473", 22 | doi="10.1186/1751-0473-8-7", 23 | url="http://dx.doi.org/10.1186/1751-0473-8-7" 24 | } 25 | 26 | @article{good-enough, 27 | author = {Greg Wilson and 28 | Jennifer Bryan and 29 | Karen Cranston and 30 | Justin Kitzes and 31 | Lex Nederbragt and 32 | Tracy K. Teal}, 33 | title = {Good Enough Practices in Scientific Computing}, 34 | journal = {CoRR}, 35 | volume = {abs/1609.00037}, 36 | year = {2016}, 37 | url = {http://arxiv.org/abs/1609.00037}, 38 | timestamp = {Mon, 03 Oct 2016 17:51:10 +0200}, 39 | biburl = {http://dblp.uni-trier.de/rec/bib/journals/corr/WilsonBCKNT16}, 40 | bibsource = {dblp computer science bibliography, http://dblp.org} 41 | } 42 | 43 | @misc{git-for-humans, 44 | Author = "Alice Bartlett", 45 | Title = "Git for Humans", 46 | Institution = "Financial Times, London", 47 | Howpublished = "Talk at UX Brighton", 48 | Year = "2016", 49 | Url = "https://speakerdeck.com/alicebartlett/git-for-humans", 50 | Abstract = "This talk will explore a tool that most developers couldn't live without. We'll look at the way it helps developers tell the story of their project, and how non-technical people can get in on the action too." 51 | } 52 | 53 | @Manual{rmd-pkg, 54 | title = {rmarkdown: Dynamic Documents for R}, 55 | author = {JJ Allaire and Joe Cheng and Yihui Xie and Jonathan McPherson and Winston Chang and Jeff Allen and Hadley Wickham and Aron Atkins and Rob Hyndman and Ruben Arslan}, 56 | year = {2017}, 57 | note = {R package version 1.5.9000}, 58 | url = {http://rmarkdown.rstudio.com}, 59 | } 60 | 61 | @Manual{knitr-pkg, 62 | title = {knitr: A General-Purpose Package for Dynamic Report 63 | Generation in R}, 64 | author = {Yihui Xie}, 65 | year = {2017}, 66 | note = {R package version 1.16}, 67 | url = {http://yihui.name/knitr/}, 68 | } 69 | 70 | 71 | @article{ten-simple-rules-git, 72 | author = {Yasset Perez-Riverol and 73 | Laurent Gatto and 74 | Rui Wang and 75 | Timo Sachsenberg and 76 | Julian Uszkoreit and 77 | Felipe da Veiga Leprevost and 78 | Christian Fufezan and 79 | Tobias Ternent and 80 | Stephen J. Eglen and 81 | Daniel S. Katz and 82 | Tom J. Pollard and 83 | Alexander Konovalov and 84 | Robert M. Flight and 85 | Kai Blin and 86 | Juan Antonio Vizcaíno}, 87 | journal = {PLOS Computational Biology}, 88 | publisher = {Public Library of Science}, 89 | title = {Ten Simple Rules for Taking Advantage of Git and GitHub}, 90 | year = {2016}, 91 | month = {07}, 92 | volume = {12}, 93 | url = {https://doi.org/10.1371/journal.pcbi.1004947}, 94 | pages = {1-11}, 95 | abstract = {}, 96 | number = {7}, 97 | doi = {10.1371/journal.pcbi.1004947} 98 | } 99 | 100 | @Manual{bookdown-pkg, 101 | title = {bookdown: Authoring Books and Technical Documents with R Markdown}, 102 | author = {Yihui Xie}, 103 | year = {2016}, 104 | note = {R package version 0.3}, 105 | url = {https://github.com/rstudio/bookdown}, 106 | } 107 | 108 | @Book{bookdown-book, 109 | title = {bookdown: Authoring Books and Technical Documents with {R} Markdown}, 110 | author = {Yihui Xie}, 111 | publisher = {Chapman and Hall/CRC}, 112 | address = {Boca Raton, Florida}, 113 | year = {2017}, 114 | note = {ISBN 978-1138700109}, 115 | url = {https://github.com/rstudio/bookdown}, 116 | } 117 | 118 | @manual{git, 119 | title = {Git}, 120 | url = {https://git-scm.com} 121 | } 122 | 123 | @manual{github, 124 | title = {GitHub}, 125 | url = {https://github.com} 126 | } 127 | 128 | @manual{rstudio, 129 | title = {RStudio Integrated Desktop Environment}, 130 | url = {https://www.rstudio.com/products/rstudio} 131 | } 132 | 133 | @manual{r, 134 | title = {R: A Language and Environment for Statistical Computing}, 135 | author = {{R Core Team}}, 136 | organization = {R Foundation for Statistical Computing}, 137 | address = {Vienna, Austria}, 138 | year = {2017}, 139 | url = {https://www.R-project.org} 140 | } 141 | 142 | @misc{donoho, 143 | author = {David Donoho}, 144 | title = {50 years of Data Science}, 145 | institution = {Stanford University}, 146 | howpublished = {Version 1.00}, 147 | month = {September}, 148 | year = {2015}, 149 | url = {http://courses.csail.mit.edu/18.337/2015/docs/50YearsDataScience.pdf} 150 | } 151 | 152 | @article{cetinkaya-rundel-dss-2017, 153 | title = {Infrastructure and tools for teaching computing throughout the statistical curriculum}, 154 | author = {Cetinkaya-Rundel, Mine and Rundel, Colin W}, 155 | year = 2017, 156 | month = aug, 157 | keywords = {R markdown, git / github, reproducibility, data science, workflow, R language, Continuous integration, RStudio, teaching, cirriculum}, 158 | abstract = { 159 | Modern statistics is fundamentally a computational discipline, but too often this fact is not reflected in our statistics curricula. With the rise of big data and data science it has become increasingly clear that students both want, expect, and need explicit training in this area of the discipline. Additionally, recent curricular guidelines clearly state that working with data requires extensive computing skills and that statistics students should be fluent in accessing, manipulating, analyzing, and modeling with professional statistical analysis software. Much has been written in the statistics education literature about pedagogical tools and approaches to provide a practical computational foundation for students. This article discusses the computational infrastructure and toolkit choices to allow for these pedagogical innovations while minimizing frustration and improving adoption for both our students and instructors. 160 | }, 161 | volume = 5, 162 | pages = {e3181v1}, 163 | journal = {PeerJ Preprints}, 164 | issn = {2167-9843}, 165 | url = {https://doi.org/10.7287/peerj.preprints.3181v1}, 166 | doi = {10.7287/peerj.preprints.3181v1} 167 | } 168 | 169 | @article {fisher, 170 | author = {FISHER, R. A.}, 171 | title = {THE USE OF MULTIPLE MEASUREMENTS IN TAXONOMIC PROBLEMS}, 172 | journal = {Annals of Eugenics}, 173 | volume = {7}, 174 | number = {2}, 175 | publisher = {Blackwell Publishing Ltd}, 176 | issn = {2050-1439}, 177 | url = {http://dx.doi.org/10.1111/j.1469-1809.1936.tb02137.x}, 178 | doi = {10.1111/j.1469-1809.1936.tb02137.x}, 179 | pages = {179--188}, 180 | year = {1936}, 181 | } 182 | 183 | @article{anderson, 184 | ISSN = {00266493}, 185 | URL = {http://www.jstor.org/stable/2394164}, 186 | author = {Edgar Anderson}, 187 | journal = {Annals of the Missouri Botanical Garden}, 188 | number = {3}, 189 | pages = {457-509}, 190 | publisher = {Missouri Botanical Garden Press}, 191 | title = {The Species Problem in Iris}, 192 | volume = {23}, 193 | year = {1936} 194 | } 195 | 196 | @book{r-pkgs-book, 197 | author = {Wickham, Hadley}, 198 | title = {R Packages}, 199 | year = {2015}, 200 | isbn = {1491910593, 9781491910597}, 201 | edition = {1st}, 202 | publisher = {O'Reilly Media, Inc.} 203 | } 204 | -------------------------------------------------------------------------------- /child-clone-a-github-repo.Rmd: -------------------------------------------------------------------------------- 1 | ```{r} 2 | #| echo = FALSE, fig.align = "center", out.width = "60%", 3 | #| fig.alt = "Clone a remote repo." 4 | knitr::include_graphics("img/new-project-github-first.jpeg") 5 | ``` 6 | 7 | I present two ways to do this: 8 | 9 | * `usethis::create_from_github()` 10 | * Via the RStudio IDE 11 | 12 | *(Recall that we showed how to do this with command line Git in chapter \@ref(push-pull-github).)* 13 | 14 | When you are cloning your own GitHub repository, the two methods are equivalent. 15 | In other scenarios, especially fork-and-clone (chapter \@ref(fork-and-clone)), I think `usethis::create_from_github()` is superior, because it does additional, recommended setup. 16 | 17 | Pick **one** of these methods below. 18 | 19 | ### `usethis::create_from_github()` 20 | 21 | You can execute this command in any R session. 22 | If you use RStudio, then do this in the R console of any RStudio instance. 23 | 24 | ```{r eval = FALSE} 25 | usethis::create_from_github( 26 | "https://github.com/YOU/YOUR_REPO.git", 27 | destdir = "~/path/to/where/you/want/the/local/repo/" 28 | ) 29 | ``` 30 | 31 | The first argument is `repo_spec` and it accepts the GitHub repo specification in various forms. 32 | In particular, you can use the URL we just copied from GitHub. 33 | 34 | The `destdir` argument specifies the parent directory where you want the new folder (and local Git repo) to live. 35 | If you don't specify `destdir`, usethis defaults to some very conspicuous place, like your desktop. 36 | If you like to keep Git repos in a certain folder on your computer, you can personalize this default by setting the `usethis.destdir` option in your `.Rprofile`. 37 | 38 | We're accepting the default behaviour of two other arguments, `rstudio` and `open`, because that's what most people will want. 39 | For example, for an RStudio user, `create_from_github()` does this: 40 | 41 | * Creates a new local directory in `destdir`, which is all of these things: 42 | - a directory or folder on your computer 43 | - a Git repository, linked to a remote GitHub repository 44 | - an RStudio Project 45 | * Opens a new RStudio instance in the new Project 46 | * **In the absence of other constraints, I suggest that all of your R projects have exactly this set-up.** 47 | 48 | ### RStudio IDE 49 | 50 | In RStudio, start a new Project: 51 | 52 | * *File > New Project > Version Control > Git*. In the "repository URL" paste 53 | the URL of your new GitHub repository. It will be something like this 54 | `https://github.com/jennybc/myrepo.git`. 55 | * Be intentional about where you create this Project. 56 | * I suggest you "Open in new session". 57 | * Click "Create Project" to create a new directory, which will be all of these things: 58 | - a directory or "folder" on your computer 59 | - a Git repository, linked to a remote GitHub repository 60 | - an RStudio Project 61 | * **In the absence of other constraints, I suggest that all of your R projects have exactly this set-up.** 62 | 63 | This should download the `README.md` file that we created on GitHub in the previous step. 64 | Look in RStudio's file browser pane for the `README.md` file. 65 | 66 | Behind the scenes, RStudio has done this for you: 67 | 68 | ```console 69 | git clone https://github.com/jennybc/myrepo.git 70 | ``` 71 | -------------------------------------------------------------------------------- /child-create-a-github-repo.Rmd: -------------------------------------------------------------------------------- 1 | Go to and make sure you are logged in. 2 | 3 | Near "Repositories", click the big green "New" button. 4 | Or, if you are on your own profile page, click on "Repositories", then click the big green "New" button. 5 | 6 | How to fill this in: 7 | 8 | * Repository template: No template. 9 | * Repository name: <<>> 10 | * Description: <<>> 11 | * Public. 12 | * <<>> 13 | 14 | Click the big green button that says "Create repository". 15 | 16 | Now click the big green button that says "<> Code". 17 | 18 | Copy a clone URL to your clipboard. 19 | If you're taking our default advice, copy the HTTPS URL. 20 | But if you're opting for SSH, then make sure to copy the SSH URL. 21 | 22 | ```{r} 23 | #| echo = FALSE, fig.align = "center", out.width = "60%", 24 | #| fig.alt = "Selecting an HTTPS vs SSH URL on GitHub" 25 | knitr::include_graphics("img/github-https-or-ssh-url-annotated.png") 26 | ``` 27 | -------------------------------------------------------------------------------- /child-the-end-of-repo-setup.Rmd: -------------------------------------------------------------------------------- 1 | Now just "lather, rinse, repeat". 2 | Do work somewhere: locally or on GitHub. 3 | Commit it. 4 | Push it or pull it, depending on where you did the work, but get local and remote "synced up". 5 | Repeat. 6 | 7 | Note that in general (and especially in future when collaborating with other developers) you will usually need to pull changes from the remote (GitHub) before pushing the local changes you have made. 8 | For this reason, it's a good idea to try and get into the habit of pulling before you attempt to push. 9 | -------------------------------------------------------------------------------- /comic-relief.Rmd: -------------------------------------------------------------------------------- 1 | # Comic relief {#comic-relief} 2 | 3 | It's not you, it's Git! 4 | 5 | If you're not crying already, these fictional-but-realistic Git man pages should do the trick: 6 | 7 | * [git-man-page-generator](http://git-man-page-generator.lokaltog.net) 8 | * And, of course, the underlying source is also available on GitHub: 9 | - 10 | 11 | If you can tolerate adult and often offensive language, you might enjoy: 12 | 13 | * 14 | * 15 | 16 | Your commits will look more glorious scrolling by Star Wars style: 17 | 18 | * 19 | * 20 | * Do this for any repo: `http://starlogs.net/#USER/REPO` 21 | 22 | -------------------------------------------------------------------------------- /connect-can-rstudio-use-git.Rmd: -------------------------------------------------------------------------------- 1 | # Detect Git from RStudio {#rstudio-see-git} 2 | 3 | If you want RStudio to help with your Git and GitHub work, it must be able to find the Git executable. 4 | 5 | This usually "just works", so this page is aimed at people who have reason to suspect they have a problem. 6 | 7 | This is something you set up once-per-computer. 8 | 9 | ## Do you have a problem? 10 | 11 | Let's check if RStudio can find the Git executable. 12 | 13 | * *File > New Project...* Do you see an option to create from Version Control? If yes, good. 14 | * Select *New Directory* > *Empty Project*. Do you see a checkbox "Create a git repository"? If yes, good, CHECK IT. 15 | 16 | Keep reading if things don't go so well or you want to know more. 17 | 18 | ## Find Git yourself 19 | 20 | RStudio can only act as a GUI front-end for Git if Git has been successfully installed (chapter \@ref(install-git)) **AND RStudio can find it**. 21 | 22 | A basic test for successful installation of Git is to simply enter `git` in the shell (Appendix \@ref(shell)). 23 | If you get a complaint about Git not being found, it means installation was unsuccessful or that it is not being found, i.e. it is not on your `PATH`. 24 | 25 | If you are not sure where the Git executable lives, try this in a shell: 26 | 27 | * `which git` (Mac, Linux, Git Bash shell on Windows) 28 | 29 | * `where git` (Windows command prompt, i.e. `cmd.exe`) 30 | 31 | ## Tell RStudio where to find Git 32 | 33 | If Git appears to be installed and findable, launch RStudio. 34 | Quit and re-launch RStudio if there's **any doubt in your mind** about whether you opened RStudio before or after installing Git. 35 | Don't make me stop this car and restart RStudio for you in office hours. 36 | DO IT. 37 | 38 | From RStudio, go to *Tools > Global Options > Git/SVN* and make sure that the box *Git executable* points to your Git executable. 39 | 40 | On macOS and Linux, the path usually looks something like this: 41 | 42 | ```console 43 | /usr/bin/git 44 | ``` 45 | 46 | If you need to set this on macOS, it can sometimes be hard to navigate to the necessary directory, once you've clicked "Browse" and are working with a Finder-type window. 47 | The keyboard shortcut "command + shift + g" will summon "Go To Folder", where you will be able to type or paste any path you want. 48 | 49 | On Windows, this path should look something like this: 50 | 51 | ``` bash 52 | C:/Program Files/Git/bin/git.exe 53 | ``` 54 | 55 | and here is a screenshot on Windows: 56 | 57 | ```{r} 58 | #| echo = FALSE, fig.align = "center", out.width = "100%", 59 | #| fig.alt = "RStudio screenshot showing path to the Git executable" 60 | knitr::include_graphics("img/windows-rstudio-git-executable-screenshot.png") 61 | ``` 62 | 63 | **WARNING**: On Windows, do __NOT__ use `C:/Program Files/Git/cmd/git.exe`. `bin` in the path is GOOD YES! 64 | `cmd` in the path is BAD NO! 65 | 66 | **WARNING**: On Windows, do __NOT__ set this to `git-bash.exe`. 67 | Something that ends in `git.exe` is GOOD YES! `git-bash.exe` is BAD NO! 68 | 69 | **Restart RStudio if you make any changes here.** 70 | Don't make me stop this car again and restart RStudio for you in office hours. 71 | DO IT. 72 | 73 | Re-do the steps at the top of the page to see if RStudio and Git are communicating now. 74 | 75 | No joy? 76 | 77 | * I've seen this help: With your Project open, go to `Tools > Project Options...`. If available, click on "Git/SVN" and select "Git" in the Version control system dropdown menu. Answer "yes" to the "Confirm New Git Repository" pop up. Answer "yes" to the "Confirm Restart RStudio" pop up. 78 | 79 | * If you installed Git via GitHub for Windows, it is possible the Git executable is really well hidden. Get help or use one of [our recommended methods of installing Git](#install-git). 80 | 81 | * Your `PATH` is probably not set up correctly and/or you should re-install Git and control/notice where it's going. Read more in \@ref(troubleshooting). 82 | 83 | * Get our help. 84 | -------------------------------------------------------------------------------- /connect-git-github.Rmd: -------------------------------------------------------------------------------- 1 | # Connect to GitHub {#push-pull-github} 2 | 3 | Objective: make sure that you can pull from and push to GitHub from your computer. 4 | 5 | I do not explain all the shell (Appendix \@ref(shell)) and Git commands in detail. 6 | This is a black box diagnostic / configuration exercise. 7 | In later chapters and in live workshops, we revisit these operations with much more narrative and discussion of alternative workflows. 8 | 9 | I assume you've decided whether to use HTTPS (see chapter \@ref(https-pat)) or SSH (see chapter \@ref(ssh-keys)) and you've prepared your credential. 10 | 11 | ## Make a repo on GitHub 12 | 13 | ```{r echo = FALSE, results = "asis"} 14 | dat <- list( 15 | repository_name_text = glue::glue(" 16 | `myrepo` or whatever you wish (we'll delete this soon)."), 17 | description_text = glue::glue(" 18 | \"Repository for testing my Git/GitHub setup\" or similar. It's nice to \\ 19 | have something here, so you'll see it appear in the README."), 20 | initialize_text = "Initialize this repository with: Add a README file." 21 | ) 22 | insert <- glue::glue_data( 23 | dat, 24 | readr::read_file("child-create-a-github-repo.Rmd"), 25 | .open = "<<<", .close = ">>>" 26 | ) 27 | res <- knitr::knit_child(text = insert, quiet = TRUE) 28 | cat(res, sep = '\n') 29 | ``` 30 | 31 | ## Clone the repo to your local computer {#git-clone-command-line} 32 | 33 | We have a few ways to do this. 34 | Here we use command line Git. 35 | In section \@ref(new-github-first), we show other methods that you might prefer in daily life: 36 | using usethis or the RStudio IDE. 37 | 38 | Go to the shell (Appendix \@ref(shell)). 39 | 40 | Take charge of -- or at least notice! -- what directory you're in. 41 | `pwd` displays the working directory. 42 | `cd` is the command to change directory. 43 | Personally, I would do this sort of thing in `~/tmp`. 44 | 45 | Clone `myrepo` from GitHub to your computer. 46 | Use the URL we just copied from GitHub. 47 | This URL should have **your GitHub username** and the name of **your practice repo**. 48 | If your shell (Appendix \@ref(shell)) cooperates, you should be able to paste the whole `https://....` bit that we copied above. 49 | But some shells are not (immediately) clipboard aware. 50 | In that sad case, you must type it. **Accurately.** 51 | 52 | ```console 53 | git clone https://github.com/YOUR-USERNAME/YOUR-REPOSITORY.git 54 | ``` 55 | 56 | This should look something like this: 57 | 58 | ```console 59 | ~/tmp % git clone https://github.com/jennybc/myrepo.git 60 | Cloning into 'myrepo'... 61 | remote: Enumerating objects: 3, done. 62 | remote: Counting objects: 100% (3/3), done. 63 | remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 64 | Receiving objects: 100% (3/3), done. 65 | ``` 66 | 67 | Make this new repo your working directory, list its files, display the README, and get some information on its connection to GitHub: 68 | 69 | ```console 70 | cd myrepo 71 | ls 72 | head README.md 73 | git remote show origin 74 | ``` 75 | 76 | This should look something like this: 77 | 78 | ``` bash 79 | ~/tmp % cd myrepo 80 | 81 | ~/tmp/myrepo % ls 82 | README.md 83 | 84 | ~/tmp/myrepo % head README.md 85 | # myrepo 86 | checking stuff for Happy Git 87 | 88 | ~/tmp/myrepo % git remote show origin 89 | * remote origin 90 | Fetch URL: https://github.com/jennybc/myrepo.git 91 | Push URL: https://github.com/jennybc/myrepo.git 92 | HEAD branch: main 93 | Remote branch: 94 | main tracked 95 | Local branch configured for 'git pull': 96 | main merges with remote main 97 | Local ref configured for 'git push': 98 | main pushes to main (up to date) 99 | ``` 100 | 101 | ## Make a local change, commit, and push 102 | 103 | Add a line to README and verify that Git notices the change: 104 | 105 | ```console 106 | echo "A line I wrote on my local computer " >> README.md 107 | git status 108 | ``` 109 | 110 | This should look something like this: 111 | 112 | ```console 113 | ~/tmp/myrepo % echo "A line I wrote on my local computer" >> README.md 114 | 115 | ~/tmp/myrepo % git status 116 | On branch main 117 | Your branch is up to date with 'origin/main'. 118 | 119 | Changes not staged for commit: 120 | (use "git add ..." to update what will be committed) 121 | (use "git restore ..." to discard changes in working directory) 122 | modified: README.md 123 | 124 | no changes added to commit (use "git add" and/or "git commit -a") 125 | ``` 126 | 127 | Stage ("add") and commit this change and push to your remote repo on GitHub. 128 | 129 | If you're a new GitHub user and using HTTPS, you might be challenged for your username and password. 130 | Even though GitHub no longer allows username/password authentication, many general Git tools still frame the authentication task with this vocabulary. 131 | By all means, provide your GitHub username when prompted. 132 | However, the most critical piece is to **provide your PAT as the password**. 133 | Do not enter your web password. 134 | Enter your PAT. 135 | If you already stored your PAT with `gitcreds::gitcreds_set()`, it should be discovered automatically and you will not see a credential challenge. 136 | 137 | ```console 138 | git add README.md 139 | git commit -m "A commit from my local computer" 140 | git push 141 | ``` 142 | 143 | This should look something like this: 144 | 145 | ```console 146 | ~/tmp/myrepo % git add README.md 147 | 148 | ~/tmp/myrepo % git commit -m "A commit from my local computer" 149 | [main e92528c] A commit from my local computer 150 | 1 file changed, 1 insertion(+) 151 | 152 | ~/tmp/myrepo % git push 153 | Enumerating objects: 5, done. 154 | Counting objects: 100% (5/5), done. 155 | Delta compression using up to 12 threads 156 | Compressing objects: 100% (2/2), done. 157 | Writing objects: 100% (3/3), 327 bytes | 327.00 KiB/s, done. 158 | Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 159 | To https://github.com/jennybc/myrepo.git 160 | 31dcaef..e92528c main -> main 161 | ``` 162 | 163 | Do you see an error like this? 164 | 165 | ```console 166 | ~/tmp/myrepo % git push 167 | remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead. 168 | remote: Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information. 169 | fatal: Authentication failed for 'https://github.com/jennybc/myrepo.git/' 170 | ``` 171 | 172 | This means you have provided your GitHub _web password_, instead of your _personal access token_ (PAT). 173 | Go back to chapter \@ref(https-pat) to get a PAT. 174 | Try `git push` again and hopefully you'll get another prompt, allowing you to correct things and provide your PAT. 175 | 176 | If you ever feel you need to overwrite a bad credential with a new one, the easiest way to do this is to call `gitcreds::gitcreds_set()` from R. 177 | 178 | ### Windows and line endings 179 | 180 | On Windows, you might see a message about `LF will be replaced by CRLF`. This is normal and does not require any action on your part. 181 | Windows handles line endings differently from other operating systems, but the default setup for Git for Windows is appropriate for most people and situations. 182 | 183 | Here's a command to reveal the current line ending configuration and some typical output **on Windows**: 184 | 185 | ```console 186 | $ git config --show-origin --get core.autocrlf 187 | file:"C:\\ProgramData/Git/config" true 188 | ``` 189 | 190 | If your value shows as `false`, you can set it to `true` with this command: 191 | 192 | ```console 193 | $ git config --global core.autocrlf true 194 | ``` 195 | 196 | `true` is the current default setting for `core.autocrlf` for [Git for Windows](#install-git-windows), our recommended method for installing Git on Windows. 197 | The need to set this explicitly in your global user config suggests you should consider reinstalling or updating Git for Windows. 198 | 199 | ## Confirm the local change propagated to the GitHub remote 200 | 201 | Go back to the browser. 202 | I assume we're still viewing your new GitHub repo. 203 | 204 | Refresh. 205 | 206 | You should see the new "A line I wrote on my local computer" in the README. 207 | 208 | If you click on "commits," you should see one with the message "A commit from my local computer." 209 | 210 | If you have made it this far, you and your test repo are ready to graduate to using Git and GitHub with RStudio (chapter \@ref(rstudio-git-github)). 211 | 212 | ## Clean up 213 | 214 | If you're ready to conclude this test of your Git installation and GitHub configuration, we can clean up the test repository now. 215 | 216 | **Local** When you're ready to clean up, you can delete the local repo any way you like. It's just a regular directory on your computer. 217 | 218 | Here's how to do that in the shell, if current working directory is `myrepo`: 219 | 220 | ```console 221 | cd .. 222 | rm -rf myrepo/ 223 | ``` 224 | 225 | **GitHub** In the browser, go to your repo's landing page on GitHub. 226 | Click on "Settings". 227 | 228 | Scroll down, click on "delete repository," and do as it asks. 229 | -------------------------------------------------------------------------------- /connect-intro.Rmd: -------------------------------------------------------------------------------- 1 | # (PART) Connect Git, GitHub, RStudio {-} 2 | 3 | # Can you hear me now? {#connect-intro .unnumbered} 4 | 5 | The next few chapters walk through some basic operations to confirm you have installed the necessary software and that the necessary connections are being made, between tools on your computer and between your computer and GitHub. 6 | 7 | This has a lot of overlap with some basic workflows we revisit later, but the second time around (or in a live workshop), we'll spend more time explaining what's happening and why. 8 | 9 | Unfortunately, we have to front-load a rather fiddly task, which is to decide whether to communicate with GitHub via HTTPS or SSH and setup some credentials accordingly. 10 | In [Personal access token for HTTPS] we discuss how to choose between HTTPS and SSH and then walk through obtaining a personal access token, which is used with HTTPS. 11 | Or, alternatively, we will help you [Set up keys for SSH]. 12 | 13 | Once we have our credentials sorted out, in [Connect to GitHub], we use Git in the shell to make sure you can clone a repo from GitHub and establish two-way communications, i.e. pull and push. 14 | 15 | In [Connect RStudio to Git and GitHub] we confirm that RStudio can work with your Git installation to perform local operations and communicate with GitHub. 16 | 17 | Hopefully you won't need it, but this part concludes with two troubleshooting chapters: [Detect Git from RStudio] and [RStudio, Git, GitHub Hell]. 18 | -------------------------------------------------------------------------------- /connect-rstudio-git-github.Rmd: -------------------------------------------------------------------------------- 1 | # Connect RStudio to Git and GitHub {#rstudio-git-github} 2 | 3 | Here we verify that RStudio can issue Git commands on your behalf. 4 | Assuming that you've gotten local Git to talk to GitHub, this means you'll also be able to pull from and push to GitHub from RStudio. 5 | 6 | In later chapters and in live workshops, we revisit these operations with much more explanation. 7 | 8 | If you succeed here, your set up is DONE. 9 | 10 | ## Prerequisites 11 | 12 | We assume the following: 13 | 14 | * You've registered a free GitHub account (chapter \@ref(github-acct)). 15 | * You've installed/updated R and RStudio (chapter \@ref(install-r-rstudio)). 16 | * You've installed Git (chapter \@ref(install-git)). 17 | * You've introduced yourself to Git (chapter \@ref(hello-git)). 18 | * You've confirmed that you can push to / pull from GitHub from the command line (chapter \@ref(push-pull-github)). 19 | 20 | You will also need a test repository on GitHub. 21 | If you don't have a suitable test repository on GitHub, follow the instructions in the next section. 22 | 23 | If you just completed the previous chapter, [Connect to GitHub], that repo will be perfect! 24 | However, I encourage you to delete the *local* repository, so you can experience how we use RStudio to clone it and get a local copy. 25 | This is a actually a workflow we refer to elsewhere (see \@ref(burn) as "burn it all down". 26 | It's a deeply pragmatic coping strategy if your local Git repo is goofed up, but the version on GitHub is pretty current. 27 | 28 | Delete the folder corresponding to the **local repo** any way you like. 29 | It's just a regular directory on your computer. 30 | Here's how to do that in the shell, if current working directory is `myrepo`: 31 | 32 | ```console 33 | cd .. 34 | rm -rf myrepo/ 35 | ``` 36 | 37 | ## Make a repo on GitHub 38 | 39 | ```{r echo = FALSE, results = "asis"} 40 | dat <- list( 41 | repository_name_text = glue::glue(" 42 | `myrepo` or whatever you wish (we'll delete this soon)."), 43 | description_text = glue::glue(" 44 | \"Repository for testing my Git/GitHub setup\" or similar. It's nice to \\ 45 | have something here, so you'll see it appear in the README."), 46 | initialize_text = "Initialize this repository with: Add a README file." 47 | ) 48 | insert <- glue::glue_data( 49 | dat, 50 | readr::read_file("child-create-a-github-repo.Rmd"), 51 | .open = "<<<", .close = ">>>" 52 | ) 53 | res <- knitr::knit_child(text = insert, quiet = TRUE) 54 | cat(res, sep = '\n') 55 | ``` 56 | 57 | ## Clone the test GitHub repository to your computer via RStudio 58 | 59 | In RStudio, start a new Project: 60 | 61 | * *File > New Project > Version Control > Git*. In "Repository URL", paste the URL of your new GitHub repository. It will be something like this `https://github.com/jennybc/myrepo.git`. 62 | - Do you NOT see an option to get the Project from Version Control? Restart RStudio and try again. Still no luck? Go to chapter \@ref(rstudio-see-git) for tips on how to help RStudio find Git. 63 | * Accept the default project directory name, e.g. `myrepo`, which coincides with the GitHub repo name. 64 | * Take charge of -- or at least notice! -- where the Project will be saved locally. A common rookie mistake is to have no idea where you are saving files or what your working directory is. Pay attention. Be intentional. Personally, I would do this in `~/tmp`. 65 | * I suggest you check "Open in new session", as that's what you'll usually do in real life. 66 | * Click "Create Project". 67 | 68 | You should find yourself in a new local RStudio Project that represents your test repo on GitHub. 69 | This should download the `README.md` file from GitHub. 70 | Look in RStudio's file browser pane for the `README.md` file. 71 | 72 | ## Make local changes, save, commit 73 | 74 | From RStudio, modify the `README.md` file, e.g., by adding the line "This is a line from RStudio". Save your changes. 75 | 76 | Commit these changes to your local repo. How? 77 | 78 | From RStudio: 79 | 80 | * Click the "Git" tab in upper right pane. 81 | * Check "Staged" box for `README.md`. 82 | * If you're not already in the Git pop-up, click "Commit". 83 | * Type a message in "Commit message", such as "Commit from RStudio". 84 | * Click "Commit". 85 | 86 | ## Push your local changes online to GitHub 87 | 88 | Click the green "Push" button to send your local changes to GitHub. 89 | 90 | You should not experience a credential challenge, since one of the pre-requisites was successfully pushing to GitHub from the command line (chapter \@ref(push-pull-github)). 91 | RStudio's Git pane just exposes a specific subset of command line Git and therefore once your credentials work in the shell, they should work in RStudio. 92 | If you do experience a credential challenge, that suggests you should have a look at the troubleshooting suggestions for your chosen protocol, either [HTTPS](#pat-troubleshooting) or [SSH](#ssh-troubleshooting). 93 | 94 | ## Confirm the local change propagated to the GitHub remote 95 | 96 | Go back to the browser. 97 | I assume we're still viewing your new GitHub repo. 98 | 99 | Refresh. 100 | 101 | You should see the new "This is a line from RStudio" in the README. 102 | 103 | If you click on "commits", you should see one with the message "Commit from RStudio". 104 | 105 | If you have made it this far, you are DONE with set up. 106 | Congratulations! 107 | 108 | ## Clean up 109 | 110 | Quit the RStudio instance that's open to your test Project / Git repo. 111 | 112 | Delete the local repo any way you like. 113 | It's just a regular directory on your computer. 114 | 115 | Here's how to do that in the shell, if current working directory is `myrepo`: 116 | 117 | ```console 118 | cd .. 119 | rm -rf myrepo/ 120 | ``` 121 | 122 | In the browser, go to your repo's landing page on GitHub. 123 | Click on "Settings". 124 | 125 | Scroll down, click on "delete repository," and do as it asks. 126 | -------------------------------------------------------------------------------- /connect-troubleshooting.Rmd: -------------------------------------------------------------------------------- 1 | # RStudio, Git, GitHub Hell {#troubleshooting} 2 | 3 | Problems we have seen and possible solutions. 4 | 5 | If you experience some new problem and, especially, find the corresponding solution, [we'd love to hear from you!](https://github.com/jennybc/happy-git-with-r/issues) 6 | 7 | ## I think I have installed Git but damn if I can find it 8 | 9 | When you install Git, try to control or record where it is being installed! 10 | Make a mental or physical note of these things. 11 | 12 | You may be able to find Git after the fact with these commands in the shell (Appendix \@ref(shell)): 13 | 14 | * `which git` (Mac, Linux, or anything running a bash shell) 15 | 16 | * `where git` (Windows, when not in a bash shell) 17 | 18 | It is not entirely crazy to just re-install Git, using a method that leaves it in a more conventional location, and to pay very close attention to where it's being installed. 19 | Live and learn. 20 | 21 | ## RStudio Git pane disappears on Mac OS 22 | 23 | Sometimes the RStudio Git pane disappears on a system where it was previously working. 24 | This usually happens to people who installed Git by installing the Xcode command line tools. 25 | It is usually a sign that you need to re-agree to the Xcode license agreement. This is necessary after a Mac OS upgrade, re-installing Xcode, or even quiet Xcode upgrades that sometimes seem to happen without the user's knowledge. 26 | 27 | In the shell, you could execute `git status` and you might see a message along these lines: 28 | 29 | ```console 30 | Agreeing to the Xcode/iOS license requires admin privileges, please run “sudo xcodebuild -license” and then retry this command. 31 | ``` 32 | 33 | If you get such clear instructions, by all means do what it says, i.e. run `sudo xcodebuild -license`, to re-agree to the license. 34 | 35 | In any case, you need to tickle the Xcode command line tools to prompt you for whatever it needs. Here are other commands that, depending on the situation, might trigger the necessary prompts: 36 | 37 | ```console 38 | xcode-select --install 39 | ``` 40 | 41 | or 42 | 43 | ```console 44 | git config --global --list 45 | ``` 46 | 47 | Then **restart RStudio**. 48 | 49 | ## Dysfunctional PATH 50 | 51 | Some cases of RStudio *not* automatically detecting the Git executable stem from problems with `PATH`. 52 | This is the set of directories where your computer will look for executables, such as Git (today) or `make`. 53 | Certain methods of Git installation, especially on Windows and/or older OSes, have a higher tendency to put Git in an unconventional location or to fail to add the relevant directory to `PATH`. 54 | 55 | How to see your `PATH`? 56 | 57 | In the shell: 58 | 59 | ```console 60 | echo $PATH 61 | ``` 62 | 63 | Take a good hard look at this. 64 | See the point above about finding your Git executable or re-installing it while you are **wide awake**. 65 | Is the Git executable's parent directory in your `PATH`? 66 | No? 67 | **Fix that.** 68 | 69 | At this point I recommend that you do a Google search to find instructions on how to modify `PATH` on your specific operating system. 70 | 71 | ## Push/Pull buttons greyed out in RStudio 72 | 73 | Are you sure your local repository is associated with a remote repository, e.g. a GitHub repo? 74 | In a shell with working directory set to the local Git repo, enter this command: 75 | 76 | ```console 77 | ~/tmp/myrepo % git remote -v 78 | origin git@github.com:jennybc/myrepo.git (fetch) 79 | origin git@github.com:jennybc/myrepo.git (push) 80 | ``` 81 | We want to see that fetch and push are set to remote URLs that point to the remote repo. 82 | 83 | If you discover you still need to set a remote, get the HTTPS or SSH URL, as appropriate, for your GitHub repo. 84 | This is easy to get onto your clipboard from the repo's GitHub page. 85 | Do this in the shell: 86 | 87 | ```console 88 | git remote add origin https://github.com/jennybc/myrepo.git 89 | ``` 90 | 91 | Download all the files from the online GitHub repository and deal with any 92 | conflicts (substituting `master` for `main`, if relevant). 93 | 94 | ```console 95 | git pull origin main 96 | ``` 97 | 98 | Call `git remote -v` again. 99 | Once you are satisfied that your GitHub remote is set properly, you can move on to the next step. 100 | 101 | Are you sure the current branch is *tracking* a branch on the remote? 102 | In that same shell, in your repo, do this: 103 | 104 | ```console 105 | ~/tmp/myrepo % git branch -vv 106 | * main 2899c91 [origin/main] A commit from my local computer 107 | ``` 108 | 109 | The above shows successful confirmation that the local `main` branch is tracking `origin/main`, i.e. the `main` branch on GitHub. 110 | If you don't see the `[origin/main]` bit, that is a problem. 111 | By the way, `git branch -r` and `git remote show origin` are two more commands that are helpful for examining your remote setup. 112 | 113 | When connecting a local repo to a new GitHub repo, a lot of people remember to add the GitHub remote, but forget to also cement this tracking relationship for any relevant branches. 114 | 115 | If you discover your local `main` branch is not yet tracking `main` on GitHub, fix that like so: 116 | 117 | ```console 118 | git push --set-upstream origin main 119 | ``` 120 | 121 | This is equivalent to `git push -u origin main` but conveys more about what you are doing. 122 | 123 | Call `git branch -vv` or `git branch -r` or `git remote show origin` again to confirm that the `main` branch on GitHub is the tracking branch for the local `main` branch. 124 | 125 | ## I have no idea if my local repo and my remote repo are connected. 126 | 127 | See the above section on "Push/Pull buttons greyed out in RStudio." 128 | 129 | ## Push rejected, i.e. fail at the Git/GitHub level 130 | 131 | You might have changes on the remote AND on your local repo. 132 | Just because you don't remember making any edits in the browser doesn't mean you didn't. 133 | Humor me. 134 | 135 | Pull first. 136 | Resolve any conflicts. 137 | Then try your push again. 138 | 139 | ## RStudio is not making certain files available for staging/committing 140 | 141 | Do you have a space in your directory or file names? [A space in a file name is a space in your soul.](https://twitter.com/aaronquinlan/status/711593127551733761) 142 | Get rid of it. 143 | 144 | Is your Git repo / RStudio Project inside a folder that ... eventually rolls up to Google Drive, DropBox, Microsoft OneDrive, or a network drive? 145 | If yes, I recommend you move the repo / Project into a plain old directory that lives directly on your computer and that is not managed by, e.g., Google Drive. 146 | 147 | If you cannot deal with the two root causes identified above, then it is possible that a more powerful Git client (chapter \@ref(git-client)) will be able to cope with these situations. 148 | But I make no promises. 149 | You should also try Git operations from the command line. 150 | 151 | ## I hear you have some Git repo inside your Git repo 152 | 153 | Do not create a Git repository inside another Git repository. Just don't. 154 | 155 | If you have a genuine need for this, which is really rare, the proper way to do it is via [submodules](http://git-scm.com/book/en/v2/Git-Tools-Submodules). 156 | 157 | In STAT 545, we certainly do not need to do this and when we've seen it, it's been a mistake. 158 | This has resulted in the unexpected and complete loss of the inner Git repository. 159 | To be sure, there was more going on here (cough, GitHub Desktop client), but non-standard usage of Git repos makes it much easier to make costly mistakes. 160 | -------------------------------------------------------------------------------- /contributors.Rmd: -------------------------------------------------------------------------------- 1 | # Contributors {#contrib} 2 | 3 | Jenny Bryan ([jennybryan.org](https://jennybryan.org)), Software Engineer at [Posit](https://posit.co/) on the [tidyverse](https://www.tidyverse.org)/[r-lib](https://github.com/r-lib/) team. Main author and content wrangler. 4 | 5 | The development and delivery of this material has also benefited greatly from contributions by: 6 | 7 | * Dean Attali ([deanattali.com](http://deanattali.com)), Shiny consultant and [STAT 545](http://stat545.com) TA alum. 8 | * Bernhard Konrad, Software Engineer at Google and [STAT 545](http://stat545.com) TA alum. 9 | * Shaun Jackman ([sjackman.ca](http://sjackman.ca)), Bioinformatics Ph.D. student at UBC, lead maintainer of [Linuxbrew](http://linuxbrew.sh), and [STAT 545](http://stat545.com) TA alum. 10 | * Jim Hester ([jimhester.com](https://www.jimhester.com)), Software Engineer at [Posit](https://posit.co/) on the [tidyverse](https://www.tidyverse.org)/[r-lib](https://github.com/r-lib/) team. 11 | * A growing number of [GitHub contributors](https://github.com/jennybc/happy-git-with-r/graphs/contributors) 12 | -------------------------------------------------------------------------------- /ga_script.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /git-basics.Rmd: -------------------------------------------------------------------------------- 1 | # Repo, commit, diff, tag {#git-basics} 2 | 3 | ## Repos or repositories 4 | 5 | Git is a version control system whose original purpose was to help groups of 6 | developers work collaboratively on big software projects. Git manages the 7 | evolution of a set of files -- called a __repository__ or __repo__ -- in a highly structured way. Historically, these files would have consisted of source code and the instructions for how to build an application from its source. 8 | 9 | Git has been re-purposed by the data science community [@Ram2013; 10 | @git-for-humans; @ten-simple-rules-git]. We use it to manage the motley collection of files that make up typical data analytical projects, which consist of data, figures, reports, and, yes, some source code. 11 | 12 | For new or existing projects, we recommend that you: 13 | 14 | * Dedicate a local directory or folder to it. 15 | * Make it an RStudio Project. *Optional but recommended; obviously only applies to projects involving R and users of RStudio.* 16 | * Make it a Git repository. 17 | 18 | This setup happens once per project and can happen at project inception or at any later point. Chances are your existing projects each already live in a dedicated directory. Making such a directory an RStudio Project and Git repository boils down to allowing those applications to leave notes for themselves in hidden files or directories. The project is still a regular directory on your computer, that you can locate, name, move, and generally interact with as you wish. You don't have to handle it with special gloves! 19 | 20 | The daily workflow is probably not dramatically different from what you do currently. You work in the usual way, writing R scripts or authoring reports in LaTeX or R Markdown. But instead of only *saving* individual files, periodically you make a __commit__, which takes a snapshot of all the files in the entire project. If you have ever versioned a file [by adding your initials or the date](http://www.phdcomics.com/comics/archive.php?comicid=1531), you have effectively made a commit, albeit only for a single file. It is a version that is significant to you and that you might want to inspect or revert to later. Periodically, you push commits to GitHub. This is like sharing a document with colleagues on DropBox or sending it out as an email attachment. By pushing to GitHub, you make your work and all your accumulated progress accessible to others. 21 | 22 | This is a moderate change to your normal, daily workflow. It feels weird at first, but quickly becomes second nature. In [STAT 545](http://stat545.com) students are required to submit all coursework via GitHub, starting in week one. Most have never seen Git before and do not identify as programmers. It is a major topic in class and office hours for the first two weeks. Then we practically never discuss it again. 23 | 24 | ## Commits, diffs, and tags 25 | 26 | We now connect the fundamental concepts of Git to the data science workflow: 27 | 28 | * repository 29 | * commit 30 | * diff 31 | 32 | Recall that a repository or repo is just a directory of files that Git manages holistically. A commit functions like a snapshot of all the files in the repo, at a specific moment. Under the hood, that is not exactly how Git implements things. Although mental models don't have to be accurate in order to be useful, in this case it helps to align the two. 33 | 34 | ```{r commit-diff-sha-tag, echo = FALSE, out.width = "100%", fig.cap="\\label{fig:commit-diff-sha-tag}Partial commit history for our iris example, highlighting diffs, commit messages, SHAs, and tags."} 35 | knitr::include_graphics("img/commit-diff-sha-tag.png") 36 | ``` 37 | 38 | Figure \@ref(fig:commit-diff-sha-tag) is a look at a fictional analysis of the iris data, focusing on the evolution of a script, `iris.R`. Consider version A of this file and a modified version, version B. Assume that version A was part of one Git commit and version B was part of the next commit. The set of differences between A and B is called a "diff" and Git users contemplate diffs a lot. Diff inspection is how you re-explain to yourself how version A differs from version B. Diff inspection is not limited to adjacent commits. You can inspect the diffs between any two commits. 39 | 40 | In fact, Git's notion of any specific version of `iris.R` is as an accumulation of diffs. If you go back far enough, you find the commit where the file was created in the first place. Every later version is stored by Git as that initial version, plus all the intervening diffs in the history that affect the file. We'll set these internal details aside now, but understanding the importance of these deltas will make Git's operations less baffling in the long run. 41 | 42 | So, by looking at diffs, it's easy to see how two snapshots differ, but what about the why? 43 | 44 | Every time you make a commit you must also write a short __commit message__. Ideally, this conveys the motivation for the change. Remember, the diff will show the content. When you revisit a project after a break or need to digest recent changes made by a colleague, looking at the __history__, by reading commit messages and skimming through diffs, is an extremely efficient way to get up to speed. Figure \@ref(fig:commit-diff-sha-tag) shows the messages associated with the last three commits. 45 | 46 | Every commit needs some sort of nickname, so you can identify it. Git does this automatically, assigning each commit what is called a SHA, a seemingly random string of 40 letters and numbers (it is not, in fact, random but is a SHA-1 checksum hash of the commit). Though you will be exposed to these, you don't have to handle them directly very often and, when you do, usually the first 7 characters suffice. The commit messages in Figure \@ref(fig:commit-diff-sha-tag) are prefixed by such truncated SHAs. You can also designate certain snapshots as special with a __tag__, which is a name of your choosing. In a software project, it is typical to tag a release with its version, e.g., "v1.0.3". For a manuscript or analytical project, you might tag the version submitted to a journal or transmitted to external collaborators. Figure \@ref(fig:commit-diff-sha-tag) shows a tag, "draft-01", associated with the last commit. 47 | -------------------------------------------------------------------------------- /git-branches.Rmd: -------------------------------------------------------------------------------- 1 | # Branches {#git-branches} 2 | 3 | Branching means that you take a detour from the main stream of development and 4 | do work without changing the main stream. 5 | It allows one or many people to work in parallel without overwriting each other's work. 6 | It allows a someone working solo to work incrementally on an experimental idea, without jeopardizing the state of the main product. 7 | 8 | Branching in Git is very lightweight, which means creating a branch and 9 | switching between branches is nearly instantaneous. 10 | This means Git encourages workflows which create small branches for exploration or new features, often merging them back together quickly. 11 | 12 | ## Create a new branch 13 | 14 | You can create a new branch with `git branch`, then checkout the branch with `git checkout`. 15 | To distinguish it from the main stream of development, presumably on `main`, we'll call this a "feature branch". 16 | 17 | ```console 18 | git branch issue-5 19 | git checkout issue-5 20 | ``` 21 | 22 | You can also use the shortcut `git checkout -b issue-5` to create and checkout the branch all at once. 23 | 24 | Once you have switched to a branch, you can commit to it as usual. 25 | 26 | ## Switching branches 27 | 28 | You use `git checkout` to switch between branches. 29 | 30 | But what do you do if you are working on a branch and need to switch, 31 | but the work on the current branch is not complete? 32 | One option is the [Git stash](https://git-scm.com/book/en/v2/ch00/_git_stashing), but generally a better option is to safeguard the current state with a temporary commit. 33 | Here I use "WIP" as the commit message to indicate work in progress. 34 | 35 | ```console 36 | git commit --all -m "WIP" 37 | git checkout main 38 | ``` 39 | 40 | Then when you come back to the branch and continue your work, you 41 | need to undo the temporary commit by [resetting](#reset) your state. 42 | Specifically, we want a mixed reset. 43 | This is "working directory safe", i.e. it does not affect the state of any files. 44 | But it does peel off the temporary WIP commit. 45 | Below, the reference `HEAD^` says to roll the commit state back to the parent of the current commit (`HEAD`). 46 | 47 | ```console 48 | git checkout issue-5 49 | git reset HEAD^ 50 | ``` 51 | 52 | If this is difficult to remember, or to roll the commit state back to a different previous state, the reference can also be given as the SHA of a specific commit, which you can see via `git log`. 53 | This is where I think a graphical Git client can be invaluable, as you can generally right click on the target commit, then select the desired type of reset (e.g., soft, mixed, or hard). 54 | This is exactly the type of intermediate-to-advanced Git usage that often feels more approachable in a graphical client. 55 | 56 | ## Merging a branch 57 | 58 | Once you have done your work and committed it to the feature branch, you can switch back to `main` and merge the feature branch. 59 | 60 | ```console 61 | git checkout main 62 | git merge issue-5 63 | ``` 64 | 65 | ## Dealing with conflicts 66 | 67 | Most of the time, the merge will go smoothly. 68 | However if both the branches you are merging changed the same part of the same file you will get a merge conflict. 69 | 70 | ```console 71 | git merge issue-5 72 | # Auto-merging index.html 73 | # CONFLICT (content): Merge conflict in index.html 74 | # Automatic merge failed; fix conflicts and then commit the result. 75 | ``` 76 | 77 | The first thing to do is **NOT PANIC**. 78 | Merge conflicts are not the end of the world and most are relatively small and straightforward to resolve. 79 | 80 | The first step to solving a merge conflict is determining which files are in 81 | conflict, which you can do with `git status`: 82 | 83 | ```shell 84 | git status 85 | # On branch main 86 | # You have unmerged paths. 87 | # (fix conflicts and run "git commit") 88 | # 89 | # Unmerged paths: 90 | # (use "git add ..." to mark resolution) 91 | # 92 | # both modified: index.html 93 | # 94 | # no changes added to commit (use "git add" and/or "git commit -a") 95 | ``` 96 | 97 | So this shows only `index.html` is unmerged and needs to be resolved. 98 | We can then open the file to see what lines are in conflict. 99 | 100 | ```html 101 | <<<<<<< HEAD:index.html 102 | 103 | ======= 104 | 107 | >>>>>>> issue-5:index.html 108 | ``` 109 | 110 | In this conflict, the lines between `<<<<<< HEAD:index.html` and `======` are 111 | the content from the branch you are currently on. 112 | The lines between `=======` and `>>>>>>> issue-5:index.html` are from the feature branch we are merging. 113 | 114 | To resolve the conflict, edit this section until it reflects the state you want in the merged result. 115 | Pick one version or the other or create a hybrid. 116 | Also remove the conflict markers `<<<<<<`, `======` and `>>>>>>`. 117 | 118 | ```html 119 | 122 | ``` 123 | 124 | Now run `git add index.html` and `git commit` to finalize the merge. 125 | CONFLICTS RESOLVED. 126 | 127 | ### Bailing out 128 | 129 | If, during the merge, you get confused about the state of things or make a 130 | mistake, use `git merge --abort` to abort the merge and go back to the state 131 | prior to running `git merge`. 132 | Then you can try to complete the merge again. 133 | 134 | Git Basic Branching and Merging: 135 | 136 | 137 | -------------------------------------------------------------------------------- /git-commands.Rmd: -------------------------------------------------------------------------------- 1 | # Git commands {#git-commands} 2 | 3 | A collection of some of the Git commands that have been largely going on under the hood. 4 | We've emphasized early workflows that are possible in RStudio. 5 | But all of this and much more can be done from the command line. 6 | This list is here mostly so we can consult it during live workshops if needed. 7 | 8 | *Unless you use the [GitHub API](https://developer.github.com/v3/), most of the GitHub bits really have to be done from the browser.* 9 | 10 | New local git repo from a repo on GitHub: 11 | 12 | ```console 13 | git clone https://github.com/jennybc/happy-git-with-r.git 14 | ``` 15 | 16 | Check the remote was cloned successfully: 17 | 18 | ```console 19 | git remote --verbose 20 | ``` 21 | 22 | Stage local changes, commit: 23 | 24 | ```console 25 | git add foo.txt 26 | git commit --message "A commit message" 27 | ``` 28 | 29 | Check on the state of the Git world: 30 | 31 | ```console 32 | git status 33 | git log 34 | git log --oneline 35 | ``` 36 | 37 | Compare versions: 38 | 39 | ```console 40 | git diff 41 | ``` 42 | 43 | Add a remote to existing local repo: 44 | 45 | ```console 46 | git remote add origin https://github.com/jennybc/happy-git-with-r 47 | git remote --verbose 48 | git remote show origin 49 | ``` 50 | 51 | Push local `main` to GitHub `main` and have local `main` track `main` on GitHub: 52 | 53 | ```console 54 | git push --set-upstream origin main 55 | # shorter form 56 | git push -u origin main 57 | # you only need to set upstream tracking once! 58 | ``` 59 | 60 | Regular push: 61 | 62 | ```console 63 | git push 64 | # the above usually implies (and certainly does in our tutorial) 65 | git push origin main 66 | # git push [remote-name] [branch-name] 67 | ``` 68 | 69 | Pull commits from GitHub: 70 | 71 | ```console 72 | git pull 73 | ``` 74 | 75 | Pull commits and don't let it put you in a merge conflict pickle: 76 | 77 | ```console 78 | git pull --ff-only 79 | ``` 80 | 81 | Fetch commits 82 | 83 | ```console 84 | git fetch 85 | ``` 86 | 87 | Switch to a branch 88 | 89 | ```console 90 | git checkout [branch-name] 91 | ``` 92 | 93 | Checking remote and branch tracking 94 | 95 | ```console 96 | git remote -v 97 | git remote show origin 98 | git branch -vv 99 | ``` 100 | -------------------------------------------------------------------------------- /git-intro.Rmd: -------------------------------------------------------------------------------- 1 | # (PART) Git fundamentals {-} 2 | 3 | # Some Git basics {#git-intro .unnumbered} 4 | 5 | We've told you shockingly little about Git so far! This is by design. 6 | 7 | We find that actual usage, in the course of your work, is the most effective way to build up a useful mental model for Git. In live workshops, we strive to introduce the most important basic ideas in the context of our guided activities. Self-learners can achieve the same by working through the "batteries included" guides earlier in the previous sections. 8 | 9 | However, building on this early success, now is the perfect time to explicitly define some Git vocabulary. We also want to help you link Git concepts to data science tasks and projects. 10 | 11 | This part collects anything we've written about core Git concepts. It is a work in progress and is conceived as a complement to the many excellent [external resources for Git](#resources), which we have no desire to re-invent. 12 | -------------------------------------------------------------------------------- /git-refs.Rmd: -------------------------------------------------------------------------------- 1 | # Refs {#git-refs} 2 | 3 | Many extremely useful Git workflows require you to identify a specific point in your repo's history, i.e. a specific commit. 4 | 5 | We've explained elsewhere that every commit is associated with a so-called SHA, i.e. a SHA-1 checksum of the commit itself. 6 | These opaque strings of 40 letters and numbers are not particularly pleasant for humans to work with. 7 | The entry-level coping strategy is to work with an abbreviated form of the SHA. 8 | It's typical to only use the first 7 characters, as this almost always uniquely identifies a commit. 9 | 10 | ```{r} 11 | #| echo = FALSE, fig.align = "center", out.width = "60%", 12 | #| fig.alt = "Git history annotated with SHAs." 13 | knitr::include_graphics("img/refs-only-shas.jpeg") 14 | ``` 15 | 16 | Luckily, there are even more ways to talk about a specific commit, that are much easier for humans to wrap their head around. 17 | These are called Git "refs", short for references and, if you're familiar with the programming concept of a pointer, that's exactly the right mental model. 18 | 19 | ## Useful refs 20 | 21 | Here are some of the most useful refs: 22 | 23 | * A branch name. 24 | Example: `main`, `wild-experiment`. 25 | When you refer to the `main` branch, that resolves to the SHA of the tip of 26 | the `main` branch. 27 | Think of a branch ref as a sliding ref that evolves as the branch does. 28 | 29 | ```{r} 30 | #| echo = FALSE, fig.align = "center", out.width = "60%", 31 | #| fig.alt = "Git history annotated with two branches." 32 | knitr::include_graphics("img/refs-only-branches.jpeg") 33 | ``` 34 | 35 | * `HEAD`. 36 | This (almost always) resolves to the tip of the branch that is currently 37 | checked out.[^HEAD-no-branch] 38 | You can think of `HEAD` as a ref that points to the tip of the current branch, 39 | which itself is a ref, that points to a specific SHA. 40 | There are two layers of indirection. 41 | This is also called a *symbolic ref*. 42 | 43 | ```{r} 44 | #| echo = FALSE, fig.align = "center", out.width = "60%", 45 | #| fig.alt = "Git history annotated with HEAD symbolic ref." 46 | knitr::include_graphics("img/refs-branches-and-HEAD-1.jpeg") 47 | ``` 48 | 49 | * A tag. 50 | Example: `v1.4.2`. 51 | Tags differ from branch refs and the `HEAD` ref in that they tend to be much 52 | more static. 53 | Tags aren't sliding by nature, although it is possible to reposition a tag to 54 | point at a new SHA, if you make an explicit effort. 55 | The most common use of a tag is to provide a nice label for a specific SHA. 56 | 57 | ```{r} 58 | #| echo = FALSE, fig.align = "center", out.width = "60%", 59 | #| fig.alt = "Git history annotated with a tag." 60 | knitr::include_graphics("img/refs-tag.jpeg") 61 | ``` 62 | 63 | [^HEAD-no-branch]: When does `HEAD` not resolve to the SHA at the tip of some branch? 64 | When you are a *detached HEAD* state. 65 | Detached HEAD! 66 | That sounds bad, but it's not intrinsically good or bad. 67 | It IS bad, though, to be in a detached HEAD state if you didn't mean to be and you don't understand the deal. 68 | You get into a detached HEAD state when you directly checkout a specific commit, as opposed to checking out or switching to a *branch*. 69 | In experienced hands, this can be a legit thing to do. 70 | But in the meantime, I recommend that you always visit a specific state in the history by checking out a *branch*, even if that means you need to create a temporary branch like `holder` or `time-travel`. 71 | To get out of the detached `HEAD` state, checkout some existing branch, with `git checkout main` or similar. 72 | Otherwise, the StackOverflow thread [How do I fix a Git detached head?](https://stackoverflow.com/q/10228760) addresses many vexing detached `HEAD` scenarios. 73 | 74 | If you'd like to make all of this more concrete, you can use `git rev-parse` in the shell to witness how refs resolve to concrete SHAs. 75 | Here's the general pattern: 76 | 77 | ```console 78 | git rev-parse YOUR_REF_GOES_HERE 79 | ``` 80 | 81 | Here are some examples executed in the Happy Git repo: 82 | 83 | ```console 84 | ~/rrr/happy-git-with-r % git rev-parse HEAD 85 | 631fee855db49d87f6c2a2cab474e89c11322bf4 86 | 87 | ~/rrr/happy-git-with-r % git rev-parse main 88 | 631fee855db49d87f6c2a2cab474e89c11322bf4 89 | 90 | ~/rrr/happy-git-with-r % git rev-parse testing-something 91 | 1eeb91d177b7cb5f9a0b29ebee3e6c0c8ff98f88 92 | ``` 93 | 94 | Notice that `HEAD` and `main` resolve to the same SHA, since the `main` branch was checked out at the time. 95 | `testing-something` is the name of a branch that happened to be lying around. 96 | 97 | These refs can be used in all sorts of Git operations, such as `git diff`, `git reset`, and `git checkout`: 98 | 99 | ```console 100 | git diff main testing-something 101 | 102 | git reset testing-something -- README.md 103 | 104 | git checkout -b my-new-branch main 105 | ``` 106 | 107 | ## Relative refs 108 | 109 | There are also modifiers that help you specify a commit relative to a ref, e.g. "the commit just before this one". 110 | 111 | `HEAD~1` refers to the commit just before `HEAD`. 112 | `HEAD^` is another way to say exactly the same thing. 113 | 114 | ```{r} 115 | #| echo = FALSE, fig.align = "center", out.width = "60%", 116 | #| fig.alt = "Git history annotated with relative refs." 117 | knitr::include_graphics("img/refs-relative.jpeg") 118 | ``` 119 | 120 | Here are some examples executed in the Happy Git repo: 121 | 122 | ```console 123 | ~/rrr/happy-git-with-r % git rev-parse HEAD~1 124 | 5dacec4950a3746310bb30704417a792302b044a 125 | 126 | ~/rrr/happy-git-with-r % git rev-parse HEAD^ 127 | 5dacec4950a3746310bb30704417a792302b044a 128 | ``` 129 | 130 | Notice that `HEAD~1` and `HEAD^` resolve to the same SHA. 131 | 132 | Both of these patterns generalize. 133 | `HEAD~3` and `HEAD^^^` are valid and equivalent refs. 134 | 135 | I must admit that I am not a big fan of these relative ref shortcuts and especially not when reaching back more than one commit. 136 | I worry that I have some sort of off-by-one error in my understanding and I'll end up targetting the wrong commit. 137 | 138 | Tools like GitKraken and GitHub make it extremely easy to copy specific SHAs to your clipboard. 139 | So when I need a ref that's not a simple branch name or tag, I almost always lean on user-friendly tools like GitKraken or GitHub to allow me to state my intent using the actual SHA of interest. 140 | I suspect that the relative ref shortcuts are most popular with folks who are exclusively using command line Git and are operating under different constraints. 141 | There's actually a rich set of ways to specify a target commit that goes well beyond the `^` and `~` syntax shown here. 142 | You can learn more in the [official Git documention about revision parameters](https://git-scm.com/docs/gitrevisions). 143 | 144 | In GitKraken, right or control click on the target commit to access a menu that includes "Copy commit sha", among many other useful commands. 145 | If you're using another Git client, there is probably a way to do this and it's worth figuring that out. 146 | 147 | ```{r} 148 | #| echo = FALSE, fig.align = "center", out.width = "60%", 149 | #| fig.alt = "GitKraken screenshot showing how to copy a specific SHA." 150 | knitr::include_graphics("img/gitkraken-screenshot-copy-commit-sha.png") 151 | ``` 152 | 153 | GitHub also makes it extremely easy to copy a SHA in many contexts. 154 | This screenshot shows just one example. 155 | Once you start looking for this feature, you'll find it in many places on GitHub. 156 | 157 | ```{r} 158 | #| echo = FALSE, fig.align = "center", out.width = "60%", 159 | #| fig.alt = "GitHub screenshot showing how to copy a specific SHA." 160 | knitr::include_graphics("img/github-screenshot-copy-the-full-sha.png") 161 | ``` 162 | -------------------------------------------------------------------------------- /git-remotes.Rmd: -------------------------------------------------------------------------------- 1 | # Remotes {#git-remotes} 2 | 3 | Remote repositories are versions of your project that are hosted on the 4 | Internet or another network. 5 | A single project can have 1, 2, or even hundreds of remotes. 6 | You pull others' changes from remotes and push your changes to remotes. 7 | 8 | ```{r setup, include = FALSE} 9 | has_bash <- Sys.which('bash') != '' && .Platform$OS.type != 'windows' 10 | ``` 11 | 12 | ## Listing what remotes exist 13 | 14 | `git remote` lists the names of available remotes, but usually it is more 15 | useful to see what URLs each note corresponds to (with `-v`). 16 | 17 | ```{bash eval = has_bash} 18 | git remote -v 19 | ``` 20 | 21 | ## Adding a new remote 22 | 23 | `git clone` automatically adds a new remote, so often you do not need to do 24 | this manually initially. 25 | However, after the initial clone, it is often useful to add additional remotes. 26 | 27 | Use `git remote add` to add a new remote: 28 | 29 | ```console 30 | git remote add happygit https://github.com/jennybc/happy-git-with-r.git 31 | ``` 32 | 33 | Note: when you add a remote you give it a nickname (here `happygit`), which you can use in git commands in place of the entire URL. 34 | 35 | ```console 36 | git fetch happygit 37 | ``` 38 | 39 | Sidebar on nicknames: there is a strong convention to use `origin` as the nickname of your main remote. 40 | At this point, it is common for the main remote of a repo to be hosted on GitHub (or GitLab or Bitbucket). 41 | It is tempting to use a more descriptive nickname (such as `github`), but you might find that following convention is worth it. 42 | It makes your setup easier for others to understand and for you to transfer information that you read in documentation, on Stack Overflow, or in blogs. 43 | 44 | A common reason to add a second remote is when you have done a "fork and clone" of a repo and your personal copy (your fork) is set up as the `origin` remote. 45 | Eventually you will want to pull changes from the original repository. It is common to use `upstream` as the nickname for this remote. 46 | 47 | ```console 48 | git remote add upstream https://github.com/TRUE_OWNER/REPO.git 49 | ``` 50 | 51 | ## Fetching data from remotes 52 | 53 | To get new data from a remote use `git fetch `. 54 | This retrieves the data locally, but importantly it does _not_ change the state of your local files in any way. 55 | To incorporate the data into your repository, you need to merge or rebase your project with the remote project. 56 | 57 | ```console 58 | # Fetch the data 59 | git fetch happygit 60 | 61 | # Now merge it with our local main 62 | git merge happygit/main main 63 | 64 | # git pull is a shortcut which does the above in one command 65 | git pull happygit main 66 | ``` 67 | 68 | For more detail on `git pull` workflows, see \@ref(pull-tricky). 69 | 70 | ## Pushing to remotes 71 | 72 | Use `git push ` to push your local changes to the `` 73 | branch on the `` remote. 74 | 75 | ```console 76 | # push my local changes to the origin remote's main branch 77 | git push origin main 78 | 79 | # push my local changes to the happygit remote's test branch 80 | git push happygit test 81 | ``` 82 | 83 | ## Renaming and changing remotes 84 | 85 | `git remote rename` can be used to rename a remote: 86 | 87 | ```console 88 | git remote rename happygit hg 89 | ``` 90 | 91 | `git remote set-url` can be used to change the URL for a remote. 92 | This is sometimes useful if you initially set up a remote using HTTPS, but now want to use SSH instead (or *vice versa*). 93 | 94 | ```console 95 | git remote set-url happygit git@github.com:jennybc/happy-git-with-r.git 96 | ``` 97 | 98 | One fairly common workflow is you initially cloned a repository on GitHub 99 | locally (without forking it), but now want to create your own fork and push 100 | changes to it. 101 | As described earlier, it is common to call the source repository `upstream` and to call your fork `origin`. 102 | So, in this case, you need to first rename the existing remote (from `origin` to `upstream`). 103 | Then add your fork as a new remote, with the name `origin`. 104 | 105 | ```console 106 | git remote rename origin upstream 107 | git remote add origin git@github.com:jimhester/happy-git-with-r.git 108 | ``` 109 | 110 | ## Upstream tracking branches 111 | 112 | It is possible to set the branch on the remote each of your local remotes 113 | corresponds to. 114 | `git clone` sets this up automatically, so for your own `main` branch this is not something you will run into. 115 | However by default if you create a new branch and try to push to it you will see something like this: 116 | 117 | ```console 118 | git checkout -b mybranch 119 | git push 120 | # fatal: The current branch foo has no upstream branch. 121 | # To push the current branch and set the remote as upstream, use 122 | # 123 | # git push --set-upstream origin foo 124 | ``` 125 | 126 | You can do as the error message says and explicitly set the upstream branch 127 | with `--set-upstream`. 128 | However I would recommend instead changing the default behavior of `push` to automatically set the upstream branch to the branch with the same name on the remote. 129 | 130 | You can do this by changing the git `push.default` option to `current`. 131 | 132 | ```console 133 | git config --global push.default current 134 | ``` 135 | 136 | See also Working with Remotes: 137 | 138 | 139 | -------------------------------------------------------------------------------- /happy-git-with-r.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Website 19 | -------------------------------------------------------------------------------- /img/2018-01-15_bash-windows-services-for-linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/2018-01-15_bash-windows-services-for-linux.png -------------------------------------------------------------------------------- /img/2018-01-15_command-prompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/2018-01-15_command-prompt.png -------------------------------------------------------------------------------- /img/2018-01-15_git-bash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/2018-01-15_git-bash.png -------------------------------------------------------------------------------- /img/2018-01-15_power-shell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/2018-01-15_power-shell.png -------------------------------------------------------------------------------- /img/2019-01-git-windows-administrator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/2019-01-git-windows-administrator.png -------------------------------------------------------------------------------- /img/2019-01_git_bash_windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/2019-01_git_bash_windows.png -------------------------------------------------------------------------------- /img/440px-Bash_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/440px-Bash_screenshot.png -------------------------------------------------------------------------------- /img/_combine-github-configs.R: -------------------------------------------------------------------------------- 1 | library(magick) 2 | library(here) 3 | library(tidyverse) 4 | library(fs) 5 | 6 | paths <- here( 7 | "img", 8 | c("no_github.png", "ours-you.png", "ours-them.png", 9 | "theirs.png", "fork-them.png", "fork-ours.png") 10 | ) 11 | 12 | x <- paths %>% set_names(~ path_ext_remove(path_file(.x))) %>% map(image_read) 13 | str(x) 14 | 15 | dat <- tibble( 16 | img = x, 17 | anno = c("no_github", "ours (1 of 2)", "ours (2 of 2)", 18 | "theirs", "fork (1 of 2)", "fork (2 of 2)") 19 | ) 20 | 21 | sz <- 45 22 | x_anno <- map2( 23 | dat$img, dat$anno, 24 | ~image_annotate(.x, .y, size = sz, gravity = "northwest", location = "+25+25") 25 | ) 26 | 27 | x_anno[[1]] 28 | x_anno[[2]] 29 | x_anno[[3]] 30 | x_anno[[4]] 31 | x_anno[[5]] 32 | x_anno[[6]] 33 | 34 | top_row <- x_anno %>% 35 | head(3) %>% 36 | image_join() %>% 37 | image_scale("x200") %>% 38 | image_append() 39 | top_row 40 | bot_row <- x_anno %>% 41 | tail(3) %>% 42 | image_join() %>% 43 | image_scale("x200") %>% 44 | image_append() 45 | bot_row 46 | all <- c(top_row, bot_row) %>% image_join() %>% image_append(stack = TRUE) 47 | all 48 | 49 | image_write(all, here("img", "six-configs.png")) 50 | -------------------------------------------------------------------------------- /img/clone-theirs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/clone-theirs.png -------------------------------------------------------------------------------- /img/clone-yours.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/clone-yours.png -------------------------------------------------------------------------------- /img/command-line-git-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/command-line-git-screenshot.png -------------------------------------------------------------------------------- /img/commit-diff-sha-tag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/commit-diff-sha-tag.png -------------------------------------------------------------------------------- /img/fork-and-clone.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/fork-and-clone.jpeg -------------------------------------------------------------------------------- /img/fork-and-clone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/fork-and-clone.png -------------------------------------------------------------------------------- /img/fork-no-upstream-sad.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/fork-no-upstream-sad.jpeg -------------------------------------------------------------------------------- /img/fork-ours.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/fork-ours.jpeg -------------------------------------------------------------------------------- /img/fork-them-pull-request.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/fork-them-pull-request.jpeg -------------------------------------------------------------------------------- /img/fork-them.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/fork-them.jpeg -------------------------------------------------------------------------------- /img/fork-triangle-happy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/fork-triangle-happy.png -------------------------------------------------------------------------------- /img/fork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/fork.png -------------------------------------------------------------------------------- /img/fork_upstream_is_not_origin_parent.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/fork_upstream_is_not_origin_parent.jpeg -------------------------------------------------------------------------------- /img/git-bash-as-rstudio-terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/git-bash-as-rstudio-terminal.png -------------------------------------------------------------------------------- /img/git-fork-new-project-push-pull-request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/git-fork-new-project-push-pull-request.png -------------------------------------------------------------------------------- /img/git-fork-update.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/git-fork-update.jpg -------------------------------------------------------------------------------- /img/git-therapy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/git-therapy.jpg -------------------------------------------------------------------------------- /img/git-via-ssh-or-https-github-api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/git-via-ssh-or-https-github-api.png -------------------------------------------------------------------------------- /img/github-https-or-ssh-url-annotated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/github-https-or-ssh-url-annotated.png -------------------------------------------------------------------------------- /img/github-https-url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/github-https-url.png -------------------------------------------------------------------------------- /img/github-pull-push.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/github-pull-push.jpeg -------------------------------------------------------------------------------- /img/github-screenshot-copy-the-full-sha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/github-screenshot-copy-the-full-sha.png -------------------------------------------------------------------------------- /img/github-ssh-url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/github-ssh-url.png -------------------------------------------------------------------------------- /img/gitkraken-pkgdown-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/gitkraken-pkgdown-screenshot.png -------------------------------------------------------------------------------- /img/gitkraken-screenshot-copy-commit-sha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/gitkraken-screenshot-copy-commit-sha.png -------------------------------------------------------------------------------- /img/maybe_fork.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/maybe_fork.jpeg -------------------------------------------------------------------------------- /img/maybe_ours_or_theirs.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/maybe_ours_or_theirs.jpeg -------------------------------------------------------------------------------- /img/new-personal-access-token-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/new-personal-access-token-screenshot.png -------------------------------------------------------------------------------- /img/new-project-github-first.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/new-project-github-first.jpeg -------------------------------------------------------------------------------- /img/no-github.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/no-github.jpeg -------------------------------------------------------------------------------- /img/ours-them.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/ours-them.jpeg -------------------------------------------------------------------------------- /img/ours-you.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/ours-you.jpeg -------------------------------------------------------------------------------- /img/pat-kills-both-birds.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/pat-kills-both-birds.jpeg -------------------------------------------------------------------------------- /img/pull-push-yours.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/pull-push-yours.png -------------------------------------------------------------------------------- /img/refs-branches-and-HEAD-1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/refs-branches-and-HEAD-1.jpeg -------------------------------------------------------------------------------- /img/refs-branches-and-HEAD-2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/refs-branches-and-HEAD-2.jpeg -------------------------------------------------------------------------------- /img/refs-only-branches.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/refs-only-branches.jpeg -------------------------------------------------------------------------------- /img/refs-only-shas.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/refs-only-shas.jpeg -------------------------------------------------------------------------------- /img/refs-relative.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/refs-relative.jpeg -------------------------------------------------------------------------------- /img/refs-tag.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/refs-tag.jpeg -------------------------------------------------------------------------------- /img/rstudio-new-branch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/rstudio-new-branch.png -------------------------------------------------------------------------------- /img/screenshots/github-commit-listing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/screenshots/github-commit-listing.png -------------------------------------------------------------------------------- /img/screenshots/github-link-to-commits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/screenshots/github-link-to-commits.png -------------------------------------------------------------------------------- /img/screenshots/github-repo-search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/screenshots/github-repo-search.png -------------------------------------------------------------------------------- /img/screenshots/github-specific-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/screenshots/github-specific-file.png -------------------------------------------------------------------------------- /img/six-configs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/six-configs.png -------------------------------------------------------------------------------- /img/sourcetree-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/sourcetree-screenshot.png -------------------------------------------------------------------------------- /img/terminal_mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/terminal_mac.png -------------------------------------------------------------------------------- /img/terminal_mac_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/terminal_mac_search.png -------------------------------------------------------------------------------- /img/theirs.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/theirs.jpeg -------------------------------------------------------------------------------- /img/updating_a_git_fork.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/updating_a_git_fork.pdf -------------------------------------------------------------------------------- /img/updating_a_git_fork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/updating_a_git_fork.png -------------------------------------------------------------------------------- /img/use_github.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/use_github.jpeg -------------------------------------------------------------------------------- /img/watch-me-diff-watch-me-rebase-smaller.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/watch-me-diff-watch-me-rebase-smaller.png -------------------------------------------------------------------------------- /img/windows-rstudio-git-executable-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jennybc/happy-git-with-r/05b5f470cf6dcdd6fdec31489ee16c686c175e90/img/windows-rstudio-git-executable-screenshot.png -------------------------------------------------------------------------------- /index.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Happy Git and GitHub for the useR" 3 | author: "Jenny Bryan, the STAT 545 TAs, Jim Hester" 4 | site: bookdown::bookdown_site 5 | documentclass: book 6 | bibliography: [book.bib, packages.bib] 7 | biblio-style: apalike 8 | link-citations: yes 9 | github-repo: jennybc/happy-git-with-r 10 | description: "Using Git and GitHub with R, Rstudio, and R Markdown" 11 | twitter-handle: jennybryan 12 | url: 'https\://happygitwithr.com/' 13 | cover-image: img/watch-me-diff-watch-me-rebase-smaller.png 14 | --- 15 | 16 | # Let's Git started {-} 17 | 18 |
    19 | Cover image 20 |

    Still from Heaven King video

    21 |
    22 | 23 | Happy Git provides opinionated instructions on how to: 24 | 25 | * Install Git and get it working smoothly with GitHub, in the shell and in the [RStudio IDE](https://www.rstudio.com/products/rstudio/). 26 | * Develop a few key workflows that cover your most common tasks. 27 | * Integrate Git and GitHub into your daily work with R and [R Markdown](https://rmarkdown.rstudio.com). 28 | 29 | The target reader is someone who uses R for data analysis or who works on R packages, although some of the content may be useful to those working in adjacent areas. 30 | 31 | The first two parts, [Installation](#install-intro) and [Connect Git, GitHub, RStudio](#connect-intro), provide a "batteries included" quick start to verify your setup. 32 | 33 | In [Early GitHub Wins](#usage-intro), we rack up some early success with the basic workflows that are necessary to get your work onto GitHub. We also show the special synergy between R/R Markdown/RStudio and GitHub, which provides a powerful demonstration of why all this setup is worthwhile. 34 | 35 | The use of Git/GitHub in data science has a slightly different vibe from that of pure software development, due to differences in the user's context and objective. Happy Git aims to complement existing, general Git resources by highlighting the most rewarding usage patterns for data science. This perspective on the Git landscape is presented in [Basic Git Concepts](#git-intro) and [Daily Workflows](#workflows-intro). 36 | 37 | ## License {-} 38 | 39 | Creative Commons License
    Happy Git and GitHub for the useR by Jennifer Bryan is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License. 40 | 41 | ```{r include = FALSE} 42 | # automatically create a bib database for R packages 43 | knitr::write_bib(c( 44 | .packages(), 'bookdown', 'knitr', 'rmarkdown' 45 | ), 'packages.bib') 46 | ``` 47 | -------------------------------------------------------------------------------- /install-git-client.Rmd: -------------------------------------------------------------------------------- 1 | # Install a Git client {#git-client} 2 | 3 | This is optional but **highly recommended**. 4 | 5 | Learning to use version control can be rough at first. I found the use of a GUI – as opposed to the command line – extremely helpful when I was getting started. I call this sort of helper application a Git client. It's really a Git(Hub) client because it also helps you interact with GitHub or other remotes. 6 | 7 | A Git client is not required for live workshops and will not be explicitly taught, though you might see us using one of these clients. 8 | 9 | ## What is a Git client? Why would you want one? 10 | 11 | "Git" is really just a collection of individual commands you execute in the shell (Appendix \@ref(shell)). This interface is not appealing for everyone. Some may prefer to do Git operations via a client with a graphical interface. 12 | 13 | Git and your Git client are not the same thing, just like R and RStudio are not the same thing. A Git client and an [integrated development environment](https://en.wikipedia.org/wiki/Integrated_development_environment), such as RStudio, are not necessary to use Git or R, respectively. But they make the experience more pleasant because they reduce the amount of "command line bullshittery"[^1] and provide a richer visual representation of the current state. 14 | 15 | [^1]: This evocative phrase originally appeared in a blog post by Philip Guo, which has subsequently been removed from the internet. 16 | 17 | RStudio offers a very basic Git client via its Git pane. I use this often for simple operations, but you probably want another, more powerful one as well. 18 | 19 | Fair warning: for some tasks, you must use the command line. But the more powerful your Git client is, the less often this happens. The visual overview given by your Git client can also be invaluable for understanding the current state of things, even when preparing calls to command line Git. 20 | 21 | Fantastic news: because all of the clients are just forming and executing Git commands on your behalf, you don't have to pick one. 22 | You can literally do one operation from the command line, do another from RStudio, and another from GitKraken, one after the other, and it just works. 23 | *Very rarely, both clients will scan the repo at the same time and you'll get an error message about `.git/index.lock`. 24 | Try the operation again at least once before doing any further troubleshooting.* 25 | 26 | ## A picture is worth a thousand words 27 | 28 | Here's a screenshot of GitKraken (see below) open to the repository for the R package [pkgdown](https://pkgdown.r-lib.org). 29 | You get a nice graphical overview of the recent commit history, branches, and diffs, as well as a GUI that facilitates the most common Git operations. 30 | 31 | ```{r} 32 | #| echo = FALSE, fig.align = "center", out.width = "100%", 33 | #| fig.alt = "GitKraken screenshot" 34 | knitr::include_graphics("img/gitkraken-pkgdown-screenshot.png") 35 | ``` 36 | 37 | In contrast, here's a shell session where I've used command line Git to access some of the same information. 38 | 39 | ```console 40 | jenny@jennys-MacBook-Pro pkgdown % git log --oneline -n 10 41 | cd888bed (HEAD -> master, upstream/master, upstream/HEAD, r-lib/master, r-lib/HEAD) Remove accidentally committed snapshot 42 | ca01d386 Add a skip link (#1833) 43 | 1f07a145 Include section class in generated subsection divs 44 | 26e1dcf2 Restore code colouring 45 | 77503979 Working on docs (#1828) 46 | 3c805e1a Make anchor tweaking stricter 47 | a6ae3ca4 use_tidy_description() 48 | d43260fb Tweak authors order 49 | 41c855df Tweak details styling 50 | 7d3c484c Anchor & news tweaks (#1830) 51 | ``` 52 | 53 | Which do you prefer? 54 | 55 | ## No one is giving out Git Nerd merit badges 56 | 57 | Work with Git in whatever way makes you most effective. 58 | Feel free to revisit your approach over time or to use different approaches for different tasks or in different settings. 59 | No one can tell whether you use the command line or a GUI when they look at your Git history or your GitHub repo. 60 | 61 | I sometimes encounter people who feel it's "better" to use command line Git, but for very ill-defined reasons. 62 | These people may feel like they *should* work in the shell, even if it leads to Git-avoidance, frequent mistakes, or limiting themselves to a small set of ~3 Git commands. 63 | This is counterproductive. 64 | 65 | I had two false starts with Git, where I failed to get proficient enough, quickly enough to truly incorporate version control into my daily work. 66 | I found a visual Git client invaluable. 67 | It made me willing to use Git multiple times per day, for a sustained period of time. 68 | This helped me build the mental model necessary for more advanced Git operations like rebasing, cherry-picking, and resetting. 69 | 70 | If your Git life happens on your own computer, there is no reason to deny yourself a GUI if that's what you like. 71 | If you prefer working in the shell or if you frequently log into a remote server, then it makes sense to prioritize building Git skills at the command line. 72 | Do whatever works for you, but don't do anything for the sake of purity or heroism. 73 | 74 | ## Recommended Git clients 75 | 76 | * [GitKraken](https://www.gitkraken.com) is a free, powerful Git(Hub) client that is my current favorite. It's especially exciting because it works on Windows, macOS, and Linux. This is great news, especially for long-suffering Linux users who previously had very few options. I used the free version for years, which works great, but now I happily pay money for the pro version. 77 | 78 | * [SourceTree](https://www.sourcetreeapp.com) is another free client that I used to highly recommend. It was my first beloved Git client, but I eventually had to give it up, due to long-standing bugs / deficiencies that seemed like they would never be fixed ([macOS bug re: leaking file handles](http://openradar.appspot.com/radar?id=1387401), no ability to control font size). GitKraken feels much more actively developed and has completely supplanted SourceTree for me. 79 | 80 | * GitHub offers a free Git(Hub) client, [GitHub Desktop](https://desktop.github.com/), for Windows and macOS. Although we previously discouraged its use, GitHub's client has since gotten a thorough makeover that eliminates several of our concerns, so we're cautiously optimistic. GitHub Desktop is aimed at beginners who want the most useful features of Git front and center. The flipside is that it may not support some of the more advanced workflows exposed by the clients above and, consequently, may not develop your mental model of Git as thoroughly. 81 | 82 | * Browse [even more Git(Hub) clients](http://git-scm.com/downloads/guis). 83 | -------------------------------------------------------------------------------- /install-git.Rmd: -------------------------------------------------------------------------------- 1 | # Install Git {#install-git} 2 | 3 | You need Git, so you can use it at the command line and so RStudio can call it. 4 | 5 | If there's any chance it's installed already, verify that, rejoice, and skip this step. (But consider *updating* an existing installation.) 6 | 7 | Otherwise, find installation instructions below for your operating system. 8 | 9 | ```{r setup, include = FALSE} 10 | has_bash <- Sys.which('bash') != '' && .Platform$OS.type != 'windows' 11 | ``` 12 | 13 | ## Git already installed? 14 | 15 | Go to the shell (Appendix \@ref(shell)). Enter `which git` to request the path to your Git executable: 16 | 17 | ```{bash collapse = TRUE, eval = has_bash} 18 | which git 19 | ``` 20 | 21 | and `git --version` to see its version: 22 | 23 | ```{bash collapse = TRUE, eval = has_bash} 24 | git --version 25 | ``` 26 | 27 | If you are successful, that's great! You have Git already. No need to install! Move on. 28 | 29 | If, instead, you see something more like `git: command not found`, keep reading. 30 | 31 | macOS users might get an immediate offer to install command line developer tools. Yes, you should accept! Click "Install" and read more below. 32 | 33 | ## Windows {#install-git-windows} 34 | 35 | **Option 1** (*highly recommended*): Install [Git for Windows](https://git-for-windows.github.io/), also known as `msysgit` or "Git Bash", to get Git in addition to some other useful tools, such as the Bash shell. Yes, all those names are totally confusing, but you might encounter them elsewhere and I want you to be well-informed. 36 | 37 | We like this because Git for Windows leaves the Git executable in a conventional location, which will help you and other programs, e.g. RStudio, find it and use it. This also supports a transition to more expert use, because the "Git Bash" shell will be useful as you venture outside of R/RStudio. 38 | 39 | * **NOTE:** When asked about "Adjusting your PATH environment", make sure to select "Git from the command line and also from 3rd-party software". Otherwise, we believe it is good to accept the defaults. 40 | * Note that RStudio for Windows prefers for Git to be installed below `C:/Program Files` and this appears to be the default. This implies, for example, that the Git executable on my Windows system is found at `C:/Program Files/Git/bin/git.exe`. Unless you have specific reasons to otherwise, follow this convention. 41 | 42 | This also leaves you with a Git client, though not a very good one. So check out Git clients we recommend (chapter \@ref(git-client)). 43 | 44 | FYI, this appears to be equivalent to what you would download from here: . 45 | 46 | **Option 2** (*recommended*): Install [Git for Windows](https://git-for-windows.github.io/) via the [Chocolatey](https://chocolatey.org) package manager. If this means anything to you, Chocolatey is like [`apt-get`](https://en.wikipedia.org/wiki/APT_(Debian)) or [Homebrew](https://brew.sh), but for Windows instead of Debian/Ubuntu Linux or macOS. As far as I can tell, using Chocolatey to install Git for Windows gives the same result as installing it yourself (option 1). 47 | 48 | This obviously requires that you already have [Chocolatey](https://chocolatey.org) installed or that you are up for installing it. It is not hard and the [instructions are here](https://chocolatey.org/install). This may be worthwhile if it seems likely you will be installing more open source software in the future. 49 | 50 | After you install Chocolatey, in a shell (Appendix \@ref(shell)), do: 51 | 52 | ``` bash 53 | choco install git.install 54 | ``` 55 | 56 | This installs the most current [Git (Install) X.Y.Z](https://chocolatey.org/packages/git.install) Chocolatey package. At the time of writing, that is "Git (Install) 2.33.1", but that version number will increment over time. 57 | 58 | ### Updating Git for Windows 59 | 60 | If you already have Git for Windows, but it's not the latest version, it's a good idea to update. 61 | You can [update like so from the command line](https://github.com/git-for-windows/git/wiki/FAQ#how-do-i-update-git-for-windows-upon-new-releases): 62 | 63 | ``` bash 64 | git update-git-for-windows 65 | ``` 66 | 67 | ## macOS 68 | 69 | **Option 1** (*highly recommended*): Install the Xcode command line tools (**not all of Xcode**), which includes Git. 70 | 71 | Go to the shell and enter one of these commands to elicit an offer to install developer command line tools: 72 | 73 | ``` bash 74 | git --version 75 | git config 76 | ``` 77 | 78 | Accept the offer! Click on "Install". 79 | 80 | Here's another way to request this installation, more directly: 81 | 82 | ``` bash 83 | xcode-select --install 84 | ``` 85 | 86 | We just happen to find this Git-based trigger apropos. 87 | 88 | Note also that, after upgrading macOS, you might need to re-do the above and/or re-agree to the Xcode license agreement. We have seen this cause the RStudio Git pane to disappear on a system where it was previously working. Use commands like those above to tickle Xcode into prompting you for what it needs, then restart RStudio. 89 | 90 | **Option 2** (*recommended*): Install Git from here: . 91 | 92 | * This arguably sets you up the best for the future. It will certainly get you the latest version of Git of all approaches described here. 93 | * The GitHub home for the macOS installer is here: . 94 | - At that link, you can find more info if something goes wrong or you are working on an old version of macOS. 95 | 96 | **Option 3** (*recommended*): If you anticipate getting heavily into scientific computing, you're going to be installing and updating lots of software. You should check out [Homebrew](http://brew.sh), "the missing package manager for OS X". Among many other things, it can install Git for you. Once you have Homebrew installed, do this in the shell: 97 | 98 | ``` 99 | brew install git 100 | ``` 101 | 102 | 103 | ## Linux 104 | 105 | Install Git via your distro's package manager. 106 | 107 | Ubuntu or Debian Linux: 108 | 109 | ```sh 110 | sudo apt-get install git 111 | ``` 112 | 113 | Fedora or RedHat Linux: 114 | 115 | ```sh 116 | sudo yum install git 117 | ``` 118 | 119 | A comprehensive list for various Linux and Unix package managers: 120 | 121 | 122 | -------------------------------------------------------------------------------- /install-github-acct.Rmd: -------------------------------------------------------------------------------- 1 | # Register a GitHub account {#github-acct} 2 | 3 | Register an account with GitHub. It's free! 4 | 5 | * 6 | 7 | ## Username advice 8 | 9 | You will be able to upgrade to a paid level of service, apply discounts, join organizations, etc. in the future, so don't fret about any of that now. **Except your username. You might want to give that some thought.** 10 | 11 | A few tips, which sadly tend to contradict each other: 12 | 13 | * Incorporate your actual name! People like to know who they're dealing with. Also makes your username easier for people to guess or remember. 14 | * Reuse your username from other contexts, e.g., Twitter or Slack. But, of course, someone with no GitHub activity will probably be squatting on that. 15 | * Pick a username you will be comfortable revealing to your future boss. 16 | * Shorter is better than longer. 17 | * Be as unique as possible in as few characters as possible. In some settings GitHub auto-completes or suggests usernames. 18 | * Make it timeless. Don't highlight your current university, employer, or place of residence, e.g. JennyFromTheBlock. 19 | * Avoid words laden with special meaning in programming. In my first inept efforts to script around the GitHub API, I assigned lots of issues to [the guy with username `NA`](https://github.com/na) because my vector of GitHub usernames contained missing values. A variant of [Little Bobby Tables](https://xkcd.com/327/). 20 | * Avoid the use of upper vs. lower case to separate words. We highly recommend all lowercase. GitHub treats usernames in a case insensitive way, but using all lowercase is kinder to people doing downstream regular expression work with usernames, in various languages. A better strategy for word separation is to use a hyphen `-`. 21 | 22 | You can change your username later, but better to get this right the first time. 23 | 24 | * 25 | * 26 | 27 | ## Free private repos 28 | 29 | GitHub offers free unlimited private repositories for all users. These free private repositories support up to three external collaborators, making them a perfect place for your personal projects, for job applications, and testing things out before making your project open source. 30 | 31 | Go ahead and register your free account NOW and then pursue any special offer that applies to you: 32 | 33 | * Students, faculty, and educational/research staff: [GitHub Education](https://education.github.com). 34 | - GitHub "Organizations" can be extremely useful for courses or research/lab groups, where you need some coordination across a set of repos and users. 35 | * Official nonprofit organizations and charities: [GitHub for Good](https://github.com/nonprofit) 36 | 37 | ## Pay for private repos 38 | 39 | Anyone can pay to have private repos with support for unlimited collaborators. A personal plan with private repos supporting unlimited collaborators is $7 / month at the time of writing, and includes several [advanced features](https://help.github.com/articles/github-s-products/#github-pro). See the current plans and pricing here: 40 | 41 | * 42 | 43 | Go ahead and register your free account NOW. You can decide later if you'd like to upgrade to a paid plan. 44 | -------------------------------------------------------------------------------- /install-intro.Rmd: -------------------------------------------------------------------------------- 1 | # (PART) Installation {-} 2 | 3 | # Half the battle {#install-intro .unnumbered} 4 | 5 | Getting all the necessary software installed, configured, and playing nicely together is honestly half the battle when first adopting Git. Brace yourself for some pain. The upside is that you can give yourself a pat on the back once you get through this. And you WILL get through this. 6 | 7 | You will find far more resources for how to *use Git* than for installation and configuration. Why? The experts ... 8 | 9 | * Have been doing this for years. It's simply not hard for them anymore. 10 | * Probably use some flavor of Unix. They may secretly (or not so secretly) take pride in neither using nor knowing Windows. 11 | * Get more satisfaction and reward for thinking and writing about Git concepts and workflows than Git installation. 12 | 13 | In their defense, it's hard to write installation instructions. Failures can be specific to an individual OS or even individual computer. If you have some new problem and, especially, the corresponding solution, [we'd love to hear from you!](https://github.com/jennybc/happy-git-with-r/issues) 14 | 15 | ## Success and operating systems {-} 16 | 17 | 22 | 23 | Our installation instructions have been forged in the fires of [STAT 545](http://stat545.com), [STAT 540](https://stat540-ubc.github.io), and assorted workshops, over several years. We regularly hear from [grateful souls](https://twitter.com/ibddoctor/status/777610645617475584) [on the internet](https://twitter.com/millsGT49/status/647059167509921793) who also have success. 24 | 25 | Here's data on the operating systems we encounter in STAT 545 and other workshops: overall the bulk are split sort of evenly between Mac and Windows (various flavours), with a dash of Linux. Except in a BioConductor context (CSAMA), which is dominated by Mac or Linux. 26 | 27 | | | 2014 | 2015 | 2016 | useR! 2016 | CSAMA 2016 | CSAMA 2017 | r::c 2018 | seattle 2018 | 28 | |------------:|---------:|---------:|---------:|-----------:|-----------:|-----------:|----------:|-------------:| 29 | | Mac | 16 (41%) | 38 (52%) | 37 (45%) | 28 (44%) | 25 (58%) | 23 (56%) | 51 (57%) | 16 (49%) | 30 | | Windows 10* | 0 (0%) | 8 (11%) | 30 (36%) | 27 (43%) | 6 (14%) | 8 (20%) | 19 (21%) | 12 (36%) | 31 | | Windows 8 | 12 (31%) | 9 (12%) | 4 (5%) | | | 1 ( 2%) | 2 (2%) | | 32 | | Windows 7 | 9 (23%) | 13 (18%) | 10 (12%) | | | 1 ( 2%) | 13 (14%) | 4 (12%) | 33 | | Linux | 2 (5%) | 5 (7%) | 2 (2%) | 8 (13%) | 12 (28%) | 9 (20%) | 5 (6%) | 1 (3%) | 34 | 35 | \* Windows 10 is the Windows catchall, when I don't have more specific info. 36 | -------------------------------------------------------------------------------- /install-introduce-self-git.Rmd: -------------------------------------------------------------------------------- 1 | # Introduce yourself to Git {#hello-git} 2 | 3 | In the shell (Appendix \@ref(shell)): 4 | 5 | ``` bash 6 | git config --global user.name "Jane Doe" 7 | git config --global user.email "jane@example.com" 8 | git config --global --list 9 | ``` 10 | 11 | substituting your name and **the email associated with your GitHub account**. 12 | 13 | The [usethis package](https://usethis.r-lib.org) offers an alternative approach. You can set your Git user name and email from within R: 14 | 15 | ```{r, eval = FALSE} 16 | ## install if needed (do this exactly once): 17 | ## install.packages("usethis") 18 | 19 | library(usethis) 20 | use_git_config(user.name = "Jane Doe", user.email = "jane@example.org") 21 | ``` 22 | 23 | ## More about `git config` 24 | 25 | An easy way to get into a shell from RStudio is *Tools > Terminal* or *Tools > Shell*. More about the shell in the Appendix \@ref(shell). 26 | 27 | Special Windows gotchas: If you are struggling on Windows, consider there are different types of shell and you might be in the wrong one. You want to be in a "Git Bash" shell, as opposed to Power Shell or the legacy `cmd.exe` command prompt. Read more in [the Appendix](#windows-shell-hell). This might also be a reason to do this configuration via the usethis package in R. 28 | 29 | What user name should you give to Git? This does not have to be your GitHub user name, although it can be. Another good option is your actual first name and last name. If you commit from different machines, sometimes people work that info into the user name. Your commits will be labelled with this user name, so make it informative to potential collaborators and future you. 30 | 31 | What email should you give to Git? This __must__ be the email associated with your GitHub account. 32 | 33 | The first two commands used in the shell beginning with `git config --global` return nothing in the terminal. You can check that Git understood what you typed by looking at the output of the third from `git config --global --list`. 34 | 35 | ### Configure the Git editor {#git-editor} 36 | 37 | Another Git option that many people eventually configure is the editor. At some point, you will fail to give Git what it wants in terms of a commit message and it will kick you into an editor. This can be distressing, if it's not your editor of choice and you don't even know how to save and quit. You can enforce your will with something along these lines: 38 | 39 | ``` bash 40 | git config --global core.editor "emacs" 41 | ``` 42 | 43 | Substitute your preferred editor for `"emacs"` here. Software Carpentry's Git lesson has a comprehensive listing of the exact `git config` command needed for [many combinations of OS and editor](https://swcarpentry.github.io/git-novice/02-setup.html). 44 | 45 | ### Configure the default name for an initial branch 46 | 47 | You may also want to configure the default name for the initial branch in a new repo. 48 | Historically, this has been `master`, as that was baked into Git itself. 49 | It's increasingly common to use `main` instead, but you have to opt-in to this. 50 | 51 | In 2020, the `init.defaultBranch` setting was introduced so that this became user-configurable. 52 | Shortly thereafter, major Git hosts like GitHub and GitLab made `main` the default initial branch name for repos created on their platforms and also provided considerable support for renaming existing default branches. 53 | 54 | You can set your default initial branch name to `main` like so, in the shell: 55 | 56 | ``` bash 57 | git config --global init.defaultBranch main 58 | ``` 59 | 60 | or from R (the default for `name` is `"main"`): 61 | 62 | ```{r eval = FALSE} 63 | usethis::git_default_branch_configure() 64 | ``` 65 | -------------------------------------------------------------------------------- /install-r-rstudio.Rmd: -------------------------------------------------------------------------------- 1 | # Install or upgrade R and RStudio {#install-r-rstudio} 2 | 3 | ```{r, include = FALSE} 4 | knitr::opts_chunk$set( 5 | comment = "#>", 6 | collapse = TRUE 7 | ) 8 | ``` 9 | 10 | 1. Install a pre-compiled binary of R for your OS from here: 11 | 12 | Already have R installed? **Hold on: This is a great time to make sure your R installation is current.** Check your current version like so: 13 | ```{r} 14 | R.version.string 15 | ``` 16 | 2. Install RStudio Desktop for your OS from here: 17 | 18 | 3. Update your R packages: 19 | ```{r, eval = FALSE} 20 | update.packages(ask = FALSE, checkBuilt = TRUE) 21 | ``` 22 | 23 | ## How to think about upgrading R and RStudio 24 | 25 | **Get current, people.** You don't want to adopt new things on day one. But at some point, running old versions of software adds unnecessary difficulty. 26 | 27 | In live workshops, there is a limit to how much we can help with ancient versions of R or RStudio. Also, frankly, there is a limit to our motivation. By definition, these problems are going away and we'd rather focus on edge cases with current versions, which affect lots of people. 28 | 29 | Is your R version "old"? R had a *major* version change in April 2020, with the release of 4.0.0. It is a good idea to be on the current major version, meaning 4.something at this point, especially if you want to get the most out of a workshop. 30 | 31 | Each major version is followed by several years of smaller releases (minor and patch releases). You can be more relaxed about upgrading minor versions, but you still want to stay reasonably current. As the 4.something series unfolds, I advise that you **never fall more than 1 minor version behind**. 32 | 33 | Concrete example: let's say the released version of R is 4.7.1, which is totally fictional and well beyond the current version of R at the time of writing. 34 | It's probably OK if you are still on 4.6.whatever, which is one minor version behind and is called "r-oldrel". 35 | Being one minor version behind usually doesn't cause trouble. 36 | Once you are 2 minor versions behind (4.5.whatever or earlier in this example), you will start to suffer. 37 | In particular, you can no longer install pre-built binary add-on packages from CRAN. 38 | 39 | Is your RStudio "old"? 40 | You can expect to update RStudio much more often than R itself. 41 | For example, I update RStudio every month or so, whereas I update R 1 or 2 times per year. 42 | -------------------------------------------------------------------------------- /notes-bookdown-cheat-sheet.Rmd: -------------------------------------------------------------------------------- 1 | # Bookdown cheat sheet 2 | 3 | Here's where I park _little_ *examples* **for myself** about bookdown mechanics that I keep forgetting. 4 | 5 | The bookdown book: 6 | 7 | ## Heading blah blah 8 | 9 | ## About labelling things {#id-example} 10 | 11 | You can label chapter and section titles using `{#label}` after them, e.g., we can reference Section \@ref(id-example). If you do not manually label them, there will be automatic labels anyway, e.g., this reference to the unlabelled heading \@ref(heading-blah-blah) uses the automatically generated label `\@ref(heading-blah-blah)`. 12 | 13 | ## Cross-references 14 | 15 | Add an explicit label by adding `{#label}` to the end of the section header. If you know you're going to refer to something, this is probably a good idea. 16 | 17 | To refer to in a chapter- or section-number-y way, use `\@ref(label)`. 18 | 19 | * `\@ref(install-git)` example: In chapter \@ref(install-git) we explain how to install Git. 20 | 21 | If you are happy with the section header as the link text, use it inside a single set of square brackets: 22 | 23 | * `[A picture is worth a thousand words]`: example "A picture is worth a thousand words" via [A picture is worth a thousand words] 24 | 25 | There are two ways to specify custom link text: 26 | 27 | * `[link text][Section header text]`, e.g., "pic = 1000 words" via [pic = 1000 words][A picture is worth a thousand words] 28 | * `[link text](#label)`, e.g., "RStudio, meet Git" via [RStudio, meet Git](#rstudio-see-git) 29 | 30 | The Pandoc documentation provides more details on automatic section IDs and implicit header references. 31 | 32 | ## Figures, tables, citations 33 | 34 | Figures and tables with captions will be placed in `figure` and `table` environments, respectively. 35 | 36 | ```{r nice-fig, fig.cap='Here is a nice figure!', out.width='80%', fig.asp=.75, fig.align='center'} 37 | par(mar = c(4, 4, .1, .1)) 38 | plot(pressure, type = 'b', pch = 19) 39 | ``` 40 | 41 | Reference a figure by its code chunk label with the `fig:` prefix, e.g., see Figure \@ref(fig:nice-fig). Similarly, you can reference tables generated from `knitr::kable()`, e.g., see Table \@ref(tab:nice-tab). 42 | 43 | ```{r nice-tab, tidy=FALSE} 44 | knitr::kable( 45 | head(iris, 20), caption = 'Here is a nice table!', 46 | booktabs = TRUE 47 | ) 48 | ``` 49 | 50 | You can write citations, too. For example, we are using the **bookdown** package [@R-bookdown] in this sample book, which was built on top of R Markdown and **knitr** [@knitr-book]. 51 | 52 | ## How the square bracket links work 53 | 54 | Context: you prefer to link with text, not a chapter or section number. 55 | 56 | * GOOD! Here's a link to [Contributors]. 57 | * BAD. You can see contributors in \@ref(contrib). 58 | 59 | Facts and vocabulary 60 | 61 | * Each chapter is a file. These files should begin with the chapter title using a level-one header, e.g., `# Chapter Title`. 62 | * A chapter can be made up of sections, indicated by lower-level headers, e.g., `## A section within the chapter`. 63 | * There are three ways to address a section when creating links within your book: 64 | - **Explicit identifier**: In `# My header {#foo}` the explicit identifier is `foo`. 65 | - **Automatically generated identifier**: `my-header` is the auto-identifier for `# My header`. Pandoc creates auto-identifiers according to rules laid out in [Extension: auto_identifiers](http://pandoc.org/README.html#extension-auto_identifiers). 66 | - The header text, e.g., `My header` be used verbatim as an **implicit header reference**. See [Extension: implicit_header_references](http://pandoc.org/README.html#extension-implicit_header_references) for more. 67 | * All 3 forms can be used to create cross-references but you build the links differently. 68 | * Advantage of explicit identification: You are less likely to update the section header and then forget to make matching edits to references elsewhere in the book. 69 | 70 | How to make text-based links using explicit identifiers, automatic identifiers, and implicit references: 71 | 72 | * Use implicit reference alone to get a link where the text is exactly the section header: 73 | - `[Introduce yourself to Git]` [Introduce yourself to Git] 74 | - `[Success and operating systems]` [Success and operating systems] 75 | * You can provide custom text for the link with all 3 methods of addressing a section: 76 | - Implicit header reference: `[link text][Recommended Git clients]` [link text][Recommended Git clients] 77 | - Explicit identifier: `[hello git! I'm Jenny](#hello-git)` [hello git! I'm Jenny](#hello-git) 78 | - Automatic identifier: `[Any text you want](#recommended-git-clients)` [Any text you want](#recommended-git-clients) 79 | -------------------------------------------------------------------------------- /notes-ideas.Rmd: -------------------------------------------------------------------------------- 1 | # Ideas for content 2 | 3 | ## Common workflow questions 4 | 5 | ### Common predicaments and how to recover/avoid 6 | 7 | https://twitter.com/JennyBryan/status/743457387730735104 8 | 9 | ### Keep something out of Git 10 | 11 | List it in `.gitignore.` 12 | 13 | ### I didn't mean to commit that 14 | 15 | Committing things you didn't mean to (too big, secret). How to undo. 16 | 17 | ## git stuff 18 | 19 | Git explainers, heavy on the diagrams 20 | 21 | https://twitter.com/JennyBryan/status/743548245645791232 22 | 23 | A Visual Git Reference 24 | http://marklodato.github.io/visual-git-guide/index-en.html 25 | 26 | A successful Git branching model 27 | http://nvie.com/posts/a-successful-git-branching-model/ 28 | 29 | A successful Git branching model considered harmful 30 | https://barro.github.io/2016/02/a-succesful-git-branching-model-considered-harmful/ 31 | 32 | Git Tutorials from Atlassian 33 | https://www.atlassian.com/git/tutorials/ 34 | 35 | Software Carpentry Git Novice Lesson 36 | http://swcarpentry.github.io/git-novice/ 37 | 38 | Michael Freeman slides on Git collaboration 39 | http://slides.com/michaelfreeman/git-collaboration#/ 40 | 41 | GitHub Training materials 42 | https://services.github.com/kit/ 43 | 44 | Git for Ages 4 and Up 45 | 46 | 47 | Learn Git Branching 48 | http://learngitbranching.js.org 49 | 50 | A Git Workflow Walkthrough Series 51 | http://vallandingham.me/git-workflow.html 52 | 53 | * Part 1: Feature Branches 54 | * Part 2: Reviewing Pull Requests 55 | * Part 3: Reviewing Pull Requests Locally 56 | * Part 4: Merging Pull Requests 57 | 58 | Git from the inside out 59 | https://codewords.recurse.com/issues/two/git-from-the-inside-out 60 | 61 | ## Disaster recovery 62 | 63 | 64 | 65 | Break it down: 66 | 67 | * Is something wrong with my filesystem/files? 68 | * Is my git repo messed up? 69 | * How can I keep this from happening again? 70 | 71 | Rebase avoidance techniques. 72 | 73 | Headless state. Rebase hell. 74 | 75 | What to do when you can't, e.g., switch branches. Stashing and WIP commits. 76 | 77 | ## Engage with R source on GitHub 78 | 79 | Browsing 80 | 81 | Searching 82 | 83 | * My gist, re: the cran user: 84 | 85 | Being a useful useR 86 | 87 | * stay informed re: development 88 | * use issues for bug reports, feature requests 89 | * make pull requests 90 | 91 | ## Workflow and psychology 92 | 93 | Stress of working in the open 94 | 95 | Workflows for group of 1, 2, 5, 10 96 | 97 | * Fork and Pull vs Shared Repository 98 | 99 | - 100 | - 101 | -------------------------------------------------------------------------------- /notes-intro.Rmd: -------------------------------------------------------------------------------- 1 | # (PART) Notes {-} 2 | 3 | # Notes {#notes-intro .unnumbered} 4 | 5 | This part holds content that is deprecated/stale, does not exist yet, or relates to bookdown mechanics. 6 | -------------------------------------------------------------------------------- /packages.bib: -------------------------------------------------------------------------------- 1 | @Manual{R-base, 2 | title = {R: A Language and Environment for Statistical Computing}, 3 | author = {{R Core Team}}, 4 | organization = {R Foundation for Statistical Computing}, 5 | address = {Vienna, Austria}, 6 | year = {2021}, 7 | url = {https://www.R-project.org/}, 8 | } 9 | 10 | @Manual{R-bookdown, 11 | title = {bookdown: Authoring Books and Technical Documents with R Markdown}, 12 | author = {Yihui Xie}, 13 | year = {2021}, 14 | note = {R package version 0.24}, 15 | url = {https://CRAN.R-project.org/package=bookdown}, 16 | } 17 | 18 | @Manual{R-knitr, 19 | title = {knitr: A General-Purpose Package for Dynamic Report Generation in R}, 20 | author = {Yihui Xie}, 21 | year = {2022}, 22 | note = {R package version 1.39}, 23 | url = {https://yihui.org/knitr/}, 24 | } 25 | 26 | @Manual{R-rmarkdown, 27 | title = {rmarkdown: Dynamic Documents for R}, 28 | 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}, 29 | year = {2022}, 30 | note = {R package version 2.14}, 31 | url = {https://CRAN.R-project.org/package=rmarkdown}, 32 | } 33 | 34 | @Book{bookdown2016, 35 | title = {bookdown: Authoring Books and Technical Documents with {R} Markdown}, 36 | author = {Yihui Xie}, 37 | publisher = {Chapman and Hall/CRC}, 38 | address = {Boca Raton, Florida}, 39 | year = {2016}, 40 | note = {ISBN 978-1138700109}, 41 | url = {https://bookdown.org/yihui/bookdown}, 42 | } 43 | 44 | @Book{knitr2015, 45 | title = {Dynamic Documents with {R} and knitr}, 46 | author = {Yihui Xie}, 47 | publisher = {Chapman and Hall/CRC}, 48 | address = {Boca Raton, Florida}, 49 | year = {2015}, 50 | edition = {2nd}, 51 | note = {ISBN 978-1498716963}, 52 | url = {https://yihui.org/knitr/}, 53 | } 54 | 55 | @InCollection{knitr2014, 56 | booktitle = {Implementing Reproducible Computational Research}, 57 | editor = {Victoria Stodden and Friedrich Leisch and Roger D. Peng}, 58 | title = {knitr: A Comprehensive Tool for Reproducible Research in {R}}, 59 | author = {Yihui Xie}, 60 | publisher = {Chapman and Hall/CRC}, 61 | year = {2014}, 62 | note = {ISBN 978-1466561595}, 63 | url = {http://www.crcpress.com/product/isbn/9781466561595}, 64 | } 65 | 66 | @Book{rmarkdown2018, 67 | title = {R Markdown: The Definitive Guide}, 68 | author = {Yihui Xie and J.J. Allaire and Garrett Grolemund}, 69 | publisher = {Chapman and Hall/CRC}, 70 | address = {Boca Raton, Florida}, 71 | year = {2018}, 72 | note = {ISBN 9781138359338}, 73 | url = {https://bookdown.org/yihui/rmarkdown}, 74 | } 75 | 76 | @Book{rmarkdown2020, 77 | title = {R Markdown Cookbook}, 78 | author = {Yihui Xie and Christophe Dervieux and Emily Riederer}, 79 | publisher = {Chapman and Hall/CRC}, 80 | address = {Boca Raton, Florida}, 81 | year = {2020}, 82 | note = {ISBN 9780367563837}, 83 | url = {https://bookdown.org/yihui/rmarkdown-cookbook}, 84 | } 85 | 86 | -------------------------------------------------------------------------------- /preamble.tex: -------------------------------------------------------------------------------- 1 | \usepackage{booktabs} 2 | -------------------------------------------------------------------------------- /process-github-config-diagrams-for-happy-git.R: -------------------------------------------------------------------------------- 1 | library(tidyverse) 2 | library(magick) 3 | library(fs) 4 | library(here) 5 | 6 | # TODO: soon, I should move the source Keynote document (or part of it) 7 | # into this project 8 | exported_paths <- dir_ls("~/rrr/happy-git-with-r-slides/github-configs/2020-06_usethis-motivated-git-diagrams/") 9 | 10 | path_file(exported_paths) 11 | 12 | # practicing 13 | y <- image_read(exported_paths[[2]]) 14 | y 15 | 16 | # wow much fiddling here to get the crop geometry right 17 | # the border is just an visual aid 18 | z <- image_crop(y, geometry = "660x640+450+10") 19 | z %>% 20 | image_border(color = "blue") 21 | 22 | # doing it to all figs 23 | dir <- here("img", "github-configs") 24 | dir_create(dir) 25 | # clean out previous attempts 26 | dir_ls(dir) %>% 27 | file_delete() 28 | 29 | f <- function(file) { 30 | file %>% 31 | image_read() %>% 32 | image_crop(geometry = "660x640+450+10") %>% 33 | image_write(here("img", "github-configs", path_file(file))) 34 | } 35 | 36 | walk(exported_paths, f) 37 | 38 | cropped_paths <- dir_ls(dir) 39 | 40 | path_file(cropped_paths) 41 | 42 | name_dat <- tibble(filename = path_file(cropped_paths)) %>% 43 | mutate(number = str_extract(filename, "\\d+(?=[.]jpeg$)")) 44 | 45 | usethis_labels <- tribble( 46 | ~ number, ~ label, 47 | "001", "no_github", 48 | "002", "ours-you", 49 | "003", "ours-them", 50 | "004", "theirs", 51 | "005", "fork-them", 52 | "006", "fork-them-pull-request", 53 | "007", "fork-ours", 54 | "008", "fork_upstream_is_not_origin_parent", 55 | "009", "maybe_ours_or_theirs", 56 | "010", "maybe_fork" 57 | ) 58 | 59 | name_dat <- name_dat %>% 60 | left_join(usethis_labels) 61 | 62 | file_copy( 63 | cropped_paths, 64 | here("img", path_ext_set(name_dat$label, "png")), 65 | overwrite = TRUE 66 | ) 67 | -------------------------------------------------------------------------------- /prompt-burn-it-all-down.Rmd: -------------------------------------------------------------------------------- 1 | # Burn it all down {#burn} 2 | 3 | This is a highly inelegant, but effective technique for disaster recovery. 4 | 5 | It has been immortalized in an xkcd comic, so it must be ok: 6 | 7 | * 8 | * 9 | 10 | Basic idea: 11 | 12 | * Commit early and often. 13 | * Push to a remote, like GitHub, often. 14 | * The state of things on GitHub is your new "worst case scenario". 15 | * If you really screw things up locally, copy all the files (or the ones that have changed) to a safe place. 16 | - Usually your files are JUST FINE. But it is easy to goof up the Git infrastructure when you're new at this. And it can be hard to get that straightened out on your own. 17 | * Rename the existing local repo as a temporary measure, i.e. before you do something radical, like delete it. 18 | * Clone the repo from GitHub to your local machine. You are back to a happy state. 19 | * Copy all relevant files back over from your safe space. The ones whose updated state you need to commit. 20 | * Stage and commit. Push. 21 | * Carry on with your life. 22 | 23 | Practice this before you need it, so you see how it works. 24 | 25 | -------------------------------------------------------------------------------- /prompt-clone.Rmd: -------------------------------------------------------------------------------- 1 | # (PART) Activity prompts {-} 2 | 3 | # Clone a repo {#clone} 4 | 5 | Clone someone else's repository on GitHub where you just want a copy. But you also want to track its evolution. That is what differentiates a GitHub clone from, say, simply downloading the ZIP archive at a specific point in time. 6 | 7 | Pick a GitHub repository that interests you. Inspiration: 8 | 9 | * an R package you care about 10 | * a data analytic project you find interesting 11 | - Example: The GitHub repo that underpins [Polygraphing's blog post](http://polygraph.cool/films/) analyzing 2,000 screenplays is here: 12 | - Example: FiveThirtyEight shared the data and code behind their [Gun Deaths in America](http://fivethirtyeight.com/gun-deaths/) project on GitHub: . Have a look around their other repos as well. 13 | 14 | Create a new RStudio Project from this GitHub repo. Refresh your memory of how to do that by re-visiting our "GitHub first" workflow in chapter \@ref(new-github-first). 15 | 16 | Once you have the code locally, try to run some of it. Try to understand how it works. 17 | 18 | Do you want to make a change? Fine do that! 19 | 20 | Do you want to send changes back to the original author? Now you have firsthand knowledge of when you should *fork instead of clone*. See chapter \@ref(fork-and-clone). 21 | -------------------------------------------------------------------------------- /prompt-fork-pr-bingo.Rmd: -------------------------------------------------------------------------------- 1 | # Create a bingo card {#bingo} 2 | 3 | Here's a specific suggestion for practicing "fork and pull". 4 | 5 | The general workflow is laid out in chapter \@ref(fork-and-clone). 6 | 7 | Jenny and Dean have a repository that makes bingo cards with R: 8 | 9 | * 10 | * Read the README to learn more about it! 11 | 12 | Your mission: 13 | 14 | * Maybe find a partner? Or a couple of partners? 15 | * Fork the `bingo` repo. 16 | * Clone it to someone's local machine. 17 | * Create a new bingo card by making a file of possible squares. 18 | - Follow the instructions in to see how to contribute a new card. 19 | - Protip: It's easy to be very funny, but create a very difficult bingo card. Remember to include some easy stuff so people have a chance to bingo. 20 | * If you're feeling virtuous, run the tests and check the package. Ask us for help! Or live dangerously and skip this. 21 | * Commit! 22 | * Push your changes back to your copy of the repo on GitHub. 23 | * Make a pull request back to the main `bingo` repo. 24 | * If your card is appropriate, we'll merge your request and it will become part of the package and available via the [Shiny app](http://daattali.com/shiny/bingo/). 25 | 26 | **Special inspiration for useR**: 27 | 28 | * Make useR-specific conference bingo. 29 | * See this issue thread for lots of square ideas! 30 | - 31 | 32 | 33 | -------------------------------------------------------------------------------- /prompt-practice-resets.Rmd: -------------------------------------------------------------------------------- 1 | # Resetting {#reset} 2 | 3 | Practice recovering from mistakes. 4 | 5 | Use a repository you've created earlier in the tutorial for this. It only needs to be local, i.e. this does not involve GitHub. 6 | 7 | If it's not your most recent commit, seriously consider just letting that go. Just. Let. It. Go. 8 | 9 | So you want to undo the last commit? 10 | 11 | If "YES UNDO IT COMPLETELY": `git reset --hard HEAD^`. You will lose any changes that were not reflected in the commit-before-last! 12 | 13 | If "YES undo the commit, but leave the files in that state (but unstaged)": `git reset HEAD^`. Your files will stay the same but the commit will be undone and nothing will be staged. 14 | 15 | If "YES go right back to the moment before I committed": `git reset --soft HEAD^`. Your files will stay the same but the commit will be undone. Even your staged changes will be restored. 16 | 17 | **If you just want to fiddle with the most recent commit or its message, you can amend it. You can do this from RStudio!** 18 | 19 | * Make the change you want and amend the commit. 20 | * Do you only want to change the commit message? 21 | - Make another small change. Surely you have a typo somewhere? Amend the commit, which gives you the chance to edit the message 22 | 23 | To amend from the command line, using an editor to create the message: 24 | 25 | ``` bash 26 | git commit --amend 27 | ``` 28 | 29 | To amend from the command line, providing the new message: 30 | 31 | ``` bash 32 | git commit --amend -m "New commit message" 33 | ``` 34 | 35 | Git Reset Demystified: 36 | 37 | 38 | -------------------------------------------------------------------------------- /prompt-search-github.Rmd: -------------------------------------------------------------------------------- 1 | # Search GitHub {#search} 2 | 3 | ## Basic resources 4 | 5 | GitHub searching 6 | 7 | * 8 | * 9 | * 10 | 11 | Read-only mirror of R source by Winston Chang: 12 | 13 | * 14 | 15 | Read-only mirror of all packages on CRAN by Gábor Csárdi: 16 | 17 | * 18 | * 19 | * [METACRAN](http://www.r-pkg.org) 20 | 21 | ## Use case 22 | 23 | What if a function in a package has no examples? Or is poorly exampled? Wouldn't it be nice to find functioning instances of it "in the wild"? 24 | 25 | [Via Twitter](https://twitter.com/noamross/status/563422536633839617), Noam Ross taught me a clever way to do such searches on GitHub. Put this into the GitHub search box to see how packages on CRAN use the `llply()` function from `plyr`: 26 | 27 | ``` bash 28 | "llply" user:cran language:R 29 | ``` 30 | 31 | Or just [click here](https://github.com/search?l=r&q=%22llply%22+user%3Acran+language%3AR&ref=searchresults&type=Code). 32 | 33 | Another example that recently came up on r-package-devel: 34 | 35 | How to see lots of examples of roxygen templates? 36 | 37 | This search finds >1400 examples of roxygen templates in the wild: 38 | 39 | 40 | -------------------------------------------------------------------------------- /references.Rmd: -------------------------------------------------------------------------------- 1 | # Resources {#resources} 2 | 3 | We practice what we preach! This site is created with Git and R markdown, using the [`bookdown`](https://github.com/rstudio/bookdown/) package. Go ahead and [peek behind the scenes](https://github.com/jennybc/happy-git-with-r). 4 | 5 | Long-term, you should understand more about what you are doing. Rote clicking in RStudio may be a short-term survival method but won't work for long. 6 | 7 | * [Git for Humans](https://speakerdeck.com/alicebartlett/git-for-humans) is a great set of slides by [Alice Bartlett](https://alicebartlett.co.uk), originally delivered in 2016 at UX Brighton. 8 | 9 | * [Git in Practice](https://www.manning.com/books/git-in-practice) by Mike McQuaid is an more approachable book, probably better than Pro Git (below) for most people starting out. Ancillary materials [on GitHub](https://github.com/MikeMcQuaid/GitInPractice). 10 | 11 | * The book [Pro Git](http://git-scm.com/book) is fantastic and comprehensive. 12 | 13 | * [Oh My Git!](https://ohmygit.org/) is a free and open source interactive game for learning Git. It's very beginner friendly, using a graph to visualise the worktree. Lessons can be completed using a playing card interface in addition to the built-in command line, which is there for when users become more comfortable. 14 | 15 | * [GitHub's own training materials](https://training.github.com) may be helpful. They also point to [many other resources](https://help.github.com/articles/what-are-other-good-resources-for-learning-git-and-github) 16 | 17 | * Find a powerful Git client (chapter \@ref(git-client)) if you'd like to minimize your usage of Git from the command line. 18 | 19 | * Ten Simple Rules for Taking Advantage of Git and GitHub 20 | 21 | * RStudio's guide [Version Control with Git and SVN](https://support.rstudio.com/hc/en-us/articles/200532077-Version-Control-with-Git-and-SVN) 22 | 23 | * The book *[Team Geek](http://shop.oreilly.com/product/0636920018025.do)* has insightful advice for the human and collaborative aspects of version control. It proposes Git strategies suited to different characteristics of teams. 24 | 25 | `r if (knitr:::is_html_output()) '# References'` 26 | -------------------------------------------------------------------------------- /remote-setups-equivocal.Rmd: -------------------------------------------------------------------------------- 1 | # Equivocal remote setups {#equivocal} 2 | 3 | Just like the previous section about the most common setups, we only consider a very constrained set of remotes: 4 | 5 | * 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`. 6 | * The remote is named `origin` or `upstream`. 7 | 8 | The setups described here are characterized by *incomplete information*. 9 | This section exists mostly to explain feedback that the usethis package might give about a GitHub remote configuration. 10 | 11 | To identify any of the remote setups described in section \@ref(common-remote-setups), we need information from GitHub: 12 | 13 | * Whether you can push to a repo 14 | * Whether a repo is a fork 15 | * For a fork, what is its source repo 16 | 17 | Sometimes some of this information is publicly available, but some of it never is, such as repo permissions. 18 | This means that programmatic access to this information, i.e. requests to the GitHub API, generally requires authorization by an authenticated GitHub user. 19 | 20 | This means that client packages, like usethis, work best when you have configured a GitHub personal access token (PAT). 21 | See section \@ref(get-a-pat) for more details on why and how to do that. 22 | 23 | If you've configured a PAT and are being told your GitHub config is problematic, consider these other explanations: 24 | Are you offline? 25 | Is GitHub down? 26 | Have you lost permission to access the repo? 27 | Has your PAT expired? 28 | By default, they now expire after 30 days. 29 | 30 | ## Maybe "ours" or "theirs" 31 | 32 | When we detect just one GitHub remote, but we can't verify the info above, usethis describes the setup as "maybe_ours_or_theirs". 33 | 34 | ```{r maybe_ours_or_theirs} 35 | #| echo = FALSE, fig.align = "center", out.width = "60%", 36 | #| fig.alt = "Setup described as 'maybe_ours_or_theirs'" 37 | knitr::include_graphics("img/maybe_ours_or_theirs.jpeg") 38 | ``` 39 | 40 | Once a PAT is available, this setup can be identified as being ["ours" (belonging to you)](#ours-you), ["ours" (but belonging to someone else)](#ours-them), or ["theirs"](#theirs). 41 | 42 | ## Maybe fork 43 | 44 | When we detect two GitHub remotes, but we can't verify the info above, usethis describes the setup as "maybe_fork". 45 | 46 | ```{r maybe_fork} 47 | #| echo = FALSE, fig.align = "center", out.width = "60%", 48 | #| fig.alt = "Setup described as 'maybe_fork'" 49 | knitr::include_graphics("img/maybe_fork.jpeg") 50 | ``` 51 | 52 | Once a PAT is available, this setup can be identified as being a well-configured [fork](#fork-them) or a [fork with incomplete setup](#fork_upstream_is_not_origin_parent) (or possibly something more weird). 53 | 54 | ## How to fix 55 | 56 | These setups aren't necessarily broken, but usethis needs more information to operate. 57 | 58 | To "fix" this, set up a GitHub personal access token. 59 | See section \@ref(get-a-pat) for more details on why and how to do that. 60 | -------------------------------------------------------------------------------- /remote-setups-intro.Rmd: -------------------------------------------------------------------------------- 1 | # (PART) Remote setups {-} 2 | 3 | # Git remote setups {#remote-scenarios-intro .unnumbered} 4 | 5 | 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. 6 | 7 | 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. 8 | 9 | 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). 10 | -------------------------------------------------------------------------------- /render-r-script-demo.md: -------------------------------------------------------------------------------- 1 | R scripts can be rendered! 2 | ================ 3 | jeremyallen 4 | 2023-10-14 5 | 6 | Here’s some prose in a very special comment. Let’s summarize the 7 | built-in dataset `VADeaths`. 8 | 9 | ``` r 10 | # here is a regular code comment, that will remain as such 11 | summary(VADeaths) 12 | ``` 13 | 14 | ## Rural Male Rural Female Urban Male Urban Female 15 | ## Min. :11.70 Min. : 8.70 Min. :15.40 Min. : 8.40 16 | ## 1st Qu.:18.10 1st Qu.:11.70 1st Qu.:24.30 1st Qu.:13.60 17 | ## Median :26.90 Median :20.30 Median :37.00 Median :19.30 18 | ## Mean :32.74 Mean :25.18 Mean :40.48 Mean :25.28 19 | ## 3rd Qu.:41.00 3rd Qu.:30.90 3rd Qu.:54.60 3rd Qu.:35.10 20 | ## Max. :66.00 Max. :54.30 Max. :71.10 Max. :50.00 21 | 22 | Here’s some more prose. I can use usual markdown syntax to make things 23 | **bold** or *italics*. Let’s use an example from the `dotchart()` help 24 | to make a Cleveland dot plot from the `VADeaths` data. I even bother to 25 | name this chunk, so the resulting PNG has a decent name. 26 | 27 | ``` r 28 | dotchart(VADeaths, main = "Death Rates in Virginia - 1940") 29 | ``` 30 | 31 | ![](render-r-script-demo_files/figure-gfm/dotchart-1.png) 32 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | p.caption { 2 | color: #777; 3 | margin-top: 10px; 4 | } 5 | p code { 6 | white-space: inherit; 7 | } 8 | pre { 9 | word-break: normal; 10 | word-wrap: normal; 11 | } 12 | pre code { 13 | white-space: inherit; 14 | } 15 | -------------------------------------------------------------------------------- /toc.css: -------------------------------------------------------------------------------- 1 | #TOC ul, 2 | #TOC li, 3 | #TOC span, 4 | #TOC a { 5 | margin: 0; 6 | padding: 0; 7 | position: relative; 8 | } 9 | #TOC { 10 | line-height: 1; 11 | border-radius: 5px 5px 0 0; 12 | background: #141414; 13 | background: linear-gradient(to bottom, #333333 0%, #141414 100%); 14 | border-bottom: 2px solid #0fa1e0; 15 | width: auto; 16 | } 17 | #TOC:after, 18 | #TOC ul:after { 19 | content: ''; 20 | display: block; 21 | clear: both; 22 | } 23 | #TOC a { 24 | background: #141414; 25 | background: linear-gradient(to bottom, #333333 0%, #141414 100%); 26 | color: #ffffff; 27 | display: block; 28 | padding: 19px 20px; 29 | text-decoration: none; 30 | text-shadow: none; 31 | } 32 | #TOC ul { 33 | list-style: none; 34 | } 35 | #TOC > ul > li { 36 | display: inline-block; 37 | float: left; 38 | margin: 0; 39 | } 40 | #TOC > ul > li > a { 41 | color: #ffffff; 42 | } 43 | #TOC > ul > li:hover:after { 44 | content: ''; 45 | display: block; 46 | width: 0; 47 | height: 0; 48 | position: absolute; 49 | left: 50%; 50 | bottom: 0; 51 | border-left: 10px solid transparent; 52 | border-right: 10px solid transparent; 53 | border-bottom: 10px solid #0fa1e0; 54 | margin-left: -10px; 55 | } 56 | #TOC > ul > li:first-child > a { 57 | border-radius: 5px 0 0 0; 58 | } 59 | #TOC.align-right > ul > li:first-child > a, 60 | #TOC.align-center > ul > li:first-child > a { 61 | border-radius: 0; 62 | } 63 | #TOC.align-right > ul > li:last-child > a { 64 | border-radius: 0 5px 0 0; 65 | } 66 | #TOC > ul > li.active > a, 67 | #TOC > ul > li:hover > a { 68 | color: #ffffff; 69 | box-shadow: inset 0 0 3px #000000; 70 | background: #070707; 71 | background: linear-gradient(to bottom, #262626 0%, #070707 100%); 72 | } 73 | #TOC .has-sub { 74 | z-index: 1; 75 | } 76 | #TOC .has-sub:hover > ul { 77 | display: block; 78 | } 79 | #TOC .has-sub ul { 80 | display: none; 81 | position: absolute; 82 | width: 200px; 83 | top: 100%; 84 | left: 0; 85 | } 86 | #TOC .has-sub ul li a { 87 | background: #0fa1e0; 88 | border-bottom: 1px dotted #31b7f1; 89 | filter: none; 90 | display: block; 91 | line-height: 120%; 92 | padding: 10px; 93 | color: #ffffff; 94 | } 95 | #TOC .has-sub ul li:hover a { 96 | background: #0c7fb0; 97 | } 98 | #TOC ul ul li:hover > a { 99 | color: #ffffff; 100 | } 101 | #TOC .has-sub .has-sub:hover > ul { 102 | display: block; 103 | } 104 | #TOC .has-sub .has-sub ul { 105 | display: none; 106 | position: absolute; 107 | left: 100%; 108 | top: 0; 109 | } 110 | #TOC .has-sub .has-sub ul li a { 111 | background: #0c7fb0; 112 | border-bottom: 1px dotted #31b7f1; 113 | } 114 | #TOC .has-sub .has-sub ul li a:hover { 115 | background: #0a6d98; 116 | } 117 | #TOC ul ul li.last > a, 118 | #TOC ul ul li:last-child > a, 119 | #TOC ul ul ul li.last > a, 120 | #TOC ul ul ul li:last-child > a, 121 | #TOC .has-sub ul li:last-child > a, 122 | #TOC .has-sub ul li.last > a { 123 | border-bottom: 0; 124 | } 125 | #TOC ul { 126 | font-size: 1.2rem; 127 | } 128 | -------------------------------------------------------------------------------- /usage-existing-project-github-first.Rmd: -------------------------------------------------------------------------------- 1 | # Existing project, GitHub first {#existing-github-first} 2 | 3 | This is a novice-friendly workflow for bringing an existing R project into the RStudio and Git/GitHub universe. 4 | 5 | We do this in a slightly goofy way, in order to avoid using Git at the command line. 6 | You won't want to work this way forever, but it's perfectly fine as you're getting started! 7 | At first, the main goal is to accumulate some experience and momentum. 8 | There is nothing goofy about the GitHub repo that this creates, it is completely standard. 9 | Transition to a more elegant process when you're ready. 10 | 11 | We assume you've got your existing R project isolated in a directory on your computer. 12 | If that's not already true, make it so. 13 | Create a directory and marshal all the existing data and R scripts there. 14 | It doesn't really matter where you do this, but note where the project currently lives. 15 | 16 | ## Make a repo on GitHub 17 | 18 | ```{r echo = FALSE, results = "asis"} 19 | dat <- list( 20 | repository_name_text = glue::glue(" 21 | `myrepo` or a similarly short name for this existing project. Approach \\ 22 | this similar to a variable name, in code: descriptive but brief, no \\ 23 | whitespace. Letters, digits, `-`, `.`, or `_` are allowed."), 24 | description_text = glue::glue(" 25 | \"Analysis of the stuff\" or any short description of the project. Write \\ 26 | this for humans."), 27 | initialize_text = "Initialize this repository with: Add a README file." 28 | ) 29 | insert <- glue::glue_data( 30 | dat, 31 | readr::read_file("child-create-a-github-repo.Rmd"), 32 | .open = "<<<", .close = ">>>" 33 | ) 34 | res <- knitr::knit_child(text = insert, quiet = TRUE) 35 | cat(res, sep = '\n') 36 | ``` 37 | 38 | ## New RStudio Project via git clone {#git-clone-usethis-rstudio} 39 | 40 | ```{r echo = FALSE, results = "asis"} 41 | insert <- readr::read_file("child-clone-a-github-repo.Rmd") 42 | res <- knitr::knit_child(text = insert, quiet = TRUE) 43 | cat(res, sep = '\n') 44 | ``` 45 | 46 | ## Bring your existing project over 47 | 48 | Using your favorite method of moving or copying files, copy the files that constitute your existing project into the directory for this new project. 49 | 50 | In RStudio, consult the Git pane and the file browser. 51 | 52 | * Are you seeing all the files? They should be here if your move/copy was successful. 53 | * Are they showing up in the Git pane with questions marks? They should be appearing as new untracked files. 54 | 55 | ## Stage and commit 56 | 57 | Commit your files to this repo. How? 58 | 59 | * Click the "Git" tab in upper right pane 60 | * Check the "Staged" box for all files that you want to commit. 61 | - Default: stage it. 62 | - When to reconsider: this will all go to GitHub. Consider if that is 63 | appropriate for each file. **You can absolutely keep a file locally, 64 | without committing it to the Git repo and sending to GitHub**. Just let it 65 | sit there in your Git pane, without being staged. No harm will be done. If 66 | this is a long-term situation, list the file in `.gitignore`. 67 | * If you're not already in the Git pop-up, click "Commit" 68 | * Type a message in "Commit message", such as "Init project XYZ". 69 | * Click "Commit" 70 | 71 | ## Push your local changes to GitHub 72 | 73 | Click the green "Push" button to send your local changes to GitHub. 74 | RStudio will display something like: 75 | 76 | ```console 77 | >>> /usr/bin/git push origin HEAD:refs/heads/main 78 | To https://github.com/jennybc/myrepo.git 79 | 3a2171f..6d58539 HEAD -> main 80 | ``` 81 | 82 | ## Confirm the local change propagated to the GitHub remote 83 | 84 | Go back to the browser. 85 | I assume we're still viewing your new GitHub repo. 86 | 87 | Refresh. 88 | 89 | You should see all the project files you committed there. 90 | 91 | If you click on "commits," you should see one with the message you used, e.g. "Init project XYZ". 92 | 93 | ## The end 94 | 95 | ```{r echo = FALSE, results = "asis"} 96 | cat(readLines("child-the-end-of-repo-setup.Rmd"), sep = '\n') 97 | ``` 98 | -------------------------------------------------------------------------------- /usage-existing-project-github-last.Rmd: -------------------------------------------------------------------------------- 1 | # Existing project, GitHub last {#existing-github-last} 2 | 3 | This an explicit workflow for connecting an existing local R project to GitHub, when for some reason you cannot or don't want to do a "GitHub first" workflow (see chapters \@ref(new-github-first) and \@ref(existing-github-first)). 4 | 5 | When does this come up? 6 | Example: it's an existing project that is already a Git repo with a history you care about. 7 | Then you have to do this properly. 8 | 9 | This may be less desirable for a novice because there are more opportunities to get confused and make a mistake. 10 | But this workflow is not that hard, even with command line Git, and is even easier if you use conveniences from the [usethis](https://cran.r-project.org/package=usethis) package or the RStudio IDE. 11 | All of these are covered below. 12 | 13 | ## Prepare the local project 14 | 15 | We assume you've got your existing R project isolated in a directory on your computer. 16 | If that's not already true, make it so. 17 | Create a directory and marshal all the existing data and R scripts there. 18 | It doesn't really matter where you do this, but note where the project currently lives. 19 | 20 | I encourage you to make this project into an RStudio project, although it is not absolutely required. 21 | If you opt-out of this, the instructions using command line Git or usethis will still work for you, outside of RStudio. 22 | 23 | ### Make or verify an RStudio Project 24 | 25 | If the project is not already an RStudio Project, make it so: 26 | 27 | * Within RStudio you can do: *File > New Project > Existing Directory* and, if you wish, "Open in new session". 28 | * Alternatively, from R, call `usethis::create_project("path/to/your/project")`, substituting the path to your existing project directory. 29 | 30 | If your project is already an RStudio Project, launch it. 31 | 32 | ### Make or verify a Git repo 33 | 34 | You should be in RStudio now, in your project. 35 | 36 | Is it already a Git repository? 37 | The presence of the Git pane should tip you off. 38 | If yes, you're done. 39 | 40 | If not, you have several options: 41 | 42 | * In the R Console, call `usethis::use_git()`. 43 | * In RStudio, go to *Tools > Project Options ... > Git/SVN*. Under "Version control system", select "Git". Confirm New Git Repository? Yes! 44 | * In the shell, with working directory set to the project's directory, do `git init`. 45 | 46 | If you used usethis or RStudio to initialize the Git repo, the Project should re-launch in RStudio. 47 | Do that yourself if you did `git init`. 48 | RStudio should now have a Git pane. 49 | 50 | ## Stage and commit 51 | 52 | If your local project was already a Git repo and was up-to-date, move on. Otherwise, you probably need to stage and commit. 53 | 54 | * Click the "Git" tab in upper right pane 55 | * Check "Staged" box for all files you want to commit. 56 | - Default: stage everything 57 | - When to do otherwise: this will all go to GitHub. So consider if that is 58 | appropriate for each file. **You can absolutely keep a file locally, 59 | without committing it to the Git repo and sending to GitHub**. Just let it 60 | sit there in your Git pane, without being staged. No harm will be done. If 61 | this is a long-term situation, list the file in `.gitignore`. 62 | * If you're not already in the Git pop-up, click "Commit" 63 | * Type a message in "Commit message". 64 | * Click "Commit" 65 | 66 | ## Create and connect a GitHub repo 67 | 68 | We'll show a few methods for creating a new GitHub repo and connecting it to your local repo. 69 | Pick one. 70 | 71 | ### Create and connect a GitHub repo with usethis 72 | 73 | To use usethis for this task, you must have configured a personal access token (PAT). 74 | This will already by configured for anyone using HTTPS as their protocol, because they are already using the PAT to authenticate for other Git operations. 75 | But if you are an SSH person, you will need to configure a PAT, which is explained in chapter \@ref(https-pat). 76 | It is fine to have both a PAT and SSH keys. 77 | 78 | In your project, in the R Console, call: 79 | 80 | ```{r eval = FALSE} 81 | usethis::use_github() 82 | #> ✓ Creating GitHub repository 'jennybc/myrepo' 83 | #> ✓ Setting remote 'origin' to 'https://github.com/jennybc/myrepo.git' 84 | #> ✓ Pushing 'main' branch to GitHub and setting 'origin/main' as upstream branch 85 | #> ✓ Opening URL 'https://github.com/jennybc/myrepo' 86 | ``` 87 | 88 | ```{r} 89 | #| echo = FALSE, fig.align = "center", out.width = "60%", 90 | #| fig.alt = "usethis::use_github() connects a local repo to a new GitHub repo." 91 | knitr::include_graphics("img/use_github.jpeg") 92 | ``` 93 | 94 | `usethis::use_github()` does the following: 95 | 96 | * Creates a new repo on GitHub. 97 | * Configures that new repo as the `origin` remote for the local repo. 98 | * Sets up your local default branch (e.g. `main`) to track same on `origin` and 99 | does an initial push. 100 | * Opens the new repo in your browser. 101 | 102 | ### Create and connect a GitHub repo without usethis 103 | 104 | First, you need to create a new repo on GitHub. 105 | 106 | ```{r echo = FALSE, results = "asis"} 107 | dat <- list( 108 | repository_name_text = glue::glue(" 109 | Ideally this will be the name of your local project's directory (and \\ 110 | RStudio Project). Why confuse yourself? But it must be a valid \\ 111 | GitHub repo name, which means only letters, digits, `-`, `.`, or `_` are \\ 112 | allowed. For future projects, think about this in advance, i.e. make \\ 113 | sure each project's local name is also a valid GitHub repo name."), 114 | description_text = glue::glue(" 115 | \"Analysis of the stuff\" or any short description of the project. Write \\ 116 | this for humans."), 117 | initialize_text = "**DO NOT initialize this repository with anything**." 118 | ) 119 | insert <- glue::glue_data( 120 | dat, 121 | readr::read_file("child-create-a-github-repo.Rmd"), 122 | .open = "<<<", .close = ">>>" 123 | ) 124 | res <- knitr::knit_child(text = insert, quiet = TRUE) 125 | cat(res, sep = '\n') 126 | ``` 127 | 128 | #### Connect local repo to GitHub repo with RStudio 129 | 130 | Click on the "two purple boxes and a white square" in the Git pane. 131 | Click "Add remote". 132 | Paste the GitHub repo's URL here and pick a remote name, almost certainly `origin`. 133 | Now "Add". 134 | 135 | We should be back in the "New Branch" dialog (if not, click on the "two purple boxes and a white square" in the Git pane again). 136 | I assume you're on the `main` branch and want it to track `main` on GitHub (or whatever default branch you are using). 137 | Enter `main` as the branch name and make sure "Sync branch with remote" is checked. 138 | Click "Create" (yes, even though the branch already exists). 139 | In the next dialog, choose "overwrite". 140 | 141 | #### Connect local repo to GitHub repo with the command line 142 | 143 | In a shell, do this, substituting your URL: 144 | 145 | ```console 146 | git remote add origin https://github.com/jennybc/myrepo.git 147 | ``` 148 | 149 | Push and cement the tracking relationship between your local `main` branch and `main` on GitHub (or whatever your default branch is named): 150 | 151 | ```console 152 | git push --set-upstream origin main 153 | ``` 154 | 155 | ## Confirm the local files propagated to the GitHub remote 156 | 157 | Go back to the browser. 158 | I assume we're still viewing your new GitHub repo. 159 | 160 | Refresh. 161 | 162 | You should see all the project files you committed there. 163 | 164 | If this project already had a Git history, it should be reflected on GitHub. 165 | 166 | ## The end 167 | 168 | ```{r echo = FALSE, results = "asis"} 169 | cat(readLines("child-the-end-of-repo-setup.Rmd"), sep = '\n') 170 | ``` 171 | -------------------------------------------------------------------------------- /usage-intro.Rmd: -------------------------------------------------------------------------------- 1 | # (PART) Early GitHub Wins {-} 2 | 3 | # Get started with GitHub {#usage-intro .unnumbered} 4 | 5 | Now that we've verified your Git/GitHub/RStudio setup, we can demo the workflows you'll use to get your work onto GitHub: 6 | 7 | * [New project, GitHub first] is the easiest way to get a working project. 8 | * [Existing project, GitHub first] is a deeply pragmatic way to get pre-existing work onto GitHub. 9 | * [Existing project, GitHub last] is the more proper way to connect existing local work to a remote on GitHub, especially if there's already a Git history. 10 | 11 | This part concludes with two R-specific workflows that show off how well [R Markdown (the format)](https://rmarkdown.rstudio.com) and [rmarkdown (the package)](https://cran.r-project.org/package=rmarkdown) work with GitHub: 12 | 13 | * [Test drive R Markdown] 14 | * [Render an R script] 15 | -------------------------------------------------------------------------------- /usage-new-project-github-first.Rmd: -------------------------------------------------------------------------------- 1 | # New project, GitHub first {#new-github-first} 2 | 3 | We create a new Project, with the preferred "GitHub first, then RStudio" sequence. 4 | Why do we prefer this? 5 | Because this method of copying the Project from GitHub to your computer also sets up the local Git repository for immediate pulling and pushing. 6 | Under the hood, we are doing `git clone`. 7 | 8 | You've actually done this before during set up (chapter \@ref(rstudio-git-github)). 9 | We're doing it again, *with feeling*. 10 | 11 | The workflow is pretty similar for other repository managers like GitLab or Bitbucket. 12 | We will specify below when you may need to do something differently. 13 | 14 | ## Make a repo on GitHub 15 | 16 | ```{r echo = FALSE, results = "asis"} 17 | dat <- list( 18 | repository_name_text = glue::glue(" 19 | `myrepo` or whatever you wish to name your new project. Approach this \\ 20 | similar to a variable name, in code: descriptive but brief, no \\ 21 | whitespace. Letters, digits, `-`, `.`, or `_` are allowed."), 22 | description_text = glue::glue(" 23 | \"Analysis of the stuff\" or any short description of the project. Write \\ 24 | this for humans."), 25 | initialize_text = "Initialize this repository with: Add a README file." 26 | ) 27 | insert <- glue::glue_data( 28 | dat, 29 | readr::read_file("child-create-a-github-repo.Rmd"), 30 | .open = "<<<", .close = ">>>" 31 | ) 32 | res <- knitr::knit_child(text = insert, quiet = TRUE) 33 | cat(res, sep = '\n') 34 | ``` 35 | 36 | ### GitLab 37 | 38 | Log in at . 39 | Click on the "+" button in the top-right corner, and then on "New project". 40 | 41 | - Project name: `myrepo` (or whatever you wish) 42 | - Public 43 | - YES Initialize repository with a README 44 | 45 | Click the big green button "Create project." 46 | 47 | Copy the HTTPS or SSH clone URL to your clipboard via the blue "Clone" button. 48 | 49 | ### Bitbucket 50 | 51 | Log in at . 52 | On the left-side pane, click on the "+" button, and then on "Repository" under "Create". 53 | 54 | - Repository name: `myrepo` (or whatever you wish) 55 | - Access level: Uncheck to make the repository public. 56 | - Include a README?: Select either "Yes, with a tutorial (for beginners)" or "Yes, with a template" 57 | - Version control system: Git 58 | 59 | Click the big blue button "Create repository." 60 | 61 | Copy the HTTPS or SSH clone URL that appears when you click on the blue "Clone" button. 62 | Make sure you remove the `git clone ...` that shows up at the beginning. 63 | 64 | ## New RStudio Project via git clone {#new-rstudio-project-via-git} 65 | 66 | ```{r echo = FALSE, results = "asis"} 67 | insert <- readr::read_file("child-clone-a-github-repo.Rmd") 68 | res <- knitr::knit_child(text = insert, quiet = TRUE) 69 | cat(res, sep = '\n') 70 | ``` 71 | 72 | ### Have a look around 73 | 74 | Regardless of whether you used usethis or RStudio, you should now be working in the new Git repo. 75 | The implicit `git clone` should download the `README.md` file that we created on GitHub in the previous step. 76 | Look in RStudio's file browser pane for the `README.md` file. 77 | 78 | There's a big advantage to the "GitHub first, then RStudio" workflow: the remote GitHub repo is configured as the `origin` remote for your local repo and your local `main` branch is now tracking the `main` on GitHub. 79 | This is a technical but important point about Git. 80 | The practical implication is that you are now set up to push and pull. 81 | No need to fanny around setting up Git remotes and tracking branches on the command line. 82 | 83 | We're about to confirm we are setup for pulling and pushing. 84 | 85 | ```{r github-pull-push, echo = FALSE, out.width = "60%", fig.cap = "Pull and push."} 86 | knitr::include_graphics("img/github-pull-push.jpeg") 87 | ``` 88 | 89 | 90 | ### Optional: peek under the hood 91 | 92 | Completely optional activity: use command line Git to see what we're talking about above, i.e. the remote and tracking branch setup. 93 | 94 | `git remote -v` or `git remote --verbose` shows the remotes you have setup. 95 | Here's how that looks for someone using HTTPS with GitHub and calling it `origin`: 96 | 97 | ```console 98 | ~/tmp/myrepo % git remote -v 99 | origin https://github.com/jennybc/myrepo.git (fetch) 100 | origin https://github.com/jennybc/myrepo.git (push) 101 | ``` 102 | 103 | `git branch -vv` prints info about the current branch (`-vv` for "very verbose", I guess). 104 | In particular, we can see that local `main` is tracking the `main` branch on `origin`, a.k.a. `origin/main`. 105 | 106 | ```console 107 | ~/tmp/myrepo % git branch -vv 108 | * main 2899c91 [origin/main] A commit from my local computer 109 | ``` 110 | 111 | Finally, `git remote show origin` gives yet another view on useful remote and branch information: 112 | 113 | ```console 114 | ~/tmp/myrepo % git remote show origin 115 | * remote origin 116 | Fetch URL: https://github.com/jennybc/myrepo.git 117 | Push URL: https://github.com/jennybc/myrepo.git 118 | HEAD branch: main 119 | Remote branch: 120 | main tracked 121 | Local branch configured for 'git pull': 122 | main merges with remote main 123 | Local ref configured for 'git push': 124 | main pushes to main (up to date) 125 | ``` 126 | 127 | `git clone`, which RStudio did for us, sets all of this up automatically. 128 | This is why "GitHub first, then RStudio" is the preferred way to start projects early in your Git/GitHub life. 129 | 130 | ## Make local changes, save, commit 131 | 132 | **Do this every time you finish a valuable chunk of work, probably many times a day.** 133 | 134 | From RStudio, modify the `README.md` file, e.g., by adding the line "This is a line from RStudio". 135 | Save your changes. 136 | 137 | Commit these changes to your local repo. How? 138 | 139 | * Click the "Git" tab in upper right pane 140 | * Check "Staged" box for any files whose existence or modifications you want to commit. 141 | - To see more detail on what's changed in file since the last commit, click on "Diff" for a Git pop-up 142 | * If you're not already in the Git pop-up, click "Commit" 143 | * Type a message in "Commit message", such as "Commit from RStudio". 144 | * Click "Commit" 145 | 146 | ## Push your local changes to GitHub 147 | 148 | **Do this a few times a day, but possibly less often than you commit.** 149 | 150 | You have new work in your local Git repository, but the changes are not online yet. 151 | 152 | This will seem counterintuitive, but first let's stop and pull from GitHub. 153 | 154 | Why? 155 | Establish this habit for the future! 156 | If you make changes to the repo in the browser or from another machine or (one day) a collaborator has pushed, you will be happier if you pull those changes in before you attempt to push. 157 | 158 | Click the blue "Pull" button in the "Git" tab in RStudio. 159 | I doubt anything will happen, i.e. you'll get the message "Already up-to-date." 160 | This is just to establish a habit. 161 | 162 | Click the green "Push" button to send your local changes to GitHub. 163 | RStudio will report something along these lines: 164 | 165 | ```console 166 | >>> /usr/bin/git push origin HEAD:refs/heads/main 167 | To https://github.com/jennybc/myrepo.git 168 | 2899c91..b34cade HEAD -> main 169 | ``` 170 | 171 | ## Confirm the local change propagated to the GitHub remote 172 | 173 | Go back to the browser. 174 | I assume we're still viewing your new GitHub repo. 175 | 176 | Refresh. 177 | 178 | You should see the new "This is a line from RStudio" in the README. 179 | 180 | If you click on "commits," you should see one with the message "Commit from RStudio". 181 | 182 | ## Make a change on GitHub 183 | 184 | Click on README.md in the file listing on GitHub. 185 | 186 | In the upper right corner, click on the pencil for "Edit this file". 187 | 188 | Add a line to this file, such as "Line added from GitHub." 189 | 190 | Edit the commit message in "Commit changes" or accept the default. 191 | 192 | Click the big green button "Commit changes." 193 | 194 | ### GitLab 195 | 196 | Click on README.md in the file listing on GitLab. 197 | 198 | In the upper right corner, click on "Edit". 199 | 200 | Add a line to this file, such as "Line added from GitLab." 201 | 202 | Edit the commit message in "Commit changes" or accept the default. 203 | 204 | Click the big green button "Commit changes." 205 | 206 | ### Bitbucket 207 | 208 | Click on README.md in the file listing on Bitbucket. 209 | 210 | In the upper right corner, click on "Edit". 211 | 212 | Add a line to this file, such as "Line added from Bitbucket." 213 | 214 | Click on the blue "Commit" button. A pop-up will show up. Edit the commit message or accept the default. 215 | 216 | Click the blue "Commit" button. 217 | 218 | ## Pull from GitHub 219 | 220 | Back in RStudio locally ... 221 | 222 | Inspect your README.md. 223 | It should NOT have the line "Line added from GitHub". 224 | It should be as you left it. 225 | Verify that. 226 | 227 | Click the blue Pull button. 228 | 229 | Look at README.md again. 230 | You should now see the new line there. 231 | 232 | ## The end 233 | 234 | ```{r echo = FALSE, results = "asis"} 235 | cat(readLines("child-the-end-of-repo-setup.Rmd"), sep = '\n') 236 | ``` 237 | -------------------------------------------------------------------------------- /usage-r-script-and-github.Rmd: -------------------------------------------------------------------------------- 1 | # Render an R script {#r-test-drive} 2 | 3 | An under-appreciated fact is that much of what you can do with R Markdown, you can also do with an R script. 4 | 5 | If you're in analysis mode and want a report as a side effect, write an R script. 6 | If you're writing a report with a lot of R code in it, write `.Rmd`. 7 | In either case, render to markdown and/or HTML to communicate with other human beings. 8 | 9 | * In R markdown, prose is top-level and code is tucked into chunks. 10 | * In R scripts, code is top-level and prose is tucked into comments. 11 | You will use `#'` to request that certain comments appear as top-level prose 12 | in the rendered output. 13 | 14 | You will continue to specify things like the output format via YAML at the top of the file. 15 | This will need to be commented with `#'`. 16 | 17 | ## Morph R Markdown into a renderable R script 18 | 19 | Get yourself a working R Markdown file, such as the one you made in your [Rmd test drive](#rmd-test-drive). 20 | Or use the boilerplate `.Rmd` document RStudio makes with *File > New File > R Markdown ...*. 21 | 22 | Save the file as `foo.R`, as opposed to `foo.Rmd`. 23 | Yes, for a brief moment, you will have R Markdown saved as an R script, but that won't be true for long. 24 | 25 | Transform the R markdown to R: 26 | 27 | * Anything that's not R code? 28 | Like the YAML and the prose? 29 | Protect it with roxygen-style comments: start each line with `#'`. 30 | * Anything that is R code? 31 | Let it exist "as is" as top-level code. 32 | That means you'll need to change the syntax of R chunk headers like so: 33 | 34 | Before: ` ```{r setup, include = FALSE}` 35 | After: `#+ r setup, include = FALSE` 36 | 37 | Replace the leading backticks and opening curly brace with `#+`. 38 | Delete the trailing curly brace. 39 | Delete the 3 backticks that end each chunk. 40 | 41 | Render the R script through one of these methods: 42 | 43 | * Click on the "notebook" icon in RStudio to "Compile Report". 44 | * In RStudio, do *File > Knit Document*. 45 | * In R, do `rmarkdown::render("foo.R")`. 46 | 47 | You'll get a markdown and/or HTML report, just as with R Markdown. 48 | 49 | If you're having trouble making all the necessary changes and you're frustrated, see below for an example you can copy and paste. 50 | 51 | All the workflow tips from the [Rmd test drive](#rmd-test-drive) apply here: 52 | when you script an analysis, render it to markdown, commit the `.R`, the `.md`, any associated figures, and push to GitHub. 53 | Collaborators can see your code, but also browse around the results without having to download and execute the code. 54 | This makes the current state of your analysis accessible to someone who does not even run R or who wants to take a quick look at things from a cell phone or while on vacation. 55 | 56 | ## Write a render-ready R script 57 | 58 | Instead of morphing an R Markdown file, let's create a render-ready R script directly. 59 | 60 | Create a new R script and copy/paste this code into it. 61 | 62 | ```{r create-temp-dir, include = FALSE} 63 | va_home <- fs::dir_create(fs::file_temp(pattern = "va-example-")) 64 | ``` 65 | 66 | 67 | ```{r define-demo-code, include = FALSE} 68 | demo_code <- c( 69 | "#' Here's some prose in a very special comment. Let's summarize the built-in", 70 | "#' dataset `VADeaths`.", 71 | "# here is a regular code comment, that will remain as such", 72 | "summary(VADeaths)", 73 | "", 74 | "#' Here's some more prose. I can use usual markdown syntax to make things", 75 | "#' **bold** or *italics*. Let's use an example from the `dotchart()` help to", 76 | "#' make a Cleveland dot plot from the `VADeaths` data. I even bother to name", 77 | "#' this chunk, so the resulting PNG has a decent name.", 78 | "#+ dotchart", 79 | "dotchart(VADeaths, main = \"Death Rates in Virginia - 1940\")" 80 | ) 81 | writeLines(demo_code, fs::path(va_home, "render-r-script-demo.R")) 82 | ``` 83 | 84 | ```{r eval = FALSE, code = demo_code} 85 | ``` 86 | 87 | Render the R script through one of these methods: 88 | 89 | * Click on the "notebook" icon in RStudio to "Compile Report". 90 | * In RStudio, do *File > Knit Document*. 91 | * In R, do `rmarkdown::render("YOURSCRIPT.R")`. 92 | 93 | Revel in your attractive looking report with almost zero effort! 94 | Seriously, all you had to do was think about when to use special comments `#'` in order to promote that to nicely rendered text. 95 | 96 | Drawing on the workflow tips in [Rmd test drive](#rmd-test-drive), let's add some YAML frontmatter, properly commented with `#'`, and request `github_document` as the output format. 97 | Here's the whole script again: 98 | 99 | ```{r augment-demo-code, include = FALSE} 100 | demo_code <- c( 101 | "#' ---", 102 | "#' title: \"R scripts can be rendered!\"", 103 | "#' output: github_document", 104 | "#' ---", 105 | "#'", 106 | demo_code 107 | ) 108 | writeLines(demo_code, fs::path(va_home, "render-r-script-demo.R")) 109 | ``` 110 | 111 | ```{r eval = FALSE, code = demo_code} 112 | ``` 113 | 114 | Behind the scenes here we have used `rmarkdown::render()` to render this script and you can go [visit it on GitHub](https://github.com/jennybc/happy-git-with-r/blob/master/render-r-script-demo.md). 115 | 116 | ```{r render-demo-code} 117 | #| include = FALSE, error = TRUE, 118 | #| eval = !as.logical(Sys.getenv("CI", unset = "FALSE")) 119 | # render must happen elsewhere, otherwise bookdown yaml clobbers doc yaml 120 | # this is, in fact, why we're working below session temp 121 | withr::with_dir(va_home, rmarkdown::render("render-r-script-demo.R")) 122 | 123 | # copy files back into the book 124 | va_files <- fs::dir_ls(va_home, recursive = TRUE) 125 | va_files_rel <- fs::path_rel(va_files, va_home) 126 | 127 | md_file <- va_files[fs::path_ext(va_files) == "md"] 128 | fs::file_copy(md_file, fs::path_rel(md_file, va_home), overwrite = TRUE) 129 | 130 | fig_dir <- va_files[grepl("_files", fs::path_file(va_files))] 131 | fig_dir_rel <- fs::path_rel(fig_dir, va_home) 132 | if (fs::dir_exists(fig_dir_rel)) { 133 | fs::dir_delete(fig_dir_rel) 134 | } 135 | # TODO: figure out why this directory is deleted in the context of local 136 | # bookdown render 137 | fs::dir_copy(fig_dir, fig_dir_rel) 138 | 139 | fs::dir_delete(va_home) 140 | ``` 141 | -------------------------------------------------------------------------------- /workflows-explore-extend-pull-request.Rmd: -------------------------------------------------------------------------------- 1 | # Explore and extend a pull request {#pr-extend} 2 | 3 | Scenario: you maintain an R package on GitHub with pull requests (PRs) from external contributors e.g. Jane Doe, janedoe on GitHub. Sometimes you need to experiment with the PR in order to provide feedback or to decide whether or not to merge. Going further, sometimes you want to add a few commits and then merge. Or maybe there are just some merge conflicts that require your personal, local attention. Let's also assume that you want the original PR author to get credit for their commits, i.e. you want to preserve history and provenance, not just diffs. 4 | 5 | How do you checkout and possibly extend an external PR? 6 | 7 | ## Update from the future 8 | 9 | The lessons learned here eventually lead to the `pr_*()` family of functions in usethis. 10 | `pr_fetch()` and `pr_push()` are now my workhorses for exploring and extending PRs. 11 | You can read more about usethis's functions to help with pull requests in their very own article: [Pull request helpers](https://usethis.r-lib.org/articles/pr-functions.html). 12 | 13 | ## Terminology 14 | 15 | Vocabulary I use throughout. 16 | 17 | **fork branch** The name of the branch in the fork from which the PR was made. Best case scenario: informative name like `fix-fluffy-bunny`. Worst case scenario: PR is from `master`. 18 | 19 | **local PR branch** The name of the local branch you'll use to work with the PR. Best case scenario: can be same as fork branch. Worse case scenario: PR is from `master`, so you must make up a new name based on something about the PR, e.g. `pr-666` or `janedoe-master`. 20 | 21 | **PR parent** The SHA of the commit in the main repo that is the base for the PR. 22 | 23 | **PR remote** The SSH or HTTPS URL for the fork from which the PR was made. Or the nickname of the remote, if you've bothered to set that up. 24 | 25 | ## Official GitHub advice, Version 1 26 | 27 | Every PR on GitHub has a link to "command line instructions" on how to merge the PR locally via command line Git. On this journey, there is a point at which you can pause and explore the PR locally. 28 | 29 | Here are their steps with my vocabulary and some example commands: 30 | 31 | * Create and check out the local PR branch, anticipating its relationship to the fork branch. Template of the Git command, plus an example of how it looks under both naming scenarios: 32 | 33 | # Template of the Git command 34 | git checkout -b LOCAL_PR_BRANCH master 35 | # How it looks under both naming scenarios 36 | git checkout -b fix-fluffy-bunny master 37 | git checkout -b janedoe-master master 38 | 39 | * Pull from the fork branch of the PR remote: 40 | 41 | # Template of the Git command 42 | git pull REMOTE FORK_PR_BRANCH 43 | # How it looks under both naming scenarios 44 | git pull https://github.com/janedoe/yourpackage.git fix-fluffy-bunny 45 | git pull https://github.com/janedoe/yourpackage.git master 46 | 47 | * Satisfy yourself that all is well and you want to merge. 48 | * Checkout `master`: 49 | 50 | git checkout master 51 | 52 | * Merge the local PR branch into master with `--no-ff`, meaning "no fast forward merge". This ensures you get a true merge commit, with two parents. 53 | 54 | # Template of the Git command 55 | git merge --no-ff LOCAL_PR_BRANCH 56 | # How it looks under both naming scenarios 57 | git merge --no-ff fix-fluffy-bunny 58 | git merge --no-ff janedoe-master 59 | 60 | * Push `master` to GitHub. 61 | 62 | git push origin master 63 | 64 | What's not to like? The parent commit of the local PR branch will almost certainly not be the parent commit of the fork PR branch, where the external contributor did their work. This often means you get merge conflicts in `git pull`, which you'll have to deal with ASAP. The older the PR, the more likely this is and the hairier the conflicts will be. 65 | 66 | I would prefer to deal with the merge conflicts only *after* I've vetted the PR and to resolve the conflicts locally, not on GitHub. So I don't use this exact workflow. 67 | 68 | ## Official GitHub advice, Version 2 69 | 70 | GitHub has another set of instructions: [Checking out pull requests locally](https://help.github.com/articles/checking-out-pull-requests-locally/) 71 | 72 | It starts out by referring to the Version 1 instructions, but goes on to address an inactive pull request", defined as a PR "whose owner has either stopped responding, or, more likely, has deleted their fork". 73 | 74 | This workflow may NOT give the original PR author credit (next time it's easy to test this, I'll update with a definitive answer). I've never used it verbatim because I've never had this exact problem re: deleted fork. 75 | 76 | ## Official GitHub advice, Version 3 77 | 78 | GitHub has yet another set of instructions: [Committing changes to a pull request branch created from a fork](https://help.github.com/articles/committing-changes-to-a-pull-request-branch-created-from-a-fork/) 79 | 80 | The page linked above explains all the pre-conditions, but the short version is that a maintainer can probably push new commits to a PR, effectively pushing commits to a fork. Strange, but true! 81 | 82 | This set of instructions suggests that you clone the fork, checkout the branch from which the PR was made, make any commits you wish, and then push. Any new commits you make will appear in the PR. And then you could merge. 83 | 84 | My main takeaway: maintainer can push to the branch of a fork associated with a PR. 85 | 86 | ## A workflow I once used 87 | 88 | *The lessons learned here eventually lead to the `pr_*()` family of functions in usethis. 89 | `pr_fetch()` and `pr_push()` are now my workhorses for exploring and extending PRs. 90 | You can read more about usethis's functions to help with pull requests in their very own article: [Pull request helpers](https://usethis.r-lib.org/articles/pr-functions.html).* 91 | 92 | This combines ideas from the three above approaches, but with a few tweaks. I am sketching this up in R code, with the hope of putting this into a function and package at some point. This is a revision of an earlier approach, based on feedback from Jim Hester. 93 | 94 | Example of a PR from the `master` branch (suboptimal but often happens) from fictional GitHub user `abcde` on usethis. 95 | 96 | ```{r, eval = FALSE} 97 | library(git2r) 98 | 99 | ## add the pull requester's fork as a named remote 100 | remote_add(name = "abcde", url = "git@github.com:abcde/usethis.git") 101 | 102 | ## fetch 103 | fetch(name = "abcde") 104 | 105 | ## list remote branches and isolate the one I want 106 | b <- branches(flags = "remote") 107 | b <- b[["abcde/master"]] 108 | 109 | ## get the SHA of HEAD on this branch 110 | sha <- branch_target(b) 111 | 112 | ## create local branch 113 | branch_create(commit = lookup(sha = sha), name = "abcde-master") 114 | 115 | ## check it out 116 | checkout(object = ".", branch = "abcde-master") 117 | 118 | ## set upstream tracking branch 119 | branch_set_upstream(repository_head(), name = "abcde/master") 120 | 121 | ## confirm upstream tracking branch 122 | branch_get_upstream(repository_head()) 123 | 124 | ## make one or more commits here 125 | 126 | ## push to the branch in the fork and, therefore, into the PR 127 | push() 128 | ``` 129 | 130 | -------------------------------------------------------------------------------- /workflows-intro.Rmd: -------------------------------------------------------------------------------- 1 | # (PART) Daily Workflows {-} 2 | 3 | # Useful Git patterns for real life {#workflows-intro .unnumbered} 4 | 5 | *Much of this originates as live workshop materials; the unlinked workflows are planned but not yet converted to prose here.* 6 | 7 | Git patterns that come up frequently in real work: 8 | 9 | * Commit early and often. Push less often. [The Repeated Amend](#repeated-amend). 10 | * [Help, my push was rejected!](#push-rejected) 11 | * [Integrating remote and local work](#pull-tricky). Probably so you can push again. 12 | * Burn it all down. 13 | * Time travel: 14 | - ["I just need to see the past".](#time-travel-see-past) Browse and search on GitHub. 15 | - "I need to visit the past". Create a checkout a branch. 16 | - "I want to return to the past". `git revert`, `git reset` 17 | - "I had a great cookie last October". `git cherry pick`, `git checkout REF -- path` 18 | 19 | Play well with others: 20 | 21 | * [Fork and clone](#fork-and-clone). 22 | * [Get upstream changes for a fork](#upstream-changes). 23 | * Disposable fork. 24 | * [Make your repo rewarding to browse on GitHub](#workflows-browsability). 25 | * [Explore and extend a pull request](#pr-extend) 26 | -------------------------------------------------------------------------------- /workflows-push-rejected.Rmd: -------------------------------------------------------------------------------- 1 | # Dealing with push rejection {#push-rejected} 2 | 3 | Problem: You want to push changes to GitHub, but you are rejected like so: 4 | 5 | ``` bash 6 | $ git push 7 | To https://github.com/YOU/REPO.git 8 | ! [rejected] main -> main (fetch first) 9 | error: failed to push some refs to 'https://github.com/YOU/REPO.git' 10 | hint: Updates were rejected because the remote contains work that you do 11 | hint: not have locally. This is usually caused by another repository pushing 12 | hint: to the same ref. You may want to first integrate the remote changes 13 | hint: (e.g., 'git pull ...') before pushing again. 14 | hint: See the 'Note about fast-forwards' in 'git push --help' for details. 15 | ``` 16 | 17 | This means that your local Git history and that on the GitHub remote are not compatible, i.e. they have diverged. 18 | 19 | I suggest that you use `git status`, your [Git client](#git-client ), or visit your GitHub remote in the browser to get more information about the situation, i.e. to get a sense of this work that you do not have. 20 | 21 | In the abstract, this is the state on GitHub: 22 | 23 | ``` 24 | A -- B -- C (on GitHub) 25 | ``` 26 | 27 | And this is your local state: 28 | 29 | ``` 30 | A -- B -- D (what you have) 31 | ``` 32 | 33 | You can't cause some sort of merge to happen to the GitHub copy when you push. 34 | 35 | Instead, you've got to pull the commit `C` and somehow integrate it into your `D`-containing history. Then you will be able to push again. 36 | 37 | This is covered in the workflow [Pull, but you have local work](#pull-tricky). 38 | 39 | But before you behold the full horror of that, this is a great time to reflect on what we can learn from this situation. 40 | 41 | ## She who pushes first wins! 42 | 43 | You may have noticed that you -- the author of `D` -- are faffing around with Git more than the person who committed and pushed `C`, i.e. your collaborator. 44 | 45 | There is a lesson to be learned here! 46 | 47 | If you had pushed `D` first, you'd be relaxing and they'd be figuring out how to integrate `C` into their history in order to push. So push your work often. Don't go dark and work "offline" for long stretches of time. 48 | 49 | Obviously, you should push work to `main` because it's "ready" to share (or at least "ready enough"), not to avoid Git merges. 50 | 51 | There is a truly legitimate point here: It is better for the overall health of a project to be committing, pushing, and integrating more often, not less. This does not eliminate the need to integrate different lines of work, but it makes each integration smaller, less burdensome, and less prone to error. 52 | 53 | ## Stay in touch 54 | 55 | Another take away is this: the sooner you know about `C`, the better. Pull (or fetch) often. 56 | 57 | Let's think about your commit `D`. Maybe it was built up over a couple of days via the [Repeated Amend pattern](#repeated-amend). Maybe `C` was sitting there on GitHub the whole time or appeared very early in your process. 58 | 59 | Consider that it might be easier to integrate `C` into your work `D` sooner rather than later. Sometimes this is not true, but more often it is. 60 | 61 | In general, it pays off to be proactively aware of what others are doing (e.g. to pull or fetch often) than to always be in reactive mode, learning about your collaborator's work only when your push is rejected. 62 | 63 | ## Use branches 64 | 65 | Finally, your early experiences collaborating with others and yourself in `main` will give you a visceral understanding of why most Git users eventually start to use [branches](#git-branches). 66 | 67 | Branches afford explicit workflows for integrating different lines of work on your own terms. This is much nicer than trying to do a tricky merge or rebase in a frustrated panic, because you need to push your work to GitHub at the end of the day. 68 | 69 | -------------------------------------------------------------------------------- /workflows-repeated-amend.Rmd: -------------------------------------------------------------------------------- 1 | # The Repeated Amend {#repeated-amend} 2 | 3 | One of the principal joys of version control is the freedom to experiment without fear. 4 | If you make a mess of things, you can always go back to a happier version of your project. 5 | We describe several methods of such time travel in *link to come*. 6 | But you must have a good commit to fall back to! 7 | 8 | ## Rock climbing analogy 9 | 10 |
    11 |
    12 | Using a Git commit is like using anchors and other protection when climbing. If you're crossing a dangerous rock face you want to make sure you've used protection to catch you if you fall. Commits play a similar role: if you make a mistake, you can't fall past the previous commit. Coding without commits is like free-climbing: you can travel much faster in the short-term, but in the long-term the chances of catastrophic failure are high! Like rock climbing protection, you want to be judicious in your use of commits. Committing too frequently will slow your progress; use more commits when you're in uncertain or dangerous territory. Commits are also helpful to others, because they show your journey, not just the destination. 13 |
    14 |

    15 | R Packages, Hadley Wickham (@r-pkgs-book)

    16 |
    17 | 18 | Let's talk about this: 19 | 20 | > use more commits when you're in uncertain or dangerous territory 21 | 22 | When I'm doing something tricky, I often proceed towards my goal in small increments, checking that everything still works along the way. 23 | Yes it works? 24 | Make a commit. 25 | This is my new worst case scenario. 26 | Keep going. 27 | 28 | What's not to love? 29 | 30 | This can lead to an awful lot of tiny commits. 31 | This is absolutely fine and nothing to be ashamed of. 32 | But one day you may start to care about the utility and aesthetics of your Git history. 33 | 34 | The Repeated Amend is a pattern where, instead of cluttering your history with lots of tiny commits, you build up a "good" commit gradually, by amending. 35 | 36 | *Yes, there are other ways to do this, e.g. via squashing and interactive rebase, but I think amending is the best way to get started.* 37 | 38 | ## Workflow sketch 39 | 40 | ### Initial condition 41 | 42 | Start with your project in a functional state: 43 | 44 | * R package? Run your tests or `R CMD check`. 45 | * Data analysis? Re-run your script or re-render your `.Rmd` with the new chunk. 46 | * Website or book? Make sure the project still compiles. 47 | * You get the idea. 48 | 49 | Make sure your "working tree is clean" and you are synced up with your GitHub remote. `git status` should show something like: 50 | 51 | ```console 52 | ~/tmp/myrepo % git status 53 | On branch main 54 | Your branch is up to date with 'origin/main'. 55 | 56 | nothing to commit, working tree clean 57 | ``` 58 | 59 | ### Get to work 60 | 61 | Imagine we start at commit C, with previous commit B and, before that, A: 62 | 63 | ``` bash 64 | ... -- A -- B -- C 65 | ``` 66 | 67 | Make a small step towards your goal. 68 | Re-check that your project "works". 69 | 70 | Stage those changes with and make a commit with the message "WIP", meaning "work in progress". 71 | Do this in RStudio or in the shell (Appendix \@ref(shell)): 72 | 73 | ```console 74 | git add path/to/the/changed/file 75 | git commit -m "WIP" 76 | ``` 77 | 78 | The message can be anything, but "WIP" is a common convention. 79 | If you use it, whenever you return to a project where the most recent commit message is "WIP", you'll know that you were probably in the middle of something. 80 | If you push a "WIP" commit, on purpose or by mistake, it signals to other people that more commits might be coming. 81 | 82 | Your history now looks like this: 83 | 84 | ``` bash 85 | A -- B -- C -- WIP* 86 | ``` 87 | 88 | **Don't push!** 89 | The `*` above signifies a commit that exists only in your local repo, not (yet) on GitHub. 90 | If you called `git status`, you'd see something like "Your branch is ahead of 'origin/main' by 1 commit.", which is also displayed in RStudio's Git pane. 91 | 92 | Do a bit more work. 93 | Re-check that your project is still in a functional state. 94 | Stage and commit again, but this time **amend** your previous commit. 95 | RStudio offers a check box for "Amend previous commit" or in the shell: 96 | 97 | ```console 98 | git commit --amend --no-edit 99 | ``` 100 | 101 | The `--no-edit` part retains the current commit message of "WIP". 102 | 103 | **Don't push!** Your history now looks like this: 104 | 105 | ``` bash 106 | A -- B -- C -- WIP* 107 | ``` 108 | 109 | but the changes associated with the `WIP*` commit now represent your last two commits, i.e. all the accumulated changes since state C. 110 | 111 | Keep going like this. 112 | 113 | Let's say you've finally achieved your goal. One last time, check that your project is functional and in a state you're willing to share with others. 114 | 115 | Commit, amending again, but with a real commit message this time. 116 | Think of this as commit D. 117 | Push. 118 | Do this in RStudio or the shell: 119 | 120 | ```console 121 | git commit --amend -m "Implement awesome feature; closes #43" 122 | git push 123 | ``` 124 | 125 | Your history -- and that on GitHub -- look like this: 126 | 127 | ``` bash 128 | A -- B -- C -- D 129 | ``` 130 | 131 | As far as the world knows, you implemented the feature in one fell swoop. 132 | But you got to work on the task incrementally, with the peace of mind that you could never truly break things. 133 | 134 | ## What if I need to fall back? 135 | 136 | Imagine you're in the middle of a Repeated Amend workflow: 137 | 138 | ```console 139 | A -- B -- C -- WIP* 140 | ``` 141 | 142 | and you make some changes that break your project, e.g. tests start failing. 143 | These bad changes are not yet committed, but they are saved. 144 | You want to fall back to the last good state, represented by `WIP*`. 145 | 146 | In Git lingo, you want to do a **hard reset** to the `WIP*` state. 147 | Your local files will be forcibly reset to their state as of the `WIP*` commit. 148 | With the command line: 149 | 150 | ```console 151 | git reset --hard 152 | ``` 153 | 154 | which is implicitly the same as 155 | 156 | ```console 157 | git reset --hard HEAD 158 | ``` 159 | 160 | which says: "reset my files to their state at the most recent commit". 161 | 162 | This is also possible in RStudio. 163 | In fact, the RStudio way makes it easier to selectively reset only specific files or only certain changes. 164 | Click on "Diff" or "Commit". 165 | Select a file with changes you do not want. 166 | Use "Discard All" to discard all changes in that file. 167 | Use "Discard chunk" to discard specific changes in a file. 168 | Repeat this procedure for each affected file until you are back to an acceptable state. 169 | Carry on. 170 | 171 | If you committed a bad state, go to *link to come* for more reset scenarios. 172 | 173 | ## Why don't we push intermediate progress? 174 | 175 | Amending a commit is an example of what's called "rewriting Git history". 176 | 177 | Rewriting history that has already been pushed to GitHub -- and therefore potentially pulled by someone else -- is a controversial practice. 178 | Like most controversial practices, lots of people still indulge in it, as do I. 179 | 180 | But there is the very real possibility that you create headaches for yourself and others, so in Happy Git we must recommend that you abstain. 181 | Once you've pushed something, consider it written in stone and move on. 182 | 183 | ## Um, what if I did push? 184 | 185 | I told you not to! 186 | 187 | But OK here we are. 188 | 189 | Let's imagine you pushed this state to GitHub by mistake: 190 | 191 | ```console 192 | A -- B -- C -- WIP (85bf30a) 193 | ``` 194 | 195 | and proceeded to `git commit --amend` again locally, leading to this state: 196 | 197 | ```console 198 | A -- B -- C -- WIP* (6e884e6) 199 | ``` 200 | 201 | I'm deliberately showing two histories that sort of look the same, in terms of commit messages. 202 | But the last SHA reveals they are actually different. 203 | 204 | You are in a pickle now, as you can't do a simple push or pull. 205 | A push will be rejected and a pull will probably lead to a merge that you don't want. 206 | 207 | You have two choices: 208 | 209 | * If you have collaborators who may have pulled the repo at commit 210 | `WIP (85bf30a)`, you have to regard that particular history as being written 211 | in stone now. 212 | If there is any very precious work that only exists locally, such as a 213 | specific file, save a copy of that to a new file path, temporarily. 214 | Hard reset your local repo to `C` (`git reset --hard HEAD^`) and pull from 215 | GitHub. 216 | GitHub and local history now show this: 217 | ```console 218 | A -- B -- C -- WIP (85bf30a) 219 | ``` 220 | If you saved some precious work to a temporary file path, bring it back into 221 | the repo now; save, stage, commit, and push. 222 | GitHub and local history now show this: 223 | ```console 224 | A -- B -- C -- WIP (85bf30a) -- E 225 | ``` 226 | * If you have no collaborators or you have reason to believe they have not 227 | pulled, you can rewrite history, even on GitHub. 228 | You might as well make sure your local commit has a real, non-"WIP" message 229 | at this point. 230 | Force push your history to GitHub (`git push --force`). 231 | GitHub and local history now show this: 232 | ```console 233 | A -- B -- C -- D 234 | ``` 235 | 236 | In both cases, you've made the changes you want and your local repo and the 237 | GitHub remote are synced up again. 238 | The history is nicer in the second case, but that's a secondary issue. 239 | 240 | *There are many different ways to rewrite history and rescue some of these situations, but we find the approaches described above to be very approachable.* 241 | -------------------------------------------------------------------------------- /workflows-see-the-past.Rmd: -------------------------------------------------------------------------------- 1 | # Time travel: See the past {#time-travel-see-past} 2 | 3 | 4 | 5 | Sometimes you just need to **see** various files in your project as they were at some significant moment in the past. Examples: 6 | 7 | * "I liked the color scheme of this plot better in last week's draft". "What's up with that new funky outlier in figure 2?" 8 | - Here you'll want to visit scripts and source data as they were the last time you generated visualizations to share with this colleague. 9 | * "The build has been failing on Windows for two weeks." 10 | - Here you'll want to inspect package source at the "last known good" version and scrutinize subsequent commits. 11 | 12 | All projects move through various states that you regard as "good" vs. "bad" or something in between. It can be useful to explore the past, when trying to get into a "good" state. 13 | 14 | ## Hyperlinks are awesome! 15 | 16 | This is where GitHub (and GitLab or BitBucket) really shine. The ability to quickly explore different commits/states, switch between branches, inspect individual files, and see the discussion in linked issues is incredibly powerful. 17 | 18 | Yes, technically, you can visit past states of your project using Git commands locally. But it is significantly more cumbersome. You generally have to checkout these previous states, which raises the prospect of getting comfortable in the "detached head" state and unintentionally making new commits on the wrong branch or on no branch at all. 19 | 20 | GitHub's hyperlink-rich presentation of your repo and its history is one of the top reasons to sync local work to a copy on GitHub, even if you keep it private. It can be much easier to hone in on a state or change of interest by clicking around or using GitHub's search features. Also, because it is so clearly a remote and read-only action, there is no possibility of goofing up local state or committing new work to the wrong branch. 21 | 22 | ## Browse commit history and specific commits 23 | 24 | From your repo's landing page, access commit history by clicking on "xyz commits". This is like using `git log` locally, but much more rewarding. If you have a good [local Git client](#git-client), it probably also provides a graphical overview of history. 25 | 26 | ```{r github-link-to-commit-listing, echo = FALSE, out.width = "100%", fig.cap = "Link to commit listing on GitHub."} 27 | knitr::include_graphics("img/screenshots/github-link-to-commits.png") 28 | ``` 29 | 30 | Once you're viewing the history, notice three ways to access more info for each commit: 31 | 32 | 1. The clipboard icon copies the SHA-1 of the commit. This can be handy if you need to refer to this commit elsewhere, e.g. in an issue thread or a commit message or in a Git command you're forming for local execution. 33 | 1. Click on the abbreviated SHA-1 itself in order to the view the diff associated with the commit. 34 | 1. Click on the double angle brackets `<>` to browse the state of the entire repo at that point in history. 35 | 36 | ```{r github-commit-listing, echo = FALSE, out.width = "100%", fig.cap = "Example of a commit listing on GitHub."} 37 | knitr::include_graphics("img/screenshots/github-commit-listing.png") 38 | ``` 39 | 40 | Back out of any drilled down view by clicking on `YOU/REPO` to return to your repo's landing page. This brings you back to the present state and top-level of your repo. 41 | 42 | ### Use hyperlinks yourself! 43 | 44 | Once you've identified a relevant commit, diff, or file state, you can copy the current URL from your browser and use it to enhance online discussion elsewhere, i.e. to bring other people to this exact view of the repo. The hyperlink-iness of repos hosted on GitHub can make online discussion of a project much more precise and efficient. 45 | 46 | ## File driven inquiries 47 | 48 | What if you're interested in how a specific file came to be the way it is? First navigate to the file, then notice "Blame" and "History" in the upper right. 49 | 50 | ```{r github-specific-file, echo = FALSE, out.width = "100%", fig.cap = "Visiting a specific file on GitHub."} 51 | knitr::include_graphics("img/screenshots/github-specific-file.png") 52 | ``` 53 | 54 | ### Blame 55 | 56 | The "blame" view of a file is related to what `git blame` does on the command line. It reveals who last touched each line of the file, how long ago, and the associated commit message. Click on the commit message to visit that commit. Or click the "stacked rectangles" icon to move further back in time, but staying in blame view. This is handy when doing forensics on a specific and small set of lines. 57 | 58 | *add a screenshot (and update that above) but first pick a better example than Happy Git, i.e. one with more contributors / more interesting history* 59 | 60 | ### History 61 | 62 | The "history" view for a file is very much like the overall commit history described above, except it only includes commits that affect the file of interest. This can be handy when your inquiry is rather diffuse and you're trying to digest the general story arc for a file. 63 | 64 | ### Hyperlink to specific lines at a specific state 65 | 66 | When viewing a file on GitHub, you can click on a line number to highlight it. Use "click ... shift-click" to select a range of lines. Notice your browser's URL shows something of this form: 67 | 68 | ``` bash 69 | https://github.com/OWNER/REPO/blob/SHA/path/to/file.R#L27-L31 70 | ``` 71 | 72 | If the URL does not contain the SHA, type "y" to toggle into that form. 73 | 74 | These file- and SHA-specific URLs are a great way to point people at particular lines of code in online conversations. It's best practice to use the uglier links that contain the SHA, as they will stand the test of time. 75 | 76 | ## Search 77 | 78 | Search is always available in the upper-righthand corner of GitHub. 79 | 80 | ```{r github-repo-search, echo = FALSE, out.width = "100%", fig.cap = "Typing into GitHub search bar."} 81 | knitr::include_graphics("img/screenshots/github-repo-search.png") 82 | ``` 83 | 84 | Once you enter some text in the search box, a dropdown provides the choice to search in the current repo (the default) or all of GitHub. GitHub searches the contents of files (described as "Code"), commit messages, and issues. Take advantage of the search hits across these different domains. Again, this is a powerful way to zoom in on specific lines of code, revisit an interesting time in project history, or re-discover a conversation thread. 85 | 86 | ### Issue search 87 | 88 | If you want to search issues specifically, the search box on any repo's Issues page is prepopulated with the filters `is:issue` and `is:open`. 89 | 90 | -------------------------------------------------------------------------------- /workshops.Rmd: -------------------------------------------------------------------------------- 1 | # Workshops 2 | 3 | These materials can be used for independent study, but they have also been used to support: 4 | 5 | * in-person workshops (see below) 6 | * [STAT 545](http://stat545.com) at UBC 7 | * [UBC Master of Data Science](http://masterdatascience.science.ubc.ca) 8 | 9 | ## Pre-workshop set-up 10 | 11 | Optional reading on the big picture motivation: [Why Git? Why GitHub?](#big-picture) 12 | 13 | **It is vital that you attempt to set up your system in advance. You cannot show up at the workshop with no preparation and keep up!** 14 | 15 | Try this. Best case scenario is about 1 - 2 hours. If you hit a wall, we will help: 16 | 17 | * [Register a free GitHub account](#github-acct). 18 | * [Install or update R and RStudio](#install-r-rstudio). 19 | * [Install Git](#install-git). 20 | * [Introduce yourself to Git](#hello-git). 21 | * [Configure a personal access token](#https-pat) or [set up SSH keys](#ssh-keys). 22 | * [Prove local Git can talk to GitHub](#push-pull-github). 23 | * [Prove RStudio can find local Git](#rstudio-git-github) and, therefore, can talk to GitHub. 24 | - FYI: this is where our hands-on activities usually start. We walk through a similar activity together, with narrative, and build from there. 25 | * Contemplate if you'd like to [install an optional Git client](#git-client), now or in future. 26 | 27 | Troubleshooting: 28 | 29 | * Sometimes RStudio [needs a little help finding Git](#rstudio-see-git). 30 | * General troubleshooting: [RStudio, Git, GitHub Hell](#troubleshooting). 31 | 32 | These are battle-tested instructions, so most will succeed. We believe in you! If you have trouble, reach out for help and stick with it. Where to get help: 33 | 34 | * If you are enrolled in an upcoming workshop, find it below to get specifics on pre-workshop support. 35 | * We *might* be able to respond to a GitHub issue [here](https://github.com/jennybc/happy-git-with-r/issues). 36 | * If there is a clear R/RStudio angle, post on . 37 | * General advice: search with Google and on , see also . 38 | 39 | ## posit::conf 2023 40 | 41 | 1-day workshop: What They Forgot to Teach You About R 42 | Will have half-day coverage of Git/GitHub 43 | Sep 17, [`posit.co/conference`](https://posit.co/conference/) Workshop Day, Chicago 44 | 45 | Registered workshop participants should use [this thread](https://forum.posit.co/t/what-they-forgot-to-teach-you-about-r-workshop-rstudio-conf-2022/138999) on forum.posit.co to discuss system prep woes. 46 | 47 | ## Previous workshops 48 | 49 | * rstudio::conf 2022 50 | - 2-day workshop: What They Forgot to Teach You About R 51 | - ~25% of content was Git/GitHub 52 | - July 25-26, 2022, Washington, D.C. 53 | * RaukR: Advanced R for Bioinformatics Summer School 54 | - June 13, 2022, online 55 | * rstudio::conf 2020 56 | - 2-day workshop: What They Forgot to Teach You About R 57 | - ~25% of content was Git/GitHub + R/Rmd/RStudio 58 | - January 27-28, 2020, San Francisco, CA 59 | * UBC Master of Data Science Program 60 | - Guest lecture on daily Git/GitHub workflows 61 | - January 9, 2020 62 | * RaukR: Advanced R for Bioinformatics Summer School 63 | - June 10-20, 2019, Visby, Sweden 64 | * rstudio::conf 2019 65 | - 2-day workshop: What They Forgot to Teach You About R 66 | - ~25% of content was Git/GitHub + R/Rmd/RStudio 67 | - Jan 15-16, 2019, Austin, TX 68 | * Seattle October 2018 69 | - 2-day workshop: [What They Forgot to Teach You About R](https://whattheyforgot.org/index.html#seattle-2018-october-4-5) 70 | - 3 of 8 units on Git/GitHub + R/Rmd/RStudio 71 | - Oct 4-5, 2018, The Westin Seattle 72 | * rstudio::conf 2018 73 | - 2-day workshop: What They Forgot to Teach You About R 74 | - ~25% of content was Git/GitHub + R/Rmd/RStudio 75 | - Jan 31 & Feb 1, 2018, San Diego, CA 76 | * CSAMA 2017: Statistical Data Analysis for Genome Biology 77 | - 78 | - June 11-16, 2017, Bressanone-Brixen, Italy 79 | * satRday Cape Town 2017 80 | - 81 | - February 16 - 18, 2017, Cape Town, South Africa 82 | * rstudio::conf 2017 83 | - 84 | - January 13 - 14, 2017, Orlando, FL 85 | - Saturday January 14, 10:15am to 12:30pm 86 | * CSAMA 2016: Statistical Data Analysis for Genome Biology 87 | - 88 | - July 10 - 15, 2016, Bressanone-Brixen, Italy 89 | * useR! 2016 Stanford 90 | - 91 | - Monday, June 27, 2016 92 | - [Using Git and GitHub with R, RStudio, and R Markdown](http://user2016.r-project.org/tutorials/01.html) 93 | --------------------------------------------------------------------------------