Day 13

For Next Time

Reading Journal Debrief

Since you’ll be working with a partner on MP4, good Git habits are all the more important. As you first start working together, you should discuss some team ground rules and expectations, including version control practices.

Exceptions

Read about Exceptions and try some examples

Exercise: Examine your code for MP3 and identify places where errors are likely to occur - make a list and be specific. Common culprits include anywhere you take input from a user, from the web, a database, or the filesystem. Decide what types of exceptions should be raised in each case and how they should be handled. Try implementing at least one exception in your code.

Assertions

Read about Assertions and try some examples

Exercise: Take 2-3 of your functions from MP3 (or a past miniproject) and make your assumptions explicit by adding assertions. There’s a bit of an art to using assertions - if you defensively try to account for every single thing that could go wrong you’ll wind up with an unreadable mountain of tests for a small amount of code. Try to aim for the most impactful checks - things most likely to go wrong/be misused, and those most likely to be difficult to debug if used incorrectly.

Git merge conflicts

Since you’ll soon have more than one person working on code at the same time, you may encounter a situation where each of you have made modifications to the same file. When this happens, you need to go through a process to decide how to blend these changes together into a single new version. Read about resolving merge conflicts.

Exercise: resolving merge conflicts

Let’s create a merge conflict so we can practice resolving it. Follow along with these commands and try it yourself. We’re going to do everything locally, but you can imagine that repo1 and repo2 belong to you and your partner on separate machines - everything works the same way.


# Create new Git repository and commit a file
$ mkdir repo1
$ cd repo1/
$ git init
$ echo -e "Knock knock\nWho's there?" > joke.txt
$ git add joke.txt 
$ git commit -m "Add joke setup"

# Clone the repo (simulating a partner)
$ cd ..
$ git clone repo1/ repo2
$ cd repo2

# Make a change in both repos simultaneously (merge conflict)
$ cd ../repo1/
$ echo "Interrupting cow" >> joke.txt 
$ git commit -a -m "Cows are always funny"
$ cd ../repo2/
$ echo "Banana" >> joke.txt 
$ git commit -a -m "Fruit-based jokes are the best"

So now we’ve got a merge conflict brewing. Two copies of the repository started from the same commit (the joke setup) but made diverging changes. Let’s see what that looks like, and how to resolve it:

# From within repo2:
$ git pull origin master
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/ben/merge_example/repo1
 * branch            master     -> FETCH_HEAD
   b056309..2d02106  master     -> origin/master
Auto-merging joke.txt
CONFLICT (content): Merge conflict in joke.txt
Automatic merge failed; fix conflicts and then commit the result.

Here Git is attempting to merge the two repository contents automatically for you. Many times it can do so successfully (e.g. if you have each changed different files, it will merge by creating a commit that has both of your changes). But in this case, we’ve edited the same part of the same file, so a choice must be made by a human about what should stay and what should go.

At this point, the contents of joke.txt in repo2 look like this:

Knock knock
Who's there?
<<<<<<< HEAD
Banana
=======
Interrupting cow
>>>>>>> 2d0210609e38d9f38bb48d8a77fbf57c3d05d15c

Git has inserted these markers around the two choices that need to be resolved. We fix the merge conflict by choosing one of the options, removing the other option and the marker lines (<<..., ==..., and >>...), and then committing the file.

You can use any text editor you like to do this, but Atom is particularly nice since it is aware of how git works (you can actually do everything including writing commit messages within Atom, feel free to explore on your own). If you open the conflicted file in Atom, it presents you with buttons like this:

Clicking one of them automatically performs the edits described above. With those changes made and saved, the last step is to commit the merge:

$ git add joke.txt
$ git commit -m "Resolved merge conflict (cows rule)"

At this point the merge conflict is resolved in repo2. In your actual workflow you would then want to push the merge resolution commit to a shared location, so that repo1 can pull it and both partners can work from a common history again.

So: merge conflicts are nothing to be afraid of, but they certainly are annoying. Some concrete suggestions for avoiding merge conflicts

Going Beyond: Git branches

What is the “master” in git push origin master? It’s the name of a branch!

Developers often use branches to work on a new feature (without halting ongoing development on the master branch). Then once the feature is complete and tested, they can merge it back into master.

To see this visually, work through the first three levels of “Learn Git Branching