Git Beginners' Cheatsheet - Branching & Merging

๐Ÿ“… February 4th, 2022โ‹…โ˜• 9 min read

Before starting, I want to mention this is not a tutorial for git branch and merge. I wrote this to be a reference or a short guide for the future. You still might get a lot out of it if you are a beginner. But if you are looking for a full-fledged tutorial, this is probably not the place. If you are looking for a complete course on git and GitHub and don't mind videos, I would recommend this course by Colt Steele.

It's assumed you already know why it is important to use branches in git. I'm also assuming you have some kind of idea why there is a requirement of merging branches. Let's get started.

Branch

Branching makes it easier to work within self-contained contexts and to work in parallel.

Things to remember while working with branch:

1๏ธโƒฃ HEAD

Head is a pointer that refers to the currently active location in the repository we are accessing/viewing. It points to a particular branch reference. By default HEAD points to the latest commit on the main branch, but that can be moved around which changes the HEAD.

head 1

If we change branch from master/main to another, HEAD will now point to the latest commit of that branch instead. Then we can switch back to the main branch or any other branch and HEAD will now point to that. So, HEAD is kind of like a bookmark in a book. Let's say we switch to a branch named FeatureBranch1:

head 2


2๏ธโƒฃ Viewing Branches

To view all the branches of the current repo, write the following command:

git branch

This will show all the branches of the repo. An * symbol will be on the left of the currently active branch (the branch that you are currently on).


3๏ธโƒฃ Creating & Switching Branches

First we will have to create a new branch. Let's name the new branch as bugfix.

git branch bugfix

This will create a new branch named bugfix. We can verify that by using git branch command.

But we will still be on the main branch. And HEAD will now point to both main and bugfix branches. So, the latest commit will point to both of the branches.

To switch to the newly created bugfix branch:

git switch bugfix

To create a new branch named bugfix and switch to that branch with a single command:

git switch -c bugfix

We have switched to the bugfix branch and now HEAD will point to the bugfix branch alone. And whatever commit we do, will be on this branch from now on unless we switch to another branch.

creating and switching branch


4๏ธโƒฃ ๐Ÿงจ Switching Branches with Unstaged Changes

We must commit or stash the changes we made in the branch, before switching to another branch. Otherwise, if there are conflicting files in two branches (the same file is present in two different branches), all the unstaged changes will be lost.

Let's imagine we have a file named ComponentOne.js in both branch-1 and branch-2. Now, if we write something on ComponentOne.js file while being on branch1 and before committing or stashing the changes, we try to switch to another branch branch2, git will abort that and throw a warning, as they have the same file in both of the branches. This switch might cause overwrites in every unstaged file of the branch.

So in this case,

โŒ git switch branch1 -> make changes -> git switch branch2
โœ… git switch branch1 -> make changes -> git commit -a -m "commit message" -> git switch branch2

BUT if a file named ComponentTwo.js is only present in let's say branch1, we make some changes to save them. And now, before committing or stashing we switch to branch2. This won't cause any conflict as branch-2 doesn't have the file.

What this will cause the switch will bring the ComponentTwo.js file with it to branch2. Now if we switch to branch3, the file ComponentTwo.js will come to branch3 too, as branch3 didn't the file before either. So branch1, branch2, branch3 all will inherit the file.

In this case,

๐Ÿ†— git switch branch1 -> make changes -> git switch branch2 -> make changes -> git switch branch3

But after that, if we change something in the file ComponentTwo while being on branch3 and commit that. And after making the commit we again change something in the same file. So a new unstaged change is in the file and we haven't committed or stashed the change. Now if we try to switch to branch2 or branch1, again a conflict will occur, and git will abort the command and throw a warning.

Now again,

โŒ git switch branch3 -> make changes -> git switch branch2

๐Ÿ‘ So it's always recommended to commit or stash changes before switching a branch.

Now let's say we write some codes to fix the bug. All the fixed codes will be on the currently active branch which is the bugfix branch.

