10 |
--------------------------------------------------------------------------------
/bin/knit_lessons.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Only try running R to translate files if there are some files present.
4 | # The Makefile passes in the names of files.
5 |
6 | if [ $# -ne 0 ] ; then
7 | Rscript -e "source('bin/generate_md_episodes.R')"
8 | fi
9 |
--------------------------------------------------------------------------------
/_includes/dc/who.html:
--------------------------------------------------------------------------------
1 |
2 | Who:
3 | The course is aimed at graduate students and other researchers.
4 |
5 | You don't need to have any previous knowledge of the tools
6 | that will be presented at the workshop.
7 |
8 |
2 | Who:
3 | The course is aimed at graduate students and other researchers.
4 |
5 | You don't need to have any previous knowledge of the tools
6 | that will be presented at the workshop.
7 |
8 |
2 | Who:
3 | The course is for librarians, archivists, and other information workers.
4 |
5 | You don't need to have any previous knowledge of the tools that
6 | will be presented at the workshop.
7 |
8 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | git-novice
2 | ==========
3 |
4 | An introduction to version control for novices using Git.
5 | Please see for a rendered version of this material,
6 | [the lesson template documentation][lesson-example]
7 | for instructions on formatting, building, and submitting material,
8 | or run `make` in this directory for a list of helpful commands.
9 |
10 | Maintainers:
11 |
12 | * [Ivan Gonzalez][gonzalez_ivan]
13 | * [Daisie Huang][huang_daisie]
14 |
15 | [gonzalez_ivan]: http://software-carpentry.org/team/#gonzalez_ivan
16 | [huang_daisie]: http://software-carpentry.org/team/#huang_daisie
17 | [lesson-example]: https://swcarpentry.github.io/lesson-example
18 |
--------------------------------------------------------------------------------
/bin/test_lesson_check.py:
--------------------------------------------------------------------------------
1 | import unittest
2 |
3 | import lesson_check
4 | import util
5 |
6 | class TestFileList(unittest.TestCase):
7 | def setUp(self):
8 | self.reporter = util.Reporter() ## TODO: refactor reporter class.
9 |
10 | def test_file_list_has_expected_entries(self):
11 | # For first pass, simply assume that all required files are present
12 | all_filenames = [filename.replace('%', '')
13 | for filename in lesson_check.REQUIRED_FILES]
14 |
15 | lesson_check.check_fileset('', self.reporter, all_filenames)
16 | self.assertEqual(len(self.reporter.messages), 0)
17 |
18 | if __name__ == "__main__":
19 | unittest.main()
20 |
--------------------------------------------------------------------------------
/_includes/workshop_footer.html:
--------------------------------------------------------------------------------
1 | {% comment %}
2 | Footer for a standard workshop.
3 | {% endcomment %}
4 |
25 |
--------------------------------------------------------------------------------
/_includes/javascript.html:
--------------------------------------------------------------------------------
1 | {% comment %}
2 | Javascript used in lesson and workshop pages.
3 | {% endcomment %}
4 |
5 |
6 |
7 |
15 |
--------------------------------------------------------------------------------
/_includes/dc/intro.html:
--------------------------------------------------------------------------------
1 |
2 | Data Carpentry
3 | aims to help researchers get their work done
4 | in less time and with less pain
5 | by teaching them basic research computing skills.
6 | This hands-on workshop will cover basic concepts and tools,
7 | including program design, version control, data management,
8 | and task automation.
9 | Participants will be encouraged to help one another
10 | and to apply what they have learned to their own research problems.
11 |
2 | Software Carpentry
3 | aims to help researchers get their work done
4 | in less time and with less pain
5 | by teaching them basic research computing skills.
6 | This hands-on workshop will cover basic concepts and tools,
7 | including program design, version control, data management,
8 | and task automation.
9 | Participants will be encouraged to help one another
10 | and to apply what they have learned to their own research problems.
11 |
19 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Please delete the text below before submitting your contribution.
2 |
3 | ---
4 |
5 | Thanks for contributing! If this contribution is for instructor training, please send an email to checkout@carpentries.org with a link to this contribution so we can record your progress. You’ve completed your contribution step for instructor checkout just by submitting this contribution.
6 |
7 | Please keep in mind that lesson maintainers are volunteers and it may be some time before they can respond to your contribution. Although not all contributions can be incorporated into the lesson materials, we appreciate your time and effort to improve the curriculum. If you have any questions about the lesson maintenance process or would like to volunteer your time as a contribution reviewer, please contact Kate Hertweck (k8hertweck@gmail.com).
8 |
9 | ---
10 |
--------------------------------------------------------------------------------
/_includes/lc/intro.html:
--------------------------------------------------------------------------------
1 |
2 | Library Carpentry
3 | is made by librarians, for librarians to help you:
4 |
5 |
6 |
automate repetitive, boring, error-prone tasks
7 |
create, maintain and analyse sustainable and reusable data
8 |
work effectively with IT and systems colleagues
9 |
better understand the use of software in research
10 |
and much more...
11 |
12 |
13 |
14 | Library Carpentry introduces you to the fundamentals of computing
15 | and provides you with a platform for further self-directed learning.
16 | For more information on what we teach and why, please see our paper
17 | "Library Carpentry: software skills training for library professionals".
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Please delete the text below before submitting your contribution.
2 |
3 | ---
4 |
5 | Thanks for contributing! If this contribution is for instructor training, please send an email to checkout@carpentries.org with a link to this contribution so we can record your progress. You’ve completed your contribution step for instructor checkout just by submitting this contribution.
6 |
7 | Please keep in mind that lesson maintainers are volunteers and it may be some time before they can respond to your contribution. Although not all contributions can be incorporated into the lesson materials, we appreciate your time and effort to improve the curriculum. If you have any questions about the lesson maintenance process or would like to volunteer your time as a contribution reviewer, please contact Kate Hertweck (k8hertweck@gmail.com).
8 |
9 | ---
10 |
--------------------------------------------------------------------------------
/_includes/episode_overview.html:
--------------------------------------------------------------------------------
1 | {% comment %}
2 | Display an episode's timings and learning objectives.
3 | {% endcomment %}
4 |
5 |
Overview
6 |
7 |
8 |
9 | Teaching: {{ page.teaching }} min
10 |
11 | Exercises: {{ page.exercises }} min
12 |
13 |
14 | Questions
15 |
16 | {% for question in page.questions %}
17 |
{{ question|markdownify }}
18 | {% endfor %}
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | Objectives
28 |
29 | {% for objective in page.objectives %}
30 |
{{ objective|markdownify }}
31 | {% endfor %}
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/_includes/workshop_ad.html:
--------------------------------------------------------------------------------
1 | {% comment %}
2 | Advertising box at the top of a workshop website home page.
3 | {% endcomment %}
4 |
5 |
6 |
7 |
{{page.venue}}
8 |
9 |
10 |
{{page.humandate}}
11 |
{% if page.humantime %}{{page.humantime}}{% endif %}
40 | {% include javascript.html %}
41 |
42 |
43 |
--------------------------------------------------------------------------------
/_includes/carpentries.html:
--------------------------------------------------------------------------------
1 | {% comment %}
2 | General description of Software and Data Carpentry.
3 | {% endcomment %}
4 |
5 |
6 |
7 |
8 |
9 | Since 1998,
10 | Software Carpentry
11 | has been teaching researchers in science, engineering, medicine, and related disciplines
12 | the computing skills they need to get more done in less time and with less pain.
13 | Its volunteer instructors have run hundreds of events
14 | for thousands of learners in the past two and a half years.
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | Data Carpentry develops and teaches workshops on the fundamental data skills needed to conduct research.
24 | Its target audience is researchers who have little to no prior computational experience,
25 | and its lessons are domain specific,
26 | building on learners' existing knowledge to enable them to quickly apply skills learned to their own research.
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | Library Carpentry is made by librarians to help librarians
36 | automate repetitive, boring, error-prone tasks;
37 | create, maintain and analyse sustainable and reusable data;
38 | work effectively with IT and systems colleagues;
39 | better understand the use of software in research;
40 | and much more.
41 | Library Carpentry was the winner of the 2016
42 | British Library Labs Teaching and Learning Award.
43 |
44 |
45 |
--------------------------------------------------------------------------------
/bin/chunk-options.R:
--------------------------------------------------------------------------------
1 | # These settings control the behavior of all chunks in the novice R materials.
2 | # For example, to generate the lessons with all the output hidden, simply change
3 | # `results` from "markup" to "hide".
4 | # For more information on available chunk options, see
5 | # http://yihui.name/knitr/options#chunk_options
6 |
7 | library("knitr")
8 |
9 | fix_fig_path <- function(pth) file.path("..", pth)
10 |
11 |
12 | ## We set the path for the figures globally below, so if we want to
13 | ## customize it for individual episodes, we can append a prefix to the
14 | ## global path. For instance, if we call knitr_fig_path("01-") in the
15 | ## first episode of the lesson, it will generate the figures in
16 | ## `fig/rmd-01-`
17 | knitr_fig_path <- function(prefix) {
18 | new_path <- paste0(opts_chunk$get("fig.path"),
19 | prefix)
20 | opts_chunk$set(fig.path = new_path)
21 | }
22 |
23 | ## We use the rmd- prefix for the figures generated by the lssons so
24 | ## they can be easily identified and deleted by `make clean-rmd`. The
25 | ## working directory when the lessons are generated is the root so the
26 | ## figures need to be saved in fig/, but when the site is generated,
27 | ## the episodes will be one level down. We fix the path using the
28 | ## `fig.process` option.
29 |
30 | opts_chunk$set(tidy = FALSE, results = "markup", comment = NA,
31 | fig.align = "center", fig.path = "fig/rmd-",
32 | fig.process = fix_fig_path)
33 |
34 | # The hooks below add html tags to the code chunks and their output so that they
35 | # are properly formatted when the site is built.
36 |
37 | hook_in <- function(x, options) {
38 | stringr::str_c("\n\n~~~\n",
39 | paste0(x, collapse="\n"),
40 | "\n~~~\n{: .r}\n\n")
41 | }
42 |
43 | hook_out <- function(x, options) {
44 | x <- gsub("\n$", "", x)
45 | stringr::str_c("\n\n~~~\n",
46 | paste0(x, collapse="\n"),
47 | "\n~~~\n{: .output}\n\n")
48 | }
49 |
50 | hook_error <- function(x, options) {
51 | x <- gsub("\n$", "", x)
52 | stringr::str_c("\n\n~~~\n",
53 | paste0(x, collapse="\n"),
54 | "\n~~~\n{: .error}\n\n")
55 | }
56 |
57 | knit_hooks$set(source = hook_in, output = hook_out, warning = hook_error,
58 | error = hook_error, message = hook_out)
59 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | #------------------------------------------------------------
2 | # Values for this lesson.
3 | #------------------------------------------------------------
4 |
5 | # Which carpentry is this ("swc" or "dc")?
6 | carpentry: "swc"
7 |
8 | # Overall title for pages.
9 | title: "Version Control with Git"
10 |
11 | # Contact email address.
12 | email: lessons@software-carpentry.org
13 |
14 | #------------------------------------------------------------
15 | # Generic settings (should not need to change).
16 | #------------------------------------------------------------
17 |
18 | # What kind of thing is this ("workshop" or "lesson")?
19 | kind: "lesson"
20 |
21 | # Magic to make URLs resolve both locally and on GitHub.
22 | # See https://help.github.com/articles/repository-metadata-on-github-pages/.
23 | repository: /
24 |
25 | # Sites.
26 | amy_site: "https://amy.software-carpentry.org/workshops"
27 | dc_site: "http://datacarpentry.org"
28 | swc_github: "https://github.com/swcarpentry"
29 | swc_site: "https://software-carpentry.org"
30 | swc_pages: "https://swcarpentry.github.io"
31 | template_repo: "https://github.com/swcarpentry/styles"
32 | example_repo: "https://github.com/swcarpentry/lesson-example"
33 | example_site: "https://swcarpentry.github.com/lesson-example"
34 | workshop_repo: "https://github.com/swcarpentry/workshop-template"
35 | workshop_site: "https://swcarpentry.github.io/workshop-template"
36 | training_site: "https://swcarpentry.github.io/instructor-training"
37 |
38 | # Surveys.
39 | pre_survey: "https://www.surveymonkey.com/r/swc_pre_workshop_v1?workshop_id="
40 | post_survey: "https://www.surveymonkey.com/r/swc_post_workshop_v1?workshop_id="
41 |
42 | # Start time in minutes (0 to be clock-independent, 540 to show a start at 09:00 am)
43 | start_time: 0
44 |
45 | # Specify that things in the episodes collection should be output.
46 | collections:
47 | episodes:
48 | output: true
49 | permalink: /:path/
50 | extras:
51 | output: true
52 |
53 | # Set the default layout for things in the episodes collection.
54 | defaults:
55 | - values:
56 | root: ..
57 | - scope:
58 | path: ""
59 | type: episodes
60 | values:
61 | layout: episode
62 |
63 | # Files and directories that are not to be copied.
64 | exclude:
65 | - Makefile
66 | - bin
67 |
68 | # Turn off built-in syntax highlighting.
69 | highlighter: false
70 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: lesson
3 | root: .
4 | ---
5 |
6 | Wolfman and Dracula have been hired by Universal Missions (a space
7 | services spinoff from Euphoric State University) to investigate if it
8 | is possible to send their next planetary lander to Mars. They want to
9 | be able to work on the plans 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]({{ page.root }}/reference/#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 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 | > ## Prerequisites
48 | >
49 | > In this lesson we use Git from the Unix Shell.
50 | > Some previous experience with the shell is expected,
51 | > *but isn't mandatory*.
52 | {: .prereq}
53 |
--------------------------------------------------------------------------------
/_includes/lc/syllabys.html:
--------------------------------------------------------------------------------
1 |
23 | {% for episode in site.episodes %}
24 | {% if episode.start %} {% comment %} Starting a new day? {% endcomment %}
25 | {% assign day = day | plus: 1 %}
26 | {% if day > 1 %} {% comment %} If about to start day 2 or later, show finishing time for previous day {% endcomment %}
27 | {% assign hours = current | divided_by: 60 %}
28 | {% assign minutes = current | modulo: 60 %}
29 |
30 | {% if multiday %}
{% endif %}
31 |
{% if hours < 10 %}0{% endif %}{{ hours }}:{% if minutes < 10 %}0{% endif %}{{ minutes }}
32 |
Finish
33 |
34 |
35 | {% endif %}
36 | {% assign current = site.start_time %} {% comment %}Re-set start time of this episode to general daily start time {% endcomment %}
37 | {% endif %}
38 | {% assign hours = current | divided_by: 60 %}
39 | {% assign minutes = current | modulo: 60 %}
40 |
41 | {% if multiday %}
{% if episode.start %}Day {{ day }}{% endif %}
{% endif %}
42 |
{% if hours < 10 %}0{% endif %}{{ hours }}:{% if minutes < 10 %}0{% endif %}{{ minutes }}
{% if hours < 10 %}0{% endif %}{{ hours }}:{% if minutes < 10 %}0{% endif %}{{ minutes }}
69 |
Finish
70 |
71 |
72 |
73 |
74 |
75 | The actual schedule may vary slightly depending on the topics and exercises chosen by the instructor.
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/reference.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: reference
3 | permalink: /reference/
4 | ---
5 |
6 | ## Git Cheatsheets for Quick Reference
7 |
8 | * A great [printable git cheatsheet](https://services.github.com/on-demand/downloads/github-git-cheat-sheet.pdf) is available in PDF from the
9 | [GitHub training website](https://services.github.com/resources/).
10 | * An [interactive one-page visualisation](http://ndpsoftware.com/git-cheatsheet.html)
11 | about the relationships between workspace, staging area, local repository, upstream repository, and the commands associated with each (with explanations).
12 | * Both resources are also available in other languages e.g. Spanish, French, and more
13 |
14 | ## Glossary
15 |
16 | {:auto_ids}
17 | changeset
18 | : A group of changes to one or more files that are or will be added
19 | to a single [commit](#commit) in a [version control](#version-control)
20 | [repository](#repository).
21 |
22 | commit
23 | : To record the current state of a set of files (a [changeset](#changeset))
24 | in a [version control](#version-control) [repository](#repository). As a noun,
25 | the result of committing, i.e. a recorded changeset in a repository.
26 | If a commit contains changes to multiple files,
27 | all of the changes are recorded together.
28 |
29 | conflict
30 | : A change made by one user of a [version control system](#version-control)
31 | that is incompatible with changes made by other users.
32 | Helping users [resolve](#resolve) conflicts
33 | is one of version control's major tasks.
34 |
35 | HTTP
36 | : The Hypertext Transfer [Protocol](#protocol) used for sharing web pages and other data
37 | on the World Wide Web.
38 |
39 | merge
40 | : (a repository): To reconcile two sets of changes to a
41 | [repository](#repository).
42 |
43 | protocol
44 | : A set of rules that define how one computer communicates with another.
45 | Common protocols on the Internet include [HTTP](#http) and [SSH](#ssh).
46 |
47 | remote
48 | : (of a repository) A version control [repository](#repository) connected to another,
49 | in such way that both can be kept in sync exchanging [commits](#commit).
50 |
51 | repository
52 | : A storage area where a [version control](#version-control) system
53 | stores the full history of [commits](#commit) of a project and information
54 | about who changed what, when.
55 |
56 | resolve
57 | : To eliminate the [conflicts](#conflict) between two or more incompatible changes to a file or set of files
58 | being managed by a [version control](#version-control) system.
59 |
60 | revision
61 | : A synonym for [commit](#commit).
62 |
63 | SHA-1
64 | : [SHA-1 hashes](http://en.wikipedia.org/wiki/SHA-1) is what Git uses to compute identifiers, including for commits.
65 | To compute these, Git uses not only the actual change of a commit, but also its metadata (such as date, author,
66 | message), including the identifiers of all commits of preceding changes. This makes Git commit IDs virtually unique.
67 | I.e., the likelihood that two commits made independently, even of the same change, receive the same ID is exceedingly
68 | small.
69 |
70 | SSH
71 | : The Secure Shell [protocol](#protocol) used for secure communication between computers.
72 |
73 | timestamp
74 | : A record of when a particular event occurred.
75 |
76 | version control
77 | : A tool for managing changes to a set of files.
78 | Each set of changes creates a new [commit](#commit) of the files;
79 | the version control system allows users to recover old commits reliably,
80 | and helps manage conflicting changes made by different users.
81 |
--------------------------------------------------------------------------------
/_includes/dc/syllabus.html:
--------------------------------------------------------------------------------
1 |
97 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | ## ========================================
2 | ## Commands for both workshop and lesson websites.
3 |
4 | # Settings
5 | MAKEFILES=Makefile $(wildcard *.mk)
6 | JEKYLL=jekyll
7 | PARSER=bin/markdown_ast.rb
8 | DST=_site
9 |
10 | # Controls
11 | .PHONY : commands clean files
12 | .NOTPARALLEL:
13 | all : commands
14 |
15 | ## commands : show all commands.
16 | commands :
17 | @grep -h -E '^##' ${MAKEFILES} | sed -e 's/## //g'
18 |
19 | ## serve : run a local server.
20 | serve : lesson-md
21 | ${JEKYLL} serve
22 |
23 | ## site : build files but do not run a server.
24 | site : lesson-md
25 | ${JEKYLL} build
26 |
27 | # repo-check : check repository settings.
28 | repo-check :
29 | @bin/repo_check.py -s .
30 |
31 | ## clean : clean up junk files.
32 | clean :
33 | @rm -rf ${DST}
34 | @rm -rf .sass-cache
35 | @rm -rf bin/__pycache__
36 | @find . -name .DS_Store -exec rm {} \;
37 | @find . -name '*~' -exec rm {} \;
38 | @find . -name '*.pyc' -exec rm {} \;
39 |
40 | ## clean-rmd : clean intermediate R files (that need to be committed to the repo).
41 | clear-rmd :
42 | @rm -rf ${RMD_DST}
43 | @rm -rf fig/rmd-*
44 |
45 | ## ----------------------------------------
46 | ## Commands specific to workshop websites.
47 |
48 | .PHONY : workshop-check
49 |
50 | ## workshop-check : check workshop homepage.
51 | workshop-check :
52 | @bin/workshop_check.py .
53 |
54 | ## ----------------------------------------
55 | ## Commands specific to lesson websites.
56 |
57 | .PHONY : lesson-check lesson-md lesson-files lesson-fixme
58 |
59 | # RMarkdown files
60 | RMD_SRC = $(wildcard _episodes_rmd/??-*.Rmd)
61 | RMD_DST = $(patsubst _episodes_rmd/%.Rmd,_episodes/%.md,$(RMD_SRC))
62 |
63 | # Lesson source files in the order they appear in the navigation menu.
64 | MARKDOWN_SRC = \
65 | index.md \
66 | CONDUCT.md \
67 | setup.md \
68 | $(wildcard _episodes/*.md) \
69 | reference.md \
70 | $(wildcard _extras/*.md) \
71 | LICENSE.md
72 |
73 | # Generated lesson files in the order they appear in the navigation menu.
74 | HTML_DST = \
75 | ${DST}/index.html \
76 | ${DST}/conduct/index.html \
77 | ${DST}/setup/index.html \
78 | $(patsubst _episodes/%.md,${DST}/%/index.html,$(wildcard _episodes/*.md)) \
79 | ${DST}/reference/index.html \
80 | $(patsubst _extras/%.md,${DST}/%/index.html,$(wildcard _extras/*.md)) \
81 | ${DST}/license/index.html
82 |
83 | ## lesson-md : convert Rmarkdown files to markdown
84 | lesson-md : ${RMD_DST}
85 |
86 | # Use of .NOTPARALLEL makes rule execute only once
87 | ${RMD_DST} : ${RMD_SRC}
88 | @bin/knit_lessons.sh ${RMD_SRC}
89 |
90 | ## lesson-check : validate lesson Markdown.
91 | lesson-check :
92 | @bin/lesson_check.py -s . -p ${PARSER} -r _includes/links.md
93 |
94 | ## lesson-check-all : validate lesson Markdown, checking line lengths and trailing whitespace.
95 | lesson-check-all :
96 | @bin/lesson_check.py -s . -p ${PARSER} -l -w
97 |
98 | ## lesson-figures : re-generate inclusion displaying all figures.
99 | lesson-figures :
100 | @bin/extract_figures.py -p ${PARSER} ${MARKDOWN_SRC} > _includes/all_figures.html
101 |
102 | ## unittest : run unit tests on checking tools.
103 | unittest :
104 | python bin/test_lesson_check.py
105 |
106 | ## lesson-files : show expected names of generated files for debugging.
107 | lesson-files :
108 | @echo 'RMD_SRC:' ${RMD_SRC}
109 | @echo 'RMD_DST:' ${RMD_DST}
110 | @echo 'MARKDOWN_SRC:' ${MARKDOWN_SRC}
111 | @echo 'HTML_DST:' ${HTML_DST}
112 |
113 | ## lesson-fixme : show FIXME markers embedded in source files.
114 | lesson-fixme :
115 | @fgrep -i -n FIXME ${MARKDOWN_SRC} || true
116 |
117 | #-------------------------------------------------------------------------------
118 | # Include extra commands if available.
119 | #-------------------------------------------------------------------------------
120 |
121 | -include commands.mk
122 |
--------------------------------------------------------------------------------
/_episodes/01-basics.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Automated Version Control
3 | teaching: 5
4 | exercises: 0
5 | questions:
6 | - "What is version control and why should I use it?"
7 | objectives:
8 | - "Understand the benefits of an automated version control system."
9 | - "Understand the basics of how Git works."
10 | keypoints:
11 | - "Version control is like an unlimited 'undo'."
12 | - "Version control also allows many people to work in parallel."
13 | ---
14 |
15 | We'll start by exploring how version control can be used
16 | to keep track of what one person did and when.
17 | Even if you aren't collaborating with other people,
18 | automated version control is much better than this situation:
19 |
20 | [](http://www.phdcomics.com)
21 |
22 | "Piled Higher and Deeper" by Jorge Cham, http://www.phdcomics.com
23 |
24 | We've all been in this situation before: it seems ridiculous to have
25 | multiple nearly-identical versions of the same document. Some word
26 | processors let us deal with this a little better, such as Microsoft
27 | Word's [Track Changes](https://support.office.com/en-us/article/Track-changes-in-Word-197ba630-0f5f-4a8e-9a77-3712475e806a), Google Docs' [version
28 | history](https://support.google.com/docs/answer/190843?hl=en), or LibreOffice's [Recording and Displaying Changes](https://help.libreoffice.org/Common/Recording_and_Displaying_Changes).
29 |
30 | Version control systems start with a base version of the document and
31 | then save just the changes you made at each step of the way. You can
32 | think of it as a tape: if you rewind the tape and start at the base
33 | document, then you can play back each change and end up with your
34 | latest version.
35 |
36 | 
37 |
38 | Once you think of changes as separate from the document itself, you
39 | can then think about "playing back" different sets of changes onto the
40 | base document and getting different versions of the document. For
41 | example, two users can make independent sets of changes based on the
42 | same document.
43 |
44 | 
45 |
46 | Unless there are conflicts, you can even play two sets of changes onto the same base document.
47 |
48 | 
49 |
50 | A version control system is a tool that keeps track of these changes for us and
51 | helps us version and merge our files. It allows you to
52 | decide which changes make up the next version, called a
53 | [commit]({{ page.root }}/reference/#commit), and keeps useful metadata about them. The
54 | complete history of commits for a particular project and their metadata make up
55 | a [repository]({{ page.root }}/reference/#repository). Repositories can be kept in sync
56 | across different computers facilitating collaboration among different people.
57 |
58 | > ## The Long History of Version Control Systems
59 | >
60 | > Automated version control systems are nothing new.
61 | > Tools like RCS, CVS, or Subversion have been around since the early 1980s and are used by many large companies.
62 | > However, many of these are now becoming considered as legacy systems due to various limitations in their capabilities.
63 | > In particular, the more modern systems, such as Git and [Mercurial](http://swcarpentry.github.io/hg-novice/)
64 | > are *distributed*, meaning that they do not need a centralized server to host the repository.
65 | > These modern systems also include powerful merging tools that make it possible for multiple authors to work within
66 | > the same files concurrently.
67 | {: .callout}
68 |
69 | > ## Paper Writing
70 | >
71 | > * Imagine you drafted an excellent paragraph for a paper you are writing, but later ruin it. How would you retrieve
72 | > the *excellent* version of your conclusion? Is it even possible?
73 | >
74 | > * Imagine you have 5 co-authors. How would you manage the changes and comments they make to your paper?
75 | > If you use LibreOffice Writer or Microsoft Word, what happens if you accept changes made using the
76 | > `Track Changes` option? Do you have a history of those changes?
77 | {: .challenge}
78 |
--------------------------------------------------------------------------------
/_episodes/11-licensing.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Licensing
3 | teaching: 5
4 | exercises: 0
5 | questions:
6 | - "What licensing information should I include with my work?"
7 | objectives:
8 | - "Explain why adding licensing information to a repository is important."
9 | - "Choose a proper license."
10 | - "Explain differences in licensing and social expectations."
11 | keypoints:
12 | - "People who incorporate GPL'd software into their own software must make their software also open under the GPL license; most other open licenses do not require this."
13 | - "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."
14 | - "People who are not lawyers should not try to write licenses from scratch."
15 | ---
16 |
17 | When a repository with source code, a manuscript or other creative
18 | works becomes public, it should include a file `LICENSE` or
19 | `LICENSE.txt` in the base directory of the repository that clearly
20 | states under which license the content is being made available. This
21 | is because creative works are automatically eligible for intellectual
22 | property (and thus copyright) protection. Reusing creative works
23 | without a license is dangerous, because the copyright holders could
24 | sue you for copyright infringement.
25 |
26 | A license solves this problem by granting rights to others (the
27 | licensees) that they would otherwise not have. What rights are being
28 | granted under which conditions differs, often only slightly, from one
29 | license to another. In practice, a few licenses are by far the most
30 | popular, and [choosealicense.com](http://choosealicense.com/) will
31 | help you find a common license that suits your needs. Important
32 | considerations include:
33 |
34 | * Whether you want to address patent rights.
35 | * Whether you require people distributing derivative works to also
36 | distribute their source code.
37 | * Whether the content you are licensing is source code.
38 | * Whether you want to license the code at all.
39 |
40 | Choosing a license that is in common use makes life easier for
41 | contributors and users, because they are more likely to already be
42 | familiar with the license and don't have to wade through a bunch of
43 | jargon to decide if they're ok with it. The [Open Source
44 | Initiative](http://opensource.org/licenses) and [Free Software
45 | Foundation](http://www.gnu.org/licenses/license-list.html) both
46 | maintain lists of licenses which are good choices.
47 |
48 | [This article][software-licensing] provides an excellent overview of
49 | licensing and licensing options from the perspective of scientists who
50 | also write code.
51 |
52 | At the end of the day what matters is that there is a clear statement
53 | as to what the license is. Also, the license is best chosen from the
54 | get-go, even if for a repository that is not public. Pushing off the
55 | decision only makes it more complicated later, because each time a new
56 | collaborator starts contributing, they, too, hold copyright and will
57 | thus need to be asked for approval once a license is chosen.
58 |
59 | > ## Can I Use Open License?
60 | >
61 | > Find out whether you are allowed to apply an open license to your software.
62 | > Can you do this unilaterally,
63 | > or do you need permission from someone in your institution?
64 | > If so, who?
65 | {: .challenge}
66 |
67 | > ## What licenses have I already accepted?
68 | >
69 | > Many of the software tools we use on a daily basis (including in this workshop) are
70 | > released as open-source software. Pick a project on GitHub from the list below, or
71 | > one of your own choosing. Find its license (usually in a file called `LICENSE` or
72 | > `COPYING`) and talk about how it restricts your use of the software. Is it one of
73 | > the licenses discussed in this session? How is it different?
74 | > - [Git](https://github.com/git/git), the source-code management tool
75 | > - [CPython](https://github.com/python/cpython), the standard implementation of the Python language
76 | > - [Jupyter](https://github.com/jupyter), the project behind the web-based Python notebooks we'll be using
77 | > - [EtherPad](https://github.com/ether/etherpad-lite), a real-time collaborative editor
78 | {: .challenge}
79 |
80 | [software-licensing]: http://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1002598
81 |
--------------------------------------------------------------------------------
/_includes/navbar.html:
--------------------------------------------------------------------------------
1 | {% comment %}
2 | Lesson navigation bar.
3 | {% endcomment %}
4 |
85 |
--------------------------------------------------------------------------------
/_episodes/13-hosting.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Hosting
3 | teaching: 10
4 | exercises: 0
5 | questions:
6 | - "Where should I host my version control repositories?"
7 | objectives:
8 | - "Explain different options for hosting scientific work."
9 | keypoints:
10 | - "Projects can be hosted on university servers, on personal domains, or on public forges."
11 | - "Rules regarding intellectual property and storage of sensitive information apply no matter where code and data are hosted."
12 | ---
13 |
14 | The second big question for groups that want to open up their work is where to
15 | host their code and data. One option is for the lab, the department, or the
16 | university to provide a server, manage accounts and backups, and so on. The
17 | main benefit of this is that it clarifies who owns what, which is particularly
18 | important if any of the material is sensitive (i.e., relates to experiments
19 | involving human subjects or may be used in a patent application). The main
20 | drawbacks are the cost of providing the service and its longevity: a scientist
21 | who has spent ten years collecting data would like to be sure that data will
22 | still be available ten years from now, but that's well beyond the lifespan of
23 | most of the grants that fund academic infrastructure.
24 |
25 | Another option is to purchase a domain and pay an Internet service provider
26 | (ISP) to host it. This gives the individual or group more control, and
27 | sidesteps problems that can arise when moving from one institution to another,
28 | but requires more time and effort to set up than either the option above or the
29 | option below.
30 |
31 | The third option is to use a public hosting service like
32 | [GitHub](http://github.com), [GitLab](http://gitlab.com),
33 | [BitBucket](http://bitbucket.org), or [SourceForge](http://sourceforge.net).
34 | Each of these services provides a web interface that enables people to create,
35 | view, and edit their code repositories. These services also provide
36 | communication and project management tools including issue tracking, wiki pages,
37 | email notifications, and code reviews. These services benefit from economies of
38 | scale and network effects: it's easier to run one large service well than to run
39 | many smaller services to the same standard. It's also easier for people to
40 | collaborate. Using a popular service can help connect your project with
41 | communities already using the same service.
42 |
43 | As an example, Software Carpentry [is on
44 | GitHub]({{ swc_github }}) where you can find the [source for this
45 | page]({{page.root}}/_episodes/13-hosting.md).
46 | Anyone with a GitHub account can suggest changes to this text.
47 |
48 | Using large, well-established services can also help you quickly take advantage
49 | of powerful tools. One such tool, continuous integration (CI), can
50 | automatically run software builds and tests whenever code is committed or pull
51 | requests are submitted. Direct integration of CI with an online hosting service
52 | means this information is present in any pull request, and helps maintain code
53 | integrity and quality standards. While CI is still available in self-hosted
54 | situations, there is much less setup and maintenance involved with using an
55 | online service. Furthermore, such tools are often provided free of charge to
56 | open source projects, and are also available for private repositories for a fee.
57 |
58 | > ## Institutional Barriers
59 | >
60 | > Sharing is the ideal for science,
61 | > but many institutions place restrictions on sharing,
62 | > for example to protect potentially patentable intellectual property.
63 | > If you encounter such restrictions,
64 | > it can be productive to inquire about the underlying motivations
65 | > either to request an exception for a specific project or domain,
66 | > or to push more broadly for institutional reform to support more open science.
67 | {: .callout}
68 |
69 | > ## Can My Work Be Public?
70 | >
71 | > Find out whether you are allowed to host your work openly on a public forge.
72 | > Can you do this unilaterally,
73 | > or do you need permission from someone in your institution?
74 | > If so, who?
75 | {: .challenge}
76 |
77 | > ## Where Can I Share My Work?
78 | >
79 | > Does your institution have a repository or repositories that you can
80 | > use to share your papers, data and software? How do institutional repositories
81 | > differ from services like [arXiV](http://arxiv.org/), [figshare](http://figshare.com/) and [GitHub](http://github.com/)?
82 | {: .challenge}
83 |
--------------------------------------------------------------------------------
/assets/css/lesson.scss:
--------------------------------------------------------------------------------
1 | ---
2 | ---
3 |
4 | //----------------------------------------
5 | // Colors.
6 | //----------------------------------------
7 |
8 | // branding
9 | $color-brand: #2b3990 !default;
10 |
11 | // code boxes
12 | $color-error: #bd2c00 !default;
13 | $color-output: #303030 !default;
14 | $color-source: #6e5494 !default;
15 |
16 | // blockquotes
17 | $color-callout: #f4fd9c !default;
18 | $color-challenge: #eec275 !default;
19 | $color-checklist: #dfd2a0 !default;
20 | $color-discussion: #eec275 !default;
21 | $color-keypoints: #7ae78e !default;
22 | $color-objectives: #daee84 !default;
23 | $color-prereq: #9cd6dc !default;
24 | $color-solution: #ded4b9 !default;
25 | $color-testimonial: #fc8dc1 !default;
26 |
27 | //----------------------------------------
28 | // Specialized code blocks.
29 | //----------------------------------------
30 |
31 | @mixin cdSetup($color) {
32 | color: $color;
33 | border-left: solid 5px $color;
34 | margin-bottom: 0px;
35 | border-radius: 4px 0 0 4px;
36 | }
37 |
38 | .error { @include cdSetup($color-error); }
39 | .output { @include cdSetup($color-output); }
40 | .source { @include cdSetup($color-source); }
41 |
42 | .bash { @include cdSetup($color-source); }
43 | .make { @include cdSetup($color-source); }
44 | .matlab { @include cdSetup($color-source); }
45 | .python { @include cdSetup($color-source); }
46 | .r { @include cdSetup($color-source); }
47 | .sql { @include cdSetup($color-source); }
48 |
49 | .error pre,
50 | .output pre,
51 | .source pre,
52 | .bash pre,
53 | .make pre,
54 | .matlab pre,
55 | .python pre,
56 | .r pre,
57 | .sql pre {
58 | border-radius: 0 4px 4px 0;
59 | }
60 |
61 | //----------------------------------------
62 | // Specialized blockquote environments for learning objectives, callouts, etc.
63 | //----------------------------------------
64 |
65 | $codeblock-padding: 5px !default;
66 |
67 | @mixin bkSetup($color, $glyph) {
68 |
69 | $gradientcolor1: $color;
70 | $gradientcolor2: scale-color($color, $lightness: 10%);
71 |
72 | padding-left: $codeblock-padding;
73 | padding-top: 0;
74 | padding-bottom: 0;
75 | padding-right: 0;
76 | border: 1px solid;
77 | border-color: $color;
78 | padding-bottom: $codeblock-padding;
79 |
80 | h2 {
81 | padding-top: $codeblock-padding;
82 | padding-bottom: $codeblock-padding;
83 | font-size: 20px;
84 | background: linear-gradient(to bottom, $gradientcolor1, $gradientcolor2);
85 | border-color: $color;
86 | margin-top: 0px;
87 | margin-left: -$codeblock-padding; // to move back to the left margin of the enclosing blockquote
88 | }
89 | h2:before {
90 | font-family: 'Glyphicons Halflings';
91 | content: $glyph;
92 | float: left;
93 | padding-left: $codeblock-padding;
94 | padding-right: $codeblock-padding;
95 | display: inline-block;
96 | -webkit-font-smoothing: antialiased;
97 | }
98 |
99 | }
100 |
101 | .callout{ @include bkSetup($color-callout, "\e146"); }
102 | .challenge{ @include bkSetup($color-challenge, "\270f"); }
103 | .checklist{ @include bkSetup($color-checklist, "\e067"); }
104 | .discussion{ @include bkSetup($color-discussion, "\e123"); }
105 | .keypoints{ @include bkSetup($color-keypoints, "\e101"); }
106 | .objectives{ @include bkSetup($color-objectives, "\e085"); }
107 | .prereq{ @include bkSetup($color-prereq, "\e124"); }
108 | .solution{ @include bkSetup($color-solution, "\e105"); }
109 | .testimonial{ @include bkSetup($color-testimonial, "\e143"); }
110 |
111 | //----------------------------------------
112 | // Override Bootstrap settings.
113 | //----------------------------------------
114 |
115 | code {
116 | padding: 2px 5px;
117 | color: #3d90d9;
118 | background-color: #e7e7e7;
119 | }
120 |
121 | img {
122 | max-width: 100%;
123 | }
124 |
125 | //----------------------------------------
126 | // Miscellaneous.
127 | //----------------------------------------
128 |
129 | .maintitle {
130 | text-align: center;
131 | }
132 |
133 | .footertext {
134 | text-align: center;
135 | }
136 |
137 | img.navbar-logo {
138 | height: 40px; // synchronize with height of navbar
139 | padding-top: 5px;
140 | padding-right: 10px;
141 | }
142 |
143 | div.branding {
144 | color: $color-brand;
145 | }
146 |
147 | ul,
148 | ol {
149 | padding-left: 2em;
150 | }
151 |
152 | span.fold-unfold {
153 | margin-left: 1em;
154 | opacity: 0.5;
155 | }
156 |
--------------------------------------------------------------------------------
/_episodes/14-supplemental-rstudio.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Using Git from RStudio
3 | teaching: 10
4 | exercises: 0
5 | questions:
6 | - "How can I use Git with RStudio?"
7 | objectives:
8 | - "Understand how to use Git from RStudio."
9 | keypoints:
10 | - "Create an RStudio project"
11 | ---
12 |
13 | Since version control is so useful when developing scripts, RStudio has built-in
14 | integration with Git. There are some more obscure Git features that you still
15 | need to use the command-line for, but RStudio has a nice interface for most
16 | common operations.
17 |
18 | RStudio let's you create a [project][rstudio-projects] associated with
19 | a given directory. This is a way to keep track of related files. One
20 | of the way to keep track of them is via version control! To get
21 | started using RStudio for version control, let's make a new project:
22 |
23 | 
24 |
25 | This will pop up a window asking us how we want to create the project. We have
26 | some options here. Let's say that we want to use RStudio with the planets
27 | repository that we already made. Since that repository lives in a directory on
28 | our computer, we'll choose "existing directory":
29 |
30 | 
31 |
32 | > ## Do You See a "Version Control" Option?
33 | >
34 | > Although we're not going to use it here, there should be a "version control"
35 | > option on this menu. That is what you would click on if you wanted to
36 | > create a project on your computer by cloning a repository from github.
37 | > If that option is not present, it probably means that RStudio doesn't know
38 | > where your Git executable is. See
39 | > [this page](https://stat545-ubc.github.io/git03_rstudio-meet-git.html)
40 | > for some debugging advice. Even if you have Git installed, you may need
41 | > to accept the XCode license if you are using MacOSX.
42 | {: .callout}
43 |
44 | Next, RStudio will ask which existing directory we want to use. Click "browse"
45 | to navigate to the correct directory on your computer, then click "create
46 | project":
47 |
48 | 
49 |
50 | Ta-da! Now you have an R project containing your repository. Notice the
51 | vertical "Git" menu that is now on the menu bar. This means RStudio has
52 | recognized that this directory is a git repository, so it's giving you tools
53 | to use Git:
54 |
55 | 
56 |
57 | To edit the files in your repository, you can click on them from the panel in
58 | the lower right. Let's add some more information about Pluto:
59 |
60 | 
61 |
62 | Once we have saved our edited files, we can also use RStudio to commit these changes. Go to the git menu and click
63 | "commit":
64 |
65 | 
66 |
67 | This will bring up a screen where you can select which files to commit (check
68 | the boxes in the "staged" column) and enter a commit message (in the upper
69 | right). The icons in the "status" column indicate the current status of each
70 | file. You can also see the changes to each file by clicking on its name. Once
71 | everything is the way you want it, click "commit":
72 |
73 | 
74 |
75 | You can push these changes by selecting "push" from the Git menu. There are
76 | also options there to pull from a remote version of the repository, and view
77 | the history:
78 |
79 | 
80 |
81 | > ## Are the Push/Pull Commands Grayed Out?
82 | >
83 | > If this is the case, it generally means that RStudio doesn't know the
84 | > location of any other version of your repository (i.e. the one on GitHub).
85 | > To fix this, open a terminal to the repository and enter the command:
86 | > `git push -u origin master`. Then restart RStudio.
87 | {: .callout}
88 |
89 | If we click on "history", we can see a pretty graphical version of what
90 | `git log` would tell us:
91 |
92 | 
93 |
94 | RStudio creates some files that is uses to keep track of your project. You
95 | generally don't want to track these, so adding them to your .gitignore file
96 | is a good idea:
97 |
98 | 
99 |
100 | There are many more features buried in the RStudio git interface, but these
101 | should be enough to get you started!
102 |
103 | [rstudio-projects]: https://support.rstudio.com/hc/en-us/articles/200526207-Using-Projects
104 |
--------------------------------------------------------------------------------
/fig/conflict.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
58 |
--------------------------------------------------------------------------------
/_episodes/03-create.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Creating a Repository
3 | teaching: 10
4 | exercises: 0
5 | questions:
6 | - "Where does Git store information?"
7 | objectives:
8 | - "Create a local Git repository."
9 | keypoints:
10 | - "`git init` initializes a repository."
11 | ---
12 |
13 | Once Git is configured,
14 | we can start using it.
15 | Let's create a directory for our work and then move into that directory:
16 |
17 | ~~~
18 | $ mkdir planets
19 | $ cd planets
20 | ~~~
21 | {: .bash}
22 |
23 | Then we tell Git to make `planets` a [repository]({{ page.root }}/reference/#repository)—a place where
24 | Git can store versions of our files:
25 |
26 | ~~~
27 | $ git init
28 | ~~~
29 | {: .bash}
30 |
31 | If we use `ls` to show the directory's contents,
32 | it appears that nothing has changed:
33 |
34 | ~~~
35 | $ ls
36 | ~~~
37 | {: .bash}
38 |
39 | But if we add the `-a` flag to show everything,
40 | we can see that Git has created a hidden directory within `planets` called `.git`:
41 |
42 | ~~~
43 | $ ls -a
44 | ~~~
45 | {: .bash}
46 |
47 | ~~~
48 | . .. .git
49 | ~~~
50 | {: .output}
51 |
52 | Git stores information about the project in this special sub-directory.
53 | If we ever delete it,
54 | we will lose the project's history.
55 |
56 | We can check that everything is set up correctly
57 | by asking Git to tell us the status of our project:
58 |
59 | ~~~
60 | $ git status
61 | ~~~
62 | {: .bash}
63 |
64 | ~~~
65 | # On branch master
66 | #
67 | # Initial commit
68 | #
69 | nothing to commit (create/copy files and use "git add" to track)
70 | ~~~
71 | {: .output}
72 |
73 | > ## Places to Create Git Repositories
74 | >
75 | > Dracula starts a new project, `moons`, related to his `planets` project.
76 | > Despite Wolfman's concerns, he enters the following sequence of commands to
77 | > create one Git repository inside another:
78 | >
79 | > ~~~
80 | > $ cd # return to home directory
81 | > $ mkdir planets # make a new directory planets
82 | > $ cd planets # go into planets
83 | > $ git init # make the planets directory a Git repository
84 | > $ mkdir moons # make a sub-directory planets/moons
85 | > $ cd moons # go into planets/moons
86 | > $ git init # make the moons sub-directory a Git repository
87 | > ~~~
88 | > {: .bash}
89 | >
90 | > Why is it a bad idea to do this? (Notice here that the `planets` project is now also tracking the entire `moons` repository.)
91 | > How can Dracula undo his last `git init`?
92 | >
93 | > > ## Solution
94 | > >
95 | > > Git repositories can interfere with each other if they are "nested" in the
96 | > > directory of another: the outer repository will try to version-control
97 | > > the inner repository. Therefore, it's best to create each new Git
98 | > > repository in a separate directory. To be sure that there is no conflicting
99 | > > repository in the directory, check the output of `git status`. If it looks
100 | > > like the following, you are good to go to create a new repository as shown
101 | > > above:
102 | > >
103 | > > ~~~
104 | > > $ git status
105 | > > ~~~
106 | > > {: .bash}
107 | > > ~~~
108 | > > fatal: Not a git repository (or any of the parent directories): .git
109 | > > ~~~
110 | > > {: .output}
111 | > >
112 | > > Note that we can track files in directories within a Git:
113 | > >
114 | > > ~~~
115 | > > $ touch moon phobos deimos titan # create moon files
116 | > > $ cd .. # return to planets directory
117 | > > $ ls moons # list contents of the moons directory
118 | > > $ git add moons/* # add all contents of planets/moons
119 | > > $ git status # show moons files in staging area
120 | > > $ git commit -m "add moon files" # commit planets/moons to planets Git repository
121 | > > ~~~
122 | > > {: .bash}
123 | > >
124 | > > Similarly, we can ignore (as discussed later) entire directories, such as the `moons` directory:
125 | > >
126 | > > ~~~
127 | > > $ nano .gitignore # open the .gitignore file in the text editor to add the moons directory
128 | > > $ cat .gitignore # if you run cat afterwards, it should look like this:
129 | > > ~~~
130 | > > {: .bash}
131 | > >
132 | > > ~~~
133 | > > moons
134 | > > ~~~
135 | > > {: .output}
136 | > >
137 | > > To recover from this little mistake, Dracula can just remove the `.git`
138 | > > folder in the moons subdirectory. To do so he can run the following command from inside the 'moons' directory:
139 | > >
140 | > > ~~~
141 | > > $ rm -rf moons/.git
142 | > > ~~~
143 | > > {: .bash}
144 | > >
145 | > > But be careful! Running this command in the wrong directory, will remove
146 | > > the entire git-history of a project you might wanted to keep. Therefore, always check your current directory using the
147 | > > command `pwd`.
148 | > {: .solution}
149 | {: .challenge}
150 |
--------------------------------------------------------------------------------
/assets/img/lc-icon-black.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
77 |
--------------------------------------------------------------------------------
/bin/repo_check.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Check repository settings.
5 | """
6 |
7 | from __future__ import print_function
8 | import sys
9 | import os
10 | from subprocess import Popen, PIPE
11 | import re
12 | from optparse import OptionParser
13 |
14 | from util import Reporter, load_yaml, require
15 |
16 | # Import this way to produce a more useful error message.
17 | try:
18 | import requests
19 | except ImportError:
20 | print('Unable to import requests module: please install requests', file=sys.stderr)
21 | sys.exit(1)
22 |
23 |
24 | # Pattern to match Git command-line output for remotes => (user name, project name).
25 | P_GIT_REMOTE = re.compile(r'upstream\s+[^:]+:([^/]+)/([^.]+)\.git\s+\(fetch\)')
26 |
27 | # Repository URL format string.
28 | F_REPO_URL = 'https://github.com/{0}/{1}/'
29 |
30 | # Pattern to match repository URLs => (user name, project name)
31 | P_REPO_URL = re.compile(r'https?://github\.com/([^.]+)/([^/]+)/?')
32 |
33 | # API URL format string.
34 | F_API_URL = 'https://api.github.com/repos/{0}/{1}/labels'
35 |
36 | # Expected labels and colors.
37 | EXPECTED = {
38 | 'bug' : 'bd2c00',
39 | 'discussion' : 'fc8dc1',
40 | 'enhancement' : '9cd6dc',
41 | 'help-wanted' : 'f4fd9c',
42 | 'instructor-training' : '6e5494',
43 | 'newcomer-friendly' : 'eec275',
44 | 'question' : '808040',
45 | 'template-and-tools' : '2b3990',
46 | 'work-in-progress' : '7ae78e'
47 | }
48 |
49 |
50 | def main():
51 | """
52 | Main driver.
53 | """
54 |
55 | args = parse_args()
56 | reporter = Reporter()
57 | repo_url = get_repo_url(args.source_dir, args.repo_url)
58 | check_labels(reporter, repo_url)
59 | reporter.report()
60 |
61 |
62 | def parse_args():
63 | """
64 | Parse command-line arguments.
65 | """
66 |
67 | parser = OptionParser()
68 | parser.add_option('-r', '--repo',
69 | default=None,
70 | dest='repo_url',
71 | help='repository URL')
72 | parser.add_option('-s', '--source',
73 | default=os.curdir,
74 | dest='source_dir',
75 | help='source directory')
76 |
77 | args, extras = parser.parse_args()
78 | require(not extras,
79 | 'Unexpected trailing command-line arguments "{0}"'.format(extras))
80 |
81 | return args
82 |
83 |
84 | def get_repo_url(source_dir, repo_url):
85 | """
86 | Figure out which repository to query.
87 | """
88 |
89 | # Explicitly specified.
90 | if repo_url is not None:
91 | return repo_url
92 |
93 | # Guess.
94 | cmd = 'git remote -v'
95 | p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, close_fds=True, universal_newlines=True)
96 | stdout_data, stderr_data = p.communicate()
97 | stdout_data = stdout_data.split('\n')
98 | matches = [P_GIT_REMOTE.match(line) for line in stdout_data]
99 | matches = [m for m in matches if m is not None]
100 | require(len(matches) == 1,
101 | 'Unexpected output from git remote command: "{0}"'.format(matches))
102 |
103 | username = matches[0].group(1)
104 | require(username, 'empty username in git remote output {0}'.format(matches[0]))
105 |
106 | project_name = matches[0].group(2)
107 | require(username, 'empty project name in git remote output {0}'.format(matches[0]))
108 |
109 | url = F_REPO_URL.format(username, project_name)
110 | return url
111 |
112 |
113 | def check_labels(reporter, repo_url):
114 | """
115 | Check labels in repository.
116 | """
117 |
118 | actual = get_labels(repo_url)
119 | extra = set(actual.keys()) - set(EXPECTED.keys())
120 |
121 | reporter.check(not extra,
122 | None,
123 | 'Extra label(s) in repository {0}: {1}',
124 | repo_url, ', '.join(sorted(extra)))
125 |
126 | missing = set(EXPECTED.keys()) - set(actual.keys())
127 | reporter.check(not missing,
128 | None,
129 | 'Missing label(s) in repository {0}: {1}',
130 | repo_url, ', '.join(sorted(missing)))
131 |
132 | overlap = set(EXPECTED.keys()).intersection(set(actual.keys()))
133 | for name in sorted(overlap):
134 | reporter.check(EXPECTED[name] == actual[name],
135 | None,
136 | 'Color mis-match for label {0} in {1}: expected {2}, found {3}',
137 | name, repo_url, EXPECTED[name], actual[name])
138 |
139 |
140 | def get_labels(repo_url):
141 | """
142 | Get actual labels from repository.
143 | """
144 |
145 | m = P_REPO_URL.match(repo_url)
146 | require(m, 'repository URL {0} does not match expected pattern'.format(repo_url))
147 |
148 | username = m.group(1)
149 | require(username, 'empty username in repository URL {0}'.format(repo_url))
150 |
151 | project_name = m.group(2)
152 | require(username, 'empty project name in repository URL {0}'.format(repo_url))
153 |
154 | url = F_API_URL.format(username, project_name)
155 | r = requests.get(url)
156 | require(r.status_code == 200,
157 | 'Request for {0} failed with {1}'.format(url, r.status_code))
158 |
159 | result = {}
160 | for entry in r.json():
161 | result[entry['name']] = entry['color']
162 | return result
163 |
164 |
165 | if __name__ == '__main__':
166 | main()
167 |
--------------------------------------------------------------------------------
/fig/play-changes.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
118 |
--------------------------------------------------------------------------------
/assets/img/swc-icon-blue.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/assets/img/dc-icon-black.svg:
--------------------------------------------------------------------------------
1 |
2 |
75 |
--------------------------------------------------------------------------------
/fig/git-staging-area.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
94 |
--------------------------------------------------------------------------------
/bin/util.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function
2 | import sys
3 | import os
4 | import json
5 | from subprocess import Popen, PIPE
6 |
7 | # Import this way to produce a more useful error message.
8 | try:
9 | import yaml
10 | except ImportError:
11 | print('Unable to import YAML module: please install PyYAML', file=sys.stderr)
12 | sys.exit(1)
13 |
14 |
15 | # Things an image file's name can end with.
16 | IMAGE_FILE_SUFFIX = {
17 | '.gif',
18 | '.jpg',
19 | '.png',
20 | '.svg'
21 | }
22 |
23 | # Files that shouldn't be present.
24 | UNWANTED_FILES = [
25 | '.nojekyll'
26 | ]
27 |
28 | # Marker to show that an expected value hasn't been provided.
29 | # (Can't use 'None' because that might be a legitimate value.)
30 | REPORTER_NOT_SET = []
31 |
32 | class Reporter(object):
33 | """Collect and report errors."""
34 |
35 | def __init__(self):
36 | """Constructor."""
37 |
38 | super(Reporter, self).__init__()
39 | self.messages = []
40 |
41 |
42 | def check_field(self, filename, name, values, key, expected=REPORTER_NOT_SET):
43 | """Check that a dictionary has an expected value."""
44 |
45 | if key not in values:
46 | self.add(filename, '{0} does not contain {1}', name, key)
47 | elif expected is REPORTER_NOT_SET:
48 | pass
49 | elif type(expected) in (tuple, set, list):
50 | if values[key] not in expected:
51 | self.add(filename, '{0} {1} value {2} is not in {3}', name, key, values[key], expected)
52 | elif values[key] != expected:
53 | self.add(filename, '{0} {1} is {2} not {3}', name, key, values[key], expected)
54 |
55 |
56 | def check(self, condition, location, fmt, *args):
57 | """Append error if condition not met."""
58 |
59 | if not condition:
60 | self.add(location, fmt, *args)
61 |
62 |
63 | def add(self, location, fmt, *args):
64 | """Append error unilaterally."""
65 |
66 | self.messages.append((location, fmt.format(*args)))
67 |
68 |
69 | def report(self, stream=sys.stdout):
70 | """Report all messages in order."""
71 |
72 | if not self.messages:
73 | return
74 |
75 | def pretty(item):
76 | location, message = item
77 | if isinstance(location, type(None)):
78 | return message
79 | elif isinstance(location, str):
80 | return location + ': ' + message
81 | elif isinstance(location, tuple):
82 | return '{0}:{1}: '.format(*location) + message
83 | else:
84 | assert False, 'Unknown item "{0}"'.format(item)
85 |
86 | def key(item):
87 | location, message = item
88 | if isinstance(location, type(None)):
89 | return ('', -1, message)
90 | elif isinstance(location, str):
91 | return (location, -1, message)
92 | elif isinstance(location, tuple):
93 | return (location[0], location[1], message)
94 | else:
95 | assert False, 'Unknown item "{0}"'.format(item)
96 |
97 | for m in sorted(self.messages, key=key):
98 | print(pretty(m), file=stream)
99 |
100 |
101 | def read_markdown(parser, path):
102 | """
103 | Get YAML and AST for Markdown file, returning
104 | {'metadata':yaml, 'metadata_len':N, 'text':text, 'lines':[(i, line, len)], 'doc':doc}.
105 | """
106 |
107 | # Split and extract YAML (if present).
108 | with open(path, 'r') as reader:
109 | body = reader.read()
110 | metadata_raw, metadata_yaml, body = split_metadata(path, body)
111 |
112 | # Split into lines.
113 | metadata_len = 0 if metadata_raw is None else metadata_raw.count('\n')
114 | lines = [(metadata_len+i+1, line, len(line)) for (i, line) in enumerate(body.split('\n'))]
115 |
116 | # Parse Markdown.
117 | cmd = 'ruby {0}'.format(parser)
118 | p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, close_fds=True, universal_newlines=True)
119 | stdout_data, stderr_data = p.communicate(body)
120 | doc = json.loads(stdout_data)
121 |
122 | return {
123 | 'metadata': metadata_yaml,
124 | 'metadata_len': metadata_len,
125 | 'text': body,
126 | 'lines': lines,
127 | 'doc': doc
128 | }
129 |
130 |
131 | def split_metadata(path, text):
132 | """
133 | Get raw (text) metadata, metadata as YAML, and rest of body.
134 | If no metadata, return (None, None, body).
135 | """
136 |
137 | metadata_raw = None
138 | metadata_yaml = None
139 | metadata_len = None
140 |
141 | pieces = text.split('---', 2)
142 | if len(pieces) == 3:
143 | metadata_raw = pieces[1]
144 | text = pieces[2]
145 | try:
146 | metadata_yaml = yaml.load(metadata_raw)
147 | except yaml.YAMLError as e:
148 | print('Unable to parse YAML header in {0}:\n{1}'.format(path, e), file=sys.stderr)
149 | sys.exit(1)
150 |
151 | return metadata_raw, metadata_yaml, text
152 |
153 |
154 | def load_yaml(filename):
155 | """
156 | Wrapper around YAML loading so that 'import yaml' is only needed
157 | in one file.
158 | """
159 |
160 | try:
161 | with open(filename, 'r') as reader:
162 | return yaml.load(reader)
163 | except (yaml.YAMLError, FileNotFoundError) as e:
164 | print('Unable to load YAML file {0}:\n{1}'.format(filename, e), file=sys.stderr)
165 | sys.exit(1)
166 |
167 |
168 | def check_unwanted_files(dir_path, reporter):
169 | """
170 | Check that unwanted files are not present.
171 | """
172 |
173 | for filename in UNWANTED_FILES:
174 | path = os.path.join(dir_path, filename)
175 | reporter.check(not os.path.exists(path),
176 | path,
177 | "Unwanted file found")
178 |
179 |
180 | def require(condition, message):
181 | """Fail if condition not met."""
182 |
183 | if not condition:
184 | print(message, file=sys.stderr)
185 | sys.exit(1)
186 |
--------------------------------------------------------------------------------
/_episodes/10-open.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Open Science
3 | teaching: 5
4 | exercises: 5
5 | questions:
6 | - "How can version control help me make my work more open?"
7 | objectives:
8 | - "Explain how a version control system can be leveraged as an electronic lab notebook for computational work."
9 | keypoints:
10 | - "Open scientific work is more useful and more highly cited than closed."
11 | ---
12 |
13 | > The opposite of "open" isn't "closed".
14 | > The opposite of "open" is "broken".
15 | >
16 | > --- John Wilbanks
17 | {: .quotation}
18 |
19 | Free sharing of information might be the ideal in science,
20 | but the reality is often more complicated.
21 | Normal practice today looks something like this:
22 |
23 | * A scientist collects some data and stores it on a machine
24 | that is occasionally backed up by her department.
25 | * She then writes or modifies a few small programs
26 | (which also reside on her machine)
27 | to analyze that data.
28 | * Once she has some results,
29 | she writes them up and submits her paper.
30 | She might include her data—a growing number of journals require this—but
31 | she probably doesn't include her code.
32 | * Time passes.
33 | * The journal sends her reviews written anonymously by a handful of other people in her field.
34 | She revises her paper to satisfy them,
35 | during which time she might also modify the scripts she wrote earlier,
36 | and resubmits.
37 | * More time passes.
38 | * The paper is eventually published.
39 | It might include a link to an online copy of her data,
40 | but the paper itself will be behind a paywall:
41 | only people who have personal or institutional access
42 | will be able to read it.
43 |
44 | For a growing number of scientists,
45 | though,
46 | the process looks like this:
47 |
48 | * The data that the scientist collects is stored in an open access repository
49 | like [figshare](http://figshare.com/) or
50 | [Zenodo](http://zenodo.org), possibly as soon as it's collected,
51 | and given its own
52 | [Digital Object Identifier](https://en.wikipedia.org/wiki/Digital_object_identifier) (DOI).
53 | Or the data was already published and is stored in
54 | [Dryad](http://datadryad.org/).
55 | * The scientist creates a new repository on GitHub to hold her work.
56 | * As she does her analysis,
57 | she pushes changes to her scripts
58 | (and possibly some output files)
59 | to that repository.
60 | She also uses the repository for her paper;
61 | that repository is then the hub for collaboration with her colleagues.
62 | * When she's happy with the state of her paper,
63 | she posts a version to [arXiv](http://arxiv.org/)
64 | or some other preprint server
65 | to invite feedback from peers.
66 | * Based on that feedback,
67 | she may post several revisions
68 | before finally submitting her paper to a journal.
69 | * The published paper includes links to her preprint
70 | and to her code and data repositories,
71 | which makes it much easier for other scientists
72 | to use her work as starting point for their own research.
73 |
74 | This open model accelerates discovery:
75 | the more open work is,
76 | [the more widely it is cited and re-used](http://dx.doi.org/10.1371/journal.pone.0000308).
77 | However,
78 | people who want to work this way need to make some decisions
79 | about what exactly "open" means and how to do it. You can find more on the different aspects of Open Science in [this book](http://link.springer.com/book/10.1007/978-3-319-00026-8).
80 |
81 | This is one of the (many) reasons we teach version control.
82 | When used diligently,
83 | it answers the "how" question
84 | by acting as a shareable electronic lab notebook for computational work:
85 |
86 | * The conceptual stages of your work are documented, including who did
87 | what and when. Every step is stamped with an identifier (the commit ID)
88 | that is for most intents and purposes unique.
89 | * You can tie documentation of rationale, ideas, and other
90 | intellectual work directly to the changes that spring from them.
91 | * You can refer to what you used in your research to obtain your
92 | computational results in a way that is unique and recoverable.
93 | * With a distributed version control system such as Git, the version
94 | control repository is easy to archive for perpetuity, and contains
95 | the entire history.
96 |
97 | > ## Making Code Citable
98 | >
99 | > [This short guide](https://guides.github.com/activities/citable-code/) from GitHub
100 | > explains how to create a Digital Object Identifier (DOI) for your code,
101 | > your papers,
102 | > or anything else hosted in a version control repository.
103 | {: .callout}
104 |
105 | > ## How Reproducible Is My Work?
106 | >
107 | > Ask one of your labmates to reproduce a result you recently obtained
108 | > using only what they can find in your papers or on the web.
109 | > Try to do the same for one of their results,
110 | > then try to do it for a result from a lab you work with.
111 | {: .challenge}
112 |
113 | > ## How to Find an Appropriate Data Repository?
114 | >
115 | > Surf the internet for a couple of minutes and check out the data repositories
116 | > mentioned above: [Figshare](http://figshare.com/), [Zenodo](http://zenodo.org),
117 | > [Dryad](http://datadryad.org/). Depending on your field of research, you might
118 | > find community-recognized repositories that are well-known in your field.
119 | > You might also find useful [these data repositories recommended by Nature](
120 | > http://www.nature.com/sdata/data-policies/repositories).
121 | > Discuss with your neighbor which data repository you might want to
122 | > approach for your current project and explain why.
123 | {: .challenge}
124 |
125 | > ## Can I Also Publish Code?
126 | >
127 | > There are many new ways to publish code and to make it citable. One
128 | > way is described [on the homepage of GitHub itself](
129 | > https://guides.github.com/activities/citable-code/).
130 | > Basically it's a combination of GitHub (where the code is) and Zenodo (the
131 | > repository creating the DOI). Read through this page while being aware
132 | > that this is only one of many ways to making your code citable.
133 | {: .challenge}
134 |
--------------------------------------------------------------------------------
/_episodes/02-setup.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Setting Up Git
3 | teaching: 5
4 | exercises: 0
5 | questions:
6 | - "How do I get set up to use Git?"
7 | objectives:
8 | - "Configure `git` the first time it is used on a computer."
9 | - "Understand the meaning of the `--global` configuration flag."
10 | keypoints:
11 | - "Use `git config` to configure a user name, email address, editor, and other preferences once per machine."
12 | ---
13 |
14 | When we use Git on a new computer for the first time,
15 | we need to configure a few things. Below are a few examples
16 | of configurations we will set as we get started with Git:
17 |
18 | * our name and email address,
19 | * to colorize our output,
20 | * what our preferred text editor is,
21 | * and that we want to use these settings globally (i.e. for every project)
22 |
23 | On a command line, Git commands are written as `git verb`,
24 | where `verb` is what we actually want to do. So here is how
25 | Dracula sets up his new laptop:
26 |
27 | ~~~
28 | $ git config --global user.name "Vlad Dracula"
29 | $ git config --global user.email "vlad@tran.sylvan.ia"
30 | $ git config --global color.ui "auto"
31 | ~~~
32 | {: .bash}
33 |
34 | Please use your own name and email address instead of Dracula's. This user name and email will be associated with your subsequent Git activity,
35 | which means that any changes pushed to
36 | [GitHub](http://github.com/),
37 | [BitBucket](http://bitbucket.org/),
38 | [GitLab](http://gitlab.com/) or
39 | another Git host server
40 | in a later lesson will include this information.
41 |
42 | > ## Line Endings
43 | >
44 | > As with other keys, when you hit the 'return' key on your keyboard,
45 | > your computer encodes this input.
46 | > For reasons that are long to explain, different operating systems
47 | > use different character(s) to represent the end of a line.
48 | > (You may also hear these referred to as newlines or line breaks.)
49 | > Because git uses these characters to compare files,
50 | > it may cause unexpected issues when editing a file on different machines.
51 | >
52 | > You can change the way git recognizes and encodes line endings
53 | > using the `core.autocrlf` command to `git config`.
54 | > The following settings are recommended:
55 | >
56 | > On OS X and Linux:
57 | >
58 | > ~~~
59 | > $ git config --global core.autocrlf input
60 | > ~~~
61 | > {: .bash}
62 | >
63 | > And on Windows:
64 | >
65 | > ~~~
66 | > $ git config --global core.autocrlf true
67 | > ~~~
68 | > {: .bash}
69 | >
70 | > You can read more about this issue
71 | > [on this GitHub page](https://help.github.com/articles/dealing-with-line-endings/).
72 | {: .callout}
73 |
74 | For these lessons, we will be interacting with [GitHub](http://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].
75 | If you elect to use a private email address with GitHub, then use that same email address for the `user.email` value, e.g. `username@users.noreply.github.com` replacing `username` with your GitHub one. You can change the email address later on by using the `git config` command again.
76 |
77 | Dracula also has to set his favorite text editor, following this table:
78 |
79 | | Editor | Configuration command |
80 | |:-------------------|:-------------------------------------------------|
81 | | Atom | `$ git config --global core.editor "atom --wait"`|
82 | | nano | `$ git config --global core.editor "nano -w"` |
83 | | BBEdit (Mac, with command line tools) | `$ git config --global core.editor "edit -w"` |
84 | | Sublime Text (Mac) | `$ git config --global core.editor "subl -n -w"` |
85 | | Sublime Text (Win, 32-bit install) | `$ git config --global core.editor "'c:/program files (x86)/sublime text 3/sublime_text.exe' -w"` |
86 | | Sublime Text (Win, 64-bit install) | `$ git config --global core.editor "'c:/program files/sublime text 3/sublime_text.exe' -w"` |
87 | | Notepad++ (Win, 32-bit install) | `$ git config --global core.editor "'c:/program files (x86)/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"`|
88 | | Notepad++ (Win, 64-bit install) | `$ git config --global core.editor "'c:/program files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"`|
89 | | Kate (Linux) | `$ git config --global core.editor "kate"` |
90 | | Gedit (Linux) | `$ git config --global core.editor "gedit --wait --new-window"` |
91 | | Scratch (Linux) | `$ git config --global core.editor "scratch-text-editor"` |
92 | | emacs | `$ git config --global core.editor "emacs"` |
93 | | vim | `$ git config --global core.editor "vim"` |
94 |
95 | It is possible to reconfigure the text editor for Git whenever you want to change it.
96 |
97 | > ## Exiting Vim
98 | >
99 | > Note that `vim` is the default editor for many programs. If you haven't used `vim` before and wish to exit a session, type `Esc` then `:q!` and `Enter`.
100 | {: .callout}
101 |
102 | The four commands we just ran above only need to be run once: the flag `--global` tells Git
103 | to use the settings for every project, in your user account, on this computer.
104 |
105 | You can check your settings at any time:
106 |
107 | ~~~
108 | $ git config --list
109 | ~~~
110 | {: .bash}
111 |
112 | You can change your configuration as many times as you want: just use the
113 | same commands to choose another editor or update your email address.
114 |
115 | > ## Proxy
116 | >
117 | > In some networks you need to use a
118 | > [proxy](https://en.wikipedia.org/wiki/Proxy_server). If this is the case, you
119 | > may also need to tell Git about the proxy:
120 | >
121 | > ~~~
122 | > $ git config --global http.proxy proxy-url
123 | > $ git config --global https.proxy proxy-url
124 | > ~~~
125 | > {: .bash}
126 | >
127 | > To disable the proxy, use
128 | >
129 | > ~~~
130 | > $ git config --global --unset http.proxy
131 | > $ git config --global --unset https.proxy
132 | > ~~~
133 | > {: .bash}
134 | {: .callout}
135 |
136 | > ## Git Help and Manual
137 | >
138 | > Always remember that if you forget a `git` command, you can access the list of commands by using `-h` and access the Git manual by using `--help` :
139 | >
140 | > ~~~
141 | > $ git config -h
142 | > $ git config --help
143 | > ~~~
144 | > {: .bash}
145 | {: .callout}
146 |
147 | [git-privacy]: https://help.github.com/articles/keeping-your-email-address-private/
148 |
--------------------------------------------------------------------------------
/_episodes/08-collab.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Collaborating
3 | teaching: 25
4 | exercises: 0
5 | questions:
6 | - "How can I use version control to collaborate with other people?"
7 | objectives:
8 | - "Clone a remote repository."
9 | - "Collaborate pushing to a common repository."
10 | keypoints:
11 | - "`git clone` copies a remote repository to create a local repository with a remote called `origin` automatically set up."
12 | ---
13 |
14 | For the next step, get into pairs. One person will be the "Owner" and the other
15 | will be the "Collaborator". The goal is that the Collaborator add changes into
16 | the Owner's repository. We will switch roles at the end, so both persons will
17 | play Owner and Collaborator.
18 |
19 | > ## Practicing By Yourself
20 | >
21 | > If you're working through this lesson on your own, you can carry on by opening
22 | > a second terminal window.
23 | > This window will represent your partner, working on another computer. You
24 | > won't need to give anyone access on GitHub, because both 'partners' are you.
25 | {: .callout}
26 |
27 | The Owner needs to give the Collaborator access.
28 | On GitHub, click the settings button on the right,
29 | then select Collaborators, and enter your partner's username.
30 |
31 | 
32 |
33 | To accept access to the Owner's repo, the Collaborator
34 | needs to go to [https://github.com/notifications](https://github.com/notifications).
35 | Once there she can accept access to the Owner's repo.
36 |
37 | Next, the Collaborator needs to download a copy of the Owner's repository to her
38 | machine. This is called "cloning a repo". To clone the Owner's repo into
39 | her `Desktop` folder, the Collaborator enters:
40 |
41 | ~~~
42 | $ git clone https://github.com/vlad/planets.git ~/Desktop/vlad-planets
43 | ~~~
44 | {: .bash}
45 |
46 | Replace 'vlad' with the Owner's username.
47 |
48 | 
49 |
50 | The Collaborator can now make a change in her clone of the Owner's repository,
51 | exactly the same way as we've been doing before:
52 |
53 | ~~~
54 | $ cd ~/Desktop/vlad-planets
55 | $ nano pluto.txt
56 | $ cat pluto.txt
57 | ~~~
58 | {: .bash}
59 |
60 | ~~~
61 | It is so a planet!
62 | ~~~
63 | {: .output}
64 |
65 | ~~~
66 | $ git add pluto.txt
67 | $ git commit -m "Add notes about Pluto"
68 | ~~~
69 | {: .bash}
70 |
71 | ~~~
72 | 1 file changed, 1 insertion(+)
73 | create mode 100644 pluto.txt
74 | ~~~
75 | {: .output}
76 |
77 | Then push the change to the *Owner's repository* on GitHub:
78 |
79 | ~~~
80 | $ git push origin master
81 | ~~~
82 | {: .bash}
83 |
84 | ~~~
85 | Counting objects: 4, done.
86 | Delta compression using up to 4 threads.
87 | Compressing objects: 100% (2/2), done.
88 | Writing objects: 100% (3/3), 306 bytes, done.
89 | Total 3 (delta 0), reused 0 (delta 0)
90 | To https://github.com/vlad/planets.git
91 | 9272da5..29aba7c master -> master
92 | ~~~
93 | {: .output}
94 |
95 | Note that we didn't have to create a remote called `origin`: Git uses this
96 | name by default when we clone a repository. (This is why `origin` was a
97 | sensible choice earlier when we were setting up remotes by hand.)
98 |
99 | Take a look to the Owner's repository on its GitHub website now (maybe you need
100 | to refresh your browser.) You should be able to see the new commit made by the
101 | Collaborator.
102 |
103 | To download the Collaborator's changes from GitHub, the Owner now enters:
104 |
105 | ~~~
106 | $ git pull origin master
107 | ~~~
108 | {: .bash}
109 |
110 | ~~~
111 | remote: Counting objects: 4, done.
112 | remote: Compressing objects: 100% (2/2), done.
113 | remote: Total 3 (delta 0), reused 3 (delta 0)
114 | Unpacking objects: 100% (3/3), done.
115 | From https://github.com/vlad/planets
116 | * branch master -> FETCH_HEAD
117 | Updating 9272da5..29aba7c
118 | Fast-forward
119 | pluto.txt | 1 +
120 | 1 file changed, 1 insertion(+)
121 | create mode 100644 pluto.txt
122 | ~~~
123 | {: .output}
124 |
125 | Now the three repositories (Owner's local, Collaborator's local, and Owner's on
126 | GitHub) are back in sync.
127 |
128 | > ## A Basic Collaborative Workflow
129 | >
130 | > In practice, it is good to be sure that you have an updated version of the
131 | > repository you are collaborating on, so you should `git pull` before making
132 | > our changes. The basic collaborative workflow would be:
133 | >
134 | > * update your local repo with `git pull origin master`,
135 | > * make your changes and stage them with `git add`,
136 | > * commit your changes with `git commit -m`, and
137 | > * upload the changes to GitHub with `git push origin master`
138 | >
139 | > It is better to make many commits with smaller changes rather than
140 | > of one commit with massive changes: small commits are easier to
141 | > read and review.
142 | {: .callout}
143 |
144 | > ## Switch Roles and Repeat
145 | >
146 | > Switch roles and repeat the whole process.
147 | {: .challenge}
148 |
149 | > ## Review Changes
150 | >
151 | > The Owner push commits to the repository without giving any information
152 | > to the Collaborator. How can the Collaborator find out what has changed with
153 | > command line? And on GitHub?
154 | >
155 | > > ## Solution
156 | > > On the command line, the Collaborator can use ```git fetch origin master```
157 | > > to get the remote changes into the local repository, but without merging
158 | > > them. Then by running ```git diff master origin/master``` the Collaborator
159 | > > will see the changes output in the terminal.
160 | > >
161 | > > On GitHub, the Collaborator can go to their own fork of the repository and
162 | > > look right above the light blue latest commit bar for a gray bar saying
163 | > > "This branch is 1 commit behind Our-Repository:master." On the far right of
164 | > > that gray bar is a Compare icon and link. On the Compare page the
165 | > > Collaborator should change the base fork to their own repository, then click
166 | > > the link in the paragraph above to "compare across forks", and finally
167 | > > change the head fork to the main repository. This will show all the commits
168 | > > that are different.
169 | > {: .solution}
170 | {: .challenge}
171 |
172 | > ## Comment Changes in GitHub
173 | >
174 | > The Collaborator has some questions about one line change made by the Owner and
175 | > has some suggestions to propose.
176 | >
177 | > With GitHub, it is possible to comment the diff of a commit. Over the line of
178 | > code to comment, a blue comment icon appears to open a comment window.
179 | >
180 | > The Collaborator posts its comments and suggestions using GitHub interface.
181 | {: .challenge}
182 |
183 | > ## Version History, Backup, and Version Control
184 | >
185 | > Some backup software can keep a history of the versions of your files. They also
186 | > allows you to recover specific versions. How is this functionality different from version control?
187 | > What are some of the benefits of using version control, Git and GitHub?
188 | {: .challenge}
189 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | [Software Carpentry][swc-site] and [Data Carpentry][dc-site] are open source projects,
4 | and we welcome contributions of all kinds:
5 | new lessons,
6 | fixes to existing material,
7 | bug reports,
8 | and reviews of proposed changes are all welcome.
9 |
10 | ## Contributor Agreement
11 |
12 | By contributing,
13 | you agree that we may redistribute your work under [our license](LICENSE.md).
14 | In exchange,
15 | we will address your issues and/or assess your change proposal as promptly as we can,
16 | and help you become a member of our community.
17 | Everyone involved in [Software Carpentry][swc-site] and [Data Carpentry][dc-site]
18 | agrees to abide by our [code of conduct](CONDUCT.md).
19 |
20 | ## How to Contribute
21 |
22 | The easiest way to get started is to file an issue
23 | to tell us about a spelling mistake,
24 | some awkward wording,
25 | or a factual error.
26 | This is a good way to introduce yourself
27 | and to meet some of our community members.
28 |
29 | 1. If you do not have a [GitHub][github] account,
30 | you can [send us comments by email][contact].
31 | However,
32 | we will be able to respond more quickly if you use one of the other methods described below.
33 |
34 | 2. If you have a [GitHub][github] account,
35 | or are willing to [create one][github-join],
36 | but do not know how to use Git,
37 | you can report problems or suggest improvements by [creating an issue][new-issue].
38 | This allows us to assign the item to someone
39 | and to respond to it in a threaded discussion.
40 |
41 | 3. If you are comfortable with Git,
42 | and would like to add or change material,
43 | you can submit a pull request (PR).
44 | Instructions for doing this are [included below](#using-github).
45 |
46 | ## Where to Contribute
47 |
48 | 1. If you wish to change this lesson,
49 | please work in ,
50 | which can be viewed at .
51 |
52 | 2. If you wish to change the example lesson,
53 | please work in ,
54 | which documents the format of our lessons
55 | and can be viewed at .
56 |
57 | 3. If you wish to change the template used for workshop websites,
58 | please work in .
59 | The home page of that repository explains how to set up workshop websites,
60 | while the extra pages in
61 | provide more background on our design choices.
62 |
63 | 4. If you wish to change CSS style files, tools,
64 | or HTML boilerplate for lessons or workshops stored in `_includes` or `_layouts`,
65 | please work in .
66 |
67 | ## What to Contribute
68 |
69 | There are many ways to contribute,
70 | from writing new exercises and improving existing ones
71 | to updating or filling in the documentation
72 | and submitting [bug reports][new-issue]
73 | about things that don't work, aren't clear, or are missing.
74 | If you are looking for ideas,
75 | please see [the list of issues for this repository][issues],
76 | or the issues for [Data Carpentry][dc-issues]
77 | and [Software Carpentry][swc-issues] projects.
78 |
79 | Comments on issues and reviews of pull requests are just as welcome:
80 | we are smarter together than we are on our own.
81 | Reviews from novices and newcomers are particularly valuable:
82 | it's easy for people who have been using these lessons for a while
83 | to forget how impenetrable some of this material can be,
84 | so fresh eyes are always welcome.
85 |
86 | ## What *Not* to Contribute
87 |
88 | Our lessons already contain more material than we can cover in a typical workshop,
89 | so we are usually *not* looking for more concepts or tools to add to them.
90 | As a rule,
91 | if you want to introduce a new idea,
92 | you must (a) estimate how long it will take to teach
93 | and (b) explain what you would take out to make room for it.
94 | The first encourages contributors to be honest about requirements;
95 | the second, to think hard about priorities.
96 |
97 | We are also not looking for exercises or other material that only run on one platform.
98 | Our workshops typically contain a mixture of Windows, Mac OS X, and Linux users;
99 | in order to be usable,
100 | our lessons must run equally well on all three.
101 |
102 | ## Using GitHub
103 |
104 | If you choose to contribute via GitHub,
105 | you may want to look at
106 | [How to Contribute to an Open Source Project on GitHub][how-contribute].
107 | In brief:
108 |
109 | 1. The published copy of the lesson is in the `gh-pages` branch of the repository
110 | (so that GitHub will regenerate it automatically).
111 | Please create all branches from that,
112 | and merge the [master repository][repo]'s `gh-pages` branch into your `gh-pages` branch
113 | before starting work.
114 | Please do *not* work directly in your `gh-pages` branch,
115 | since that will make it difficult for you to work on other contributions.
116 |
117 | 2. We use [GitHub flow][github-flow] to manage changes:
118 | 1. Create a new branch in your desktop copy of this repository for each significant change.
119 | 2. Commit the change in that branch.
120 | 3. Push that branch to your fork of this repository on GitHub.
121 | 4. Submit a pull request from that branch to the [master repository][repo].
122 | 5. If you receive feedback,
123 | make changes on your desktop and push to your branch on GitHub:
124 | the pull request will update automatically.
125 |
126 | Each lesson has two maintainers who review issues and pull requests
127 | or encourage others to do so.
128 | The maintainers are community volunteers,
129 | and have final say over what gets merged into the lesson.
130 |
131 | ## Other Resources
132 |
133 | General discussion of [Software Carpentry][swc-site] and [Data Carpentry][dc-site]
134 | happens on the [discussion mailing list][discuss-list],
135 | which everyone is welcome to join.
136 | You can also [reach us by email][contact].
137 |
138 | [contact]: mailto:admin@software-carpentry.org
139 | [dc-issues]: https://github.com/issues?q=user%3Adatacarpentry
140 | [dc-lessons]: http://datacarpentry.org/lessons/
141 | [dc-site]: http://datacarpentry.org/
142 | [discuss-list]: http://lists.software-carpentry.org/listinfo/discuss
143 | [github]: http://github.com
144 | [github-flow]: https://guides.github.com/introduction/flow/
145 | [github-join]: https://github.com/join
146 | [how-contribute]: https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github
147 | [new-issue]: https://github.com/swcarpentry/git-novice/issues/new
148 | [issues]: https://github.com/swcarpentry/git-novice/issues/
149 | [repo]: https://github.com/swcarpentry/git-novice/
150 | [swc-issues]: https://github.com/issues?q=user%3Aswcarpentry
151 | [swc-lessons]: http://software-carpentry.org/lessons/
152 | [swc-site]: http://software-carpentry.org/
153 |
--------------------------------------------------------------------------------
/_episodes/06-ignore.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Ignoring Things
3 | teaching: 5
4 | exercises: 0
5 | questions:
6 | - "How can I tell Git to ignore files I don't want to track?"
7 | objectives:
8 | - "Configure Git to ignore specific files."
9 | - "Explain why ignoring files can be useful."
10 | keypoints:
11 | - "The `.gitignore` file tells Git what files to ignore."
12 | ---
13 |
14 | What if we have files that we do not want Git to track for us,
15 | like backup files created by our editor
16 | or intermediate files created during data analysis.
17 | Let's create a few dummy files:
18 |
19 | ~~~
20 | $ mkdir results
21 | $ touch a.dat b.dat c.dat results/a.out results/b.out
22 | ~~~
23 | {: .bash}
24 |
25 | and see what Git says:
26 |
27 | ~~~
28 | $ git status
29 | ~~~
30 | {: .bash}
31 |
32 | ~~~
33 | On branch master
34 | Untracked files:
35 | (use "git add ..." to include in what will be committed)
36 |
37 | a.dat
38 | b.dat
39 | c.dat
40 | results/
41 | nothing added to commit but untracked files present (use "git add" to track)
42 | ~~~
43 | {: .output}
44 |
45 | Putting these files under version control would be a waste of disk space.
46 | What's worse,
47 | having them all listed could distract us from changes that actually matter,
48 | so let's tell Git to ignore them.
49 |
50 | We do this by creating a file in the root directory of our project called `.gitignore`:
51 |
52 | ~~~
53 | $ nano .gitignore
54 | $ cat .gitignore
55 | ~~~
56 | {: .bash}
57 |
58 | ~~~
59 | *.dat
60 | results/
61 | ~~~
62 | {: .output}
63 |
64 | These patterns tell Git to ignore any file whose name ends in `.dat`
65 | and everything in the `results` directory.
66 | (If any of these files were already being tracked,
67 | Git would continue to track them.)
68 |
69 | Once we have created this file,
70 | the output of `git status` is much cleaner:
71 |
72 | ~~~
73 | $ git status
74 | ~~~
75 | {: .bash}
76 |
77 | ~~~
78 | On branch master
79 | Untracked files:
80 | (use "git add ..." to include in what will be committed)
81 |
82 | .gitignore
83 | nothing added to commit but untracked files present (use "git add" to track)
84 | ~~~
85 | {: .output}
86 |
87 | The only thing Git notices now is the newly-created `.gitignore` file.
88 | You might think we wouldn't want to track it,
89 | but everyone we're sharing our repository with will probably want to ignore
90 | the same things that we're ignoring.
91 | Let's add and commit `.gitignore`:
92 |
93 | ~~~
94 | $ git add .gitignore
95 | $ git commit -m "Add the ignore file"
96 | $ git status
97 | ~~~
98 | {: .bash}
99 |
100 | ~~~
101 | # On branch master
102 | nothing to commit, working directory clean
103 | ~~~
104 | {: .output}
105 |
106 | As a bonus, using `.gitignore` helps us avoid accidentally adding to the repository files that we don't want to track:
107 |
108 | ~~~
109 | $ git add a.dat
110 | ~~~
111 | {: .bash}
112 |
113 | ~~~
114 | The following paths are ignored by one of your .gitignore files:
115 | a.dat
116 | Use -f if you really want to add them.
117 | ~~~
118 | {: .output}
119 |
120 | If we really want to override our ignore settings,
121 | we can use `git add -f` to force Git to add something. For example,
122 | `git add -f a.dat`.
123 | We can also always see the status of ignored files if we want:
124 |
125 | ~~~
126 | $ git status --ignored
127 | ~~~
128 | {: .bash}
129 |
130 | ~~~
131 | On branch master
132 | Ignored files:
133 | (use "git add -f ..." to include in what will be committed)
134 |
135 | a.dat
136 | b.dat
137 | c.dat
138 | results/
139 |
140 | nothing to commit, working directory clean
141 | ~~~
142 | {: .output}
143 |
144 | > ## Ignoring Nested Files
145 | >
146 | > Given a directory structure that looks like:
147 | >
148 | > ~~~
149 | > results/data
150 | > results/plots
151 | > ~~~
152 | > {: .bash}
153 | >
154 | > How would you ignore only `results/plots` and not `results/data`?
155 | >
156 | > > ## Solution
157 | > >
158 | > > As with most programming issues, there are a few ways that you
159 | > > could solve this. If you only want to ignore the contents of
160 | > > `results/plots`, you can change your `.gitignore` to ignore
161 | > > only the `/plots/` subfolder by adding the following line to
162 | > > your .gitignore:
163 | > >
164 | > > `results/plots/`
165 | > >
166 | > > If, instead, you want to ignore everything in `/results/`, but wanted to track
167 | > > `results/data`, then you can add `results/` to your .gitignore
168 | > > and create an exception for the `results/data/` folder.
169 | > > The next challenge will cover this type of solution.
170 | > >
171 | > > Sometimes the `**` pattern comes in handy, too, which matches
172 | > > multiple directory levels. E.g. `**/results/plots/*` would make git ignore
173 | > > the `results/plots` directory in any root directory.
174 | > {: .solution}
175 | {: .challenge}
176 |
177 | > ## Including Specific Files
178 | >
179 | > How would you ignore all `.data` files in your root directory except for
180 | > `final.data`?
181 | > Hint: Find out what `!` (the exclamation point operator) does
182 | >
183 | > > ## Solution
184 | > >
185 | > > You would add the following two lines to your .gitignore:
186 | > >
187 | > > ~~~
188 | > > *.data # ignore all data files
189 | > > !final.data # except final.data
190 | > > ~~~
191 | > > {: .output}
192 | > >
193 | > > The exclamation point operator will include a previously excluded entry.
194 | > {: .solution}
195 | {: .challenge}
196 |
197 | > ## Ignoring all data Files in a Directory
198 | >
199 | > Given a directory structure that looks like:
200 | >
201 | > ~~~
202 | > results/data/position/gps/a.data
203 | > results/data/position/gps/b.data
204 | > results/data/position/gps/c.data
205 | > results/data/position/gps/info.txt
206 | > results/plots
207 | > ~~~
208 | > {: .bash}
209 | >
210 | > What's the shortest `.gitignore` rule you could write to ignore all `.data`
211 | > files in `result/data/position/gps`? Do not ignore the `info.txt`.
212 | >
213 | > > ## Solution
214 | > >
215 | > > Appending `results/data/position/gps/*.data` will match every file in `results/data/position/gps` that ends with `.data`.
216 | > > The file `results/data/position/gps/info.txt` will not be ignored.
217 | > {: .solution}
218 | {: .challenge}
219 |
220 | > ## The Order of Rules
221 | >
222 | > Given a `.gitignore` file with the following contents:
223 | >
224 | > ~~~
225 | > *.data
226 | > !*.data
227 | > ~~~
228 | > {: .bash}
229 | >
230 | > What will be the result?
231 | >
232 | > > ## Solution
233 | > >
234 | > > The `!` modifier will negate an entry from a previously defined ignore pattern.
235 | > > Because the `!*.data` entry negates all of the previous `.data` files in the `.gitignore`,
236 | > > none of them will be ignored, and all `.data` files will be tracked.
237 | > >
238 | > {: .solution}
239 | {: .challenge}
240 |
241 | > ## Log Files
242 | >
243 | > You wrote a script that creates many intermediate log-files of the form `log_01`, `log_02`, `log_03`, etc.
244 | > You want to keep them but you do not want to track them through `git`.
245 | >
246 | > 1. Write **one** `.gitignore` entry that excludes files of the form `log_01`, `log_02`, etc.
247 | >
248 | > 2. Test your "ignore pattern" by creating some dummy files of the form `log_01`, etc.
249 | >
250 | > 3. You find that the file `log_01` is very important after all, add it to the tracked files without changing the `.gitignore` again.
251 | >
252 | > 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`.
253 | >
254 | > > ## Solution
255 | > >
256 | > > 1. append either `log_*` or `log*` as a new entry in your .gitignore
257 | > > 3. track `log_01` using `git add -f log_01`
258 | > {: .solution}
259 | {: .challenge}
260 |
--------------------------------------------------------------------------------
/fig/versions.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
185 |
--------------------------------------------------------------------------------
/fig/git-checkout.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
112 |
--------------------------------------------------------------------------------