Learn Git Basics in 10 Minutes

Introduction to the core concepts of Git, one of the most common source code management systems.

Git is a free and open source distributed version control system. It’s incredibly powerful and prevalent in the IT industry, meaning that having at least a basic understanding of Git is crucial for most tech roles.

The core concepts are best explained via a series of practical examples, which we will flesh out to increase your overall understanding. By the end of this 10-minute read you should have picked up the basics of Git.

Getting Started — Install and Configure

Installers are available for most platforms via https://git-scm.com/.

Alternatively you can also download Desktop GUIs — examples from GitHub [Windows, Mac] and Atlassian [download Sourcetree].

Once installed, head to your console of choice and type git --version to verify all is working.

Next step is to do some basic configuration. You should initially configure your user information that will be used to identity any changes you make.

git config --global user.name "firstname lastname"
git config --global user.email "firstname.lastname@example.com"

Now you’re ready to get going!

Workflow

To learn the fundamentals of Git workflows, there are four main stores to understand (you may hear of a fifth — “stash” — but that’s beyond the scope of this basic introduction).

  • Workspace
  • Staging Area
  • Local Repository
  • Remote Repository (optional)

As the name suggests, the Workspace or Working Directory is the view of the directories and files that you are actively editing. These are the versions you will be able to see by navigating to the directory using File Explorer and when opening a file in your favourite editor.

Underneath the covers, the files in your Workspace will relate to a branch that you have checked out. We’ll explore those concepts shortly.

Once you are happy with your file edits in your Workspace you add them into a Git-managed holding store that is known as the Staging Area. You can choose to stage one, all, or a subset of edited files into Staging. Git knows about the files you have staged, and has indexed and is tracking them, but at this time they have not yet been committed into your Local Repository.

You may continue making changes to these files in your Workspace and add them to the Staging Area as often as you like.

Once your edits are complete and you have added files into the Staging Area it is time to commit these from Staging into your Local Repository.

Every commit has a corresponding message — such as “Change the website background colour from white to black” — and retains metadata for who made the change using the user configuration settings.

A timeline (log) of commits exists to see all the changes made to a Repository.

You may repeat this cycle as many times as you like: edit, add, and commit.

In the diagram you will have noticed the Remote Repository. We’ll cover “push” and “fetch” (plus “clone” and “pull”) later in this tutorial when we discuss interacting with remote/upstream repositories.

Working with your local repository

Now that we have summarised the core concepts, let’s get your hands dirty, create a local repository, edit some files, and go through the workflow a few times. We’ll then explore some more advanced concepts — almost everyone will need these at some point (pretty early on, I bet).

Initialize Git

First two steps to get started are trivial.

  1. Create a new, empty directory and navigate into it.
  2. Create a Local Repository. This is also known as “initializing” and we do this with the git init command. This is a one-time activity.
$ mkdir sandbox
$ cd sandbox
$ git init
Initialized empty Git repository

On completion, you will see a hidden directory called .git located in your new directory — you don’t need to worry about what goes on in this directory (it belongs to Git and is where all the magic happens).

Status

At this point it’s worthwhile giving you an early introduction to git status, a command that you will end up running a lot. If you run the command now you will see some interesting information which we will briefly dig into.

$ git status
On branch master
No commits yetnothing to commit (create/copy files and use "git add" to track)

Your current branch in your Workspace is master — this is the default branch that was automatically created for you. Depending on your version of Git, you may see this as main instead of master.

Given we haven’t done anything yet the other status information should not be a surprise — there are no commits, and no staged files available to commit.

Let’s change that now…

Create a file

An empty directory is a bit dull, so create your first file called index.html as we’ll use a trivial website for our example.

$ echo '<h1>Hello World!</h1>' > index.html

Revisit git status to see what it now tells us about our Workspace.

$ git status
On branch master
No commits yetUntracked files:
(use "git add <file>..." to include in what will be committed)
index.html
nothing added to commit but untracked files present (use "git add" to track)

Git has detected the new index.html file in your Working Directory and is also informing you that the file is currently untracked. If you remember back to the overview your first step is to add the file to the Staging Area.

Stage the file

Stage your new index.html file with the git add [filename] command.

