├── .Rbuildignore ├── .Rprofile ├── .gitignore ├── CNAME ├── LICENSE.md ├── README.Rmd ├── README.md ├── _brand.yml ├── _quarto.yml ├── img ├── branch-link-rstudio.PNG ├── github-revert-pr.PNG ├── github_conflict.PNG ├── new-project-wizard.PNG ├── rebase_commit_history.PNG ├── show-clone-github.PNG └── show-fork-github.PNG ├── intro-git-github.Rproj ├── renv.lock ├── renv ├── .gitignore ├── activate.R └── settings.json ├── session-break-slide.html ├── session-break-slide.qmd ├── session-commit-main.html ├── session-commit-main.qmd ├── session-conflict.html ├── session-conflict.qmd ├── session-fork-clone.html ├── session-fork-clone.qmd ├── session-intro.html ├── session-intro.qmd ├── session-prework.html ├── session-prework.qmd ├── session-pull-requests.html ├── session-pull-requests.qmd ├── session-setup.html ├── session-setup.qmd ├── session-undo-merge.html ├── session-undo-merge.qmd ├── session-usethis-errors.html ├── session-usethis-errors.qmd ├── session-usethis-gert.html ├── session-usethis-gert.qmd ├── session-version-control.html ├── session-version-control.qmd ├── session-version-workflow.html └── session-version-workflow.qmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^renv$ 2 | ^renv\.lock$ 3 | ^LICENSE\.md$ 4 | -------------------------------------------------------------------------------- /.Rprofile: -------------------------------------------------------------------------------- 1 | source("renv/activate.R") 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | .Rdata 6 | .httr-oauth 7 | .DS_Store 8 | 9 | /.quarto/ 10 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | intro-git-github.nhsrcommunity.com -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## creative commons 2 | 3 | # CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. 6 | 7 | ### Statement of Purpose 8 | 9 | The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). 10 | 11 | Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. 12 | 13 | For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. 14 | 15 | 1. __Copyright and Related Rights.__ A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: 16 | 17 | i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; 18 | 19 | ii. moral rights retained by the original author(s) and/or performer(s); 20 | 21 | iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; 22 | 23 | iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; 24 | 25 | v. rights protecting the extraction, dissemination, use and reuse of data in a Work; 26 | 27 | vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and 28 | 29 | vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. 30 | 31 | 2. __Waiver.__ To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. 32 | 33 | 3. __Public License Fallback.__ Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. 34 | 35 | 4. __Limitations and Disclaimers.__ 36 | 37 | a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. 38 | 39 | b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. 40 | 41 | c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. 42 | 43 | d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. 44 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>" 11 | ) 12 | ``` 13 | 14 | # Introduction to Git and GitHub 15 | 16 | 17 | 18 | 19 | Introduction to Git and GitHub training based on the Forwards workshops: 20 | 21 | [Setting up your system](http://bit.ly/pkg-dev-2) and [Your first package](http://bit.ly/pkg-dev-3) as part of the one-hour package development series. 22 | 23 | ## Part 1 24 | 25 | - [Prework](https://intro-git-github.nhsrcommunity.com/session-prework.html#/title-slide) - Get set up on a computer 26 | - [Introduction](https://intro-git-github.nhsrcommunity.com/session-intro.html#/title-slide) - What is version control? 27 | - [Setting up](https://intro-git-github.nhsrcommunity.com/session-setup.html#/title-slide) - Getting started with Git and GitHub 28 | 29 | ### Break 30 | 31 | [Break](https://intro-git-github.nhsrcommunity.com/session-break-slide.html#/title-slide) 32 | 33 | - [Version Control](https://intro-git-github.nhsrcommunity.com/session-version-control.html#/title-slide) - What is Git/GitHub and how they relate to RStudio along with the ups and downs of Git 34 | - [Workflow](https://intro-git-github.nhsrcommunity.com/session-version-workflow.html#/title-slide) - Brief introduction to the Git and GitHub terminology 35 | - [Workflow with {usethis} and {gert}](https://intro-git-github.nhsrcommunity.com/session-usethis-gert.html#/title-slide) - start work and making a commit 36 | 37 | ## Part 2 38 | 39 | - [Pull Requests (PRs)](https://intro-git-github.nhsrcommunity.com/session-pull-requests.html#/title-slide) - making pull request, pausing, resuming and finishing 40 | - [Merge conflict!](https://intro-git-github.nhsrcommunity.com/session-conflict.html#/title-slide) - repeat steps from previous session and create a conflict merge 41 | 42 | ### Break 43 | 44 | [Break](https://intro-git-github.nhsrcommunity.com/session-break-slide.html#/title-slide) 45 | 46 | - [Commit to main (and undo last commit!)](https://intro-git-github.nhsrcommunity.com/session-commit-main.html#/title-slide) - how committing is possible to the main and undo last commits 47 | - [Undo last merge](https://intro-git-github.nhsrcommunity.com/session-undo-merge.html#/title-slide) - undoing a merge (reverting a pull request) 48 | - [Existing repositories](https://intro-git-github.nhsrcommunity.com/session-fork-clone.html#/title-slide) - Getting copies of existing repositories 49 | 50 | ## Appendix slides 51 | 52 | [{usethis} errors](https://intro-git-github.nhsrcommunity.com/session-usethis-errors.html#/title-slide) - typical errors from set up issues 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Introduction to Git and GitHub 5 | 6 | 7 | 8 | 9 | Introduction to Git and GitHub training based on the Forwards workshops: 10 | 11 | [Setting up your system](http://bit.ly/pkg-dev-2) and [Your first 12 | package](http://bit.ly/pkg-dev-3) as part of the one-hour package 13 | development series. 14 | 15 | ## Part 1 16 | 17 | - [Prework](https://intro-git-github.nhsrcommunity.com/session-prework.html#/title-slide) - 18 | Get set up on a computer 19 | - [Introduction](https://intro-git-github.nhsrcommunity.com/session-intro.html#/title-slide) - 20 | What is version control? 21 | - [Setting 22 | up](https://intro-git-github.nhsrcommunity.com/session-setup.html#/title-slide) - 23 | Getting started with Git and GitHub 24 | 25 | ### Break 26 | 27 | [Break](https://intro-git-github.nhsrcommunity.com/session-break-slide.html#/title-slide) 28 | 29 | - [Version 30 | Control](https://intro-git-github.nhsrcommunity.com/session-version-control.html#/title-slide) - 31 | What is Git/GitHub and how they relate to RStudio along with the ups 32 | and downs of Git 33 | - [Workflow](https://intro-git-github.nhsrcommunity.com/session-version-workflow.html#/title-slide) - 34 | Brief introduction to the Git and GitHub terminology 35 | - [Workflow with {usethis} and 36 | {gert}](https://intro-git-github.nhsrcommunity.com/session-usethis-gert.html#/title-slide) - 37 | start work and making a commit 38 | 39 | ## Part 2 40 | 41 | - [Pull Requests 42 | (PRs)](https://intro-git-github.nhsrcommunity.com/session-pull-requests.html#/title-slide) - 43 | making pull request, pausing, resuming and finishing 44 | - [Merge 45 | conflict!](https://intro-git-github.nhsrcommunity.com/session-conflict.html#/title-slide) - 46 | repeat steps from previous session and create a conflict merge 47 | 48 | ### Break 49 | 50 | [Break](https://intro-git-github.nhsrcommunity.com/session-break-slide.html#/title-slide) 51 | 52 | - [Commit to main (and undo last 53 | commit!)](https://intro-git-github.nhsrcommunity.com/session-commit-main.html#/title-slide) - 54 | how committing is possible to the main and undo last commits 55 | - [Undo last 56 | merge](https://intro-git-github.nhsrcommunity.com/session-undo-merge.html#/title-slide) - 57 | undoing a merge (reverting a pull request) 58 | - [Existing 59 | repositories](https://intro-git-github.nhsrcommunity.com/session-fork-clone.html#/title-slide) - 60 | Getting copies of existing repositories 61 | 62 | ## Appendix slides 63 | 64 | [{usethis} 65 | errors](https://intro-git-github.nhsrcommunity.com/session-usethis-errors.html#/title-slide) - 66 | typical errors from set up issues 67 | -------------------------------------------------------------------------------- /_brand.yml: -------------------------------------------------------------------------------- 1 | meta: 2 | name: 3 | short: NHSR 4 | full: NHS-R Community 5 | link: 6 | home: https://nhsrcommunity.com/ 7 | 8 | # # Download the NHS-R Community logo and store it next to _brand.yml 9 | # # You'll have to update this section with the correct file names 10 | # logo: 11 | # images: 12 | # header: nhsr-logo.svg 13 | # small: nhsr-logo.svg 14 | # medium: header 15 | # large: header 16 | 17 | # NHS-R Community uses the NHS England colour palette 18 | # https://www.england.nhs.uk/nhsidentity/identity-guidelines/colours/ used 19 | # under the OGL Licence v3.0 20 | 21 | color: 22 | palette: 23 | # Core neutrals (Level 2) 24 | white: "#FFFFFF" 25 | black: "#231F20" 26 | grey-dark: "#425563" 27 | grey-mid: "#768692" 28 | grey-pale: "#E8EDEE" 29 | 30 | # Blues (Level 1) 31 | blue-dark: "#003087" 32 | blue: "#005EB8" 33 | blue-bright: "#0072CE" 34 | blue-light: "#41B6E6" 35 | blue-aqua: "#00A9CE" 36 | 37 | # Greens (Level 3) 38 | green-dark: "#006747" 39 | green: "#009639" 40 | green-light: "#78BE20" 41 | green-aqua: "#00A499" 42 | 43 | # Purples and Pinks 44 | purple: "#330072" 45 | pink-dark: "#7C2855" 46 | pink: "#AE2573" 47 | 48 | # Reds 49 | red-dark: "#8A1538" 50 | red: "#DA291C" # Emergency Services Red 51 | 52 | # Yellows and Orange 53 | orange: "#ED8B00" 54 | yellow-warm: "#FFB81C" 55 | yellow: "#FAE100" 56 | 57 | # Bootstrap color aliases - using closest matches without duplication 58 | indigo: blue-dark 59 | cyan: blue-aqua 60 | teal: green-aqua 61 | 62 | foreground: black 63 | background: white 64 | primary: blue 65 | secondary: grey-dark 66 | tertiary: grey-pale 67 | success: green 68 | danger: red 69 | warning: yellow-warm 70 | info: blue-light 71 | light: grey-pale 72 | dark: grey-dark 73 | 74 | typography: 75 | fonts: 76 | # Note: Frutiger is a licensed NHS England font that requires purchasing 77 | # https://www.england.nhs.uk/nhsidentity/identity-guidelines/fonts/ 78 | # - family: Frutiger W01 79 | # source: file 80 | # files: 81 | # - path: fonts/FrutigerLTW01-55Roman.ttf 82 | # - path: fonts/FrutigerLTW01-65Bold.ttf 83 | # weight: bold 84 | 85 | - family: Arial 86 | source: system 87 | 88 | base: 89 | family: "Arial, sans-serif" 90 | line-height: 1.5 91 | 92 | headings: 93 | family: "Arial, sans-serif" 94 | weight: 700 95 | line-height: 1.25 96 | color: blue 97 | 98 | defaults: 99 | bootstrap: 100 | defaults: 101 | # NHS-R Community specific variables could be added here 102 | enable-rounded: false 103 | -------------------------------------------------------------------------------- /_quarto.yml: -------------------------------------------------------------------------------- 1 | project: 2 | title: "intro-git-github" 3 | render: 4 | - "*.qmd" 5 | - "!LICENCE.md" 6 | embed-resources: true 7 | format: 8 | revealjs: 9 | footer: "" 10 | code-link: true 11 | preview-links: true 12 | logo: https://raw.githubusercontent.com/nhs-r-community/assets/main/logo/nhsr-logo.svg 13 | author: "Zoë Turner" 14 | execute: 15 | echo: true 16 | eval: false 17 | title-slide-attributes: 18 | data-background-color: "#43464B" 19 | brand: _brand.yml 20 | 21 | # output-dir: "/slides" 22 | -------------------------------------------------------------------------------- /img/branch-link-rstudio.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhs-r-community/intro-git-github/aa9fc1313ff123f4396a3568b30da040a9322ee3/img/branch-link-rstudio.PNG -------------------------------------------------------------------------------- /img/github-revert-pr.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhs-r-community/intro-git-github/aa9fc1313ff123f4396a3568b30da040a9322ee3/img/github-revert-pr.PNG -------------------------------------------------------------------------------- /img/github_conflict.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhs-r-community/intro-git-github/aa9fc1313ff123f4396a3568b30da040a9322ee3/img/github_conflict.PNG -------------------------------------------------------------------------------- /img/new-project-wizard.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhs-r-community/intro-git-github/aa9fc1313ff123f4396a3568b30da040a9322ee3/img/new-project-wizard.PNG -------------------------------------------------------------------------------- /img/rebase_commit_history.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhs-r-community/intro-git-github/aa9fc1313ff123f4396a3568b30da040a9322ee3/img/rebase_commit_history.PNG -------------------------------------------------------------------------------- /img/show-clone-github.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhs-r-community/intro-git-github/aa9fc1313ff123f4396a3568b30da040a9322ee3/img/show-clone-github.PNG -------------------------------------------------------------------------------- /img/show-fork-github.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhs-r-community/intro-git-github/aa9fc1313ff123f4396a3568b30da040a9322ee3/img/show-fork-github.PNG -------------------------------------------------------------------------------- /intro-git-github.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | ProjectId: 1771fb92-52cc-4c92-97b0-bdb25115a0b3 3 | 4 | RestoreWorkspace: Default 5 | SaveWorkspace: Default 6 | AlwaysSaveHistory: Default 7 | 8 | EnableCodeIndexing: Yes 9 | UseSpacesForTab: Yes 10 | NumSpacesForTab: 2 11 | Encoding: UTF-8 12 | 13 | RnwWeave: Sweave 14 | LaTeX: pdfLaTeX 15 | -------------------------------------------------------------------------------- /renv.lock: -------------------------------------------------------------------------------- 1 | { 2 | "R": { 3 | "Version": "4.4.1", 4 | "Repositories": [ 5 | { 6 | "Name": "CRAN", 7 | "URL": "https://cran.rstudio.com" 8 | } 9 | ] 10 | }, 11 | "Packages": { 12 | "R6": { 13 | "Package": "R6", 14 | "Version": "2.5.1", 15 | "Source": "Repository", 16 | "Repository": "CRAN", 17 | "Requirements": [ 18 | "R" 19 | ], 20 | "Hash": "470851b6d5d0ac559e9d01bb352b4021" 21 | }, 22 | "askpass": { 23 | "Package": "askpass", 24 | "Version": "1.2.1", 25 | "Source": "Repository", 26 | "Repository": "CRAN", 27 | "Requirements": [ 28 | "sys" 29 | ], 30 | "Hash": "c39f4155b3ceb1a9a2799d700fbd4b6a" 31 | }, 32 | "base64enc": { 33 | "Package": "base64enc", 34 | "Version": "0.1-3", 35 | "Source": "Repository", 36 | "Repository": "CRAN", 37 | "Requirements": [ 38 | "R" 39 | ], 40 | "Hash": "543776ae6848fde2f48ff3816d0628bc" 41 | }, 42 | "bslib": { 43 | "Package": "bslib", 44 | "Version": "0.8.0", 45 | "Source": "Repository", 46 | "Repository": "CRAN", 47 | "Requirements": [ 48 | "R", 49 | "base64enc", 50 | "cachem", 51 | "fastmap", 52 | "grDevices", 53 | "htmltools", 54 | "jquerylib", 55 | "jsonlite", 56 | "lifecycle", 57 | "memoise", 58 | "mime", 59 | "rlang", 60 | "sass" 61 | ], 62 | "Hash": "b299c6741ca9746fb227debcb0f9fb6c" 63 | }, 64 | "cachem": { 65 | "Package": "cachem", 66 | "Version": "1.1.0", 67 | "Source": "Repository", 68 | "Repository": "CRAN", 69 | "Requirements": [ 70 | "fastmap", 71 | "rlang" 72 | ], 73 | "Hash": "cd9a672193789068eb5a2aad65a0dedf" 74 | }, 75 | "cli": { 76 | "Package": "cli", 77 | "Version": "3.6.3", 78 | "Source": "Repository", 79 | "Repository": "CRAN", 80 | "Requirements": [ 81 | "R", 82 | "utils" 83 | ], 84 | "Hash": "b21916dd77a27642b447374a5d30ecf3" 85 | }, 86 | "clipr": { 87 | "Package": "clipr", 88 | "Version": "0.8.0", 89 | "Source": "Repository", 90 | "Repository": "CRAN", 91 | "Requirements": [ 92 | "utils" 93 | ], 94 | "Hash": "3f038e5ac7f41d4ac41ce658c85e3042" 95 | }, 96 | "countdown": { 97 | "Package": "countdown", 98 | "Version": "0.4.0", 99 | "Source": "Repository", 100 | "Repository": "CRAN", 101 | "Requirements": [ 102 | "htmltools", 103 | "prismatic", 104 | "utils", 105 | "whisker" 106 | ], 107 | "Hash": "b44ad5a5e287637c3b8ca0e9bb64bb18" 108 | }, 109 | "crayon": { 110 | "Package": "crayon", 111 | "Version": "1.5.3", 112 | "Source": "Repository", 113 | "Repository": "CRAN", 114 | "Requirements": [ 115 | "grDevices", 116 | "methods", 117 | "utils" 118 | ], 119 | "Hash": "859d96e65ef198fd43e82b9628d593ef" 120 | }, 121 | "credentials": { 122 | "Package": "credentials", 123 | "Version": "2.0.2", 124 | "Source": "Repository", 125 | "Repository": "CRAN", 126 | "Requirements": [ 127 | "askpass", 128 | "curl", 129 | "jsonlite", 130 | "openssl", 131 | "sys" 132 | ], 133 | "Hash": "09fd631e607a236f8cc7f9604db32cb8" 134 | }, 135 | "curl": { 136 | "Package": "curl", 137 | "Version": "6.0.1", 138 | "Source": "Repository", 139 | "Repository": "CRAN", 140 | "Requirements": [ 141 | "R" 142 | ], 143 | "Hash": "e8ba62486230951fcd2b881c5be23f96" 144 | }, 145 | "desc": { 146 | "Package": "desc", 147 | "Version": "1.4.3", 148 | "Source": "Repository", 149 | "Repository": "CRAN", 150 | "Requirements": [ 151 | "R", 152 | "R6", 153 | "cli", 154 | "utils" 155 | ], 156 | "Hash": "99b79fcbd6c4d1ce087f5c5c758b384f" 157 | }, 158 | "digest": { 159 | "Package": "digest", 160 | "Version": "0.6.37", 161 | "Source": "Repository", 162 | "Repository": "CRAN", 163 | "Requirements": [ 164 | "R", 165 | "utils" 166 | ], 167 | "Hash": "33698c4b3127fc9f506654607fb73676" 168 | }, 169 | "evaluate": { 170 | "Package": "evaluate", 171 | "Version": "1.0.1", 172 | "Source": "Repository", 173 | "Repository": "CRAN", 174 | "Requirements": [ 175 | "R" 176 | ], 177 | "Hash": "3fd29944b231036ad67c3edb32e02201" 178 | }, 179 | "farver": { 180 | "Package": "farver", 181 | "Version": "2.1.2", 182 | "Source": "Repository", 183 | "Repository": "CRAN", 184 | "Hash": "680887028577f3fa2a81e410ed0d6e42" 185 | }, 186 | "fastmap": { 187 | "Package": "fastmap", 188 | "Version": "1.2.0", 189 | "Source": "Repository", 190 | "Repository": "CRAN", 191 | "Hash": "aa5e1cd11c2d15497494c5292d7ffcc8" 192 | }, 193 | "fontawesome": { 194 | "Package": "fontawesome", 195 | "Version": "0.5.3", 196 | "Source": "Repository", 197 | "Repository": "CRAN", 198 | "Requirements": [ 199 | "R", 200 | "htmltools", 201 | "rlang" 202 | ], 203 | "Hash": "bd1297f9b5b1fc1372d19e2c4cd82215" 204 | }, 205 | "fs": { 206 | "Package": "fs", 207 | "Version": "1.6.5", 208 | "Source": "Repository", 209 | "Repository": "CRAN", 210 | "Requirements": [ 211 | "R", 212 | "methods" 213 | ], 214 | "Hash": "7f48af39fa27711ea5fbd183b399920d" 215 | }, 216 | "gert": { 217 | "Package": "gert", 218 | "Version": "2.1.4", 219 | "Source": "Repository", 220 | "Repository": "CRAN", 221 | "Requirements": [ 222 | "askpass", 223 | "credentials", 224 | "openssl", 225 | "rstudioapi", 226 | "sys", 227 | "zip" 228 | ], 229 | "Hash": "ae855ad6d7be20dd7b05d43d25700398" 230 | }, 231 | "gh": { 232 | "Package": "gh", 233 | "Version": "1.4.1", 234 | "Source": "Repository", 235 | "Repository": "CRAN", 236 | "Requirements": [ 237 | "R", 238 | "cli", 239 | "gitcreds", 240 | "glue", 241 | "httr2", 242 | "ini", 243 | "jsonlite", 244 | "lifecycle", 245 | "rlang" 246 | ], 247 | "Hash": "fbbbc48eba7a6626a08bb365e44b563b" 248 | }, 249 | "gitcreds": { 250 | "Package": "gitcreds", 251 | "Version": "0.1.2", 252 | "Source": "Repository", 253 | "Repository": "CRAN", 254 | "Requirements": [ 255 | "R" 256 | ], 257 | "Hash": "ab08ac61f3e1be454ae21911eb8bc2fe" 258 | }, 259 | "glue": { 260 | "Package": "glue", 261 | "Version": "1.8.0", 262 | "Source": "Repository", 263 | "Repository": "CRAN", 264 | "Requirements": [ 265 | "R", 266 | "methods" 267 | ], 268 | "Hash": "5899f1eaa825580172bb56c08266f37c" 269 | }, 270 | "highr": { 271 | "Package": "highr", 272 | "Version": "0.11", 273 | "Source": "Repository", 274 | "Repository": "CRAN", 275 | "Requirements": [ 276 | "R", 277 | "xfun" 278 | ], 279 | "Hash": "d65ba49117ca223614f71b60d85b8ab7" 280 | }, 281 | "htmltools": { 282 | "Package": "htmltools", 283 | "Version": "0.5.8.1", 284 | "Source": "Repository", 285 | "Repository": "CRAN", 286 | "Requirements": [ 287 | "R", 288 | "base64enc", 289 | "digest", 290 | "fastmap", 291 | "grDevices", 292 | "rlang", 293 | "utils" 294 | ], 295 | "Hash": "81d371a9cc60640e74e4ab6ac46dcedc" 296 | }, 297 | "httr2": { 298 | "Package": "httr2", 299 | "Version": "1.0.6", 300 | "Source": "Repository", 301 | "Repository": "CRAN", 302 | "Requirements": [ 303 | "R", 304 | "R6", 305 | "cli", 306 | "curl", 307 | "glue", 308 | "lifecycle", 309 | "magrittr", 310 | "openssl", 311 | "rappdirs", 312 | "rlang", 313 | "vctrs", 314 | "withr" 315 | ], 316 | "Hash": "3ef5d07ec78803475a94367d71b40c41" 317 | }, 318 | "ini": { 319 | "Package": "ini", 320 | "Version": "0.3.1", 321 | "Source": "Repository", 322 | "Repository": "CRAN", 323 | "Hash": "6154ec2223172bce8162d4153cda21f7" 324 | }, 325 | "jquerylib": { 326 | "Package": "jquerylib", 327 | "Version": "0.1.4", 328 | "Source": "Repository", 329 | "Repository": "CRAN", 330 | "Requirements": [ 331 | "htmltools" 332 | ], 333 | "Hash": "5aab57a3bd297eee1c1d862735972182" 334 | }, 335 | "jsonlite": { 336 | "Package": "jsonlite", 337 | "Version": "1.8.9", 338 | "Source": "Repository", 339 | "Repository": "CRAN", 340 | "Requirements": [ 341 | "methods" 342 | ], 343 | "Hash": "4e993b65c2c3ffbffce7bb3e2c6f832b" 344 | }, 345 | "knitr": { 346 | "Package": "knitr", 347 | "Version": "1.49", 348 | "Source": "Repository", 349 | "Repository": "CRAN", 350 | "Requirements": [ 351 | "R", 352 | "evaluate", 353 | "highr", 354 | "methods", 355 | "tools", 356 | "xfun", 357 | "yaml" 358 | ], 359 | "Hash": "9fcb189926d93c636dea94fbe4f44480" 360 | }, 361 | "lifecycle": { 362 | "Package": "lifecycle", 363 | "Version": "1.0.4", 364 | "Source": "Repository", 365 | "Repository": "CRAN", 366 | "Requirements": [ 367 | "R", 368 | "cli", 369 | "glue", 370 | "rlang" 371 | ], 372 | "Hash": "b8552d117e1b808b09a832f589b79035" 373 | }, 374 | "magrittr": { 375 | "Package": "magrittr", 376 | "Version": "2.0.3", 377 | "Source": "Repository", 378 | "Repository": "CRAN", 379 | "Requirements": [ 380 | "R" 381 | ], 382 | "Hash": "7ce2733a9826b3aeb1775d56fd305472" 383 | }, 384 | "memoise": { 385 | "Package": "memoise", 386 | "Version": "2.0.1", 387 | "Source": "Repository", 388 | "Repository": "CRAN", 389 | "Requirements": [ 390 | "cachem", 391 | "rlang" 392 | ], 393 | "Hash": "e2817ccf4a065c5d9d7f2cfbe7c1d78c" 394 | }, 395 | "mime": { 396 | "Package": "mime", 397 | "Version": "0.12", 398 | "Source": "Repository", 399 | "Repository": "CRAN", 400 | "Requirements": [ 401 | "tools" 402 | ], 403 | "Hash": "18e9c28c1d3ca1560ce30658b22ce104" 404 | }, 405 | "openssl": { 406 | "Package": "openssl", 407 | "Version": "2.2.2", 408 | "Source": "Repository", 409 | "Repository": "CRAN", 410 | "Requirements": [ 411 | "askpass" 412 | ], 413 | "Hash": "d413e0fef796c9401a4419485f709ca1" 414 | }, 415 | "prismatic": { 416 | "Package": "prismatic", 417 | "Version": "1.1.2", 418 | "Source": "Repository", 419 | "Repository": "CRAN", 420 | "Requirements": [ 421 | "R", 422 | "farver", 423 | "grDevices", 424 | "graphics" 425 | ], 426 | "Hash": "51967d2e55a523791ae22832e86209ae" 427 | }, 428 | "purrr": { 429 | "Package": "purrr", 430 | "Version": "1.0.2", 431 | "Source": "Repository", 432 | "Repository": "CRAN", 433 | "Requirements": [ 434 | "R", 435 | "cli", 436 | "lifecycle", 437 | "magrittr", 438 | "rlang", 439 | "vctrs" 440 | ], 441 | "Hash": "1cba04a4e9414bdefc9dcaa99649a8dc" 442 | }, 443 | "rappdirs": { 444 | "Package": "rappdirs", 445 | "Version": "0.3.3", 446 | "Source": "Repository", 447 | "Repository": "CRAN", 448 | "Requirements": [ 449 | "R" 450 | ], 451 | "Hash": "5e3c5dc0b071b21fa128676560dbe94d" 452 | }, 453 | "renv": { 454 | "Package": "renv", 455 | "Version": "0.17.3", 456 | "Source": "Repository", 457 | "Repository": "CRAN", 458 | "Requirements": [ 459 | "utils" 460 | ], 461 | "Hash": "4543b8cd233ae25c6aba8548be9e747e" 462 | }, 463 | "rlang": { 464 | "Package": "rlang", 465 | "Version": "1.1.4", 466 | "Source": "Repository", 467 | "Repository": "CRAN", 468 | "Requirements": [ 469 | "R", 470 | "utils" 471 | ], 472 | "Hash": "3eec01f8b1dee337674b2e34ab1f9bc1" 473 | }, 474 | "rmarkdown": { 475 | "Package": "rmarkdown", 476 | "Version": "2.29", 477 | "Source": "Repository", 478 | "Repository": "CRAN", 479 | "Requirements": [ 480 | "R", 481 | "bslib", 482 | "evaluate", 483 | "fontawesome", 484 | "htmltools", 485 | "jquerylib", 486 | "jsonlite", 487 | "knitr", 488 | "methods", 489 | "tinytex", 490 | "tools", 491 | "utils", 492 | "xfun", 493 | "yaml" 494 | ], 495 | "Hash": "df99277f63d01c34e95e3d2f06a79736" 496 | }, 497 | "rprojroot": { 498 | "Package": "rprojroot", 499 | "Version": "2.0.4", 500 | "Source": "Repository", 501 | "Repository": "CRAN", 502 | "Requirements": [ 503 | "R" 504 | ], 505 | "Hash": "4c8415e0ec1e29f3f4f6fc108bef0144" 506 | }, 507 | "rstudioapi": { 508 | "Package": "rstudioapi", 509 | "Version": "0.17.1", 510 | "Source": "Repository", 511 | "Repository": "CRAN", 512 | "Hash": "5f90cd73946d706cfe26024294236113" 513 | }, 514 | "sass": { 515 | "Package": "sass", 516 | "Version": "0.4.9", 517 | "Source": "Repository", 518 | "Repository": "CRAN", 519 | "Requirements": [ 520 | "R6", 521 | "fs", 522 | "htmltools", 523 | "rappdirs", 524 | "rlang" 525 | ], 526 | "Hash": "d53dbfddf695303ea4ad66f86e99b95d" 527 | }, 528 | "sys": { 529 | "Package": "sys", 530 | "Version": "3.4.3", 531 | "Source": "Repository", 532 | "Repository": "CRAN", 533 | "Hash": "de342ebfebdbf40477d0758d05426646" 534 | }, 535 | "tinytex": { 536 | "Package": "tinytex", 537 | "Version": "0.54", 538 | "Source": "Repository", 539 | "Repository": "CRAN", 540 | "Requirements": [ 541 | "xfun" 542 | ], 543 | "Hash": "3ec7e3ddcacc2d34a9046941222bf94d" 544 | }, 545 | "usethis": { 546 | "Package": "usethis", 547 | "Version": "3.0.0", 548 | "Source": "Repository", 549 | "Repository": "CRAN", 550 | "Requirements": [ 551 | "R", 552 | "cli", 553 | "clipr", 554 | "crayon", 555 | "curl", 556 | "desc", 557 | "fs", 558 | "gert", 559 | "gh", 560 | "glue", 561 | "jsonlite", 562 | "lifecycle", 563 | "purrr", 564 | "rappdirs", 565 | "rlang", 566 | "rprojroot", 567 | "rstudioapi", 568 | "stats", 569 | "utils", 570 | "whisker", 571 | "withr", 572 | "yaml" 573 | ], 574 | "Hash": "b2fbf93c2127bedd2cbe9b799530d5d2" 575 | }, 576 | "vctrs": { 577 | "Package": "vctrs", 578 | "Version": "0.6.5", 579 | "Source": "Repository", 580 | "Repository": "CRAN", 581 | "Requirements": [ 582 | "R", 583 | "cli", 584 | "glue", 585 | "lifecycle", 586 | "rlang" 587 | ], 588 | "Hash": "c03fa420630029418f7e6da3667aac4a" 589 | }, 590 | "whisker": { 591 | "Package": "whisker", 592 | "Version": "0.4.1", 593 | "Source": "Repository", 594 | "Repository": "CRAN", 595 | "Hash": "c6abfa47a46d281a7d5159d0a8891e88" 596 | }, 597 | "withr": { 598 | "Package": "withr", 599 | "Version": "3.0.2", 600 | "Source": "Repository", 601 | "Repository": "CRAN", 602 | "Requirements": [ 603 | "R", 604 | "grDevices", 605 | "graphics" 606 | ], 607 | "Hash": "cc2d62c76458d425210d1eb1478b30b4" 608 | }, 609 | "xfun": { 610 | "Package": "xfun", 611 | "Version": "0.49", 612 | "Source": "Repository", 613 | "Repository": "CRAN", 614 | "Requirements": [ 615 | "R", 616 | "grDevices", 617 | "stats", 618 | "tools" 619 | ], 620 | "Hash": "8687398773806cfff9401a2feca96298" 621 | }, 622 | "yaml": { 623 | "Package": "yaml", 624 | "Version": "2.3.10", 625 | "Source": "Repository", 626 | "Repository": "CRAN", 627 | "Hash": "51dab85c6c98e50a18d7551e9d49f76c" 628 | }, 629 | "zip": { 630 | "Package": "zip", 631 | "Version": "2.3.1", 632 | "Source": "Repository", 633 | "Repository": "CRAN", 634 | "Hash": "fcc4bd8e6da2d2011eb64a5e5cc685ab" 635 | } 636 | } 637 | } 638 | -------------------------------------------------------------------------------- /renv/.gitignore: -------------------------------------------------------------------------------- 1 | library/ 2 | local/ 3 | cellar/ 4 | lock/ 5 | python/ 6 | sandbox/ 7 | staging/ 8 | -------------------------------------------------------------------------------- /renv/activate.R: -------------------------------------------------------------------------------- 1 | 2 | local({ 3 | 4 | # the requested version of renv 5 | version <- "0.17.3" 6 | 7 | # the project directory 8 | project <- getwd() 9 | 10 | # figure out whether the autoloader is enabled 11 | enabled <- local({ 12 | 13 | # first, check config option 14 | override <- getOption("renv.config.autoloader.enabled") 15 | if (!is.null(override)) 16 | return(override) 17 | 18 | # next, check environment variables 19 | # TODO: prefer using the configuration one in the future 20 | envvars <- c( 21 | "RENV_CONFIG_AUTOLOADER_ENABLED", 22 | "RENV_AUTOLOADER_ENABLED", 23 | "RENV_ACTIVATE_PROJECT" 24 | ) 25 | 26 | for (envvar in envvars) { 27 | envval <- Sys.getenv(envvar, unset = NA) 28 | if (!is.na(envval)) 29 | return(tolower(envval) %in% c("true", "t", "1")) 30 | } 31 | 32 | # enable by default 33 | TRUE 34 | 35 | }) 36 | 37 | if (!enabled) 38 | return(FALSE) 39 | 40 | # avoid recursion 41 | if (identical(getOption("renv.autoloader.running"), TRUE)) { 42 | warning("ignoring recursive attempt to run renv autoloader") 43 | return(invisible(TRUE)) 44 | } 45 | 46 | # signal that we're loading renv during R startup 47 | options(renv.autoloader.running = TRUE) 48 | on.exit(options(renv.autoloader.running = NULL), add = TRUE) 49 | 50 | # signal that we've consented to use renv 51 | options(renv.consent = TRUE) 52 | 53 | # load the 'utils' package eagerly -- this ensures that renv shims, which 54 | # mask 'utils' packages, will come first on the search path 55 | library(utils, lib.loc = .Library) 56 | 57 | # unload renv if it's already been loaded 58 | if ("renv" %in% loadedNamespaces()) 59 | unloadNamespace("renv") 60 | 61 | # load bootstrap tools 62 | `%||%` <- function(x, y) { 63 | if (is.environment(x) || length(x)) x else y 64 | } 65 | 66 | `%??%` <- function(x, y) { 67 | if (is.null(x)) y else x 68 | } 69 | 70 | bootstrap <- function(version, library) { 71 | 72 | # attempt to download renv 73 | tarball <- tryCatch(renv_bootstrap_download(version), error = identity) 74 | if (inherits(tarball, "error")) 75 | stop("failed to download renv ", version) 76 | 77 | # now attempt to install 78 | status <- tryCatch(renv_bootstrap_install(version, tarball, library), error = identity) 79 | if (inherits(status, "error")) 80 | stop("failed to install renv ", version) 81 | 82 | } 83 | 84 | renv_bootstrap_tests_running <- function() { 85 | getOption("renv.tests.running", default = FALSE) 86 | } 87 | 88 | renv_bootstrap_repos <- function() { 89 | 90 | # get CRAN repository 91 | cran <- getOption("renv.repos.cran", "https://cloud.r-project.org") 92 | 93 | # check for repos override 94 | repos <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA) 95 | if (!is.na(repos)) { 96 | 97 | # check for RSPM; if set, use a fallback repository for renv 98 | rspm <- Sys.getenv("RSPM", unset = NA) 99 | if (identical(rspm, repos)) 100 | repos <- c(RSPM = rspm, CRAN = cran) 101 | 102 | return(repos) 103 | 104 | } 105 | 106 | # check for lockfile repositories 107 | repos <- tryCatch(renv_bootstrap_repos_lockfile(), error = identity) 108 | if (!inherits(repos, "error") && length(repos)) 109 | return(repos) 110 | 111 | # if we're testing, re-use the test repositories 112 | if (renv_bootstrap_tests_running()) { 113 | repos <- getOption("renv.tests.repos") 114 | if (!is.null(repos)) 115 | return(repos) 116 | } 117 | 118 | # retrieve current repos 119 | repos <- getOption("repos") 120 | 121 | # ensure @CRAN@ entries are resolved 122 | repos[repos == "@CRAN@"] <- cran 123 | 124 | # add in renv.bootstrap.repos if set 125 | default <- c(FALLBACK = "https://cloud.r-project.org") 126 | extra <- getOption("renv.bootstrap.repos", default = default) 127 | repos <- c(repos, extra) 128 | 129 | # remove duplicates that might've snuck in 130 | dupes <- duplicated(repos) | duplicated(names(repos)) 131 | repos[!dupes] 132 | 133 | } 134 | 135 | renv_bootstrap_repos_lockfile <- function() { 136 | 137 | lockpath <- Sys.getenv("RENV_PATHS_LOCKFILE", unset = "renv.lock") 138 | if (!file.exists(lockpath)) 139 | return(NULL) 140 | 141 | lockfile <- tryCatch(renv_json_read(lockpath), error = identity) 142 | if (inherits(lockfile, "error")) { 143 | warning(lockfile) 144 | return(NULL) 145 | } 146 | 147 | repos <- lockfile$R$Repositories 148 | if (length(repos) == 0) 149 | return(NULL) 150 | 151 | keys <- vapply(repos, `[[`, "Name", FUN.VALUE = character(1)) 152 | vals <- vapply(repos, `[[`, "URL", FUN.VALUE = character(1)) 153 | names(vals) <- keys 154 | 155 | return(vals) 156 | 157 | } 158 | 159 | renv_bootstrap_download <- function(version) { 160 | 161 | # if the renv version number has 4 components, assume it must 162 | # be retrieved via github 163 | nv <- numeric_version(version) 164 | components <- unclass(nv)[[1]] 165 | 166 | # if this appears to be a development version of 'renv', we'll 167 | # try to restore from github 168 | dev <- length(components) == 4L 169 | 170 | # begin collecting different methods for finding renv 171 | methods <- c( 172 | renv_bootstrap_download_tarball, 173 | if (dev) 174 | renv_bootstrap_download_github 175 | else c( 176 | renv_bootstrap_download_cran_latest, 177 | renv_bootstrap_download_cran_archive 178 | ) 179 | ) 180 | 181 | for (method in methods) { 182 | path <- tryCatch(method(version), error = identity) 183 | if (is.character(path) && file.exists(path)) 184 | return(path) 185 | } 186 | 187 | stop("failed to download renv ", version) 188 | 189 | } 190 | 191 | renv_bootstrap_download_impl <- function(url, destfile) { 192 | 193 | mode <- "wb" 194 | 195 | # https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17715 196 | fixup <- 197 | Sys.info()[["sysname"]] == "Windows" && 198 | substring(url, 1L, 5L) == "file:" 199 | 200 | if (fixup) 201 | mode <- "w+b" 202 | 203 | args <- list( 204 | url = url, 205 | destfile = destfile, 206 | mode = mode, 207 | quiet = TRUE 208 | ) 209 | 210 | if ("headers" %in% names(formals(utils::download.file))) 211 | args$headers <- renv_bootstrap_download_custom_headers(url) 212 | 213 | do.call(utils::download.file, args) 214 | 215 | } 216 | 217 | renv_bootstrap_download_custom_headers <- function(url) { 218 | 219 | headers <- getOption("renv.download.headers") 220 | if (is.null(headers)) 221 | return(character()) 222 | 223 | if (!is.function(headers)) 224 | stopf("'renv.download.headers' is not a function") 225 | 226 | headers <- headers(url) 227 | if (length(headers) == 0L) 228 | return(character()) 229 | 230 | if (is.list(headers)) 231 | headers <- unlist(headers, recursive = FALSE, use.names = TRUE) 232 | 233 | ok <- 234 | is.character(headers) && 235 | is.character(names(headers)) && 236 | all(nzchar(names(headers))) 237 | 238 | if (!ok) 239 | stop("invocation of 'renv.download.headers' did not return a named character vector") 240 | 241 | headers 242 | 243 | } 244 | 245 | renv_bootstrap_download_cran_latest <- function(version) { 246 | 247 | spec <- renv_bootstrap_download_cran_latest_find(version) 248 | type <- spec$type 249 | repos <- spec$repos 250 | 251 | message("* Downloading renv ", version, " ... ", appendLF = FALSE) 252 | 253 | baseurl <- utils::contrib.url(repos = repos, type = type) 254 | ext <- if (identical(type, "source")) 255 | ".tar.gz" 256 | else if (Sys.info()[["sysname"]] == "Windows") 257 | ".zip" 258 | else 259 | ".tgz" 260 | name <- sprintf("renv_%s%s", version, ext) 261 | url <- paste(baseurl, name, sep = "/") 262 | 263 | destfile <- file.path(tempdir(), name) 264 | status <- tryCatch( 265 | renv_bootstrap_download_impl(url, destfile), 266 | condition = identity 267 | ) 268 | 269 | if (inherits(status, "condition")) { 270 | message("FAILED") 271 | return(FALSE) 272 | } 273 | 274 | # report success and return 275 | message("OK (downloaded ", type, ")") 276 | destfile 277 | 278 | } 279 | 280 | renv_bootstrap_download_cran_latest_find <- function(version) { 281 | 282 | # check whether binaries are supported on this system 283 | binary <- 284 | getOption("renv.bootstrap.binary", default = TRUE) && 285 | !identical(.Platform$pkgType, "source") && 286 | !identical(getOption("pkgType"), "source") && 287 | Sys.info()[["sysname"]] %in% c("Darwin", "Windows") 288 | 289 | types <- c(if (binary) "binary", "source") 290 | 291 | # iterate over types + repositories 292 | for (type in types) { 293 | for (repos in renv_bootstrap_repos()) { 294 | 295 | # retrieve package database 296 | db <- tryCatch( 297 | as.data.frame( 298 | utils::available.packages(type = type, repos = repos), 299 | stringsAsFactors = FALSE 300 | ), 301 | error = identity 302 | ) 303 | 304 | if (inherits(db, "error")) 305 | next 306 | 307 | # check for compatible entry 308 | entry <- db[db$Package %in% "renv" & db$Version %in% version, ] 309 | if (nrow(entry) == 0) 310 | next 311 | 312 | # found it; return spec to caller 313 | spec <- list(entry = entry, type = type, repos = repos) 314 | return(spec) 315 | 316 | } 317 | } 318 | 319 | # if we got here, we failed to find renv 320 | fmt <- "renv %s is not available from your declared package repositories" 321 | stop(sprintf(fmt, version)) 322 | 323 | } 324 | 325 | renv_bootstrap_download_cran_archive <- function(version) { 326 | 327 | name <- sprintf("renv_%s.tar.gz", version) 328 | repos <- renv_bootstrap_repos() 329 | urls <- file.path(repos, "src/contrib/Archive/renv", name) 330 | destfile <- file.path(tempdir(), name) 331 | 332 | message("* Downloading renv ", version, " ... ", appendLF = FALSE) 333 | 334 | for (url in urls) { 335 | 336 | status <- tryCatch( 337 | renv_bootstrap_download_impl(url, destfile), 338 | condition = identity 339 | ) 340 | 341 | if (identical(status, 0L)) { 342 | message("OK") 343 | return(destfile) 344 | } 345 | 346 | } 347 | 348 | message("FAILED") 349 | return(FALSE) 350 | 351 | } 352 | 353 | renv_bootstrap_download_tarball <- function(version) { 354 | 355 | # if the user has provided the path to a tarball via 356 | # an environment variable, then use it 357 | tarball <- Sys.getenv("RENV_BOOTSTRAP_TARBALL", unset = NA) 358 | if (is.na(tarball)) 359 | return() 360 | 361 | # allow directories 362 | if (dir.exists(tarball)) { 363 | name <- sprintf("renv_%s.tar.gz", version) 364 | tarball <- file.path(tarball, name) 365 | } 366 | 367 | # bail if it doesn't exist 368 | if (!file.exists(tarball)) { 369 | 370 | # let the user know we weren't able to honour their request 371 | fmt <- "* RENV_BOOTSTRAP_TARBALL is set (%s) but does not exist." 372 | msg <- sprintf(fmt, tarball) 373 | warning(msg) 374 | 375 | # bail 376 | return() 377 | 378 | } 379 | 380 | fmt <- "* Bootstrapping with tarball at path '%s'." 381 | msg <- sprintf(fmt, tarball) 382 | message(msg) 383 | 384 | tarball 385 | 386 | } 387 | 388 | renv_bootstrap_download_github <- function(version) { 389 | 390 | enabled <- Sys.getenv("RENV_BOOTSTRAP_FROM_GITHUB", unset = "TRUE") 391 | if (!identical(enabled, "TRUE")) 392 | return(FALSE) 393 | 394 | # prepare download options 395 | pat <- Sys.getenv("GITHUB_PAT") 396 | if (nzchar(Sys.which("curl")) && nzchar(pat)) { 397 | fmt <- "--location --fail --header \"Authorization: token %s\"" 398 | extra <- sprintf(fmt, pat) 399 | saved <- options("download.file.method", "download.file.extra") 400 | options(download.file.method = "curl", download.file.extra = extra) 401 | on.exit(do.call(base::options, saved), add = TRUE) 402 | } else if (nzchar(Sys.which("wget")) && nzchar(pat)) { 403 | fmt <- "--header=\"Authorization: token %s\"" 404 | extra <- sprintf(fmt, pat) 405 | saved <- options("download.file.method", "download.file.extra") 406 | options(download.file.method = "wget", download.file.extra = extra) 407 | on.exit(do.call(base::options, saved), add = TRUE) 408 | } 409 | 410 | message("* Downloading renv ", version, " from GitHub ... ", appendLF = FALSE) 411 | 412 | url <- file.path("https://api.github.com/repos/rstudio/renv/tarball", version) 413 | name <- sprintf("renv_%s.tar.gz", version) 414 | destfile <- file.path(tempdir(), name) 415 | 416 | status <- tryCatch( 417 | renv_bootstrap_download_impl(url, destfile), 418 | condition = identity 419 | ) 420 | 421 | if (!identical(status, 0L)) { 422 | message("FAILED") 423 | return(FALSE) 424 | } 425 | 426 | message("OK") 427 | return(destfile) 428 | 429 | } 430 | 431 | renv_bootstrap_install <- function(version, tarball, library) { 432 | 433 | # attempt to install it into project library 434 | message("* Installing renv ", version, " ... ", appendLF = FALSE) 435 | dir.create(library, showWarnings = FALSE, recursive = TRUE) 436 | 437 | # invoke using system2 so we can capture and report output 438 | bin <- R.home("bin") 439 | exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R" 440 | r <- file.path(bin, exe) 441 | 442 | args <- c( 443 | "--vanilla", "CMD", "INSTALL", "--no-multiarch", 444 | "-l", shQuote(path.expand(library)), 445 | shQuote(path.expand(tarball)) 446 | ) 447 | 448 | output <- system2(r, args, stdout = TRUE, stderr = TRUE) 449 | message("Done!") 450 | 451 | # check for successful install 452 | status <- attr(output, "status") 453 | if (is.numeric(status) && !identical(status, 0L)) { 454 | header <- "Error installing renv:" 455 | lines <- paste(rep.int("=", nchar(header)), collapse = "") 456 | text <- c(header, lines, output) 457 | writeLines(text, con = stderr()) 458 | } 459 | 460 | status 461 | 462 | } 463 | 464 | renv_bootstrap_platform_prefix <- function() { 465 | 466 | # construct version prefix 467 | version <- paste(R.version$major, R.version$minor, sep = ".") 468 | prefix <- paste("R", numeric_version(version)[1, 1:2], sep = "-") 469 | 470 | # include SVN revision for development versions of R 471 | # (to avoid sharing platform-specific artefacts with released versions of R) 472 | devel <- 473 | identical(R.version[["status"]], "Under development (unstable)") || 474 | identical(R.version[["nickname"]], "Unsuffered Consequences") 475 | 476 | if (devel) 477 | prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r") 478 | 479 | # build list of path components 480 | components <- c(prefix, R.version$platform) 481 | 482 | # include prefix if provided by user 483 | prefix <- renv_bootstrap_platform_prefix_impl() 484 | if (!is.na(prefix) && nzchar(prefix)) 485 | components <- c(prefix, components) 486 | 487 | # build prefix 488 | paste(components, collapse = "/") 489 | 490 | } 491 | 492 | renv_bootstrap_platform_prefix_impl <- function() { 493 | 494 | # if an explicit prefix has been supplied, use it 495 | prefix <- Sys.getenv("RENV_PATHS_PREFIX", unset = NA) 496 | if (!is.na(prefix)) 497 | return(prefix) 498 | 499 | # if the user has requested an automatic prefix, generate it 500 | auto <- Sys.getenv("RENV_PATHS_PREFIX_AUTO", unset = NA) 501 | if (auto %in% c("TRUE", "True", "true", "1")) 502 | return(renv_bootstrap_platform_prefix_auto()) 503 | 504 | # empty string on failure 505 | "" 506 | 507 | } 508 | 509 | renv_bootstrap_platform_prefix_auto <- function() { 510 | 511 | prefix <- tryCatch(renv_bootstrap_platform_os(), error = identity) 512 | if (inherits(prefix, "error") || prefix %in% "unknown") { 513 | 514 | msg <- paste( 515 | "failed to infer current operating system", 516 | "please file a bug report at https://github.com/rstudio/renv/issues", 517 | sep = "; " 518 | ) 519 | 520 | warning(msg) 521 | 522 | } 523 | 524 | prefix 525 | 526 | } 527 | 528 | renv_bootstrap_platform_os <- function() { 529 | 530 | sysinfo <- Sys.info() 531 | sysname <- sysinfo[["sysname"]] 532 | 533 | # handle Windows + macOS up front 534 | if (sysname == "Windows") 535 | return("windows") 536 | else if (sysname == "Darwin") 537 | return("macos") 538 | 539 | # check for os-release files 540 | for (file in c("/etc/os-release", "/usr/lib/os-release")) 541 | if (file.exists(file)) 542 | return(renv_bootstrap_platform_os_via_os_release(file, sysinfo)) 543 | 544 | # check for redhat-release files 545 | if (file.exists("/etc/redhat-release")) 546 | return(renv_bootstrap_platform_os_via_redhat_release()) 547 | 548 | "unknown" 549 | 550 | } 551 | 552 | renv_bootstrap_platform_os_via_os_release <- function(file, sysinfo) { 553 | 554 | # read /etc/os-release 555 | release <- utils::read.table( 556 | file = file, 557 | sep = "=", 558 | quote = c("\"", "'"), 559 | col.names = c("Key", "Value"), 560 | comment.char = "#", 561 | stringsAsFactors = FALSE 562 | ) 563 | 564 | vars <- as.list(release$Value) 565 | names(vars) <- release$Key 566 | 567 | # get os name 568 | os <- tolower(sysinfo[["sysname"]]) 569 | 570 | # read id 571 | id <- "unknown" 572 | for (field in c("ID", "ID_LIKE")) { 573 | if (field %in% names(vars) && nzchar(vars[[field]])) { 574 | id <- vars[[field]] 575 | break 576 | } 577 | } 578 | 579 | # read version 580 | version <- "unknown" 581 | for (field in c("UBUNTU_CODENAME", "VERSION_CODENAME", "VERSION_ID", "BUILD_ID")) { 582 | if (field %in% names(vars) && nzchar(vars[[field]])) { 583 | version <- vars[[field]] 584 | break 585 | } 586 | } 587 | 588 | # join together 589 | paste(c(os, id, version), collapse = "-") 590 | 591 | } 592 | 593 | renv_bootstrap_platform_os_via_redhat_release <- function() { 594 | 595 | # read /etc/redhat-release 596 | contents <- readLines("/etc/redhat-release", warn = FALSE) 597 | 598 | # infer id 599 | id <- if (grepl("centos", contents, ignore.case = TRUE)) 600 | "centos" 601 | else if (grepl("redhat", contents, ignore.case = TRUE)) 602 | "redhat" 603 | else 604 | "unknown" 605 | 606 | # try to find a version component (very hacky) 607 | version <- "unknown" 608 | 609 | parts <- strsplit(contents, "[[:space:]]")[[1L]] 610 | for (part in parts) { 611 | 612 | nv <- tryCatch(numeric_version(part), error = identity) 613 | if (inherits(nv, "error")) 614 | next 615 | 616 | version <- nv[1, 1] 617 | break 618 | 619 | } 620 | 621 | paste(c("linux", id, version), collapse = "-") 622 | 623 | } 624 | 625 | renv_bootstrap_library_root_name <- function(project) { 626 | 627 | # use project name as-is if requested 628 | asis <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT_ASIS", unset = "FALSE") 629 | if (asis) 630 | return(basename(project)) 631 | 632 | # otherwise, disambiguate based on project's path 633 | id <- substring(renv_bootstrap_hash_text(project), 1L, 8L) 634 | paste(basename(project), id, sep = "-") 635 | 636 | } 637 | 638 | renv_bootstrap_library_root <- function(project) { 639 | 640 | prefix <- renv_bootstrap_profile_prefix() 641 | 642 | path <- Sys.getenv("RENV_PATHS_LIBRARY", unset = NA) 643 | if (!is.na(path)) 644 | return(paste(c(path, prefix), collapse = "/")) 645 | 646 | path <- renv_bootstrap_library_root_impl(project) 647 | if (!is.null(path)) { 648 | name <- renv_bootstrap_library_root_name(project) 649 | return(paste(c(path, prefix, name), collapse = "/")) 650 | } 651 | 652 | renv_bootstrap_paths_renv("library", project = project) 653 | 654 | } 655 | 656 | renv_bootstrap_library_root_impl <- function(project) { 657 | 658 | root <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT", unset = NA) 659 | if (!is.na(root)) 660 | return(root) 661 | 662 | type <- renv_bootstrap_project_type(project) 663 | if (identical(type, "package")) { 664 | userdir <- renv_bootstrap_user_dir() 665 | return(file.path(userdir, "library")) 666 | } 667 | 668 | } 669 | 670 | renv_bootstrap_validate_version <- function(version) { 671 | 672 | loadedversion <- utils::packageDescription("renv", fields = "Version") 673 | if (version == loadedversion) 674 | return(TRUE) 675 | 676 | # assume four-component versions are from GitHub; 677 | # three-component versions are from CRAN 678 | components <- strsplit(loadedversion, "[.-]")[[1]] 679 | remote <- if (length(components) == 4L) 680 | paste("rstudio/renv", loadedversion, sep = "@") 681 | else 682 | paste("renv", loadedversion, sep = "@") 683 | 684 | fmt <- paste( 685 | "renv %1$s was loaded from project library, but this project is configured to use renv %2$s.", 686 | "Use `renv::record(\"%3$s\")` to record renv %1$s in the lockfile.", 687 | "Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library.", 688 | sep = "\n" 689 | ) 690 | 691 | msg <- sprintf(fmt, loadedversion, version, remote) 692 | warning(msg, call. = FALSE) 693 | 694 | FALSE 695 | 696 | } 697 | 698 | renv_bootstrap_hash_text <- function(text) { 699 | 700 | hashfile <- tempfile("renv-hash-") 701 | on.exit(unlink(hashfile), add = TRUE) 702 | 703 | writeLines(text, con = hashfile) 704 | tools::md5sum(hashfile) 705 | 706 | } 707 | 708 | renv_bootstrap_load <- function(project, libpath, version) { 709 | 710 | # try to load renv from the project library 711 | if (!requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) 712 | return(FALSE) 713 | 714 | # warn if the version of renv loaded does not match 715 | renv_bootstrap_validate_version(version) 716 | 717 | # execute renv load hooks, if any 718 | hooks <- getHook("renv::autoload") 719 | for (hook in hooks) 720 | if (is.function(hook)) 721 | tryCatch(hook(), error = warning) 722 | 723 | # load the project 724 | renv::load(project) 725 | 726 | TRUE 727 | 728 | } 729 | 730 | renv_bootstrap_profile_load <- function(project) { 731 | 732 | # if RENV_PROFILE is already set, just use that 733 | profile <- Sys.getenv("RENV_PROFILE", unset = NA) 734 | if (!is.na(profile) && nzchar(profile)) 735 | return(profile) 736 | 737 | # check for a profile file (nothing to do if it doesn't exist) 738 | path <- renv_bootstrap_paths_renv("profile", profile = FALSE, project = project) 739 | if (!file.exists(path)) 740 | return(NULL) 741 | 742 | # read the profile, and set it if it exists 743 | contents <- readLines(path, warn = FALSE) 744 | if (length(contents) == 0L) 745 | return(NULL) 746 | 747 | # set RENV_PROFILE 748 | profile <- contents[[1L]] 749 | if (!profile %in% c("", "default")) 750 | Sys.setenv(RENV_PROFILE = profile) 751 | 752 | profile 753 | 754 | } 755 | 756 | renv_bootstrap_profile_prefix <- function() { 757 | profile <- renv_bootstrap_profile_get() 758 | if (!is.null(profile)) 759 | return(file.path("profiles", profile, "renv")) 760 | } 761 | 762 | renv_bootstrap_profile_get <- function() { 763 | profile <- Sys.getenv("RENV_PROFILE", unset = "") 764 | renv_bootstrap_profile_normalize(profile) 765 | } 766 | 767 | renv_bootstrap_profile_set <- function(profile) { 768 | profile <- renv_bootstrap_profile_normalize(profile) 769 | if (is.null(profile)) 770 | Sys.unsetenv("RENV_PROFILE") 771 | else 772 | Sys.setenv(RENV_PROFILE = profile) 773 | } 774 | 775 | renv_bootstrap_profile_normalize <- function(profile) { 776 | 777 | if (is.null(profile) || profile %in% c("", "default")) 778 | return(NULL) 779 | 780 | profile 781 | 782 | } 783 | 784 | renv_bootstrap_path_absolute <- function(path) { 785 | 786 | substr(path, 1L, 1L) %in% c("~", "/", "\\") || ( 787 | substr(path, 1L, 1L) %in% c(letters, LETTERS) && 788 | substr(path, 2L, 3L) %in% c(":/", ":\\") 789 | ) 790 | 791 | } 792 | 793 | renv_bootstrap_paths_renv <- function(..., profile = TRUE, project = NULL) { 794 | renv <- Sys.getenv("RENV_PATHS_RENV", unset = "renv") 795 | root <- if (renv_bootstrap_path_absolute(renv)) NULL else project 796 | prefix <- if (profile) renv_bootstrap_profile_prefix() 797 | components <- c(root, renv, prefix, ...) 798 | paste(components, collapse = "/") 799 | } 800 | 801 | renv_bootstrap_project_type <- function(path) { 802 | 803 | descpath <- file.path(path, "DESCRIPTION") 804 | if (!file.exists(descpath)) 805 | return("unknown") 806 | 807 | desc <- tryCatch( 808 | read.dcf(descpath, all = TRUE), 809 | error = identity 810 | ) 811 | 812 | if (inherits(desc, "error")) 813 | return("unknown") 814 | 815 | type <- desc$Type 816 | if (!is.null(type)) 817 | return(tolower(type)) 818 | 819 | package <- desc$Package 820 | if (!is.null(package)) 821 | return("package") 822 | 823 | "unknown" 824 | 825 | } 826 | 827 | renv_bootstrap_user_dir <- function() { 828 | dir <- renv_bootstrap_user_dir_impl() 829 | path.expand(chartr("\\", "/", dir)) 830 | } 831 | 832 | renv_bootstrap_user_dir_impl <- function() { 833 | 834 | # use local override if set 835 | override <- getOption("renv.userdir.override") 836 | if (!is.null(override)) 837 | return(override) 838 | 839 | # use R_user_dir if available 840 | tools <- asNamespace("tools") 841 | if (is.function(tools$R_user_dir)) 842 | return(tools$R_user_dir("renv", "cache")) 843 | 844 | # try using our own backfill for older versions of R 845 | envvars <- c("R_USER_CACHE_DIR", "XDG_CACHE_HOME") 846 | for (envvar in envvars) { 847 | root <- Sys.getenv(envvar, unset = NA) 848 | if (!is.na(root)) 849 | return(file.path(root, "R/renv")) 850 | } 851 | 852 | # use platform-specific default fallbacks 853 | if (Sys.info()[["sysname"]] == "Windows") 854 | file.path(Sys.getenv("LOCALAPPDATA"), "R/cache/R/renv") 855 | else if (Sys.info()[["sysname"]] == "Darwin") 856 | "~/Library/Caches/org.R-project.R/R/renv" 857 | else 858 | "~/.cache/R/renv" 859 | 860 | } 861 | 862 | 863 | renv_json_read <- function(file = NULL, text = NULL) { 864 | 865 | jlerr <- NULL 866 | 867 | # if jsonlite is loaded, use that instead 868 | if ("jsonlite" %in% loadedNamespaces()) { 869 | 870 | json <- catch(renv_json_read_jsonlite(file, text)) 871 | if (!inherits(json, "error")) 872 | return(json) 873 | 874 | jlerr <- json 875 | 876 | } 877 | 878 | # otherwise, fall back to the default JSON reader 879 | json <- catch(renv_json_read_default(file, text)) 880 | if (!inherits(json, "error")) 881 | return(json) 882 | 883 | # report an error 884 | if (!is.null(jlerr)) 885 | stop(jlerr) 886 | else 887 | stop(json) 888 | 889 | } 890 | 891 | renv_json_read_jsonlite <- function(file = NULL, text = NULL) { 892 | text <- paste(text %||% read(file), collapse = "\n") 893 | jsonlite::fromJSON(txt = text, simplifyVector = FALSE) 894 | } 895 | 896 | renv_json_read_default <- function(file = NULL, text = NULL) { 897 | 898 | # find strings in the JSON 899 | text <- paste(text %||% read(file), collapse = "\n") 900 | pattern <- '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' 901 | locs <- gregexpr(pattern, text, perl = TRUE)[[1]] 902 | 903 | # if any are found, replace them with placeholders 904 | replaced <- text 905 | strings <- character() 906 | replacements <- character() 907 | 908 | if (!identical(c(locs), -1L)) { 909 | 910 | # get the string values 911 | starts <- locs 912 | ends <- locs + attr(locs, "match.length") - 1L 913 | strings <- substring(text, starts, ends) 914 | 915 | # only keep those requiring escaping 916 | strings <- grep("[[\\]{}:]", strings, perl = TRUE, value = TRUE) 917 | 918 | # compute replacements 919 | replacements <- sprintf('"\032%i\032"', seq_along(strings)) 920 | 921 | # replace the strings 922 | mapply(function(string, replacement) { 923 | replaced <<- sub(string, replacement, replaced, fixed = TRUE) 924 | }, strings, replacements) 925 | 926 | } 927 | 928 | # transform the JSON into something the R parser understands 929 | transformed <- replaced 930 | transformed <- gsub("{}", "`names<-`(list(), character())", transformed, fixed = TRUE) 931 | transformed <- gsub("[[{]", "list(", transformed, perl = TRUE) 932 | transformed <- gsub("[]}]", ")", transformed, perl = TRUE) 933 | transformed <- gsub(":", "=", transformed, fixed = TRUE) 934 | text <- paste(transformed, collapse = "\n") 935 | 936 | # parse it 937 | json <- parse(text = text, keep.source = FALSE, srcfile = NULL)[[1L]] 938 | 939 | # construct map between source strings, replaced strings 940 | map <- as.character(parse(text = strings)) 941 | names(map) <- as.character(parse(text = replacements)) 942 | 943 | # convert to list 944 | map <- as.list(map) 945 | 946 | # remap strings in object 947 | remapped <- renv_json_remap(json, map) 948 | 949 | # evaluate 950 | eval(remapped, envir = baseenv()) 951 | 952 | } 953 | 954 | renv_json_remap <- function(json, map) { 955 | 956 | # fix names 957 | if (!is.null(names(json))) { 958 | lhs <- match(names(json), names(map), nomatch = 0L) 959 | rhs <- match(names(map), names(json), nomatch = 0L) 960 | names(json)[rhs] <- map[lhs] 961 | } 962 | 963 | # fix values 964 | if (is.character(json)) 965 | return(map[[json]] %||% json) 966 | 967 | # handle true, false, null 968 | if (is.name(json)) { 969 | text <- as.character(json) 970 | if (text == "true") 971 | return(TRUE) 972 | else if (text == "false") 973 | return(FALSE) 974 | else if (text == "null") 975 | return(NULL) 976 | } 977 | 978 | # recurse 979 | if (is.recursive(json)) { 980 | for (i in seq_along(json)) { 981 | json[i] <- list(renv_json_remap(json[[i]], map)) 982 | } 983 | } 984 | 985 | json 986 | 987 | } 988 | 989 | # load the renv profile, if any 990 | renv_bootstrap_profile_load(project) 991 | 992 | # construct path to library root 993 | root <- renv_bootstrap_library_root(project) 994 | 995 | # construct library prefix for platform 996 | prefix <- renv_bootstrap_platform_prefix() 997 | 998 | # construct full libpath 999 | libpath <- file.path(root, prefix) 1000 | 1001 | # attempt to load 1002 | if (renv_bootstrap_load(project, libpath, version)) 1003 | return(TRUE) 1004 | 1005 | # load failed; inform user we're about to bootstrap 1006 | prefix <- paste("# Bootstrapping renv", version) 1007 | postfix <- paste(rep.int("-", 77L - nchar(prefix)), collapse = "") 1008 | header <- paste(prefix, postfix) 1009 | message(header) 1010 | 1011 | # perform bootstrap 1012 | bootstrap(version, libpath) 1013 | 1014 | # exit early if we're just testing bootstrap 1015 | if (!is.na(Sys.getenv("RENV_BOOTSTRAP_INSTALL_ONLY", unset = NA))) 1016 | return(TRUE) 1017 | 1018 | # try again to load 1019 | if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) { 1020 | message("* Successfully installed and loaded renv ", version, ".") 1021 | return(renv::load()) 1022 | } 1023 | 1024 | # failed to download or load renv; warn the user 1025 | msg <- c( 1026 | "Failed to find an renv installation: the project will not be loaded.", 1027 | "Use `renv::activate()` to re-initialize the project." 1028 | ) 1029 | 1030 | warning(paste(msg, collapse = "\n"), call. = FALSE) 1031 | 1032 | }) 1033 | -------------------------------------------------------------------------------- /renv/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "bioconductor.version": null, 3 | "external.libraries": [], 4 | "ignored.packages": [], 5 | "package.dependency.fields": [ 6 | "Imports", 7 | "Depends", 8 | "LinkingTo" 9 | ], 10 | "r.version": null, 11 | "snapshot.type": "implicit", 12 | "use.cache": true, 13 | "vcs.ignore.cellar": true, 14 | "vcs.ignore.library": true, 15 | "vcs.ignore.local": true, 16 | "vcs.manage.ignores": true 17 | } 18 | -------------------------------------------------------------------------------- /session-break-slide.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to Git and GitHub" 3 | subtitle: "Session - Break" 4 | execute: 5 | echo: false 6 | eval: true 7 | --- 8 | 9 | ```{r} 10 | #| label: "libs" 11 | #| include: false 12 | #| eval: true 13 | #| echo: false 14 | library(countdown) 15 | ``` 16 | 17 | ```{r} 18 | countdown::countdown(minutes = 10, 19 | color_border = "#005EB8", 20 | color_text = "#005EB8", 21 | color_running_text = "white", 22 | color_running_background = "#005EB8", 23 | color_finished_text = "#005EB8", 24 | color_finished_background = "white", 25 | margin = "0.9em", 26 | font_size = "2em") 27 | ``` 28 | 29 | -------------------------------------------------------------------------------- /session-commit-main.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to Git and GitHub" 3 | subtitle: "Session - Commit to main (and undo last commit!)" 4 | --- 5 | 6 | ## Not recommended, but sometimes useful 7 | 8 | The `pr_*` functions all relate to Pull Requests but it is possible to commit to main directly 9 | 10 | Commit work using 11 | 12 | ```{r} 13 | gert::git_commit_all("This is a message") 14 | 15 | # or 16 | 17 | gert::git_add("file.qmd") 18 | gert::git_commit("This is a message") 19 | 20 | ``` 21 | 22 | and then use the `Push` button in the Git RStudio pane 23 | 24 | ## Accidental commits! 25 | 26 | If you commit by accident to any branch, but particularly `main`, you can undo the last commit 27 | 28 | In fact, you can undo any number of last commits! 29 | 30 | This has to be done in the `Terminal` though ($)! 31 | 32 | ```{bash} 33 | git reset --soft HEAD~1 34 | ``` 35 | 36 | :::{.callout-warning collapse=false appearance='default' icon=true} 37 | ## Resetting doesn't delete 38 | Be careful if you are trying to undo something sensitive, a reset is not a deletion 39 | ::: 40 | 41 | ## Moving changes from one branch to another 42 | 43 | What if you've made a few changes that you want to keep but committed to `main`? 44 | 45 | - In RStudio create a new branch (which will have all the changes) 46 | - Return to `main` 47 | - Use the `terminal` to reset the commits you don't want 48 | 49 | ## End session 50 | -------------------------------------------------------------------------------- /session-conflict.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to Git and GitHub" 3 | subtitle: "Session - Conflicts!" 4 | --- 5 | 6 | ## Conflicts! 7 | 8 | Conflicts can happen when you merge a branch and can occur when working with others, or even yourself! 9 | 10 | Let's create a conflict... 11 | 12 | ## Your Turn 13 | 14 | 1. `usethis::pr_init("author_change")` 15 | 2. Replace the author in the Quarto YAML with `author: Person A` and Render 16 | 3. `gert::git_commit_all("Added Person A as author")` 17 | 4. `usethis::pr_push()` 18 | 5. In GitHub create a pull request to `main` using `Merge pull request` and do the merge 19 | 20 | ::: {.callout-warning collapse="false" appearance="default" icon="true"} 21 | ## Not pulling from `main` 22 | 23 | We'll miss the `pr_finish()` part because this function reduces the possibility of conflict as it `pulls` changes made on `main` 24 | ::: 25 | 26 | ## Together we will... 27 | 28 | ... create another branch in RStudio, not {usethis}, as we miss the steps that reduce conflicts: 29 | 30 | 1. Go to the `main` branch using the RStudio Git pane 31 | 2. Create a branch in that pane using the button next to `person-b` 32 | 3. Replace the author in the Quarto YAML with `author: Person B` and Render 33 | 4. Tick the box next to the file and commit using the Git pane in RStudio 34 | 5. Push the changes using RStudio Git pane (the button is not greyed out) 35 | 6. In GitHub create a pull request to `main` using `Merge pull request` and do the merge 36 | 37 | ## Conflict in GitHub! 38 | 39 | ![](img/github_conflict.PNG){fig-alt="Screenshot of GitHub merge conflict with the Resolve Conflict grey section of the Pull Request"} 40 | 41 | ## Looking for the symbols 42 | 43 | To resolve the conflict we need to edit (in this case delete) one of the names and also delete all the merge text: 44 | 45 | ``` markdown 46 | <<<<<< person-b 47 | ======= 48 | >>>>>> main 49 | ``` 50 | This can be done in GitHub and ends with a new commit. 51 | 52 | ## Seeing the conflict locally 53 | 54 | To see the same conflicted files locally: 55 | 56 | 1. On the branch with the conflict (`person-b`) 57 | 1. Go to the `Console` ($) and type `usethis::pr_merge_main()` 58 | 59 | . . . 60 | 61 | ```markdown 62 | ✔ Pushing local 'author_change' branch to 'origin/author_change'. 63 | • Create PR at link given below 64 | ✔ Opening URL 'https://github.com/Letxuga007/project/compare/author_change' 65 | > usethis::pr_merge_main() 66 | ✔ Pulling changes from 'origin/main'. 67 | Merge has resulted in merge conflict(s). 68 | There are 1 conflicted files: 69 | * 'my_report.qmd' 70 | Are you ready to sort this out? 71 | If so, we will open the conflicted files for you to edit. 72 | 73 | 1: Yes, I'm ready to resolve the merge conflicts. 74 | 2: No, I want to abort this merge. 75 | 76 | Selection: 77 | ``` 78 | 79 | ## End session 80 | -------------------------------------------------------------------------------- /session-fork-clone.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to Git and GitHub" 3 | subtitle: "Session - Getting copies of existing repositories (fork and clone)" 4 | --- 5 | 6 | ## Existing repositories 7 | 8 | All this course has been about you creating a new repository but what about collaboration with existing projects? 9 | 10 | ::: incremental 11 | - your own repository on a new computer (clone) 12 | - a repository from your team which you are a member (clone) 13 | - a repository from someone or somewhere that you don't have rights to change (fork) 14 | ::: 15 | 16 | . . . 17 | 18 | ```{r} 19 | usethis::create_from_github(repo_spec = "nhs-r-community/r4ds-ed2-exercise-solutions") 20 | ``` 21 | 22 | ::: {.callout-warning collapse="false" appearance="default" icon="true"} 23 | ## Cloud specific folder structure 24 | 25 | On Posit Cloud the project gets saved in \`Cloud\> home \> r99999 (similar) \> r4ds-ed2-exercise-solutions 26 | ::: 27 | 28 | ## The benefits of {usethis} 29 | 30 | Using the function `create_from_github()` means that it: 31 | 32 | - Automatically checks if this would be a clone or a fork! 33 | - Automatically goes to the main working directory, mine is in `C:/Users/zoe.turner` 34 | - Opens up a new RStudio session 35 | 36 | ## Clone (access) and Fork (no access) 37 | 38 | Cloned message: 39 | 40 | ``` markdown 41 | ✔ Setting `fork = FALSE` 42 | ✔ Creating 'C:/Users/zoe.turner/r4ds-ed2-exercise-solutions/' 43 | ✔ Cloning repo from 'https://github.com/nhs-r-community/r4ds-ed2-exercise-solutions.git' into 'C:/Users/zoe.turner/r4ds-ed2-exercise-solutions' 44 | ✔ Setting active project to 'C:/Users/zoe.turner/r4ds-ed2-exercise-solutions' 45 | ℹ Default branch is 'main' 46 | ✔ Opening 'C:/Users/zoe.turner/r4ds-ed2-exercise-solutions/' in new RStudio session 47 | ✔ Setting active project to '' 48 | ``` 49 | 50 | . . . 51 | 52 | Forked message (will also appear in your GitHub): 53 | 54 | ``` markdown 55 | ✔ Setting `fork = TRUE` 56 | ✔ Creating 'C:/Users/zoe.turner/nhspy-plotthedots/' 57 | ✔ Forking 'nhs-pycom/nhspy-plotthedots' 58 | ✔ Waiting for the fork to finalize before cloning 59 | ✔ Cloning repo from 'https://github.com/Lextuga007/nhspy-plotthedots.git' into 'C:/Users/zoe.turner/nhspy-plotthedots' 60 | ✔ Setting active project to 'C:/Users/zoe.turner/nhspy-plotthedots' 61 | ℹ Default branch is 'main' 62 | ✔ Adding 'upstream' remote: 'https://github.com/nhs-pycom/nhspy-plotthedots.git' 63 | ✔ Pulling changes from 'upstream/main'. 64 | ✔ Setting remote tracking branch for local 'main' branch to 'upstream/main' 65 | ✔ Writing 'nhspy-plotthedots.Rproj' 66 | ✔ Adding '.Rproj.user' to '.gitignore' 67 | ✔ Opening 'C:/Users/zoe.turner/nhspy-plotthedots/' in new RStudio session 68 | ✔ Setting active project to '' 69 | ``` 70 | 71 | ## Alternatives - Cloning in GitHub 72 | 73 | Select the green button for `<> Code` and it will give you an option to clone 74 | 75 | This course has used `https` and the copy button to the right takes the whole code 76 | 77 | ![](img/show-clone-github.PNG){fig-alt="Screenshot of the GitHub code menu extended to see the Clone, Open with GitHub Desktop and Download ZIP options"} 78 | 79 | ## Forking in GitHub - then needs Cloning! 80 | 81 | `Fork` to your own repository and then `Clone` from there to your computer: 82 | 83 | ![](img/show-fork-github.PNG){fig-alt="Screenshot of GitHub with the Fork link highlighted"} 84 | 85 | ## In RStudio 86 | 87 | With the copied HTTPS url, in RStudio you will need to start a new Project and use the third option (possibly ignored until now!) for versioning: 88 | 89 | ![](img/new-project-wizard.PNG){fig-alt="Screenshot of the 3 options wizard in RStudio for creating a new project"} 90 | 91 | ::: {.callout-warning collapse="false" appearance="default" icon="true"} 92 | ## Posit Cloud is already a project! 93 | 94 | - Creating a project on the Cloud isn't possible because **it is** a project 95 | - Even in RStudio it's not possible to put a project in another project. 96 | ::: 97 | 98 | ## End session 99 | -------------------------------------------------------------------------------- /session-intro.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to Git and GitHub" 3 | subtitle: "Session - Introduction" 4 | execute: 5 | echo: false 6 | --- 7 | 8 | ## Opinionated Course Aims 9 | 10 | ::: incremental 11 | - To set up Git and GitHub using R and RStudio 12 | - To practice a few workflows scenarios (but not all) 13 | - To reassure that mistakes will happen and that's a feature of Git 14 | - [Turn around your Git mistakes in 17 ways](https://dev.to/smitterhane/turn-around-your-git-mistakes-in-17-ways-2mn1) 15 | The following **comes with a language warning!** 16 | - [Oh Shit, Git!?!](https://ohshitgit.com/) 17 | ::: 18 | 19 | ## Agenda - session one (about 3.5 hours) 20 | 21 | Chapter overview 22 | 23 | ::: {.fragment .fade-in} 24 | Check prework set up and Introduction 25 | ::: 26 | 27 | ::: {.fragment .fade-in} 28 | Setting up 29 | ::: 30 | 31 | ::: {.fragment .fade-in} 32 | --------- Break ----------- 33 | ::: 34 | 35 | ::: {.fragment .fade-in} 36 | Version Control 37 | ::: 38 | 39 | ::: {.fragment .fade-in} 40 | 41 | Workflow 42 | ::: 43 | 44 | ::: {.fragment .fade-in} 45 | --------- Course end ----------- 46 | ::: 47 | 48 | 49 | ## Agenda - session two (about 3.5 hours) 50 | 51 | Chapter overview 52 | 53 | ::: {.fragment .fade-in} 54 | Useing R packages {gert} and {usethis} 55 | ::: 56 | 57 | ::: {.fragment .fade-in} 58 | Merge conflict! 59 | ::: 60 | 61 | ::: {.fragment .fade-in} 62 | --------- Break ----------- 63 | ::: 64 | 65 | ::: {.fragment .fade-in} 66 | Commit to main (and undo last commit!) 67 | ::: 68 | 69 | ::: {.fragment .fade-in} 70 | Undo last merge 71 | ::: 72 | 73 | ::: {.fragment .fade-in} 74 | --------- Course end --------- 75 | ::: 76 | 77 | 78 | ## This is not a definitive course 79 | 80 | ::: incremental 81 | - Like learning anything, you don't get "everything" all at once 82 | - There are many workflows that are possible but we can only learn a few in this workshop 83 | - This will get you started! 84 | ::: 85 | 86 | ## End session 87 | -------------------------------------------------------------------------------- /session-prework.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to Git and GitHub" 3 | subtitle: "Session - Prework for a computer" 4 | --- 5 | 6 | ## Check Git 7 | 8 | Check if Git is already installed. Run the following in the *Terminal* (not the RStudio Console!) 9 | 10 | ``` 11 | which git 12 | ``` 13 | 14 | Check the version of your Git 15 | 16 | ``` 17 | git --version 18 | ``` 19 | 20 | If asked to install the Xcode command line tools, say yes! 21 | Right click to copy on a Terminal line 22 | 23 | ## Downloading Git 24 | 25 | - Download the installer from [https://git-scm.com/downloads](https://git-scm.com/downloads) 26 | - Run keeping all the default settings. 27 | 28 | :::{.callout-note collapse=false appearance='default' icon=true} 29 | ## Installer hangs at 100% 30 | 31 | If the installer hangs with the progress bar at 100%, close the installer with Task Manager (press `Ctrl + Alt + Delete`; 32 | select Task Manager; 33 | find Git for Windows installer and close). 34 | ::: 35 | 36 | 37 | ## Connecting RStudio to Git 38 | 39 | - Open RStudio 40 | - In the menus go to `Tools > Global Options > Git/SVN` 41 | - Check RStudio has found Git under "Git executable:" 42 | 43 | You may need to click `Browse` and find the Git executable 44 | 45 | :::{.callout-note collapse=false appearance='default' icon=true} 46 | ## Where to find the git.exe 47 | It may be under `C:\Users\username\AppData\Local\Programs\Git\` - remember if file extensions are hidden it will show as git rather than git.exe. 48 | Restart RStudio before trying to use git. 49 | ::: 50 | 51 | 52 | ## GitHub 53 | 54 | Register a GitHub account at [github.com](https://github.com/). 55 | 56 | - Suggest to incorporate your actual name/reuse your username from other contexts (like Social Media) 57 | - Pick a username you will be comfortable revealing to your boss 58 | - Shorter is better 59 | - Be as unique as possible in as few characters as possible 60 | - Make it timeless 61 | - Avoid words laden with special meaning in programming 62 | - Use all lower case letters 63 | 64 | ## Think about security 65 | 66 | Particularly for GitHub and your own account safety 67 | 68 | Set up [2FA (two-factor authentication)](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication) using an app or save the generated code 69 | 70 | ## Install packages 71 | 72 | The following packages are required for the course: 73 | 74 | ```{r} 75 | install.packages("gert") 76 | install.packages("usethis") 77 | install.packages("gitcreds") 78 | ``` 79 | 80 | 81 | ## End session 82 | 83 | # Acknowledgements 84 | 85 | These slides were designed by Mine Çetinkaya-Rundel and Emma Rand for the Forwards Package development module course 86 | 87 | [Your first package](https://forwards.github.io/workshops/package-dev-modules/slides/03-your-first-package/your-first-package.html#1) and 88 | [Setting up your system](https://forwards.github.io/workshops/package-dev-modules/slides/02-setting-up-system/setting-up-system.html#1) -------------------------------------------------------------------------------- /session-pull-requests.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to Git and GitHub" 3 | subtitle: "Session - Pull Requests" 4 | --- 5 | 6 | ## Pushing to the remote (GitHub) 7 | 8 | We want to `push` the copy branch to GitHub, make a `pull request` to `merge` into main 9 | 10 | ```{r} 11 | usethis::pr_push() 12 | ``` 13 | 14 | This open the pull request in GitHub/a browser, select the `Create Pull Request` button 15 | 16 | ::: {.callout-note collapse="false" appearance="default" icon="true"} 17 | ## Draft pull requests 18 | 19 | - For public repositories it's possible to change the pull request to a draft. 20 | - In GitHub click on the down arrow on the green button for `Create pull request` and select Draft 21 | - Click the green button again to make the pull request 22 | ::: 23 | 24 | ## Extra unnecessary step? 25 | 26 | ::: incremental 27 | - Creating a pull request to the `main` branch can be seen as an extra step, particularly when you are working alone 28 | - But if you are working with others or the main is a *clean* working branch you need to protect it 29 | - Pull requests will be where your *merge conflicts* will be highlighted 30 | - People can see you are working on things 31 | - You have a remote copy of your work if anything were to happen to your local computer! 32 | - Reverting (undoing) a pull request is really easy in GitHub, even more so if you have a lot of commits 33 | ::: 34 | 35 | ## Options to merge - default 36 | 37 | There are three options the default being 38 | 39 | `Create a merge commit` creates a new `merge commit` which isn't very descriptive in the name 40 | 41 | > Merge pull request #1 from Letxuga007/new_work 42 | 43 | but is recommended as an easier way to debug for when things get muddled 44 | 45 | ## Squashing 46 | 47 | `Squash and merge` details multiple commits in one 48 | 49 | > New work (#1) \* First commit for quarto document \* Removed author 50 | 51 | which is a nice way to keep all the commit messages but messages can get long 52 | 53 | ::: {.callout-tip collapse="false" appearance="default" icon="true"} 54 | ## Squashing 55 | 56 | - Atomic committing is a practice in Git versioning where each distinct step is committed 57 | - Squashing is only used in this this practice if things are very closely related:\ 58 | \# updated titles\ 59 | \# renamed titles\ 60 | \# correct spelling in title 61 | ::: 62 | 63 | ## Rebase 64 | 65 | `Rebase and merge` keeps all the commits as you created them in a linear way 66 | 67 | The history is more readable but can be tougher to resolve conflicts 68 | 69 | ![Screenshot of the commits from a rebase merge](img/rebase_commit_history.PNG) 70 | 71 | ::: notes 72 | When to use merge versus rebase https://www.gitkraken.com/learn/git/problems/git-rebase-vs-merge 73 | 74 | Rebase seems to be incredibly useful if there are many people working on a project and can see the branches in a visual way. GitHub only presents commits in a linear way anyway so this may not be necessary for many analytical type repositories. 75 | ::: 76 | 77 | ## Let's pause! 78 | 79 | Sometimes you need to go back to `main` to get changes from colleagues or create a new branch: 80 | 81 | ```{r} 82 | usethis::pr_pause() 83 | ``` 84 | 85 | This does a few things 86 | 87 | ``` markdown 88 | ✔ Setting active project to '/cloud/project' 89 | ✔ Switching back to the default branch. 90 | ✔ Checking that local branch 'new_work' has the changes in 'origin/new_work' 91 | ✔ Switching back to default branch ('main'). 92 | ✔ Pulling changes from 'origin/main' 93 | ``` 94 | 95 | ## Resuming your PR 96 | 97 | First find the PR to work on: 98 | 99 | ```{r} 100 | usethis::pr_fetch() 101 | ``` 102 | 103 | Gives you details of what is open as a PR: 104 | 105 | ``` markdown 106 | ✔ Setting active project to '/cloud/project' 107 | ℹ No PR specified ... looking up open PRs. 108 | Which PR are you interested in? (0 to exit) 109 | 110 | 1: #1 (@Letxuga007): 'New work' 111 | ``` 112 | 113 | . . . 114 | 115 | To resume then select the number or if you know the PR before then 116 | 117 | ```{r} 118 | usethis::pr_fetch(1) 119 | ``` 120 | 121 | ## Finish with the PR 122 | 123 | - If the PR is set to Draft then, in GitHub, set to review 124 | - If the PR was not a Draf the button `Merge pull request` will be available straight away 125 | - Return to RStudio and type 126 | 127 | ```{r} 128 | usethis::pr_finish() 129 | ``` 130 | 131 | Several things gets tidied up all in one function 132 | 133 | . . . 134 | 135 | ``` markdown 136 | ✔ Switching back to default branch ('main'). 137 | ✔ Pulling changes from 'origin/main' 138 | ✔ Deleting local 'new_work' branch. 139 | ✔ PR 'Letxuga007/project/#1' has been merged, deleting remote branch 'origin/new_work' 140 | ``` 141 | ## You might want to discard a PR 142 | 143 | If you are working on something and change your mind 144 | 145 | ```{r} 146 | usethis::pr_forget() 147 | ``` 148 | 149 | when in the branch you want to discard: 150 | 151 | ```markdown 152 | ✔ Switching back to default branch ('main'). 153 | ✔ Pulling changes from 'origin/main' 154 | ✔ Deleting local 'mistake-branch' branch. 155 | ``` 156 | 157 | :::{.callout-note collapse=false appearance='default' icon=true} 158 | ## PR needs to be tidied in GitHub 159 | - Because local is different to remote you will need to close any PR on GitHub 160 | ::: 161 | 162 | ## Local and remote branches 163 | 164 | Local and Remote branches are distinct things so although `new_work` branch has been deleted and the remote has been merged, the connection in RStudio remains 165 | 166 | ![](img/branch-link-rstudio.PNG){fig-alt="Screenshot of the drop down of branches in the RStudio git pane where under the greyed out (REMOTE: ORIGIN) new_work can be seen"} 167 | 168 | To tidy, in the Terminal type: 169 | 170 | ```{bash} 171 | git remote prune origin 172 | ``` 173 | 174 | ## End session 175 | 176 | ## Acknowledgements 177 | 178 | [Happy Git and GitHub](https://happygitwithr.com/) for the useR by Jenny Bryan 179 | 180 | [Pull Request Flow with usethis](https://www.garrickadenbuie.com/blog/pull-request-flow-usethis/?interactive=) by Garrick Aden-Buie 181 | 182 | ## End session 183 | 184 | ## Acknowledgements 185 | 186 | [Happy Git and GitHub](https://happygitwithr.com/) for the useR by Jenny Bryan 187 | 188 | [Pull Request Flow with usethis](https://www.garrickadenbuie.com/blog/pull-request-flow-usethis/?interactive=) by Garrick Aden-Buie 189 | -------------------------------------------------------------------------------- /session-setup.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to Git and GitHub" 3 | subtitle: "Session - Getting started with Git and GitHub" 4 | --- 5 | 6 | ## Configure Git 7 | 8 | Configure `user.name` and `user.email` 9 | 10 | ```{r} 11 | library(usethis) 12 | usethis::use_git_config( 13 | user.name = "github_name", # Make sure this matches your GitHub account 14 | user.email = "jane@example.com" # Use the email associated with GitHub account 15 | ) 16 | ``` 17 | 18 | ## Check Git configuration 19 | 20 | Ask for a **sit**uation **rep**ort. 21 | 22 | ```{r} 23 | usethis::git_sitrep() 24 | ``` 25 | 26 | A lot of information will appear in the RStudio Console! 27 | 28 | . . . 29 | 30 | ``` 31 | Git config (global) 32 | • Name: 33 | • Email: 34 | • Global (user-level) gitignore file: 35 | • Vaccinated: FALSE 36 | ℹ See `?git_vaccinate` to learn more 37 | ℹ Defaulting to 'https' Git protocol 38 | • Default Git protocol: 'https' 39 | • Default initial branch name: 40 | GitHub 41 | • Default GitHub host: 'https://github.com' 42 | • Personal access token for 'https://github.com': 43 | • To create a personal access token, call `create_github_token()` 44 | • To store a token for current and future use, call `gitcreds::gitcreds_set()` 45 | ℹ Read more in the 'Managing Git(Hub) Credentials' article: 46 | https://usethis.r-lib.org/articles/articles/git-credentials.html 47 | Git repo for current project 48 | • Active usethis project: '/cloud/project' 49 | ℹ Active project is not a Git repo 50 | ``` 51 | 52 | ## Vaccinate 53 | 54 | ```{r} 55 | usethis::git_vaccinate() 56 | ``` 57 | 58 | . . . 59 | 60 | Adds .DS_Store, .Rproj.user, .Rdata, .Rhistory, and .httr-oauth to your global (a.k.a. user-level) .gitignore. This is good practice as it decreases the chance that you will accidentally leak credentials to GitHub. git_vaccinate() also tries to detect and fix the situation where you have a global gitignore file, but it's missing from your global Git config. 61 | 62 | ## Personal access token 63 | 64 | - Communicating with GitHub will require authentication 65 | 66 | - Instead of typing in your username and password each time, use a **PAT** (personal access token) 67 | 68 | ## Create a PAT 69 | 70 | - To amend/delete existing tokens go to: [https://github.com/settings/tokens](https://github.com/settings/tokens) 71 | - Give the token a descriptive name like `connect-posit-github` 72 | - Copy and also store this token somewhere (you won't be able to see it again!) 73 | 74 | ```{r} 75 | usethis::create_github_token() 76 | ``` 77 | 78 | :::{.callout-warning collapse=false appearance='default' icon=true} 79 | ## PAT tokens on the cloud 80 | - These will get deleted automatically at regular intervals 81 | - For the purpose of the course this will need to be added a few times! 82 | ::: 83 | 84 | 85 | ## Store your PAT 86 | 87 | When you use the following code you'll get a prompt, copy the token with no quotes. 88 | 89 | ```{r} 90 | gitcreds::gitcreds_set() 91 | ``` 92 | 93 | :::{.callout-note collapse=false appearance='default' icon=true} 94 | ## Deleting a PAT 95 | If you are using the Cloud or want to delete the PAT from your system use `gitcreds::gitcreds_delete()` 96 | ::: 97 | 98 | ## Starting Git from an existing project 99 | 100 | To make our project a Git repository, or 'repo' on our local machine we use 101 | 102 | ```{r} 103 | usethis::use_git() 104 | ``` 105 | 106 | :::{.callout-note collapse=false appearance='default' icon=true} 107 | ## A word on R Projects 108 | - Git needs to be in an R Project to work in RStudio (it's good practice to use them) 109 | 110 | ``` markdown 111 | ✔ Initialising Git repo 112 | Error: Path 'C:/Users/zoe.turner/OneDrive - Midlands and Lancashire CSU/Documents/' does not appear to be inside a project or package. 113 | Read more in the help for `proj_get()`. 114 | ``` 115 | 116 | - The Cloud workspace _is_ a project so already has the `.Rproj` file set up for Projects 117 | ::: 118 | 119 | ## Verbose feedback 120 | 121 | ``` 122 | √ Initialising Git repo 123 | √ Adding '.Rdata', '.httr-oauth', '.DS_Store' to '.gitignore' 124 | There are 2 uncommitted files: 125 | • '.gitignore' 126 | • 'git_project.Rproj' 127 | Is it ok to commit them? 128 | 129 | 1: Yeah 130 | 2: Absolutely not 131 | 3: No 132 | ``` 133 | 134 | :::{.callout-note collapse=false appearance='default' icon=true} 135 | ## Changing selections 136 | Choose the positive option (these change so might say `I agree` instead of `Yes`) 137 | ::: 138 | 139 | ## Initial commit 140 | 141 | ``` 142 | √ Adding files 143 | √ Commit with message 'Initial commit' 144 | • A restart of RStudio is required to activate the Git pane 145 | Restart now? 146 | 147 | 1: Nope 148 | 2: Definitely 149 | 3: No 150 | ``` 151 | 152 | - Choose the positive option (which changes!) 153 | - The save workspace option to `.Rdata` can be either no for this, more info at [intro-r course](https://intro-r-rstudio.nhsrcommunity.com/session-rstudio.html#/tools-options-workspace) 154 | - A new file for `.gitignore` will appear in the Files pane 155 | 156 | ## Connect this to GitHub 157 | 158 | To create a copy on GitHub 159 | 160 | ```{r} 161 | usethis::use_github() 162 | ``` 163 | 164 | This will open up the GitHub page in your default browser 165 | 166 | ## Message about ssh and https 167 | 168 | If you get this: 169 | 170 | ``` 171 | ✔ Checking that current branch is 'main' 172 | Which git protocol to use? (enter 0 to exit) 173 | 1: ssh <-- presumes that you have set up ssh keys 174 | 2: https <-- choose this if you don't have ssh keys (or don't know if you do) 175 | ``` 176 | 177 | Choose 2 at the moment. 178 | 179 | ## GitHub connected message in RStudio 180 | 181 | ``` 182 | ℹ Defaulting to 'https' Git protocol 183 | ✔ Setting active project to '/cloud/project' 184 | ✔ Creating GitHub repository 'Lextuga007/project' 185 | ✔ Setting remote 'origin' to 'https://github.com/Lextuga007/project.git' 186 | ✔ Pushing 'master' branch to GitHub and setting 'origin/master' as upstream branch 187 | ✔ Opening URL 'https://github.com/Lextuga007/project' 188 | ``` 189 | 190 | ## master or main? 191 | 192 | The branch is called `master` here as default but conventionally people have moved to `main` 193 | To rename this branch: 194 | 195 | ```{r} 196 | usethis::git_default_branch_rename(from = "master", to = "main") 197 | ``` 198 | 199 | :::{.callout-note collapse=false appearance='default' icon=true} 200 | ## Details of where the change has occurred 201 | - This function changes GitHub (on the web) not your local project 202 | ::: 203 | 204 | 205 | ## Changing the branch name locally 206 | 207 | Repeat the code and a different message appears 208 | 209 | ``` 210 | ✖ It's weird that the current default branch for your local repo and the source repo are different: 211 | 'master' (local) != 'main' (source) 212 | Are you sure you want to proceed? 213 | 214 | 1: yes 215 | 2: no 216 | ``` 217 | 218 | This is our first insight into how Git sees local and remote as two separate things! 219 | 220 | ## Set future default branches to main 221 | 222 | This won't affect other projects in the cloud but is useful on a computer 223 | 224 | ```{r} 225 | usethis::git_default_branch_configure() 226 | ``` 227 | 228 | ## Updating historic repositories 229 | 230 | If you want to update a lot of old repository default branches from `master` to `main` this can be done using a [Shiny app](https://www.garrickadenbuie.com/blog/branchmover/) built by Garrick Aden-Buie, Software Engineer for Shiny at Posit. 231 | 232 | 233 | ## End session 234 | 235 | # Acknowledgements 236 | 237 | These slides were designed by Mine Çetinkaya-Rundel and Emma Rand for the Forwards Package development module course 238 | 239 | [Your first package](https://forwards.github.io/workshops/package-dev-modules/slides/03-your-first-package/your-first-package.html#1) and 240 | [Setting up your system](https://forwards.github.io/workshops/package-dev-modules/slides/02-setting-up-system/setting-up-system.html#1) 241 | 242 | CDU Data Science [Personal Access Tokens blog](https://cdu-data-science-team.github.io/team-blog/posts/2021-12-18-personal-access-tokens/) 243 | -------------------------------------------------------------------------------- /session-undo-merge.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to Git and GitHub" 3 | subtitle: "Session - Undo last merge" 4 | --- 5 | 6 | ## The benefit of working in increments 7 | 8 | Working in small chunks, committing and using pull requests means that there are more points to revert back to if things go wrong 9 | 10 | In GitHub, find the pull request and at the bottom is a button `Revert` and this doesn't disappear over time 11 | 12 | ## Revert button 13 | 14 | ![](img/github-revert-pr.PNG){fig-alt="Screenshot of a day old GitHub Pull Request with the Revert button highlighted"} 15 | 16 | ## History of mistakes 17 | 18 | - Using `Revert` in GitHub (and other ways to undo work) creates a new commit 19 | 20 | ::: incremental 21 | - This means that your commit history is a record of all your work, even mistakes 22 | - It's absolutely ok and not something to be anxious about (when it's code) 23 | - But if you do commit information that is sensitive this needs to be removed this needs to be treated as an incident or breach 24 | ::: 25 | 26 | ## Removing sensitive data from a repository 27 | 28 | It's a thing that every user of GitHub needs to consider and GitHub has [guidance](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository) but does refer to a [tool](https://rtyley.github.io/bfg-repo-cleaner/) that needs installing 29 | 30 | > If this isn't available to you it is still possible to purge a file and its commit history but as there are many different scenarios... [TiddlyWiki](http://sukima.github.io/GitFixUm/). 31 | 32 | is like a choose your own adventure. 33 | 34 | ::: notes 35 | Acknowledge making a mistake is scary and not an adventure! There will be people to help though, through the NHS-R Community and people should definitely feel they can ask for help. 36 | ::: 37 | 38 | ## When in doubt - make it private 39 | 40 | You can change the visibility of a repository through the `Settings` tab in GitHub 41 | 42 | It's possible to move a public repository to private and back again any number of times 43 | 44 | ## End session 45 | 46 | ### Acknowledgements 47 | 48 | CDU Data Science Team blog [When things go wrong in GitHub](https://cdu-data-science-team.github.io/team-blog/posts/2022-11-09-when-things-go-wrong-in-github/) 49 | -------------------------------------------------------------------------------- /session-usethis-errors.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to Git and GitHub" 3 | subtitle: "Session - {usethis} errors" 4 | --- 5 | 6 | ## Error in "stop_bad_github_remote_config()" 7 | 8 | If you get this 9 | 10 | ``` 11 | ✔ Setting active project to '/cloud/project' 12 | Error in `stop_bad_github_remote_config()`: 13 | ! Unsupported GitHub remote configuration: 'no_github' 14 | • Host = NA 15 | • origin = 16 | • upstream = 17 | • Neither 'origin' nor 'upstream' is a GitHub repo. 18 | 19 | Read more about the GitHub remote configurations that usethis supports at: 20 | 'https://happygitwithr.com/common-remote-setups.html' 21 | Run `rlang::last_trace()` to see where the error occurred. 22 | ``` 23 | 24 | It's because GitHub connections (including personal access tokens) haven't been set up. 25 | The {usethis} functions won't work though as they require a connection to GitHub 26 | 27 | You can use Git locally (F5 refresh in the Cloud). 28 | 29 | ## If they continue 30 | 31 | In the Terminal (starts with `$` on the command line 32 | 33 | ```{bash} 34 | git remote -v 35 | ``` 36 | 37 | Gives details of the remote branch, if nothing shows and both the `push` and `pull` buttons in RStudio are grey 38 | 39 | ```{bash} 40 | git remote add origin 41 | ``` 42 | 43 | with the url coming from the HTTPS url from GitHub's green button `Code` on the repo. 44 | 45 | ## Posit Cloud repos are called `project` 46 | 47 | Particularly because Posit Cloud repos are called `project`, if you have set up a connection to GitHub before you will geta message 48 | 49 | > Error: Repo 'Lextuga007/project' already exists on 'github.com' 50 | 51 | It's best to delete the GitHub repo (check for any work you want to keep!) and start again when using Posit Cloud. 52 | 53 | In GitHub, under the Settings tab and scroll down to the `Danger Zone`. 54 | You may need to Restart the R session as a refresh. 55 | 56 | ## Pop up for username for `https://github.com` 57 | 58 | This is because the Personal Access Token hasn't been set up correctly. 59 | It might have expired or deleted. 60 | Best resolved by resetting the PAT details. 61 | 62 | ## Unable to confirm the GitHub remote configuration is "pull request ready" 63 | 64 | ``` 65 | Unable to confirm the GitHub remote configuration is "pull request ready". 66 | You probably need to configure a personal access token for 'github.com'. 67 | See `gh_token_help()` for help. 68 | (Or maybe we're just offline?) 69 | Unexpected GitHub remote configuration: 'maybe_ours_or_theirs' 70 | Host = 'https://github.com' 71 | origin = 'nhs-r-community/intro-git-github' 72 | upstream = 73 | 'origin' is a GitHub repo and 'upstream' is either not configured or is not a GitHub repo. 74 | 75 | We may be offline or you may need to configure a GitHub personal access 76 | token. `gh_token_help()` can help with that. 77 | 78 | Read more about what this GitHub remote configurations means at: 79 | 'https://happygitwithr.com/common-remote-setups.html' 80 | 81 | 1: Yes, I want to proceed. I know what I'm doing. 82 | 2: No, I want to stop and straighten out my GitHub remotes first. 83 | ``` 84 | 85 | Trying `pr_pull()` may give this: 86 | 87 | ``` 88 | Error: Unable to get GitHub info for these remotes: 'origin' 89 | Are we offline? Is GitHub down? Has the repo been deleted? 90 | Otherwise, you probably need to configure a personal access token (PAT) for 'github.com' 91 | See `?gh_token_help` for advice 92 | ``` 93 | 94 | which suggests the PAT has been removed/deleted or is unobtainable by the project. 95 | 96 | It may be that an alternative place to save the PAT is needed 97 | 98 | ## Storing the PAT in .Renviron 99 | 100 | This is no longer a recommended way of saving a PAT but is required in some circumstances (linux servers) 101 | 102 | ```{r} 103 | usethis::edit_r_environ() 104 | ``` 105 | 106 | will open a blank document in RStudio 107 | 108 | ## Text in .Renviron 109 | 110 | With no spaces, returns or any spacing the PAT is added to the file like 111 | 112 | > GITHUB_PAT=ghp_gobbledygookgeneratedbygithub 113 | 114 | Restart the R session (Ctrl+Shift+F10) 115 | 116 | Running `Sys.getenv("GITHUB_PAT")` in the Console will show the PAT code 117 | 118 | ## "Error in libgit2::git_branch_create" 119 | 120 | With the error: 121 | 122 | >Error in libgit2::git_branch_create : 123 | the given reference name 'refs/heads/Add render specifics to _quarto.yml' is not valid 124 | 125 | Check that the name given in the command `usethis::pr_init()` is in the branch format 126 | 127 | ```{r} 128 | usethis::pr_init("update-quarto-yml") 129 | 130 | ``` 131 | 132 | not like a commit format (with spaces often) 133 | 134 | ```{r} 135 | usethis::pr_init("Add render specifics to _quarto.yml") 136 | ``` 137 | 138 | ## Error: The `pr_*()` functions facilitate pull requests. 139 | 140 | This may be where the function `pr_push()` is being used but from the main branch 141 | 142 | If changes are required (for example to reinstate the greyed out `push` and `pull` in RStudio) 143 | 144 | On the Git Terminal (where the command line starts with `$`) 145 | 146 | ```{bash} 147 | git push --set-upstream origin main 148 | ``` 149 | 150 | Refresh the RStudio git pane to ensure the buttons are no longer greyed out 151 | ## End session 152 | -------------------------------------------------------------------------------- /session-usethis-gert.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to Git and GitHub" 3 | subtitle: "Session - Workflow with {usethis} and {gert}" 4 | --- 5 | 6 | ## Not the command line! 7 | 8 | - Many courses in Git refer to the Command line 9 | - This is under the `Terminal` tab in RStudio 10 | - There are many resources available for Git commands but perhaps the hardest part is the workflow 11 | - Which is where R packages can make things a little friendlier... 12 | 13 | ## Getting started 14 | 15 | Using two packages: 16 | 17 | ```{r} 18 | library(usethis) 19 | library(gert) 20 | ``` 21 | 22 | ::: {.callout-tip collapse="false" appearance="default" icon="true"} 23 | ## Terminal or Console? 24 | 25 | The `Console` starts with `>` and is for `R`\ 26 | The `Terminal` starts with `$` and is for `git` but other things too like `quarto` 27 | ::: 28 | 29 | ## Set up a project 30 | 31 | ::: {.callout-tip collapse="false" appearance="default" icon="true"} 32 | ## Remember! 33 | 34 | - On Posit Cloud the workspace *is* a project! 35 | ::: 36 | 37 | - [Setting up a project on your own computer](https://nhs-r-community.github.io/intro-r-rstudio/session-projects.html#/title-slide) 38 | - The Files should have a file called `*.Rproj` if it's a project 39 | 40 | ## Start new work 41 | 42 | Rather than working on the `main` branch we need a copy called "new_work" 43 | 44 | ```{r} 45 | usethis::pr_init("new_work") 46 | ``` 47 | 48 | 1. Next [create a quarto file](https://intro-r-rstudio.nhsrcommunity.com/session-quarto.html#/open-a-new-quarto-file) 49 | 2. include a title and author 50 | 3. Render it (which will require you to also save it) 51 | 52 | ## Commit the new files 53 | 54 | In the Git pane three new items will have appeared 55 | 56 | - the `*.qmd` file 57 | - an `*.html` file from the rendered quarto 58 | - a folder for the corresponding html (because this isn't self-contained) 59 | 60 | ## Making a quarto html self-contained 61 | 62 | Add to the YAML (the first few lines at the top) 63 | 64 | ```{r} 65 | #| code-line-numbers: "5" 66 | title: "My report" 67 | author: "Zoë Turner" 68 | format: html 69 | editor: visual 70 | embed-resources: true 71 | ``` 72 | 73 | And render again - the folder will disappear. 74 | 75 | ## Staging the new files 76 | 77 | Individual new files can be `staged` with code or by ticking the box next to the file in the RStudio Git pane 78 | 79 | ```{r} 80 | gert:git_add("name_of_file.qmd") 81 | ``` 82 | 83 | ## Adding multiple files - first method 84 | 85 | - Using [RStudio](https://nhsrcommunity.com/rstudio-and-git-selecting-many-files/) can be done in the Git pane by clicking on the first file name (highlighting it) 86 | - Then use `Shift` and click the second file to highlight down (or arrow down) 87 | - Select one of the tick boxes and they all get selected 88 | 89 | ## Commit 90 | 91 | This records the changes with a message in Git 92 | 93 | ```{r} 94 | gert::git_commit(message = "First commit for quatro document") 95 | ``` 96 | 97 | ## Adding multiple files - second method 98 | 99 | Stage everything and do the commit message at the same time! 100 | 101 | ```{r} 102 | gert::git_commit_all(message = "First commit for quatro document") 103 | ``` 104 | 105 | ::: {.callout-warning collapse="false" appearance="default" icon="true"} 106 | ## Watch out! 107 | 108 | This will only `stage` files that have already been "seen" as in committed. 109 | 110 | New files will get missed by this command. 111 | ::: 112 | 113 | ## Oops mistake in the message! 114 | 115 | Let's correct the misspelling of `quatro` to `quarto` using a feature of RStudio 116 | 117 | ::: incremental 118 | - Click on the `Commit` button in the Git pane of RStudio (a pop up will appear) 119 | - Select the box `Amend previous commit` under the Commit message (starts off blank) 120 | - Correct `quarot` for `quarto` and then click the Commit button. 121 | ::: 122 | 123 | ## Work in progress 124 | 125 | Committing frequently is beneficial but can create a lot of history (commits) 126 | 127 | ::: incremental 128 | - A recommended way of working can be to commit with a message "WIP" and update the one commit 129 | - RStudio can be used to both change the message and add/delete files 130 | ::: 131 | 132 | ## Make a change as WIP 133 | 134 | - Change the title of the quarto document and save 135 | - Note the appearance of the file in the Git pane with an `M` icon next to it 136 | - Stage the file using `gert::git_add("name_of_file.qmd")` or tick in RStudio 137 | - Commit using the RStudio button and select `Amend previous commit` 138 | 139 | ## Look at the history 140 | 141 | - In the Git pane of RStudio click on `History` 142 | - Show Diff will need to be selected as the files are new 143 | - Two links will appear for the `*.qmd` and `*.html`, click on the qmd file 144 | - You will see your most recent Title name and there is no reference to that because the commit was changed 145 | 146 | ## A scenario for use 147 | 148 | ::: incremental 149 | - In building this course and the slides the content has changed a lot! 150 | - Slides were merged and split out into topics but the content wasn't always changed 151 | - WIP on a branch shared on GitHub can show you are still working on this as it's good practice to never have a WIP commit on `main` 152 | ::: 153 | 154 | ## Your turn! 155 | 156 | - Remove the author of the quarto document, save and Render 157 | - Create a new Quarto presentation and save 158 | - Use `gert::git_commit_all("Removed author and created slides")` 159 | - Stage and commit either as a new commit or amend the last 160 | 161 | ## End session 162 | 163 | ## Acknowledgements 164 | 165 | [Happy Git and GitHub](https://happygitwithr.com/) for the useR by Jenny Bryan 166 | 167 | [Pull Request Flow with usethis](https://www.garrickadenbuie.com/blog/pull-request-flow-usethis/?interactive=) by Garrick Aden-Buie 168 | -------------------------------------------------------------------------------- /session-version-control.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to Git and GitHub" 3 | subtitle: "Session - What is version control?" 4 | --- 5 | 6 | ## Git - the version control system 7 | 8 | > “Track Changes” features from Microsoft Word 9 | 10 | . . . 11 | 12 | > on steroids 13 | 14 | . . . 15 | 16 | Source: [Happy Git and GitHub for the useR](https://happygitwithr.com/big-picture.html?q=version%20control#big-picture) by Jenny Bryan 17 | 18 | ## Managing your files 19 | 20 | Is this familiar? 21 | 22 | ::: {.fragment .fade-in} 23 | file_v1.0.doc 24 | ::: 25 | ::: {.fragment .fade-in} 26 | file_v1.1.doc 27 | ::: 28 | ::: {.fragment .fade-in} 29 | file_v1.0.1.doc 30 | ::: 31 | ::: {.fragment .fade-in} 32 | file_final_1.0.doc 33 | ::: 34 | ::: {.fragment .fade-in} 35 | file_final_final.doc 36 | ::: 37 | ::: {.fragment .fade-in} 38 | Inspired by comic cartoons like [xkcd](https://xkcd.com/1459/) 39 | ::: 40 | 41 | ## Git learning downside 42 | 43 | Git may not really make sense if you are working on your own 44 | 45 | >A solo data analyst, working on a single computer, will benefit from adopting version control. But not nearly enough to justify the pain of installation and workflow upheaval. There are much easier ways to get versioned back ups of your files, if that’s all you’re worried about. 46 | 47 | [Happy Git and GitHub for the userR](https://happygitwithr.com/big-picture.html) - Jenny Bryan 48 | 49 | ## Reasons why Git and GitHub hurts 50 | 51 | ::: incremental 52 | - requires a completely new and longer workflow to your analysis 53 | - collaborating with others can cause **merge conflicts** 54 | - you can cause your own merge conflicts mess (we will do that in this course!) 55 | ::: 56 | 57 | . . . 58 | 59 | > this is not a one-time pain, this could be a dull ache for a long time 60 | 61 | Source: Happy Git and GitHub for the useR - [Is it going to hurt](https://happygitwithr.com/big-picture.html?q=version%20control#is-it-going-to-hurt) by Jenny Bryan 62 | 63 | ## So why bother? 64 | 65 | ::: incremental 66 | - Personal exposure: sharing publicly can feel scary because you assume people will judge, but you'll soon find the judgement is positive as people are grateful for your sharing 67 | - Team exposure: there is a lot of repeated code for tasks duplicated across many organisations (particularly in the public sector) 68 | - Be keener: you can use other people's work (with the right [licences](https://nhs-r-community.github.io/statements-on-tools/open-code-in-the-nhs.html#licenceslicenses)) and keep up to date with all the work through GitHub for any changes, developments or improvements 69 | - Collaboration: we can work together! 70 | ::: 71 | 72 | ## Git benefits 73 | 74 | :::incremental 75 | - Are important if you want to share/communicate with others 76 | - Are paramount if you want to collaborate 77 | - Combined with RStudio, GitHub and R packages, can be a little easier to get started 78 | ::: 79 | 80 | ## GitHub 81 | 82 | :::incremental 83 | - Uses Git but is a separate platform (other services are available) 84 | - It's a web hosted site for public and private repositories 85 | - GitHub is a very friendly user interface and is being updated with new features 86 | - Individuals and [organisations](https://github.com/nhs-r-community) can have accounts 87 | - You can have public and private repositories 88 | ::: 89 | 90 | ## RStudio benefits 91 | 92 | As with so many things, other IDEs (Integrated development environment) are available 93 | 94 | :::incremental 95 | - Never having to leave one program: clean data, visualise it and do statistics in one place! 96 | - Also allows version control and use of Git/GitHub without having to open another program 97 | ::: 98 | 99 | ## End session 100 | 101 | ## Acknowledgements 102 | 103 | [Happy Git and GitHub](https://happygitwithr.com/) for the useR by Jenny Bryan 104 | 105 | Material adapted from the [Git training](https://github.com/nhs-r-community/git_training/blob/main/guides/workshop_slides/Part%201-Intro%20to%20Git-Version%20Control.pdf) delivered at the NHS-R Community conference 2022. -------------------------------------------------------------------------------- /session-version-workflow.qmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to Git and GitHub" 3 | subtitle: "Session - Versioning workflow" 4 | --- 5 | 6 | ## Snapshots 7 | 8 | It's good to practice regular saving of files when you work - whatever the program 9 | 10 | :::incremental 11 | - But what if you want to take a snapshot before you do something major? 12 | - You could save files as version 1, version 2 and so on 13 | - Git allows whole project snapshots of many documents 14 | ::: 15 | 16 | ## Not just for new material 17 | 18 | Have you ever commented out code that you don't want to use but want to keep - just in case? 19 | 20 | :::incremental 21 | - Git allows things to be deleted and add a message as to why you did that 22 | - Roll backs are also available! 23 | - And if you want to find the old code but not roll back - Git has that history, it keeps everything 24 | ::: 25 | 26 | ## Local and Remote 27 | 28 | Once you have a snapshot stored locally (Git) you can **push** the snapshot to a remote site (GitHub) 29 | 30 | This is like: 31 | 32 | ::: incremental 33 | - sending file updates by email and also 34 | - sharing on something like DropBox 35 | ::: 36 | 37 | ## An unnecessary extra step? 38 | 39 | The tendency for much of analysis work is to share once something is finished 40 | 41 | But **commits** (snapshots): 42 | 43 | ::: incremental 44 | - allow others to contribute with your work in progress 45 | - forces you to think clearly about code as others will see it 46 | - give the opportunity to **revert** (roll back) to something that was better 47 | ::: 48 | 49 | ## Private or public repository? 50 | 51 | GitHub offers the possibility of having private repositories 52 | 53 | ::: {.fragment .fade-in} 54 | They have a few restrictions on functionality (unless in a paid account) 55 | ::: 56 | ::: {.fragment .fade-in} 57 | Still should never have any identifiable information for security 58 | ::: 59 | ## End session 60 | 61 | # Acknowledgements 62 | 63 | [Happy Git and GitHub](https://happygitwithr.com/) for the useR by Jenny Bryan 64 | --------------------------------------------------------------------------------