Skip to content

Branching and Merging

Objectives📍

  • branch
  • switch
  • restore
  • HEAD and detached HEAD
  • merge and how to solve a merge conflict

Now that we know how to make, record, and inspect changes with Git we want to dive into the really cool features of Git. In the introduction we heard something about "multiple streams of work". In Git this is done by branches. So far we only worked on the main branch. This is our main development stream. However, sometimes we want to try something new with our code and see if it works out without trashing our main development stream with too many commits. Or, we work collaboratively and you work on one module of the code and your collaborator works on another module of the code. To not interfere too much and having to incorporate the changes of your collaborator all the time and keep a clean main development stream, you should work on separate branches. In the end, you can merge your versions into the main branch.

git branch
Branching with Git. You always start your development on the main branch. Along the way you might want to try out different things while keeping your main development stream clean. For this you can create as many branches as you need, working on them in parallel and incorporate the work you did on these features into the main branch. Or not.

Before we try this, we need some more vocabulary:

More Git vocabulary

  • git branch: create a new branch
  • git switch: move between branches or move among commits
  • git restore --source=HASH file-to-restore: restore an old version of a file.
  • git merge: to merge two separate streams of versions (branches) into one

Creating a new branch

Let's say you were asked by our supervisor to set up your experiment with a new feature, e.g., adding some eye tracking in addition to your EEG experiment. Because want to keep the main development stream clean and we know that we need to work on the eye tracking feature a lot, we decide to set up an extra branch for it.

Task 4

1) Create a new branch by typing git branch eyetrack. Check with git branch if it worked.
2) Switch to your new eyetrack branch by typing git switch eyetrack. You should see "Switched to branch eyetrack". Check if you are really on the new branch.
3) Make a change to your experiment code, add and commit it.
4) Do a git log.

What is different about the git log output compared to the last git log we did?

Why is HEAD not with main?

git branch and git switch

  • to know which branch we're currently on we can do a git branch
  • we can switch between branches by doing git switch branchname. The changes you make on a branch belong to that branch’s commit history. Be mindful of which branch you’re on.
  • instead of git branch name-of-new-branch plus git switch name-of-new-branch we could also just do a git switch --create name-of-new-branch

Restore the specific version of one file

git restore --source=HASH file-to-restore allows you to restore a previous version of a file by specifying, with HASH, which version you want to restore and then indicating the file to restore. You might want to do this because you realize that you prefer the instruction for your experiment from an earlier version and want to bring it back without losing all the other changes you have made since then.

Moving around in your commit history

git switch --detach allows you to move to a specific commit and view a previous version of your project. This is useful when you want to check whether an older version of your work (for example, earlier experiment instructions) is better, without changing anything yet.

Unlike git restore --source=HASH file-to-restore, which restores only a single file, git switch --detach HASH shows you the entire project as it was at that commit.

git switch --detach

  • git switch --detach HASH moves you to a specific commit so you can inspect an older version of your project.
  • This puts you in a detached HEAD state, which simply means you are viewing a specific snapshot of the project rather than working on a branch. You can safely look around, run the project, and compare files. No changes are made unless you explicitly modify something.
  • A common use case is to inspect an older version of your project without making any changes. Once you’ve found the version you want, switch back to your branch, then restore the desired file using git restore --source=HASH file-to-restore

Task 5

1) Switch to the eyetrack branch and make 3-4 commits.
2) Move to your third commit and inspect it.
3) Switch back to the eyetrack branch.
4) Bring back the old version of a file from the third commit.

Answer

1) check with git branch if you're currently on the eyetrack branch. If not: git switch eyetrack. Make a change. git add change & git commit.
2) git log to find hash of third commit.
3) git switch --detach hash-of-third-commit to inspect old files.
4) git switch eyetrack to move out of inspecting mode back to the eyetrack branch.
5) git restore --source=third-commit-hash file-to-restore to restore a file you want.
6) git add and git commit to commit the restored file.
7) git log to inspect the restoration"

Task 6

How does our development stream look like? Draw your commit history with all the branches like in Fig. 13 shown at the top of this page.

Merging and merge conflicts

Merging means bringing two independent development streams together. Previously, we said we wanted to add an eye tracking feature to our experiment code. Now that we worked on it a bit we are certain that we can incorporate eye tracking into our experiment. This means, we want to incorporate our work from the eyetrack branch into the main branch. It will look like this 1:

branches merging
Independent branches of work. Merged branches.

Git merge

  • Merging always refers to two branches
  • with the command git merge name-of-the-branch, name-of-the-branch will be incorporated into the branch you're currently on
  • especially when you start working collaboratively with Git, you will run into merge conflicts. This is something common and not a catastrophe. There is a solution to the conflict (see below).

Task 7

Merge the eyetrack branch into the main branch.

Answer
  • check if you're currently on the main branch. If not: git switch main
  • git merge eyetrack

Did you run into a merge conflict? If not, do the optional Task.

Optional task to induce a merge conflict

1) while you are still on main, change a file and commit it.
2) git switch eyetrack
3) change something in your code on the eyetrack branch by deleting something in your instructions and writing an alternative text on the exact same place as you deleted from. Add and commit.
4) git switch main
5) git merge eyetrack

The reason why we run into merge conflicts is because of the way Git tracks the changes in our files. Git inspects our project on a file-by-file and line-by-line basis. This is the reason why a git diff can give us such detailed information about our changes. However, this also means that when we make changes on the eyetrack branch to a line that already exists on the main branch and then want to merge, Git simply is confused and doesn't know which one of the two versions we want to keep.

merge conflict

So, Git is super nice and asks us which one we want to keep by giving us a notice about a merge conflict. A merge conflict looks like this:

git merge eyetrack
Auto-merging crtt_exp.py
CONFLICT (content): Merge conflict in crtt_exp.py
Automatic merge failed; fix conflicts and then commit the result.

As you can see, Git tells us in which file the merge conflict appeared and asks us to fix the conflicts. We can fix it by opening the file and modifying it so that only one version stays.

Task 8

  • open the file in which the merge conflict appeared
  • at the place where the merge conflict is you will see this:

<<<<<<< HEAD
this is the content of the file on main
...
=======
this is the content of the file on eyetrack
. >>>>>>> eyetrack

You can see that Git tells you where the merge conflict starts and what the merge conflict is about. Thanks to VSCode you have some buttons where you can click on to choose which of the two versions you want to keep.

  • solve the merge conflict
  • do git status. It will tell you that you are still in a merge process
  • add the file. If all conflicts are solved by your changes, git status will now tell you that committing will conclude the merge procedure.
  • commit your changes
  • do a git merge eyetrack again. It should tell you that it is already up to date.
  • Check with the Git-Graph feature of VSCode how your project development looks like.
git database

Now that we are experts in using Git locally on our machine, we're finally ready to start using Git collaboratively!!!!

P.S.: check out this tutorial for learning advanced git commands.


  1. Figures retrieved from the Atlassian tutorial ↩