$ git add index.html

Checking git status again to see what effect this had upon our Workspace.

$ git status
On branch master
No commits yetChanges to be committed:
(use "git rm --cached <file>..." to unstage)
new file: index.html

Git has staged our new index.html file and it is now being tracked. We are ready for it to be committed into our Local Repository.

If you prefer, you can keep working on your file if you want to make further changes. Although a cautionary note that can catch out beginners: if you edit the file you will need to add the file again, as Git has only staged this version.

Add multiple files? In most scenarios you will want to add all your files, not just one. There is a shortcut for this: git add --all.

Commit to Local Repository

When we commit, we are committing the entire contents from the Staging Area into the Local Repository. In our case that is just a single file, but in most cases this is likely to be a number of files relating to a common goal.

Run the commit using the git commit -m "message" command. The message is mandatory and can be anything you like — but it’s good to write something descriptive so your log makes sense over time. Here’s an example to use.

$ git commit -m "First Hello World page"
[master (root-commit) e819195] First Hello World page
1 file changed, 1 insertion(+)
create mode 100644 index.html

Well done! You’ve now successfully created a file and saved it into your Local Git Repository. The output from the command gives you some further information that is useful to explore.

What is “e819195”? Every commit is given a unique id that is 32 characters long — although often shortened to the first 7 characters. When you get into more advanced use-cases, these commit ids (also known as “commit sha”) will come in very useful.

What if we run git status again now.

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

Nothing to see again now as we went through the full cycle of “edit”, “add”, and “commit”. You’ll quickly get into that routine now.

Making another change

Now make a further change to index.html to repeat the cycle. This gives an opportunity to show you a couple more useful commands.

$ echo '<h1>Hello World! Version 2</h1>' > index.html
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: index.html
no changes added to commit (use "git add" and/or "git commit -a")

You’ll see this time that Git has identified that there has been a modification to yourindex.html file. And once again, it informs us that we have not staged the file for commit.

What’s changed?

Before we run git add, let’s briefly introduce a new command that will allow you to review the differences — you can do that with git diff.

$ git diff
diff --git a/index.html b/index.html
index de8b69b..fd352a8 100644
--- a/index.html
+++ b/index.html
@@ -1 +1 @@
-<h1>Hello World!</h1>
+<h1>Hello World! Version 2</h1>

This command allows you to view all the changes before you stage them. A chance to do a last-minute review and/or verify that you have not missed anything — or just as worse, included an edit you did not intend. A diff beginning - means old and a line beginning + means the new line.

Having reviewed your change, you’re ready to add and commit again.

$ git add index.html
$ git commit -m "Update homepage heading for Version 2"
[master a3b8d95] Update homepage heading for Version 2
1 file changed, 1 insertion(+), 1 deletion(-)

Reviewing the timeline / log

So that’s two changes made now and the latest version of our file is now in your Local Repository. We’re at a good time to check out another new command: git log.

This command gives you the opportunity to view the history of commits made against this branch in the Local Repository. It identifies the author of every commit, the date and time, and the commit id.

$ git log
commit a3b8d95b8f11bf482887ef1084d37b7626ee54c5 (HEAD -> master)
Author: Dave Sugden <xxxxx@gmail.com>
Date: Mon Nov 30 21:02:08 2020 +0000
Update homepage heading for Version 2commit e8191954b92b27ec2ada438445d5c7bd5e65a174
Author: Dave Sugden <xxxxx@gmail.com>
Date: Sun Nov 29 21:32:34 2020 +0000
First Hello World page

Introducing Git branches

So far we have made our changes on a single branch, master, the default branch that Git created automatically for us when we initialized the empty directory. We edited a file, added to Staging, and committed to master. We did that cycle twice so we have two commits.

Often you will want to work multiple changes in parallel, or you may want to keep some edits separate to avoid constantly updating your primary branch. You may want to distinguish between development and production, or between different release versions. This is where branches come in useful —and it’s also a mind-blowing concept for every Git beginner.

Checkout. Whenever you want to switch between branches, you use the git checkout [branch name] command. This commands updates your Working Directory to the contents of the branch held in the Local Repository. If you want to create a new branch, add the -b switch. Try it now.

