DEV Community

Cover image for Handy Git Commands and practices to improve your workflow
Ted Ngeene
Ted Ngeene

Posted on • Edited on

Handy Git Commands and practices to improve your workflow

I have been in active software development for the better part of the last year and a half. For the majority of that period, I've come to appreciate the power of git, especially since the onset of the pandemic, where I've been working remotely 90% of the time, the technology has been very crucial in the development of my career.
The aim of this post is to highlight some of the common git commands that I use on a daily, which I'm sure most of you reading this will apply at some point or do also apply. The post is also meant to deconstruct the notion that git is complicated. Hopefully, you'll gain new insights into it. Let's dive in...

This article is divided into four parts:

  1. Definition of terms
  2. Commands
  3. Best Practices
  4. Resources

*Disclosure: I only recommend products I would use myself and all opinions expressed here are my own. This post may contain affiliate links that at no additional cost to you, I may earn a small commission.

Definition of terms

Before we move to the commands, it's important to familiarise ourselves with common terms used in the git world.
Let's have a look at some of them.

  • Git - it is a distributed version control system for tracking any set of files, for coordination among developers. Basically put, it is like a savings program for your project. It enables tracking and logging the changes you make to your file or file sets over time, a version-control system gives you the power to review or even restore earlier versions by taking snapshots of every revision in your project. You can access these versions to compare and revise them when the need arises.
  • Git repository hosting service - these are third-party web applications that wrap and enhance a version control system. An example of popular ones are; Github, Bitbucket, Gitlab. Many people confuse these to be one and the same thing with git. However, they are completely different. So, are they much more closely connected than Java and JavaScript? Yes, git is the underlying technology that platforms such as Github use to manage repositories. For a more detailed explanation on this, check out this article.
  • Git branch - a branch represents an independent line of development on a project. For example, if you're working on a feature that involves creating an admin dashboard, you may choose to create a branch called dashboard in which you work on all the dashboard logic.
  • HEAD - When working with Git, only one branch can be checked out at a time - and this is what's called the "HEAD" branch. Often, this is also referred to as the "active" or "current" branch. Git makes note of this current branch in a file located inside the Git repository, in .git/HEAD. (This is an internal file, so it should not be manually manipulated!). By now you may have noticed that the tree is the symbolic representation in git 😄.

Commands

-git init - This command creates a new Git repository. It can be used to convert an existing, unversioned project to a Git repository or initialize a new, empty repository.
-git remote add origin {remote_url} - connects a repo to a remote git URL. An example is;
git remote add origin https://github.com/tngeene/Dadjokes-app.git

  • git remote -v - checks the remote URLs set on a particular repo. A repo can have more than one remote, say for example you're pushing the code to two platforms such as Github and Bitbucket
  • git remote remove origin or git remote rm origin - removes a remote
    • alternatively, you can use git remote set-url origin {new.url.here} this command automatically removes the old remote and assigns the new one. In our example above, you might realize you've made a mistake and set the wrong origin, using the second approach of removing an origin, (I won't delve into the first one since it's pretty straightforward), you can run this command git remote set-url origin https://github.com/tngeene/Bakery-template.git and this will remove the previously specified url and set the new one.
  • git rm -r --cached . - this command comes in handy when you want to untrack files, say you realized you would like to add it to the .gitignore file when it was already tracked.
    • rm : remove command.
    • -r : allows recursive removal.
    • — cached : will only remove files from the index. Your files will still be there.
    • . : untracks all files. You can untrack a specific file by git rm -r --cached {path_to_ file}
  • git clone - useful for getting the contents of a remote repo to your local machine. Usually used when you don't initially have the code. Example usage is git clone {url_of_repo}, for example git clone https://github.com/tngeene/fibonacci-sequence-react.git
  • git fetch - really only downloads new data from a remote repository - but it doesn't integrate any of this new data into your working files. Fetch is great for getting a fresh view of all the things that happened in a remote repository.
  • git pull - in contrast, is used with a different goal in mind: to update your current HEAD branch with the latest changes from the remote server. This means that pull not only downloads new data; it also directly integrates it into your current working copy files. This has a couple of consequences:

    • Since git pull tries to merge remote changes with your local ones, a so-called "merge conflict" can occur.

Sytntax to use

git pull {remote_branch_name} {feature_branch_name} - for example git pull origin master

One can use git pull —set-upstream {remote_branch_name} {feature_branch_name}. This syntax avoids specifying the remote branch to update every time, for example, git pull —set-upstream origin master will allow you to just type git pull once you've checked out in the master branch.

  • git push - pushing the code that's in your local machine to a remote branch. The syntax is the same as the git pull command highlighted above.

A thing to note about this is that for an initial repo, especially if it was initialized with a README file, it might bring in errors such as the remote having contents you do not have. Another one could be that the repo has unrelated histories. So before you push code make sure to first pull from the remote by specifying git pull origin master —allow-unrelated-histories

  • git branch - allows one to create a new branch. The syntax for this is, git branch -f {branch} {start_point}.
