├── .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 | 
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 | [](https://slack-invite.carpentries.org/)
2 | [](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 | {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 | {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 | {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 | {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 | {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 | {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 | {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 | {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 | {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 | {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 | {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 | {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 | {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 | {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 | {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 | {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 |
--------------------------------------------------------------------------------
/episodes/fig/git-freshly-made-github-repo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/episodes/fig/git-restore.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
112 |
--------------------------------------------------------------------------------
/episodes/fig/git-staging-area.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
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 |
--------------------------------------------------------------------------------
/episodes/fig/phd101212s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swcarpentry/git-novice/560e602e72c983d2416ec45e7b0743a170ff1e63/episodes/fig/phd101212s.png
--------------------------------------------------------------------------------
/episodes/fig/play-changes.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
176 |
--------------------------------------------------------------------------------
/episodes/fig/versions.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 |
--------------------------------------------------------------------------------