Last updated on
Git II: Distributed version control
Here are a few questions, exercises, and resources to guide your exploration of version control systems (part 2). Please do ask on Ed or in exercise sessions if anything is unclear!
If you ask a complex Git question on Ed, it will often be much easier for us to help you debug if you include a copy of your repo. For this, post your repo as a git bundle
in a private Ed post (look up the documentation of git bundle
to know what it does).
Make sure you have good backups before experimenting with your computer on the command line!
These exercises are written with just enough information to specify what to do, but they don’t specify how to do it. We expect you to look things up in the manual pages, online, or to discuss it among yourselves. But whichever source you use, make sure that you understand what you are doing! Don’t just blindly copy-paste commands.
As usual, ⭐️ indicates the most important exercises and questions and 🔥 indicates the most challenging ones. Exercises or questions marked 🧪 are intended to build up to concepts used in this week’s lab.
You do not need to complete all exercises to succeed in this class, and you do not need to do all exercises in the order they are written.
Using a Git UI
Some advanced Git users prefer the command line, but most have a favorite UI. Decide whether you prefer to work on the command line or graphically. If you decide to go the graphical route, make sure that UI supports the following features:
diff3
conflict indicators (equivalent togit config --global merge.conflictStyle diff3
)- Line-range history, which shows you the evolution of a range of lines (equivalent to
git log -L
) - Partial and interactive staging (equivalent to
git add -i
) - Word-level diffs and space-agnostic diffs (equivalent to the
--word-diff=color
and--ignore-all-space
flags ofgit diff
)
The UI that I demonstrated in class was Magit, a package for Emacs. Staff members use a mix of Emacs, Neovim, VS Code, plain command line, and a few other editors.
Configure Git text editor
If you plan to use the command line, configure which text editor Git will use for editing commit messages and other interactions. See Git I for tips on how to do this.
Creating branches ⭐️
-
Download the scaffold for this week’s FP exercises. Unzip it, and initialize a local Git repository in the root directory of the exercises.
-
Commit the scaffold on the
main
branch. -
Create a branch for each exercise. Commit your solutions regularly as you make progress on each exercise. Make sure that you know how to:
- Create a branch
- Switch between branches
- Compare two branches with
git diff
Resolving divergences: Patching
-
Read up on
git reset
andgit reset --hard
. What do these commands do? Experiment with them until you can confidently predict their results. -
Collect all changes from your various branches onto the
main
branch using each of the following techniques:- ⭐️
format-patch
,switch
,am
cherry-pick
- ⭐️
-
What happens if you apply the same patch multiple times, or cherry-pick the same commits multiple times?
Resolving divergences: Merging
-
Reset
main
to its initial state. -
Collect all changes from your various branches onto the
main
branch using each of the following techniques:- ⭐️ Individual merges.
- A single octopus merge with all branches.
- A series of
--ff-only
merges, usingrebase
on each branch before merging it.
-
What happens if you try to merge the same branch multiple times? What happens if you merge a branch, add commits to it, and merge it again?
History editing 🔥
-
Find an exercise branch on which you had a suboptimal history: either a bad commit message, or multiple partial commits that would have been better as one, or a single commit that solves multiple parts of an exercise, etc.
-
Use interactive rebasing (
git rebase -i
) to perform the following:- Split a single commit into multiple
- Combine multiple consecutive commits into a single one
- Reword a commit message
- Reorder commits
Conflicts
-
Make sure that you have configured Git to use the
diff3
style (git config --global merge.conflictStyle diff3
). -
⭐️ Pick a branch containing a complex exercise, create two branches from it, and make different changes to the same piece of code on both branches. Merge one branch into
main
, then the second. What happens during the second merge? Resolve the conflict and commit the merge. -
Reset
main
, then use cherry-picks to move both commits to it. Resolve the conflict again and finish the cherry-pick. -
Reset
main
, then rebase one of the two branches onto the other. Resolve the conflict again and finish the rebase.