$ git checkout -b version-3-dev
Switched to a new branch 'version-3-dev'
$ git status
On branch version-3-dev
nothing to commit, working tree clean

Alternatively, you can also create a new branch with the git branch [new branch] command.

Right now your Local Repository has two branches, both at the same point in the git timeline (commit 2).

Now you have a new branch, we are going to begin the next set of code changes — you should be used to this cycle by now: edit, add, commit.

$ echo '<h1>Hello World! Version 3</h1>' > index.html
$ git add index.html
$ git commit -m "Updated homepage for version 3"
[version-3-dev 71af8dc] Updated homepage for version 3
1 file changed, 1 insertion(+), 1 deletion(-)

Now when you run git log you will start to see some differences as to how the two branches have diverged in time. You can see from below that your new version-3-dev branch is one commit in front of the master branch — now this might seem obvious from the steps you followed, but the concept is very powerful and visual (what if you had ten branches?).

$ git log
commit 71af8dce8ef6b9aa44dababee86b112281bc17ba (HEAD -> version-3-dev)
Author: Dave Sugden <xxxxx@gmail.com>
Date: Mon Nov 30 21:33:31 2020 +0000
Updated homepage for version 3commit a3b8d95b8f11bf482887ef1084d37b7626ee54c5 (master)
Author: Dave Sugden <xxxxx@gmail.com>
Date: Mon Nov 30 21:02:08 2020 +0000
Update homepage heading for Version 2commit e8191954b92b27ec2ada438445d5c7bd5e65a174
Author: Dave Sugden <xxxxx@gmail.com>
Date: Sun Nov 29 21:32:34 2020 +0000
First Hello World page

Your timeline now looks like this:

Switch to another branch.

This is the point that blew my mind when I first started out with Git. “How did that happen?”, I asked myself. Let’s show you what happens to your local Working Directory when you switch branches.

First of all, we do a quick double check to verify that we do indeed have version 3 of index.html in our local Working Directory.

$ cat index.html
<h1>Hello World! Version 3</h1>

Now checkout master branch again and see what happens.

$ git checkout master
Switched to branch 'master'
$ cat index.html
<h1>Hello World! Version 2</h1>

Git automatically and immediately updates your Working Directory to the contents of the selected branch from your Local Repository.

What if you do a git log command now… can you guess?

$ git log
commit a3b8d95b8f11bf482887ef1084d37b7626ee54c5 (HEAD -> master)
Author: Dave Sugden <xxxxx@gmail.com>
Date: Mon Nov 30 21:02:08 2020 +0000
Update homepage heading for Version 2commit e8191954b92b27ec2ada438445d5c7bd5e65a174
Author: Dave Sugden <xxxxx@gmail.com>
Date: Sun Nov 29 21:32:34 2020 +0000
First Hello World page

Wooah! You went back in time? Where’s the change I just made? Well, remember that your version 3 code doesn’t exist on the master branch. This branch only saw Version 2 and its commit history up to that point in time.

Let’s get back to version-3-dev before our mind explodes.

$ git checkout version-3-dev
Switched to branch 'version-3-dev'
$ cat index.html
<h1>Hello World! Version 3</h1>

That’s better.

Merging branches.

So it’s all well and good having multiple branches, but what if you want to move your edits between branches. For example, once you have finished doing your changes on version-3-dev you’ll no doubt be ready to put those same changes onto your master branch.

Don’t worry — you don’t need to make the edits again — this is where git merge command comes in.

To run a merge you need to be on the target branch, in our case master. Hopefully you remember the command to switch branches.

$ git checkout master
Switched to branch 'master'

The merge command has a lot of options, and we’ll use all the defaults in this introduction. The simplest case is the one we are going to demonstrate next — git merge [source branch].

$ git merge version-3-dev
Updating a3b8d95..71af8dc
Fast-forward
index.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

This output is telling us that we have updated our branch from id “a3b8d95” (commit 2) to id “71af8dc” (commit 3). If we review git log again now, we will see that master now has the full history and is at the same commit id as our development branch.

