Version Control Basics Git

How to Use Source Code Control

Source code control systems (also known as Version Control Systems) let you manage projects effectively. They're very useful for one person and essential for a group. They track all changes in different versions so that no code is ever lost and meaning can be assigned to changes. One can create throw-away and debugging code with confidence with a source code control system, since the code you modify is kept carefully separate from committed, official code that will be shared with the team or released.

I was late to appreciate the benefits of source code control systems but now I wouldn't live without one even on a one-person project. Generally they are necessary when you have team working on the same code base. However, they have another great advantage: they encourage thinking about the code as a growing, organic system. Since each change is marked as a new revision with a new name or number, one begins to think of the software as a visibly progressive series of improvements. I think this is especially useful for beginners.

A good technique for using a source code control system is to stay within a few days of being up-to-date at all time. Code that can't be finished in a few days is checked in, but in a way that it is inactive and will not be called, and therefore not create any problems for anybody else. Committing a mistake that slows down your team-mates is a serious error; it is often taboo.


Git is a must-know for every aspiring software developer because it helps you to manage your files as well as allow you to work on a project with other people. This lesson will get you started on how to use it. No matter how experienced you are, you will never stop discovering new things you can do with Git.

💡 For this tutorial, we will be focusing on using Git from the command line. The rationale for this is so that you are able to use Git on external servers or even other people's computer.

Prerequisites

Terminology

Before we get started on using Git, let us define certain keywords so that we are on the same page. Click the link below to get started.

Video 1: Very short intro to why we use Git

https://www.youtube.com/watch?v=2ReR1YJrNOM

Video 2: Brief overview of what you can do with Git

https://www.youtube.com/watch?v=HkdAHXoRtos

[Optional] Video 3: Find out more about Git's features

https://www.youtube.com/watch?v=BUGjkDVsH_Y&t=135s

Initialise Git Repository

To turn a folder into a Git repository, navigate into the desired folder from the command line then enter the command $ git init. This creates a hidden .git directory at the current directory. The current directory will also be the root of this repository.

Clone Git Repository

More often than initialising Git repos from your own computer, you will probably be cloning Git repositories from GitHub.

To do so, click the green "Clone" button and copy the link shown under the HTTPS tab to clipboard.

Then, navigate to the directory where you want to save the project folder and enter the command git clone <link_you_copied>.

Voila, a clone of the remote repository is now saved on your local machine.

GitHub Authentication

Keying in your password every time you push and pull is tough. Fortunately, there is a solution to that. Follow the guide in the link below. Using it is left as an exercise for the reader. Learning to comprehend and follows guides are an essential developer skill!

https://docs.github.com/en/authentication/connecting-to-github-with-ssh

Save and Undo Changes

Do read up on the terminology if you have not yet done so. From this point forward, I will assume that you are equipped with the necessary vocabulary.

Video 2 above also demonstrates the basics on how to perform these tasks.

Checking Status

A command you will use a lot is $ git status.

It informs you of the branch you are on, as well as which files are staged and which are not. Git is smart in that only files that have been changed from the last commit will show up here. For example, let's say you created a file called HelloWorld.txt in the root of the repo.

Running $ git status will should give you something like this:

$ git status

On branch master
Your branch is up to date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        HelloWorld.txt

nothing added to commit but untracked files present (use "git add" to track)

Staging

The first step to take is to stage the desired files to be committed. You can do so using the command $ git add <insert_files_or_directory>. Take note that the files or directory argument provided is relative to the directory that you are currently in so make sure you are in the correct directory.

Most of the time, you might be using this command:

$ git add .

What the full stop represents is the current directory. Therefore, this can also be translated as "Add/Stage all files and folders in the current directory". You should be running this command in the root directory of the repository.

Continued from the previous example, checking $ git status after running $ git add . or $git add HelloWorld.txt should produce the following output:

$ git status

On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   HelloWorld.txt

Committing

After you have made enough changes and you want to save a checkpoint, it is time to commit.

Make sure that you have staged all the files that you want to commit beforehand.

Then, use this command to commit the changes:

$ git commit -m "<description_of_commit>"

Following our previous example, committing should look something like this:

$ git commit -m "Create text file to say hello"
[main (root-commit) fff0033] Create text file to say hello
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 HelloWorld.txt

After that if you check the status, you should see something like this:

$ git status
On branch main
nothing to commit, working tree clean

If you accidentally typed $ git commit without the -m flag, you might be taken into Vim to enter your commit message. Good luck getting out of Vim ☺️ Google is your friend.

💡 Make sure your commit message is descriptive so that other people can understand what your commit contains without looking at the code. Avoid using any tense such as "Created" or "Creates".

Unstaging