๐Ÿ”ฅ Now we must commit or stash the changes of the bugfix branch before switching to another branch. Otherwise, all the unstaged local changes of the bugfix branch will be lost. If we then decide to switch back to the main branch (which we definitely can do), we won't find the newly written bug-fixed codes on master. Because the changes will only occur in the active branch.


5๏ธโƒฃ git checkout vs git switch

Historically, git checkout was used to switch branches which still works. But git checkout can do a lot more additional things to switching branches, so a simpler standalone command for switching git switch was added.

๐Ÿ“’ The git switch -c bugfix equivalent command for checkout is: git checkout -b bugfix.


6๏ธโƒฃ Renaming a Branch

๐Ÿ”ฅ To rename a branch we must switch to that branch first.

If we want to rename a branch named branch1 to branchOne, we first have to switch to branch1.

git switch branch1

Then:

git branch -m branchOne

7๏ธโƒฃ Deleting a Branch

We can't delete a branch if we are currently on that branch. Let's assume we have a branch named `experimentalBranch` and we want to delete it. If we are currently switched to this branch, we won't be able to delete it. We have to switch to another branch first.

So at first,

git switch experimentalBranch

Then we can use:

git branch -d experimentalBranch

But for this to work, the branch experimentalBranch must be fully merged in its upstream branch. If no upstream is set, it must be merged fully in the HEAD.

If we want to delete the branch no matter what:

git branch -D experimentalBranch

๐Ÿ”ฅ But in this case, you must be completely aware of what you are doing.




Merge

Often we want to integrate changes from one branch to another. Couple of things to remember before merging:

  • ๐Ÿ“’ Branches are merged, not specific commits
  • ๐Ÿ“’ We always merge to the current HEAD branch (we merge to where HEAD currently is)

Generally, master/main is considered as the source of truth or the main production branch, and other feature branches are merged to the main branch.

Fast-forward merge is possible if a direct linear path exists from the source branch to the destination branch. In other words, if we want to merge a branch named bugfix to the main branch, and the main branch doesn't have any additional commits that don't exist in the bugfix branch, in this case, the merging is fast-forward merging.

โœ” Fast-forward merging:

fast forward merge

โŒ Not fast-forward merging:

not fast forward merge

In the case of fast-forward, all git has to do is to change the pointer of the main branch by moving it forward to the bugfix branch. This is why it is called fast-forward merging.

We can use git log to analyze the possibility of fast-forward merging.

Let's consider fast-forward merging is possible here and we want to merge the bugfix branch to the main branch:

  1. First switch to the main branch, this will make HEAD point to the main branch.

    git switch main
  2. Then merge the bugfix branch

    git merge bugfix

2๏ธโƒฃ Merge Commits

Whenever we try to merge two branches, git tries its best to merge the branches automatically whether it's a fast forward merge or not.

not fast forward merge

In the above case, the main branch has some information or additional commits that the bugfix branch doesn't have, and the bugfix branch has some information or additional commits that the main branch doesn't have. So fast forward merging is not possible.

For these cases, git will generate a merge commit unless there is a conflict between two branches. Merge commit is a commit that git generates on the recipient branch (the branch in which we are merging to, in this case, main). After generating a merge commit, git will prompt (open the default editor) the user for a message. Though when git generates a merge commit, it generates a default commit message too, which can be edited in the editor.

merge commits

The newly generated merge commit will have two different parents (one commit from main and one from bugfix).

This merge will be made using recursive strategy.

๐Ÿ”ฅ๐Ÿ”ฅ Reminder: This is when there are no conflicts.


3๏ธโƒฃ Merge Conflicts

Merge conflicts arise when git can't automatically decide what to keep and what to get rid of and as a result can't merge the branches by itself.

If merge conflicts arise, git will console an error that it failed to merge automatically and it marks the contents of conflicting files to indicate the issues that have to be resolved manually.

So, to resolve this conflict:

  • Open up the files where conflicts occurred
  • Edit the file contents according to what you want to keep and what you want to get rid of
  • Delete the conflict markers in the file
  • Save and commit the changes


This wraps up this post. Hopefully, some of you get some help out of it. If there's something that needs modification or something totally wrong, kindly let me know.