If you’re a developer, coder, or software engineer and have not been hiding under a rock, then you’re probably familiar with Git. Git is a distributed version control system that helps developers track changes to their code and collaborate with others. While Git can be a bit complex (especially if used improperly), there are some easy commands you can learn to improve your workflow. In this blog post, we’ll walk you through 10 of the most essential Git commands.

TL;DR

The commands we address in this post are:

  1. git config
  2. git clone
  3. git branch / git checkout
  4. git pull
  5. git push
  6. git status / git add
  7. git commit
  8. git stash
  9. git restore
  10. git reset

It is assumed that you have basic knowledge of what the terms like branch, commit, or checkout mean. If not, or you really want to get into the nitty-gritty details, the official Git documentation book is a must-read!

Setup and Configuration

First things first – to get started with Git you need to get it installed and configured! Any Linux package manager today is going to have Git available:

# APT Package Manager (Debian/Ubuntu/etc.)
sudo apt install git

# YUM Package Manager (RedHat/Fedora/CentOS/etc.)
sudo yum install git

# APK Package Manager (Alpine)
sudo apk add gitCode language: PHP (php)

If you happen to be on Windows or Mac, you can find a link to download Git here.

Once you have Git installed, it’s time to do some initial configuration using the command git config. Git will store your configuration in various configuration files, which are platform dependent. On Linux distributions, including WSL, it will setup a .gitconfig file in your user’s home directory.

There are two things that you really need to setup at first:

  1. Who you are
  2. What editor you use

To tell git who you are so that it can tag your commits properly, use the following commands:

$ git config --global user.name "<Your Name Here>"
$ git config --global user.email <youremail>@<yourdomain>Code language: HTML, XML (xml)

The –global option tells git to store the configuration in the global configuration file, which is stored in your home directory. There are times when you might need to use different email addresses for your commits in different respositories. To set that up, you can run the following command from the git repository in question:

$ git config user.email <your-other-email>@<your-other-domain>Code language: HTML, XML (xml)

To verify that you have your configuration setup properly for a given repo, run the following command:

$ git config --list --show-originCode language: PHP (php)

Finally, to setup your editor, run the following command:

$ git config --global core.editor vimCode language: PHP (php)

Working With Repositories

In order to work with repositories, there are a few primary commands you need to work with — clone, branch, checkout, pull, and push.

Cloning

git clone is the command you will use to pull a repository from a URL and create a copy of it on your machine. There are a couple protocols you can use to clone your repository: SSH or HTTPS. I always prefer to set up SSH keys and use SSH, but that is because in the past it wasn’t as easy to cache your HTTPS credentials for Git to use. Those details are beyond the scope of this post, but there is plenty of information about using SSH and HTTPS here.

To clone an existing repository from a URL, you would use the following command:

$ git clone https://github.com/jhaws1982/zRPC.gitCode language: PHP (php)

This will reach out to the URL, ask for your HTTPS credentials (if anonymous access is not allowed), and then download the contents of the repository to a new folder entitled zRPC. You can then start to work on the code!

Sometimes a repository may refer to other Git repositories via Git submodules. When you clone a repository with submodules, you can save yourself a separate step to pull those by simply passing the --recursive option to git clone, like so:

$ git clone --recursive https://github.com/jhaws1982/zRPC.gitCode language: PHP (php)

Branches

When working with Git repositories, the most common workflow is to make all of your changes in a branch. You can see a list of branches using the git branch command and optionally see what branches are available on the remote server:

$ git branch         # list only your local branches
$ git branch --all   # list all branches (local and remote)Code language: PHP (php)

To checkout an existing branch, simply use the git checkout command:

$ git checkout amazing-new-feature
Switched to branch 'amazing-new-feature'
Your branch is up to date with 'origin/amazing-new-feature'.Code language: JavaScript (javascript)

You can also checkout directly to a new branch that does not exist by passing the -b option to git checkout:

$ git checkout -b fix-problem-with-writer
Switched to a new branch 'fix-problem-with-writer'Code language: JavaScript (javascript)

Interacting with the Remote Server

Let’s now assume that you have a new bug fix branch in your local repository, and have committed your changes to that branch (more on that later). It is time to understand how to interact with the remote server, so you can share your changes with others.

First, to be sure that you are working with the latest version of the code, you will need to pull the latest changes from the server using git pull. This is best done before you start a branch for work and periodically if other developers are working in the same branch.

$ git pull

This will reach out to the server and pull the latest changes to your current branch and merge those changes with your local changes. If you have files that have local changes and the pull would overwrite those, Git will notify you of the error and ask you to resolve it. If there are no conflicts, then you are up-to-date with the remote server.

Now that you are up-to-date, you can push your local commits to the remote server using git push:

$ git push

git push will work as long as the server has a branch that your local one is tracking. git status will tell you whether that is the case:

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

nothing to commit, working tree cleanCode language: JavaScript (javascript)
$ git status
On branch fix-problem-with-writer
nothing to commit, working tree cleanCode language: JavaScript (javascript)

If you happen to be on a local branch with no remote tracking branch, you can use git push to create a remote tracking branch on the server:

$ git push -u origin fix-problem-with-writerCode language: JavaScript (javascript)

Working with Source Code

Git makes it very easy to work with your source code. There are a few commands that are easy to use and make managing code changes super simple. Those commands are: status, add, commit, stash, and reset.

Staging Your Changes

To stage your changes in Git means to prepare them to be added in the next commit.

In order to view the files that have local changes, use the git status command:

