Skip to content

Update git course with exercises and some more advanced material#268

Open
fcooper8472 wants to merge 2 commits into
mainfrom
267-update-git-course-with-intermediate-material
Open

Update git course with exercises and some more advanced material#268
fcooper8472 wants to merge 2 commits into
mainfrom
267-update-git-course-with-intermediate-material

Conversation

@fcooper8472

@fcooper8472 fcooper8472 commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Add:

  • More advanced material (rebase, bisect etc)
  • Add exercises with solutions (previously none in this course)
  • Add "key points" sections for each lesson

The main additions are migrating the remaining content from this course:
https://github.com/OxfordRSE/git-github-course

The more advanced material is marked as such, so minor content changes for someone just starting with Git, but some stretch material for people more familiar.

The other major change is adding some exercises. They're fairly trivial, but hopefully will help improve engagement.

(There are a large number of whitespace changes, Windows to Unix endings... @alasdairwilson dunno if it's worth a one-time normalisation of line endings and some instrumentation to catch this on PRs in future, to avoid future large diffs?)

@martinjrobins martinjrobins left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @fcooper8472, changes look great, a few suggestions below

![GitHub Desktop](fig/01-background/desktop.png)

Fundamentally, though, these are all just 'wrappers' around the command line version of Git.
If you understand what they're doing under the hood, you can easily switch between versions. You can, for example, manage your code on Iridis using command-line git and GitHub Desktop on your desktop workstation.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is Iridis?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like southamptons supercsomputer


:::callout

## Git GUI Integrations

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Git GUI Integrations
## Git IDE Integrations

A colleague is about to put their research project into Git. Which of the following would you recommend they track, and which would you leave out?

1. Their analysis scripts (`analysis.py`)
2. A 2 GB raw data file downloaded from a public archive

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't discuss anywhere above what can and can't be tracked

...
```

By default, `restore` replaces the file with the version of it in the _staging area_. If you haven't used `git add`, that should be the same as the version in the last commit. But what if we already used `git add` on our incorrect version of a file, or we broke the file more than one commit ago?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one thing I found confusing looking at the git documentation was that the staging area is usually called the "index", not sure if you mention that anywhere

Consider a situation where all your code is in one file,
and you fixed a bug in one section but accidentally introduced one elsewhere.

You can't just roll back to fix one bug without un-fixing the other.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, you can fairly easily if you are in an IDE. or (more difficult) you can use the interactive mode of git to do it line by line

:::callout
If the change you're reverting overlaps with later edits, Git may not be able to
work out how to undo it automatically and will report a **conflict**. If that
happens, resolve it by hand exactly as you did for merge conflicts in the previous

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember if merge conflicts were covered?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in 06-remote.md, so after this.

The remaining modules in this course are optional and marked _(Advanced)_. Come
back to them whenever you meet the problem each one solves:

- **Rebasing and Squashing**: produce a clean, linear history.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put links to these modules

them, rebasing will rewrite commits that others already have - and things will
get badly tangled.

Only rebase commits that are still **private** to your local repository. If in

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or in a private branch on the remote

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in general this callout both undersells rebase, cause it is useful even on shared work, and also

“Never rebase anything already pushed” obscures the actual danger. Rebasing creates new commit identities; if someone has fetched or based work on the original commits, their history will diverge and they must reconcile it after the rewritten branch is force-pushed.

But rebasing pushed feature, draft-PR, backport branches is routine when ownership is clear and collaborators are coordinated. Could this callout instead say: Do not rebase commits that other people may be using without coordinating with them first?

@alasdairwilson alasdairwilson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I sliced the end off one of my fingers :( so I'm making a lot of typos, typing a finger down on my left hand.

So apologies for the unreadbale garbage.

Otherwise this looks good to me mostly..

I've made some suggestions though.

Comment on lines +29 to +51
## 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`:

```bash
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:

```bash
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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think this should include that git stash only stashed changes in tracked files, so it will leave untracked files.

Could also include "git stash -u" for stashing untracked files.

:::callout
If the change you're reverting overlaps with later edits, Git may not be able to
work out how to undo it automatically and will report a **conflict**. If that
happens, resolve it by hand exactly as you did for merge conflicts in the previous

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in 06-remote.md, so after this.


## Referencing remotes

When you run `git fetch`, Git downloads the latest state of a remote **without**

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because this is right after saying git remote add upstream then perhaps it is not transparent enough that this will only fetch origin and not upstream (add -all or specifically call out git fetch upstream)

Comment on lines +119 to +121
For example, `git clean -fdX` clears out everything your `.gitignore` matches
(such as generated `*.pdf` or `__pycache__` files) while leaving new source files
you haven't committed yet untouched.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this perhaps is a bad command to have as ane xample, someone is likely to run it and lose files? could you do the preview version. -ndX? and have the callout indicate that omitting the -n from git clean is dangerous

Comment on lines +31 to +36
A `git merge` is only one of two ways to combine someone else's work (or the work
on another branch) with your own. The other is called a **rebase**.