git branch - f updates master
Enter fullscreen mode Exit fullscreen mode
  • git checkout The git checkout command lets you navigate between the branches created by the git branch command. For example, if we would like to navigate to the updates branch created above, we would simply run git checkout updates. Something to note when we're checking out is to make sure we've committed the changes we were working on in the branch we're checking out from.
    • Using the git checkout command, one can also create a new branch and checkout to it immediately, all using one command! So how do we go about this, you might ask. Well, simply type git checkout -b {branch_name} while in the current working branch. In our case above, git checkout -b updates. This will automatically merge all the existing changes in your current branch into the newly created branch.
  • git add - now that you've finished working on all the cool stuff you've been working on, you'll want to push them to the remote origin we set with the git add remote origin command. The git add command is part one of that process. This command adds a change in the working directory to the staging area. It tells Git that you want to include updates to a particular file in the next commit. There are two approaches to adding files that you want to push to the remote.
    • git add . This command adds all the changes you've made to be included when you push them to the remote. The . at the end signifies that you want to stage all the files.
    • git add {path_to_file_you_want_to_stage} - this command lets you specify which updates you'd like to be staged for commit. For example one might only want to update the settings file, you would only need to type git add ./settings.py
  • git commit - finally that you've added all your changes you will want to save them to be included once you decide to push to the remote repo. This command saves the changes to your local machine.
    • The syntax for this commit involves including a message to describe what changes you've been working on, for example after working on a bug that fixes the login logic on a form, one might choose to commit it using this git commit -m "fixed email validation on login API" The -m flag denotes message
   It is important to write informative commit messages so 
   those other people who are working on the branch know 
   exactly what you were working on(just as it's important to 
   use descriptive variable names 😉).
Enter fullscreen mode Exit fullscreen mode
  • git merge - after working on all the changes in your newly checked out branch, you might want to merge all the changes to the main branch before pushing them to the remote. After making a commit on the feature branch, run the command git checkout {branch_you_want_to_checkout_to} and then git merge {feature_branch_name}. In our example above, if we want to merge changes we've made into the main branch, we would go through these steps
        git checkout main
        git merge updates
Enter fullscreen mode Exit fullscreen mode
  • git log - this command allows you to view information about previous commits. it simply shows the commits that lead up to the current state of the current working branch.

Reverting to a previous commit.

Often times you may realize that you made a mistake and would like to roll back to a more stable version of the project. Luckily, git offers solutions to this problem. We can choose to either use git revert or git reset commands. For the purposes of this guide, I'll go with git revert as I have more experience using it. However, for in-depth analysis and comparison of both commands, you can have a look at this article from atlassian.
The first step in rolling back is to identify at which point you'd like to go back. For this, we'll use our friend, git log
Git log ngeene
Notice the ordering of the commit history, with the "HEAD" being the first one on the list. If we want to go back to the commit with the message "reverted to ssr", we would run

git revert --no-commit 4eab63b2..HEAD
git commit
Enter fullscreen mode Exit fullscreen mode

This will revert everything from the HEAD back to the commit hash, meaning it will recreate that commit state in the working tree as if every commit after 4eab63b2 had been walked back. You can then commit the current tree, and it will create a brand new commit essentially equivalent to the commit you "reverted" to.
The --no-commit flag lets git revert all the commits at once.

Note that we've used the commit hash of the commit above the one we'd like to roll back to.

There is of course more than one way to revert, but this is what works for me. Feel free to add to the discussion on best practices to revert in the comments.

Best Practices

While working with git, it vital to follow some practices, especially working with a team. The practices I'll mention are my personal preference and totally biased towards my own views.

Use Descriptive commit messages

It's important to let other developers working on the project on what exactly you've been working on. writing a commit message such as "fixed loader on landing page" instead of "landing page update" goes a long way in informing the code reviewers of what you've worked on.

Make Pull Requests

Once you've pushed your changes to Github if on a feature branch, remember to make a pull request(merge request in GitLab). This will notify project owners of a request to integrate your changes into the main branch and they can do a code review.

Write an informative pull request message.

Still, on the subject of pull requests, it's important to let code reviewers know why you'd like your code to be merged into the main branch. An example of a pull request message would go along the lines of;

This commit contains updates on the user registration logic
1. Fixed signup form validation by adding error handling
2. Added vee-validate on login and registration forms
3. Updated redirection on successful signup
4. Integrated social auth as a signup option (using google and Facebook)
Enter fullscreen mode Exit fullscreen mode

Keep Commit Revisions minimal

As a minimalist, I believe that it's best to work on bits of the code and push them instead of making revisions on many files and pushing them at once. My case for this argument is that it provides for good tracking in case things break at some point, we can just roll back to the commit and undo the minor mistake made on a couple of files instead of multiple files, which can prove to be a nightmare.

