Session 1: Version control and project organisation
In order to speed up this short course, we are going to use GitHub Codespaces as a remote development environment. While setting up the Codespace virtual machine, we will be using a devcontainer to install some extensions and packages that you'll use.
What all of that means is that there's nothing for you to install. Head over to the Python project template and log in with your GitHub account which you set up before attending the course. Click the green Use this template button and select Create a new repository. If you're logged in, you should now get a prompt that asks you for a name.
Picking a name
We want to write a piece of software that uses the Pythagorean theorem to calculate the length of the hypotenuse of a right-angled triangle. In general, it's a good idea to name your GitHub repository the same thing as you intend on calling your Python package. You can see here for more information on picking a suitable name.
Once you've chosen the name, select "public" for the repository visibility. We want to share the code publicly, and having a public repository will allow us to use more of GitHub's free features (such as building a documentation website using GitHub pages).
Launching Codespaces
With your new copied repository, click the "<> Code" button, and select the green "Create Codespace" button. This will open a new browser window. Sit back and relax; it will take a while to open. You'll see a note at the bottom of the "<> Code" dropdown saying that "Codespace usage on this repository is paid for by your username". Each account gets 120 hour of free Codespace use per month, with hte option to upgrade and pay per use beyond this point. We will be purely using the free offerings.
The new Codespaces browser tab resembles the interface of VSCode. Wait while it installs the pre-specified extensions and packages. You can see what settings have been used to initialise the Codespace by looking at .devcontainer/devcontainer.json
.
In your Codespace, in your git repo
The virtual machine is running on Ubuntu, a Linux distribution. Once the Codespace instance is launched, you can navigate through the folder structure via the terminal using Linux commands such as ls
to list the contents of the current folder, and pwd
to check the patch of the working directory.
# Essential linux/bash commands
cd # change directory to home
cd /workspaces # return to the /workspaces directory
cd .. # go up a level in the directory structure
ls # list the contents of the current directory
pwd # get the path to the current working directory
As we already mentioned, this repository or folder is version controlled by git.
# Essential git commands
git status # check on status of current git repo
git branch NAME # create a branch called NAME
git checkout NAME # swap over to the branch called NAME
git add . # stage all changed files for commit, you can replace "." with FILE to add a single file called FILE
git commit # commit the staged files (this will open your text editor to create a commit message)
git push origin NAME # push local commits to the remote branch tracking the branch NAME
Try it out
From the terminal of your git repository, create a new branch called something sensible, like initial-files
:
git branch initial-files
git checkout initial-files
You can create some test files and open them in the VSCode editor in your browser:
code example.txt
: create a file "example.txt" and open it with code
. Add some text and save it.
Now that you've added a file, check the status of the repository:
git status
Let's just throw out those changes instead of merging them:
git stash -u
We can abandon this branch and swap back to main
:
git checkout main
Set up a sensible project directory structure
Further reading
If you are interested in reading more about how to structure your Python project (such as about src/
vs "flat" layout), or how you might organise a larger, more complex project, read on!
We are going to create a simple directory structure that will help keep your code tidy, will enable us to use some automated tools for testing, packaging and documentation, and will allow users of your code/supervisors/reviewers to quickly understand what is going on.
For this example, we are going to use the following directory set up:
example-package/ This is the directory you are working in now!
├── src/
│ └── example_package/
│ ├── __init__.py Makes the folder a package.
│ └── source.py An example module containing source code.
├── tests/
| ├── __init__.py Sets up the test suite.
│ └── test_source.py A file containing tests for the code in source.py.
├── README.md README with information about the project.
└── CITATION.cff Citation file that makes it easy for people to cite you!
To speed things up, we are going to use this simple tool to quickly generate the required directories and files for your project. Of course, you can do this manually!
In the README.md
file, write a sentence or two about the project, stating what the code will do. If you've used our Python project template, this will already have lots of information in it. You just add a dividing line using hyphens (---
) at the top and add your information above this. Later on we can delete the extra information in the README, and add some useful details.
Save, add, commit, and push your work!
Remember that when you add files or folders and make changes, in addition to hitting "save", you need to add and commit your work.
First, check what has been changed in your repository since your last commit:
git status
Then, you can stage files to be committed using add
:
git add FILENAME
to add a specific file, or git add .
to add everything that's changed in the repository.
Then, you commit
the staged files with a message:
git commit
This will open up a text editor (in this case, using VSCode) for you to add a commit message. This message should be short, in the imperative, and explain the changes succinctly; for example: "Update session1.md to add essential git commands
". Once happy, save and close this text file. You can now push
your local changes to the remote repository on GitHub:
git push origin BRANCHNAME
If you are working and committing incrementally, you can speed things up by squishing together the add and commit commands:
git commit . # add and commit everything that's changed in the repository
This will open your preferred text editor for you to enter a commit message. You can check that the files you intended have been added, and can close the editor without saving to cancel if you realise you are tracking a file you don't mean to be. You can then instead add and commit files individually.
Merging this set-up branch
Further reading
If you are interested in reading more about how to use git
in your project,
see our notes for software dev here
Once you've created your directory structure, you should use the instructions above to add, commit and push your changes to your remote branch. Let's try merging this back to the main
branch and then creating a new branch to start brainstorming and writing our code.
Navigate to the GitHub repository url (https://github.com/{YOUR_USER_NAME}/{YOUR_REPOSITORY_NAME}
). You'll see a button with a drop-down options under the title of your repository with the git branch symbol that reads "main". If you click this, you should see the name of the branch you made your changes on. Click onto your recent branch, and when a new banner shows up with the word "Contribute", select this. This will allow you to create a pull request to merge changes back on to main. Read more about pull requests here.
Before you make any more changes, create a new branch to work on and swap over to it:
git branch BRANCH-NAME
git checkout BRANCH-NAME
Don't work on main
!
In general, it's a good idea to keep your main
branch clean, and only add work to it via a pull request. This allows you to catch any errors before merging them, ensuring that the code on your main
branch is always in working order (or at least, it stays in working order once it's reached that point).
Check what branch you're on with git status
, and swap to a different branch before adding and committing anything if you realise you're on main
.