├── .editorconfig ├── .github └── workflows │ ├── README.md │ ├── pr-close-signal.yaml │ ├── pr-comment.yaml │ ├── pr-post-remove-branch.yaml │ ├── pr-preflight.yaml │ ├── pr-receive.yaml │ ├── sandpaper-main.yaml │ ├── sandpaper-version.txt │ ├── update-cache.yaml │ └── update-workflows.yaml ├── .gitignore ├── .mailmap ├── .update-copyright.conf ├── .zenodo.json ├── AUTHORS ├── CITATION ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── config.yaml ├── episodes ├── 01-basics.md ├── 02-setup.md ├── 03-create.md ├── 04-changes.md ├── 05-history.md ├── 06-ignore.md ├── 07-github.md ├── 08-collab.md ├── 09-conflict.md ├── 10-open.md ├── 11-licensing.md ├── 12-citation.md ├── 13-hosting.md ├── 14-supplemental-rstudio.md └── fig │ ├── RStudio_screenshot_afterclone.png │ ├── RStudio_screenshot_commit.png │ ├── RStudio_screenshot_editfiles.png │ ├── RStudio_screenshot_existingdirectory.png │ ├── RStudio_screenshot_gitignore.png │ ├── RStudio_screenshot_history.png │ ├── RStudio_screenshot_navigateexisting.png │ ├── RStudio_screenshot_newproject.png │ ├── RStudio_screenshot_review.png │ ├── RStudio_screenshot_viewhistory.png │ ├── conflict.svg │ ├── git-committing.svg │ ├── git-freshly-made-github-repo.svg │ ├── git-restore.svg │ ├── git-staging-area.svg │ ├── git_staging.svg │ ├── github-add-collaborators.png │ ├── github-change-repo-string.png │ ├── github-collaboration.svg │ ├── github-create-repo-01.png │ ├── github-create-repo-02.png │ ├── github-create-repo-03.png │ ├── github-find-repo-string.png │ ├── github-repo-after-first-push.svg │ ├── merge.svg │ ├── phd101212s.png │ ├── play-changes.svg │ └── versions.svg ├── index.md ├── instructors └── instructor-notes.md ├── learners ├── discuss.md ├── reference.md └── setup.md ├── profiles └── learner-profiles.md ├── requirements.txt └── site └── README.md /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | 8 | [*.md] 9 | indent_size = 2 10 | indent_style = space 11 | max_line_length = 100 # Please keep this in sync with bin/lesson_check.py! 12 | trim_trailing_whitespace = false # keep trailing spaces in markdown - 2+ spaces are translated to a hard break (
) 13 | 14 | [*.r] 15 | max_line_length = 80 16 | 17 | [*.py] 18 | indent_size = 4 19 | indent_style = space 20 | max_line_length = 79 21 | 22 | [*.sh] 23 | end_of_line = lf 24 | 25 | [Makefile] 26 | indent_style = tab 27 | -------------------------------------------------------------------------------- /.github/workflows/README.md: -------------------------------------------------------------------------------- 1 | # Carpentries Workflows 2 | 3 | This directory contains workflows to be used for Lessons using the {sandpaper} 4 | lesson infrastructure. Two of these workflows require R (`sandpaper-main.yaml` 5 | and `pr-receive.yaml`) and the rest are bots to handle pull request management. 6 | 7 | These workflows will likely change as {sandpaper} evolves, so it is important to 8 | keep them up-to-date. To do this in your lesson you can do the following in your 9 | R console: 10 | 11 | ```r 12 | # Install/Update sandpaper 13 | options(repos = c(carpentries = "https://carpentries.r-universe.dev/", 14 | CRAN = "https://cloud.r-project.org")) 15 | install.packages("sandpaper") 16 | 17 | # update the workflows in your lesson 18 | library("sandpaper") 19 | update_github_workflows() 20 | ``` 21 | 22 | Inside this folder, you will find a file called `sandpaper-version.txt`, which 23 | will contain a version number for sandpaper. This will be used in the future to 24 | alert you if a workflow update is needed. 25 | 26 | What follows are the descriptions of the workflow files: 27 | 28 | ## Deployment 29 | 30 | ### 01 Build and Deploy (sandpaper-main.yaml) 31 | 32 | This is the main driver that will only act on the main branch of the repository. 33 | This workflow does the following: 34 | 35 | 1. checks out the lesson 36 | 2. provisions the following resources 37 | - R 38 | - pandoc 39 | - lesson infrastructure (stored in a cache) 40 | - lesson dependencies if needed (stored in a cache) 41 | 3. builds the lesson via `sandpaper:::ci_deploy()` 42 | 43 | #### Caching 44 | 45 | This workflow has two caches; one cache is for the lesson infrastructure and 46 | the other is for the lesson dependencies if the lesson contains rendered 47 | content. These caches are invalidated by new versions of the infrastructure and 48 | the `renv.lock` file, respectively. If there is a problem with the cache, 49 | manual invaliation is necessary. You will need maintain access to the repository 50 | and you can either go to the actions tab and [click on the caches button to find 51 | and invalidate the failing cache](https://github.blog/changelog/2022-10-20-manage-caches-in-your-actions-workflows-from-web-interface/) 52 | or by setting the `CACHE_VERSION` secret to the current date (which will 53 | invalidate all of the caches). 54 | 55 | ## Updates 56 | 57 | ### Setup Information 58 | 59 | These workflows run on a schedule and at the maintainer's request. Because they 60 | create pull requests that update workflows/require the downstream actions to run, 61 | they need a special repository/organization secret token called 62 | `SANDPAPER_WORKFLOW` and it must have the `public_repo` and `workflow` scope. 63 | 64 | This can be an individual user token, OR it can be a trusted bot account. If you 65 | have a repository in one of the official Carpentries accounts, then you do not 66 | need to worry about this token being present because the Carpentries Core Team 67 | will take care of supplying this token. 68 | 69 | If you want to use your personal account: you can go to 70 | 71 | to create a token. Once you have created your token, you should copy it to your 72 | clipboard and then go to your repository's settings > secrets > actions and 73 | create or edit the `SANDPAPER_WORKFLOW` secret, pasting in the generated token. 74 | 75 | If you do not specify your token correctly, the runs will not fail and they will 76 | give you instructions to provide the token for your repository. 77 | 78 | ### 02 Maintain: Update Workflow Files (update-workflow.yaml) 79 | 80 | The {sandpaper} repository was designed to do as much as possible to separate 81 | the tools from the content. For local builds, this is absolutely true, but 82 | there is a minor issue when it comes to workflow files: they must live inside 83 | the repository. 84 | 85 | This workflow ensures that the workflow files are up-to-date. The way it work is 86 | to download the update-workflows.sh script from GitHub and run it. The script 87 | will do the following: 88 | 89 | 1. check the recorded version of sandpaper against the current version on github 90 | 2. update the files if there is a difference in versions 91 | 92 | After the files are updated, if there are any changes, they are pushed to a 93 | branch called `update/workflows` and a pull request is created. Maintainers are 94 | encouraged to review the changes and accept the pull request if the outputs 95 | are okay. 96 | 97 | This update is run weekly or on demand. 98 | 99 | ### 03 Maintain: Update Package Cache (update-cache.yaml) 100 | 101 | For lessons that have generated content, we use {renv} to ensure that the output 102 | is stable. This is controlled by a single lockfile which documents the packages 103 | needed for the lesson and the version numbers. This workflow is skipped in 104 | lessons that do not have generated content. 105 | 106 | Because the lessons need to remain current with the package ecosystem, it's a 107 | good idea to make sure these packages can be updated periodically. The 108 | update cache workflow will do this by checking for updates, applying them in a 109 | branch called `updates/packages` and creating a pull request with _only the 110 | lockfile changed_. 111 | 112 | From here, the markdown documents will be rebuilt and you can inspect what has 113 | changed based on how the packages have updated. 114 | 115 | ## Pull Request and Review Management 116 | 117 | Because our lessons execute code, pull requests are a secruity risk for any 118 | lesson and thus have security measures associted with them. **Do not merge any 119 | pull requests that do not pass checks and do not have bots commented on them.** 120 | 121 | This series of workflows all go together and are described in the following 122 | diagram and the below sections: 123 | 124 | ![Graph representation of a pull request](https://carpentries.github.io/sandpaper/articles/img/pr-flow.dot.svg) 125 | 126 | ### Pre Flight Pull Request Validation (pr-preflight.yaml) 127 | 128 | This workflow runs every time a pull request is created and its purpose is to 129 | validate that the pull request is okay to run. This means the following things: 130 | 131 | 1. The pull request does not contain modified workflow files 132 | 2. If the pull request contains modified workflow files, it does not contain 133 | modified content files (such as a situation where @carpentries-bot will 134 | make an automated pull request) 135 | 3. The pull request does not contain an invalid commit hash (e.g. from a fork 136 | that was made before a lesson was transitioned from styles to use the 137 | workbench). 138 | 139 | Once the checks are finished, a comment is issued to the pull request, which 140 | will allow maintainers to determine if it is safe to run the 141 | "Receive Pull Request" workflow from new contributors. 142 | 143 | ### Receive Pull Request (pr-receive.yaml) 144 | 145 | **Note of caution:** This workflow runs arbitrary code by anyone who creates a 146 | pull request. GitHub has safeguarded the token used in this workflow to have no 147 | priviledges in the repository, but we have taken precautions to protect against 148 | spoofing. 149 | 150 | This workflow is triggered with every push to a pull request. If this workflow 151 | is already running and a new push is sent to the pull request, the workflow 152 | running from the previous push will be cancelled and a new workflow run will be 153 | started. 154 | 155 | The first step of this workflow is to check if it is valid (e.g. that no 156 | workflow files have been modified). If there are workflow files that have been 157 | modified, a comment is made that indicates that the workflow is not run. If 158 | both a workflow file and lesson content is modified, an error will occurr. 159 | 160 | The second step (if valid) is to build the generated content from the pull 161 | request. This builds the content and uploads three artifacts: 162 | 163 | 1. The pull request number (pr) 164 | 2. A summary of changes after the rendering process (diff) 165 | 3. The rendered files (build) 166 | 167 | Because this workflow builds generated content, it follows the same general 168 | process as the `sandpaper-main` workflow with the same caching mechanisms. 169 | 170 | The artifacts produced are used by the next workflow. 171 | 172 | ### Comment on Pull Request (pr-comment.yaml) 173 | 174 | This workflow is triggered if the `pr-receive.yaml` workflow is successful. 175 | The steps in this workflow are: 176 | 177 | 1. Test if the workflow is valid and comment the validity of the workflow to the 178 | pull request. 179 | 2. If it is valid: create an orphan branch with two commits: the current state 180 | of the repository and the proposed changes. 181 | 3. If it is valid: update the pull request comment with the summary of changes 182 | 183 | Importantly: if the pull request is invalid, the branch is not created so any 184 | malicious code is not published. 185 | 186 | From here, the maintainer can request changes from the author and eventually 187 | either merge or reject the PR. When this happens, if the PR was valid, the 188 | preview branch needs to be deleted. 189 | 190 | ### Send Close PR Signal (pr-close-signal.yaml) 191 | 192 | Triggered any time a pull request is closed. This emits an artifact that is the 193 | pull request number for the next action 194 | 195 | ### Remove Pull Request Branch (pr-post-remove-branch.yaml) 196 | 197 | Tiggered by `pr-close-signal.yaml`. This removes the temporary branch associated with 198 | the pull request (if it was created). 199 | -------------------------------------------------------------------------------- /.github/workflows/pr-close-signal.yaml: -------------------------------------------------------------------------------- 1 | name: "Bot: Send Close Pull Request Signal" 2 | 3 | on: 4 | pull_request: 5 | types: 6 | [closed] 7 | 8 | jobs: 9 | send-close-signal: 10 | name: "Send closing signal" 11 | runs-on: ubuntu-22.04 12 | if: ${{ github.event.action == 'closed' }} 13 | steps: 14 | - name: "Create PRtifact" 15 | run: | 16 | mkdir -p ./pr 17 | printf ${{ github.event.number }} > ./pr/NUM 18 | - name: Upload Diff 19 | uses: actions/upload-artifact@v4 20 | with: 21 | name: pr 22 | path: ./pr 23 | -------------------------------------------------------------------------------- /.github/workflows/pr-comment.yaml: -------------------------------------------------------------------------------- 1 | name: "Bot: Comment on the Pull Request" 2 | 3 | # read-write repo token 4 | # access to secrets 5 | on: 6 | workflow_run: 7 | workflows: ["Receive Pull Request"] 8 | types: 9 | - completed 10 | 11 | concurrency: 12 | group: pr-${{ github.event.workflow_run.pull_requests[0].number }} 13 | cancel-in-progress: true 14 | 15 | 16 | jobs: 17 | # Pull requests are valid if: 18 | # - they match the sha of the workflow run head commit 19 | # - they are open 20 | # - no .github files were committed 21 | test-pr: 22 | name: "Test if pull request is valid" 23 | runs-on: ubuntu-22.04 24 | if: > 25 | github.event.workflow_run.event == 'pull_request' && 26 | github.event.workflow_run.conclusion == 'success' 27 | outputs: 28 | is_valid: ${{ steps.check-pr.outputs.VALID }} 29 | payload: ${{ steps.check-pr.outputs.payload }} 30 | number: ${{ steps.get-pr.outputs.NUM }} 31 | msg: ${{ steps.check-pr.outputs.MSG }} 32 | steps: 33 | - name: 'Download PR artifact' 34 | id: dl 35 | uses: carpentries/actions/download-workflow-artifact@main 36 | with: 37 | run: ${{ github.event.workflow_run.id }} 38 | name: 'pr' 39 | 40 | - name: "Get PR Number" 41 | if: ${{ steps.dl.outputs.success == 'true' }} 42 | id: get-pr 43 | run: | 44 | unzip pr.zip 45 | echo "NUM=$(<./NR)" >> $GITHUB_OUTPUT 46 | 47 | - name: "Fail if PR number was not present" 48 | id: bad-pr 49 | if: ${{ steps.dl.outputs.success != 'true' }} 50 | run: | 51 | echo '::error::A pull request number was not recorded. The pull request that triggered this workflow is likely malicious.' 52 | exit 1 53 | - name: "Get Invalid Hashes File" 54 | id: hash 55 | run: | 56 | echo "json<> $GITHUB_OUTPUT 59 | - name: "Check PR" 60 | id: check-pr 61 | if: ${{ steps.dl.outputs.success == 'true' }} 62 | uses: carpentries/actions/check-valid-pr@main 63 | with: 64 | pr: ${{ steps.get-pr.outputs.NUM }} 65 | sha: ${{ github.event.workflow_run.head_sha }} 66 | headroom: 3 # if it's within the last three commits, we can keep going, because it's likely rapid-fire 67 | invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} 68 | fail_on_error: true 69 | 70 | # Create an orphan branch on this repository with two commits 71 | # - the current HEAD of the md-outputs branch 72 | # - the output from running the current HEAD of the pull request through 73 | # the md generator 74 | create-branch: 75 | name: "Create Git Branch" 76 | needs: test-pr 77 | runs-on: ubuntu-22.04 78 | if: ${{ needs.test-pr.outputs.is_valid == 'true' }} 79 | env: 80 | NR: ${{ needs.test-pr.outputs.number }} 81 | permissions: 82 | contents: write 83 | steps: 84 | - name: 'Checkout md outputs' 85 | uses: actions/checkout@v4 86 | with: 87 | ref: md-outputs 88 | path: built 89 | fetch-depth: 1 90 | 91 | - name: 'Download built markdown' 92 | id: dl 93 | uses: carpentries/actions/download-workflow-artifact@main 94 | with: 95 | run: ${{ github.event.workflow_run.id }} 96 | name: 'built' 97 | 98 | - if: ${{ steps.dl.outputs.success == 'true' }} 99 | run: unzip built.zip 100 | 101 | - name: "Create orphan and push" 102 | if: ${{ steps.dl.outputs.success == 'true' }} 103 | run: | 104 | cd built/ 105 | git config --local user.email "actions@github.com" 106 | git config --local user.name "GitHub Actions" 107 | CURR_HEAD=$(git rev-parse HEAD) 108 | git checkout --orphan md-outputs-PR-${NR} 109 | git add -A 110 | git commit -m "source commit: ${CURR_HEAD}" 111 | ls -A | grep -v '^.git$' | xargs -I _ rm -r '_' 112 | cd .. 113 | unzip -o -d built built.zip 114 | cd built 115 | git add -A 116 | git commit --allow-empty -m "differences for PR #${NR}" 117 | git push -u --force --set-upstream origin md-outputs-PR-${NR} 118 | 119 | # Comment on the Pull Request with a link to the branch and the diff 120 | comment-pr: 121 | name: "Comment on Pull Request" 122 | needs: [test-pr, create-branch] 123 | runs-on: ubuntu-22.04 124 | if: ${{ needs.test-pr.outputs.is_valid == 'true' }} 125 | env: 126 | NR: ${{ needs.test-pr.outputs.number }} 127 | permissions: 128 | pull-requests: write 129 | steps: 130 | - name: 'Download comment artifact' 131 | id: dl 132 | uses: carpentries/actions/download-workflow-artifact@main 133 | with: 134 | run: ${{ github.event.workflow_run.id }} 135 | name: 'diff' 136 | 137 | - if: ${{ steps.dl.outputs.success == 'true' }} 138 | run: unzip ${{ github.workspace }}/diff.zip 139 | 140 | - name: "Comment on PR" 141 | id: comment-diff 142 | if: ${{ steps.dl.outputs.success == 'true' }} 143 | uses: carpentries/actions/comment-diff@main 144 | with: 145 | pr: ${{ env.NR }} 146 | path: ${{ github.workspace }}/diff.md 147 | 148 | # Comment if the PR is open and matches the SHA, but the workflow files have 149 | # changed 150 | comment-changed-workflow: 151 | name: "Comment if workflow files have changed" 152 | needs: test-pr 153 | runs-on: ubuntu-22.04 154 | if: ${{ always() && needs.test-pr.outputs.is_valid == 'false' }} 155 | env: 156 | NR: ${{ github.event.workflow_run.pull_requests[0].number }} 157 | body: ${{ needs.test-pr.outputs.msg }} 158 | permissions: 159 | pull-requests: write 160 | steps: 161 | - name: 'Check for spoofing' 162 | id: dl 163 | uses: carpentries/actions/download-workflow-artifact@main 164 | with: 165 | run: ${{ github.event.workflow_run.id }} 166 | name: 'built' 167 | 168 | - name: 'Alert if spoofed' 169 | id: spoof 170 | if: ${{ steps.dl.outputs.success == 'true' }} 171 | run: | 172 | echo 'body<> $GITHUB_ENV 173 | echo '' >> $GITHUB_ENV 174 | echo '## :x: DANGER :x:' >> $GITHUB_ENV 175 | echo 'This pull request has modified workflows that created output. Close this now.' >> $GITHUB_ENV 176 | echo '' >> $GITHUB_ENV 177 | echo 'EOF' >> $GITHUB_ENV 178 | 179 | - name: "Comment on PR" 180 | id: comment-diff 181 | uses: carpentries/actions/comment-diff@main 182 | with: 183 | pr: ${{ env.NR }} 184 | body: ${{ env.body }} 185 | -------------------------------------------------------------------------------- /.github/workflows/pr-post-remove-branch.yaml: -------------------------------------------------------------------------------- 1 | name: "Bot: Remove Temporary PR Branch" 2 | 3 | on: 4 | workflow_run: 5 | workflows: ["Bot: Send Close Pull Request Signal"] 6 | types: 7 | - completed 8 | 9 | jobs: 10 | delete: 11 | name: "Delete branch from Pull Request" 12 | runs-on: ubuntu-22.04 13 | if: > 14 | github.event.workflow_run.event == 'pull_request' && 15 | github.event.workflow_run.conclusion == 'success' 16 | permissions: 17 | contents: write 18 | steps: 19 | - name: 'Download artifact' 20 | uses: carpentries/actions/download-workflow-artifact@main 21 | with: 22 | run: ${{ github.event.workflow_run.id }} 23 | name: pr 24 | - name: "Get PR Number" 25 | id: get-pr 26 | run: | 27 | unzip pr.zip 28 | echo "NUM=$(<./NUM)" >> $GITHUB_OUTPUT 29 | - name: 'Remove branch' 30 | uses: carpentries/actions/remove-branch@main 31 | with: 32 | pr: ${{ steps.get-pr.outputs.NUM }} 33 | -------------------------------------------------------------------------------- /.github/workflows/pr-preflight.yaml: -------------------------------------------------------------------------------- 1 | name: "Pull Request Preflight Check" 2 | 3 | on: 4 | pull_request_target: 5 | branches: 6 | ["main"] 7 | types: 8 | ["opened", "synchronize", "reopened"] 9 | 10 | jobs: 11 | test-pr: 12 | name: "Test if pull request is valid" 13 | if: ${{ github.event.action != 'closed' }} 14 | runs-on: ubuntu-22.04 15 | outputs: 16 | is_valid: ${{ steps.check-pr.outputs.VALID }} 17 | permissions: 18 | pull-requests: write 19 | steps: 20 | - name: "Get Invalid Hashes File" 21 | id: hash 22 | run: | 23 | echo "json<> $GITHUB_OUTPUT 26 | - name: "Check PR" 27 | id: check-pr 28 | uses: carpentries/actions/check-valid-pr@main 29 | with: 30 | pr: ${{ github.event.number }} 31 | invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} 32 | fail_on_error: true 33 | - name: "Comment result of validation" 34 | id: comment-diff 35 | if: ${{ always() }} 36 | uses: carpentries/actions/comment-diff@main 37 | with: 38 | pr: ${{ github.event.number }} 39 | body: ${{ steps.check-pr.outputs.MSG }} 40 | -------------------------------------------------------------------------------- /.github/workflows/pr-receive.yaml: -------------------------------------------------------------------------------- 1 | name: "Receive Pull Request" 2 | 3 | on: 4 | pull_request: 5 | types: 6 | [opened, synchronize, reopened] 7 | 8 | concurrency: 9 | group: ${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | test-pr: 14 | name: "Record PR number" 15 | if: ${{ github.event.action != 'closed' }} 16 | runs-on: ubuntu-22.04 17 | outputs: 18 | is_valid: ${{ steps.check-pr.outputs.VALID }} 19 | steps: 20 | - name: "Record PR number" 21 | id: record 22 | if: ${{ always() }} 23 | run: | 24 | echo ${{ github.event.number }} > ${{ github.workspace }}/NR # 2022-03-02: artifact name fixed to be NR 25 | - name: "Upload PR number" 26 | id: upload 27 | if: ${{ always() }} 28 | uses: actions/upload-artifact@v4 29 | with: 30 | name: pr 31 | path: ${{ github.workspace }}/NR 32 | - name: "Get Invalid Hashes File" 33 | id: hash 34 | run: | 35 | echo "json<> $GITHUB_OUTPUT 38 | - name: "echo output" 39 | run: | 40 | echo "${{ steps.hash.outputs.json }}" 41 | - name: "Check PR" 42 | id: check-pr 43 | uses: carpentries/actions/check-valid-pr@main 44 | with: 45 | pr: ${{ github.event.number }} 46 | invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} 47 | 48 | build-md-source: 49 | name: "Build markdown source files if valid" 50 | needs: test-pr 51 | runs-on: ubuntu-22.04 52 | if: ${{ needs.test-pr.outputs.is_valid == 'true' }} 53 | env: 54 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 55 | RENV_PATHS_ROOT: ~/.local/share/renv/ 56 | CHIVE: ${{ github.workspace }}/site/chive 57 | PR: ${{ github.workspace }}/site/pr 58 | MD: ${{ github.workspace }}/site/built 59 | steps: 60 | - name: "Check Out Main Branch" 61 | uses: actions/checkout@v4 62 | 63 | - name: "Check Out Staging Branch" 64 | uses: actions/checkout@v4 65 | with: 66 | ref: md-outputs 67 | path: ${{ env.MD }} 68 | 69 | - name: "Set up R" 70 | uses: r-lib/actions/setup-r@v2 71 | with: 72 | use-public-rspm: true 73 | install-r: false 74 | 75 | - name: "Set up Pandoc" 76 | uses: r-lib/actions/setup-pandoc@v2 77 | 78 | - name: "Setup Lesson Engine" 79 | uses: carpentries/actions/setup-sandpaper@main 80 | with: 81 | cache-version: ${{ secrets.CACHE_VERSION }} 82 | 83 | - name: "Setup Package Cache" 84 | uses: carpentries/actions/setup-lesson-deps@main 85 | with: 86 | cache-version: ${{ secrets.CACHE_VERSION }} 87 | 88 | - name: "Validate and Build Markdown" 89 | id: build-site 90 | run: | 91 | sandpaper::package_cache_trigger(TRUE) 92 | sandpaper::validate_lesson(path = '${{ github.workspace }}') 93 | sandpaper:::build_markdown(path = '${{ github.workspace }}', quiet = FALSE) 94 | shell: Rscript {0} 95 | 96 | - name: "Generate Artifacts" 97 | id: generate-artifacts 98 | run: | 99 | sandpaper:::ci_bundle_pr_artifacts( 100 | repo = '${{ github.repository }}', 101 | pr_number = '${{ github.event.number }}', 102 | path_md = '${{ env.MD }}', 103 | path_pr = '${{ env.PR }}', 104 | path_archive = '${{ env.CHIVE }}', 105 | branch = 'md-outputs' 106 | ) 107 | shell: Rscript {0} 108 | 109 | - name: "Upload PR" 110 | uses: actions/upload-artifact@v4 111 | with: 112 | name: pr 113 | path: ${{ env.PR }} 114 | overwrite: true 115 | 116 | - name: "Upload Diff" 117 | uses: actions/upload-artifact@v4 118 | with: 119 | name: diff 120 | path: ${{ env.CHIVE }} 121 | retention-days: 1 122 | 123 | - name: "Upload Build" 124 | uses: actions/upload-artifact@v4 125 | with: 126 | name: built 127 | path: ${{ env.MD }} 128 | retention-days: 1 129 | 130 | - name: "Teardown" 131 | run: sandpaper::reset_site() 132 | shell: Rscript {0} 133 | -------------------------------------------------------------------------------- /.github/workflows/sandpaper-main.yaml: -------------------------------------------------------------------------------- 1 | name: "01 Build and Deploy Site" 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | schedule: 9 | - cron: '0 0 * * 2' 10 | workflow_dispatch: 11 | inputs: 12 | name: 13 | description: 'Who triggered this build?' 14 | required: true 15 | default: 'Maintainer (via GitHub)' 16 | reset: 17 | description: 'Reset cached markdown files' 18 | required: false 19 | default: false 20 | type: boolean 21 | jobs: 22 | full-build: 23 | name: "Build Full Site" 24 | 25 | # 2024-10-01: ubuntu-latest is now 24.04 and R is not installed by default in the runner image 26 | # pin to 22.04 for now 27 | runs-on: ubuntu-22.04 28 | permissions: 29 | checks: write 30 | contents: write 31 | pages: write 32 | env: 33 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 34 | RENV_PATHS_ROOT: ~/.local/share/renv/ 35 | steps: 36 | 37 | - name: "Checkout Lesson" 38 | uses: actions/checkout@v4 39 | 40 | - name: "Set up R" 41 | uses: r-lib/actions/setup-r@v2 42 | with: 43 | use-public-rspm: true 44 | install-r: false 45 | 46 | - name: "Set up Pandoc" 47 | uses: r-lib/actions/setup-pandoc@v2 48 | 49 | - name: "Setup Lesson Engine" 50 | uses: carpentries/actions/setup-sandpaper@main 51 | with: 52 | cache-version: ${{ secrets.CACHE_VERSION }} 53 | 54 | - name: "Setup Package Cache" 55 | uses: carpentries/actions/setup-lesson-deps@main 56 | with: 57 | cache-version: ${{ secrets.CACHE_VERSION }} 58 | 59 | - name: "Deploy Site" 60 | run: | 61 | reset <- "${{ github.event.inputs.reset }}" == "true" 62 | sandpaper::package_cache_trigger(TRUE) 63 | sandpaper:::ci_deploy(reset = reset) 64 | shell: Rscript {0} 65 | -------------------------------------------------------------------------------- /.github/workflows/sandpaper-version.txt: -------------------------------------------------------------------------------- 1 | 0.16.12 2 | -------------------------------------------------------------------------------- /.github/workflows/update-cache.yaml: -------------------------------------------------------------------------------- 1 | name: "03 Maintain: Update Package Cache" 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | name: 7 | description: 'Who triggered this build (enter github username to tag yourself)?' 8 | required: true 9 | default: 'monthly run' 10 | schedule: 11 | # Run every tuesday 12 | - cron: '0 0 * * 2' 13 | 14 | jobs: 15 | preflight: 16 | name: "Preflight Check" 17 | runs-on: ubuntu-22.04 18 | outputs: 19 | ok: ${{ steps.check.outputs.ok }} 20 | steps: 21 | - id: check 22 | run: | 23 | if [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then 24 | echo "ok=true" >> $GITHUB_OUTPUT 25 | echo "Running on request" 26 | # using single brackets here to avoid 08 being interpreted as octal 27 | # https://github.com/carpentries/sandpaper/issues/250 28 | elif [ `date +%d` -le 7 ]; then 29 | # If the Tuesday lands in the first week of the month, run it 30 | echo "ok=true" >> $GITHUB_OUTPUT 31 | echo "Running on schedule" 32 | else 33 | echo "ok=false" >> $GITHUB_OUTPUT 34 | echo "Not Running Today" 35 | fi 36 | 37 | check_renv: 38 | name: "Check if We Need {renv}" 39 | runs-on: ubuntu-22.04 40 | needs: preflight 41 | if: ${{ needs.preflight.outputs.ok == 'true'}} 42 | outputs: 43 | needed: ${{ steps.renv.outputs.exists }} 44 | steps: 45 | - name: "Checkout Lesson" 46 | uses: actions/checkout@v4 47 | - id: renv 48 | run: | 49 | if [[ -d renv ]]; then 50 | echo "exists=true" >> $GITHUB_OUTPUT 51 | fi 52 | 53 | check_token: 54 | name: "Check SANDPAPER_WORKFLOW token" 55 | runs-on: ubuntu-22.04 56 | needs: check_renv 57 | if: ${{ needs.check_renv.outputs.needed == 'true' }} 58 | outputs: 59 | workflow: ${{ steps.validate.outputs.wf }} 60 | repo: ${{ steps.validate.outputs.repo }} 61 | steps: 62 | - name: "validate token" 63 | id: validate 64 | uses: carpentries/actions/check-valid-credentials@main 65 | with: 66 | token: ${{ secrets.SANDPAPER_WORKFLOW }} 67 | 68 | update_cache: 69 | name: "Update Package Cache" 70 | needs: check_token 71 | if: ${{ needs.check_token.outputs.repo== 'true' }} 72 | runs-on: ubuntu-22.04 73 | env: 74 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 75 | RENV_PATHS_ROOT: ~/.local/share/renv/ 76 | steps: 77 | 78 | - name: "Checkout Lesson" 79 | uses: actions/checkout@v4 80 | 81 | - name: "Set up R" 82 | uses: r-lib/actions/setup-r@v2 83 | with: 84 | use-public-rspm: true 85 | install-r: false 86 | 87 | - name: "Update {renv} deps and determine if a PR is needed" 88 | id: update 89 | uses: carpentries/actions/update-lockfile@main 90 | with: 91 | cache-version: ${{ secrets.CACHE_VERSION }} 92 | 93 | - name: Create Pull Request 94 | id: cpr 95 | if: ${{ steps.update.outputs.n > 0 }} 96 | uses: carpentries/create-pull-request@main 97 | with: 98 | token: ${{ secrets.SANDPAPER_WORKFLOW }} 99 | delete-branch: true 100 | branch: "update/packages" 101 | commit-message: "[actions] update ${{ steps.update.outputs.n }} packages" 102 | title: "Update ${{ steps.update.outputs.n }} packages" 103 | body: | 104 | :robot: This is an automated build 105 | 106 | This will update ${{ steps.update.outputs.n }} packages in your lesson with the following versions: 107 | 108 | ``` 109 | ${{ steps.update.outputs.report }} 110 | ``` 111 | 112 | :stopwatch: In a few minutes, a comment will appear that will show you how the output has changed based on these updates. 113 | 114 | If you want to inspect these changes locally, you can use the following code to check out a new branch: 115 | 116 | ```bash 117 | git fetch origin update/packages 118 | git checkout update/packages 119 | ``` 120 | 121 | - Auto-generated by [create-pull-request][1] on ${{ steps.update.outputs.date }} 122 | 123 | [1]: https://github.com/carpentries/create-pull-request/tree/main 124 | labels: "type: package cache" 125 | draft: false 126 | -------------------------------------------------------------------------------- /.github/workflows/update-workflows.yaml: -------------------------------------------------------------------------------- 1 | name: "02 Maintain: Update Workflow Files" 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | name: 7 | description: 'Who triggered this build (enter github username to tag yourself)?' 8 | required: true 9 | default: 'weekly run' 10 | clean: 11 | description: 'Workflow files/file extensions to clean (no wildcards, enter "" for none)' 12 | required: false 13 | default: '.yaml' 14 | schedule: 15 | # Run every Tuesday 16 | - cron: '0 0 * * 2' 17 | 18 | jobs: 19 | check_token: 20 | name: "Check SANDPAPER_WORKFLOW token" 21 | runs-on: ubuntu-22.04 22 | outputs: 23 | workflow: ${{ steps.validate.outputs.wf }} 24 | repo: ${{ steps.validate.outputs.repo }} 25 | steps: 26 | - name: "validate token" 27 | id: validate 28 | uses: carpentries/actions/check-valid-credentials@main 29 | with: 30 | token: ${{ secrets.SANDPAPER_WORKFLOW }} 31 | 32 | update_workflow: 33 | name: "Update Workflow" 34 | runs-on: ubuntu-22.04 35 | needs: check_token 36 | if: ${{ needs.check_token.outputs.workflow == 'true' }} 37 | steps: 38 | - name: "Checkout Repository" 39 | uses: actions/checkout@v4 40 | 41 | - name: Update Workflows 42 | id: update 43 | uses: carpentries/actions/update-workflows@main 44 | with: 45 | clean: ${{ github.event.inputs.clean }} 46 | 47 | - name: Create Pull Request 48 | id: cpr 49 | if: "${{ steps.update.outputs.new }}" 50 | uses: carpentries/create-pull-request@main 51 | with: 52 | token: ${{ secrets.SANDPAPER_WORKFLOW }} 53 | delete-branch: true 54 | branch: "update/workflows" 55 | commit-message: "[actions] update sandpaper workflow to version ${{ steps.update.outputs.new }}" 56 | title: "Update Workflows to Version ${{ steps.update.outputs.new }}" 57 | body: | 58 | :robot: This is an automated build 59 | 60 | Update Workflows from sandpaper version ${{ steps.update.outputs.old }} -> ${{ steps.update.outputs.new }} 61 | 62 | - Auto-generated by [create-pull-request][1] on ${{ steps.update.outputs.date }} 63 | 64 | [1]: https://github.com/carpentries/create-pull-request/tree/main 65 | labels: "type: template and tools" 66 | draft: false 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # sandpaper files 2 | episodes/*html 3 | site/* 4 | !site/README.md 5 | 6 | # History files 7 | .Rhistory 8 | .Rapp.history 9 | # Session Data files 10 | .RData 11 | # User-specific files 12 | .Ruserdata 13 | # Example code in package build process 14 | *-Ex.R 15 | # Output files from R CMD build 16 | /*.tar.gz 17 | # Output files from R CMD check 18 | /*.Rcheck/ 19 | # RStudio files 20 | .Rproj.user/ 21 | # produced vignettes 22 | vignettes/*.html 23 | vignettes/*.pdf 24 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 25 | .httr-oauth 26 | # knitr and R markdown default cache directories 27 | *_cache/ 28 | /cache/ 29 | # Temporary files created by R markdown 30 | *.utf8.md 31 | *.knit.md 32 | # R Environment Variables 33 | .Renviron 34 | # pkgdown site 35 | docs/ 36 | # translation temp files 37 | po/*~ 38 | # renv detritus 39 | renv/sandbox/ 40 | *.pyc 41 | *~ 42 | .DS_Store 43 | .ipynb_checkpoints 44 | .sass-cache 45 | .jekyll-cache/ 46 | .jekyll-metadata 47 | __pycache__ 48 | _site 49 | .Rproj.user 50 | .bundle/ 51 | .vendor/ 52 | vendor/ 53 | .docker-vendor/ 54 | Gemfile.lock 55 | .*history 56 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Abigail Cabunoc Mayes 2 | Abigail Cabunoc Mayes 3 | Alois Heilmaier 4 | Andrew Lonsdale 5 | Andrew Rohl 6 | Ariel Rokem 7 | Arnstein Orten 8 | Bennet Fauber 9 | Bérénice Batut 10 | Bérénice Batut 11 | Bernhard Konrad 12 | Bill Mills 13 | Brenna O'Brien 14 | Chris Pawsey 15 | Christoph Junghans 16 | Daisie Huang 17 | Danielle Traphagen 18 | Dorota Jarecka 19 | Emily Dolson 20 | Emmanouil Farsarakis 21 | Erin Becker 22 | Evan P. Williamson 23 | François Michonneau 24 | Greg Watson 25 | Greg Wilson 26 | Ivan Gonzalez 27 | James Allen 28 | Jane Charlesworth 29 | Kate Lee 30 | Luke W. Johnston 31 | Marisa Guarinello 32 | Mark Wheelhouse 33 | Mary C. Kinniburgh 34 | Mateusz Kuzak 35 | Matthias Haeni 36 | Maxim Belkin 37 | Michael Panitz 38 | Mike Jackson 39 | Nicholas Hannah 40 | Nicola Soranzo 41 | Patrick C. Shriwise 42 | Pauline Barmby 43 | Peter Steinbach 44 | Raniere Silva 45 | Raniere Silva 46 | Rémi Emonet 47 | Rémi Emonet 48 | Sarah Stevens 49 | Sean Aubin 50 | Steve Vandervalk 51 | Tiffany Timbers 52 | Timothée Poisot 53 | Tom Kelly 54 | Vijay P. Nagraj 55 | Yuandra Ismiraldi 56 | zz-abracarambar 57 | -------------------------------------------------------------------------------- /.update-copyright.conf: -------------------------------------------------------------------------------- 1 | [project] 2 | vcs: Git 3 | 4 | [files] 5 | authors: yes 6 | files: no 7 | -------------------------------------------------------------------------------- /.zenodo.json: -------------------------------------------------------------------------------- 1 | { 2 | "contributors": [ 3 | { 4 | "type": "Editor", 5 | "name": "Katherine E. Koziar", 6 | "orcid": "0000-0003-0505-7973" 7 | }, 8 | { 9 | "type": "Editor", 10 | "name": "Nima S Hejazi", 11 | "orcid": "0000-0002-7127-2789" 12 | }, 13 | { 14 | "type": "Editor", 15 | "name": "Madicken Munk" 16 | }, 17 | { 18 | "type": "Editor", 19 | "name": "Scott Gruber", 20 | "orcid": "0000-0001-9780-351X" 21 | } 22 | ], 23 | "creators": [ 24 | { 25 | "name": "Katherine E. Koziar", 26 | "orcid": "0000-0003-0505-7973" 27 | }, 28 | { 29 | "name": "Madicken Munk" 30 | }, 31 | { 32 | "name": "Andrew Greene" 33 | }, 34 | { 35 | "name": "Annajiat Alim Rasel", 36 | "orcid": "0000-0003-0198-3734" 37 | }, 38 | { 39 | "name": "Ed Bennett", 40 | "orcid": "0000-0002-1678-6701" 41 | }, 42 | { 43 | "name": "Sarah LR Stevens", 44 | "orcid": "0000-0002-7040-548X" 45 | }, 46 | { 47 | "name": "Ece Turnator" 48 | }, 49 | { 50 | "name": "Jon Haitz Legarreta Gorroño", 51 | "orcid": "0000-0002-9661-1396" 52 | }, 53 | { 54 | "name": "Katrin Leinweber", 55 | "orcid": "0000-0001-5135-5758" 56 | }, 57 | { 58 | "name": "Lex Nederbragt", 59 | "orcid": "0000-0001-5539-0999" 60 | }, 61 | { 62 | "name": "Samuel Lelièvre", 63 | "orcid": "0000-0002-7275-0965" 64 | }, 65 | { 66 | "name": "Vyas Ramasubramani" 67 | }, 68 | { 69 | "name": "Anthony Gitter" 70 | }, 71 | { 72 | "name": "Daniela Cassol", 73 | "orcid": "0000-0003-2417-6337" 74 | }, 75 | { 76 | "name": "Judy Zhu" 77 | }, 78 | { 79 | "name": "Nicola Soranzo", 80 | "orcid": "0000-0003-3627-5340" 81 | }, 82 | { 83 | "name": "Nima S Hejazi", 84 | "orcid": "0000-0002-7127-2789" 85 | }, 86 | { 87 | "name": "Wouter Deconinck" 88 | }, 89 | { 90 | "name": "laurentheirendt" 91 | }, 92 | { 93 | "name": "Alison Clarke" 94 | }, 95 | { 96 | "name": "Camilla Bressan" 97 | }, 98 | { 99 | "name": "Charles Guan" 100 | }, 101 | { 102 | "name": "Cristina Urizar" 103 | }, 104 | { 105 | "name": "Dave Horsfall" 106 | }, 107 | { 108 | "name": "David" 109 | }, 110 | { 111 | "name": "Deborah" 112 | }, 113 | { 114 | "name": "Ed Lowther" 115 | }, 116 | { 117 | "name": "fwoerister" 118 | }, 119 | { 120 | "name": "François Bissey" 121 | }, 122 | { 123 | "name": "HaoZeke" 124 | }, 125 | { 126 | "name": "James Kent", 127 | "orcid": "0000-0002-4892-2659" 128 | }, 129 | { 130 | "name": "Jessica Holmes" 131 | }, 132 | { 133 | "name": "John Huddleston" 134 | }, 135 | { 136 | "name": "Juho Lehtonen" 137 | }, 138 | { 139 | "name": "Karen Word", 140 | "orcid": "0000-0002-7294-7231" 141 | }, 142 | { 143 | "name": "Kilian Lieret" 144 | }, 145 | { 146 | "name": "Luca Modenese", 147 | "orcid": "0000-0003-1402-5359" 148 | }, 149 | { 150 | "name": "Marco Foscato" 151 | }, 152 | { 153 | "name": "Marius Bjørnstad" 154 | }, 155 | { 156 | "name": "Mark Matney" 157 | }, 158 | { 159 | "name": "Matti Juvonen" 160 | }, 161 | { 162 | "name": "Maxim Belkin" 163 | }, 164 | { 165 | "name": "Mingrui Yang" 166 | }, 167 | { 168 | "name": "Olga Silantyeva", 169 | "orcid": "0000-0001-5440-6768" 170 | }, 171 | { 172 | "name": "Patrick McCann", 173 | "orcid": "0000-0002-9324-2775" 174 | }, 175 | { 176 | "name": "Riley Lanfear", 177 | "orcid": "0000-0001-9328-4513" 178 | }, 179 | { 180 | "name": "Sadie L. Bartholomew" 181 | }, 182 | { 183 | "name": "Sam Cox" 184 | }, 185 | { 186 | "name": "Scott Gruber", 187 | "orcid": "0000-0001-9780-351X" 188 | }, 189 | { 190 | "name": "Stewart Christopher Jamieson", 191 | "orcid": "0000-0003-4842-0373" 192 | }, 193 | { 194 | "name": "Sylwester Arabas", 195 | "orcid": "0000-0003-2361-0082" 196 | }, 197 | { 198 | "name": "Tom Russell" 199 | }, 200 | { 201 | "name": "Tuomas Koskela" 202 | }, 203 | { 204 | "name": "Will" 205 | }, 206 | { 207 | "name": "Wolff, Benjamin" 208 | }, 209 | { 210 | "name": "catherinef37", 211 | "orcid": "0000-0001-7003-4431" 212 | }, 213 | { 214 | "name": "Huijun ZHU" 215 | }, 216 | { 217 | "name": "kerimoff" 218 | } 219 | ], 220 | "license": { 221 | "id": "CC-BY-4.0" 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Alison Appling 2 | Sean Aubin 3 | Pete Bachant 4 | Daniel Baird 5 | Pauline Barmby 6 | Bérénice Batut 7 | Maxim Belkin 8 | Madeleine Bonsma 9 | Jon Borrelli 10 | Andy Boughton 11 | Daina Bouquin 12 | Rudi Brauning 13 | Matthew Brett 14 | Amy Brown 15 | Jane Charlesworth 16 | Billy Charlton 17 | Daniel Chen 18 | Garret Christensen 19 | Ruth Collings 20 | Marianne Corvellec 21 | Matt Davis 22 | Emily Dolson 23 | Laurent Duchesne 24 | Jonah Duckles 25 | Rémi Emonet 26 | Loïc Estève 27 | Emmanouil Farsarakis 28 | Bennet Fauber 29 | Anne Fouilloux 30 | Stuart Geiger 31 | Ivan Gonzalez 32 | Marisa Guarinello 33 | Stéphane Guillou 34 | Jamie Hadwin 35 | Matthias Haeni 36 | Pierre Haessig 37 | Nicholas Hannah 38 | Sumana Harihareswara 39 | Alois Heilmaier 40 | Martin Heroux 41 | Kate Hertweck 42 | Daisie Huang 43 | Yuandra Ismiraldi 44 | Christian Jacobs 45 | Dorota Jarecka 46 | Luke W. Johnston 47 | David Jones 48 | Zbigniew Jędrzejewski-Szmek 49 | Tom Kelly 50 | W. Trevor King 51 | Thomas Kluyver 52 | Bernhard Konrad 53 | Mateusz Kuzak 54 | Arne Küderle 55 | Kathleen Labrie 56 | Hilmar Lapp 57 | Mark Laufersweiler 58 | David LeBauer 59 | Kate Lee 60 | Matthias Liffers 61 | Clara Llebot 62 | Catrina Loucks 63 | Keith Ma 64 | Kunal Marwaha 65 | Ryan May 66 | Bill Mills 67 | Andreas Mueller 68 | Madicken Munk 69 | Juan Nunez-Iglesias 70 | Brenna O'Brien 71 | Catherine Olsson 72 | Michael Panitz 73 | Chris Pawsey 74 | Stefan Pfenninger 75 | Paul Preney 76 | Timothy Rice 77 | Kristina Riemer 78 | Annika Rockenberger 79 | Andrew Rohl 80 | Ariel Rokem 81 | Bill Sacks 82 | Michael Sarahan 83 | Sebastian Schmeier 84 | Hartmut Schmider 85 | Peter Shellito 86 | Patrick C. Shriwise 87 | Raniere Silva 88 | Brendan Smithyman 89 | Nicola Soranzo 90 | Peter Steinbach 91 | Sarah Stevens 92 | Oliver Stueker 93 | Benjamin Stuermer 94 | Tiffany Timbers 95 | Danielle Traphagen 96 | Tim Tröndle 97 | Anelda van der Walt 98 | Steve Vandervalk 99 | Greg Watson 100 | Belinda Weaver 101 | Mark Wheelhouse 102 | Ethan White 103 | Greg Wilson 104 | Steven Wu 105 | Qingpeng Zhang 106 | Andrew Lonsdale 107 | Arnstein Orten 108 | Ben Bolker 109 | Christoph Junghans 110 | David Jennings 111 | James Tocknell 112 | Jonathan Cooper 113 | Katrin Leinweber 114 | Leo Browning 115 | Mary C. Kinniburgh 116 | Matthew Bourque 117 | Matthew Hartley 118 | Raphaël Grolimund 119 | Scott Bailey 120 | Todd Gamblin 121 | Tommy Keswick 122 | Vijay P. Nagraj 123 | Will Usher 124 | -------------------------------------------------------------------------------- /CITATION: -------------------------------------------------------------------------------- 1 | Please cite as: 2 | 3 | Ivan Gonzalez; Daisie Huang; Nima Hejazi; Katherine Koziar; 4 | Madicken Munk (eds): "Software Carpentry: Version Control with Git." 5 | Version 2019.06.1, July 2019, 6 | https://github.com/swcarpentry/git-novice, 10.5281/zenodo.3264950 7 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Contributor Code of Conduct" 3 | --- 4 | 5 | As contributors and maintainers of this project, 6 | we pledge to follow the [The Carpentries Code of Conduct][coc]. 7 | 8 | Instances of abusive, harassing, or otherwise unacceptable behavior 9 | may be reported by following our [reporting guidelines][coc-reporting]. 10 | 11 | 12 | [coc-reporting]: https://docs.carpentries.org/policies/coc/incident-reporting.html 13 | [coc]: https://docs.carpentries.org/policies/coc/ 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | [The Carpentries][cp-site] ([Software Carpentry][swc-site], [Data 4 | Carpentry][dc-site], and [Library Carpentry][lc-site]) are open source 5 | projects, and we welcome contributions of all kinds: new lessons, fixes to 6 | existing material, bug reports, and reviews of proposed changes are all 7 | welcome. 8 | 9 | ### Contributor Agreement 10 | 11 | By contributing, you agree that we may redistribute your work under [our 12 | license](LICENSE.md). In exchange, we will address your issues and/or assess 13 | your change proposal as promptly as we can, and help you become a member of our 14 | community. Everyone involved in [The Carpentries][cp-site] agrees to abide by 15 | our [code of conduct](CODE_OF_CONDUCT.md). 16 | 17 | ### How to Contribute 18 | 19 | The easiest way to get started is to file an issue to tell us about a spelling 20 | mistake, some awkward wording, or a factual error. This is a good way to 21 | introduce yourself and to meet some of our community members. 22 | 23 | 1. If you do not have a [GitHub][github] account, you can [send us comments by 24 | email][contact]. However, we will be able to respond more quickly if you use 25 | one of the other methods described below. 26 | 27 | 2. If you have a [GitHub][github] account, or are willing to [create 28 | one][github-join], but do not know how to use Git, you can report problems 29 | or suggest improvements by [creating an issue][repo-issues]. This allows us 30 | to assign the item to someone and to respond to it in a threaded discussion. 31 | 32 | 3. If you are comfortable with Git, and would like to add or change material, 33 | you can submit a pull request (PR). Instructions for doing this are 34 | [included below](#using-github). For inspiration about changes that need to 35 | be made, check out the [list of open issues][issues] across the Carpentries. 36 | 37 | Note: if you want to build the website locally, please refer to [The Workbench 38 | documentation][template-doc]. 39 | 40 | ### Where to Contribute 41 | 42 | 1. If you wish to change this lesson, add issues and pull requests here. 43 | 2. If you wish to change the template used for workshop websites, please refer 44 | to [The Workbench documentation][template-doc]. 45 | 46 | 47 | ### What to Contribute 48 | 49 | There are many ways to contribute, from writing new exercises and improving 50 | existing ones to updating or filling in the documentation and submitting [bug 51 | reports][issues] about things that do not work, are not clear, or are missing. 52 | If you are looking for ideas, please see [the list of issues for this 53 | repository][repo-issues], or the issues for [Data Carpentry][dc-issues], 54 | [Library Carpentry][lc-issues], and [Software Carpentry][swc-issues] projects. 55 | 56 | Comments on issues and reviews of pull requests are just as welcome: we are 57 | smarter together than we are on our own. **Reviews from novices and newcomers 58 | are particularly valuable**: it's easy for people who have been using these 59 | lessons for a while to forget how impenetrable some of this material can be, so 60 | fresh eyes are always welcome. 61 | 62 | ### What *Not* to Contribute 63 | 64 | Our lessons already contain more material than we can cover in a typical 65 | workshop, so we are usually *not* looking for more concepts or tools to add to 66 | them. As a rule, if you want to introduce a new idea, you must (a) estimate how 67 | long it will take to teach and (b) explain what you would take out to make room 68 | for it. The first encourages contributors to be honest about requirements; the 69 | second, to think hard about priorities. 70 | 71 | We are also not looking for exercises or other material that only run on one 72 | platform. Our workshops typically contain a mixture of Windows, macOS, and 73 | Linux users; in order to be usable, our lessons must run equally well on all 74 | three. 75 | 76 | ### Using GitHub 77 | 78 | If you choose to contribute via GitHub, you may want to look at [How to 79 | Contribute to an Open Source Project on GitHub][how-contribute]. In brief, we 80 | use [GitHub flow][github-flow] to manage changes: 81 | 82 | 1. Create a new branch in your desktop copy of this repository for each 83 | significant change. 84 | 2. Commit the change in that branch. 85 | 3. Push that branch to your fork of this repository on GitHub. 86 | 4. Submit a pull request from that branch to the [upstream repository][repo]. 87 | 5. If you receive feedback, make changes on your desktop and push to your 88 | branch on GitHub: the pull request will update automatically. 89 | 90 | NB: The published copy of the lesson is usually in the `main` branch. 91 | 92 | Each lesson has a team of maintainers who review issues and pull requests or 93 | encourage others to do so. The maintainers are community volunteers, and have 94 | final say over what gets merged into the lesson. 95 | 96 | ### Other Resources 97 | 98 | The Carpentries is a global organisation with volunteers and learners all over 99 | the world. We share values of inclusivity and a passion for sharing knowledge, 100 | teaching and learning. There are several ways to connect with The Carpentries 101 | community listed at including via social 102 | media, slack, newsletters, and email lists. You can also [reach us by 103 | email][contact]. 104 | 105 | [repo]: https://github.com/swcarpentry/git-novice 106 | [repo-issues]: https://github.com/swcarpentry/git-novice/issues 107 | [contact]: mailto:team@carpentries.org 108 | [cp-site]: https://carpentries.org/ 109 | [dc-issues]: https://github.com/issues?q=user%3Adatacarpentry 110 | [dc-lessons]: https://datacarpentry.org/lessons/ 111 | [dc-site]: https://datacarpentry.org/ 112 | [discuss-list]: https://lists.software-carpentry.org/listinfo/discuss 113 | [github]: https://github.com 114 | [github-flow]: https://guides.github.com/introduction/flow/ 115 | [github-join]: https://github.com/join 116 | [how-contribute]: https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github 117 | [issues]: https://carpentries.org/help-wanted-issues/ 118 | [lc-issues]: https://github.com/issues?q=user%3ALibraryCarpentry 119 | [swc-issues]: https://github.com/issues?q=user%3Aswcarpentry 120 | [swc-lessons]: https://software-carpentry.org/lessons/ 121 | [swc-site]: https://software-carpentry.org/ 122 | [lc-site]: https://librarycarpentry.org/ 123 | [template-doc]: https://carpentries.github.io/workbench/ 124 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Licenses" 3 | --- 4 | 5 | ## Instructional Material 6 | 7 | All Carpentries (Software Carpentry, Data Carpentry, and Library Carpentry) 8 | instructional material is made available under the [Creative Commons 9 | Attribution license][cc-by-human]. The following is a human-readable summary of 10 | (and not a substitute for) the [full legal text of the CC BY 4.0 11 | license][cc-by-legal]. 12 | 13 | You are free: 14 | 15 | - to **Share**---copy and redistribute the material in any medium or format 16 | - to **Adapt**---remix, transform, and build upon the material 17 | 18 | for any purpose, even commercially. 19 | 20 | The licensor cannot revoke these freedoms as long as you follow the license 21 | terms. 22 | 23 | Under the following terms: 24 | 25 | - **Attribution**---You must give appropriate credit (mentioning that your work 26 | is derived from work that is Copyright (c) The Carpentries and, where 27 | practical, linking to ), provide a [link to the 28 | license][cc-by-human], and indicate if changes were made. You may do so in 29 | any reasonable manner, but not in any way that suggests the licensor endorses 30 | you or your use. 31 | 32 | - **No additional restrictions**---You may not apply legal terms or 33 | technological measures that legally restrict others from doing anything the 34 | license permits. With the understanding that: 35 | 36 | Notices: 37 | 38 | * You do not have to comply with the license for elements of the material in 39 | the public domain or where your use is permitted by an applicable exception 40 | or limitation. 41 | * No warranties are given. The license may not give you all of the permissions 42 | necessary for your intended use. For example, other rights such as publicity, 43 | privacy, or moral rights may limit how you use the material. 44 | 45 | ## Software 46 | 47 | Except where otherwise noted, the example programs and other software provided 48 | by The Carpentries are made available under the [OSI][osi]-approved [MIT 49 | license][mit-license]. 50 | 51 | Permission is hereby granted, free of charge, to any person obtaining a copy of 52 | this software and associated documentation files (the "Software"), to deal in 53 | the Software without restriction, including without limitation the rights to 54 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 55 | of the Software, and to permit persons to whom the Software is furnished to do 56 | so, subject to the following conditions: 57 | 58 | The above copyright notice and this permission notice shall be included in all 59 | copies or substantial portions of the Software. 60 | 61 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 62 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 63 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 64 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 65 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 66 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 67 | SOFTWARE. 68 | 69 | ## Trademark 70 | 71 | "The Carpentries", "Software Carpentry", "Data Carpentry", and "Library 72 | Carpentry" and their respective logos are registered trademarks of [The Carpentries, Inc.][carpentries]. 73 | 74 | [cc-by-human]: https://creativecommons.org/licenses/by/4.0/ 75 | [cc-by-legal]: https://creativecommons.org/licenses/by/4.0/legalcode 76 | [mit-license]: https://opensource.org/licenses/mit-license.html 77 | [carpentries]: https://carpentries.org 78 | [osi]: https://opensource.org 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Create a Slack Account with us](https://img.shields.io/badge/Create_Slack_Account-The_Carpentries-071159.svg)](https://slack-invite.carpentries.org/) 2 | [![Slack Status](https://img.shields.io/badge/Slack_Channel-swc--git-E01563.svg)](https://carpentries.slack.com/messages/C91JS49HD) 3 | 4 | # git-novice 5 | 6 | An introduction to version control for novices using Git. 7 | Please see [https://swcarpentry.github.io/git-novice/](https://swcarpentry.github.io/git-novice/) for a rendered version of this material, 8 | or [the lesson template documentation][lesson-example] for instructions on formatting, building, and submitting material. 9 | 10 | Maintainers: 11 | 12 | - [Kat Koziar][koziar_kat]: [@kekoziar](https://github.com/kekoziar) 13 | - [Martino Sorbaro][sorbaro_mart]: [@martinosorb](https://github.com/martinosorb) 14 | - Erin Graham: [@erinmgraham](https://github.com/erinmgraham) 15 | 16 | Alumni maintainers: 17 | 18 | - [Ivan Gonzalez][gonzalez_ivan]: [@iglpdc](https://github.com/iglpdc) 19 | - [Daisie Huang][huang_daisie]: [@daisieh](https://github.com/daisieh) 20 | - [Nima Hejazi][hejazi_nima]: [@nhejazi](https://github.com/nhejazi) 21 | - [Madicken Munk][munk_madicken]: [@munkm](https://github.com/munkm) 22 | 23 | 24 | [lesson-example]: https://carpentries.github.io/sandpaper-docs/ 25 | [hejazi_nima]: https://carpentries.org/instructors/#nhejazi 26 | [koziar_kat]: https://carpentries.org/instructors/#kekoziar 27 | [munk_madicken]: https://carpentries.org/instructors/#munkm 28 | [gonzalez_ivan]: https://carpentries.org/instructors/#iglpdc 29 | [huang_daisie]: https://software-carpentry.org/team/#huang_daisie 30 | [sorbaro_mart]: https://carpentries.org/instructors/#martinosorb 31 | -------------------------------------------------------------------------------- /config.yaml: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------ 2 | # Values for this lesson. 3 | #------------------------------------------------------------ 4 | 5 | # Which carpentry is this (swc, dc, lc, or cp)? 6 | # swc: Software Carpentry 7 | # dc: Data Carpentry 8 | # lc: Library Carpentry 9 | # cp: Carpentries (to use for instructor training for instance) 10 | # incubator: The Carpentries Incubator 11 | carpentry: 'swc' 12 | 13 | # Overall title for pages. 14 | title: 'Version Control with Git' 15 | 16 | # Date the lesson was created (YYYY-MM-DD, this is empty by default) 17 | created: '2014-12-04' 18 | 19 | # Comma-separated list of keywords for the lesson 20 | keywords: 'software, data, lesson, The Carpentries' 21 | 22 | # Life cycle stage of the lesson 23 | # possible values: pre-alpha, alpha, beta, stable 24 | life_cycle: 'stable' 25 | 26 | # License of the lesson materials (recommended CC-BY 4.0) 27 | license: 'CC-BY 4.0' 28 | 29 | # Link to the source repository for this lesson 30 | source: 'https://github.com/swcarpentry/git-novice' 31 | 32 | # Default branch of your lesson 33 | branch: 'main' 34 | 35 | # Who to contact if there are any issues 36 | contact: 'team@carpentries.org' 37 | 38 | # Navigation ------------------------------------------------ 39 | # 40 | # Use the following menu items to specify the order of 41 | # individual pages in each dropdown section. Leave blank to 42 | # include all pages in the folder. 43 | # 44 | # Example ------------- 45 | # 46 | # episodes: 47 | # - introduction.md 48 | # - first-steps.md 49 | # 50 | # learners: 51 | # - setup.md 52 | # 53 | # instructors: 54 | # - instructor-notes.md 55 | # 56 | # profiles: 57 | # - one-learner.md 58 | # - another-learner.md 59 | 60 | # Order of episodes in your lesson 61 | episodes: 62 | - 01-basics.md 63 | - 02-setup.md 64 | - 03-create.md 65 | - 04-changes.md 66 | - 05-history.md 67 | - 06-ignore.md 68 | - 07-github.md 69 | - 08-collab.md 70 | - 09-conflict.md 71 | - 10-open.md 72 | - 11-licensing.md 73 | - 12-citation.md 74 | - 13-hosting.md 75 | - 14-supplemental-rstudio.md 76 | 77 | # Information for Learners 78 | learners: 79 | 80 | # Information for Instructors 81 | instructors: 82 | 83 | # Learner Profiles 84 | profiles: 85 | 86 | # Customisation --------------------------------------------- 87 | # 88 | # This space below is where custom yaml items (e.g. pinning 89 | # sandpaper and varnish versions) should live 90 | 91 | 92 | url: 'https://swcarpentry.github.io/git-novice' 93 | analytics: carpentries 94 | lang: en 95 | -------------------------------------------------------------------------------- /episodes/01-basics.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Automated Version Control 3 | teaching: 5 4 | exercises: 0 5 | --- 6 | 7 | ::::::::::::::::::::::::::::::::::::::: objectives 8 | 9 | - Understand the benefits of an automated version control system. 10 | - Understand the basics of how automated version control systems work. 11 | 12 | :::::::::::::::::::::::::::::::::::::::::::::::::: 13 | 14 | :::::::::::::::::::::::::::::::::::::::: questions 15 | 16 | - What is version control and why should I use it? 17 | 18 | :::::::::::::::::::::::::::::::::::::::::::::::::: 19 | 20 | We'll start by exploring how version control can be used 21 | to keep track of what one person did and when. 22 | Even if you aren't collaborating with other people, 23 | automated version control is much better than this situation: 24 | 25 | !["notFinal.doc" by Jorge Cham, ](fig/phd101212s.png){alt='Comic: a PhD student sends "FINAL.doc" to their supervisor, but after several increasingly intense and frustrating rounds of comments and revisions they end up with a file named "FINAL_rev.22.comments49.corrections.10.#@$%WHYDIDCOMETOGRADSCHOOL????.doc"'} 26 | 27 | We've all been in this situation before: it seems unnecessary to have 28 | multiple nearly-identical versions of the same document. Some word 29 | processors let us deal with this a little better, such as Microsoft 30 | Word's 31 | [Track Changes](https://support.office.com/en-us/article/Track-changes-in-Word-197ba630-0f5f-4a8e-9a77-3712475e806a), 32 | Google Docs' [version history](https://support.google.com/docs/answer/190843?hl=en), or 33 | LibreOffice's [Recording and Displaying Changes](https://help.libreoffice.org/Common/Recording_and_Displaying_Changes). 34 | 35 | Version control systems start with a base version of the document and 36 | then record changes you make each step of the way. You can 37 | think of it as a recording of your progress: you can rewind to start at the base 38 | document and play back each change you made, eventually arriving at your 39 | more recent version. 40 | 41 | ![](fig/play-changes.svg){alt='A diagram demonstrating how a single document grows as the result of sequential changes'} 42 | 43 | Once you think of changes as separate from the document itself, you 44 | can then think about "playing back" different sets of changes on the base document, ultimately 45 | resulting in different versions of that document. For example, two users can make independent 46 | sets of changes on the same document. 47 | 48 | ![](fig/versions.svg){alt='A diagram with one source document that has been modified in two different ways to produce two different versions of the document'} 49 | 50 | Unless multiple users make changes to the same section of the document - a 51 | [conflict](../learners/reference.md#conflict) - you can 52 | incorporate two sets of changes into the same base document. 53 | 54 | ![](fig/merge.svg){alt='A diagram that shows the merging of two different document versions into one document that contains all of the changes from both versions'} 55 | 56 | A version control system is a tool that keeps track of these changes for us, 57 | effectively creating different versions of our files. It allows us to decide 58 | which changes will be made to the next version (each record of these changes is 59 | called a [commit](../learners/reference.md#commit)), and keeps useful metadata 60 | about them. The complete history of commits for a particular project and their 61 | metadata make up a [repository](../learners/reference.md#repository). 62 | Repositories can be kept in sync across different computers, facilitating 63 | collaboration among different people. 64 | 65 | ::::::::::::::::::::::::::::::::::::::::: callout 66 | 67 | ## The Long History of Version Control Systems 68 | 69 | Automated version control systems are nothing new. 70 | Tools like [RCS](https://en.wikipedia.org/wiki/Revision_Control_System), [CVS](https://en.wikipedia.org/wiki/Concurrent_Versions_System), or [Subversion](https://en.wikipedia.org/wiki/Apache_Subversion) have been around since the early 1980s and are used by 71 | many large companies. 72 | However, many of these are now considered legacy systems (i.e., outdated) due to various 73 | limitations in their capabilities. 74 | More modern systems, such as [Git](https://en.wikipedia.org/wiki/Git) and [Mercurial](https://en.wikipedia.org/wiki/Mercurial), 75 | are *distributed*, meaning that they do not need a centralized server to host the repository. 76 | These modern systems also include powerful merging tools that make it possible for multiple authors to work on 77 | the same files concurrently. 78 | 79 | For those interested, The Carpentries has a [Version Control with Mercurial](https://swcarpentry.github.io/hg-novice/) lesson (2013-2018), which provides additional context and historical perspective. 80 | :::::::::::::::::::::::::::::::::::::::::::::::::: 81 | 82 | ::::::::::::::::::::::::::::::::::::::: challenge 83 | 84 | ## Paper Writing 85 | 86 | - Imagine you drafted an excellent paragraph for a paper you are writing, but later ruin 87 | it. How would you retrieve the *excellent* version of your conclusion? Is it even possible? 88 | 89 | - Imagine you have 5 co-authors. How would you manage the changes and comments 90 | they make to your paper? If you use LibreOffice Writer or Microsoft Word, what happens if 91 | you accept changes made using the `Track Changes` option? Do you have a 92 | history of those changes? 93 | 94 | ::::::::::::::: solution 95 | 96 | ## Solution 97 | 98 | - Recovering the excellent version is only possible if you created a copy 99 | of the old version of the paper. The danger of losing good versions 100 | often leads to the problematic workflow illustrated in the PhD Comics 101 | cartoon at the top of this page. 102 | 103 | - Collaborative writing with traditional word processors is cumbersome. 104 | Either every collaborator has to work on a document sequentially 105 | (slowing down the process of writing), or you have to send out a 106 | version to all collaborators and manually merge their comments into 107 | your document. The 'track changes' or 'record changes' option can 108 | highlight changes for you and simplifies merging, but as soon as you 109 | accept changes you will lose their history. You will then no longer 110 | know who suggested that change, why it was suggested, or when it was 111 | merged into the rest of the document. Even online word processors like 112 | Google Docs or Microsoft Office Online do not fully resolve these 113 | problems. 114 | 115 | 116 | 117 | ::::::::::::::::::::::::: 118 | 119 | :::::::::::::::::::::::::::::::::::::::::::::::::: 120 | 121 | :::::::::::::::::::::::::::::::::::::::: keypoints 122 | 123 | - Version control is like an unlimited 'undo'. 124 | - Version control also allows many people to work in parallel. 125 | 126 | :::::::::::::::::::::::::::::::::::::::::::::::::: 127 | -------------------------------------------------------------------------------- /episodes/02-setup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Setting Up Git 3 | teaching: 5 4 | exercises: 0 5 | --- 6 | 7 | ::::::::::::::::::::::::::::::::::::::: objectives 8 | 9 | - Configure `git` the first time it is used on a computer. 10 | - Understand the meaning of the `--global` configuration flag. 11 | 12 | :::::::::::::::::::::::::::::::::::::::::::::::::: 13 | 14 | :::::::::::::::::::::::::::::::::::::::: questions 15 | 16 | - How do I get set up to use Git? 17 | 18 | :::::::::::::::::::::::::::::::::::::::::::::::::: 19 | 20 | When we use Git on a new computer for the first time, 21 | we need to configure a few things. Below are a few examples 22 | of configurations we will set as we get started with Git: 23 | 24 | - our name and email address, 25 | - what our preferred text editor is, 26 | - and that we want to use these settings globally (i.e. for every project). 27 | 28 | On a command line, Git commands are written as `git verb options`, 29 | where `verb` is what we actually want to do and `options` is additional optional information which may be needed for the `verb`. So here is how 30 | Alfredo sets up his new laptop: 31 | 32 | ```bash 33 | $ git config --global user.name "Alfredo Linguini" 34 | $ git config --global user.email "a.linguini@ratatouille.fr" 35 | ``` 36 | 37 | Please use your own name and email address instead of Alfredo's. This user name and email will be associated with your subsequent Git activity, 38 | which means that any changes pushed to 39 | [GitHub](https://github.com/), 40 | [BitBucket](https://bitbucket.org/), 41 | [GitLab](https://gitlab.com/) or 42 | another Git host server 43 | after this lesson will include this information. 44 | 45 | For this lesson, we will be interacting with [GitHub](https://github.com/) and so the email address used should be the same as the one used when setting up your GitHub account. If you are concerned about privacy, please review [GitHub's instructions for keeping your email address private][git-privacy]. 46 | 47 | ::::::::::::::::::::::::::::::::::::::::: callout 48 | 49 | ## Keeping your email private 50 | 51 | If you elect to use a private email address with GitHub, then use GitHub's no-reply email address for the `user.email` value. It looks like `ID+username@users.noreply.github.com`. You can look up your own address in your GitHub [email settings](https://github.com/settings/emails). 52 | 53 | 54 | :::::::::::::::::::::::::::::::::::::::::::::::::: 55 | 56 | ::::::::::::::::::::::::::::::::::::::::: callout 57 | 58 | ## Line Endings 59 | 60 | As with other keys, when you press Enter or or on Macs, Return on your keyboard, 61 | your computer encodes this input as a character. 62 | Different operating systems use different character(s) to represent the end of a line. 63 | (You may also hear these referred to as newlines or line breaks.) 64 | Because Git uses these characters to compare files, 65 | it may cause unexpected issues when editing a file on different machines. 66 | Though it is beyond the scope of this lesson, you can read more about this issue 67 | [in the Pro Git book](https://www.git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#_core_autocrlf). 68 | 69 | You can change the way Git recognizes and encodes line endings 70 | using the `core.autocrlf` command to `git config`. 71 | The following settings are recommended: 72 | 73 | On macOS and Linux: 74 | 75 | ```bash 76 | $ git config --global core.autocrlf input 77 | ``` 78 | 79 | And on Windows: 80 | 81 | ```bash 82 | $ git config --global core.autocrlf true 83 | ``` 84 | 85 | :::::::::::::::::::::::::::::::::::::::::::::::::: 86 | 87 | Alfredo also has to set his favorite text editor, following this table: 88 | 89 | | Editor | Configuration command | 90 | | :----------- | :------------------------------ | 91 | | Atom | `$ git config --global core.editor "atom --wait"` | 92 | | nano | `$ git config --global core.editor "nano -w"` | 93 | | BBEdit (Mac, with command line tools) | `$ git config --global core.editor "bbedit -w"` | 94 | | Sublime Text (Mac) | `$ git config --global core.editor "/Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl -n -w"` | 95 | | Sublime Text (Win, 32-bit install) | `$ git config --global core.editor "'c:/program files (x86)/sublime text 3/sublime_text.exe' -w"` | 96 | | Sublime Text (Win, 64-bit install) | `$ git config --global core.editor "'c:/program files/sublime text 3/sublime_text.exe' -w"` | 97 | | Notepad (Win) | `$ git config --global core.editor "c:/Windows/System32/notepad.exe"` | 98 | | Notepad++ (Win, 32-bit install) | `$ git config --global core.editor "'c:/program files (x86)/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"` | 99 | | Notepad++ (Win, 64-bit install) | `$ git config --global core.editor "'c:/program files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"` | 100 | | Kate (Linux) | `$ git config --global core.editor "kate"` | 101 | | Gedit (Linux) | `$ git config --global core.editor "gedit --wait --new-window"` | 102 | | Scratch (Linux) | `$ git config --global core.editor "scratch-text-editor"` | 103 | | Emacs | `$ git config --global core.editor "emacs"` | 104 | | Vim | `$ git config --global core.editor "vim"` | 105 | | VS Code | `$ git config --global core.editor "code --wait"` | 106 | 107 | It is possible to reconfigure the text editor for Git whenever you want to change it. 108 | 109 | ::::::::::::::::::::::::::::::::::::::::: callout 110 | 111 | ## Exiting Vim 112 | 113 | Note that Vim is the default editor for many programs. If you haven't used Vim before and wish to exit a session without saving 114 | your changes, press Esc then type `:q!` and press Enter or or on Macs, Return. 115 | If you want to save your changes and quit, press Esc then type `:wq` and press Enter or or on Macs, Return. 116 | 117 | 118 | :::::::::::::::::::::::::::::::::::::::::::::::::: 119 | 120 | Git (2.28+) allows configuration of the name of the branch created when you 121 | initialize any new repository. Alfredo decides to use that feature to set it to `main` so 122 | it matches the cloud service he will eventually use. 123 | 124 | ```bash 125 | $ git config --global init.defaultBranch main 126 | ``` 127 | 128 | ::::::::::::::::::::::::::::::::::::::::: callout 129 | 130 | ## Default Git branch naming 131 | 132 | Source file changes are associated with a "branch." 133 | For new learners in this lesson, it's enough to know that branches exist, and this lesson uses one branch. 134 | By default, Git will create a branch called `master` 135 | when you create a new repository with `git init` (as explained in the next Episode). This term evokes 136 | the racist practice of human slavery and the 137 | [software development community](https://github.com/github/renaming) has moved to adopt 138 | more inclusive language. 139 | 140 | In 2020, most Git code hosting services transitioned to using `main` as the default 141 | branch. As an example, any new repository that is opened in GitHub and GitLab default 142 | to `main`. However, Git has not yet made the same change. As a result, local repositories 143 | must be manually configured have the same main branch name as most cloud services. 144 | 145 | For versions of Git prior to 2.28, the change can be made on an individual repository level. The 146 | command for this is in the next episode. Note that if this value is unset in your local Git 147 | configuration, the `init.defaultBranch` value defaults to `master`. 148 | 149 | :::::::::::::::::::::::::::::::::::::::::::::::::: 150 | 151 | The five commands we just ran above only need to be run once: the flag `--global` tells Git 152 | to use the settings for every project, in your user account, on this computer. 153 | 154 | Let's review those settings and test our `core.editor` right away: 155 | 156 | ```bash 157 | $ git config --global --edit 158 | ``` 159 | 160 | Let's close the file without making any additional changes. Remember, since typos in the config file will cause 161 | issues, it's safer to view the configuration with: 162 | 163 | ```bash 164 | $ git config --list --global 165 | ``` 166 | 167 | And if necessary, change your configuration using the 168 | same commands to choose another editor or update your email address. 169 | This can be done as many times as you want. 170 | 171 | ::::::::::::::::::::::::::::::::::::::::: callout 172 | 173 | ## Proxy 174 | 175 | In some networks you need to use a 176 | [proxy](https://en.wikipedia.org/wiki/Proxy_server). If this is the case, you 177 | may also need to tell Git about the proxy: 178 | 179 | ```bash 180 | $ git config --global http.proxy proxy-url 181 | $ git config --global https.proxy proxy-url 182 | ``` 183 | 184 | To disable the proxy, use 185 | 186 | ```bash 187 | $ git config --global --unset http.proxy 188 | $ git config --global --unset https.proxy 189 | ``` 190 | 191 | :::::::::::::::::::::::::::::::::::::::::::::::::: 192 | 193 | ::::::::::::::::::::::::::::::::::::::::: callout 194 | 195 | ## Git Help and Manual 196 | 197 | Always remember that if you forget the subcommands or options of a `git` command, you can access the 198 | relevant list of options typing `git -h` or access the corresponding Git manual by typing 199 | `git --help`, e.g.: 200 | 201 | ```bash 202 | $ git config -h 203 | $ git config --help 204 | ``` 205 | 206 | While viewing the manual, remember the `:` is a prompt waiting for commands and you can press Q to exit the manual. 207 | 208 | More generally, you can get the list of available `git` commands and further resources of the Git manual typing: 209 | 210 | ```bash 211 | $ git help 212 | ``` 213 | 214 | :::::::::::::::::::::::::::::::::::::::::::::::::: 215 | 216 | [git-privacy]: https://help.github.com/articles/keeping-your-email-address-private/ 217 | 218 | 219 | :::::::::::::::::::::::::::::::::::::::: keypoints 220 | 221 | - Use `git config` with the `--global` option to configure a user name, email address, editor, and other preferences once per machine. 222 | 223 | :::::::::::::::::::::::::::::::::::::::::::::::::: 224 | 225 | 226 | -------------------------------------------------------------------------------- /episodes/03-create.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Creating a Repository 3 | teaching: 10 4 | exercises: 0 5 | --- 6 | 7 | ::::::::::::::::::::::::::::::::::::::: objectives 8 | 9 | - Create a local Git repository. 10 | - Describe the purpose of the `.git` directory. 11 | 12 | :::::::::::::::::::::::::::::::::::::::::::::::::: 13 | 14 | :::::::::::::::::::::::::::::::::::::::: questions 15 | 16 | - Where does Git store information? 17 | 18 | :::::::::::::::::::::::::::::::::::::::::::::::::: 19 | 20 | Once Git is configured, 21 | we can start using it. 22 | 23 | We will help Alfredo with his new project, create a repository with all his recipes. 24 | 25 | First, let's create a new directory in the `Desktop` folder for our work and then change the current working directory to the newly created one: 26 | 27 | ```bash 28 | $ cd ~/Desktop 29 | $ mkdir recipes 30 | $ cd recipes 31 | ``` 32 | 33 | Then we tell Git to make `recipes` a [repository](../learners/reference.md#repository) 34 | \-- a place where Git can store versions of our files: 35 | 36 | ```bash 37 | $ git init 38 | ``` 39 | 40 | It is important to note that `git init` will create a repository that 41 | can include subdirectories and their files---there is no need to create 42 | separate repositories nested within the `recipes` repository, whether 43 | subdirectories are present from the beginning or added later. Also, note 44 | that the creation of the `recipes` directory and its initialization as a 45 | repository are completely separate processes. 46 | 47 | If we use `ls` to show the directory's contents, 48 | it appears that nothing has changed: 49 | 50 | ```bash 51 | $ ls 52 | ``` 53 | 54 | But if we add the `-a` flag to show everything, 55 | we can see that Git has created a hidden directory within `recipes` called `.git`: 56 | 57 | ```bash 58 | $ ls -a 59 | ``` 60 | 61 | ```output 62 | . .. .git 63 | ``` 64 | 65 | Git uses this special subdirectory to store all the information about the project, 66 | including the tracked files and sub-directories located within the project's directory. 67 | If we ever delete the `.git` subdirectory, 68 | we will lose the project's history. 69 | 70 | We can now start using one of the most important git commands, which is particularly helpful to beginners. `git status` tells us the status of our project, and better, a list of changes in the project and options on what to do with those changes. We can use it as often as we want, whenever we want to understand what is going on. 71 | 72 | ```bash 73 | $ git status 74 | ``` 75 | 76 | ```output 77 | On branch main 78 | 79 | No commits yet 80 | 81 | nothing to commit (create/copy files and use "git add" to track) 82 | ``` 83 | 84 | If you are using a different version of `git`, the exact 85 | wording of the output might be slightly different. 86 | 87 | ::::::::::::::::::::::::::::::::::::::: challenge 88 | 89 | ## Places to Create Git Repositories 90 | 91 | Along with tracking information about recipes (the project we have already created), 92 | Alfredo would also like to track information about desserts specifically. 93 | Alfredo creates a `desserts` project inside his `recipes` 94 | project with the following sequence of commands: 95 | 96 | ```bash 97 | $ cd ~/Desktop # return to Desktop directory 98 | $ cd recipes # go into recipes directory, which is already a Git repository 99 | $ ls -a # ensure the .git subdirectory is still present in the recipes directory 100 | $ mkdir desserts # make a sub-directory recipes/desserts 101 | $ cd desserts # go into desserts subdirectory 102 | $ git init # make the desserts subdirectory a Git repository 103 | $ ls -a # ensure the .git subdirectory is present indicating we have created a new Git repository 104 | ``` 105 | 106 | Is the `git init` command, run inside the `desserts` subdirectory, required for 107 | tracking files stored in the `desserts` subdirectory? 108 | 109 | ::::::::::::::: solution 110 | 111 | ## Solution 112 | 113 | No. Alfredo does not need to make the `desserts` subdirectory a Git repository 114 | because the `recipes` repository will track all files, sub-directories, and 115 | subdirectory files under the `recipes` directory. Thus, in order to track 116 | all information about desserts, Alfredo only needed to add the `desserts` subdirectory 117 | to the `recipes` directory. 118 | 119 | Additionally, Git repositories can interfere with each other if they are "nested": 120 | the outer repository will try to version-control 121 | the inner repository. Therefore, it's best to create each new Git 122 | repository in a separate directory. To be sure that there is no conflicting 123 | repository in the directory, check the output of `git status`. If it looks 124 | like the following, you are good to go to create a new repository as shown 125 | above: 126 | 127 | ```bash 128 | $ git status 129 | ``` 130 | 131 | ```output 132 | fatal: Not a git repository (or any of the parent directories): .git 133 | ``` 134 | 135 | ::::::::::::::::::::::::: 136 | 137 | ## Correcting `git init` Mistakes 138 | 139 | Jimmy explains to Alfredo how a nested repository is redundant and may cause confusion 140 | down the road. Alfredo would like to go back to a single git repository. How can Alfredo undo 141 | his last `git init` in the `desserts` subdirectory? 142 | 143 | ::::::::::::::: solution 144 | 145 | ## Solution -- USE WITH CAUTION! 146 | 147 | ### Background 148 | 149 | Removing files from a Git repository needs to be done with caution. But we have not learned 150 | yet how to tell Git to track a particular file; we will learn this in the next episode. Files 151 | that are not tracked by Git can easily be removed like any other "ordinary" files with 152 | 153 | ```bash 154 | $ rm filename 155 | ``` 156 | 157 | Similarly a directory can be removed using `rm -r dirname`. 158 | If the files or folder being removed in this fashion are tracked by Git, then their removal 159 | becomes another change that we will need to track, as we will see in the next episode. 160 | 161 | ### Solution 162 | 163 | Git keeps all of its files in the `.git` directory. 164 | To recover from this little mistake, Alfredo can remove the `.git` 165 | folder in the desserts subdirectory by running the following command from inside the `recipes` directory: 166 | 167 | ```bash 168 | $ rm -rf desserts/.git 169 | ``` 170 | 171 | But be careful! Running this command in the wrong directory will remove 172 | the entire Git history of a project you might want to keep. 173 | In general, deleting files and directories using `rm` from the command line cannot be reversed. 174 | Therefore, always check your current directory using the command `pwd`. 175 | 176 | 177 | 178 | ::::::::::::::::::::::::: 179 | 180 | :::::::::::::::::::::::::::::::::::::::::::::::::: 181 | 182 | :::::::::::::::::::::::::::::::::::::::: keypoints 183 | 184 | - `git init` initializes a repository. 185 | - Git stores all of its repository data in the `.git` directory. 186 | 187 | :::::::::::::::::::::::::::::::::::::::::::::::::: 188 | -------------------------------------------------------------------------------- /episodes/06-ignore.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Ignoring Things 3 | teaching: 5 4 | exercises: 0 5 | --- 6 | 7 | ::::::::::::::::::::::::::::::::::::::: objectives 8 | 9 | - Configure Git to ignore specific files. 10 | - Explain why ignoring files can be useful. 11 | 12 | :::::::::::::::::::::::::::::::::::::::::::::::::: 13 | 14 | :::::::::::::::::::::::::::::::::::::::: questions 15 | 16 | - How can I tell Git to ignore files I don't want to track? 17 | 18 | :::::::::::::::::::::::::::::::::::::::::::::::::: 19 | 20 | What if we have files that we do not want Git to track for us, 21 | like backup files created by our editor 22 | or intermediate files created during data analysis? 23 | Let's create a few dummy files: 24 | 25 | ```bash 26 | $ mkdir pictures 27 | $ touch a.png b.png c.png pictures/cake1.jpg pictures/cake2.jpg 28 | ``` 29 | 30 | and see what Git says: 31 | 32 | ```bash 33 | $ git status 34 | ``` 35 | 36 | ```output 37 | On branch main 38 | Untracked files: 39 | (use "git add ..." to include in what will be committed) 40 | 41 | a.png 42 | b.png 43 | c.png 44 | pictures/ 45 | 46 | nothing added to commit but untracked files present (use "git add" to track) 47 | ``` 48 | 49 | Putting these files under version control would be a waste of disk space. 50 | What's worse, 51 | having them all listed could distract us from changes that actually matter, 52 | so let's tell Git to ignore them. 53 | 54 | We do this by creating a file in the root directory of our project called `.gitignore`: 55 | 56 | ```bash 57 | $ nano .gitignore 58 | ``` 59 | 60 | Type the text below into the `.gitignore` file: 61 | 62 | ``` 63 | *.png 64 | pictures/ 65 | ``` 66 | 67 | Save the file and exit your editor. 68 | 69 | Verify that the file contains the files to ignore. 70 | 71 | ```bash 72 | $ cat .gitignore 73 | ``` 74 | 75 | ```output 76 | *.png 77 | pictures/ 78 | ``` 79 | 80 | These patterns tell Git to ignore any file whose name ends in `.png` 81 | and everything in the `pictures` directory. 82 | (If any of these files were already being tracked, 83 | Git would continue to track them.) 84 | 85 | Once we have created this file, 86 | the output of `git status` is much cleaner: 87 | 88 | ```bash 89 | $ git status 90 | ``` 91 | 92 | ```output 93 | On branch main 94 | Untracked files: 95 | (use "git add ..." to include in what will be committed) 96 | 97 | .gitignore 98 | 99 | nothing added to commit but untracked files present (use "git add" to track) 100 | ``` 101 | 102 | The only thing Git notices now is the newly-created `.gitignore` file. 103 | You might think we wouldn't want to track it, 104 | but everyone we're sharing our repository with will probably want to ignore 105 | the same things that we're ignoring. 106 | Let's add and commit `.gitignore`: 107 | 108 | ```bash 109 | $ git add .gitignore 110 | $ git commit -m "Ignore png files and the pictures folder." 111 | $ git status 112 | ``` 113 | 114 | ```output 115 | On branch main 116 | nothing to commit, working tree clean 117 | ``` 118 | 119 | As a bonus, using `.gitignore` helps us avoid accidentally adding files to the repository that we don't want to track: 120 | 121 | ```bash 122 | $ git add a.png 123 | ``` 124 | 125 | ```output 126 | The following paths are ignored by one of your .gitignore files: 127 | a.png 128 | Use -f if you really want to add them. 129 | ``` 130 | 131 | If we really want to override our ignore settings, 132 | we can use `git add -f` to force Git to add something. For example, 133 | `git add -f a.csv`. 134 | We can also always see the status of ignored files if we want: 135 | 136 | ```bash 137 | $ git status --ignored 138 | ``` 139 | 140 | ```output 141 | On branch main 142 | Ignored files: 143 | (use "git add -f ..." to include in what will be committed) 144 | 145 | a.png 146 | b.png 147 | c.png 148 | pictures/ 149 | 150 | nothing to commit, working tree clean 151 | ``` 152 | 153 | ::::::::::::::::::::::::::::::::::::::: challenge 154 | 155 | ## Ignoring Nested Files 156 | 157 | Given a directory structure that looks like: 158 | 159 | ```bash 160 | pictures/cake 161 | pictures/pizza 162 | ``` 163 | 164 | How would you ignore only `pictures/cake` and not `pictures/pizza`? 165 | 166 | ::::::::::::::: solution 167 | 168 | ## Solution 169 | 170 | If you only want to ignore the contents of 171 | `pictures/cake`, you can change your `.gitignore` to ignore 172 | only the `/cake/` subfolder by adding the following line to 173 | your .gitignore: 174 | 175 | ```output 176 | pictures/cake/ 177 | ``` 178 | 179 | This line will ensure only the contents of `pictures/cake` is ignored, and 180 | not the contents of `pictures/pizza`. 181 | 182 | As with most programming issues, there 183 | are a few alternative ways that one may ensure this ignore rule is followed. 184 | The "Ignoring Nested Files: Variation" exercise has a slightly 185 | different directory structure 186 | that presents an alternative solution. 187 | Further, the discussion page has more detail on ignore rules. 188 | 189 | 190 | 191 | ::::::::::::::::::::::::: 192 | 193 | :::::::::::::::::::::::::::::::::::::::::::::::::: 194 | 195 | ::::::::::::::::::::::::::::::::::::::: challenge 196 | 197 | ## Including Specific Files 198 | 199 | How would you ignore all `.png` files in your root directory except for 200 | `final.png`? 201 | Hint: Find out what `!` (the exclamation point operator) does 202 | 203 | ::::::::::::::: solution 204 | 205 | ## Solution 206 | 207 | You would add the following two lines to your .gitignore: 208 | 209 | ```output 210 | *.png # ignore all png files 211 | !final.png # except final.png 212 | ``` 213 | 214 | The exclamation point operator will include a previously excluded entry. 215 | 216 | Note also that, if you've previously committed `.png` files in this 217 | lesson, they will not be ignored with this new rule. Only future additions 218 | of `.png` files to the root directory will be ignored. 219 | 220 | 221 | 222 | ::::::::::::::::::::::::: 223 | 224 | :::::::::::::::::::::::::::::::::::::::::::::::::: 225 | 226 | ::::::::::::::::::::::::::::::::::::::: challenge 227 | 228 | ## Ignoring Nested Files: Variation 229 | 230 | Given a directory structure that looks similar to the earlier Nested Files 231 | exercise, but with a slightly different directory structure: 232 | 233 | ```bash 234 | pictures/cake 235 | pictures/pizza 236 | pictures/pie 237 | pictures/brownie 238 | ``` 239 | 240 | How would you ignore all of the contents in the pictures folder, but not `pictures/pie`? 241 | 242 | Hint: think a bit about how you created an exception with the `!` operator 243 | before. 244 | 245 | ::::::::::::::: solution 246 | 247 | ## Solution 248 | 249 | If you want to ignore the contents of 250 | `pictures/` but not those of `pictures/pie/`, you can change your `.gitignore` to ignore 251 | the contents of pictures folder, but create an exception for the contents of the 252 | `pictures/pie` subfolder. Your .gitignore would look like this: 253 | 254 | ```output 255 | pictures/* # ignore everything in pictures folder 256 | !pictures/pie/ # do not ignore pictures/data/ contents 257 | ``` 258 | 259 | ::::::::::::::::::::::::: 260 | 261 | :::::::::::::::::::::::::::::::::::::::::::::::::: 262 | 263 | ::::::::::::::::::::::::::::::::::::::: challenge 264 | 265 | ## Ignoring all data Files in a Directory 266 | 267 | Assuming you have an empty .gitignore file, and given a directory structure that looks like: 268 | 269 | ```bash 270 | pictures/data/location/gps/a.dat 271 | pictures/data/location/gps/b.dat 272 | pictures/data/location/gps/c.dat 273 | pictures/data/location/gps/info.txt 274 | pictures/plots 275 | ``` 276 | 277 | What's the shortest `.gitignore` rule you could write to ignore all `.dat` 278 | files in `pictures/data/location/gps`? Do not ignore the `info.txt`. 279 | 280 | ::::::::::::::: solution 281 | 282 | ## Solution 283 | 284 | Appending `pictures/data/location/gps/*.dat` will match every file in `pictures/data/location/gps` 285 | that ends with `.dat`. 286 | The file `pictures/data/location/gps/info.txt` will not be ignored. 287 | 288 | 289 | 290 | ::::::::::::::::::::::::: 291 | 292 | :::::::::::::::::::::::::::::::::::::::::::::::::: 293 | 294 | ::::::::::::::::::::::::::::::::::::::: challenge 295 | 296 | ## Ignoring all data Files in the repository 297 | 298 | Let us assume you have many `.csv` files in different subdirectories of your repository. 299 | For example, you might have: 300 | 301 | ```bash 302 | results/a.csv 303 | data/experiment_1/b.csv 304 | data/experiment_2/c.csv 305 | data/experiment_2/variation_1/d.csv 306 | ``` 307 | 308 | How do you ignore all the `.csv` files, without explicitly listing the names of the corresponding folders? 309 | 310 | ::::::::::::::: solution 311 | 312 | ## Solution 313 | 314 | In the `.gitignore` file, write: 315 | 316 | ```output 317 | **/*.csv 318 | ``` 319 | 320 | This will ignore all the `.csv` files, regardless of their position in the directory tree. 321 | You can still include some specific exception with the exclamation point operator. 322 | 323 | 324 | 325 | ::::::::::::::::::::::::: 326 | 327 | :::::::::::::::::::::::::::::::::::::::::::::::::: 328 | 329 | ::::::::::::::::::::::::::::::::::::::: challenge 330 | 331 | ## The Order of Rules 332 | 333 | Given a `.gitignore` file with the following contents: 334 | 335 | ```bash 336 | *.csv 337 | !*.csv 338 | ``` 339 | 340 | What will be the result? 341 | 342 | ::::::::::::::: solution 343 | 344 | ## Solution 345 | 346 | The `!` modifier will negate an entry from a previously defined ignore pattern. 347 | Because the `!*.csv` entry negates all of the previous `.csv` files in the `.gitignore`, 348 | none of them will be ignored, and all `.csv` files will be tracked. 349 | 350 | ::::::::::::::::::::::::: 351 | 352 | :::::::::::::::::::::::::::::::::::::::::::::::::: 353 | 354 | ::::::::::::::::::::::::::::::::::::::: challenge 355 | 356 | ## Log Files 357 | 358 | You wrote a script that creates many intermediate log-files of the form `log_01`, `log_02`, `log_03`, etc. 359 | You want to keep them but you do not want to track them through `git`. 360 | 361 | 1. Write **one** `.gitignore` entry that excludes files of the form `log_01`, `log_02`, etc. 362 | 363 | 2. Test your "ignore pattern" by creating some dummy files of the form `log_01`, etc. 364 | 365 | 3. You find that the file `log_01` is very important after all, add it to the tracked files without changing the `.gitignore` again. 366 | 367 | 4. Discuss with your neighbor what other types of files could reside in your directory that you do not want to track and thus would exclude via `.gitignore`. 368 | 369 | ::::::::::::::: solution 370 | 371 | ## Solution 372 | 373 | 1. append either `log_*` or `log*` as a new entry in your .gitignore 374 | 2. track `log_01` using `git add -f log_01` 375 | 376 | 377 | 378 | ::::::::::::::::::::::::: 379 | 380 | :::::::::::::::::::::::::::::::::::::::::::::::::: 381 | 382 | :::::::::::::::::::::::::::::::::::::::: keypoints 383 | 384 | - The .gitignore file is a text file that tells Git which files to track and which to ignore in the repository. 385 | - You can list specific files or folders to be ignored by Git, or you can include files that would normally be ignored. 386 | 387 | :::::::::::::::::::::::::::::::::::::::::::::::::: 388 | 389 | 390 | -------------------------------------------------------------------------------- /episodes/08-collab.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Collaborating 3 | teaching: 25 4 | exercises: 0 5 | --- 6 | 7 | ::::::::::::::::::::::::::::::::::::::: objectives 8 | 9 | - Clone a remote repository. 10 | - Collaborate by pushing to a common repository. 11 | - Describe the basic collaborative workflow. 12 | 13 | :::::::::::::::::::::::::::::::::::::::::::::::::: 14 | 15 | :::::::::::::::::::::::::::::::::::::::: questions 16 | 17 | - How can I use version control to collaborate with other people? 18 | 19 | :::::::::::::::::::::::::::::::::::::::::::::::::: 20 | 21 | For the next step, get into pairs. One person will be the "Owner" and the other 22 | will be the "Collaborator". The goal is that the Collaborator add changes into 23 | the Owner's repository. We will switch roles at the end, so both persons will 24 | play Owner and Collaborator. 25 | 26 | ::::::::::::::::::::::::::::::::::::::::: callout 27 | 28 | ## Practicing By Yourself 29 | 30 | If you're working through this lesson on your own, you can carry on by opening 31 | a second terminal window. 32 | This window will represent your partner, working on another computer. You 33 | won't need to give anyone access on GitHub, because both 'partners' are you. 34 | 35 | 36 | :::::::::::::::::::::::::::::::::::::::::::::::::: 37 | 38 | The Owner needs to give the Collaborator access. In your repository page on GitHub, click the "Settings" 39 | button on the right, select "Collaborators", click "Add people", and 40 | then enter your partner's username. 41 | 42 | ![](fig/github-add-collaborators.png){alt='A screenshot of the GitHub Collaborators settings page, which is accessed by clicking "Settings" then "Collaborators"'} 43 | 44 | To accept access to the Owner's repo, the Collaborator 45 | needs to go to [https://github.com/notifications](https://github.com/notifications) 46 | or check for email notification. Once there she can accept access to the Owner's repo. 47 | 48 | Next, the Collaborator needs to download a copy of the Owner's repository to her 49 | machine. This is called "cloning a repo". 50 | 51 | The Collaborator doesn't want to overwrite her own version of `recipes.git`, so 52 | needs to clone the Owner's repository to a different location than her own 53 | repository with the same name. 54 | 55 | To clone the Owner's repo into her `Desktop` folder, the Collaborator enters: 56 | 57 | ```bash 58 | $ git clone git@github.com:alflin/recipes.git ~/Desktop/alflin-recipes 59 | ``` 60 | 61 | Replace 'alflin' with the Owner's username. 62 | 63 | If you choose to clone without the clone path 64 | (`~/Desktop/alflin-recipes`) specified at the end, 65 | you will clone inside your own recipes folder! 66 | Make sure to navigate to the `Desktop` folder first. 67 | 68 | ![](fig/github-collaboration.svg){alt='A diagram showing that "git clone" can create a copy of a remote GitHub repository, allowing a second person to create their own local repository that they can make changes to.'} 69 | 70 | The Collaborator can now make a change in her clone of the Owner's repository, 71 | exactly the same way as we've been doing before: 72 | 73 | ```bash 74 | $ cd ~/Desktop/alflin-recipes 75 | $ nano hummus.md 76 | $ cat hummus.md 77 | ``` 78 | 79 | ```output 80 | # Hummus 81 | ## Ingredients 82 | * chickpeas 83 | * lemon 84 | * olive oil 85 | * salt 86 | ``` 87 | 88 | ```bash 89 | $ git add hummus.md 90 | $ git commit -m "Add ingredients for hummus" 91 | ``` 92 | 93 | ```output 94 | 1 file changed, 6 insertion(+) 95 | create mode 100644 hummus.md 96 | ``` 97 | 98 | Then push the change to the *Owner's repository* on GitHub: 99 | 100 | ```bash 101 | $ git push origin main 102 | ``` 103 | 104 | ```output 105 | Enumerating objects: 4, done. 106 | Counting objects: 4, done. 107 | Delta compression using up to 4 threads. 108 | Compressing objects: 100% (2/2), done. 109 | Writing objects: 100% (3/3), 306 bytes, done. 110 | Total 3 (delta 0), reused 0 (delta 0) 111 | To https://github.com/alflin/recipes.git 112 | 9272da5..29aba7c main -> main 113 | ``` 114 | 115 | Note that we didn't have to create a remote called `origin`: Git uses this 116 | name by default when we clone a repository. (This is why `origin` was a 117 | sensible choice earlier when we were setting up remotes by hand.) 118 | 119 | Take a look at the Owner's repository on GitHub again, and you should be 120 | able to see the new commit made by the Collaborator. You may need to refresh 121 | your browser to see the new commit. 122 | 123 | ::::::::::::::::::::::::::::::::::::::::: callout 124 | 125 | ## Some more about remotes 126 | 127 | In this episode and the previous one, our local repository has had 128 | a single "remote", called `origin`. A remote is a copy of the repository 129 | that is hosted somewhere else, that we can push to and pull from, and 130 | there's no reason that you have to work with only one. For example, 131 | on some large projects you might have your own copy in your own GitHub 132 | account (you'd probably call this `origin`) and also the main "upstream" 133 | project repository (let's call this `upstream` for the sake of examples). 134 | You would pull from `upstream` from time to 135 | time to get the latest updates that other people have committed. 136 | 137 | Remember that the name you give to a remote only exists locally. It's 138 | an alias that you choose - whether `origin`, or `upstream`, or `alfred` - 139 | and not something intrinstic to the remote repository. 140 | 141 | The `git remote` family of commands is used to set up and alter the remotes 142 | associated with a repository. Here are some of the most useful ones: 143 | 144 | - `git remote -v` lists all the remotes that are configured (we already used 145 | this in the last episode) 146 | - `git remote add [name] [url]` is used to add a new remote 147 | - `git remote remove [name]` removes a remote. Note that it doesn't affect the 148 | remote repository at all - it just removes the link to it from the local repo. 149 | - `git remote set-url [name] [newurl]` changes the URL that is associated 150 | with the remote. This is useful if it has moved, e.g. to a different GitHub 151 | account, or from GitHub to a different hosting service. Or, if we made a typo when 152 | adding it! 153 | - `git remote rename [oldname] [newname]` changes the local alias by which a remote 154 | is known - its name. For example, one could use this to change `upstream` to `alfred`. 155 | 156 | 157 | :::::::::::::::::::::::::::::::::::::::::::::::::: 158 | 159 | To download the Collaborator's changes from GitHub, the Owner now enters: 160 | 161 | ```bash 162 | $ git pull origin main 163 | ``` 164 | 165 | ```output 166 | remote: Enumerating objects: 4, done. 167 | remote: Counting objects: 100% (4/4), done. 168 | remote: Compressing objects: 100% (2/2), done. 169 | remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0 170 | Unpacking objects: 100% (3/3), done. 171 | From https://github.com/alflin/recipes 172 | * branch main -> FETCH_HEAD 173 | 9272da5..29aba7c main -> origin/main 174 | Updating 9272da5..29aba7c 175 | Fast-forward 176 | hummus.md | 5 + 177 | 1 file changed, 5 insertion(+) 178 | create mode 100644 hummus.md 179 | ``` 180 | 181 | Now the three repositories (Owner's local, Collaborator's local, and Owner's on 182 | GitHub) are back in sync. 183 | 184 | ::::::::::::::::::::::::::::::::::::::::: callout 185 | 186 | ## A Basic Collaborative Workflow 187 | 188 | In practice, it is good to be sure that you have an updated version of the 189 | repository you are collaborating on, so you should `git pull` before making 190 | our changes. The basic collaborative workflow would be: 191 | 192 | - update your local repo with `git pull origin main`, 193 | - make your changes and stage them with `git add`, 194 | - commit your changes with `git commit -m`, and 195 | - upload the changes to GitHub with `git push origin main` 196 | 197 | It is better to make many commits with smaller changes rather than 198 | of one commit with massive changes: small commits are easier to 199 | read and review. 200 | 201 | 202 | :::::::::::::::::::::::::::::::::::::::::::::::::: 203 | 204 | ::::::::::::::::::::::::::::::::::::::: challenge 205 | 206 | ## Switch Roles and Repeat 207 | 208 | Switch roles and repeat the whole process. 209 | 210 | 211 | :::::::::::::::::::::::::::::::::::::::::::::::::: 212 | 213 | ::::::::::::::::::::::::::::::::::::::: challenge 214 | 215 | ## Review Changes 216 | 217 | The Owner pushed commits to the repository without giving any information 218 | to the Collaborator. How can the Collaborator find out what has changed with 219 | command line? And on GitHub? 220 | 221 | ::::::::::::::: solution 222 | 223 | ## Solution 224 | 225 | On the command line, the Collaborator can use `git fetch origin main` 226 | to get the remote changes into the local repository, but without merging 227 | them. Then by running `git diff main origin/main` the Collaborator 228 | will see the changes output in the terminal. 229 | 230 | On GitHub, the Collaborator can go to the repository and click on 231 | "commits" to view the most recent commits pushed to the repository. 232 | 233 | 234 | 235 | ::::::::::::::::::::::::: 236 | 237 | :::::::::::::::::::::::::::::::::::::::::::::::::: 238 | 239 | ::::::::::::::::::::::::::::::::::::::: challenge 240 | 241 | ## Comment Changes in GitHub 242 | 243 | The Collaborator has some questions about one line change made by the Owner and 244 | has some suggestions to propose. 245 | 246 | With GitHub, it is possible to comment on the diff of a commit. Over the line of 247 | code to comment, a blue comment icon appears to open a comment window. 248 | 249 | The Collaborator posts her comments and suggestions using the GitHub interface. 250 | 251 | 252 | :::::::::::::::::::::::::::::::::::::::::::::::::: 253 | 254 | ::::::::::::::::::::::::::::::::::::::: challenge 255 | 256 | ## Version History, Backup, and Version Control 257 | 258 | Some backup software can keep a history of the versions of your files. They also 259 | allows you to recover specific versions. How is this functionality different from version control? 260 | What are some of the benefits of using version control, Git and GitHub? 261 | 262 | 263 | :::::::::::::::::::::::::::::::::::::::::::::::::: 264 | 265 | :::::::::::::::::::::::::::::::::::::::: keypoints 266 | 267 | - `git clone` copies a remote repository to create a local repository with a remote called `origin` automatically set up. 268 | 269 | :::::::::::::::::::::::::::::::::::::::::::::::::: 270 | -------------------------------------------------------------------------------- /episodes/10-open.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Open Science 3 | teaching: 5 4 | exercises: 5 5 | --- 6 | 7 | ::::::::::::::::::::::::::::::::::::::: objectives 8 | 9 | - Explain how a version control system can be leveraged as an electronic lab notebook for computational work. 10 | 11 | :::::::::::::::::::::::::::::::::::::::::::::::::: 12 | 13 | :::::::::::::::::::::::::::::::::::::::: questions 14 | 15 | - How can version control help me make my work more open? 16 | 17 | :::::::::::::::::::::::::::::::::::::::::::::::::: 18 | 19 | > The opposite of "open" isn't "closed". 20 | > The opposite of "open" is "broken". 21 | > 22 | > \--- John Wilbanks 23 | 24 | Free sharing of information might be the ideal in science, 25 | but the reality is often more complicated. 26 | Normal practice today looks something like this: 27 | 28 | - A scientist collects some data and stores it on a machine 29 | that is occasionally backed up by their department. 30 | - They then write or modify a few small programs 31 | (which also reside on the machine) 32 | to analyze that data. 33 | - Once they have some results, 34 | they write them up and submit a paper. 35 | The scientist might include their data -- a growing number of journals require this -- but 36 | they probably don't include the code. 37 | - Time passes. 38 | - The journal sends the scientist reviews written anonymously by a handful of other people in their field. 39 | The scientist revises the paper to satisfy the reviewers, 40 | during which time they might also modify the scripts they wrote earlier, 41 | and resubmits. 42 | - More time passes. 43 | - The paper is eventually published. 44 | It might include a link to an online copy of the data, 45 | but the paper itself will be behind a paywall: 46 | only people who have personal or institutional access 47 | will be able to read it. 48 | 49 | For a growing number of scientists, 50 | though, 51 | the process looks like this: 52 | 53 | - The data that the scientist collects is stored in an open access repository. 54 | Specialised repositories exist for data produced in many domains of research 55 | (e.g. [OpenNeuro](https://openneuro.org/) for neuroscience; [the European Nucleotide Archive](https://www.ebi.ac.uk/ena/browser/home) for genomics), 56 | as well as "generalist" repositories 57 | like [figshare](https://figshare.com/), 58 | [Zenodo](https://zenodo.org), or [Dryad](https://datadryad.org/). 59 | The data may receive its own 60 | [Digital Object Identifier](https://en.wikipedia.org/wiki/Digital_object_identifier) (DOI) when deposited. 61 | - The scientist creates a new repository on GitHub to hold their work. 62 | - During analysis, 63 | they push changes to their scripts 64 | (and possibly some output files) 65 | to that repository. 66 | The scientist also uses the repository for their paper; 67 | that repository is then the hub for collaboration with colleagues. 68 | They may use a "literate programming" tool like [Jupyter](https://jupyter.org/), [R Markdown](https://rmarkdown.rstudio.com/), or [Quarto](https://quarto.org/) to combine these elements together, mixing code for analysis, output from that code, and explanatory comments, notes, and other annotations into a single document. 69 | - When they are happy with the state of the paper, 70 | the scientist posts a version to [arXiv](https://arxiv.org/) 71 | or some other preprint server 72 | to invite feedback from peers. 73 | - Based on that feedback, 74 | they may post several revisions 75 | before finally submitting the paper to a journal. 76 | - The published paper includes links to the preprint 77 | and to the code and data repositories, 78 | which makes it much easier for other scientists 79 | to use their work as starting point for their own research. 80 | 81 | This open model accelerates discovery: 82 | the more open work is, 83 | [the more widely it is cited and re-used](https://doi.org/10.1371/journal.pone.0000308). 84 | However, 85 | people who want to work this way need to make some decisions 86 | about what exactly "open" means and how to do it. You can find more on the different aspects of Open Science in [this book](https://link.springer.com/book/10.1007/978-3-319-00026-8). 87 | 88 | This is one of the (many) reasons we teach version control. 89 | When used diligently, 90 | it answers the "how" question 91 | by acting as a shareable electronic lab notebook for computational work: 92 | 93 | - The conceptual stages of your work are documented, including who did 94 | what and when. Every step is stamped with an identifier (the commit ID) 95 | that is for most intents and purposes unique. 96 | - You can tie documentation of rationale, ideas, and other 97 | intellectual work directly to the changes that spring from them. 98 | - You can refer to what you used in your research to obtain your 99 | computational results in a way that is unique and recoverable. 100 | - With a version control system such as Git, 101 | the entire history of the repository is easy to archive for perpetuity. 102 | 103 | ::::::::::::::::::::::::::::::::::::::::: callout 104 | 105 | ## Making Code Citable 106 | 107 | Anything that is hosted in a version control repository (data, code, papers, 108 | etc.) can be turned into a citable object. You'll learn how to do this in 109 | [the later episode on Citation](12-citation.md). 110 | 111 | 112 | :::::::::::::::::::::::::::::::::::::::::::::::::: 113 | 114 | ::::::::::::::::::::::::::::::::::::::: challenge 115 | 116 | ## How Reproducible Is My Work? 117 | 118 | Ask one of your labmates to reproduce a result you recently obtained 119 | using only what they can find in your papers or on the web. 120 | Try to do the same for one of their results, 121 | then try to do it for a result from a lab you work with. 122 | 123 | 124 | :::::::::::::::::::::::::::::::::::::::::::::::::: 125 | 126 | ::::::::::::::::::::::::::::::::::::::: challenge 127 | 128 | ## How to Find an Appropriate Data Repository? 129 | 130 | Surf the internet for a couple of minutes and check out the generalist data repositories 131 | mentioned above: [Figshare](https://figshare.com/), [Zenodo](https://zenodo.org), 132 | [Dryad](https://datadryad.org/). 133 | Try to also find one or more repositories for data in your field. 134 | You might also find useful [these data repositories recommended by Nature](https://www.nature.com/sdata/data-policies/repositories). 135 | Discuss with your neighbor which data repository you might want to 136 | approach for your current project and explain why. 137 | 138 | :::::: hint 139 | 140 | ### Useful Resource 141 | Confused by the sheer number of different repositories you could choose for your data? 142 | This [repository selection flowchart](https://zenodo.org/records/11105430) aims to "guide users through a series of considerations for slecting the right repository for sharing data." 143 | 144 | ::::::::::::::: 145 | 146 | 147 | :::::::::::::::::::::::::::::::::::::::::::::::::: 148 | 149 | ::::::::::::::::::::::::::::::::::::::: challenge 150 | 151 | ## How to Track Large Data or Image Files using Git? 152 | 153 | Large data or image files such as `.md5` or `.psd` file types can be tracked within 154 | a github repository using the [Git Large File Storage](https://git-lfs.github.com) 155 | open source extension tool. This tool automatically uploads large file contents to 156 | a remote server and replaces the file with a text pointer within the github repository. 157 | 158 | Try downloading and installing the Git Large File Storage extension tool, then add 159 | tracking of a large file to your github repository. Ask a colleague to clone your 160 | repository and describe what they see when they access that large file. 161 | 162 | 163 | :::::::::::::::::::::::::::::::::::::::::::::::::: 164 | 165 | :::::::::::::::::::::::::::::::::::::::: keypoints 166 | 167 | - Open scientific work is more useful and more highly cited than closed. 168 | 169 | :::::::::::::::::::::::::::::::::::::::::::::::::: 170 | 171 | 172 | -------------------------------------------------------------------------------- /episodes/11-licensing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Licensing 3 | teaching: 5 4 | exercises: 0 5 | --- 6 | 7 | ::::::::::::::::::::::::::::::::::::::: objectives 8 | 9 | - Explain why adding licensing information to a repository is important. 10 | - Choose a proper license. 11 | - Explain differences in licensing and social expectations. 12 | 13 | :::::::::::::::::::::::::::::::::::::::::::::::::: 14 | 15 | :::::::::::::::::::::::::::::::::::::::: questions 16 | 17 | - What licensing information should I include with my work? 18 | 19 | :::::::::::::::::::::::::::::::::::::::::::::::::: 20 | 21 | As an open source project, Software Carpentry relies on volunteers to create our lessons and includes a file named `LICENSE` or `LICENSE.txt` file in all public lesson repositories. This file is used to specify that all materials are freely available under the Creative Commons Attribution license. Without a file that clearly states under which license any public source code, manuscript or other creative works is being made available, the default copyright laws apply. To learn more about licensing and open source, you can read more about [Github's description of licenses] and the [legal grounds for open source licensing]. 22 | 23 | A license solves this problem by granting rights to others (the 24 | licensees) that they would otherwise not have. What rights are being 25 | granted under which conditions differs, often only slightly, from one 26 | license to another. In practice, a few licenses are by far the most 27 | popular, and [choosealicense.com](https://choosealicense.com/) will 28 | help you find a common license that suits your needs. Important 29 | considerations include: 30 | 31 | - Whether you want to address patent rights. 32 | - Whether you require people distributing derivative works to also 33 | distribute their source code. 34 | - Whether the content you are licensing is source code. 35 | - Whether you want to license the code at all. 36 | 37 | Choosing a license that is in common use makes life easier for 38 | contributors and users, because they are more likely to already be 39 | familiar with the license and don't have to wade through a bunch of 40 | jargon to decide if they're ok with it. The [Open Source 41 | Initiative](https://opensource.org/licenses) and [Free Software 42 | Foundation](https://www.gnu.org/licenses/license-list.html) both 43 | maintain lists of licenses which are good choices. 44 | 45 | [This article][software-licensing] provides an excellent overview of 46 | licensing and licensing options from the perspective of scientists who 47 | also write code. 48 | 49 | At the end of the day what matters is that there is a clear statement 50 | as to what the license is. Also, the license is best chosen from the 51 | get-go, even if for a repository that is not public. Pushing off the 52 | decision only makes it more complicated later, because each time a new 53 | collaborator starts contributing, they, too, hold copyright and will 54 | thus need to be asked for approval once a license is chosen. 55 | 56 | ::::::::::::::::::::::::::::::::::::::: challenge 57 | 58 | ## Can I Use Open License? 59 | 60 | Find out whether you are allowed to apply an open license to your software. 61 | Can you do this unilaterally, 62 | or do you need permission from someone in your institution? 63 | If so, who? 64 | 65 | 66 | :::::::::::::::::::::::::::::::::::::::::::::::::: 67 | 68 | ::::::::::::::::::::::::::::::::::::::: challenge 69 | 70 | ## What licenses have I already accepted? 71 | 72 | Many of the software tools we use on a daily basis (including in this workshop) are 73 | released as open-source software. Pick a project on GitHub from the list below, or 74 | one of your own choosing. Find its license (usually in a file called `LICENSE` or 75 | `COPYING`) and talk about how it restricts your use of the software. Is it one of 76 | the licenses discussed in this session? How is it different? 77 | 78 | - [Git](https://github.com/git/git), the source-code management tool 79 | - [CPython](https://github.com/python/cpython), the standard implementation of the Python language 80 | - [Jupyter](https://github.com/jupyter), the project behind the web-based Python notebooks we'll be using 81 | - [EtherPad](https://github.com/ether/etherpad-lite), a real-time collaborative editor 82 | 83 | 84 | :::::::::::::::::::::::::::::::::::::::::::::::::: 85 | 86 | [software-licensing]: https://doi.org/10.1371/journal.pcbi.1002598 87 | [Github's description of licenses]: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/licensing-a-repository 88 | [legal grounds for open source licensing]: https://opensource.guide/legal/#are-public-github-projects-open-source 89 | 90 | :::::::::::::::::::::::::::::::::::::::: keypoints 91 | 92 | - The `LICENSE`, `LICENSE.md`, or `LICENSE.txt` file is often used in a repository to indicate how the contents of the repo may be used by others. 93 | - People who incorporate General Public License (GPL'd) software into their own software must make the derived software also open under the GPL license if they decide to share it; most other open licenses do not require this. 94 | - The Creative Commons family of licenses allow people to mix and match requirements and restrictions on attribution, creation of derivative works, further sharing, and commercialization. 95 | - People who are not lawyers should not try to write licenses from scratch. 96 | 97 | :::::::::::::::::::::::::::::::::::::::::::::::::: 98 | 99 | 100 | -------------------------------------------------------------------------------- /episodes/12-citation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Citation 3 | teaching: 2 4 | exercises: 0 5 | --- 6 | 7 | ::::::::::::::::::::::::::::::::::::::: objectives 8 | 9 | - Make your work easy to cite 10 | 11 | :::::::::::::::::::::::::::::::::::::::::::::::::: 12 | 13 | :::::::::::::::::::::::::::::::::::::::: questions 14 | 15 | - How can I make my work easier to cite? 16 | 17 | :::::::::::::::::::::::::::::::::::::::::::::::::: 18 | 19 | You may want to include a file called `CITATION` or `CITATION.txt` 20 | that describes how to reference your project; 21 | the [one for Software 22 | Carpentry](https://github.com/swcarpentry/website/blob/gh-pages/CITATION) 23 | states: 24 | 25 | ```source 26 | To reference Software Carpentry in publications, please cite: 27 | 28 | Greg Wilson: "Software Carpentry: Lessons Learned". F1000Research, 29 | 2016, 3:62 (doi: 10.12688/f1000research.3-62.v2). 30 | 31 | @online{wilson-software-carpentry-2016, 32 | author = {Greg Wilson}, 33 | title = {Software Carpentry: Lessons Learned}, 34 | version = {2}, 35 | date = {2016-01-28}, 36 | url = {http://f1000research.com/articles/3-62/v2}, 37 | doi = {10.12688/f1000research.3-62.v2} 38 | } 39 | ``` 40 | 41 | More detailed advice, and other ways to make your code citable can be found 42 | [at the Software Sustainability Institute blog](https://www.software.ac.uk/publication/how-cite-and-describe-software) and in: 43 | 44 | ```source 45 | Smith AM, Katz DS, Niemeyer KE, FORCE11 Software Citation Working Group. (2016) Software citation 46 | principles. [PeerJ Computer Science 2:e86](https://peerj.com/articles/cs-86/) 47 | https://doi.org/10.7717/peerj-cs.8 48 | ``` 49 | 50 | There is also an [`@software{...`](https://www.google.com/search?q=git+citation+%22%40software%7B%22) 51 | [BibTeX](https://www.ctan.org/pkg/bibtex) entry type in case 52 | no "umbrella" citation like a paper or book exists for the project you want to 53 | make citable. 54 | 55 | Finally, you may wish to include citation information in a [Citation File Format 56 | (`CITATION.cff`)](https://citation-file-format.github.io/). CFF files are standardized human and machine readable citation 57 | information files for software and datasets. If you host your repository on GitHub, this information is automatically linked 58 | and rendered on the repository page and a BibTeX snippet is provided, which users can copy and paste, making it easy for 59 | your project to be cited. Further, integration with both Zenodo and Zotero is supported. 60 | 61 | A [chapter of The Turing Way](https://the-turing-way.netlify.app/communication/citable/citable-cite#citing-software) provides more detail on how you can use CFF files to make your software citable. 62 | 63 | You can use the [cff-init](https://citation-file-format.github.io/cff-initializer-javascript/#/) website to easily 64 | create and update a `CITATION.cff` file. 65 | 66 | :::::::::::::::::::::::::::::::::::::::: keypoints 67 | 68 | - Add a CITATION file to a repository to explain how you want your work cited. 69 | 70 | :::::::::::::::::::::::::::::::::::::::::::::::::: 71 | -------------------------------------------------------------------------------- /episodes/13-hosting.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hosting 3 | teaching: 10 4 | exercises: 0 5 | --- 6 | 7 | ::::::::::::::::::::::::::::::::::::::: objectives 8 | 9 | - Explain different options for hosting scientific work. 10 | 11 | :::::::::::::::::::::::::::::::::::::::::::::::::: 12 | 13 | :::::::::::::::::::::::::::::::::::::::: questions 14 | 15 | - Where should I host my version control repositories? 16 | 17 | :::::::::::::::::::::::::::::::::::::::::::::::::: 18 | 19 | After [choosing a license](11-licensing.md), 20 | another big question for groups that want to open up their work is where to 21 | host their code and data. One option is for the lab, the department, or the 22 | university to provide a server, manage accounts and backups, and so on. The 23 | main benefit of this is that it clarifies who owns what, which is particularly 24 | important if any of the material is sensitive (i.e., relates to experiments 25 | involving human subjects or may be used in a patent application). The main 26 | drawbacks are the cost of providing the service and its longevity: a scientist 27 | who has spent ten years collecting data would like to be sure that data will 28 | still be available ten years from now, but that's well beyond the lifespan of 29 | most of the grants that fund academic infrastructure. 30 | 31 | Another option is to purchase a domain and pay an Internet service provider 32 | (ISP) to host it. This gives the individual or group more control, and 33 | sidesteps problems that can arise when moving from one institution to another, 34 | but requires more time and effort to set up than either the option above or the 35 | option below. 36 | 37 | The third option is to use a public hosting service like 38 | [GitHub](https://github.com), [GitLab](https://gitlab.com), or 39 | [BitBucket](https://bitbucket.org). 40 | Each of these services provides a web interface that enables people to create, 41 | view, and edit their code repositories. These services also provide 42 | communication and project management tools including issue tracking, wiki pages, 43 | email notifications, and code reviews. These services benefit from economies of 44 | scale and network effects: it's easier to run one large service well than to run 45 | many smaller services to the same standard. It's also easier for people to 46 | collaborate. Using a popular service can help connect your project with 47 | communities already using the same service. 48 | 49 | As an example, Software Carpentry [is on GitHub](https://github.com/swcarpentry/) where you can find the [source for this 50 | page](https://github.com/swcarpentry/git-novice/blob/main/episodes/13-hosting.md). Anyone with a GitHub account can suggest changes to this text. 51 | 52 | GitHub repositories can also be assigned DOIs, [by connecting its releases to 53 | Zenodo](https://guides.github.com/activities/citable-code/). For example, 54 | [`10.5281/zenodo.7908089`](https://zenodo.org/record/7908089) is the DOI that has 55 | been "minted" for this introduction to Git. 56 | 57 | Using large, well-established services can also help you quickly take advantage 58 | of powerful tools. One such tool, continuous integration (CI), can 59 | automatically run software builds and tests whenever code is committed or pull 60 | requests are submitted. Direct integration of CI with an online hosting service 61 | means this information is present in any pull request, and helps maintain code 62 | integrity and quality standards. While CI is still available in self-hosted 63 | situations, there is much less setup and maintenance involved with using an 64 | online service. Furthermore, such tools are often provided free of charge to 65 | open source projects, and are also available for private repositories for a fee. 66 | 67 | ::::::::::::::::::::::::::::::::::::::::: callout 68 | 69 | ## Institutional Barriers 70 | 71 | Sharing is the ideal for science, 72 | but many institutions place restrictions on sharing, 73 | for example to protect potentially patentable intellectual property. 74 | If you encounter such restrictions, 75 | it can be productive to inquire about the underlying motivations and 76 | either to request an exception for a specific project or domain, 77 | or to push more broadly for institutional reform to support more open science. 78 | 79 | 80 | :::::::::::::::::::::::::::::::::::::::::::::::::: 81 | 82 | ::::::::::::::::::::::::::::::::::::::: challenge 83 | 84 | ## Can My Work Be Public? 85 | 86 | Find out whether you are allowed to host your work openly in a public repository. 87 | Can you do this unilaterally, 88 | or do you need permission from someone in your institution? 89 | If so, who? 90 | 91 | 92 | :::::::::::::::::::::::::::::::::::::::::::::::::: 93 | 94 | ::::::::::::::::::::::::::::::::::::::: challenge 95 | 96 | ## Where Can I Share My Work? 97 | 98 | Does your institution have a repository or repositories that you can 99 | use to share your papers, data and software? How do institutional repositories 100 | differ from services like [arXiV](https://arxiv.org/), [figshare](https://figshare.com/), [GitHub](https://github.com/) or [GitLab](https://about.gitlab.com/)? 101 | 102 | 103 | :::::::::::::::::::::::::::::::::::::::::::::::::: 104 | 105 | :::::::::::::::::::::::::::::::::::::::: keypoints 106 | 107 | - Projects can be hosted on university servers, on personal domains, or on a public hosting service. 108 | - Rules regarding intellectual property and storage of sensitive information apply no matter where code and data are hosted. 109 | 110 | :::::::::::::::::::::::::::::::::::::::::::::::::: 111 | 112 | 113 | -------------------------------------------------------------------------------- /episodes/14-supplemental-rstudio.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Supplemental: Using Git from RStudio' 3 | teaching: 10 4 | exercises: 0 5 | --- 6 | 7 | ::::::::::::::::::::::::::::::::::::::: objectives 8 | 9 | - Understand how to use Git from RStudio. 10 | 11 | :::::::::::::::::::::::::::::::::::::::::::::::::: 12 | 13 | :::::::::::::::::::::::::::::::::::::::: questions 14 | 15 | - How can I use Git with RStudio? 16 | 17 | :::::::::::::::::::::::::::::::::::::::::::::::::: 18 | 19 | Version control can be very useful when developing data analysis scripts. For 20 | that reason, the popular development environment 21 | [RStudio][rstudio] for the R programming language has built-in 22 | integration with Git. While some advanced Git features still require the 23 | command-line, RStudio has a nice interface for many common Git operations. 24 | 25 | RStudio allows us to create a [project][rstudio-projects] associated with a 26 | given directory to keep track of various related files. To be able to track the 27 | development of the project over time, to be able to revert to previous 28 | versions, and to collaborate with others, we version control the Rstudio 29 | project with Git. To get started using Git in RStudio, we create a new project: 30 | 31 | ![](fig/RStudio_screenshot_newproject.png){alt='RStudio screenshot showing the file menu dropdown with "New Project..." selected'} 32 | 33 | This opens a dialog asking us how we want to create the project. We have 34 | some options here. Let's say that we want to use RStudio with the recipes 35 | repository that we already made. Since that repository lives in a directory on 36 | our computer, we choose the option "Existing Directory": 37 | 38 | ![](fig/RStudio_screenshot_existingdirectory.png){alt='RStudio screenshot showing New Project dialog window with "Create project from existing directory" selected'} 39 | 40 | ::::::::::::::::::::::::::::::::::::::::: callout 41 | 42 | ## Do You See a "Version Control" Option? 43 | 44 | Although we're not going to use it here, there should be a "version control" 45 | option on this menu. That is what you would click on if you wanted to 46 | create a project on your computer by cloning a repository from GitHub. 47 | If that option is not present, it probably means that RStudio doesn't know 48 | where your Git executable is, and you won't be able to progress further 49 | in this lesson until you tell RStudio where it is. 50 | 51 | ### Find your Git Executable 52 | 53 | First let's make sure that Git is installed on your computer. 54 | Open your shell on Mac or Linux, or on Windows open the command prompt 55 | and then type: 56 | 57 | - `which git` (macOS, Linux) 58 | - `where git` (Windows) 59 | 60 | If there is no version of Git on your computer, please follow the 61 | [Git installation instructions](https://swcarpentry.github.io/git-novice/#installing-git) 62 | in the setup of this lesson to install Git now. Next open your shell or command prompt 63 | and type `which git` (macOS, Linux), or `where git` (Windows). 64 | Copy the path to the git executable. 65 | 66 | On one Windows computer which had GitHub Desktop installed on it, the path was: 67 | `C:/Users/UserName/AppData/Local/GitHubDesktop/app-1.1.1/resources/app/git/cmd/git.exe` 68 | 69 | NOTE: The path on your computer will be somewhat different. 70 | 71 | ### Tell RStudio where to find GitHub 72 | 73 | In RStudio, go to the `Tools` menu > `Global Options` > `Git/SVN` and then 74 | browse to the Git executable you found in the command prompt or shell. Now restart 75 | RStudio. 76 | Note: Even if you have Git installed, you may need 77 | to accept the Xcode license if you are using macOS. 78 | 79 | 80 | :::::::::::::::::::::::::::::::::::::::::::::::::: 81 | 82 | Next, RStudio will ask which existing directory we want to use. Click 83 | "Browse..." and navigate to the correct directory, then click "Create Project": 84 | 85 | ![](fig/RStudio_screenshot_navigateexisting.png){alt='RStudio window showing the "Create Project From Existing Directory" dialog. In the dialog, the project working directory has been set to "~/Desktop/recipes"'} 86 | 87 | Ta-da! We have created a new project in RStudio within the existing recipes 88 | repository. Notice the vertical "Git" menu in the menu bar. RStudio has 89 | recognized that the current directory is a Git repository, and gives us a 90 | number of tools to use Git: 91 | 92 | ![](fig/RStudio_screenshot_afterclone.png){alt='RStudio window after new project is created with large arrow pointing to vertical Git menu bar.'} 93 | 94 | To edit the existing files in the repository, we can click on them in the 95 | "Files" panel on the lower right. Now let's add some additional information 96 | about Hummus: 97 | 98 | ![](fig/RStudio_screenshot_editfiles.png){alt='RStudio window demonstrating the use of the editor panel to modify the "pluto.txt" file'} 99 | 100 | Once we have saved our edited files, we can use RStudio to commit the changes 101 | by clicking on "Commit..." in the Git menu: 102 | 103 | ![](fig/RStudio_screenshot_commit.png){alt='RStudio screenshot showing the Git menu dropdown with the "Commit..." option selected'} 104 | 105 | This will open a dialogue where we can select which files to commit (by 106 | checking the appropriate boxes in the "Staged" column), and enter a commit 107 | message (in the upper right panel). The icons in the "Status" column indicate 108 | the current status of each file. Clicking on a file shows information about 109 | changes in the lower panel (using output of `git diff`). Once everything is the 110 | way we want it, we click "Commit": 111 | 112 | ![](fig/RStudio_screenshot_review.png){alt='RStudio screenshow showing the "Review Changes" dialog. The top left panel shows the list of files that can be included or excluded from the commit. The top right panel is for writing a commit message. The bottom panel shows information about the currently selected file in the top left panel.'} 113 | 114 | The changes can be pushed by selecting "Push Branch" from the Git menu. There 115 | are also options to pull from the remote repository, and to view the commit 116 | history: 117 | 118 | ![](fig/RStudio_screenshot_history.png){alt='RStudio screenshot showing the git menu dropdown with the "History" option selected'} 119 | 120 | ::::::::::::::::::::::::::::::::::::::::: callout 121 | 122 | ## Are the Push/Pull Commands Grayed Out? 123 | 124 | Grayed out Push/Pull commands generally mean that RStudio doesn't know the 125 | location of your remote repository (e.g. on GitHub). To fix this, open a 126 | terminal to the repository and enter the command: `git push -u origin main`. Then restart RStudio. 127 | 128 | 129 | :::::::::::::::::::::::::::::::::::::::::::::::::: 130 | 131 | If we click on "History", we can see a graphical version of what `git log` 132 | would tell us: 133 | 134 | ![](fig/RStudio_screenshot_viewhistory.png){alt='RStudio screenshot showing the "Review Changes" dialog after pressing the "History" button. The top panel lists the commits in the repository, similar to git log. The bottom panel shows the changes included in the commit that has been selected in the top panel.'} 135 | 136 | RStudio creates a number of files that it uses to keep track of a project. We 137 | often don't want to track these, in which case we add them to our `.gitignore` 138 | file: 139 | 140 | ![](fig/RStudio_screenshot_gitignore.png){alt='RStudio screenshot showing .gitignore open in the editor pane with the files .Rproj.user, .Rhistory, .RData, and \*.Rproj added to the end'} 141 | 142 | ::::::::::::::::::::::::::::::::::::::::: callout 143 | 144 | ## Tip: versioning disposable output 145 | 146 | Generally you do not want to version control disposable output (or read-only 147 | data). You should modify the `.gitignore` file to tell Git to ignore these 148 | files and directories. 149 | 150 | 151 | :::::::::::::::::::::::::::::::::::::::::::::::::: 152 | 153 | ::::::::::::::::::::::::::::::::::::::: challenge 154 | 155 | ## Challenge 156 | 157 | 1. Create a new directory within your project called `graphs`. 158 | 2. Modify the `.gitignore` so that the `graphs` directory is not version controlled. 159 | 160 | ::::::::::::::: solution 161 | 162 | ## Solution to Challenge 163 | 164 | This can be done in Rstudio: 165 | 166 | ```r 167 | dir.create("./graphs") 168 | ``` 169 | 170 | Then open up the `.gitignore` file from the right-hand panel of Rstudio and add 171 | `graphs/` to the list of files to ignore. 172 | 173 | 174 | 175 | ::::::::::::::::::::::::: 176 | 177 | :::::::::::::::::::::::::::::::::::::::::::::::::: 178 | 179 | There are many more features in the RStudio Git menu, but these should be 180 | enough to get you started! 181 | 182 | [rstudio]: https://www.rstudio.com/ 183 | [rstudio-projects]: https://support.rstudio.com/hc/en-us/articles/200526207-Using-Projects 184 | 185 | 186 | :::::::::::::::::::::::::::::::::::::::: keypoints 187 | 188 | - Using RStudio's Git integration allows you to version control a project over time. 189 | 190 | :::::::::::::::::::::::::::::::::::::::::::::::::: 191 | -------------------------------------------------------------------------------- /episodes/fig/RStudio_screenshot_afterclone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/RStudio_screenshot_afterclone.png -------------------------------------------------------------------------------- /episodes/fig/RStudio_screenshot_commit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/RStudio_screenshot_commit.png -------------------------------------------------------------------------------- /episodes/fig/RStudio_screenshot_editfiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/RStudio_screenshot_editfiles.png -------------------------------------------------------------------------------- /episodes/fig/RStudio_screenshot_existingdirectory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/RStudio_screenshot_existingdirectory.png -------------------------------------------------------------------------------- /episodes/fig/RStudio_screenshot_gitignore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/RStudio_screenshot_gitignore.png -------------------------------------------------------------------------------- /episodes/fig/RStudio_screenshot_history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/RStudio_screenshot_history.png -------------------------------------------------------------------------------- /episodes/fig/RStudio_screenshot_navigateexisting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/RStudio_screenshot_navigateexisting.png -------------------------------------------------------------------------------- /episodes/fig/RStudio_screenshot_newproject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/RStudio_screenshot_newproject.png -------------------------------------------------------------------------------- /episodes/fig/RStudio_screenshot_review.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/RStudio_screenshot_review.png -------------------------------------------------------------------------------- /episodes/fig/RStudio_screenshot_viewhistory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/RStudio_screenshot_viewhistory.png -------------------------------------------------------------------------------- /episodes/fig/conflict.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | image/svg+xml 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 88 | 309 | -------------------------------------------------------------------------------- /episodes/fig/git-freshly-made-github-repo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | image/svg+xml.git 79 | https://github.com/alflin/recipes.git 85 | .git 111 | ~/alflin/recipes 123 | git add 272 | git commit 293 | staging area 304 | repository 315 | -------------------------------------------------------------------------------- /episodes/fig/git-restore.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | .git 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 31 | 32 | 35 | 36 | 37 | 40 | 41 | 42 | 44 | 45 | 46 | 47 | 48 | 50 | 51 | 52 | 53 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | FILE1.txt 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | FILE2.txt 85 | 86 | 87 | HEAD 88 | 89 | HEAD~1 90 | 91 | HEAD~2 92 | 93 | 892134f 94 | 95 | f22b25e 96 | 97 | 3a54f76 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | git restore -s HEAD~1 .or git restore -s f22b25e . 107 | 108 | 109 | repository 110 | 111 | 112 | -------------------------------------------------------------------------------- /episodes/fig/git-staging-area.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | .git 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 26 | 27 | 28 | 29 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 43 | 44 | 48 | 49 | 50 | 53 | 54 | 55 | 58 | 59 | 60 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | git add 82 | 83 | 84 | 85 | 86 | 87 | git commit 88 | 89 | staging area 90 | 91 | repository 92 | 93 | 94 | -------------------------------------------------------------------------------- /episodes/fig/github-add-collaborators.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/github-add-collaborators.png -------------------------------------------------------------------------------- /episodes/fig/github-change-repo-string.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/github-change-repo-string.png -------------------------------------------------------------------------------- /episodes/fig/github-create-repo-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/github-create-repo-01.png -------------------------------------------------------------------------------- /episodes/fig/github-create-repo-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/github-create-repo-02.png -------------------------------------------------------------------------------- /episodes/fig/github-create-repo-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/github-create-repo-03.png -------------------------------------------------------------------------------- /episodes/fig/github-find-repo-string.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/github-find-repo-string.png -------------------------------------------------------------------------------- /episodes/fig/merge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /episodes/fig/phd101212s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/phd101212s.png -------------------------------------------------------------------------------- /episodes/fig/play-changes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /episodes/fig/versions.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 190 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: index.html 3 | site: sandpaper::sandpaper_site 4 | --- 5 | 6 | Jimmy and Alfredo have been hired by Ratatouille restaurant (a special 7 | restaurant from Euphoric State University) to investigate if it 8 | is possible to make the best recipes archive ever. They want to 9 | be able to work on indexing the prices at the same time, but they have run into 10 | problems doing this in the past. If they take turns, each one will 11 | spend a lot of time waiting for the other to finish, but if they work 12 | on their own copies and email changes back and forth things will be 13 | lost, overwritten, or duplicated. 14 | 15 | A colleague suggests using [version control](learners/reference.md#version-control) to 16 | manage their work. Version control is better than mailing files back and forth: 17 | 18 | - Nothing that is committed to version control is ever lost, unless 19 | you work really, really hard at losing it. Since all old versions of 20 | files are saved, it's always possible to go back in time to see 21 | exactly who wrote what on a particular day, or what version of a 22 | program was used to generate a particular set of results. 23 | 24 | - As we have this record of who made what changes when, we know who to ask 25 | if we have questions later on, and, if needed, revert to a previous 26 | version, much like the "undo" feature in an editor. 27 | 28 | - When several people collaborate in the same project, it's possible to 29 | accidentally overlook or overwrite someone's changes. The version control 30 | system automatically notifies users whenever there's a conflict between one 31 | person's work and another's. 32 | 33 | Teams are not the only ones to benefit from version control: lone 34 | researchers can benefit immensely. Keeping a record of what was 35 | changed, when, and why is extremely useful for all researchers if they 36 | ever need to come back to the project later on (e.g., a year later, 37 | when memory has faded). 38 | 39 | Version control is the lab notebook of the digital world: it's what 40 | professionals use to keep track of what they've done and to 41 | collaborate with other people. Every large software development 42 | project relies on it, and most programmers use it for their small jobs 43 | as well. And it isn't just for software: books, 44 | papers, small data sets, and anything that changes over time or needs 45 | to be shared can and should be stored in a version control system. 46 | 47 | :::::::::::::::::::::::::::::::::::::::::: prereq 48 | 49 | ## Prerequisites 50 | 51 | In this lesson we use Git from the Unix Shell. 52 | Some previous experience with the shell is expected, 53 | *but isn't mandatory*. 54 | 55 | 56 | :::::::::::::::::::::::::::::::::::::::::::::::::: 57 | 58 | 59 | -------------------------------------------------------------------------------- /learners/discuss.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Discussion 3 | --- 4 | 5 | ## Frequently Asked Questions 6 | 7 | People often have questions about Git beyond the scope of the core material. 8 | Students who have completed the rest of the lessons might find value in looking through the following topics. 9 | 10 | Note that since this material isn't essential for basic Git usage, it won't be covered by the instructor. 11 | 12 | ## More Advanced Git Configuration 13 | 14 | In [Setting Up Git](../episodes/02-setup.md), 15 | we used `git config --global` to set some default options for Git. 16 | It turns out that these configuration options get stored in your home directory 17 | in a plain text file called `.gitconfig`. 18 | 19 | ```bash 20 | $ cat ~/.gitconfig 21 | ``` 22 | 23 | ```output 24 | [user] 25 | name = Alfredo Linguini 26 | email = a.linguini@ratatouille.fr 27 | [color] 28 | ui = true 29 | [core] 30 | editor = nano 31 | ``` 32 | 33 | This file can be opened in your preferred text editor. 34 | (Note that it is recommended to continue using the `git config` command, 35 | as this helps avoid introducing syntax errors.) 36 | 37 | Eventually, you will want to start customizing Git's behaviour. 38 | This can be done by adding more entries to your `.gitconfig`. 39 | The available options are described in the manual: 40 | 41 | ```bash 42 | $ git config --help 43 | ``` 44 | 45 | In particular, you might find it useful to add aliases. 46 | These are like shortcuts for longer Git commands. 47 | For example, if you get sick of typing `git checkout` all the time, 48 | you could run the command: 49 | 50 | ```bash 51 | $ git config --global alias.co checkout 52 | ``` 53 | 54 | Now if we return to the example from [Exploring History](../episodes/05-history.md) where we ran: 55 | 56 | ```bash 57 | $ git checkout f22b25e guacamole.md 58 | ``` 59 | 60 | we could now instead type: 61 | 62 | ```bash 63 | $ git co f22b25e guacamole.md 64 | ``` 65 | 66 | ## Styling Git's Log 67 | 68 | A good target for customization is output from the log. 69 | The default log is quite verbose but gives no graphical hints 70 | such as information about which commits were done locally 71 | and which were pulled from remotes. 72 | 73 | You can use `git log --help` and `git config --help` to look for different ways to change 74 | the log output. 75 | Try the following commands and see what effect they have: 76 | 77 | ```bash 78 | $ git config --global alias.lg "log --graph" 79 | $ git config --global log.abbrevCommit true 80 | $ git config --global format.pretty oneline 81 | $ git lg 82 | ``` 83 | 84 | If you don't like the effects, 85 | you can undo them with: 86 | 87 | ```bash 88 | $ git config --global --unset alias.lg 89 | $ git config --global --unset log.abbrevCommit 90 | $ git config --global --unset format.pretty 91 | ``` 92 | 93 | ::::::::::::::::::::::::::::::::::::::::: callout 94 | 95 | ## Undoing Git Configuration Changes 96 | 97 | You can use the `--unset` flag to delete unwanted options from `.gitconfig`. 98 | Another way to roll back changes is to store your `.gitconfig` using Git. 99 | 100 | For hints on what you might want to configure, 101 | go to GitHub and search for "gitconfig". 102 | You will find hundreds of repositories in which people have stored 103 | their own Git configuration files. 104 | Sort them by the number of stars and have a look at the top few. 105 | If you find some you like, 106 | please check that they're covered by an open source license before you clone them. 107 | 108 | 109 | :::::::::::::::::::::::::::::::::::::::::::::::::: 110 | 111 | ## Non-text Files 112 | 113 | Recall when we discussed [Conflicts](../episodes/09-conflict.md) 114 | there was a challenge that asked, 115 | "What does Git do 116 | when there is a conflict in an image or some other non-textual file 117 | that is stored in version control?" 118 | 119 | We will now revisit this in more detail. 120 | 121 | Many people want to version control non-text files, such as images, PDFs and Microsoft Office or LibreOffice documents. 122 | It is true that Git can handle these filetypes (which fall under the banner of "binary" file types). 123 | However, just because it *can* be done doesn't mean it *should* be done. 124 | 125 | Much of Git's magic comes from being able to do line-by-line comparisons ("diffs") between files. 126 | This is generally easy for programming source code and marked up text. 127 | For non-text files, a diff can usually only detect that the files have changed 128 | but can't say how or where. 129 | 130 | This has various impacts on Git's performance and will make it difficult to 131 | compare different versions of your project. 132 | 133 | For a basic example to show the difference it makes, 134 | we're going to go see what would have happened if Alfredo had tried 135 | using outputs from a word processor instead of plain text. 136 | 137 | Create a new directory and go into it: 138 | 139 | ```bash 140 | $ mkdir recipes-nontext 141 | $ cd recipes-nontext 142 | ``` 143 | 144 | Use a program such as Microsoft Word or LibreOffice Writer to create a new document. 145 | Enter the same text that we began with before: 146 | 147 | ```output 148 | # Ingredients 149 | # Instructions 150 | ``` 151 | 152 | Save the document into the `recipes-nontext` directory with the name of `guacamole.doc`. 153 | Back in the terminal, run the usual commands for setting up a new Git repository: 154 | 155 | ```bash 156 | $ git init 157 | $ git add guacamole.doc 158 | $ git commit -m "Create a template for recipe" 159 | ``` 160 | 161 | Then make the same changes to `guacamole.doc` that we (or Alfredo) previously made to `guacamole.md`. 162 | 163 | ```output 164 | # Ingredients 165 | - avocado 166 | - lemon 167 | - salt 168 | # Instructions 169 | ``` 170 | 171 | Save and close the word processor. 172 | Now see what Git thinks of your changes: 173 | 174 | ```bash 175 | $ git diff 176 | ``` 177 | 178 | ```output 179 | diff --git a/guacamole.doc b/guacamole.doc 180 | index 53a66fd..6e988e9 100644 181 | Binary files a/guacamole.doc and b/guacamole.doc differ 182 | ``` 183 | 184 | Compare this to the earlier `git diff` obtained when using text files: 185 | 186 | ```output 187 | diff --git a/guacamole.md b/guacamole.md 188 | index df0654a..315bf3a 100644 189 | --- a/guacamole.md 190 | +++ b/guacamole.md 191 | @@ -1,2 +1,5 @@ 192 | # Ingredients 193 | +- avocado 194 | +- lemon 195 | +- salt 196 | # Instructions 197 | ``` 198 | 199 | Notice how plain text files give a much more informative diff. 200 | You can see exactly which lines changed and what the changes were. 201 | 202 | An uninformative `git diff` is not the only consequence of using Git on binary files. 203 | However, most of the other problems boil down to whether or not a good diff is possible. 204 | 205 | This isn't to say you should *never* use Git on binary files. 206 | A rule of thumb is that it's OK if the binary file won't change very often, 207 | and if it does change, you don't care about merging in small differences between versions. 208 | 209 | We've already seen how a word processed report will fail this test. 210 | An example that passes the test is a logo for your organization or project. 211 | Even though a logo will be stored in a binary format such as `jpg` or `png`, 212 | you can expect it will remain fairly static through the lifetime of your repository. 213 | On the rare occasion that branding does change, 214 | you will probably just want to replace the logo completely rather than merge little differences in. 215 | 216 | ## Removing a File 217 | 218 | Adding and modifying files are not the only actions one might take 219 | when working on a project. It might be required to remove a file 220 | from the repository. 221 | 222 | Create a new file for the invisible ink: 223 | 224 | ```bash 225 | $ echo "This is where we keep the secret sauce" > invisible.md 226 | ``` 227 | 228 | Now add to the repository like you have learned earlier: 229 | 230 | ```bash 231 | $ git add invisible.md 232 | $ git commit -m 'Add secret sauce' 233 | $ git status 234 | ``` 235 | 236 | ```output 237 | On branch main 238 | nothing to commit, working directory clean 239 | ``` 240 | 241 | Invisible ink is not a real food. That was a silly idea. Let us remove 242 | it from the disk and let Git know about it: 243 | 244 | ```bash 245 | $ git rm invisible.md 246 | $ git status 247 | ``` 248 | 249 | ```output 250 | On branch main 251 | Changes to be committed: 252 | (use "git reset HEAD ..." to unstage) 253 | 254 | deleted: invisible.md 255 | 256 | ``` 257 | 258 | The change has been staged. Now commit the removal, and remove the 259 | file from the repository itself. Note that the file will be removed 260 | in the new commit. The previous commit will still 261 | have the file, if you were to retrieve that specific commit. 262 | 263 | ```bash 264 | $ git commit -m 'Remove info on Invisible ink. It is not an edible sauce!' 265 | ``` 266 | 267 | ## Removing a File with Unix 268 | 269 | Sometimes we might forget to remove the file through Git. If you removed the 270 | file with Unix `rm` instead of using `git rm`, no worries, 271 | Git is smart enough to notice the missing file. Let us recreate the file and 272 | commit it again. 273 | 274 | ```bash 275 | $ echo "This is another way to make invisible ink" > secret.md 276 | $ git add secret.md 277 | $ git commit -m 'Add invisible ink again' 278 | ``` 279 | 280 | Now we remove the file with Unix `rm`: 281 | 282 | ```bash 283 | $ rm secret.md 284 | $ git status 285 | ``` 286 | 287 | ```output 288 | On branch main 289 | Changes not staged for commit: 290 | (use "git add/rm ..." to update what will be committed) 291 | (use "git checkout -- ..." to discard changes in working directory) 292 | 293 | deleted: secret.md 294 | 295 | no changes added to commit (use "git add" and/or "git commit -a") 296 | ``` 297 | 298 | See how Git has noticed that the file `secret.md` has been removed 299 | from the disk. The next step is to "stage" the removal of the file 300 | from the repository. This is done with the command `git rm` just as 301 | before. 302 | 303 | ```bash 304 | $ git rm secret.md 305 | $ git status 306 | ``` 307 | 308 | ```output 309 | On branch main 310 | Changes to be committed: 311 | (use "git reset HEAD ..." to unstage) 312 | 313 | deleted: secret.md 314 | 315 | ``` 316 | 317 | The change that was made in Unix has now been staged and needs to be 318 | committed. 319 | 320 | ```bash 321 | $ git commit -m 'Remove info on invisible ink, again!' 322 | ``` 323 | 324 | ## Renaming a File 325 | 326 | Another common change when working on a project is to rename a file. 327 | 328 | Create a file for the whitesauce recipe: 329 | 330 | ```bash 331 | $ echo "Very fun recipe to do" > whitesauce.md 332 | ``` 333 | 334 | Add it to the repository: 335 | 336 | ```bash 337 | $ git add whitesauce.md 338 | $ git commit -m 'Add white sauce recipe' 339 | ``` 340 | 341 | We all know that white sauce has a more sophisticated name. 342 | 343 | Rename the file `whitesauce.md` to `bechamel.md` with Git: 344 | 345 | ```bash 346 | $ git mv whitesauce.md bechamel.md 347 | $ git status 348 | ``` 349 | 350 | ```output 351 | On branch main 352 | Changes to be committed: 353 | (use "git reset HEAD ..." to unstage) 354 | 355 | renamed: whitesauce.md -> bechamel.md 356 | ``` 357 | 358 | The final step is commit our change to the repository: 359 | 360 | ```bash 361 | $ git commit -m 'Use the French name for the whitesauce' 362 | ``` 363 | 364 | ## Renaming a File with Unix 365 | 366 | If you forgot to use Git and you used Unix `mv` instead 367 | of `git mv`, you will have a touch more work to do but Git will 368 | be able to deal with it. Let's try again renaming the file, 369 | this time with Unix `mv`. First, we need to recreate the 370 | `whitesauce.md` file: 371 | 372 | ```bash 373 | $ echo "Very fun recipe to do" > whitesauce.md 374 | $ git add whitesauce.md 375 | $ git commit -m 'Add white sauce recipe' 376 | ``` 377 | 378 | Let us rename the file and see what Git can figure out by itself: 379 | 380 | ```bash 381 | $ mv whitesauce.md bechamel.md 382 | $ git status 383 | ``` 384 | 385 | ```output 386 | On branch main 387 | Changes not staged for commit: 388 | (use "git add/rm ..." to update what will be committed) 389 | (use "git checkout -- ..." to discard changes in working directory) 390 | 391 | deleted: whitesauce.md 392 | 393 | Untracked files: 394 | (use "git add ..." to include in what will be committed) 395 | 396 | bechamel.md 397 | 398 | no changes added to commit (use "git add" and/or "git commit -a") 399 | ``` 400 | 401 | Git has noticed that the file `whitesauce.md` has disappeared from the 402 | file system and a new file `bechamel.md` has showed up. 403 | 404 | Add those changes to the staging area: 405 | 406 | ```bash 407 | $ git add whitesauce.md bechamel.md 408 | $ git status 409 | ``` 410 | 411 | ```output 412 | On branch main 413 | Changes to be committed: 414 | (use "git reset HEAD ..." to unstage) 415 | 416 | renamed: whitesauce.md -> bechamel.md 417 | 418 | ``` 419 | 420 | Notice how Git has now figured out that the `whitesauce.md` has not 421 | disappeared - it has simply been renamed. 422 | 423 | The final step, as before, is to commit our change to the repository: 424 | 425 | ```bash 426 | $ git commit -m 'Use the French name for the whitesauce' 427 | ``` 428 | 429 | ## Further .gitignore concepts 430 | 431 | For additional documentation on .gitignore, please reference 432 | [the official git documentation](https://git-scm.com/docs/gitignore). 433 | 434 | In the ignore exercise, learners were presented with two variations of ignoring 435 | nested files. Depending on the organization of your repository, one may suit 436 | your needs over another. Keep in mind that the way that Git travels along 437 | directory paths can be confusing. 438 | 439 | Sometimes the `**` pattern comes in handy, too, which matches multiple 440 | directory levels. E.g. `**/results/plots/*` would make git ignore the 441 | `results/plots` directory in any root directory. 442 | 443 | ::::::::::::::::::::::::::::::::::::::: challenge 444 | 445 | ## Ignoring Nested Files: Challenge Problem 446 | 447 | Given a directory structure that looks like: 448 | 449 | ```bash 450 | results/data 451 | results/plots 452 | results/run001.log 453 | results/run002.log 454 | ``` 455 | 456 | And a .gitignore that looks like: 457 | 458 | ```output 459 | *.csv 460 | ``` 461 | 462 | How would you track all of the contents of `results/data/`, including `*.csv` 463 | files, but ignore the rest of `results/`? 464 | 465 | ::::::::::::::: solution 466 | 467 | ## Solution 468 | 469 | To do this, your .gitignore would look like this: 470 | 471 | ```output 472 | *.csv # ignore the .csv files 473 | results/* # ignore the files in the results directory 474 | !results/data/ # do not ignore the files in results/data 475 | !results/data/* # do not ignore the .csv files in reults/data 476 | ``` 477 | 478 | ::::::::::::::::::::::::: 479 | 480 | :::::::::::::::::::::::::::::::::::::::::::::::::: 481 | 482 | 483 | -------------------------------------------------------------------------------- /learners/reference.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Git Cheatsheets for Quick Reference' 3 | --- 4 | 5 | ## Git Cheatsheets for Quick Reference 6 | 7 | - Printable Git cheatsheets in several languages are [available here](https://github.github.com/training-kit/) ([English version](https://github.github.com/training-kit/downloads/github-git-cheat-sheet.pdf)). More material is available from the [GitHub training website](https://try.github.io/). 8 | - An [interactive one-page visualisation](https://ndpsoftware.com/git-cheatsheet.html) 9 | about the relationships between workspace, staging area, local repository, upstream repository, and the commands associated with each (with explanations). 10 | - Both resources are also available in other languages (e.g. Spanish, French, and more). 11 | - "[Happy Git and GitHub for the useR](https://happygitwithr.com)" is an accessible, free online book by Jenny Bryan on how to setup and use Git and GitHub with specific references on the integration of Git with RStudio and working with Git in R. 12 | - [Open Scientific Code using Git and GitHub](https://open-source-for-researchers.github.io/open-source-workshop/) - A collection of explanations and short practical exercises to help researchers learn more about version control and open source software. 13 | 14 | ## Glossary 15 | 16 | [changeset]{#changeset} 17 | : A group of changes to one or more files that are or will be added 18 | to a single [commit](#commit) in a [version control](#version-control) 19 | [repository](#repository). 20 | 21 | [commit]{#commit} 22 | : To record the current state of a set of files (a [changeset](#changeset)) 23 | in a [version control](#version-control) [repository](#repository). As a noun, 24 | the result of committing, i.e. a recorded changeset in a repository. 25 | If a commit contains changes to multiple files, 26 | all of the changes are recorded together. 27 | 28 | [conflict]{#conflict} 29 | : A change made by one user of a [version control system](#version-control) 30 | that is incompatible with changes made by other users. 31 | Helping users [resolve](#resolve) conflicts 32 | is one of version control's major tasks. 33 | 34 | [HTTP]{#http} 35 | : The Hypertext Transfer [Protocol](#protocol) used for sharing web pages and other data 36 | on the World Wide Web. 37 | 38 | [merge]{#merge} 39 | : (a repository): To reconcile two sets of changes to a 40 | [repository](#repository). 41 | 42 | [protocol]{#protocol} 43 | : A set of rules that define how one computer communicates with another. 44 | Common protocols on the Internet include [HTTP](#http) and [SSH](#ssh). 45 | 46 | [remote]{#remote} 47 | : (of a repository) A version control [repository](#repository) connected to another, 48 | in such way that both can be kept in sync exchanging [commits](#commit). 49 | 50 | [repository]{#repository} 51 | : A storage area where a [version control](#version-control) system 52 | stores the full history of [commits](#commit) of a project and information 53 | about who changed what, when. 54 | 55 | [resolve]{#resolve} 56 | : To eliminate the [conflicts](#conflict) between two or more incompatible changes to a file or set of files 57 | being managed by a [version control](#version-control) system. 58 | 59 | [revision]{#revision} 60 | : A synonym for [commit](#commit). 61 | 62 | [SHA-1]{#sha-1} 63 | : [SHA-1 hashes](https://en.wikipedia.org/wiki/SHA-1) is what Git uses to compute identifiers, including for commits. 64 | To compute these, Git uses not only the actual change of a commit, but also its metadata (such as date, author, 65 | message), including the identifiers of all commits of preceding changes. This makes Git commit IDs virtually unique. 66 | I.e., the likelihood that two commits made independently, even of the same change, receive the same ID is exceedingly 67 | small. 68 | 69 | [SSH]{#ssh} 70 | : The Secure Shell [protocol](#protocol) used for secure communication between computers. 71 | 72 | [timestamp]{#timestamp} 73 | : A record of when a particular event occurred. 74 | 75 | [version control]{#version-control} 76 | : A tool for managing changes to a set of files. 77 | Each set of changes creates a new [commit](#commit) of the files; 78 | the version control system allows users to recover old commits reliably, 79 | and helps manage conflicting changes made by different users. 80 | 81 | 82 | -------------------------------------------------------------------------------- /learners/setup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Setup 3 | --- 4 | 5 | ## Installing Git 6 | 7 | Since several Carpentries lessons rely on Git, please see 8 | [this section of the workshop template][workshop-setup] for 9 | instructions on installing Git for various operating systems. 10 | 11 | - [Git installation on Windows][workshop-setup] 12 | - [Git installation on MacOS][workshop-setup] 13 | - [Git installation on Linux][workshop-setup] 14 | 15 | ## Creating a GitHub Account 16 | 17 | You will need an account for [GitHub](https://github.com) to follow episodes 7 & 8 in this lesson. 18 | 19 | 1. Go to and follow the "Sign up" link at the top-right of the window. 20 | 2. Follow the instructions to create an account. 21 | 3. Verify your email address with GitHub. 22 | 4. Configure multifactor authentication (see below). 23 | 24 | ### Multi-factor Authentication 25 | 26 | In 2023, GitHub introduced a requirement for 27 | all accounts to have 28 | [multi-factor authentication (2FA)](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/about-two-factor-authentication) 29 | configured for extra security. 30 | Several options exist for setting up 2FA, which are summarised here: 31 | 32 | 1. If you already use an authenticator app, 33 | like [Google Authenticator](https://support.google.com/accounts/answer/1066447?hl=en&co=GENIE.Platform%3DiOS&oco=0) 34 | or [Duo Mobile](https://duo.com/product/multi-factor-authentication-mfa/duo-mobile-app) on your smartphone for example, 35 | [add GitHub to that app](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication#configuring-two-factor-authentication-using-a-totp-mobile-app). 36 | 2. If you have access to a smartphone but do not already use an authenticator app, install one and 37 | [add GitHub to the app](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication#configuring-two-factor-authentication-using-a-totp-mobile-app). 38 | 3. If you do not have access to a smartphone or do not want to install an authenticator app, you have two options: 39 | 1. [set up 2FA via text message](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication#configuring-two-factor-authentication-using-text-messages) 40 | ([list of countries where authentication by SMS is supported](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/countries-where-sms-authentication-is-supported)), or 41 | 2. [use a hardware security key](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication#configuring-two-factor-authentication-using-a-security-key) 42 | like [YubiKey](https://www.yubico.com/products/yubikey-5-overview/) 43 | or the [Google Titan key](https://store.google.com/us/product/titan_security_key?hl=en-US&pli=1). 44 | 45 | The GitHub documentation provides [more details about configuring 2FA](https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa/configuring-two-factor-authentication). 46 | 47 | ---------------- 48 | 49 | ## Preparing Your Working Directory 50 | 51 | We'll do our work in the `Desktop` folder so make sure you change your working directory to it with: 52 | 53 | ```bash 54 | $ cd 55 | $ cd Desktop 56 | ``` 57 | 58 | [workshop-setup]: https://carpentries.github.io/workshop-template/install_instructions/#git 59 | 60 | -------------------------------------------------------------------------------- /profiles/learner-profiles.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: FIXME 3 | --- 4 | 5 | This is a placeholder file. Please add content here. 6 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | PyYAML 2 | update-copyright 3 | -------------------------------------------------------------------------------- /site/README.md: -------------------------------------------------------------------------------- 1 | This directory contains rendered lesson materials. Please do not edit files 2 | here. 3 | --------------------------------------------------------------------------------