Suraj Deshmukh

Blog

containers, programming, golang, hacks, kubernetes, productivity, books

Being Productive with Git

Tips and tricks to make your day to day usage easier.

Suraj Deshmukh

5-Minute Read

Contents

Introduction

Git is a day to day tool for version control. It has become a de facto method of source code versioning, it has become ubiquitous with development and its an essential skill for a programmer. I use it all the time.

Because of its usage frequency, I wanted to optimise the number of keystrokes I made to get things done with it. I have made some tweaks and personalisation to my git workflow. Obviously, it involves aliases, scripts and other bash graphic tools.

Bash Aliases

The most straightforward way to shorten any long Linux command is to use an alias. And I use quite a bunch of aliases for everyday git commands. I have aliases for things like checking out the master branch, pulling stuff from remotes commonly named upstream or origin, looking at git commits, rebasing and amending commits.

Configuration

alias gpum="git pull --ff upstream master"
alias gpom="git pull --ff origin master"
alias gcm="git checkout master"
alias gs="git status"
alias gcmt="git commit -s"
alias gl="git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
alias grba="git rebase -i --autosquash "
alias gca="git commit --amend --no-edit"

Installation

Above aliases you saw are placed in ~/.bashrc. You can find mine here.

Global Git Configuration

Configuration

The contents of gitconfig file look like this. I don’t have a lot of customisation just basic stuff. In the following snippet code means Visual Studio Code. I use vscode as my primary editor so I prefer it to be my difftool as well. The entire gitconfig is stored in my dotfiles repository.

[user]
  name = Suraj Deshmukh
[color]
  diff = auto
  status = auto
  branch = auto
  interactive = auto
  ui = auto
  pager = true
[diff]
  tool = default-difftool
  noprefix = true
[difftool "default-difftool"]
  cmd = code --wait --diff $LOCAL $REMOTE
[core]
  excludesfile = ~/.gitignore
  editor = code --wait

Installation

My global git configuration ~/.gitconfig is not something I create manually. I have an unusual way of creating it. So if you look at the configuration, it is just a symlink to the actual file which resides in my dotfiles repository. I have a special way of creating these symlinks, which is explained in my previous blog here.

$ ls -al ~/.gitconfig
lrwxrwxrwx@ 43 surajd 27 Jul  1:05 /home/surajd/.gitconfig -> /home/surajd/git/dotfiles/configs/gitconfig

Repository Specific Git Settings

There are some settings I want only for that particular repository. For instance, for my work, I sign-off all my commits with my work email id. For those repository-specific settings, I have a script which does the job for me.

Configuration

Right now this is all I do for work repository, so that’s all I need.

git config user.email "me@work.com"

Installation

You can copy above snippet in a file make it executable and place it in your PATH. I have this file in a dotfiles repository from where a script creates a symlink for this executable file and places in the PATH. All this script management framework is explained in my previous blog post here. You can find the exact file here.

Bash Git Prompt

Now when you are using plain old bash, it is not very helpful in terms of the context of the directory you are in. When you don’t have a visual aid, it is easy to make mistakes like commit something on the wrong branch or other undesired things. So I use this helper utility called bash-git-prompt which provides me with the git directory context. Like it tells me the path to the repository, the branch, the number of files changed, if the files are committed or untracked, exit code of the previous command, current time, etc. The bash prompt will change to look something like this when you are in a git repository:

✘-127 ~/git/blog_contents [foobar L|✚ 1…1]
23:01 $

Configuration

You need to have these two settings in your ~/.bashrc. So that the bash git prompt scripts are sourced every time the terminal starts.

# Bash Git Prompt
source ~/.bash-git-prompt/gitprompt.sh
GIT_PROMPT_ONLY_IN_REPO=1

Installation

Again this is installed easily using this helper script I have here. So I just have to run the command update-git-prompt, and then the repository is installed to be consumed.

Git Push

I have a script to push my changes to the PR I am working on. So every time I am done committing, I just need to do gpo.sh, and the changes are pushed to your origin remote. Behind the scene, there is a simple command which finds out what the current branch is and then push the current branch to origin.

git push origin $(git branch --show-current) "$@"

PR Reviews

For PR reviews, it is tough to comprehend all the code just by looking on Github. So I like to pull those changes locally. There is a handy script for it that I use. All I run is something like pr.sh 704 origin, so this is pulling PR number 704 from the remote named origin. If you have to pull changes from upstream then specify such or whatever your remote name maybe.

Configuration

random="${RANDOM}${RANDOM}"
git fetch "${remote}" "pull/${id}/head:pr_${id}_${remote}_${random}"
git checkout "pr_${id}_${remote}_${random}"

Installation

I use my regular framework to install above pr.sh. You can find the entire file here.

Demo

  • Step 1: Create branch:
git checkout foobar
  • Step 2: Make changes as needed. Look at the changes:
gs
  • Step 3: Add the changes:
git add .
  • Step 4: Commit these changes:
gcmt
  • Step 5: Push them:
gpo.sh
  • Step 6: CI failed, and now you need to make changes. Make necessary fixes and follow step 2 to 3. Then to amend the last commit just run:
gca
  • Step 7: Look at the git commits in the branch
gl
  • Step 8: Force push changes now:
gpo.sh -f

Conclusion

That was my tweaked Git workflow. Let me know your productivity hacks with git, in the comments or on twitter. Thanks for reading. Happy Hacking!

comments powered by Disqus

Recent Posts

Categories

About

I am a Senior Software Engineer at Microsoft, working on various tooling around container technology like Docker, Kubernetes, etc.