diff --git a/_config.yml b/_config.yml index ce8c8d5..4ba8f75 100644 --- a/_config.yml +++ b/_config.yml @@ -6,7 +6,7 @@ description: Learn to use version control to manage your software development an n_sessions: 3 prereq: NA url: https://uniexeterrse.github.io/intro-version-control -notes_on: false +notes_on: true # Specify that things in the episodes collection should be output. collections: diff --git a/_episodes/01_intro.md b/_episodes/01_intro.md new file mode 100644 index 0000000..923a169 --- /dev/null +++ b/_episodes/01_intro.md @@ -0,0 +1,63 @@ +--- +layout: page +title: Introductions +order: 1 +session: 1 +length: 5 +toc: true +adapted: false +--- + +## Welcome + +This workshop was put together by the Research Software Engineering Group. +This is as part of an ongoing initiative to provide training for staff and +students to expand their skill sets and position themselves to confidently +perform the informatics elements of their research projects in an efficient and +reproducible way. The programme and workshops are under constant evolution, and +we are grateful for your feedback which is a core component of this process. + +We will start by introducing the workshop leaders and helpers. We are all here +because we are passionate about sharing our knowledge and supporting the +development of our colleagues. + + +## Housekeeping + +The workshop in organised into episodes of content, which can be seen in the +[workshop schedule]({{ site.url }}/schedule.html). Our aim is to have an official break +every 60-90 minutes, but there will also be periods in-between demonstrations +where you are free to take additional comfort breaks if required. + +This workshop will be delivered mainly by live coding and exercises, with +participants expected to follow along with the worked examples. Our aim is to be +responsive to the needs of the group, both in person and +virtually. Therefore, think of the schedule as a guide rather than a strict +timetable. We welcome questions and queries as we go along: there are helpers +in the room so if you need assistance at any point please do indicate this to +them. There is also a dedicated +helper for the virtual participants so please raise your virtual hand to +attract their attention, or drop a question in the meeting chat if you prefer. + +Please conduct yourselves in line with the +[code of conduct]({{ site.url }}/code.html) — +essentially, be respectful and aware that we all have different backgrounds, +experiences and viewpoints. + + +## Acknowledgement + +This course has been adapted from Software Carpentry's +Version Control with Git +course [[^1]], which is © Software Carpentry and licensed +under Creative Commons BY 4.0. +Changes have been made from the original content. + + +### References + +[^1]: Ivan Gonzalez; Daisie Huang; Nima Hejazi; Katherine Koziar; + Madicken Munk (eds): "Software Carpentry: Version Control with Git." + Version 2019.06.1, July 2019, + https://github.com/swcarpentry/git-novice, + 10.5281/zenodo.3264950 diff --git a/_episodes/02_motivation.md b/_episodes/02_motivation.md new file mode 100644 index 0000000..d5121c8 --- /dev/null +++ b/_episodes/02_motivation.md @@ -0,0 +1,139 @@ +--- +layout: page +title: "Motivation: Why use Version Control Systems?" +order: 2 +session: 1 +length: 10 +toc: true +adapted: false +--- + +## Learning Objectives + +At the end of this episode you will be able to describe what version control +systems are and why they are useful. + + +## What is a version control system? + +A **version control system** is software that enables you to +record and manage the history of versions of files as they change. They are +typically used for tracking the changes to software source code, such as Python +files, R files, C/C++ source files, or other text-based documents like HTML, LaTeX, Markdown, etc. +With a version control system, you +make changes to a file (or files) as normal, but then use the version control +system to capture the updated version. You can attach comments to each captured +version to explain the changes made. In this way, you incrementally +build up a history of versions of the file(s). The version control system +allows you to view the evolution of files and 'roll back' to any previous +version you like. It also takes care of storing away this history out of your +day-to-day sight. + +So a version control system acts as a record-keeping device. This is useful, but +the real power of a version control system is that that they +_facilitate collaboration_ when multiple +people work on a set of files, such as when a team of people are developing +code. In particular, they provide a set of +tools that allow you to easily share your changes with others and, crucially, +_combine other peoples' changes with your own_. The tooling enables you to do +this in a structured way that makes combining changes transparent +and less error-prone. Furthermore, the histories of each person's changes are +shared with each other, so that the record of changes to files is not split out +amongst multiple person's computers. + + +## Why bother to use a version control system? + +There is, of course, a disadvantage to using a version control system: you need +to learn how to use it. Is it perhaps easier to use other methods to keep track +of versioning your files? + +Let's compare version control systems to a couple of other options. + +### Cloud-based synchronisation e.g. Google Drive, DropBox, OneDrive/SharePoint + +These days there are cloud-based services that allow you to sync your local +files with copies kept in the cloud: e.g. Google Drive, DropBox, OneDrive etc. +These services can keep a record of file versions and allow you to roll back to +previous versions, so why not just use these? + +- **Answer 1:** These kinds of features tend to capture versions + of files as they are saved and are more geared to recovery from e.g. + accidental deletion or modification. It is almost certain they won't give you an + organised 'chunking up' of the evolution of a file. For example, perhaps you + are fixing a bug and end up taking a day to fix it, saving the file dozens of + times while you try to fix it. This will likely lead to lots of small revisions + to files that are ultimately unhelpful and make finding a + meaningful previous version of the code more difficult. Besides this, the + log of versions of the file(s) probably won't have any helpful description to + help you understand the content of each version — you'll likely only get + a timestamp giving when the file was last modified. With a version control + system, you control the snapshots of a file's history and provide helpful + descriptions, so that a more helpful 'story' of the file's evolution is + recorded. + +- **Answer 2**: These services offer little to help with collaboration + on files (except perhaps files like word processing documents, spreadsheets + and the like). If you want to combine edits to a file from multiple people, you + need to do things like agree that only one person can work on the file at + once, which is cumbersome. They also don't give a way for you to quickly view the + changes that were made to a file by someone else. Version control systems + address both of these shortcomings. + + +### Multiple versions of files locally + +Have you ever created a folder of code that ends up looking something like +this? + +![Versioning software with chaotic file names]({{ site.url }}/images/folder-chaos.png) + +Sure, you can remember which of these files you need to use as you're in the +thick of developing your code. But what about when you come back to it a +month later? + +... Or 6 months later? + +... Or three years from now, when you've forgotten all +those little bits of working knowledge of the code, and you receive a question +from someone who, having 'just a +small query' about the validity of your findings, asks you to send them +the code used to generate the results? + +Which files would you send? + +Wouldn't you rather turn back to that folder and find this? + +![A clean folder of software]({{ site.url }}/images/folder-calm.png) + +(Note: the `.git` folder is particular to the version control system Git, +which you'll learn about in this course!) + +Even if you're much more disciplined about keeping versions of your files than +the chaotic example above, it's worth considering the following: + +* Your system probably doesn't help you much when collaborating with others, like + when you need to merge changes from others into your code. Version control + systems include tools to help with this. + +* If you work together with others on the same files, do they follow the same + conventions for keeping track of versions as you? If everyone is using the + same version control system, then this provides consistency of approach. + +* Let's face it, keeping up a discipline of manually versioning your files is a + drag, and will likely go out the window when the pressure of a deadline starts + biting. Using a version control system significantly reduces the effort + required to keep a good, orderly record of development, and to combine your + work with others'. Sure, it still requires discipline to use a version control system, + but like all good disciplines it _helps to make your life easier_. + In quite a short space of time, using a version control system just becomes + part of your rhythm of work. + + +## Note for the course + +In this episode we have talked about version control systems being used to +keep track of the evolution of files in general. Going forward, we will often +discuss the use of version control in the context of developing code for +software, which is arguably the most +common context in which version control systems are used. diff --git a/_episodes/03_git_vs_github.md b/_episodes/03_git_vs_github.md new file mode 100644 index 0000000..75e914f --- /dev/null +++ b/_episodes/03_git_vs_github.md @@ -0,0 +1,121 @@ +--- +layout: page +title: "Git vs GitHub" +order: 3 +session: 1 +length: 5 +toc: true +adapted: false +--- + +## Learning Objectives + +At the end of this episode you will be able to tell your friends and colleagues +what Git and GitHub are and describe how they are different. + + +## Git: our version control system of choice + +In the last episode we explained what version control systems are and why they +are useful. This course teaches you the basics of using a particular version +control system, called +Git. + +Git is one of the most popular and relied-upon version control systems used +today, both in research and commercially. Git is simply a piece of software that +you run on your computer. You can use it +directly from the command line, using the command `git`. + +> ### Terminals +> +> In this course we will work through examples with command line syntax that +> you would find on most Unix-style systems (MacOS or Linux). If you are using +> Windows and have followed the installation instructions, you will have +> installed _Git for Windows_. This comes with the _Git Bash_ program, which +> emulates a Unix Bash shell (e.g. it uses forward slashes `/` for path +> separators and comes with common Unix programs like `ls` for listing the +> contents of a directory). We recommend you use Git Bash to follow through the +> course. You can launch Git Bash by opening the Start menu +> and typing `Git Bash` to find the program. + + +If you have Git installed +on your machine, you can run it right now: open up a terminal and try running the following +command: + +``` bash +git --version +``` + +If you have Git installed, your output should looking something like this (your +version number may differ): + +``` output +git version 2.25.1 +``` + +Because Git is so popular, there is a lot of software that integrates with it, +which can lead to confusion about exactly what Git is. For example, +you may have used programs like Visual Studio Code, RStudio or PyCharm to write +your code. These additionally provide graphical user interfaces to help +developers interact with Git via 'point and click' while you work on code, +giving developers a more 'integrated' experience. But it's helpful to remember +that these programs are just using Git under the hood and that it's perfectly +possible to use Git without these. Indeed, it's best _not_ to rely on these +integrated facilities for using Git, because you may well come up against +situations in your work where you need to use Git in environments which force +you to use it at the command line, such as remote servers. + +Chances are that, at some +point, you will want to share your work, either with collaborators as the code is developed or +in order to publicise your work. On it's own, Git doesn't provide the means to +do this — for that, you also need somewhere to host a 'remote' version +of your code which others can access. Many web platforms have been created to +provide this service. They use Git as the core version control technology, while +providing additional layers of functionality to facilitate sharing and collaboration +with other developers. Examples of these platforms include +GitLab, +Codeberg and +GitHub. +It is possible to use Git completely 'locally'; that is, +without interacting over the internet with some remote service. This is +perfectly fine if you just want to version control your own software project +that you have no intention of sharing with anyone. + + +## Managing collaboration with GitHub + +As well as teaching you the basics of using Git, this course will give you an +introduction to using GitHub as a way of sharing your code and managing its +development. + +In some ways, the naming of GitHub is unfortunate, because it could easily sound +like it's Git but 'on the web'. But that's not really true and to think +of it in these terms can lead to confusion, especially early on. Remember that +_Git_ is a tool that software developers use as they write code on their machines. +_GitHub_ is a web +platform that makes it easy to share code and provides extra functionality to +support teams of software developers in their collaboration. Taking an analogy +from scientific research, Git is more +akin to a lab book that a scientist might use day-to-day to record what they +did that day, the results of experiments, etc., whereas GitHub sits more at the +level of planning and project management that a Principal Investigator would do +to ensure the project runs smoothly and everyone is kept on the same page. It +should also be noted that GitHub is not a replacement for Git. In fact, you will +typically interact with GitHub _via Git_ while you develop your code. + +The full suite of facilities that GitHub provides is multi-faceted and it is far +beyond the scope of this course for us to cover all of it. We will focus on +features that support: + +* Sharing your code within your development team and the wider world + +* Ways to keep track of proposed additions or improvements to a codebase (via + GitHub _issues_) and to ensure significant changes to the codebase are + integrated in a controlled way (via GitHub _pull requests_). + +If you feel somewhat hazy on exactly how Git and GitHub differ, then don't worry: +this should become clearer as we go through the course. For now, the key thing +to bear in mind is that they play different roles: Git for day-to-day +record-keeping while writing code, and GitHub for sharing and collaborating with +others. diff --git a/_episodes/04_configuring_git.md b/_episodes/04_configuring_git.md new file mode 100644 index 0000000..b51cf4c --- /dev/null +++ b/_episodes/04_configuring_git.md @@ -0,0 +1,264 @@ +--- +layout: page +title: "Setting up Git and GitHub" +order: 4 +session: 1 +length: 30 +toc: true +adapted: true +attrib_name: Version Control with Git - Setting Up Git +attrib_link: https://swcarpentry.github.io/git-novice/02-setup/index.html +attrib_copywrite: Software Carpentry +attrib_license: CC-BY 4.0 +attrib_license_link: https://creativecommons.org/licenses/by/4.0/ +--- + +## Learning Objectives + +By the end of this episode you will know how to set up Git and GitHub for use +in your projects. + + +## Setting up Git + +When we use Git on a new computer for the first time, +we need to configure a few things. Below are a few examples +of configurations we will set as we get started with Git: + +* Our name and email address. +* Our preferred text editor to use with Git. + +We will also want to set these settings _globally_, meaning they'll apply +whenever we use Git within a given user account on a specific computer. + + +### Username and email address + +On a command line, Git commands are written as `git `, +where `` is what we actually want to do and `` is additional +optional information which may be needed for the ``. To configure Git, +settings, we use the 'command' `config`. + +``` bash +$ git config --global user.name "Joe Bloggs" +$ git config --global user.email "joe.bloggs@example.net" +``` + +This user name and email will be associated with your subsequent Git activity, +which means that any changes pushed to GitHub (or another Git host server) +from here on will include this information. If you work on public repositories +with these services, then this information will be publicly visible. + +For this course, we will be interacting with GitHub 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. + +> #### Keeping your email private +> +> If you elect to use a private email address with GitHub, then use that same +> email address for the `user.email` value. It will look something like +> `nnnnnnnnn-username@users.noreply.github.com` where +> `nnnnnnnnn-username` is your username prepended with a numerical ID. + +The commands we just ran above only need to be run once: the flag `--global` tells Git +to use the settings for _every_ Git repository, in your user account, on this computer. + +You can check your global settings at any time: + +``` bash +$ git config --global --list +``` + + +### Setting a text editor + +Git will use a text editor installed on your computer when you need to write +'commit messages' (about which more later in the course). The default editor on +most operating systems is set to Vim which, while powerful, is difficult to +use if you're not used to it. You can configure Git to instead use something +you're more familiar with. We recommend trying *Nano* for Git usage: it works +at the command line, making it quick to write the short 'commit messages', but +is much simpler to use than Vim. You can change this at any time if you find you'd +prefer to use something else. + +> #### Git for Windows +> +> If you followed the recommendations in the +> [installation instructions for Git for Windows]({{ site.url }}/setup.html#windows) then +> Nano should already be the default editor used by Git. + +The following table shows how to set the default editor for Git for several popular +text editors. In some cases, you need to provide the path to the executable +program for the editor — this indicated as `path/to/executable-name` (if you +aren't sure what to enter for this, do some online searching or try a search +on your computer). + +| Editor | Configuration command | +|:-------------------|:-------------------------------------------------| +| Atom | `$ git config --global core.editor "atom --wait"`| +| nano | `$ git config --global core.editor "nano -w"` | +| BBEdit (Mac, with command line tools) | `$ git config --global core.editor "bbedit -w"` | +| Sublime Text (Mac) | `$ git config --global core.editor "'path/to/subl' -n -w"` | +| Sublime Text (Win) | `$ git config --global core.editor "'path/to/sublime_text.exe' -w"` | +| Notepad (Win) | `$ git config --global core.editor "path/to/notepad.exe"`| +| Notepad++ (Win) | `$ git config --global core.editor "'path/to/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"`| +| Kate (Linux) | `$ git config --global core.editor "kate"` | +| Gedit (Linux) | `$ git config --global core.editor "gedit --wait --new-window"` | +| Scratch (Linux) | `$ git config --global core.editor "scratch-text-editor"` | +| Emacs | `$ git config --global core.editor "emacs"` | +| Vim | `$ git config --global core.editor "vim"` | +| VS Code | `$ git config --global core.editor "code --wait"` | + + +### Default Git branch naming + +Git (2.28+) allows configuration of the name of the branch created when you +initialize any new repository. (We will cover *repositories* and *branches* later +in the course; for now, you can think of a repository as a place where files +for a project are kept and a branch just as a name for the development history +of the files in the repository.) + +By default, Git will create a branch called `master` whenever +you start a new repository. However, there is a move in the +software development community +to stop using this term in favour of more inclusive language, due to the overtones of +the racist practice of human slavery evoked by the term 'master'. Most Git +code hosting services have transitioned to using `main` as the default +branch; for example, any new repository that is opened in GitHub defaults +to using `main` for the name of the branch. + +At the time of writing, Git has not yet made the same change. For this course, +we will manually configure Git to use the same `main` branch name as most cloud +services. + +For versions of Git 2.28 or later, this can be achieved by setting the +`init.defaultBranch` setting to `main` globally: + +``` bash +$ git config --global init.defaultBranch main +``` + +For versions of Git prior to 2.28, the change can only be made on an individual +repository level and we will cover this in the episode on +[making repositories]({{ site.url }}/05_making_repos/index.html) later. + +> #### Exercise +> +> Set up Git the way you'd like it by configuring settings for: +> - Your username and password +> - Your preferred text editor +> - (Optional) Changing the default Git branch naming to `main`. If your version +> of Git is older than 2.28 then you won't be able to do this yet. + + +### Final notes on configuring Git + +#### Changing configuration + +You can change your configuration as many times as you want. Use the +same commands as above to choose another editor, update your email address, etc. + +#### Git Help and Manual + +Always remember that if you forget the subcommands or options of a `git` command, +you can access the relevant list of options typing `git -h`, or +access the corresponding Git manual by typing +`git --help`, e.g.: + +``` bash +$ git config -h +$ git config --help +``` + +While viewing the manual, remember the `:` is a prompt waiting for commands and +you can press Q to exit the manual. +More generally, you can get the list of available `git` commands and further +resources of the Git manual typing: +``` bash +$ git help +``` + +#### On line Endings + +You can sometimes run into issues when using Git if you (or your team) use +different machines when working on files. If you've followed the default +installation instructions (particularly Windows users who are using +*Git for Windows*) then you shouldn't run into problems, but we include a note +here in case you run into trouble. + +As with other keys, when you hit Enter / / Return +on your keyboard, your computer encodes this input as a character. +Different operating systems use different character(s) to represent the end of a line. +(You may also hear these referred to as newlines or line breaks.) +Because Git uses these characters to compare files, +it may cause unexpected issues when editing a file on different machines. +You can change the way Git recognizes and encodes line endings +using the `core.autocrlf` setting to `git config`. The following settings are +recommended: + +- **MacOS and Linux:** + ``` bash + $ git config --global core.autocrlf input + ``` +- **Windows:** + ``` bash + $ git config --global core.autocrlf false + ``` +You can read more about this issue +in the Pro Git book. + + +## Setting up GitHub credentials + +We're going to be using Git to communicate with GitHub. To do this, we need to +set up some authentication to enable us to do this securely. The approach we +will adopt in this course is to use GitHub +Personal Access Tokens (PAT). A PAT is +a way for some application or service (such as Git) to identify itself as being +authorised to interact with GitHub on your behalf. Part of setting up a PAT +involves specifying the scope of what an application using that PAT is allowed +to do on GitHub. PATs are generated via your GitHub account and then saved for +later use. + +> ### Look after your PATs! +> +> **You should treat PATs with the same level of care you would your GitHub +> account password. Store the PAT somewhere secure, such as in a password +> manager. If you ever suspect a PAT has been exposed, then you should +> delete the token and generate a new one.** + +> ### Note on classic tokens +> +> At the time of writing, GitHub is in the process of creating newer, so-called 'fine +> grained' personal access tokens. These provide more fine grained control, but are +> still in a developmental phase. The older, 'classic', PATs are sufficient for +> our needs and simpler to set up, so we'll use them throughout this course. + +To set up a PAT, follow the +instructions provided by GitHub for classic tokens. Note: + +- You will need to set an expiration time on your token. This is part of the + GitHub's security and we strongly suggest you don't select the _No expiration_ + option, however tempting it may be. You should get an email a few days before the + token expires reminding you to regenerate it. + +- As part of the process, you will need to select scopes for the token. + All that is needed for this course (and likely for your standard, day-to-day use + of Git) is to select the **repo** option: this will enable you to interact + with repositories you have been invited to work on. More information about + scopes can be found in the + GitHub documentation on OAuth scopes. + +- You can regenerate a PAT that has expired + by going to your _Personal access tokens (classic)_ as described + in the link above, selecting the affected token and then clicking on _Regenerate token_. + +- To delete a token (e.g. if you suspect it's been compromised), go to your + _Personal access tokens (classic)_ as described in the link above and then + click on _Delete_ next to the token. + +> ### Exercise +> +> Using the instructions on GitHub linked above, create a PAT and save it +> somewhere safe for later use in this course. diff --git a/_episodes/05_making_repos.md b/_episodes/05_making_repos.md new file mode 100644 index 0000000..24d3aac --- /dev/null +++ b/_episodes/05_making_repos.md @@ -0,0 +1,295 @@ +--- +layout: page +title: "Making Repositories" +order: 5 +session: 1 +length: 15 +toc: true +adapted: true +attrib_name: Version Control with Git - Creating a Repository +attrib_link: https://swcarpentry.github.io/git-novice/03-create/index.html +attrib_copywrite: Software Carpentry +attrib_license: CC-BY 4.0 +attrib_license_link: https://creativecommons.org/licenses/by/4.0/ +--- + +## Learning Objectives + +At the end of this episode you will be able to describe what a repository is +and how to create them, either by cloning an existing remote repository or +creating a new one locally from scratch. You'll also be able to create a +remote repository on GitHub. + + +## What is a repository? + +In version control systems, such as Git, a **repository** is a space where +your files live together with information about the version history of the files. +In Git, this repository can live either _locally_ (i.e. on your own computer) or +_remotely_ (somewhere other than your own computer). Remote repositories may +be hosted on another machine, such as an institutional server, or +on a cloud-based service, such as GitHub. + +It is perfectly possible to create a Git repository on your own computer and have +it exist in isolation. This allows you to keep a version history of files +that you develop within the repository, but doesn't provide a way to easily +share this developmental history with others, or collaborate with them on code. +By contrast, the most common way that a person uses Git is to have a local repository +that is linked to a remote repository. A typical example here is +where there is a remote repository on GitHub and you have a local version of the +repository on your own computer. You keep the remote repository up-to-date by +'pushing' updates you make to your local repository to it (we will look more at +this later in the course). Someone else can then obtain a copy of your work +by getting it from the remote repository. + +We'll see later in this course that a whole team of developers can contribute +to a shared codebase by working with a common remote repository. In this set up, +the remote repository acts as a +central location for receiving updates from all team members, and these updates +are propagated throughout the team by the individual members keeping +their own local versions of the repository up-to-date with the remote one. + + +## Creating repositories + +So how do you create repositories? We'll look at two different +ways to do this: + +1. Creating a remote repository on GitHub. + +2. 'Cloning' a remote repository to create a local version on your own computer. + +Case 2 is probably the most immediately helpful for Git novices, allowing them +to get working with a repository that has already been set up by somebody else. +Case 1 is, of course, helpful if you find yourself in the situation of needing +to create a remote repository on GitHub... And it gives us something +to demonstrate case 2 with! + +We'll also briefly cover how you can create a new repository on a computer +without using a platform like GitHub. You're less likely to come across this in +practice, but we cover it for completeness. + + +### Creating a remote repository on GitHub + +Below we outline simplified steps for creating a new repository on your personal +GitHub account, which will be adequate for this course. Full instructions for +creating repositories on GitHub can be found at +. +In what follows, accept the default options on GitHub unless we specify +otherwise. + +- **Step 1:** Log into your GitHub account. + +- **Step 2:** Click on the '+' drop-down menu in the top right-hand corner and + select _New repository_. + +- **Step 3:** Enter the name for your repository. + - This should be short and meaningful. Only use characters that you would use + for naming folders on your own computer. + +- **Step 4:** Choose whether to make your repository publicly visible or + private. We suggest making any repositories you create for this course + _private_, so that you can practice out of the gaze of the internet. + - _Public_ repositories can be viewed by _anyone_ on the internet, even those + who don't have a GitHub account. _Private_ repositories are only visible by + you and people that you specifically invite. + +- **Step 5:** In the section _Initialize this repository with:_, select the + _Add a README file_ option. A readme file provides useful information to new + users of the repository, explaining what the repository is for and generally + helping them get started with using the code in it. This is not necessary, but + it's good practice to include one whenever you create a new repository. + +- **Step 6:** Click on _Create repository_ to finish and create the repository. + +Immediately after creating the repository you'll be taken to the repository's +main page on GitHub. For now, the main thing to look at is the content under the +_Code_ tab in the top left hand corner, which gives you a view of the contents +of the repository. (There won't be much in there to begin with, of course.) + +In the future, you can return to the repo by going to your main +GitHub account page and finding it under the _Repositories_ tab. Notice that +the URL for the repository has the format `https://github.com/user-name/repo-name` +where `user-name` is your GitHub username and `repo-name` is the name you gave +the repository. + + +> #### Further options for GitHub repositories +> +> Let's take a moment mention a few extra things about creating repositories on +> GitHub. None of these points are essential for moving forward, but you'll likely +> come into contact with them as you use GitHub more: +> +> * When creating the repository, there was the option to initialise the +> repository with some extra files: +> - A `.gitignore` file. This is a particular file that can be used to tell Git +> about files that it should _not_ keep a version history for. We will see +> this later in the course. +> - A licence file. If you intend to make your work publicly available, then +> it's important to include a licence file which both allows others to use +> your work and specify the terms for their use. You can read more about this +> important topic on GitHub +> and on the Software Sustainability Institute's website. +> +> * If you belong to an _Organisation_ on GitHub and have the correct +> permissions, then you will be able to create repositories under the +> organisation instead of your own user account. See GitHub's +> overview on organisations +> for more information. + + +### Cloning a remote repository + +We mentioned above that the most common way of using Git is to have a local +repository that is linked to a remote repository. In Git parlance, the local +repository is created by **cloning** the remote repository. + +Any remote repository will have a URL which specifies its location — you can +recognise them in that they end with `.git`. You need this URL to clone the +remote repository. + + +> #### Example: GitHub repositories +> +> The URL for a remote repository on GitHub can be found by going to the +> repository's main webpage. Under the _Code_ tab, there is a green +> drop-down button, also labelled _Code_. Click this and copy the HTTPS address +> listed under the _Clone_ section — this is the URL for the remote repository. +> +> (Strictly speaking, this is the URL that uses the HTTPS protocol; other +> protocols, such as SSH, are available to use instead if you prefer. We'll +> use HTTPS for this course because it doesn't require extra set-up.) + +To create a local 'clone' of the remote repository, navigate in the command-line +to a folder where you'd like to put your repository. Then run + +``` bash +git clone +``` + +This will create a new folder with the same name as the remote repository and +download all the repository's contents into it. + + +> #### GitHub authentication +> +> If the remote repository is private, you may be prompted to enter your +> GitHub username and a password. Use your Personal Access Token +> for the password, not your GitHub account password. + +If you instead want to put the contents of the repository into a specific +folder, then use the form + +``` bash +git clone path/to/folder +``` + +> #### Example +> +> Joe Bloggs created a remote repository on GitHub called `test-repo` +> and the remote repository's URL is `https://github.com/jbloggs9999/test-repo.git`. +> On his Mac, he navigates to the folder `~/Documents/Repositories` and runs +> +> ``` bash +> git clone https://github.com/jbloggs9999/test-repo.git +> ``` +> +> This creates a new folder called `test-repo` within his `Repositories` folder, +> which contains the local, cloned repository. If he instead had run +> +> ``` bash +> git clone https://github.com/jbloggs9999/test-repo.git my-test-repo-clone/ +> ``` +> +> then this would have put the contents of the repository into the folder +> `~/Documents/Repositories/my-test-repo-clone`. + + +### Creating a new repository on your computer + +We can also create a new repository from scratch on our computer. Since there +isn't any existing remote repository to clone from, we use a different command: + +``` bash +git init path/to/new/repo +``` + +For example, running `git init foobar` will create a folder `foobar` in +our current working directory, which contains the new Git repository. + +Using `git init` creates a repository that is contained on the host computer +only. This can be used if you just want to keep track of your work, with no +interest in sharing it with others or syncing it with a remote version. Other +than that, `git init` can also be used for manually setting up a repository +that serves as a remote repository. This might be done on a +departmental server so that the remote repository is contained on the server, for example. +We won't say more on how to do this in this course, but if you are interested +then see the section on 'bare' repositories on +[Atlassian's tutorial page for `git init`](https://www.atlassian.com/git/tutorials/setting-up-a-repository/git-init). + + +> #### Renaming the default branch +> +> In the previous episode, we discussed changing the name of the default branch +> from `master` to something else, e.g. `main`. For Git versions 2.28 and later, +> the configuration can be set so that new repositories have this new name by +> default, see the +> [Setting up Git and GitHub]({{ site.url }}/04_configuring_git/index.html#default-git-branch-naming) +> episode. If the version of Git you are +> using is earlier than 2.28, then this needs to be done for each repository +> individually. After creating the repository with `git init`, run the following +> command: +> +> ``` +> $ git checkout -b main +> ``` + + +## What does a local repository look like? + +We'll conclude this episode with taking a peek into an example repository that has been +created locally, whether this be via cloning or using `git init`. + +Let's consider an example, looking at the more organised folder of work +introduced in the episode [Git vs GitHub]({{ site.url }}/03_git_vs_github/index.html). +Below is a screenshot of the repository on a Windows machine; note that we've +enabled the display of 'hidden' files and folders, i.e. those whose names +begin with a period. + +![A simple Git repository on Windows]({{ site.url }}/images/basic-repo.png) + +And here is the same repository displayed on a Linux operating system, using the +command line; note we are displaying hidden files using the `-a` option +in the `ls` command: + +``` +$ ls -a awesome-research-done-right/ +. .. .git data plot_results.py process_geo_data.py run-everything.py simulate.py simulation-engine +``` + +It is common for people to refer to the top level folder of the repository as the +**root folder**; in the above example, +`awesome-research-done-right` is the root folder. (Note: this is distinct from the +'root' folder `/` on Unix systems that you might have heard of.) By +default, Git will keep track of the version history of _all_ files located within the +root folder or subfolders thereof. Where exactly does Git keep all the +versioning information? Answer: it's kept in the `.git` folder, which you may +have spotted in the example outputs above. This is a folder that Git creates +automatically when the repository is created. + + +> ### Warning! +> +> As a general rule, don't go modifying the files in the `.git` +> folder within a repository. Accidentally modifying a file / subfolder will likely +> mess up the version history of the repository. There are files in the +> `.git` folder that are suitable for direct modification, allowing users to +> customise their interaction with Git, but this +> comes under more advanced use that is beyond the scope of this course. +> +> Our advice: don't poke around the `.git` folder, unless you are a confident +> Git user and need to customise Git (even then, follow a reputable tutorial or +> guide the first time). + + \ No newline at end of file diff --git a/_episodes/06_example_repo.md b/_episodes/06_example_repo.md new file mode 100644 index 0000000..f5d1efb --- /dev/null +++ b/_episodes/06_example_repo.md @@ -0,0 +1,80 @@ +--- +layout: page +title: "An Example Repository" +order: 6 +session: 1 +length: 15 +toc: true +adapted: false +--- + +## An example repository + +To help you get familiar with working with Git and GitHub, we encourage you to +work through an example repository, which you will populate through exercises +that appear in episodes throughout this course. We'll use the repository to +begin building up a cheatsheet of Git commands, some tips on good practice and +links to further resources. + + +### Markdown + +We'll be writing the material for this example repository using +Markdown. +Markdown is a simple markup +language that is well suited to writing documentation for software, or +communicating about code. Many applications, such as the +VS Code text editor, +can understand and render Markdown files in a visually appealing way. +You write Markdown in files with a `.md` extension and the syntax is such that even +if you just view a Markdown file as a text file, it looks neat and tidy. +Beyond this, GitHub has support for understanding Markdown throughout its +website and automatically renders Markdown files. As a case in point, the +README file it can generate when you create a new repository is a Markdown +file. It doesn't take long to get up to speed with Markdown and we feel it's +worth the effort to learn. + +One slight complication is that there are different _flavours_ of Markdown i.e. +variations on the syntax. The basic syntax +is pretty much uniform across different +flavours, but different flavours provide different ways to extend the basic +syntax to handle more complicated features (such as tables). We'll use the +GitHub Flavoured Markdown, since (surprise!) this is what is used on GitHub. You +can find a pretty comprehensive introduction to the syntax of GitHub Flavoured +Markdown at +. + +It isn't necessary to know Markdown to follow the examples in this course — we'll +point out bits of Markdown syntax as we go. + +> #### Previewing in VS Code +> +> If you're using VS Code as your text editor, you can preview a rendered Markdown +> document by opening the Command Palette (_View_ > _Command Palette..._), +> searching for _Markdown: Open Preview_ and selecting this command. There's also +> and option to open the preview side-by-side with the Markdown source document, +> which is useful when editing. +> +> If you're using VS Code to view Markdown documents, note that not all aspects +> of GitHub Flavoured Markdown will render correctly in VS Code. For example, task lists are not +> rendered in the VS Code Markdown viewer. + + +## Creating the repository + +Our first exercise is to create this repository on GitHub and clone a local +version. + + +### Exercise + +Using the instructions in the [_Making Repositories_ episode]({{ site.url }}/05_making_repos/index.html): + +1. Create a new repository on GitHub called `git-good-practice`. + When doing this, have GitHub generate a readme file for you as part of the + repository creation, but otherwise accept the default options. We suggest + creating this as a _private_ repository in your personal GitHub account. + +2. Clone the repository just created on GitHub to your own computer, making + sure the repository is cloned into a folder called `git-good-practice` + (note that this is the default behaviour of `git clone`.) diff --git a/_episodes/07_recording_changes.md b/_episodes/07_recording_changes.md new file mode 100644 index 0000000..78ef8cd --- /dev/null +++ b/_episodes/07_recording_changes.md @@ -0,0 +1,591 @@ +--- +layout: page +title: "Recording Changes" +order: 7 +session: 1 +length: 40 +toc: true +adapted: true +attrib_name: Version Control with Git - Tracking Changes +attrib_link: https://swcarpentry.github.io/git-novice/04-changes/index.html +attrib_copywrite: Software Carpentry +attrib_license: CC-BY 4.0 +attrib_license_link: https://creativecommons.org/licenses/by/4.0/ +--- + +## Learning objectives + +By the end of this episode you will be be able to record changes made to files +using the `git add` and `git commit` commands. You will understand the difference +between these commands and the general _modify-add-commit_ workflow for building +up a version history of files in Git. + + +## Viewing the status of a repository + +So, we have a new repository, either a clone from a remote repository or a +brand new, empty one. It's time to get to work adding content to it. But before +we do that, let's cover one of the simplest, yet most useful, Git commands: +`git status`. + +The `git status` command gives you information about the current state of work +when working with a Git repository. Let's take a look at an example with our recently cloned +`git-good-practice` repository. We first need to make sure that we're located +in the root folder of the repository. In the example below, this is contained +within the parent folder `~/repositories`, so we first change directories with +`cd` and remind ourselves of the contents: + +``` +$ cd ~/repositories/git-good-practice +$ ls +README.md +``` + +Currently there's just a single readme file. Recall that the `git-good-practice` +folder actually also contains the hidden folder `.git`, which we would have also +seen if we'd used `ls -a` instead of just plain old `ls`. Now we can check the +status of the repository: + +``` +$ git status +On branch main +Your branch is up to date with 'origin/main'. + +nothing to commit, working tree clean +``` +Let's consider what the output means: + +- The first two lines refer to a *branch* called `main`, and how it's up-to-date + with another branch called `origin/main`. For now, + you can regard these lines as saying that our local version of the repository + is in sync with the remote version. (This is not the whole story and + is, at best, a partial truth. We'll uncover more about what this really means later + in the course when we learn about branches more generally.) + +- The line `nothing to commit, working tree clean` is of more immediate interest. + This is Git's way of saying that it hasn't identified any changes to the + contents of the repository ('working tree clean'), so there are no new changes + that could be recorded in the repository's history ('nothing to commit'). + +- Finally, note that `git status` only gives us information about *changes* to + the contents of the repository. It doesn't spell out the whole contents of + the repository like `ls` would. For example, we know that the repository + contains the file `README.md`, yet it doesn't feature in + the output of `git status` because there aren't any (new) changes to it. + +For our purposes, you can think of the **working tree** as the contents of the +repository, just like you're used to thinking of files within a folder or +subfolders. Git is able to detect changes to files in the working tree, including +those that are in subfolders of the repository root folder (or sub-subfolders, etc.) + + +> ### Run `git status` often +> +> We're going to flag here that you should get into the habit of running +> `git status` often. It's the primary way of seeing at a glance what state +> your working tree is in and how it differs (or not) with what was last +> recorded in the repository. + + +## Adding and committing files + +Let's make some changes to the repository. First, we'll create a new Markdown +file called `Git-cheatsheet.md`, for us to record key Git commands as we go. +Running `git status` now shows us: + +``` +$ git status +On branch main +Your branch is up to date with 'origin/main'. + +Untracked files: + (use "git add ..." to include in what will be committed) + Git-cheatsheet.md + +nothing added to commit but untracked files present (use "git add" to track) +``` + +The 'Untracked files:' bit indicates that Git has spotted a new file which it +has no record of. Before going further, let's add some content to the cheatsheet +about `git status`: + +``` +# Git Cheatsheet + +*Note: run commands from within a Git repository* + + +## Checking the state of files (do this often!) + +`git status` — Checks the state of the working tree in a Git repository. + +``` + +> ### Markdown syntax +> +> * Hash symbols (`#`) are used to denote the document title and headings. One +> hash `#` denotes the document title, two hashes `##` indicates a section heading, +> three hashes `###` indicates a sub-heading, etc. +> +> * Wrapping text with asterisks (`*`) will emphasise text i.e. set it in italics. +> You can also wrap the text in underscores (`_`) e.g. `*This* is in italics, +> so is _this_.` +> +> * Wrapping text in backticks (`` ` ``) is used to display code. It won't be +> formatted like regular text. Compare: +> - Wrapped in backticks: `` `foo _bar_` `` renders as `foo _bar_` +> - As regular text: `foo _bar_` renders as foo _bar_ +> +> * Extra spaces and tabs are just treated as a single space. Paragraphs must +> have a blank line between them to be rendered on different lines. E.g. +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +>
Markdown codeRendered output
+> No       extra spaces here +> +> No extra spaces here +>
+> +> These lines are in
+> the same paragraph +>
+>
+> These lines are in +> the same paragraph +>
+> +> These lines are in
+>
+> different paragraphs
+>
+>
+>