- In a **merge**, Git adds a new _merge commit_ that brings the two branches
together. **Both histories are kept**, and the graph shows a divergence
followed by a convergence.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I felt that this misrepresented git merge (which as you explain later can fast forward)

Suggested change
A `git merge` is only one of two ways to combine someone else's work (or the work
on another branch) with your own. The other is called a **rebase**.
- In a **merge**, Git adds a new _merge commit_ that brings the two branches
together. **Both histories are kept**, and the graph shows a divergence
followed by a convergence.
Merging and rebasing are two common ways to combine work from different branches:
- When **diverged branches are merged**, Git preserves their existing commits and normally creates a new _merge commit_ that joins the two histories.

Comment on lines +69 to +75
```bash
python -m pytest tests/test_conversion.py # passes?
git bisect good

python -m pytest tests/test_conversion.py # fails?
git bisect bad
```

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to explain this like:

Suggested change
```bash
python -m pytest tests/test_conversion.py # passes?
git bisect good
python -m pytest tests/test_conversion.py # fails?
git bisect bad
```
```bash
python -m pytest tests/test_conversion.py
```
If it passes, mark the current commit as good:
```bash
git bisect good
```
Or, if it fails, mark the current commit as bad:
```bash
git bisect bad
```

Comment on lines +117 to +120
:::callout{variant="tip"}
This is a strong argument for keeping a good test suite: with automated tests,
finding _when_ a regression was introduced becomes a single command.
:::

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean it isnt a single command, requires setup and repeated commands but shall we say...

Suggested change
:::callout{variant="tip"}
This is a strong argument for keeping a good test suite: with automated tests,
finding _when_ a regression was introduced becomes a single command.
:::
:::callout{variant="tip"}
This is a strong argument for keeping a good test suite: with automated tests and bisect,
finding _when_ a regression was introduced becomes a much simpler process.
:::

Comment on lines +73 to +74
If `..` is used with nothing after it, `HEAD` is assumed, so `v1.0..` means
"everything after v1.0, up to now".

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since "everything after v1.0" implies a linear history, IK thought the following was better

Suggested change
If `..` is used with nothing after it, `HEAD` is assumed, so `v1.0..` means
"everything after v1.0, up to now".
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.


| Centralised (cvs, svn) | Distributed (git, mercurial) |
| ---------------------------------- | ------------------------------------- |
| Server holds the history | Every clone has the _full_ history |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aorry, peantry drives this cahnge (sahllow clones)

Suggested change
| Server holds the history | Every clone has the _full_ history |
| Server holds the history | A normal clone has the _full_ history |

Comment on lines +31 to +33
Older version control systems (like CVS and Subversion) were **centralised**: the
history lived only on a server, and almost every operation required an internet
connection.

@alasdairwilson alasdairwilson Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this perhaps minimsed these toosl, both that they needed internet,might be a locla server, and that every opoeration needed the server.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Update git course with intermediate material

3 participants