Day 15

Today

Git Merge Conflicts with Minimal Pain

The setup

Suppose you are working on a software project with one other person. You and your partner share a repository on GitHub; you have a local copy of the repo on your laptop, and your partner has a local copy on their laptop.

Initially, there is a file named README.md in the repo, your local copy, and your partner’s local copy; and all three versions are identical.

Now suppose you and your partner want to revise this file. There are several ways you might collaborate:

(1) Time sharing: You could talk to each other and agree that you will not edit the same file at the same time. Instead, one of you will edit the file in your local copy, push the change to the repo, and then tell your partner that you are done. The other partner will pull the modified file, make additional changes, and then push them back to the repo.

(2) Space sharing: You could work on separate files at the same time. Each of you could edit their own files, push changes to the repo, and pull the other partner’s changes from the repo.

(3) [NOT RECOMMENDED] Work in branches: Before you start making changes, you could create a branch, push changes to the branch, and then work on merging the branches in the future.

(4) [NOT RECOMMENDED] Work on the same files, in the same branch, at the same time.

For people who are relatively new to Git, working on relatively small projects, and working part time, we STRONGLY recommend choosing option (1) or (2).

People with more Git experience will try to make you feel bad about these options, and they will badger you into choosing option (3). Ignore them.

However, even if you intend to choose (1) or (2), you are likely to make a mistake at some point and accidentally choose (4). In that case, you are likely to encounter a merge conflict.

What is a merge conflict?

In this document, we use “merge conflict” to refer to any scenario where you and your partner have changed the same file and you need to reconcile your changes.

With Jupyter notebooks, in particular, you should be aware that running a notebook generally modifies the contents, which can cause a merge conflict.

We’ll consider two scenarios, depending on whether the change you have made has been committed.

Scenario I: Local change, not committed

Suppose your partner has modified README.md and pushed the change to the repo. In your local copy, you have also modified README.md, but you have not yet committed the change. Let’s see what happens, and what you can do to resolve it.

1.) Clone a repo on GitHub to make a local copy. If you have a partner, have them clone a local copy, too.

2.) Tell your partner to edit README.md, commit the change, and push it to the repo. Or, if you are working alone, you can simulate the same effect by viewing the repo on GitHub, editing README.md, making a small change, and committing the change.

3.) In you local copy, edit README.md and save the change but don’t commit it. If you run git status, you should see:

modified:   README.md

4.) If you run git pull, you should see:

error: Your local changes to the following files would be overwritten by merge:
	README.md
Please, commit your changes or stash them before you can merge.

This is a merge conflict. There are several ways you might proceed, depending on what changes you and your partner have made.

A: If you don’t care about the changes you have made in your local copy, the easiest thing to do is delete the file that would be overwritten by the merge. Try this:

$ rm README.md
$ git pull

The git pull should succeed now: it should pull the modified version of README.md from the repo, along with any other changes that are in the repo but not in your local copy.

B: If you don’t care about the changes your partner made and you want to replace them with your changes, the easiest thing to do is upload your modified file to GitHub. View your repo in a web browser, navigate to the directory that contains the conflicted file, and press the “Upload files” button. Navigate to your modified file and upload it. Now delete your local copy of the file and git pull again.

B2: Again, if you don’t care about the changes your partner made and you want to replace them with your changes, you can

$ mv README.md README.md.mine
$ git pull
$ mv README.md.mine README.md

And then add README.md, commit and push.

C: If there are changes in both versions that you want to keep, the easiest thing to do is merge them by hand. You can do that by running

$ mv README.md README.md.mine
$ git pull
$ meld README.md README.md.mine

Meld is a graphical program that compares files and makes it easy to merge changes from the two of them until you have what you want. If you don’t already have it installed, run

$ sudo apt-get install meld

Or use whatever text editor you like to move the changes you want to keep from README.md.mine to README.md.

Then add, commit, and push the merged version of README.md as usual.

Scenario II: Local change, committed

Suppose your partner has modified README.md and pushed the change to the repo. In your local copy, you have also modified README.md, and you have committed the change. Let’s see what happens, and what you can do to reconcile it.

