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:

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 ⭐️

  1. Download the scaffold for this week’s FP exercises. Unzip it, and initialize a local Git repository in the root directory of the exercises.

  2. Commit the scaffold on the main branch.

  3. Create a branch for each exercise. Commit your solutions regularly as you make progress on each exercise. Make sure that you know how to:

    1. Create a branch
    2. Switch between branches
    3. Compare two branches with git diff

Resolving divergences: Patching

  1. Read up on git reset and git reset --hard. What do these commands do? Experiment with them until you can confidently predict their results.

  2. Collect all changes from your various branches onto the main branch using each of the following techniques:

    1. ⭐️ format-patch, switch, am
    2. cherry-pick
  3. What happens if you apply the same patch multiple times, or cherry-pick the same commits multiple times?

Resolving divergences: Merging

  1. Reset main to its initial state.

  2. Collect all changes from your various branches onto the main branch using each of the following techniques:

    1. ⭐️ Individual merges.
    2. A single octopus merge with all branches.
    3. A series of --ff-only merges, using rebase on each branch before merging it.
  3. 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 🔥

  1. 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.

  2. 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

  1. Make sure that you have configured Git to use the diff3 style (git config --global merge.conflictStyle diff3).

  2. ⭐️ 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.

  3. Reset main, then use cherry-picks to move both commits to it. Resolve the conflict again and finish the cherry-pick.

  4. Reset main, then rebase one of the two branches onto the other. Resolve the conflict again and finish the rebase.