<style>
/* Formatting for the title slide */
.title {
text-align: center;
}
/* Formatting for body text */
section {
font-size: 36px;
text-align: left;
}
/* Formatting for image credits */
.credit {
font-size: 10px;
}
/* Formatting for columns of content */
.columns {
column-count: 2;
text-align: justify;
}
/* Formatting for code blocks */
code {
/* Automatic line wrapping */
white-space : pre-wrap !important;
}
</style>
## Intermediate Git and GitHub
#### Assumed knowledge
In this course, we assume familiarity with the following Git commands and GitHub concepts:
* `add`, `commit`, `push`, `pull`, `log`
* Issues
* Pull requests (PRs)
If these are new to you then please join the *Introduction to Git and GitHub for Beginners* course, which is running in parallel.
<!--
Presenter notes:
Have this slide up for the first 5 minutes while people arrive.
-->
---
<div class="title">
# Intermediate Git and GitHub
Joe Wallwork and Tom Meltzer
Slides: https://hackmd.io/@jwallwork/2024-07-10-intermediate-git-tools?type=slide
GitHub repo: https://github.com/Cambridge-ICCS/intermediate-git-iccs-summer-school-2024
</div>
---
## Contents
1. Branching and conflicts.
2. Intermediate Git commands.
3. Software engineering with GitHub.
4. Tips, tricks, and fun stuff!
---
## GitHub <i class="fa fa-github"></i>
Navigate to the GitHub repo: https://github.com/Cambridge-ICCS/intermediate-git-iccs-summer-school-2024
#### Exercises
1. Check you are happy with the contents of the README.
2. Create a fork of the repo under your username.
3. Clone your fork to your local machine.
<!--
Presenter notes:
Navigate to the repository, show the README, and ask to take a look around.
Allow 5 minutes for this task and then give a quick tour.
-->
---
# 1. Branching and conflicts
---
## Branching basics
The `main` branch is protected in our repo, meaning contributors cannot push directly to it. (More on this later.)
To contribute to `main`, create a branch for your developments and open a PR when it's ready.
<img src="https://hackmd.io/_uploads/ryQ9nibPC.svg" alt="git_branching.drawio" width="600"/>
---
## Branching basics
The `main` branch is protected in our repo, meaning contributors cannot push directly to it. (More on this later.)
To contribute to `main`, create a branch for your developments and open a PR when it's ready.
<img src="https://hackmd.io/_uploads/ryQ9nibPC.svg" alt="basic_branch.drawio" width="600"/>
:::info
:bulb: Shortcut to create a new branch and switch to it:
`git switch -c <branchname>`
:::
---
## Branch-of-branch
Suppose `mybranch` adds a significant new feature. What if you spot a bug and have a fix for it?
<img src="https://hackmd.io/_uploads/ByC62j-w0.svg" alt="branch_of_branch.drawio.drawio" width="800"/>
---
## `develop` branch
Large codes often have a `develop` branch in addition to the `main` branch.
<img src="https://hackmd.io/_uploads/Hy8baiZwC.svg" alt="develop_branch.drawio" width="800"/>
---
## Merge conflicts
What if two branches modify the same part of a file?
<img src="https://hackmd.io/_uploads/B1RETsZw0.svg" alt="merge_conflict.drawio" width="800"/>
---
## Merge conflict example
Consider the following enhancements to `equation_of_line`:
[#12](https://github.com/Cambridge-ICCS/intermediate-git-iccs-summer-school-2024/pull/12): Implement Lagrange polynomial approach.
[#13](https://github.com/Cambridge-ICCS/intermediate-git-iccs-summer-school-2024/pull/13): Check that the points provided differ.
[#14](https://github.com/Cambridge-ICCS/intermediate-git-iccs-summer-school-2024/pull/14): Implement SymPy approach.
<!--
Presenter notes:
1. The first merge will be fine.
2. The second merge will be fine.
3. The third merge will hit a conflict!
When we hit the conflict, we have to decide what to do. Options:
a) Drop the SymPy change because we don't want another dependency.
b) Drop the error check because SymPy does it anyway.
c) Use both because we want our own error check.
-->
---
# 2. Intermediate Git commands
---
## Checking state: `git status`
Snapshot of changes staged and not staged for commit.
```git
On branch mybranch
Your branch is up-to-date with 'origin/mybranch'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: README.md
renamed: maths.py -> mathematics.py
new file: physics.py
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: test_maths.py
Untracked files:
(use "git add <file>..." to include in what will be committed)
tmp.patch TODO
```
:::info
:bulb: Check this regularly!
:::
---
## Checking state: `git diff`

Useful but not meant for human consumption :male-detective:
:::info
:bulb: See also `git show <branch/commit-hash>`
:::
---
## Checking state: `git difftool`