That covers the end of this article. There's a ton of information on git, but for now, we'll only dive into the shallow end that is the very deep pool of git. I hope this piece helps someone and feel free to drop your thoughts. You can also check out my website or follow me on Twitter.

Include a gitignore file

When working on a project, there are some directories and files you'd prefer git not to track as well as some files which are not recommended to be tracked, an example being the node_modules files in node.js. This aids in reducing boilerplate code since the files are still going to be recreated in the other developer's machine. I found this interesting GitHub repo containing a list of popular .gitignore templates for most frameworks and languages.

Resources

This section highlights some useful resources to get you started with git. It includes videos, blog posts, and podcasts.

  1. Freecodecamp's Git and GitHub youtube course
  2. A collection of gitignore templates
  3. Ladybug podcast episode on git and github
  4. Devmountain's explanation on the difference between git and github
  5. The official git documentation
  6. Edureka's youtube git course

Sponsors

  • Do you need a place to host your website or app, Digital ocean is just the solution you need, sign up on digital ocean using this link and experience the best cloud service provider.
  • The journey to becoming a developer can be long and tormentuos, luckily Pluralsight makes it easier to learn. They offer a wide range of courses, with top quality trainers, whom I can personally vouch for. Sign up using this link and get a 50% discount on your first course.
  • Scraper API is a startup specializing in strategies that'll ease the worry of your IP address from being blocked while web scraping. They utilize IP rotation so you can avoid detection. Boasting over 20 million IP addresses and unlimited bandwidth. Using Scraper API and a tool like 2captcha will give you an edge over other developers. The two can be used together to automate processes. Sign up on Scraper API and use this link to get a 10% discount on your first purchase.

Thanks for going through the article. I hope in one way or another, you have a better understanding of git. Cheers!

Top comments (11)

Collapse
 
michaelcurrin profile image
Michael Currin

Thanks for sharing. I rarely use git rm - I usually use rm and commit. And I rename the path to something else if I need to keep it.
I added to my notes regarding cached and -r flags though.

I don't need to use git branch for a new branch. Your usage of git checkout -b is much more common and practical.

And pro tip. I rarely use add if a file already exists...

If i make file changes, then i do this for the directory (or use a dir name).

git commit .
Enter fullscreen mode Exit fullscreen mode

You can also check the comments in your commit message editor window if you need to see which paths are going to be committed. Or use git status before you commit.

Here I commit changes to package.json and package-lock.json without using add but preventing changes in other files getting commited.

git commit package*
Enter fullscreen mode Exit fullscreen mode
Collapse
 
tngeene profile image
Ted Ngeene

this is a new way of looking at things. Really helpful. Thanks Mike.

Collapse
 
neurovelho profile image
Teemu Hirvonen

That's a very nice list! The bit about descriptive commit messages and pull requests is especially important. It's not very nice navigating a codebase where half the commits are "updated stuff" and "implemented thingamajig".

Here's a couple of more commands if you want to show off a bit to other developers in your team (or maybe make your and your teams lives a bit easier 😄):

$ git config --global alias.co checkout
Enter fullscreen mode Exit fullscreen mode

Comes in pretty handy if you're tired of having to write git checkout [branch] every time you want to change branches. Can just do git co [branch]. You can of course create aliases for other stuff like commit, etc.

Another cool command is rebase. Many people use it mainly for rebasing master onto a feature branch but you can also use it for cleaning up commits on your feature branch. Here's a pretty cool article showing how to do it.

Collapse
 
tngeene profile image
Ted Ngeene

Thanks! I didn't know this. I tried it out and works like a charm!

Collapse
 
singhrahul31 profile image
singhrahul31

Just a query here. So we take out a branch from the 'main' as 'code fix'. Once done with the changes we would commit & push the branch to the repo. Checkout the 'main' branch and then merge the 'code fix' to the main
Am i saying this right or missing out on something?

Collapse
 
tngeene profile image
Ted Ngeene

Yeah, you're saying it right. But the appropriate way is to push it to the repo and wait for it to be merged. The only reason you'd merge locally is when you're working alone. But it's advisable that you push to the remote, once it's been merged then you can pull from the master.

Collapse
 
watiriroyalty profile image
Watiri Kambo

Nice read.....you made it so easy to understand 😀

Collapse
 
realtoughcandy profile image
RealToughCandy.io

Useful list here for Git newbies and experienced users alike.

Collapse
 
willteksoftwares profile image
willteksoftwares

Very well explained Teddy. Nice one.

Collapse
 
bmuskalla profile image
Benjamin Muskalla

Nice one! You may be interested in this one as well as explaining some of the cool features behind git log/blame: dev.to/bmuskalla/git-archeology-1nl3

Collapse
 
tngeene profile image
Ted Ngeene

nice article...