$ git log
commit 71af8dce8ef6b9aa44dababee86b112281bc17ba (HEAD -> master, version-3-dev)
Author: Dave Sugden <xxxxx@gmail.com>
Date: Mon Nov 30 21:33:31 2020 +0000
Updated homepage for version 3commit a3b8d95b8f11bf482887ef1084d37b7626ee54c5
Author: Dave Sugden <xxxxx@gmail.com>
Date: Mon Nov 30 21:02:08 2020 +0000
Update homepage heading for Version 2commit e8191954b92b27ec2ada438445d5c7bd5e65a174
Author: Dave Sugden <xxxxx@gmail.com>
Date: Sun Nov 29 21:32:34 2020 +0000
First Hello World page

Deleting a branch

With your changes now merged back into master you may be wondering what you can do with version-3-dev. If you have finished with it, you can delete it with the git branch -d [branch name] command.

$ git branch -a
* master
version-3-dev
$ git branch -d version-3-dev
Deleted branch version-3-dev (was 71af8dc).
$ git branch -a
* master

Use the -a switch shown above to list all the branches that exist.

Interacting with remotes / upstream repositories

The power of Git is that it is a distributed version control system. You can share a git repository with a friend, pair up on a problem with a team mate, or push your branch updates up to a central repository (e.g. GitHub). Each of these are called remote repositories, from which you can pull down new branches and updates and push up your changes to share them with others.

In most cases, you will have a single Remote Repository, but there is no restriction from working with many.

Interacting with a Remote Repository introduces a handful of additional everyday commands. These commands will also introduce the need for credentials to authenticate and authorize your access to the repository.

  • git clone — a one-time activity to initialize a new Local Repository and Workspace (i.e. into a new clean folder) from the contents of the remote. Consider this a similar concept to the git init we ran at the start.
  • git fetch & git pull — these commands bring down updates from the Remote Repository down into your Local Repository. In the case of pull this command will also merge the updates into your branch.
  • git push — the inverse scenario, this commands pushes commits from your Local Repository up to the Remote Repository.

Now that we have summarised the core concepts for working with a Remote Repository, let’s get in some hands-on practice. For this, we will work with GitHub to create an account and your first Remote Repository.

Register with GitHub

GitHub is free and allows you unlimited number of public and private repositories. A public repository is one that everyone can view, whereas with a private repository you can choose which users can view its contents. With both public and private repositories you can manage who can push updates.

Register for your account and once signed in follow the link to create a new repository. I’ve called mine “git-sandbox” and given it a description.

Once you’ve created your repository, you will be faced with a couple of options and example commands to run. There is also a third option, which is to run git clone and create an empty workspace.

Choosing between these options will depend if you already have source code developed locally in a folder — indeed you may even have a Local Repository in place too — or if this is a brand new repository.

For our tutorial, we’re going to demonstrate git clone [remote url] and create a clean workspace. You’ll see the URL you need at the top of the list of options — for example, my new repository is shown as https://github.com/davelms/git-sandbox.git.

In your command line run the command as shown below. Ignore the warning, it is just telling you that there is nothing to see yet — had this been a repository with history and existing files, you would have seen output downloading the repository and checking out the main branch.

$ git clone https://github.com/davelms/git-sandbox.git
Cloning into 'git-sandbox'...
warning: You appear to have cloned an empty repository.

Tip: your Remote Repository will have been given the name of origin. Nothing special about this, it’s just the default.

After running the command, you will have a new directory named after the repository name (“git-sandbox” in my case). Here there will be a Local Repository already created for you, so now you can proceed per the original part of our tutorial — practice what you learn earlier by creating yourself a file, add and commit, edit, and repeat to get yourself a small history.