- Syntax highlighting AND context
- Much easier to read :eyes:
---
## Checking state: `git difftool`
Configure by adding the following to your `~/.gitconfig`:
```gitconfig
[diff]
tool = vimdiff
[difftool]
prompt = false
```
Or run these commands:
```git
git config --global diff.tool vimdiff
git config --global difftool.prompt false
```
:::info
:keyboard: **Exercise**
Configure using one of the methods above.
`git switch `[`example-diff`](https://github.com/Cambridge-ICCS/intermediate-git-iccs-summer-school-2024/tree/example-diff)
`git diff 2df42ae`
`git difftool 2df42ae`
:::
---
## Temporary work: `git patch`
I need to put aside temporary work and do some branch manipulations. How?
```sh
git diff > my_patch.patch # Stash your current changes
git restore . # Restore latest commit
# <Do the required branch manipulations>
git apply my_patch.patch # Reapply changes from the patch
```
<!--
Presenter notes:
Patch files were introduced before centralised version control systems. Contributors could email patch files to provide updates to a codebase.
-->
---
## Temporary work: `git patch`
I need to put aside temporary work and do some branch manipulations. How?
```sh
git diff > my_patch.patch # Stash your current changes
git restore . # Restore latest commit
# <Do the required branch manipulations>
git apply my_patch.patch # Reapply changes from the patch
```
:::info
:bulb: Apply patch in reverse:
`git apply -R my_patch.patch`
:::
---
## Temporary work: `git patch`
I need to put aside temporary work and do some branch manipulations. How?
```sh
git diff > my_patch.patch # Stash your current changes
git restore . # Restore latest commit
# <Do the required branch manipulations>
git apply my_patch.patch # Reapply changes from the patch
```
:::warning
:house: **Subversion users: do try this at home**
`svn diff > svn.patch && git apply svn.patch`
`git diff > git.patch && svn patch git.patch`
:::
---
## Temporary work: `git stash`
*Why do I keep finding `tmp.patch` files everywhere?*
Stashing changes puts them on the *stack*.
<div class="columns">
```sh
git stash
# <Do the required branch manipulations>
git stash pop
```

</div>
`git stash list`
```git
stash@{0}: WIP on impl3: 8895c93 Add SymPy as a dependency
stash@{1}: WIP on check_points_differ: a92866d Raise error if points are identical
stash@{2}: WIP on main: a58ff9a Merge pull request #9 from Cambridge-ICCS/impl1
```
---
## Editing history: `git rebase` :trophy:
Some common problems:
1. I want to drop some commits from my branch.
2. I want to reword a commit message.
3. I want to squash some commits in my branch.
4. I want to change the 'base' of my branch to start at the head of another branch.
All these things (and more) can be done with `git rebase` - one of the most powerful Git tools.
---
## Editing history: `git rebase` :trophy:
*I want to change the 'base' of my branch to start at the head of another branch.*
Consider the simple case of upgrading to a later version.
<img src="https://hackmd.io/_uploads/HkhOg2bv0.svg" alt="rebase.drawio" width="800"/>
---
## Editing history: `git rebase` :trophy:
Some common problems:
1. I want to drop some commits from my branch.
2. I want to reword a commit message.
3. I want to squash some commits in my branch.
4. I want to change the 'base' of my branch to start at the head of another branch.
:::info
:keyboard: **Exercise**
Run an interactive rebase (`git rebase -i <target>`) on branch [`rebase-exercise`](https://github.com/Cambridge-ICCS/intermediate-git-iccs-summer-school-2024/tree/rebase-exercise) to complete tasks 1-4.
:::
<!--
Demonstrator notes:
Point out the help text!
Discuss rebase vs merge.
-->
---
## Editing history: `git reflog`
Ahh, my rebase broke things! How can I reverse it?
```auto!
92d0571 (HEAD -> rebase-exercise, origin/rebase-exercise) HEAD@{0}: commit: Instructions for task 4
e6509be HEAD@{1}: commit: Drop this commit
3131c09 HEAD@{2}: commit: Reword this commit message
007117a HEAD@{3}: commit: Squash this commit into the previous one
09a6337 HEAD@{4}: commit: Squash the following commit into this one
93212e5 (origin/main, origin/HEAD, main) HEAD@{5}: checkout: moving from main to rebase-exercise
```
Go back to an earlier state with (for example)
`git reset --hard 3131c09`.
Note that the `reset` goes in the `reflog`, too!
:::danger
:warning: **Warning**
The `--hard` option is potentially destructive.
:::
---
# 3. Software engineering with GitHub
---
## GitHub: Project boards
The example repository has a [Project Board](https://github.com/orgs/Cambridge-ICCS/projects/34/views/1) for planning and tracking progress.
:::success
:computer: **Live demo**
:::
:::info
:keyboard: **Exercise**
Try setting up a project board for your fork.
:::
Note: project boards are associated with users or organisations, rather than repositories.
<!--
Presenter notes:
* Show how to remove limits on numbers of issues in each column.
* Note including the following in the PR text box: `Closes #<ISSUE_NUMBER>`.
* Add "review required" and "blocked" columns.
* Discuss milestones.
If there is time for the exercise then leave 5 minutes for this.
-->
---
## GitHub Actions: cloud testing
From [Wikipedia](https://en.wikipedia.org/wiki/Continuous_integration):
> Continuous integration (CI) is the practice of integrating source code changes frequently and ensuring that the integrated codebase is in a workable state.
CI testing is the part that ensures the codebase is in a 'workable state'.
This was added to the example repo in [#9](https://github.com/Cambridge-ICCS/intermediate-git-iccs-summer-school-2024/pull/9).
<!--
Presenter notes:
Go to the PR and walk through changes.
Discuss how tests initially failed and we were able to spot a typo.
-->
---
## GitHub: Files to always include
* `LICENSE`: Sets out how the code may be interacted with (e.g., can it be redistributed?)
* `README.md`: Tells users what the repository is for and important details about its usage (e.g., installation instructions).
---
## GitHub: Settings to always use
* Protect `main` branch.
* Ensure tests pass before merging PRs.
* Require PR approvals.
* Do not allow bypassing rules.
:::info
:keyboard: **Exercise**
Set these up on your fork of the example repository.
Hint: [https://github.com/<username>/intermediate-git-iccs-summer-school-2024/settings/branches](https://github.com/Cambridge-ICCS/intermediate-git-iccs-summer-school-2024/settings/branches)
:::
<!--
Allow 5 minutes for the exercise then click the link to demo what would be required.
-->
---
## Debugging on GitHub Actions
Debug GitHub Actions using [tmate](https://github.com/mxschmitt/action-tmate)
```yaml
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup tmate session
uses: mxschmitt/action-tmate@v3
```
:::success
:computer: **Live demo**
:::
:::warning
:house: **Do try this at home**
:::
---
# 4. Tips, tricks, and fun stuff!
*The following slides are for information. We might not get to them in the live course.*
---
## `git bisect`: a debugging life-saver
A bug was introduced somewhere in the development process, but it's unclear when. What do I do? :shrug:

:::warning
:house: **Do try this at home**
https://github.com/TomMelt/git-bisect-demo
:::
<!--
Presenter notes:
Live demo requires around 20 minutes.
-->
---
## GitHub Container Registry
* Like DockerHub but easier to integrate with GitHub
* Store container images on your account
* Inherit project permissions or set granular permissions
```yaml
runs-on: ubuntu-latest
container:
image: ghcr.io/<YOUR_USERNAME>/<IMAGE_NAME>:<IMAGE_TAG>
credentials:
username: <YOUR_USERNAME>
password: ${{ secrets.DOCKER_CONTAINER_REGISTRY_TOKEN }}
```
:::info
For more info, please see GitHub's [documentation](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#about-the-container-registry)
:::
---
## `.gitignore`
Does this `git status` look familiar to anyone?
```git
On branch main
Your branch is up-to-date with 'origin/main'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
FIXME
Notes.txt
TODO
__pycache__/
a.out
job.err
job.out
maths.py.swp
output.nc
test_maths.py.swp
tmp.patch
tmp2.patch
```
---
## `.gitignore`
Ignore certain subdirectories, filename patterns, and/or extensions with a `.gitignore` file. For example:
```git
# Directories
__pycache__/
# Other common files
FIXME
NOTES
Notes.txt
TODO
# File extensions
*.*.swp
*.err
*.nc
*.out
*.patch
*.pyc
```
---
## `git config`
Recall how we configured `git difftool` with a `.gitconfig` file. We can do the same for other Git commands:
```gitconfig
[user]
name = Joe Bloggs # User credentials to be used in
email = j.bloggs@blogco.com # commits
[init]
defaultBranch = trunk # Default branch other than 'main'
[core]
commentChar = & # Comment character other than '#'
excludesFile = ~/.gitignore # Global .gitignore file
[column]
ui = auto # Allow multi-column output
[alias]
ci = commit # Aliases/shortcuts for Git commands
co = checkout # (Any subversion users in the
st = status # room?)
```
---
## Fun stuff :balloon:
:::warning
:house: **Do try these at home**
* `git blame`
* `git commit -p`
* `git log -p`
* `git diff --name-only`
* `git diff --word-diff`
* [Semantic commit messages](https://gist.github.com/joshbuchea/6f47e86d2510bce28f8e7f42ae84c716)
:::
<!--
* [Git butler](https://gitbutler.com/)
-->
---
# Thank you for attending!
{"description":"Software engineering using Git and GitHub for intermediate users.","title":"Intermediate Git and GitHub","contributors":"[{\"id\":\"033ac354-bcb8-4c50-8db3-75282f8d798a\",\"add\":22989,\"del\":9383},{\"id\":\"dc15f293-368c-4ca5-9e71-50ccc99f6028\",\"add\":1297,\"del\":500}]"}