Git - Summarizing the Most Useful Commands

It’s been a while since I wrote something tech or anything for that matter. I’m an avid user of Git and think it’s the best version control software out there currently. And GitHub as a repository for Git goes just like bread does with butter. Alright, I may have exaggerated a bit there with the bread part, but you get the gi[s]t. With that said, I thought I’d write a set of handy-dandy commands I tend to use on a regular basis which may be useful to some of you out there as much as it is to me. This by no means is a complete listing. You should refer to the original documentation whenever you have something more detailed to do. Let’s begin…

I will assume you have your repository already setup say on GitHub for example. You could have any other repository setup too since Git is independent of that, but you do need one. First thing you need is to set up your local repository and branch. Checkout your remote repository. In git terms, this is generally called origin essentially pointing to the origin/remote location of your repository, the one all the developers eventually commit their branch/code to. You can read more about how to get that done over here.

git clone <repo-url>

Set up your origin using SSH/HTTP

# SSH 
git remote add origin login@IP/path/to/repository 
# HTTP 
git remote add origin http://path/to/repository

General Branching

Branching is Git’s standout feature and the reason that makes it so powerful and unique. But be warned, that you could get into trouble if you’re not smart about how you want to manage many branches. I would generally recommend following the git-flow technique as far as managing and working with git branches goes, but you can use the more general branching commands that are standard in git too just as long as you can effectively manage them. I mention more about git flow in the Useful References section at the end of this post.

# Checkout a branch-name from your repository 
$ git checkout --track -b <local_branch_name> origin/<remote_branch_name>
# Create a new branch 
$ git branch <new_branch_name>
# Get list of all branches currently present 
$ git branch -r
# Delete branch locally 
$ git branch -d <branch-name> 

# Delete branch remotely 
$ git push origin :<branch-name>
# Getting differences between two branches 
$ git diff origin/master origin/develop 

# listing the differences separately in a file 
$ git diff origin/master origin/develop > my_diff.diff 

# getting updates to your branch, watch out! This could lead to merge conflicts sometimes 
$ git pull origin <your-branch-name>

Stashing Changes

Personal experience has got me to the conclusion that you don’t really know git if you haven’t learnt how to stash. Not to mention how immensely useful this feature is. Just as the word ‘stash’ would suggest, this feature helps you save state as you switch between many branches and helps you get back to the previous state of your branch. This is a very common scenario especially when you have many branches and a large code base. Say you’re on your feature branch and you want to make a hotfix since production just realized a major bug that needs immediate addressing. Stash to the rescue here. You can easily stash your feature branch changes and move over to the production branch and do your hotfix. Also git kind of enforces this since you can’t exactly change branches without either commiting or stashing your changes. And many a times you don’t want to commit stuff that doesn’t work or is pretty nascent.

# Stash changes in current branch
$ git stash

# Apply previous stash to your branch once you get back
$ git stash pop

# View the list of stashed items
$ git stash list

# Clear/Empty out you stash stack
$ git stash clear

Handling Merge Conflicts

There comes a time when you try to update your code with whatever’s in the remote repository (if many developers are working together) and you run into merge issues. That’s the story of every version control user. Sure there are some tools that help you auto fix merge issues but that doesn’t always necessarily cut it. Sometimes, you need to get into the specific file in issue and fix it by reading/viewing the code at length. I generally use one of these 3 ways to handle it.

# Merging another branch into your branch
$ git merge <branch-name>
# If the above leads to merge conflicts git will already indicate that to you
# and would not allow you to do any further commits until you resolved them.

# Get the list of all files in conflict after the merge
$ git diff --name-only --diff-filter=U

# To checkout your own version of the file and override what's at the master branch, do these:
$ git checkout HEAD -- <filename>
$ git checkout --ours -- <filename>
$ git show :2:<filename> > <filename>
# The :2 above would stand for our version of the file name,
# 1 and 3 stand for common base and the main develop/master branch respectively as shown later below.

# To checkout the version of the file from the branch that you merged(their's), do these
$ git checkout main-branch -- <filename>
$ git checkout --theirs -- <filename>
$ git show :3:<filename> > <filename> # (version 3 is theirs)

# Finally if you manually go into the file and remove the conflicted lines and edit them,
# you'll need to readd the file or else git will not acknowledge the conflict as resolved.
$ git add <filename>

Commit Process

So when you’re ready to commit code, you need to first not only commit the code locally to your branch, but you also need to push those changes eventually to your remote code repository on GitHub or anywhere else.

# If you want to cancel your commit and reset your branch to last version before you made changes, do this
$ git reset --hard

# If you want to go to a specific commit before in time, do this
$ git reset <SHA-ID of the commit>
# You can obtain the SHA ID by doing a git log and seeing the SHA hash of the commit you need.

# Before you commit, do a status check to see all the files that are ready to be staged to push
$ git status

# Commiting the changes
$ git commit -a -m 'commit message'
# -a above means send all the files form the status check that is
# automatically stage files that have been modified and/or deleted

# Pushing the changes to your repo, much like the earlier pull for getting updates
$ git push origin <branch-name>

Miscellaneous

Some additonal commands I tend to use occasionally but can’t really be classified as essential but are useful too for some cases.

The git config helps you see/change your config settings that decide where to push/pull code to/from. Say your repo or email changes, this is the place to update

# change email for example
# View the current value
$ git config --global user.email

# Change it
$ git config --global user.email "[email protected]"

Useful References:

  • Git Visual Cheat Sheet
  • Git Flow Process