1.) Clone a repo on GitHub to make a local copy. If you have a partner, have them clone a local copy, too.

2.) Tell your partner to edit README.md, commit the change, and push it to the repo. Or, if you are working alone, you can simulate the same effect by viewing the repo on GitHub, editing README.md, making a small change, and committing the change.

3.) In you local copy, edit README.md, save the change, and commit it. If you run git status, you should see:

On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

4.) Run git push. You should see

! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'https://github.com/AllenDowney/blair-walden-project.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.

Before you can push your changes to the repo, you have to pull the changes from the repo, resolve any conflicts, and then push your changes back to the repo.

5.) Run git pull. You should see

Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.

This is the first example we have seen that is really a merge conflict in the sense that Git is aware that there is a conflict. If you run git status, you should see

both modified:      README.md

6.) Edit README.md. You will see that Git has combined the changes from the repo and your local copy:

<<<<<<< HEAD
text you added to your local copy
=======
text your partner pushed to the repo
>>>>>>> 98663bb97c1053ed8cc0cc3961a16972a2656e4f

In this example, HEAD refers to the most recent commit in your local copy, and the long hexadecimal string refers to the commit in the repo.

You can use any text editor to edit this file and resolve the conflict as you see fit. Save the resolved file.

Now you should be able to add, commit, and push the resolved file.

  1. As an alternative to Step 6, you can use git mergetool. First, configure git to use meld, rather than whatever inchoate beast from the depths it uses by default:
$ git config merge.tool meld

Then run git mergetool. You should see:

Merging:
README.md

Normal merge conflict for 'README.md':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (meld):

If you hit return, it should launch meld and show you three versions of your file. Edit until the local version is what you want, then add, commit, and push it.

Final Project Ideation

Priming [10 minutes]

Individually, engage with the following prompts that will help you identify some important factors when designing your final project experience.

Project Hopes

My ideal final project would…

For each of these, ask yourself why you care (or don’t) about each of these.

Learning Goals

Identify the learning goals that are most important for you to achieve during the final project. These could be software engineering skills, ways to apply computational principles, teaming strategies, communication skills, etc. If you wind up with a high number of these (> 5), try to either eliminate less important goals or condense similar goals into a single goal.

Individual Project Topic Ideation [7 minutes]

On post-its, jot down ideas for final projects. Once you’ve transferred your ideas to post-its, categorize your ideas based on whether or not they are well-aligned with your project hopes and goals (perhaps group them into low, medium, and high coherence with these).

If you are interested in drawing inspiration from past projects, check out our catalog of SoftDes Final Projects (a work in progress).

Share with your neighbors [15 minutes]

These can be anyone in the class. A good group size is four.

As sharer: Share your hopes and goals. Share two ideas that you came up with that you think are well aligned with your hopes and goals and two ideas that you are either unsure of the alignment or that you think have low / moderate alignment. As you get feedback from the folks you are sharing with, you may consider jotting down new topics or modifying existing ones.

As listener: especially for projects that the sharer doesn’t think are particularly well aligned with their hopes and goals, offer suggestions about how these two things could be brought into better alignment. Alternatively, if you think there is a real tension that prevents a project topic from being compatible with someone’s hopes and goals, you can offer that opinion as well.

Do Some Targeted Ideation (Round 1) [15 minutes]

We have set up stations for more targeted ideation. We realize that there will be project ideas that don’t neatly fit into the stations that we have selected, but if you go to the station that seems most similar to a topic you are excited about, you are likely to find other folks who may be interested.

Round 1 Station List:

Once you arrive at the station, take turns pitching your favorite projects. If you hear an idea that is particularly exciting, ask some clarifying questions or offer some suggestions.

Do Some Targeted Ideation (Round 2) [15 minutes]

Repeat round 1 for a new topic area.

Round 2 Station List:

Fill out the Reflection, Teaming, and Project Preferences Survey (due Saturday by 5pm)

Please fill out the Reflection, Teaming, and Project Preferences Survey.