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.
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
:
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.
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:
โ Not fast-forward merging:
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:
First switch to the
main
branch, this will make HEAD point to themain
branch.git switch main
Then merge the
bugfix
branchgit 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.
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.
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.