Git command-line essentials

I use a popular Git workflow called feature branching. Here are the top commands I use on a daily basis to accomplish this. There’s a whole lot more to Git, but this should hopefully give you a solid foundation 🙏

  1. Cloning a repository
  2. Creating a new branch
  3. Checking the status
  4. Staging changes
  5. Committing changes
  6. Viewing your commits
  7. Viewing differences
  8. Pushing your commits
  9. Creating a pull request
  10. Fetching and pulling changes
  11. Deleting a branch
  12. Wrapping up

Cloning a repository

After creating a repository on GitHub, you’ll want to create a local copy. To do this, you can use the git clone command:

git clone https://github.com/kieranbarker/test.git

By default, Git will place the clone into a new folder with the same name as the repository. The example above would place the repository called test inside a new folder with the same name.

You can specify a different folder name by appending it to the git clone command:

git clone https://github.com/kieranbarker/example.git my-cool-folder

This would place the clone into a new folder called my-cool-folder.

Creating a new branch

Once you’ve navigated to your local repository (probably using the cd command), you can create a new branch for the feature you’d like to work on. You can do this using the git checkout command, appending it with the -b flag and the name of the branch:

git checkout -b hello

This would create a new branch called hello.

You’ll want to set up this branch on GitHub as well. You can do this using the git push command, appending it with the --set-upstream flag (you can also use -u for short):

git push --set-upstream origin hello
git push -u origin hello

Both are identical in function. After running one of them, your GitHub repository will have a remote version of the branch.

Checking the status

Let’s assume you’ve added some new files but you’ve forgotten exactly what’s changed. You can check exactly where you are by using the git status command. You’ll see some output like this (with different files, of course):

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

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	app.js
	index.html
	styles.css

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

In the example above, you can see I’m working on a branch called hello. I’m up to date with the remote version of my branch stored on GitHub.

(To check if there are any changes on the remote branch, you can safely run the git fetch command first.)

Git also says I have new, untracked files present. I’ll show you how to add these to a commit, but you can see it’s already given us a hint!

Staging changes

To stage your changes (add them to a commit), you can use the git add command. You prepend it with the names of the file(s) you want to add:

git add index.html

If I do that and run git status again, there’s a new message:

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

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	new file:   index.html

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

It says that the index.html file is ready to be committed, but the others are still untracked. I want to add those to my commit as well. Here’s a nice little trick: . refers to the current directory, so you can use git add . to stage all your changes at once. You can also use git add --all or git add -A:

git add .
git add --all
git add -A

All three will do the same thing. If I run git status again, I can see that all of my new files are staged (ready to be committed):

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

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	new file:   app.js
	new file:   index.html
	new file:   styles.css

Committing changes

I’m happy with my changes, so it’s time to commit them to my repository’s history. I can do this using the git commit command, passing in a message with the -m flag.

It’s a good practice to imagine your commit will complete the sentence “This commit will…”. Here are some example commit messages:

With that in mind, let’s commit our changes:

git commit -m "Add markup, styles, and scripts"

After running this, you’ll see some output like this:

[hello 770863f] Add markup, styles, and scripts
 3 files changed, 26 insertions(+)
 create mode 100644 app.js
 create mode 100644 index.html
 create mode 100644 styles.css

The random-looking string 770863f is the SHA-1 hash that refers to the commit. You don’t need to understand hashing, so don’t worry! Just realise that this jumble of characters can be used to refer to this specific commit.

Running git status again, I can see that I have one commit ready to push up to the remote branch on GitHub:

On branch hello
Your branch is ahead of 'origin/hello' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

Viewing your commits

Let’s say I had a break from my computer. I’ve come back to it and forgotten what commits I made. I can view them using the git log command:

commit 770863f20da0134119ae8ed087d09f42660b75e6 (HEAD -> hello)
Author: Kieran Barker <29986418+kieranbarker@users.noreply.github.com>
Date:   Thu Apr 16 11:12:18 2020 +0100

    Add markup, styles, and scripts

The commits are listed in reverse chronological order (newest at the top). I’ve only shown the most recent commit for brevity, but there are more.

If you want to see what changes you actually made, you can run git log -p:

commit 770863f20da0134119ae8ed087d09f42660b75e6 (HEAD -> hello)
Author: Kieran Barker <29986418+kieranbarker@users.noreply.github.com>
Date:   Thu Apr 16 11:12:18 2020 +0100

    Add markup, styles, and scripts