$ cd git-sandbox$ echo "Hello" > hello.txt
$ git add hello.txt
$ git commit -m "First file"
[master (root-commit) f685797] First file
1 file changed, 1 insertion(+)
create mode 100644 hello.txt
$ echo "Hello World!" > hello.txt
$ git add hello.txt
$ git commit -m "Update greeting to World"
[master 931fc2d] Update greeting to World
1 file changed, 1 insertion(+), 1 deletion(-)
$ echo "Hello Dave!" > hello.txt
$ git add hello.txt
$ git commit -m "Update greeting to Dave"
[master 049dd92] Update greeting to Dave
1 file changed, 1 insertion(+), 1 deletion(-)
$ git log
commit 049dd92107d7ddfaa868eca1509a3718abf61a94 (HEAD -> master)
Author: Dave Sugden <xxxxx@gmail.com>
Date: Fri Jan 1 18:51:11 2021 +0000
Update greeting to Davecommit 931fc2dd55c1395c90b783dca9d60257994226d8
Author: Dave Sugden <xxxxx@gmail.com>
Date: Fri Jan 1 18:50:58 2021 +0000
Update greeting to Worldcommit f685797c34afe85f123ef7f2d9ea8a712306a21e
Author: Dave Sugden <xxxxx@gmail.com>
Date: Fri Jan 1 18:50:33 2021 +0000
First file
davelms@LAPTOP-EAGHCCN1:~/projects/git-sandbox$

At this stage you’ll have a history built up locally. But what about the source code in GitHub, what do you think that will show?

That’s right — nothing, yet — the code tab in your repository in GitHub will continue to be empty and waiting for your first push.

Pushing to a Remote Repository

We’re going to push our branch — default is usually master or main — to the Remote Repository.

To do so we run the command git push [remote name] [branch name].

It is also typical to include the -u switch that sets remote (aka upstream) tracking for this branch.

Remember that the default name given is origin so our command becomes git push -u origin master.

$ git push -u origin master
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (9/9), 681 bytes | 56.00 KiB/s, done.
Total 9 (delta 0), reused 0 (delta 0)
To https://github.com/davelms/git-sandbox.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

Now if you head back to GitHub and refresh the page you will see your source code is now showing. You will see the most recent commit message along with a link to view the commit log.

GitHub shows a nice presentation for your commit history, with the date, time, and the person that made the changes.

Keeping Local and Remote in sync

Now that you’ve pushed your commits to the Remote Repository, everything is currently in sync. What if you have a team of contributors and someone else subsequently pushes a change into the Remote Repository.

That’s where the commands git fetch and git pull come into play. The difference between these two commands is that fetch updates your Local Repository with the updates whereas pull will fetch and subsequently merge the updates into your current working branch as well.

For the benefit of demonstration, move to a clean folder (not under git-sandbox) and clone your repository again. You can use this temporary directory to simulate the work of another person.

$ git clone https://github.com/davelms/git-sandbox.git
Cloning into 'git-sandbox'...
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 9 (delta 0), reused 9 (delta 0), pack-reused 0
Unpacking objects: 100% (9/9), 661 bytes | 11.00 KiB/s, done.

Did you notice the difference in the output? This time there are contents in the Remote Repository for the clone command to download.

Now we shall do one additional commit as our work colleague, “Alice”.

$ echo "Hello Alice!" > hello.txt
$ git add hello.txt
$ git commit -m "Updating greeting to Alice"
[master 6311a03] Updating greeting to Alice
1 file changed, 1 insertion(+), 1 deletion(-)
$ git push origin master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 266 bytes | 53.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/davelms/git-sandbox.git
049dd92..6311a03 master -> master

Check that GitHub displays this new commit before navigating back into your original directory. Run a git log command to verify that you don’t yet see the update from “Alice”.

To update your local workspace you should run the git pull command and observe the update from “Alice” being pulled down from the Remote Repository and merged into your workspace.

$ git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 246 bytes | 15.00 KiB/s, done.
From https://github.com/davelms/git-sandbox
049dd92..6311a03 master -> origin/master
Updating 049dd92..6311a03
Fast-forward
hello.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

Run a git log and view the contents of the file to verify.

$ cat hello.txt
Hello Alice!

Conclusion

Over the course of this 10-minute tutorial we have walked through the basic introductory concepts of Git. These are the core commands that you will work with on a day to day basis to clone a Remote Repository, create branches and push and share your work to collaborate with team-mates.

There’s so much more to Git, and you’ll quick find further commands, switches, and pro tips online as you expand your knowledge.

A note from the author

Thank you for reading this article — I hope this served well as an introduction and you found it useful in your journey to getting started with Git.

You can follow me on Twitter and connect on LinkedIn.

DevOps | SRE | AWS | GCP https://twitter.com/davelms

Get the Medium app