Maybe you ran $ git add . and you realise you accidentally staged some files that you did not intend to. Maybe you changed your mind regarding whether to commit changes from a certain file.

If you want to unstage ALL files, enter:

$ git reset

If you want to unstage a specific file or directory, use the command:

$ git reset -- <file_or_directory_name>

Assuming you have not yet committed, checking $ git status after unstaging with $ git reset -- HelloWorld.txt should give you the same output as before you staged the file.

.gitignore

If there are certain files that you do not want Git to track, such as files that contain sensitive info or temporary files, add them to the .gitignore file located at the root of the repository.

Suppose there is a folder in the root called "data" and you want to ignore a file called "useless.txt" in that folder. Add the following line into your .gitignore file and git will know to no longer track it.

./data/useless.txt

⚠️ Don't forget to commit the changes in `.gitignore`!

Create and Merge Branches

Creating a Branch

There are multiple ways to create a new branch from the current branch.

The method I am used to is:

$ git checkout -b <newBranchName>

This command creates a new branch called then switches to it.

For example, you will see this when creating a new branch

$ git checkout -b anotherBranch
Switched to a new branch 'anotherBranch'

Then, you can switch between branches using this command:

$ git checkout <branchname>

Merging Branches

When merging, take note of two things:

  1. The branch you are merging FROM

  2. The branch you are merging TO (branch that will take in the changes)

Branch 2 will be the final branch that will contain changes from both branches so make sure you are merging in the correct direction.

First, checkout to branch 2 which is the branch you are merging to.

$ git checkout <branch2name>

Next, use $ git merge to merge the two branches.

$ git merge <branch1name>

That's it! Unfortunately, sometimes things are not that simple...

Resolving Merge Conflicts

When two different branches make changes to the same line of code, there will be a merge conflict. In this scenario, Git cannot tell which one you want to keep, or if you want to keep a combination of both. Therefore, you will have to manually resolve this conflict in your text editor.

$ git merge other-branch
Auto-merging merge.txt
CONFLICT (content): Merge conflict in merge.txt
Automatic merge failed; fix conflicts and then commit the result.

If you check the status at this point, you should see something like this:

$ git status
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)

Unmerged paths:
(use "git add <file>..." to mark resolution)

both modified:   merge.txt

From here, you can identify the files where there are conflicts and proceed to resolve them.

If you open the file with conflicts, you should see new lines being added by Git:

Lines before that have no conflicts

<<<<<<< HEAD
Sample line in main branch
=======
Sample line in other branch
>>>>>>> other-branch

Lines after that have no conflicts

This happens when that line was changed by both branches, then Git does not know which change to keep.

To fix this, edit that segment to whatever you want to keep. Suppose you want to keep both lines, you should have something like this at the end:

Lines before that have no conflicts

Sample line in main branch
Sample line in other branch

Lines after that have no conflicts

🚨 Take note to remove the lines that have <<<<<, =====, and >>>>>

Run $ git status to ensure that all merge conflicts have been resolved.

Then, make a new commit for these edits to finalise the merge.

🚨 Make sure to test your code before committing! If you miss out any merge conflicts, you will likely break the entire code base.

Pushing, Pulling and Pull Requests

Basic Push and Pull

You have committed to a branch on your local machine. Now you want to push it to GitHub. Make sure you are on the correct branch that you want to push, then enter the command:

$ git push

Similarly, if there are commits on the same branch in the origin that you have yet to download on your own machine, enter the command:

$ git pull

Resolve any merge conflicts that might occur when merging between the your local branch and the branch in the origin.

However, what if the branch you want to push only exists only on your local machine? This happens when you created the branch using $ git checkout -b taught earlier. The GitHub repository is unaware that such a branch exists yet. All you have to do is provide more arguments to the command like so:

$ git push -u origin <branchname>

This will create a branch in GitHub called <branchname> and you will push all your changes in your current branch to that branch. Git will also remember that these 2 branches are connected and in the future you can simply $ git push or $ git pull.

Hands-On!

There is no better way to learn than to try it yourself. Here is a useful website.

https://learngitbranching.js.org/

Shortcuts

Memorising long commands sometimes can really be a pain. Luckily, we can define short forms for Git using aliases.

For example, you can shorten commit -m to cm by running this command:

git config --global alias.cm "commit -m"

After that, you can type git cm instead of git commit -m when making a new commit.

If you are interested in finding out more ways you can save time using git aliases, here is an interesting article.

8 Git aliases that make me more efficient

Advance your Git Knowledge

https://www.youtube.com/watch?v=Uszj_k0DGsg

Note: even in professional setting, you most likely wont need to use certain concepts. Depends on your team.

Last updated