diff --git a/app.js b/app.js
new file mode 100644
index 0000000..09a2f09
--- /dev/null
+++ b/app.js
@@ -0,0 +1,7 @@
+;(function () {
+
+  "use strict";
+
+  console.log("Hello, World!");
+
+})();
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..a384c0b
--- /dev/null
+++ b/index.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <title>Hello, World!</title>
+    <link href="styles.css" rel="stylesheet">
+  </head>
+  <body>
+    <h1>Hello, World!</h1>
+    <script src="app.js"></script>
+  </body>
+</html>
\ No newline at end of file
diff --git a/styles.css b/styles.css
new file mode 100644
index 0000000..fe2b1b1
--- /dev/null
+++ b/styles.css
@@ -0,0 +1,6 @@
+body {
+  width: 88%;
+  max-width: 40em;
+  margin: 1em auto;
+  line-height: 1.5;
+}
\ No newline at end of file

As you can see, this is a much longer message which shows the actual changes. I’ve again only shown the most recent commit for the sake of brevity.

With this command running, you can scroll using the Up and Down arrows on your keyboard. You can exit by pressing the Q key.

Viewing differences

Let’s say I’ve changed the title in my index.html file, but I forgot exactly what I changed. If the changes haven’t been staged yet, you can view the differences using the git diff command.

Running it on its own will show all changes. To view only the changes for a specific file, you can append the file name, e.g. git diff index.html.

Here’s what I see after changing the title and running git diff:

diff --git a/index.html b/index.html
index a384c0b..c493a29 100644
--- a/index.html
+++ b/index.html
@@ -3,11 +3,11 @@
   <head>
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
-    <title>Hello, World!</title>
+    <title>Kieran Barker</title>
     <link href="styles.css" rel="stylesheet">
   </head>
   <body>
-    <h1>Hello, World!</h1>
+    <h1>Kieran Barker</h1>
     <script src="app.js"></script>
   </body>
 </html>
\ No newline at end of file

You can see that I’ve changed the content of my <title> and <h1> elements from Hello, World! to my name, Kieran Barker.

Once I’ve staged this change using git add, running the git diff command won’t do anything. To view the staged differences, you need to add the --staged flag like so:

git diff --staged

Pushing your commits

I’ve committed my change to the title. Running git status again, I can see that I have two commits ready to be pushed to GitHub:

On branch hello
Your branch is ahead of 'origin/hello' by 2 commits.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

As Git has suggested, you can use the git push command to push your changes. It defaults to the branch you’re currently working on (which you can check by running the git branch command—it will have an asterisk (*) next to it). If you want to be more specific, you can specify the name of the branch:

git push
git push origin hello

After pushing my commits, I see the following output:

Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 4 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (8/8), 1.01 KiB | 1.01 MiB/s, done.
Total 8 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), done.
To https://github.com/kieranbarker/test.git
   adea91a..d453809  hello -> hello

The push was successful. Great! Running git status again, I can see that there are no commits and the working tree is clean (there are no changes):

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

nothing to commit, working tree clean

Creating a pull request

Once you’re happy with your feature branch, you’re ready to merge it into your master branch (the main branch). First, you’ll want to create a pull request on GitHub. You can do that by visiting the following URL, swapping in your own username, repository, and branch:

https://github.com/kieranbarker/test/pull/new/hello

GitHub will guide you through creating a pull request and merging the changes into your master branch. It will also ask if you want to delete the branch. If you’re done with it, you can. You can always create it again later.

Fetching and pulling changes

We’ve created a pull request and merged our changes into the master branch. We’re still working on our hello branch locally, so let’s switch to the master branch. We can do that using the git checkout command, appending the name of the branch:

git checkout master

You’ll see a message like this:

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

Is it true that we’re up “up to date with origin/master”, though? We just merged our changes into that branch. Let’s run git fetch to make sure. I see some output like this:

remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (1/1), done.
From https://github.com/kieranbarker/test
   adea91a..1142ec4  master     -> origin/master

Running git status again now shows us the true story:

On branch master
Your branch is behind 'origin/master' by 3 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)

nothing to commit, working tree clean

As Git has helpfully told us, we can run the git pull command to get these changes in our local copy of the master branch. After doing so, I see the following output:

Updating adea91a..1142ec4
Fast-forward
 app.js     |  7 +++++++
 index.html | 13 +++++++++++++
 styles.css |  6 ++++++
 3 files changed, 26 insertions(+)
 create mode 100644 app.js
 create mode 100644 index.html
 create mode 100644 styles.css

Now our master branch is up to date with the changes from our feature branch. Awesome!

Deleting a branch

You may have already deleted your branch on GitHub, but you still have a local copy. To get rid of it, you can run the git branch command, appending the -d flag and the name of the branch:

git branch -d hello

Running this, I see the following output:

Deleted branch hello (was d453809).

If I now run git branch without any flags—which shows a list of my branches—I can see that only the master branch exists now:

* master

Wrapping up

And there you have it: my crash course on what I consider to be the most essential Git commands. I’ll probably write more articles about some other cool things you can do wih Git.

This post is perhaps a bit long, but I hope it’s a useful reference you can bookmark. I’ve tried to keep it as simple as possible 👍


If you have questions, feedback, or any other suggestions, please do email me. I'd love to hear from you!