Skip to main content
A Git Toolbox (Advanced)
This material was adapted from the OxfordRSE "Git and GitHub" course, a derivative work of the UCL Research Software Development Group teaching materials and the Software Carpentry "Version Control with Git" lesson.

This material was adapted from the OxfordRSE "Git and GitHub" course, a derivative work of the UCL Research Software Development Group teaching materials and the Software Carpentry "Version Control with Git" lesson.

Creative Commons License

A Git Toolbox (Advanced)

Advanced: safe to skip

This module is a grab-bag of handy Git commands you don't strictly need for the everyday workflow. Each section stands on its own, so dip in whenever you meet the problem it solves.

Setting work aside with git stash

Before you can git pull, you need to have committed any changes you have made. But what if you want to pull, and you're not ready to commit? You can temporarily "put aside" your uncommitted changes with git stash:
git stash git pull
Stashing takes your uncommitted changes off the working directory and saves them away, leaving your repository clean so the pull can proceed. When you're ready, bring your changes back with:
git stash pop
(git stash apply does the same but keeps a copy in the stash list; git stash list shows what you have stashed.) The stash is a great way to save your working state in a pinch - for example when you need to quickly switch branches to fix something urgent.
By default, git stash only stashes changes to tracked files - any new, untracked files are left behind in your working directory. To stash those too, use git stash -u (or --include-untracked).

Labelling revisions with git tag

Commit hashes are precise but unmemorable. Tags are human-readable labels for a specific commit, and can be used anywhere you would name a commit. They are ideal for marking releases, or the exact version used to produce a paper's results:
git tag -a v1.0 -m "Release 1.0" git push --tags
The -a flag creates an annotated tag (with a message, author and date). Once a tag exists you can use its name in place of a hash - for example to list every commit since the release:
git log v1.0.. --oneline
If .. is used with nothing after it, HEAD is assumed. This lists commits reachable from HEAD that are not part of v1.0. In a simple linear history, these are the commits made since the release.

Staging part of a file: interactive add

A single edited file may contain several unrelated changes that really belong in different commits. Git calls each contiguous block of changes a hunk, and lets you stage them one at a time with the -p (patch) flag:
git add -p climate_analysis.py
Git shows each hunk in turn and asks what to do with it:
+import numpy as np import sys import temp_conversion Stage this hunk [y,n,q,a,d,s,e,?]?
Answer y to stage a hunk, n to skip it, s to split it into smaller hunks, and q to quit. This lets you build a clean, focused commit even when your working file contains a mix of changes. git reset -p does the reverse, un-staging individual hunks.

Removing untracked files with git clean

Sometimes you end up with lots of stray files - build artefacts, generated outputs - that you never want in version control. git clean removes files that Git is not tracking:
git clean -n # dry run: list what *would* be removed git clean -f # actually remove untracked files
Because this deletes files that are not in version control, it cannot be undone - always run the dry run (-n) first. Useful flags:
  • -f: force; required for the command to actually delete anything.
  • -d: also remove untracked directories.
  • -x: also remove files that are ignored by .gitignore.
  • -X: remove only the files ignored by .gitignore, keeping other untracked files.
For example, first preview with the dry-run equivalent:
git clean -ndX
This lists everything your .gitignore matches (such as generated *.pdf or __pycache__ files) that would be removed, leaving new source files you haven't committed yet untouched. Once you're happy with the preview, swap -n for -f to actually delete them:
git clean -fdX
git clean permanently deletes files that Git isn't tracking, so they can't be recovered from history. Omitting -n and running git clean -f (or any variant with -f) directly is dangerous - it's easy to lose files you meant to keep. Always preview with -n first.

Key Points

  • git stash / git stash pop temporarily set aside uncommitted work (for example, so you can pull).
  • git tag -a v1.0 labels a specific commit - ideal for releases or the version used in a paper.
  • git add -p stages changes one hunk at a time, so a single file can go into several focused commits.
  • git clean deletes untracked files - always preview with git clean -n before using -f.