These lines are in

+>

different paragraphs

+>
+ +After adding the above text to `Git-cheatsheet.md` file and saving our changes, +we now tell Git to start tracking changes to this file by using the `add` +command: + +``` +$ git add Git-cheatsheet.md +``` + +Let's see what `git status` now tells us: + +``` +$ git status +On branch main +Your branch is up to date with 'origin/main'. + +Changes to be committed: + (use "git restore --staged ..." to unstage) + new file: Git-cheatsheet.md +``` + +The difference between this status and the status before we did `git add` on our +cheatsheet is the 'Changes to be committed:' bit. Git has now recognised that +it has a new file, called `Git-cheatsheet.md`, to keep track of. It Git parlance, +`Git-cheatsheet.md` has become a **tracked** file. But it hasn't +yet stored the new version of the file as part of its history. To do that, we +need to run another Git command, called `commit`: + +``` +$ git commit +``` + +Upon entering this command, the text editor we configured for Git earlier springs into life, opening up a file with some pre-defined text and leaving space at the top for us +to write in. (The lines preceded by hashes are comments that are ignored by Git.) + +``` + +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# +# On branch main +# Your branch is up to date with 'origin/main'. +# +# Changes to be committed: +# new file: Git-cheatsheet.md +# +``` + +As you can see, this file is for writing a **commit message**. This is a message +that tells people about changes that are being committed to the repository. +It should briefly, but clearly, describe the main changes that have been made. We +add our commit message at the top of the opened file: + +``` +Create a cheatsheet document + +Start the document by adding an entry for Git's status command. + +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# +# On branch main +# Your branch is up to date with 'origin/main'. +# +# Changes to be committed: +# new file: Git-cheatsheet.md +# +``` + +Once we've written our message, we save the document (**don't** change the file +name!) and close it. The `git commit` command finishes and we get a little +summary message about what was just committed (note the first line of our +commit message is included): + +``` +$ git commit +[main 17912ce] Create a cheatsheet document + 1 file changed, 8 insertions(+) + create mode 100644 Git-cheatsheet.md +``` + +When we run `git commit`, +Git takes everything we have told it to save by using `git add` +and stores a copy permanently inside the special `.git` directory. +This permanent copy is called a **commit** (or **revision**). + +> ### Best practice: commit messages +> +> Good commit messages +> start with a brief (usually < 50 characters) statement about the +> changes made in the commit. Generally, the message should complete the sentence +> "If applied, this commit will [_commit message here_]". +> If you want to go into more detail, add a blank line between the summary line +> and your additional notes. Use this additional space to explain why you made +> changes and/or what their impact will be. Avoid uninformative messages such as +> "small tweaks" or "updates" — write what will be useful for others to read +> (which includes yourself in one year's time). + + +If we now run `git status` again, we get the following: + +``` +$ git status +On branch main +Your branch is ahead of 'origin/main' by 1 commit. + (use "git push" to publish your local commits) + +nothing to commit, working tree clean +``` + +Git is now telling us that: + +* There are no further changes in the repository to record + ('nothing to commit, working tree clean'). + +* The new version of the repository has been recorded in a commit ("Your branch + is ahead of 'origin/main' by 1 commit.") The "ahead of + 'origin/main'" bit indicates that our local repository now has new snapshots + that aren't recorded in the remote repository. We'll discuss this in a later + episode, so just focus on the "1 commit" bit for now. + + +## Modify-add-commit + +The example above alludes to the idea that developing files in Git involves +iteratively going round a three step cycle: + +1. _Modify_ the files in your repository. + +2. _Add_ the changes you want to record. + +3. _Commit_ these changes to the repository's history. + +This _modify-add-commit_ cycle is the bread-and-butter of using Git and it will +very soon become second nature to you. + +Before continuing, we want to mention another piece of terminology relating to +the `add` command. In Git parlance, applying `git add` to a file +**stages** the changes in that file, ready for committing. To allow for this, +Git has a special **staging area** (also called the **index**) where it keeps +track of things that should go into the next commit. It might help to remember +these terms by thinking of `git add` as 'setting the stage' for the next commit. + +> ### Best practice: commit little and often +> +> A commit is much easier to digest if it contains few changes. In fact, you +> should aim for each commit to capture one conceptual change to your work that +> can stand alone. This will make the history of your files' development much easier +> to follow. A good rule of thumb: a commit should capture a change that +> you can describe in about 50 characters or fewer, potentially with extra +> explanation in the commit message if needed. Examples (with commit message): +> +> * Adding a new function to read in some sequencing data ('_Add a function to +> read in sequencing data_'). +> * Updating a configuration file to include the setting required for a particular +> experiment ('_Change settings for experiment A simulation_' — the rest of the commit +> message may then give more detail on what these settings are). +> * Giving a variable a better name, which may be done across multiple files in +> the same commit ('_Rename input variable to a more descriptive name_'). +> * Adding this box about best practice for commit ('_Add content about best +> practice for commits_'). +> +> This is something you gain a feel for as you use Git more and study other +> developers' work. + + +## Selective staging + +Let's make some more changes to our example repository, in a way that +demonstrates the flexibility afforded by separating out the 'add' and 'commit' +steps. + +We'll first modify `Git-cheatsheet` to include a note about how to use +`git add` for staging changes to files. +Note that, although we've only seen an example of adding changes to a single file, we +can actually add changes to multiple files by listing them out when running +`git add`, like this: + +``` +git add path/to/file1 path/to/file2 path/to/file3 ... +``` + +So we add the following lines to `Git-cheatsheet.md`: +``` +## Adding / committing changes + +`git add ` — Stages changes in the ``, ready for committing. + +``` + +However, we've also seen some tips on good practice about commits and commit +messages. So let's create a new file, called `Commit-good-practice.md` and record +what we learnt about commit messages: + +``` +# Best practice when committing + +## Commit messages + +[Good commit messages](https://chris.beams.io/posts/git-commit/) +start with a brief (usually < 50 characters) summary statement about the +changes made in the commit, with more explanation given in a new paragraph if +required. Generally, the summary should complete the sentence "If applied, this +commit will [_commit message here_]". + +Avoid uninformative messages such as "small tweaks" or "updates" — write what +will be useful for others to read. + +``` + +> ### Markdown syntax +> +> Hyperlinks to external URLs are included by putting the text of the hyperlink +> in square brackets, immediately followed by the URL of the link in parentheses +> (with no space between the square brackets and parentheses). To just include +> a URL as its own hyperlink, just place it between angle brackets. Examples: +> +> * `[Good commit messages](https://chris.beams.io/posts/git-commit/)` renders +> as the hyperlinked text +> [Good commit messages](https://chris.beams.io/posts/git-commit/). +> +> * `` renders as +> . + +Let's now check the state of the working tree: + +``` +$ git status +On branch main +Your branch is ahead of 'origin/main' by 1 commit. + (use "git push" to publish your local commits) + +Changes not staged for commit: + (use "git add ..." to update what will be committed) + (use "git restore ..." to discard changes in working directory) + modified: Git-cheatsheet.md + +Untracked files: + (use "git add ..." to include in what will be committed) + Commit-good-practice.md + +no changes added to commit (use "git add" and/or "git commit -a") +``` + +Git has noticed that: + +* The `Git-cheatsheet.md` file has been modified, but it's not yet been 'staged' + for committing i.e. it's not been added to the set of changes to include in the + next commit. (Note the output under the section 'Changes not staged for commit:'.) + +* There is a new file `Commit-good-practice.md`, which is currently not being + tracked because we haven't run `git add` on it. + +At this point, we could run `git add Git-cheatsheet.md Commit-good-practice.md` +to add both of these files, ready to commit with `git commit`. However, the +changes made to `Git-cheatsheet.md` are about using `git add`, whereas +the content of the new file `Commit-best-practice.md` is all about commits. So +it would instead be better to separate these changes out: +first commit the material about `git add` in the cheatsheet, then commit the +material about best practice with commit messages. Come to think of it, +we could extend the cheatsheet with a note about `git commit` along the way: this +would be a natural accompaniment to the `Commit-good-practice.md` file. + +First thing's first: we commit only the cheatsheet with it's material about +using `git add`. We apply `git add` to `Git-cheatsheet.md`, then check the +status of the repository: + +``` +$ git add Git-cheatsheet.md +$ git status +On branch main +Your branch is ahead of 'origin/main' by 1 commit. + (use "git push" to publish your local commits) + +Changes to be committed: + (use "git restore --staged ..." to unstage) + modified: Git-cheatsheet.md + +Untracked files: + (use "git add ..." to include in what will be committed) + Commit-good-practice.md +``` + +`Commit-good-practice.md` is still not being tracked, but now the modifications +made to `Git-cheatsheet.md` have been staged, ready to be committed (as indicated +by the 'Changes to be committed:' part of the output). + +Next we'll commit the change to `Git-cheatsheet.md`, using the message +"Add entry about staging files with 'git add'". To speed things up a bit, we can +use the optional argument `--message` (equivalently, `-m`) to record use this +commit message without opening up a text editor, like so: + +``` +$ git commit -m "Add entry about staging files with 'git add'" +[main ad56194] Add entry about staging files with 'git add' + 1 file changed, 5 insertions(+) +``` + +Having committed just the changes to `Git-cheatsheet.md`, we see that Git still +recognises it has an untracked file in `Commit-good-practice.md`: + +``` +$ git status +On branch main +Your branch is ahead of 'origin/main' by 2 commits. + (use "git push" to publish your local commits) + +Untracked files: + (use "git add ..." to include in what will be committed) + Commit-good-practice.md + +nothing added to commit but untracked files present (use "git add" to track) +``` + +We now take the opportunity to add an cheatsheet entry about the `commit` +command (under the 'Adding / committing changes' section): + +``` +`git commit` — Commit changes to the repository that have been staged with + `git add`. + +``` + +We now again have two sets of changes that have yet to be staged, one to the +cheatsheet and the other to the as yet still untracked `Commit-good-practice.md`. +So, finally, we now bank these changes in a single commit; first we stage them +with `git add`: + +``` +$ git add Git-cheatsheet.md Commit-good-practice.md +$ git status +On branch main +Your branch is ahead of 'origin/main' by 2 commits. + (use "git push" to publish your local commits) + +Changes to be committed: + (use "git restore --staged ..." to unstage) + new file: Commit-good-practice.md + modified: Git-cheatsheet.md +``` + +Having checked with `git status` that each file has indeed been staged, we +go ahead and perform the commit. The commit message we use is the following: + +``` +Add material on committing + +This includes both an entry for 'git commit' in the cheatsheet +and also material on good practice for commit messages in a new +'good practice' document. +``` + +Since this is a longer message (in particular, featuring line breaks) we use +the default `git commit` to use a text editor: + +``` +$ git commit +[main 34c19f2] Add material on committing + 2 files changed, 15 insertions(+) + create mode 100644 Commit-good-practice.md +``` + +If we wanted, we could now verify that we have no more changes outstanding by +another call to `git status`. + + +## Review + +At this point, you are hopefully starting to get an appreciation for why there +are two separate steps required to record changes to files in a +repository. Git insists that we +identify which files we want to commit, via `git add`, +before actually committing anything. If you think of Git as taking snapshots of +changes over the life of a project, +`git add` specifies *what* will go in a snapshot (putting things in the staging +area), and `git commit` then *actually takes* the snapshot, making a permanent +record of it (as a commit). This allows us to commit our +changes in stages and be selective in what we capture, so that changes are +recorded in logical steps rather than in large batches. + +To summarise, there are three key 'spaces' to be aware of when working with files +in Git: + +* The working tree — modifications that have not been staged with `git add` + +* The staging area (a.k.a index) — contains changes that have been staged + with `git add` but not yet committed with `git commit`. + +* The repository — a permanent record of changes (commits) that have been + committed with `git commit`. + +`git add` moves changes from the working tree to the staging area, and `git commit` +'seals the deal' by moving changes from the staging area to the repository. This +process is captured in the following diagram. + +![The Git Commit Workflow](https://swcarpentry.github.io/git-novice/fig/git-committing.svg) + +The Git Commit Workflow +_image is © Software Carpentry and reused under +CC-BY 4.0. +It's taken from Version Control with Git – Tracking Changes._ + +> ### Exercise +> +> Using the modify-add-commit cycle, add more content to the cheatsheet and commit +> good practice documents, by adding +> an entry in the cheatsheet about the `--message` / `-m` option for `git commit` +> and including a section on 'committing little and often' in the `Commit-good-practice.md` +> document. Try practising 'selective staging' when you do this: modify both files +> to begin with, but then commit the changes one file at a time by using `git add` +> selectively. diff --git a/_episodes/08_history_and_changes.md b/_episodes/08_history_and_changes.md new file mode 100644 index 0000000..c06218a --- /dev/null +++ b/_episodes/08_history_and_changes.md @@ -0,0 +1,461 @@ +--- +layout: page +title: "Viewing History and Changes" +order: 8 +session: 1 +length: 30 +toc: true +adapted: true +attrib_custom: > + Material other than code snippets and example programs is licensed under + Creative Commons BY 4.0. + It has been adapted from Version Control with Git - Tracking Changes + and Version Control with Git - Exploring History, + which are © Software Carpentry and licensed under CC-BY 4.0. +--- + + +## Learning objectives + +By the end of this episode, you will know how to view a history of the commits +that have been made to a repository. You will also be able to examine the exact +changes that were made to files between different commits in a repository, as +well as changes that have yet to be committed. + + +## Viewing repository history + +There's little point in keeping a history of changes to files in a repository if +we can't view it. We can view a record of the commits made in a repository using +the `git log` command. If you completed the exercise at the end of the last +episode, [Recording Changes]({{ site.url }}/07_recording_changes/index.html), then +running `git log` from within the `git-good-practice` repository should look +something like the following: + +``` +commit 46b11e612128e68a9d558be1bcaa82bbdaac34ab (HEAD -> main) +Author: Joe Bloggs +Date: Tue Feb 7 16:47:21 2023 +0000 + + Add advice on committing little and often + +commit ecbf67e161e805a3183ebc84eb7d39c229a78451 +Author: Joe Bloggs +Date: Tue Feb 7 16:46:54 2023 +0000 + + Add entry for 'git commit' with '-m' option + +commit 34c19f2dd01c42fa2981520ca436bde5378979cb +Author: Joe Bloggs +Date: Tue Feb 7 16:14:14 2023 +0000 + + Add material on committing + + This includes both an entry for 'git commit' in the cheatsheet + and also material on good practice for commit messages in a new + 'good practice' document. + +commit ad56194133fcac4f65d236260f372665fbec605b +Author: Joe Bloggs +: +``` + +> ### Paging the Log +> +> When the output of `git log` is too long to fit in your screen, +> Git uses a program called a _pager_ to split it into pages of the size of your screen. +> When this pager is called, you will notice that the last line in your +> screen is a `:`, instead of your usual prompt. +> +> * To get out of the pager, press Q. +> * To move to the next page, press Spacebar. +> * To search for `some_word` in all pages, +> press / +> and type `some_word`. +> Navigate through matches pressing N. + +The log contains one entry for each commit. The commit messages for the +commits are included, as well as details of who made the commit. The name and email address +are those that were given when configuring Git (see the episode +[Setting up Git and GitHub]({{ site.url }}/04_configuring_git/index.html)). + +In addition, each commit has a unique **identifier** associated to it, which is the long +random-looking string next to each commit. (The identifiers for your +commits may differ from those above.) We can refer to commits by their +identifiers within Git. As we'll shortly see, commits can also be identified via +their **short identifier**, which is just the first 7 characters of the usual +identifier. + +Git also has a way of referring to the current, or most recent, commit: this is +called `HEAD`. In the above output, `HEAD` refers to the commit with message +"Add advice on committing little and often" (as indicated by `(HEAD -> main)`). + + +### Limiting log output + +To avoid having `git log` cover your entire terminal screen, you can limit the +number of commits that Git lists by using `-n`, where `n` is the number of +commits that you want to view. For example, if you only want information from +the last commit you can use `git log -1`: + +``` +$ git log -1 +commit 46b11e612128e68a9d558be1bcaa82bbdaac34ab (HEAD -> main) +Author: Joe Bloggs +Date: Tue Feb 7 16:47:21 2023 +0000 + + Add advice on committing little and often +``` + +You can also reduce the quantity of information using the `--oneline` option: + + ``` +$ git log --oneline +46b11e6 (HEAD -> main) Add advice on committing little and often +ecbf67e Add entry for 'git commit' with '-m' option +34c19f2 Add material on committing +ad56194 Add entry about staging files with 'git add' +17912ce Create a cheatsheet document +3917168 (origin/main, origin/HEAD) Initial commit + ``` + +Note that, in this format, each commit has its short identifier displayed. +You can also combine the `--oneline` option with others. For example, to view +just the last 3 log entries on single lines: + +``` +$ git log --oneline -3 +46b11e6 (HEAD -> main) Add advice on committing little and often +ecbf67e Add entry for 'git commit' with '-m' option +34c19f2 Add material on committing +``` + +## `git diff`: viewing changes + +One of the key features of Git is being able to see the changes that +have been made to files when working in a Git repository, not just a record of +the commits. The `git diff` command gives us access to this information. +Like many Git commands, `git diff` can take arguments in several different +formats, depending on things like the optional arguments used. We'll focus on +two basic use cases of `git diff`, considering various shortcut forms along the +way: + +* `git diff ` for viewing differences in files between + particular commits. + +* `git diff ` and `git diff --staged ` for viewing changes to + files that have yet to be staged or, in the second form, yet to be committed. + + +## Differences between commits + +Let's first look at how to examine file changes +that have been made to go from one commit to another. The general form of +the command to do this is: + +``` +git diff +``` + +Commits should be referred to by their identifiers (either their normal or short +formats). The order that the commits are specified matters: in the above, the +output will describe the changes that need to be applied to `` to get +``. The `` argument can be a single file or list of multiple +files. + +As an example, based on the full one-line log given above, let's look at the +changes required to go from commit +`ad56194` (with message "Add entry about staging files with 'git add'") to commit +`34c19f2` (with message "Add material on committing"), for each of the files +`Git-cheatsheet.md` and `Commit-good-practice.md`: + +``` +$ git diff ad56194 34c19f2 Git-cheatsheet.md Commit-good-practice.md +diff --git a/Commit-good-practice.md b/Commit-good-practice.md +new file mode 100644 +index 0000000..9610409 +--- /dev/null ++++ b/Commit-good-practice.md +@@ -0,0 +1,12 @@ ++# Best practice when committing ++ ++## Commit messages ++ ++[Good commit messages](https://chris.beams.io/posts/git-commit/) ++start with a brief (usually < 50 characters) summary statement about the ++changes made in the commit, with more explanation given in a new paragraph if ++required. Generally, the summary should complete the sentence "If applied, this ++commit will [_commit message here_]". ++ ++Avoid uninformative messages such as "small tweaks" or "updates" — write what ++will be useful for others to read. +diff --git a/Git-cheatsheet.md b/Git-cheatsheet.md +index c2409dd..26bcb5c 100644 +--- a/Git-cheatsheet.md ++++ b/Git-cheatsheet.md +@@ -11,3 +11,6 @@ + ## Adding / committing changes + + `git add ` — Stages changes in the ``, ready for committing. ++ ++`git commit` — Commit changes to the repository that have been staged with ++ `git add`. +``` + +The output describes the **differences** (or **diffs**) of each file between the +versions in the specified commits. + +> ### Understanding the output of `git diff` +> +> The output of `git diff`, as shown above, is cryptic because +> it is actually a series of commands for tools like editors and `patch` +> telling them how to reconstruct one file given the other. +> If we break it down into pieces: +> +> 1. The 'diff' for each file begins with a line like +> `diff --git a/ b/`. It tells us that Git is producing output +> similar to the Unix `diff` command, comparing the old and new versions of the +> file ``. In the example above, the output starts +> with the diff for +> `Commit-good-practice.md` until just before the line +> `diff --git a/Git-cheatsheet.md b/Git-cheatsheet.md`, at which point it switches +> to the diff for `Git-cheatsheet.md`. +> 2. The next few lines in each file's diff tell exactly which versions of the file +> Git is comparing. Confusingly, it looks like it contains commit identifiers, +> but these are in face different, computer-generated labels for the +> versions of the files. +> 3. The remaining lines, beginning `@@`, are the most interesting: they show us the actual differences +> and the lines on which they occur. In particular, +> the `+` marker in the first column shows where we added a line. If we had +> lines that were removed, these would be marked with `-`. + +If we wanted to view just the diff for the file `Git-cheatsheet.md` we would +supply that as the only file argument, like so: + +``` +$ git diff ad56194 34c19f2 Git-cheatsheet.md +``` + +If we leave out `` altogether, then Git will show the diffs for all files +that were changed in the given commits. With the commits `ad56194` and `34c19f2` +above we only have the two files, so in this case + +``` +git diff ad56194 34c19f2 +``` + +would give the same output as `git diff ad56194 34c19f2 Git-cheatsheet.md Commit-good-practice.md`. + +Sometimes you only want to see which files have changed between commits. This +can be achieved with the `--name-only` option: + +``` +$ git diff --name-only ad56194 34c19f2 +Commit-good-practice.md +Git-cheatsheet.md +``` + +If we just want to compare the _latest_ commit — that is, the commit referred to +by `HEAD` — with a previous commit, we just provide an identifier for the +commit to compare to: + +``` +git diff +``` + +The rules for `` are the same as before. For example, to view the changes +to the file `Commit-good-practice.md` from commit `34c19f2` +("Add material on committing") to the latest commit: + +``` +$ git diff 34c19f2 Commit-good-practice.md +diff --git a/Commit-good-practice.md b/Commit-good-practice.md +index 9610409..524d4ec 100644 +--- a/Commit-good-practice.md ++++ b/Commit-good-practice.md +@@ -10,3 +10,14 @@ commit will [_commit message here_]". + + Avoid uninformative messages such as "small tweaks" or "updates" — write what + will be useful for others to read. ++ ++ ++## Commit little and often ++ ++Aim for each commit to capture one conceptual change to your work that ++can stand alone. This will make the history of your files' development much easier ++to follow. ++ ++A good rule of thumb: a commit should capture a change that ++you can describe in about 50 characters or fewer, potentially with extra ++explanation in the commit message if needed. +``` + +### Using your `HEAD` + +The case where you want to compare the most recent commit to an earlier one in +the history especially common. Git provides some syntax to refer +to commits relative to the current `HEAD` commit. We can refer to the commit that is +`n` commits before `HEAD` with `HEAD~n` (think `HEAD` minus `n` steps). These +are just more convenient ways to refer to commits and so can be used instead of +the identifiers we've been using so far. Let's look at some concrete examples, +using our `git log --oneline` output from earlier: + +* The command `git diff HEAD~1` would give the file changes applied in the most + recent commit (i.e. to go from `HEAD~1` to `HEAD`). This is just the changes + made in commit `46b11e6` (with message "Add advice on committing little and often"). + +* The command `git diff HEAD~3 Git-cheatsheet.md` would give the aggregate + changes that have been made to `Git-cheatsheet.md` since commit `ad56194` + i.e. the changes required to go from 3 commits earlier to the current commit. + +* The command `git diff HEAD~3 HEAD~2` would give the changes required to fo + from commit `HEAD~3` (`ad56194`) to `HEAD~2` (`34c19f2`). In other words, it + just gives the changes applied back when we did commit `34c19f2`. + + +> ### Exercise +> +> Verify the claims in the three bullet point examples given above, checking +> the outputs of `git diff` agree for the `HEAD` versions and the regular +> commit identifier versions. _Note: make sure to use the commit identifiers +> found in your own log, not the ones that feature in the example output above!_ + + +## Working tree and staging area diffs + +It is good practice to check exactly what you are going to commit before you +do so, especially if you have been working on multiple files simultaneously. +We can use `git diff` to examine changes to files that have yet to be staged +or committed. + + +### Changes that have not been staged + +Let's suppose we add some new content to our cheatsheet about `git log`: + +``` + + +## Viewing repository history + +`git log` — Shows the history of commits that have been made. + +`git log --oneline` — Show summary commit information, one commit per line. + +``` + +This will add changes to the working tree for our repository. We can view the +diff for changes that are in the working tree, but have not yet been staged, +by using `diff` without reference to any commits: + +``` +git diff +``` +As usual, we can leave `` empty and Git will return the diffs for all +files that have changed. + +Running this in our `git-good-practice` repository now yields + +``` +$ git diff +diff --git a/Git-cheatsheet.md b/Git-cheatsheet.md +index 135822a..86e679f 100644 +--- a/Git-cheatsheet.md ++++ b/Git-cheatsheet.md +@@ -17,3 +17,10 @@ + + `git commit -m "commit message here" — Commit changes to the repository, using + the given commit message ++ ++ ++## Viewing repository history ++ ++`git log` — Shows the history of commits that have been made. ++ ++`git log --oneline` — Show summary commit information, one commit per line. + +``` + +as we would expect. + + +### Changes staged, but not committed + +Suppose we now stage the changes above made in the previous section and run +`git diff` again: + +``` +$ git add Git-cheatsheet.md + +$ git diff + +$ +``` + +No output is returned because the default +behaviour of `git diff` is to show changes that are _in the working tree_ but +have not been staged. We can use the `--staged` option to view the changes that +have been staged, but not yet committed: + +``` +$ git diff --staged +diff --git a/Git-cheatsheet.md b/Git-cheatsheet.md +index 135822a..86e679f 100644 +--- a/Git-cheatsheet.md ++++ b/Git-cheatsheet.md +@@ -17,3 +17,10 @@ + + `git commit -m "commit message here" — Commit changes to the repository, using + the given commit message ++ ++ ++## Viewing repository history ++ ++`git log` — Shows the history of commits that have been made. ++ ++`git log --oneline` — Show summary commit information, one commit per line. + +``` + + +> ### Exercise +> +> First follow the steps above, so that you end up with entries about `git log` and +> `git log --oneline` in `Git-cheatsheet.md` that are staged but not committed. +> Now add a new entry to the cheatsheet about `git log -n`, but don't stage it. +> Now do the following: +> +> * Run `git diff Git-cheatsheet.md` +> * Run `git status` +> +> Can you explain what the output from these commands is saying, and why we get +> it? Once you're happy you understand what's going on, complete +> the task of adding the material about `git log` to the cheatsheet by making +> an appropriate commit, making sure to include the entry about `git log -n`. + + +## Viewing diffs with GUIs + +We appreciate that the output of `git diff` is not the most intuitive +way to view differences between file versions. Fortunately, many text editors +and IDEs support ways of visually depicting differences, either 'out of the box' +or through the installation of a plug-in / extension. Do a search online +to see if this is the case for your preferred text editor / IDE. + +> ### VS Code +> +> For VS Code users, the following links may be of help: +> +> * View the diffs for files that have not been staged, or have been staged but +> not committed . +> +> * View the commit history of a file: +> . +> This also suggests some extensions for VS Code to make working with Git more +> graphical. +> +> * Displaying diffs by selecting files to compare: +> . +> Note that the method described in this link can be used on the 'timeline' +> described in the previous link: simply right-click on different commits in +> the timeline for a given file to see the changes between the commits. diff --git a/_episodes/09_recording_changes_revisited.md b/_episodes/09_recording_changes_revisited.md new file mode 100644 index 0000000..5e408aa --- /dev/null +++ b/_episodes/09_recording_changes_revisited.md @@ -0,0 +1,284 @@ +--- +layout: page +title: "Recording Changes – Revisited" +order: 9 +session: 1 +length: 20 +toc: true +adapted: false +--- + +## Learning objectives + +By the end of this episode, you will understand how to incrementally stage changes +in a file.You will also be able to delete and move files that are +under version control within a Git repository. + + +## Staging in steps + +The last exercise in the previous episode, +[Viewing History and Changes]({{ site.url }}/08_history_and_changes/index.html), +began to touch on an important point about staging changes to files. It is possible +to stage some changes to a file, then make further changes to the _same_ file. + +For example, suppose we want to start adding content to `Git-cheatsheet.md` +about `git diff`: + +``` + +## Viewing changes + +`git diff ` — Show changes to files that have not yet been staged. + +`git diff ` — Show the differences in files between + two commits. + +``` + +Let's stage these changes: + +``` +$ git add Git-cheatsheet.md +``` + +Now let's add some content about the `--name-only` optional argument for +`git diff` to the cheatsheet: + +``` +`git diff --name-only ...` — Only show the names of files that have changed. + +``` + +Now run `git status`: + +``` +$ git status +On branch main +Your branch is ahead of 'origin/main' by 6 commits. + (use "git push" to publish your local commits) + +Changes to be committed: + (use "git restore --staged ..." to unstage) + modified: Git-cheatsheet.md + +Changes not staged for commit: + (use "git add ..." to update what will be committed) + (use "git restore ..." to discard changes in working directory) + modified: Git-cheatsheet.md + +``` + +`Git-cheatsheet.md` appears as a file that has both changes to be staged and +also further changes that have not yet been staged, which makes sense. From +here, we could + +* commit the staged changes (i.e. the content about `git diff ` + and `git diff `), + leaving the material about `git diff --name-only ...` as 'work in + progress' in the working tree; or + +* stage the further changes about `git diff --name-only ...`, so that + they join what's already been staged; or + +* leave things as they are and continue working on files in the repository. + +This gives us a lot of flexibility to make our commits nice and tidy. Let's go +for the first option. We make the commit and then view the remaining changes +left in the working tree: + +``` +$ git commit -m "Add entries about 'git diff' to cheatsheet" +[main 9bb2714] Add entries about 'git diff' to cheatsheet + 1 file changed, 8 insertions(+) + +$ git diff +diff --git a/Git-cheatsheet.md b/Git-cheatsheet.md +index 75e4430..acff2ee 100644 +--- a/Git-cheatsheet.md ++++ b/Git-cheatsheet.md +@@ -34,3 +34,5 @@ + + `git diff ` — Show the differences in files between + two commits. ++ ++`git diff --name-only ...` — Only show the names of files that have changed. + +``` + +As expected, the changes left to stage are about the `--name-only` option. Let's +tidy up by doing a round of 'add-commit' on these changes, then viewing the log +to see our last two commits: + +``` +$ git add Git-cheatsheet.md + +$ git commit -m "Add note about '--name-only' option to 'git diff'" +[main 910bb79] Add note about '--name-only' option to 'git diff' + 1 file changed, 2 insertions(+) + +$ git log -2 --oneline +910bb79 (HEAD -> main) Add note about '--name-only' option to 'git diff' +9bb2714 Add entries about 'git diff' to cheatsheet +``` + + +## Staging multiple files + +It can be a bit tedious to list out each file whose changes need to be staged, +or who's diffs we want to examine. Git provides convenient shorthands to refer +to multiple files at once. For example, if `path/to/directory` defines a +directory within the root folder of our repository, the command + +``` +git add path/to/directory +``` + +would stage all changes to files that are contained in `path/to/directory` _or in +directories descended from it_. (So, for example, both the files +`path/to/directory/file1.txt` and `path/to/directory/foo/bar/file2.txt` would +be included by the above command.) A particular example is the case where +`path/to/directory` is just the current working directory, i.e. `.`. If our +current working directory is the root directory of the repository, then the +command + +``` +git add . +``` + +would stage changes to all files contained in the repository root directory or +any directory descended from it. +This can be a useful to way to grab all changes to all files in a repository. + +> ### Caution with `git add .` +> +> Exercise caution when running `git add .`, because you may end up staging +> changes to files you didn't intend to! + +The above examples work analogously with `git diff` as well. + + +> ### Pathspecs +> +> The shorthands introduced here are examples of what are called **pathspecs**. +> This is Git's terminology for referring to files, in a way that provides more +> flexibility than just listing out all file paths individually. If you look at +> the Git help pages for commands like `git add` and `git diff`, you may well +> find that the command signature includes mention of `` rather than +> 'files'. You can think of this `` entry as meaning 'file paths, or +> shortcut syntax for specifying multiple files in one go'. We'll see a bit +> more about this later in the course. If you want to read more, check out the +> Git Glossary manual by running `man gitglossary` and paging down to the +> `pathspec` entry. + + +## Deleting and moving files + +Sometimes we may need to delete, move or rename files that are under version control +in a repository (i.e. that feature in commits in the repository). Git has +specific commands to do this: `git rm` for deletion +and `git mv` for moving and renaming. The key things to remember about these +commands are: + +* they only work when applied to files under version control; and + +* they perform the deletion / move _and then stage the result_, ready for committing. + + +> ### Comparison with `rm` and `mv` +> +> You may be familiar with the Unix commands `rm` (for deleting files) and +> `mv` (for moving files). If you use these commands on files that are under version control, +> then the changes will be detected by Git but not staged. The `git rm` and `git mv` +> versions automatically perform the staging for you. If a file is not under +> version control, then you should use the usual Unix commands for deletion and +> moving. + + +### Deletion + +The general form for deleting files that is under version control is + +``` +git rm +``` + +Let's create a new file, `rubbish.txt` that we'll put in the root folder +of the `git-good-practice` repository. For the purposes of demonstration, we'll +commit this file and then delete it. First, we create a commit for the file: + +``` +$ git add rubbish.txt + +$ git commit -m "Add some rubbish to try out 'git rm'" +[main d26a698] Add some rubbish to try out 'git rm' + 1 file changed, 0 insertions(+), 0 deletions(-) + create mode 100644 rubbish.txt +``` + +Now we apply `git rm` on the `rubbish.txt` file and check the status after having +done so: + +``` +$ git rm rubbish.txt +rm 'rubbish.txt' + +$ git status +On branch main +Your branch is ahead of 'origin/main' by 9 commits. + (use "git push" to publish your local commits) + +Changes to be committed: + (use "git restore --staged ..." to unstage) + deleted: rubbish.txt +``` + +The deletion has been staged, but not yet committed to the repository. Moreover, +if we view the contents of the folder with `ls`, we can see the file has been +deleted from the file system: + +``` +$ ls +Commit-good-practice.md Git-cheatsheet.md README.md +``` + +We then commit the deletion to the repository in the usual way: + +``` +$ git commit -m "Remove rubbish.txt" +[main 5cf8321] Remove rubbish.txt + 1 file changed, 0 insertions(+), 0 deletions(-) + delete mode 100644 rubbish.txt +``` + + +### Moving + +The general form of the `git mv` command is: + +``` +git mv +``` +Note that if `` is a directory, the file will be +moved there but keep the same name; otherwise, the file will be renamed to +``. Note that the directories in the destination path must already +exist. Here are some examples: + +* If `foo/bar` is an existing directory path from the current working directory, + then `git mv file.txt foo/bar/baz.txt` + will move the file `file.txt` to the new file `./foo/bar/baz.txt` (and stage this + move). + +* If `foo` is a directory, then `git mv file.txt foo` will move `file.txt` to + `./foo/file.txt` + +* `git mv file.txt newfile.txt` will rename `file.txt` to `newfile.txt`. + + +> ### Exercise +> +> We may want to create more 'good practice' files as we go through this course, +> so let's prepare by moving `Commit-good-practice.md` to a directory called +> `Good-practice-guides` in the root folder of the repository. Make this directory +> and then create a commit that moves `Commit-good-practice.md` to this +> directory. \ No newline at end of file diff --git a/_episodes/10_pushing_and_pulling.md b/_episodes/10_pushing_and_pulling.md new file mode 100644 index 0000000..947edc2 --- /dev/null +++ b/_episodes/10_pushing_and_pulling.md @@ -0,0 +1,176 @@ +--- +layout: page +title: "Pushing to and Pulling From the Remote Repository" +order: 10 +session: 1 +length: 10 +toc: true +adapted: false +--- + +## Learning objectives + +By the end of this episode you will be able to add changes from your local +repository to your remote repository using the `git push` command and view these +changes on GitHub. You will also have a high-level understanding of how to use +the `git pull` command. + + +## Pushing to the remote + +By now we've done quite a bit of work on our cheatsheet and good practice +material in our local `git-good-practice` repository. It seems like a good point to +put this work on the remote repository residing on GitHub. + +Let's review the status of the repository and view the log: + +``` +$ git status +On branch main +Your branch is ahead of 'origin/main' by 11 commits. + (use "git push" to publish your local commits) + +nothing to commit, working tree clean + +$ git log --oneline +92b2ac2 (HEAD -> main) Create general good practice guides directory +5cf8321 Remove rubbish.txt +d26a698 Add some rubbish to try out 'git rm' +910bb79 Add note about '--name-only' option to 'git diff' +9bb2714 Add entries about 'git diff' to cheatsheet +37be130 Add entry about 'git log' to cheatsheet +46b11e6 Add advice on committing little and often +ecbf67e Add entry for 'git commit' with '-m' option +34c19f2 Add material on committing +ad56194 Add entry about staging files with 'git add' +17912ce Create a cheatsheet document +3917168 (origin/main, origin/HEAD) Initial commit +``` + +The status indicates `main`, our local *branch*, is ahead of `origin/main`, the +remote *branch*, by 11 commits. (We will look at branches more formally later +in the course; for now, just think of these as different commit histories: one +local, the other remote.) These commits are our new snapshots that are yet +to be recorded in the remote repository. As a recap, note that the log shows the +short identifier and commit message of each of these commits, along with the +initial commit generated when the repository was created (`3917168`). + +The status also includes a handy comment, suggesting "use "git push" to publish +your local commits" - this is exactly what we should do next! Ultimately, `git push` +transfers the commits we have made in our local repository to the remote repository. +It should be noted that it will only push _commits_, not changes residing in the +working tree or staging area. We can alternatively use `git push origin`, if we +would like to be more explicit about which remote repository we are pushing to +(`origin` by default). + +When using the `git push` command, we may be prompted to enter our Git username +and a password. Since we set up the repository to work with HTTPs, we use the +Personal Access Token (PAT) we generated in the +[Setting up Git and GitHub]({{ site.url }}/04_configuring_git/index.html) +episode as said password. + +> ### Pasting the PAT +> +> You can paste the PAT in most terminals by right-clicking at the prompt. + +We now push the commits to our remote `git-good-practice` repository (note +that our terminal program doesn't display the PAT when we paste it in): + +``` +$ git push origin +Username for 'https://github.com': jbloggs9999 +Password for 'https://jbloggs9999@github.com': +Enumerating objects: 33, done. +Counting objects: 100% (33/33), done. +Delta compression using up to 8 threads +Compressing objects: 100% (31/31), done. +Writing objects: 100% (32/32), 4.09 KiB | 1.02 MiB/s, done. +Total 32 (delta 13), reused 0 (delta 0), pack-reused 0 +remote: Resolving deltas: 100% (13/13), done. +To https://github.com/jbloggs9999/git-good-practice.git + 3917168..92b2ac2 main -> main +``` + +Now we check the status and log again: + +``` +$ git status +On branch main +Your branch is up to date with 'origin/main'. + +nothing to commit, working tree clean + +$ git log --oneline +92b2ac2 (HEAD -> main, origin/main, origin/HEAD) Create general good practice guides directory +5cf8321 Remove rubbish.txt +d26a698 Add some rubbish to try out 'git rm' +910bb79 Add note about '--name-only' option to 'git diff' +9bb2714 Add entries about 'git diff' to cheatsheet +37be130 Add entry about 'git log' to cheatsheet +46b11e6 Add advice on committing little and often +ecbf67e Add entry for 'git commit' with '-m' option +34c19f2 Add material on committing +ad56194 Add entry about staging files with 'git add' +17912ce Create a cheatsheet document +3917168 Initial commit +``` + +Once again, the status shows we have no outstanding commits to push, meaning +`main` and `origin/main` are now pointing at the same commit (i.e. the remote +repository is now up to date with the local repository). + + +## Viewing the repository on GitHub + +GitHub provides some nice facilities to view the commit history on its website. +Below we outline the steps you will need to take to view these newly pushed commits +in the remote repository on your personal GitHub account. + +- **Step 1:** Log into your GitHub account. + +- **Step 2:** Click on your profile picture in the top right-hand corner - this will + activate a drop-down menu. Select _Your repositories_ from this drop-down menu. + +- **Step 3:** Click on the name of the repository you have been working on. + +- **Step 4:** Click on _commits_, above the list of files on the right-hand side. + It should look akin to the following screenshot (the number of commits you have + may differ if you've diverged from our ongoing example, or if you've skipped + some exercises): + + ![Link to viewing commits on GitHub]({{ site.url }}/images/github-commits-link.png) + + +## Pulling changes from a remote repository + +Platforms like GitHub can be used to share our code with the world. If you're +interested in taking a closer look at someone else's code, or even making use +of it, then you could clone their repository as explained in the +[Making Repositories]({{ site.url }}/05_making_repos/index.html) episode. But +what do you do if the owner of said repository makes updates at a later date? +You can retrieve these +updates to your local repository by using the `git pull` command. We'll cover +this command more later in the course, when we talk about collaborating with +others on code. You use `git pull` in the analogous way to `git push`: from +within the root folder of the repository, just run + +``` +git pull +``` + +or, to be more explicit about the remote repository, you can equivalently run + +``` +git pull origin +``` + + +## A final note + +In this episode, we have explored using `git push` in a way which is only really +suitable when we are working alone on a repository. This is fine if you want +to use a platform like GitHub for publishing your work, or if you just want +to use it to keep a backup with a record of the development history. In contrast, +when collaborating with others, we need to be more careful about using `git push` +and `git pull` to avoid conflicts between our work and others'. We will explore +this in more detail later in the course. diff --git a/_episodes/11_undoing_changes.md b/_episodes/11_undoing_changes.md new file mode 100644 index 0000000..0a7eed9 --- /dev/null +++ b/_episodes/11_undoing_changes.md @@ -0,0 +1,372 @@ +--- +layout: page +title: "Undoing Changes" +order: 11 +session: 2 +length: 20 +toc: true +adapted: false +--- + +## Episode objectives + +At the end of this episode you will know how to unstage file changes you didn't +mean to stage and how to undo accidental commits. + + +## Removing files from the staging area + +We've got quite a bit of outstanding stuff we could add to our cheatsheet +and good practice guide. Let's make a note of these things in a `TODO.txt` +file, which we'll put in the root folder of our repository: + +``` +TODO: + +Add note about staging multiple files with `git add` and `git diff` + +Add note to commit good practice about perils of `git add .` + +Add cheatsheet entries for `git rm` and `git mv` + +Add cheatsheet entries for pushing and pulling +``` + +We might as well tick off the first two items, so let's add the following content +to `Git-cheatsheet.md`: + +``` + +## Specifying multiple files + +`git path/to/directory` — Apply `` to all files in and descended + from `path/to/directory` + +Examples: + +`git add .` — Stage all changes to files in current directory or descended from + current directory. + +`git diff foo/` — Show diffs of all files in directory `foo` or descended from + `foo`. + +``` + +And we add the following to `Good-practice-guides/Commit-good-practice.md`: + +``` + +## Make sure you know what you're committing + +Take care when staging multiple files with e.g. `git add .` that you don't +stage changes you didn't mean to. Always check what you're committing with +`git diff` or `git status`. + +``` + +We go ahead and stage these, using our recently learnt syntax for staging +changes to multiple files (our working directory is the repository root +folder, as usual): + +``` +$ git add . +``` + +Wait! Something doesn't feel right... Let's check the status: + +``` +$ git status +On branch main +Your branch is up to date with 'origin/main'. + +Changes to be committed: + (use "git restore --staged ..." to unstage) + modified: Git-cheatsheet.md + modified: Good-practice-guides/Commit-good-practice.md + new file: TODO.txt + +``` + +Ah, no! We don't want to commit our `TODO.txt` file. This was just to help us +keep track of our work and it doesn't belong in the repository. Fortunately +we can remove changes to a file from the staging area. In fact, +`git status` tells us how to do this. The general command to use is: + +``` +git restore --staged +``` + +So let's use this on our `TODO.txt` file. We run the command, then check that +the only differences staged are for the cheatsheet and good practice guide + +``` +$ git restore --staged TODO.txt + +$ git diff --name-only --staged +Git-cheatsheet.md +Good-practice-guides/Commit-good-practice.md +``` + +That's better, now we can go ahead and commit. (Good thing we checked before +committing the first time round!) + +``` +$ git commit -m "Add material on basic pathspec usage (directories)" +[main 0984d2b] Add material on basic pathspec usage (directories) + 2 files changed, 21 insertions(+) +``` + +## Undoing commits + +What if we'd gone ahead and actually committed our `TODO.txt` file by accident? +Git offers a couple of ways to address this: + +* _Reverting_: Create a new commit that undoes the old commit + +* _Resetting_: Move `HEAD` back to a previous commit, so that all the later commits are + removed from the commit history. + + +### Reverting (undo a commit by making a new one) + +Let's suppose we've 'accidentally' made a new commit which puts `TODO.txt` under +version control, which we want to undo: + +``` +$ git log --oneline -3 +cc01bda (HEAD -> main) Add TODO.txt +0984d2b Add material on basic pathspec usage (directories) +92b2ac2 (origin/main, origin/HEAD) Create general good practice guides directory +``` + +The command + +``` +git revert +``` +can be used to create a new commit that undoes a previous ``. In our +case, we want to undo the commit where we added `TODO.txt`, i.e. commit +`cc01bda`. We'll run that shortly, but first we need to make sure to make +a temporary copy of `TODO.txt` and store it outside the repository. This is +because the revert will return the repository to the state before we'd added +`TODO.txt`, which will involve deleting the file. Having done this, we now +perform the reversion: + +``` +$ git revert cc01bda +``` + +Because `git revert` is actually making a new commit, our text editor pops into +life for us to write a commit message. It's been pre-populated with a +helpful message, telling us which commit is being reverted: + +``` +Revert "Add TODO.txt" + +This reverts commit cc01bdaf30a98d5bfaf5e43838d90522695f251e. + +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# +# On branch main +# Your branch is ahead of 'origin/main' by 2 commits. +# (use "git push" to publish your local commits) +# +# Changes to be committed: +# deleted: TODO.txt +# +``` + +We could edit this if we wanted to, but the default is fine, so we just close +the file to complete the commit. + +``` +$ git revert cc01bda +[main bc9d190] Revert "Add TODO.txt" + 1 file changed, 9 deletions(-) + delete mode 100644 TODO.txt +``` + +Now our commit history includes our new 'reverting' commit. Note also that +`TODO.txt` has been deleted. + +``` +$ git log --oneline -4 +bc9d190 (HEAD -> main) Revert "Add TODO.txt" +cc01bda Add TODO.txt +0984d2b Add material on basic pathspec usage (directories) +92b2ac2 (origin/main, origin/HEAD) Create general good practice guides directory + +$ ls +Git-cheatsheet.md Good-practice-guides/ README.md +``` + +> #### Note on `git revert` +> +> The `revert` command will only work if the working tree and staging area have +> no changes in them. + + +### Resetting (move back to a previous commit and lose later ones) + +Reverting a commit is often considered a 'safe' way to undo a commit, because +the original, offending commit is not actually lost. This way, if we decide we +_did_ in fact want to make that commit, we can easily recover it (by doing +`git revert` on it). There is a +more destructive way to undo commit history that will get rid of the commits. + +The `git reset` command is used to move back our `HEAD` to an earlier commit. +The default form of the command is: + +``` +git reset +``` + +In effect, this will 'rewind' the commit history back to finish at the given +``, dropping later commits as if they'd never happened. However, it will +put all changes since `` in the working tree, giving us a chance to +work with the files as they currently are before the reset. + +For example, let's create a file `foo.txt` that contains some random +text: + +``` +Some foo-ey random text + +``` + +We'll make a commit of this new file and remove it via a reset. First, we make +the commit: + +``` +$ git add foo.txt + +$ git commit -m "Add foo.txt to practice resetting" +[main fcecec0] Add foo.txt to practice resetting + 1 file changed, 1 insertion(+) + create mode 100644 foo.txt + +$ ls +foo.txt Git-cheatsheet.md Good-practice-guides/ README.md +``` + +Let's now reset the commit history back to how it was before +we committed `TODO.txt`. We check the log to get the commit identifier, +perform our reset, then check the status of the repository: + +``` +$ git log --oneline -5 +fcecec0 (HEAD -> main) Add foo.txt to practice resetting +bc9d190 Revert "Add TODO.txt" +cc01bda Add TODO.txt +0984d2b Add material on basic pathspec usage (directories) +92b2ac2 (origin/main, origin/HEAD) Create general good practice guides directory + +$ git reset 0984d2b + +$ git log --oneline -5 +0984d2b (HEAD -> main) Add material on basic pathspec usage (directories) +92b2ac2 (origin/main, origin/HEAD) Create general good practice guides directory +5cf8321 Remove rubbish.txt +d26a698 Add some rubbish to try out 'git rm' +910bb79 Add note about '--name-only' option to 'git diff' +``` + +We can see that our new `HEAD`, i.e. our new 'current commit', is what we reset +to, namely `0984d2b`. What state will our working tree be in? The answer is that it +will contain the changes that would need to be made to recover the state of +the repository as it was at `HEAD` just before the reset (at the +now-removed commit `fcecec0`). In other words, we expect to see just the change +that adds `foo.txt`. We can verify this with `git status`: + +``` +$ git status +On branch main +Your branch is ahead of 'origin/main' by 1 commit. + (use "git push" to publish your local commits) + +Untracked files: + (use "git add ..." to include in what will be committed) + foo.txt + +nothing added to commit but untracked files present (use "git add" to track) +``` + +We don't want to keep this `foo.txt` file, so let's just delete it with the +usual Unix command `rm` to get a nice, clean working tree again. + +``` +$ rm foo.txt +``` + +After all that, we can move that TODO list back into the repository. We'll +finish by removing the tasks we've completed and add some new tasks, leaving our +list like so: + +``` +TODO: + +Add cheatsheet entries for `git rm` and `git mv` + +Add cheatsheet entries for pushing and pulling + +Add cheatsheet entries about undoing changes + +``` + +> #### Hard reset +> +> If you're really sure you don't need to keep the changes from later commits when +> resetting, then you can automatically discard them by using the `--hard` option: +> `git reset --hard `. This will set your working tree to the exact same state as +> the commit you're resetting to. It thus deletes the work you did after +> ``; be sure that this is what you want before running a hard reset! + + +### Warning: pushing after a reset + +Something to be aware of when using `git reset` is that you can't by default push to a +remote repository if the tip of your local `main` branch is pointing to a commit +that is behind where the remote repository (`origin/main`) is. + +For example, suppose we had reset our local repository to the commit _before_ +`origin/main`, i.e. commit `5cf8321`, "Remove rubbish.txt". If we then tried to push +our local repository to the remote one, Git would not complete the request and +complain to us with the following message: + +``` +$ git push origin +To https://github.com/jbloggs9999/git-good-practice.git + ! [rejected] main -> main (non-fast-forward) +error: failed to push some refs to 'https://github.com/jbloggs9999/git-good-practice.git' +hint: Updates were rejected because the tip of your current branch is behind +hint: its remote counterpart. Integrate the remote changes (e.g. +hint: 'git pull ...') before pushing again. +hint: See the 'Note about fast-forwards' in 'git push --help' for details. +``` + +The main reason for this is to avoid a situation where commit history in the +remote repository gets lost. This is especially important when collaborating +with others, which we'll cover in later episodes in this course. + +You can read more on the topic of resetting on +Atlassian's tutorial. + + +## Important note: sensitive data + +The methods for undoing commits discussed here are appropriate when the commit +you made in error contains changes you didn't want, but don't fundamentally matter +if they've been recorded in the repository. In fact, even with a reset, it is +possible to recover the commit, with some advanced Git use that involves +something called the +reflog. + +This means that, if you accidentally commit _sensitive data_, such as passwords +or confidential information, you cannot work on the basis that `git reset` or +`git revert` has removed the data from the repository. Moreover, if you +pushed the commits to a remote repository, the information will be stored there. + +In these cases, you need to use specialist tools to remove all traces of the +sensitive data from the repository. See +the GitHub documentation for information on this topic. diff --git a/_episodes/12_ignoring_files.md b/_episodes/12_ignoring_files.md new file mode 100644 index 0000000..1dbacd9 --- /dev/null +++ b/_episodes/12_ignoring_files.md @@ -0,0 +1,302 @@ +--- +layout: page +title: "Ignoring Files" +order: 12 +session: 2 +length: 20 +toc: true +adapted: true +attrib_name: Version Control with Git - Ignoring Things +attrib_link: https://swcarpentry.github.io/git-novice/06-ignore/index.html +attrib_copywrite: Software Carpentry +attrib_license: CC-BY 4.0 +attrib_license_link: https://creativecommons.org/licenses/by/4.0/ +--- + +## Learning objectives + +By the end of this episode you will know how to get Git to ignore certain files +so that they are not included as part of a repository's commit history. You +will also be able to describe some examples of the kinds of files that shouldn't +be stored in a repository. + + +## Ignoring files + +Currently we still have our `TODO.txt` file hanging around in the working tree: + +``` +$ git status +On branch main +Your branch is ahead of 'origin/main' by 1 commit. + (use "git push" to publish your local commits) + +Untracked files: + (use "git add ..." to include in what will be committed) + TODO.txt + +nothing added to commit but untracked files present (use "git add" to track) +``` + +While this file is recognised by Git, there's always a risk we might accidentally +commit it to the repository. Git provides a way to **ignore** files, so that +any changes to these files are just ignored by Git. We can do this by creating +a special file, which must be named `.gitignore`, in the root folder of the +repository. In this file we specify which files Git should ignore; when doing +this, we need to specify paths relative to the root directory of the repository. + +We therefore create a `.gitignore` file in the root folder of `git-good-practice` +and add the following content to it to ensure the `TODO.txt` file is ignored: + +``` +TODO.txt + +``` + +> ### `.gitignore` comments +> +> Any line that begins with a hash (`#`) in a `.gitignore` file is treated +> as a comment and thus not processed by Git. Note +> that the line must have `#` as the first character to be considered a +> comment e.g. a comment line cannot begin with whitespace followed by `#`. + + +Now we check the state of the working tree again: + +``` +$ git status +On branch main +Your branch is ahead of 'origin/main' by 1 commit. + (use "git push" to publish your local commits) + +Untracked files: + (use "git add ..." to include in what will be committed) + .gitignore + +nothing added to commit but untracked files present (use "git add" to track) +``` + +The only thing Git notices now is the newly-created `.gitignore` file. +In general, it's useful to keep the `.gitignore` file under version control, so +that other users of the repository can also have the same things ignored as we +do. Let's add and commit `.gitignore`: + +``` +$ git add .gitignore + +$ git commit -m "Ignore TODO list file" +[main 42a9a32] Ignore TODO list file + 1 file changed, 1 insertion(+) + create mode 100644 .gitignore + +$ git status +On branch main +Your branch is ahead of 'origin/main' by 2 commits. + (use "git push" to publish your local commits) + +nothing to commit, working tree clean +``` + +As a bonus, using `.gitignore` helps us avoid accidentally adding files +to the repository that we don't want to track: + +``` +$ git add TODO.txt +The following paths are ignored by one of your .gitignore files: +TODO.txt +hint: Use -f if you really want to add them. +hint: Turn this message off by running +hint: "git config advice.addIgnoredFile false" +``` + +As the message says, if we really want to override our ignore settings, +we can use `git add -f` to force Git to add something. We can also always see +the status of ignored files if we want: + +``` +$ git status --ignored +On branch main +Your branch is ahead of 'origin/main' by 2 commits. + (use "git push" to publish your local commits) + +Ignored files: + (use "git add -f ..." to include in what will be committed) + TODO.txt + +nothing to commit, working tree clean +``` + + +## Ignore similar files with pathspecs + +So far, we have been specifying files individually whenever we want to ignore them. +Git has its own mini-language for referring to multiple, related files +simultaneously, which can give us much more flexibility in certain situations, +such as when specifying files to ignore. + +This is done through what are called **pathspecs**. We already touched on these +when we discussed e.g. using `git add` on all files in a directory. We aren't +going to cover everything there is to know about pathspecs, but here are some +examples that cover quite a lot of cases in practice: + +* `.` refers to files in the current working directory and all directories + descended from it (e.g. would include `./foo/bar/baz/file.txt`) + +* Specifying a directory `foo` will limit to files that descend from `foo` + (e.g. `./foo/bar/baz/file.txt` but not `./qux/bar/file.txt`) + +* `*.pyc` refers to all `.pyc` files in the current working directory. + +* `foo/bar/*.pyc` matches all `.pyc` files in the directory `foo/bar` + +Most commands in Git that work on files also work on pathspecs and you'll see +this term in the help pages (try `git add --help` for an example). +For the complete specification of pathspecs, check out the +Git Glossary manual, by running `man gitglossary` and paging down to the entry +for `pathspec`. + +Let's create a few dummy files for trying this out, imagining that we've got +some research code that takes in data files, outputs some results and produces +a log file of the run. We use the Unix commands `mkdir` +to create a new `data` directory and `touch` to create new files: + +``` +$ mkdir data + +$ touch data/a.dat data/b.dat data/c.dat + +$ touch a.out b.out c.out + +$ touch 2023-02-10-15-36-02_modelRun.log + +$ ls +2023-02-10-15-36-02_modelRun.log a.out b.out c.out data/ Git-cheatsheet.md Good-practice-guides/ README.md TODO.txt + +$ ls data/ +a.dat b.dat c.dat +``` + +As expected, Git detects all of these as untracked files: + +``` +$ git status +On branch main +Your branch is ahead of 'origin/main' by 2 commits. + (use "git push" to publish your local commits) + +Untracked files: + (use "git add ..." to include in what will be committed) + 2023-02-10-15-36-02_modelRun.log + a.out + b.out + c.out + data/ + +nothing added to commit but untracked files present (use "git add" to track) +``` + +We can succinctly tell Git to ignore these files by adding three different +pathspecs: + +``` +TODO.txt + +# Ignore files in the data folder and subfolder therein +data/ + +# Ignore .log files in the root folder of the repository +*.log + +# Ignore .out files in the root folder of the repository +*.out + +``` + +Now we can see that all these files have become ignored by Git: + +``` +$ git status --ignored +On branch main +Your branch is ahead of 'origin/main' by 2 commits. + (use "git push" to publish your local commits) + +Changes not staged for commit: + (use "git add ..." to update what will be committed) + (use "git restore ..." to discard changes in working directory) + modified: .gitignore + +Ignored files: + (use "git add -f ..." to include in what will be committed) + 2023-02-10-15-36-02_modelRun.log + TODO.txt + a.out + b.out + c.out + data/ + +no changes added to commit (use "git add" and/or "git commit -a") +``` + +Since this was just for experimenting with pathspecs, we'll clean up by setting +our `.gitignore` file back to just containing `TODO.txt` and removing the +files and `data` directory we created. + +``` +$ rm 2023-02-10-15-36-02_modelRun.log a.out b.out c.out + +$ rm -rf data/ +``` + +Having done this, we now have a clean working tree again, with the `TODO.txt` +file still ignored: + +``` +$ git status +On branch main +Your branch is ahead of 'origin/main' by 2 commits. + (use "git push" to publish your local commits) + +nothing to commit, working tree clean +``` + + +## What kind of files should be ignored? + +As we've suggested, not all files should be kept under version control in a +Git repository. For one thing, certain files only serve to bloat the repository, +potentially affecting the performance of Git (e.g. when syncing with a +remote repository). For another, some files may contain sensitive information +that should not be shared with others. + +Here are some examples of files that should definitely not be kept under version +control: + +* Sensitive files that should not be shared with others, e.g. passwords, access + tokens. + +* Artifacts from the process of building software e.g. compiled Python files + (`.pyc`) or similar, compiled executables, `.o` files, etc. + +* Anything that is tied to you, your computer, or the operating system you use, + which may not work or mean anything to other users of the code. + +Here are some examples of files that should generally not be kept under version +control, though there may be legitimate exceptions in some cases: + +* Data files, especially if these are quite large. + +* Binary files, such as images, audio, certain kinds of data formats, PDFs and + the like. Git is designed to work with text-based files e.g. source code + files. Although Git can store binary files in repositories, it will not be able + to display changes to these files, limiting the benefits gained from Git in + this case. + +* Any files that are output from the software in the repository (including log + files). If anything can be generated from the software then there's no need + to store it under version control, since it can be regenerated if needed. + +* 3rd party package dependencies. Instead, a suitable + specification file (e.g. a `requirements.txt` file for + Python pip packages, a Conda environment specification file, etc.) should be + kept under version + control to allow users to obtain software dependencies themselves. diff --git a/_includes/prev_next_navbar.html b/_includes/prev_next_navbar.html index 8dcb493..5164e9d 100644 --- a/_includes/prev_next_navbar.html +++ b/_includes/prev_next_navbar.html @@ -1,6 +1,6 @@ {% include sortedpages.html %}
- Home + Home {% for node in sorted_pages %} {% if page.url == node.url %} {% unless forloop.first %} diff --git a/_layouts/page.html b/_layouts/page.html index 1be8a34..c1ad6f4 100644 --- a/_layouts/page.html +++ b/_layouts/page.html @@ -35,11 +35,17 @@

{{ page.title | default: site.github.repository_name }}The material on this page is © University of Exeter.

{% if page.adapted %} + {% if page.attrib_custom %} + + {% else %} + {% endif %} {% else %}