From d542e5f03f83ea77b6c31d59701889df4e08cc5a Mon Sep 17 00:00:00 2001 From: Andree Valle Campos Date: Mon, 4 Mar 2024 21:31:40 +0000 Subject: [PATCH 1/8] fix callout without title --- learners/setup.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/learners/setup.md b/learners/setup.md index 0e2cdce627..f54cc8d4d8 100644 --- a/learners/setup.md +++ b/learners/setup.md @@ -99,6 +99,8 @@ instructions on the screen. ::::::::::::::::::::::::::::: callout +### On updates + While this may sound scary, it is **far more common** to run into issues due to using out-of-date versions of R or R packages. Keeping up with the latest versions of R, RStudio, and any packages you regularly use is a good practice. ::::::::::::::::::::::::::::: @@ -111,6 +113,7 @@ Open RStudio and **copy and paste** the following code chunk into the [console w if(!require("pak")) install.packages("pak") new <- c("gh", + "gitcreds", "usethis") pak::pak(new) @@ -124,6 +127,7 @@ When the installation has finished, you can try to load the packages by pasting ```r library(gh) +library(gitcreds) library(usethis) ``` From 9b59712ef368ea0464666c5516118350534f03e4 Mon Sep 17 00:00:00 2001 From: Andree Valle Campos Date: Mon, 4 Mar 2024 21:32:06 +0000 Subject: [PATCH 2/8] fix callout without title + add info on data git --- episodes/01-basics.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/episodes/01-basics.md b/episodes/01-basics.md index 239ae787b6..525b7cd24b 100644 --- a/episodes/01-basics.md +++ b/episodes/01-basics.md @@ -169,7 +169,17 @@ Plain text files can be text, code, and data. Example for each of these are Mark ::::::::::::::::: callout -We can use `Git` to track changes of these plain text files. However, for [plain text data files](https://www.r4epi.com/importing-plain-text-files.html) (like `.csv` and `.tsv`) we prefer different version control systems. +### data files + +We can use `Git` to track changes of **data files** (like `.csv` and `.tsv`). However, if we consider data files as **raw files**, which should not change in time, then we may not be needed to use Git with them. We'll take a look into this in the chapter on [Ignoring things](06-ignore.md). + +Also, if you consider your data file **large** with respect to your computer, you can opt to use: + +- a file hosting service like Google Drive and the [`{googlesheets4}` R package](https://r4ds.hadley.nz/spreadsheets#google-sheets) to import data, +- a different version control system like [Git Large File Storage (LFS)](https://git-lfs.github.com/), or +- a different data format like the `parquet` format using [the `{arrow}` R package](https://r4ds.hadley.nz/arrow.html). + + ::::::::::::::::::::::::: From cc307bbd4f73231d93c26ab8763b885b3cc9e62e Mon Sep 17 00:00:00 2001 From: Andree Valle Campos Date: Mon, 4 Mar 2024 21:36:35 +0000 Subject: [PATCH 3/8] update level of callouts --- episodes/02-setup.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/episodes/02-setup.md b/episodes/02-setup.md index a507c42784..140e8ebe4a 100644 --- a/episodes/02-setup.md +++ b/episodes/02-setup.md @@ -100,7 +100,7 @@ For this lesson, we will be interacting with [GitHub](https://github.com/) and s ::::::::::::::::::::::::::::::::::::::::: callout -## Keeping your email private +### Keeping your email private If you elect to use a private email address with GitHub, then use that same email address for the `user.email` value, e.g. `username@users.noreply.github.com` replacing `username` with your GitHub one. @@ -203,6 +203,8 @@ Copy your token. Save it for the next step. ::::::::::::::::: callout +### token options + Briefly: - `"repo"` will give you control of your _private_ repositories online (YES! you can have private repos!). From 14dd54fc8623d6444851875b48d0b0ff87033472 Mon Sep 17 00:00:00 2001 From: Andree Valle Campos Date: Tue, 5 Mar 2024 02:29:47 +0000 Subject: [PATCH 4/8] relocate MCQ challenges before self-practice --- episodes/04-changes.md | 144 +++++++++++++++++++++++------------------ 1 file changed, 81 insertions(+), 63 deletions(-) diff --git a/episodes/04-changes.md b/episodes/04-changes.md index 7bf1fc4192..7fd4988c2d 100644 --- a/episodes/04-changes.md +++ b/episodes/04-changes.md @@ -573,6 +573,86 @@ than you would like! ::::::::::::::::::::::::::: +## Group Challenges + +::::::::::::::::::::::::::::::::::::::: challenge + +## Choosing a Commit Message + +Which of the following commit messages would be most appropriate for the +last commit made to `sitrep.Rmd`? + +1. "Changes" +2. "Added line 'Maps illustrate the spread and impact of outbreak' to sitrep.Rmd" +3. "Discuss effects of Sitrep' climate on the Mummy" + +::::::::::::::: solution + +## Solution + +Answer 1 is not descriptive enough, and the purpose of the commit is unclear; +and answer 2 is redundant to using "git diff" to see what changed in this commit; +but answer 3 is good: short, descriptive, and imperative. + + + +::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::: challenge + +## Committing Changes to Git + +Which command(s) below would save the changes of `myfile.txt` +to my local Git repository? + +1. ```bash + $ git commit -m "my recent changes" + ``` +2. ```bash + $ git init myfile.txt + $ git commit -m "my recent changes" + ``` +3. ```bash + $ git add myfile.txt + $ git commit -m "my recent changes" + ``` +4. ```bash + $ git commit -m myfile.txt "my recent changes" + ``` + +::::::::::::::: solution + +## Solution + +1. Would only create a commit if files have already been staged. +2. Would try to create a new repository. +3. Is correct: first add the file to the staging area, then commit. +4. Would try to commit a file "my recent changes" with the message myfile.txt. + + + +::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::::: + + +::::::::::::::::::::::::::: + +### Your turn! + +Take 10 minutes to the following two sections: + +- Practice the workflow +- Relevant callouts + +If you want to keep practicing, move to the last one: + +- Individual Challenges + +::::::::::::::::::::::::::: + ## Practice the workflow Let's watch as our changes to a file move from our editor to the staging area and into long-term storage. First, __in the Console__, we'll add another line to the file: @@ -831,69 +911,7 @@ repository (`git commit`): ![](fig/git-committing.svg){alt='The Git Commit Workflow'} -## Challenges - -::::::::::::::::::::::::::::::::::::::: challenge - -## Choosing a Commit Message - -Which of the following commit messages would be most appropriate for the -last commit made to `sitrep.Rmd`? - -1. "Changes" -2. "Added line 'Maps illustrate the spread and impact of outbreak' to sitrep.Rmd" -3. "Discuss effects of Sitrep' climate on the Mummy" - -::::::::::::::: solution - -## Solution - -Answer 1 is not descriptive enough, and the purpose of the commit is unclear; -and answer 2 is redundant to using "git diff" to see what changed in this commit; -but answer 3 is good: short, descriptive, and imperative. - - - -::::::::::::::::::::::::: - -:::::::::::::::::::::::::::::::::::::::::::::::::: - -::::::::::::::::::::::::::::::::::::::: challenge - -## Committing Changes to Git - -Which command(s) below would save the changes of `myfile.txt` -to my local Git repository? - -1. ```bash - $ git commit -m "my recent changes" - ``` -2. ```bash - $ git init myfile.txt - $ git commit -m "my recent changes" - ``` -3. ```bash - $ git add myfile.txt - $ git commit -m "my recent changes" - ``` -4. ```bash - $ git commit -m myfile.txt "my recent changes" - ``` - -::::::::::::::: solution - -## Solution - -1. Would only create a commit if files have already been staged. -2. Would try to create a new repository. -3. Is correct: first add the file to the staging area, then commit. -4. Would try to commit a file "my recent changes" with the message myfile.txt. - - - -::::::::::::::::::::::::: - -:::::::::::::::::::::::::::::::::::::::::::::::::: +## Individual Challenges ::::::::::::::::::::::::::::::::::::::: challenge From 162f4ed4f4a4e59c429c8b20de841826d98b1cf1 Mon Sep 17 00:00:00 2001 From: Andree Valle Campos Date: Tue, 5 Mar 2024 03:03:05 +0000 Subject: [PATCH 5/8] add callout tag --- episodes/04-changes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/episodes/04-changes.md b/episodes/04-changes.md index 7fd4988c2d..1f97f258f3 100644 --- a/episodes/04-changes.md +++ b/episodes/04-changes.md @@ -638,7 +638,7 @@ to my local Git repository? :::::::::::::::::::::::::::::::::::::::::::::::::: -::::::::::::::::::::::::::: +::::::::::::::::::::::::::: testimonial ### Your turn! From 59bd83ea07e0ceed9f482f90229bbe941f75b514 Mon Sep 17 00:00:00 2001 From: Andree Valle Campos Date: Tue, 5 Mar 2024 03:03:58 +0000 Subject: [PATCH 6/8] close forcing step + diff live and home challenges --- episodes/06-ignore.md | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/episodes/06-ignore.md b/episodes/06-ignore.md index 6ee93e5bdc..0e42ba36c2 100644 --- a/episodes/06-ignore.md +++ b/episodes/06-ignore.md @@ -133,6 +133,10 @@ a.csv Use -f if you really want to add them. ``` +::::::::::::::::::::::: spoiler + +### How to override our ignore settings? + If we really want to override our ignore settings, we can use `git add -f` to force Git to add something. For example, `git add -f a.csv`. @@ -155,6 +159,8 @@ Ignored files: nothing to commit, working tree clean ``` +::::::::::::::::::::::: + ::::::::::::::::: checklist ### Good Practice @@ -169,7 +175,22 @@ A good version control project: ::::::::::::::::::::::::::: -## Challenges +::::::::::::::::::::::::::: testimonial + +### Your turn! + +Take 5 minutes to the following two challenges: + +- Ignoring Nested Files +- Including Specific Files + +If you want to keep practicing, move to the last one: + +- Home challenges + +::::::::::::::::::::::::::: + +## Live challenges ::::::::::::::::::::::::::::::::::::::: challenge @@ -229,7 +250,7 @@ How would you ignore all `.csv` files in your root directory except for ::::::::::::::: hint -Find out what `!` (the exclamation point operator) does in the [Git Reference documentation](../learners/reference.md) for `gitignore`. +Find out what `!` (the exclamation point operator) does for `gitignore` in the [Git Reference documentation](../learners/reference.md). ::::::::::::::: @@ -256,6 +277,8 @@ of `.csv` files added to the root directory will be ignored. :::::::::::::::::::::::::::::::::::::::::::::::::: +## Home challenges + ::::::::::::::::::::::::::::::::::::::: challenge ## Ignoring Nested Files: Variation From c170b3f3608fde5a0033415dac662d07543b52e6 Mon Sep 17 00:00:00 2001 From: Andree Valle Campos Date: Tue, 5 Mar 2024 04:35:59 +0000 Subject: [PATCH 7/8] prioritize using usethis + add push pull section and diff group and individual challenge --- episodes/07-github.md | 459 ++++++++++++++++++------------------------ 1 file changed, 194 insertions(+), 265 deletions(-) diff --git a/episodes/07-github.md b/episodes/07-github.md index d3dfceb47c..2ec737f5d5 100644 --- a/episodes/07-github.md +++ b/episodes/07-github.md @@ -41,7 +41,65 @@ and cons of this in a [later episode](13-hosting.md). Let's start by sharing the changes we've made to our current project with the world. To this end we are going to create a *remote* repository that will be linked to our *local* repository. -## 1\. Create a remote repository +## How to connect from Local to GitHub? + +From your local R project, after using `usethis::use_git()` to initialise your **Local repository**, then you can also use `{usethis}` to connect it with the **Remote repository** (a.k.a, "the remote"): + +```r +usethis::use_github() +``` + +```output +ℹ Defaulting to 'https' Git protocol +✔ Creating GitHub repository 'vlad/cases' +✔ Setting remote 'origin' to 'https://github.com/vlad/cases.git' +✔ Pushing 'main' branch to GitHub and setting 'origin/main' as upstream branch +✔ Opening URL 'https://github.com/vlad/cases' +``` + +This will open a new tab in your web browser with the URL path of your remote repository in GitHub. + +You can use `usethis::use_github()` to _create_ a remote repository, _connect_ the local and the remote, and _push_ your local changes to a remote. + +```r +usethis::git_sitrep() +``` + +The output in the last section called `── GitHub project` should look like this: + +```output +── GitHub project +• Type = 'ours' +• Host = 'https://github.com' +• Config supports a pull request = TRUE +• origin = 'vlad/cases' (can push) +• upstream = +• Desc = 'origin' is both the source and primary repo. +``` + +The `(can push)` line of the output above is critical! + +If you remember back to the earlier [episode](04-changes.md) where we added and +committed our earlier work on `sitrep.Rmd`, we had a diagram of the local repository +which looked like this: + +![](fig/git-staging-area.svg){alt='The Local Repository with Git Staging Area'} + +Now that we have two repositories, we need a diagram like this: + +![](fig/git-freshly-made-github-repo.png){alt='Freshly-Made GitHub Repository'} + +Note that our local repository still contains our earlier work on `sitrep.Rmd`, but the +remote repository on GitHub appears empty as it doesn't contain any files yet. + +We'll discuss remotes in more detail in the next episode, while +talking about how they might be used for collaboration. + +::::::::::::::::::::::::::::::::::: spoiler + +## How to connect from GitHub to Local? + +### 1\. Create a remote repository Log in to [GitHub](https://github.com), then click on the icon in the top right corner to create a new repository called `cases`: @@ -83,7 +141,7 @@ Now that we have two repositories, we need a diagram like this: Note that our local repository still contains our earlier work on `sitrep.Rmd`, but the remote repository on GitHub appears empty as it doesn't contain any files yet. -## 2\. Connect local to remote repository +### 2\. Connect local to remote repository Now we connect the two repositories. We do this by making the GitHub repository a [remote](../learners/reference.md#remote) for the local repository. @@ -145,200 +203,85 @@ origin git@github.com:vlad/cases.git (fetch) origin git@github.com:vlad/cases.git (push) ``` -You can also check this steps with `{usethis}`: - -```r -usethis::git_sitrep() -``` - -The output in the last section called `── GitHub project` should look like this: - -```output -── GitHub project -• Type = 'ours' -• Host = 'https://github.com' -• Config supports a pull request = TRUE -• origin = 'vlad/cases' (can push) -• upstream = -• Desc = 'origin' is both the source and primary repo. -``` - -We'll discuss remotes in more detail in the next episode, while -talking about how they might be used for collaboration. - - -```output -The authenticity of host 'github.com (192.30.255.112)' can't be established. -RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8. -This key is not known by any other names -Are you sure you want to continue connecting (yes/no/[fingerprint])? y -Please type 'yes', 'no' or the fingerprint: yes -Warning: Permanently added 'github.com' (RSA) to the list of known hosts. -git@github.com: Permission denied (publickey). -``` +::::::::::::::::::::::::::::::::::: -Right, we forgot that we need to give GitHub our public key! +## Push local changes to a remote -First, we need to copy the public key. Be sure to include the `.pub` at the end, otherwise you're looking at the private key. +We can add new changes to the remote repository. +Let's make a change to `sitrep.Rmd`, adding yet another line. -```bash -cat ~/.ssh/id_ed25519.pub +```r +usethis::edit_file("sitrep.Rmd") ``` ```output -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDmRA3d51X0uu9wXek559gfn6UFNF69yZjChyBIU2qKI vlad@tran.sylvan.ia +Comparison of attack rates in different age groups +This can identify priority groups for interventions +Maps illustrate the spread and impact of outbreak +Read shapefiles with the {sf} R package ``` -Now, going to GitHub.com, click on your profile icon in the top right corner to get the drop-down menu. Click "Settings," then on the -settings page, click "SSH and GPG keys," on the left side "Account settings" menu. Click the "New SSH key" button on the right side. Now, -you can add the title (Dracula uses the title "Vlad's Lab Laptop" so he can remember where the original key pair -files are located), paste your SSH key into the field, and click the "Add SSH key" to complete the setup. - -Now that we've set that up, let's check our authentication again from the command line. +Add and commit this change to the local repository: ```bash -$ ssh -T git@github.com -``` - -```output -Hi Vlad! You've successfully authenticated, but GitHub does not provide shell access. +git add sitrep.Rmd +git commit -m "Add package to read spatial data" ``` -Good! This output confirms that the SSH key works as intended. We are now ready to push our work to the remote repository. ---> - -## 3\. Push local changes to a remote - -Now that authentication is setup, we can return to the remote. This command will push the changes from +This command will push the changes from our local repository to the repository on GitHub: ```bash -$ git push origin main +$ git push ``` Since Dracula set up a passphrase, it will prompt him for it. If you completed advanced settings for your authentication, it @@ -356,31 +299,7 @@ To https://github.com/vlad/cases.git * [new branch] main -> main ``` -::::::::::::::::::::::::::::::::::::::::: callout - -## Proxy - -If the network you are connected to uses a proxy, there is a chance that your -last command failed with "Could not resolve hostname" as the error message. To -solve this issue, you need to tell Git about the proxy: - -```bash -$ git config --global http.proxy http://user:password@proxy.url -$ git config --global https.proxy https://user:password@proxy.url -``` - -When you connect to another network that doesn't use a proxy, you will need to -tell Git to disable the proxy using: - -```bash -$ git config --global --unset http.proxy -$ git config --global --unset https.proxy -``` - -:::::::::::::::::::::::::::::::::::::::::::::::::: - - + Our local and remote repositories are now in this state: ![](fig/github-repo-after-first-push.png){alt='GitHub Repository After First Push'} -::::::::::::::::::::::::::::::::::::::::: callout +::::::::::::::::::::::::::::::::::::::::: spoiler ## The '-u' Flag @@ -421,23 +340,26 @@ command, and is used to associate the current branch with a remote branch so that the `git pull` command can be used without any arguments. To do this, simply use `git push -u origin main` once the remote has been set up. - :::::::::::::::::::::::::::::::::::::::::::::::::: - -## All in one step - -You can use `usethis::use_github()` to _create_ a remote repository, _connect_ the local and the remote, and _push_ your local changes to a remote. - ::::::::::::::::::::::::::::::::: challenge For the Outbreak response, along with tracking information about cases (the project we have already created), Dracula would also like to track information about interventions. -Create new local repository for `interventions` and connect it with a remote repository: +1. Create new local repository for `interventions` and connect it with a remote repository. + +2. Create a `read-data.R` file. + +3. Add and commit that change to the local repository. -- First, if you are in Rstudio, close your R Project from `File` > `Close Project`. -- In the Console, run: +4. Push that change to the remote repository. + +::::::::::::::::: solutions + +First, if you are in Rstudio, close your R Project from `File` > `Close Project`. + +In the Console, run: ```r # create a new R project in a new directory @@ -452,27 +374,30 @@ usethis::use_git() usethis::use_github() ``` -```output -ℹ Defaulting to 'https' Git protocol -✔ Creating GitHub repository 'vlad/cases' -✔ Setting remote 'origin' to 'https://github.com/vlad/cases.git' -✔ Pushing 'main' branch to GitHub and setting 'origin/main' as upstream branch -✔ Opening URL 'https://github.com/vlad/cases' +Create the file + +```r +usethis::edit_file("read-data.R") ``` -This will open a new tab in your web browser with the URL path of your remote repository in GitHub. +In the Terminal, run: +```bash +$ git add read-data.R +$ git commit -m "Add read data file" +$ git push +``` ::::::::::::::::: - +:::::::::::::::::::::::::::::::::: ## Pull changes We can pull changes from the remote repository to the local one as well: ```bash -$ git pull origin main +$ git pull ``` ```output @@ -485,6 +410,69 @@ Pulling has no effect in this case because the two repositories are already synchronized. If someone else had pushed some changes to the repository on GitHub, though, this command would download them to our local repository. +## Group Challenges + +Take 5 minutes to solve this challenge! + +::::::::::::::::::::::::::::::::::::::: challenge + +## GitHub License and README files + +In this episode we learned about creating a remote repository on GitHub, but when you initialized your GitHub repo, you didn't add a README.md or a license file. + +1. Create a README file in the remote repository. + +2. Pull your changes from the remote to the local repository. + +::::::::::::::: hint + +Click in the **Add README** option. + +![](fig/readme-github-01.png) + +Copy and paste this minimal template of a `README.md` file: + +``` +# Situational Report + +This is a report for a disease outbreak investigation by Outbreak Missions. + +## Files + +- sitrep.Rmd + +## Authors + +- Wolfman +- Dracula +``` + +::::::::::::::: + +::::::::::::::: solution + +## Solution + +To pull changes from remote to local, use this command: + +```bash +$ git pull +``` + + +::::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::: checklist + +![Use `git pull` to download content from a remote repository to the workspace and update the local repository to match that content. Use `git push` to upload local repository content to a remote repository.](fig/cut-git-verb_map-09.png) + +::::::::::::::::::::::::::: + + +## Individual Challenges + ::::::::::::::::::::::::::::::::::::::: challenge ## GitHub GUI @@ -579,65 +567,6 @@ Commit only updates your local repository. :::::::::::::::::::::::::::::::::::::::::::::::::: -::::::::::::::::::::::::::::::::::::::: challenge - -## GitHub License and README files - -In this episode we learned about creating a remote repository on GitHub, but when you initialized -your GitHub repo, you didn't add a README.md or a license file. If you had, what do you think -would have happened when you tried to link your local and remote repositories? - -::::::::::::::: solution - -## Solution - -In this case, we'd see a merge conflict due to unrelated histories. When GitHub creates a -README.md file, it performs a commit in the remote repository. When you try to pull the remote -repository to your local repository, Git detects that they have histories that do not share a -common origin and refuses to merge. - -```bash -$ git pull origin main -``` - -```output -warning: no common commits -remote: Enumerating objects: 3, done. -remote: Counting objects: 100% (3/3), done. -remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 -Unpacking objects: 100% (3/3), done. -From https://github.com/vlad/cases - * branch main -> FETCH_HEAD - * [new branch] main -> origin/main -fatal: refusing to merge unrelated histories -``` - -You can force git to merge the two repositories with the option `--allow-unrelated-histories`. -Be careful when you use this option and carefully examine the contents of local and remote -repositories before merging. - -```bash -$ git pull --allow-unrelated-histories origin main -``` - -```output -From https://github.com/vlad/cases - * branch main -> FETCH_HEAD -Merge made by the 'recursive' strategy. -README.md | 1 + -1 file changed, 1 insertion(+) -create mode 100644 README.md -``` - -::::::::::::::::::::::::: - -:::::::::::::::::::::::::::::::::::::::::::::::::: - -::::::::::::::::: checklist - -![Use `git pull` to download content from a remote repository to the workspace and update the local repository to match that content. Use `git push` to upload local repository content to a remote repository.](fig/cut-git-verb_map-09.png) - -::::::::::::::::::::::::::: :::::::::::::::::::::::::::::::::::::::: keypoints From b8ba640a86dde39a6670c91cb48a34e4c8ff9f09 Mon Sep 17 00:00:00 2001 From: Andree Valle Campos Date: Tue, 5 Mar 2024 04:52:10 +0000 Subject: [PATCH 8/8] add readme figure --- episodes/fig/readme-github-01.png | Bin 0 -> 11292 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 episodes/fig/readme-github-01.png diff --git a/episodes/fig/readme-github-01.png b/episodes/fig/readme-github-01.png new file mode 100644 index 0000000000000000000000000000000000000000..cda776a164cb50ca2006a030572fc1c7978dd4b9 GIT binary patch literal 11292 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