List of exercises
Full list
This is a list of all exercises and solutions in this lesson, mainly as a reference for helpers and instructors. This list is automatically generated from all of the other pages in the lesson. Any single teaching event will probably cover only a subset of these, depending on their interests.
Quick recap on Git Basics: Commits and Branches
Exercise
In order to achieve an equivalent result, you need to
clone the repository https://github.com/coderefinery/recipe-book locally on your computer
create a properly named repository on the forge of your choice
push the newly created repository there.
Detailed steps
Please follow these steps. The Bash command needed for each step are shown along.
create a directory called
centralized-workflow-exercise
on your computer.mkdir centralized-workflow-exercise
clone the repository https://github.com/coderefinery/recipe-book on your computer in the directory you just created:
git clone https://github.com/coderefinery/recipe-book
Log into your preferred forge and create an empty and public repository called
recipe-book
.On GitLab, click the blue “New Project” button on the top right part of the page. Among other things, remember to:
Choose “Blank Project”,
Set the Visibility Level to be Public (this can be changed later)
untick the box close to “Initialize repository with a README”
On codeberg.org, click the
+
symbol on the top right corner of the page, and Choose the “New Repository” option.
Add the remote to your local repository. In this case, we will use the name of the forge as the name of the remote. If you configured ssh access:
git remote add <forge-name> git@<forge-name>:<username>/recipe-book
If not, you can try https instead:
git remote add <forge-name> https://<forge-name>/<username>/recipe-book
Push the main branch there:
git push <forge-name> main
Have a look at the Authentication: connecting to the repository from your computer section if you have troubles problems during the push.
Exercise: Practice creating commits and branches (20 min)
Make sure that you now work on your fork of the recipe-book repository (
USER/recipe-book
, notcoderefinery/recipe-book
)First create a new branch and then add a recipe to the branch and commit the change.
In a new commit, modify the recipe you just added.
Switch to the
main
branch and modify a recipe there.Browse the network and locate the commits that you just created (“Insights” -> “Network”).
Compare the branch that you created with the
main
branch. Can you find an easy way to see the differences?Can you find a way to compare versions between two arbitrary commits in the repository?
Try to rename the branch that you created and then browse the network again.
Try to create a tag for one of the commits that you created (on GitHub, create a “release”).
Inspecting history
Exercise: Explore basic archaeology commands (20 min)
Let us explore the value of these commands in an exercise. Future exercises do not depend on this, so it is OK if you do not complete it fully.
Exercise steps:
Make sure you are not inside another Git repository when running this exercise. If you are, first step “outside” of it. We want to avoid creating a Git repository inside another Git repository.
You can check if you are inside a Git repository with:
$ git status fatal: not a git repository (or any of the parent directories): .git
You want to see the above message which tells us that this is not a Git repository.
This is not a problem in the GitHub web interface since we are not creating a new local repository.
Warning: many of these exercise tasks aren’t possible in the VS Code interface without extensions. You can use VS Code to clone the project, but be prepared to start the terminal to do the main tasks.
“File” → “New Window”.
Warning: many of these exercise tasks aren’t possible in the RStudio interface. You can use RStudio to clone the project, but be prepared to start the terminal to do the main tasks.
File → New Project.
Clone this repository: https://github.com/networkx/networkx.git.
$ git clone https://github.com/networkx/networkx.git
Nothing to clone. We will try to inspect the repository directly on GitHub.
From a new VS Code window, select “Clone Git repository” and enter that URL.
From the new project window, choose Version Control → Git → and enter the URL
Then let us all make sure we are working on a well-defined version of the repository.
Step into the new directory and create an exercise branch from the networkx-2.6.3 tag/release:
$ cd networkx $ git switch --create exercise networkx-2.6.3
On old Git versions which do not know the
switch
command (before 2.23), you need to use this instead:$ git checkout -b exercise networkx-2.6.3
We can visit the version directly: https://github.com/networkx/networkx/tree/networkx-2.6.3
Switch to “Source Control”, then the “…” menu, then “Branch”, then “Create new branch from…” and select “networkx-2.6.3”.
Use the command line method (but you don’t need to
cd networkx
, the RStudio terminal starts in the right place.) So, run this:$ git switch --create exercise networkx-2.6.3
(and if it doesn’t work, check Command Line for the command for older git)
Then using the above toolbox try to:
Find the code line which contains
"Logic error in degree_correlation"
.Find out when this line was last modified or added. Find the actual commit which modified that line.
Inspect that commit with
git show
.Create a branch pointing to the past when that commit was created to be able to browse and use the code as it was back then.
How would you bring the code to the version of the code right before that line was last modified?
Solution
We provide here a solution for the command line but we also encourage you to try to solve this in the browser.
We use
git grep
:$ git grep "Logic error in degree_correlation"
This gives the output:
networkx/algorithms/threshold.py: print("Logic error in degree_correlation", i, rdi)
Maybe you also want to know the line number:
$ git grep -n "Logic error in degree_correlation"
We use
git annotate
:$ git annotate networkx/algorithms/threshold.py
Then search for “Logic error” by typing “/Logic error” followed by Enter. The last commit that modified it was
90544b4fa
(unless that line changed since).We use
git show
:$ git show 90544b4fa
Create a branch pointing to that commit (here we called the branch “past-code”):
$ git branch past-code 90544b4fa
This is a compact way to access the first parent of
90544b4fa
(here we called the branch “just-before”):$ git switch --create just-before 90544b4fa~1
(optional) History-2: Use git bisect to find the bad commit
In this exercise, we use git bisect
on an example repository. It
is OK if you do not complete this exercise fully.
Begin by cloning https://github.com/coderefinery/git-bisect-exercise.
Motivation
The motivation for this exercise is to be able to do archaeology with Git on a source code where the bug is difficult to see visually. Finding the offending commit is often more than half the debugging.
Background
The script get_pi.py
approximates pi using terms of the Nilakantha series. It
should produce 3.14 but it does not. The script broke at some point and
produces 3.57 using the last commit:
$ python get_pi.py
3.57
At some point within the 500 first commits, an error was introduced. The only thing we know is that the first commit worked correctly.
Your task
Clone this repository and use
git bisect
to find the commit which broke the computation (solution - spoiler alert!).Once you have found the offending commit, also practice navigating to the last good commit.
Bonus exercise: Write a script that checks for a correct result and use
git bisect run
to find the offending commit automatically (solution - spoiler alert!).
Hints
Finding the first commit:
$ git log --oneline | tail -n 1
How to navigate to the parent of a commit with hash SOMEHASH:
$ git switch --create BRANCHNAME SOMEHASH~1
Instead of a tilde you can also use this:
$ git switch --create BRANCHNAME SOMEHASH^
Optional: Git Internals
Changes and their effect: files and commits
Refer to the figure above, and discuss: which SHA-1 hashes would change in the diagram if:
the content of the first file is changed,
we recreate a commit with another message or author
we recreate a commit with the same message or author
Is it possibe to have multiple commits refer to the same tree?
What happens when you use git revert
?
Solution
When reverting a commit B that happens after a commit A, the new commit will point at the same tree as A.
A look at the objects
Let us poke a bit into raw objects! Start with:
$ git cat-file -p HEAD
Then explore the tree
object, then the file
object, etc. recursively using the hashes you see.
Operating on Branches
Exercise
By changing the content of .git/HEAD
we have manually “switched”
from a branch
to another one
that actually points
to the same commit.
What would have happened if we changed HEAD to point to a branch
that does not point to the same commit
as the one we were on before?
What would we see with git status
?
Branches on different repositories
How are branches on different repositories related to each other?
Solution
After creating a branch, one can use the --set-upstream-to
options
$ git branch <new-branch>
$ git branch <new-branch> --set-upstream-to=<remote>/<branch>
to set the default upstream branch.
When pushing, it is possible to use the verbose command:
$ git push <repository> <local-branch>:<remote-branch>
Typically <local-branch>
and <remote-branch>
are the same,
and :<remote-branch>
is omitted it is assumed to be equal to <local-branch>
.
git push
can also use the default upstream branch
if configured correctly:
$ git config --local push.default upstream
But typically there is no need for such complex setups.
Concepts around collaboration
Exercise
What is the difference between forking and then cloning (your fork, to your computer) vs cloning (to your computer) and then pushing to a brand new repository?
Solution
Forking on a forge and then cloning creates links:
from your fork to the original repository;
from clone to your fork.
When cloning and then pushing to a new repository, you will create links:
from your clone to the original repository;
from your clone to the new repository.
Your repository on the forge will not have a link to the original repository and will not be listed as a fork of the original repository.
Collaborating within the same repository: issues and pull requests
Exercise
In order to achieve an equivalent result, you need to
clone the repository https://github.com/coderefinery/template-centralized-workflow-exercise locally on your computer
delete the
.git
directory to get rid of all the historyre-initialize the repo in the directory
add the content of the directory and create a first commit
create a properly named repository on the forge of your choice
push the newly created repository there.
Detailed steps
Please follow these steps. The Bash command needed for each step are shown along.
create a directory called
centralized-workflow-exercise
on your computer.mkdir centralized-workflow-exercise
clone the repository https://github.com/coderefinery/template-centralized-workflow-exercise on your computer in the directory you just created:
git clone https://github.com/coderefinery/template-centralized-workflow-exercise \ centralized-workflow-exercise
We need to delete the whole history to avoid distractions. To do this, remove the
.git
directory:rm -r centralized-workflow-exercise/.git
Initialize again the repository:
cd centralized-workflow-exercise git init
Add everything
git add . # '.' means the whole repository
Create a first commit
git commit -m "Initial commit"
Log into your preferred forge and create an empty and public repository called
centralized-workflow-exercise
.On GitLab, click the blue “New Project” button on the top right part of the page. Among other things, remember to:
Choose “Blank Project”,
Set the Visibility Level to be Public (this can be changed later)
untick the box close to “Initialize repository with a README”
On codeberg.org, click the
+
symbol on the top right corner of the page, and Choose the “New Repository” option.
Add the remote to your local repository. In this case, we will use the name of the forge as the name of the remote. If you configured ssh access:
git remote add <forge-name> git@<forge-name>:<username>/centralized-workflow-exercise
If not, you can try https instead:
git remote add <forge-name> https://<forge-name>/<username>/centralized-workflow-exercise
Push the main branch there:
git push <forge-name> main
Have a look at the Authentication: connecting to the repository from your computer section if you have troubles problems during the push.
Code review demo
Exercise: Practicing code review (25 min)
Technical requirements:
If you create the commits locally: Being able to authenticate to your preferred forge
What should be familiar:
Creating a branch (lesson from CodeRefinery)
Committing a change on the new branch (lesson from CodeRefinery)
Opening and merging pull requests (lesson from CodeRefinery)
What will be new in this exercise:
As a reviewer, we will learn how to ask for changes in a pull request.
As a reviewer, we will learn how to suggest a change in a pull request.
As a submitter, we will learn how to modify a pull request without closing the incomplete one and opening a new one.
Exercise tasks:
Create a new branch and one or few commits: in these improve something but also deliberately introduce a typo and also a larger mistake which we will want to fix during the code review.
Open a pull request towards the main branch.
As a reviewer to somebody else’s pull request, ask for an improvement and also directly suggest a change for the small typo. (Hint: suggestions are possible through the GitHub web interface, view of a pull request, “Files changed” view, after selecting some lines. Look for the “±” button.)
As the submitter, learn how to accept the suggested change. (Hint: GitHub web interface, “Files Changed” view.)
As the submitter, improve the pull request without having to close and open a new one: by adding a new commit to the same branch. (Hint: push to the branch again.)
Once the changes are addressed, merge the pull request.
How to contribute changes to repositories that belong to others
Interrupted work
Interrupted-1: Stash some uncommitted work
Make a change.
Check status/diff, stash the change with
git stash
, check status/diff again.Make a separate, unrelated change which doesn’t touch the same lines. Commit this change.
Pop off the stash you saved with
git stash pop
, and check status/diff.Optional: Do the same but stash twice. Also check
git stash list
. Can you pop the stashes in the opposite order?Advanced: What happens if stashes conflict with other changes? Make a change and stash it. Modify the same line or one right above or below. Pop the stash back. Resolve the conflict. Note there is no extra commit.
Advanced: what does
git graph
show when you have something stashed?
Solution
5: Yes you can. With git stash pop INDEX
you can decie which stash
index to pop.
6: In this case Git will ask us to resolve the conflict the same way when resolving conflicts between two branches.
7: It shows an additional commit hash with refs/stash
.
Stashing all
Sometimes we want to stash
files that are not yet tracked by git
(i.e., have not been add
ed).
How would we do that?
Look at the man page using git help stash
.
Solution
By passing the option -a
,
we are telling git stash
to take every file in our working tree,
including untracked and ignored files.
Stash vs commit
In what sense are stashes similar to commits?
Solution
Stashing is roughly equivalent to
```console
git switch -c tempbranch; git add -u; git commit -m 'temp commit'}).
```
In particular, stashes are identified as `commit` objects in the object database,
and they are referenced by `refs/stash` and the reflog of the "stash" reference.
Option 2: Create branches
You can use branches almost like you have already been doing if you need to save some work. You need to do something else for a bit? Sounds like a good time to make a feature branch.
You basically know how to do this:
$ git switch --create temporary # create a branch and switch to it
$ git add PATHS # stage changes
$ git commit # commit them
$ git switch main # back to main, continue your work there ...
$ git switch temporary # continue again on "temporary" where you left off
Tooling and practices that you might find useful
Try them out!
Install and/or configure some of the mentioned tooling that can be helpful for your daily workflow.
Merge and beyond
Predict conflicts
Will the merge between branch-1 and branch-2 cause a conflict? Why?
Solution
Unfortunately, yes. Both versions have appended lines at the end, and Git cannot determine in which order they need to be.
Optional: revert
a merge commit
When reverting a merge commit, it is not clear which is the parent commit to which we want to revert.
Use the -m
option
(--mainline
)
to select the version
you want to revert to.
See the documentation
for git revert
.
Interactive rebase on another branch
You can practice interactive rebase with
$ git switch rebase-me
$ git reset reset --hard d30163f
$ git rebase -i rebase-onto-this
Comments
The option
-m
to add a message is optional. Why use it?Solution
By looking at the output of
git stash list
, it will be much easier to determine which stash we are interested in.