$ git status
On branch fix-problem-with-writer
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:   CMakeLists.txt
        modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")Code language: Bash (bash)

Once you are ready to stage your changes, you can stage them using git add:

$ git add README.md

If README.md has a lot of changes, and you want to separate them into different commits? Just pass the -p option to git add to add specific pieces of the patch.

$ git add -p README.md
$ git status
On branch fix-problem-with-writer
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   README.md

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:   CMakeLists.txt
Code language: JavaScript (javascript)

To commit these changes you have staged, you would use the git commit command:

$ git commit

Git commit will bring up an editor where you can fill out your commit message (for a good commit message format, read this; you can also read this for details on how to set up your Git command line to enforce a commit log format).

You can also amend your last commit if you forgot to include some changes or made a typo in your commit message. Simply stage your new changes, then issue:

$ git commit --amend

Storing Changes For Later

Git has a fantastic tool that allows you to take a bunch of changes you have made and save them for later! This feature is called git stash. Imagine you are making changes in your local branch, fixing bug after bug, when your manager calls you and informs you of a critical bug that they need you to fix immediately. You haven’t staged all your local changes, nor do you want to spend the time to work through them to write proper commit logs.

Enter git stash. git stash simply “stashes” all your local, unstaged changes off to the side, leaving you with a pristine branch. Now you can switch to a new branch for this critical bug fix, make the necessary changes, push to the server, and jump right back into what you were working on before. That sort of flow would look like this:

<working in fix-problem-with-writer>
$ git status
On branch fix-problem-with-writer
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:   CMakeLists.txt

no changes added to commit (use "git add" and/or "git commit -a")

$ git stash
Saved working directory and index state WIP on fix-problem-with-writer

$ git status
On branch fix-problem-with-writer
nothing to commit, working tree clean

$ git checkout fix-problem-with-reader
Switched to branch 'fix-problem-with-reader'

<make necessary changes>
$ git add <changes>
$ git commit
$ git push

$ git checkout fix-problem-with-writer
Switched to branch 'fix-problem-with-writer'

$ git status
On branch fix-problem-with-writer
nothing to commit, working tree clean

$ git stash pop
On branch fix-problem-with-writer
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:   CMakeLists.txt

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (5e3a53d36338f1906e871b52d3c97236f139b75e)Code language: JavaScript (javascript)

There are a couple of things to understand about git stash:

  • The stash is a stack – you can stash as much as you want on it and when you pop, you’ll get the last thing stashed
  • The stash will try to apply all the changes in the stash, and in the event of a conflict, will notify you of the conflict and leave the stash on the stack

I run into the second bullet quite often, but it isn’t hard to fix. If I run into that sort of issue, it is usually simple conflicts that are easily addresses manually. Manually address the conflicts in the file, restore all staged changes from the git stash pop, and then drop the last stash.

$ git stash pop
Auto-merging CMakeLists.txt
CONFLICT (content): Merge conflict in CMakeLists.txt
The stash entry is kept in case you need it again.

$ git status
On branch fix-problem-with-writer
Unmerged paths:
  (use "git restore --staged <file>..." to unstage)
  (use "git add <file>..." to mark resolution)
        both modified:   CMakeLists.txt

no changes added to commit (use "git add" and/or "git commit -a")

$ vim CMakeLists.txt   # manually edit and resolve the conflicts
$ git status
On branch fix-problem-with-writer
Unmerged paths:
  (use "git restore --staged <file>..." to unstage)
  (use "git add <file>..." to mark resolution)
        both modified:   CMakeLists.txt

no changes added to commit (use "git add" and/or "git commit -a")

$ git restore --staged CMakeLists.txt

$ git stash drop
Dropped refs/stash@{0} (6c7d34915b38e5d75072eacee856fb427f916aa8)Code language: HTML, XML (xml)

Undoing Changes or Commits

There are often times when I need to undo the previous commit or I accidentally added the wrong file to my stage. When this happens it is useful to know that you have ways to back up and try again.

To remove files from your staging area, you would use the git restore command, like so:

$ git restore --staged <path to file to unstage>Code language: HTML, XML (xml)

This will remove the file from your staging area, but your changes will remain intact. You can also use restore to revert a file back to the version in the latest commit. To do this, simply omit the --staged option:

$ git restore <path to file to discard all changes>Code language: HTML, XML (xml)

You can do similar things with the git reset command. One word of caution with the git reset command — you can truly and royally mess this up and lose lots of hard work — so be very mindful of your usage of this command!

git reset allows you to undo commits from your local history — as many as you would like! To do this, you would use the command like so:

$ git reset HEAD~n

# For example, to remove 3 commits
$ git reset HEAD~3
Unstaged changes after reset:
M       CMakeLists.txt
M       tests/unit.cppCode language: PHP (php)

The HEAD~n indicates how many commits you want to back up, replacing n with the number you want. With this version of the command, all the changes present in those commits are placed in your working copy as unstaged changes.

You can also undo commits and discard the changes:

$ git reset --hard HEAD~n

# For example, to discard 1 commit
$ git reset --hard HEAD~1
HEAD is now at 345cd79 fix(writer): upgrade writer to v1.73Code language: PHP (php)

So there you have it – our top 10 Git commands to help improve your workflow. As we have mentioned before, when you take the time to understand your language and tools, you can make better decisions and avoid common pitfalls! Improving your Git workflow is a conscious decision that can save you a lot of time and headaches! Do you have a favorite command that we didn’t mention? Let us know in the comments below!

Last modified: January 30, 2023

Author

Comments

Write a Reply or Comment

Your email address will not be published.