I'm a command line lover and use Git from the terminal all the time.
If you're like me, you might start getting annoyed by some little things at a certain point. For example, it starts to get a bit annoying to always type two separate commands - git add <file>
then git commit -m 'Your commit message'
- to commit your changes. Or maybe you want to have a better looking git history when you type git log
. Or you want your local branch to be automatically pruned when the remote branch has been deleted. Little things like these - you get the idea.
Over time, I have built up a curated list of commands, aliases and configrations that I use on a daily basis that makes my workflow more efficient and pleasant. And I'd like to share them with you below.
In addition, this command also shows the hash code and the commit message of the latest commit. It also tells you if the remote branch has been deleted.
git branch -vv
For example, running the command produces the following output on my machine,
With Git versions ≥ 1.6.6 and with only one remote, you can just do:
git fetch
git checkout <branch_name>
git checkout <branch_name>
will NOT work in modern Git if you have multiple remotes. In this case use
git checkout -b <branch_name> <remote_name>/<branch_name>
or the shorthand
git checkout -t <remote_name>/<branch_name>
Add either one of the following aliases to your global Git config file (usually at ~/.gitconfig
on a Linux/Mac OS system). I prefer the second one because it saves a few more keystrokes.
# add a `add-commit` alias, or
git config --global alias.add-commit '!git add -A && git commit'
# add a `ac` alias to save a few more keystrokes
git config --global alias.ac '!git add -A && git commit'
And use it with
git add-commit -m 'My commit message' # or
git ac -m 'My commit message'
When you're done with a branch, you can delete it from both the remote and your local machine using the commands below.
# delete a remote branch
git push -d <remote_name> <branch_name> # or
git push -D <remote_name> <branch_name>
# delete a local branch
git branch -d <branch_name> # or
git branch -D <branch_name>
Note: The -d
option is an alias for --delete
, which only deletes the branch if it has already been fully merged in its upstream branch. You could also use -D
, which is an alias for --delete --force
, which deletes the branch "irrespective of its merged status".
Assume you have a long running development
branch, and you branch off it to create different feature branches e.g. feature/A
, feature/B
.
After your peers have reviewed your pull requests for both features, merged them back to development
and deleted them from remote. You can delete feature/A
and feature/B
from your local by running,
# switch to the development branch first
git checkout development
# delete local branches whose remote tracking branches have been merged back to development
git delete-merged
You probably have noticed that delete-merged
is not a Git command - it's actually an alias we set up. The parameters used in the actual command is different depending on your setup. But you can follow the following steps to construct a command that suits your needs.
Step 1: Check out the development
branch.
Step 2: List all branches that have been merged into it in remote.
git branch --merged
Step 3: You might see a few branches that you don't want to remove e.g. master
, release
etc. And you can filter down the list by excluding those branches by
git branch --merged | egrep -v "(^\*|master|development|skip_branch_name)"
The regular expression used by the egrep
command basically means "all branches whose name starts with master
, development
or skip_branch_name
will not be deleted".
You can modify the branches above or add your own branches that you don't want to delete.
Step 4: Delete all local branches that are already merged into the currently checked out branch
git branch --merged | egrep -v "(^\*|master|development|skip_branch_name)" | xargs git branch -d
Step 5: Set a global alias deleted-merged
for the command
git config --global alias.delete-merged 'git branch --merged | egrep -v "(^\*|master|development|skip_branch_name)" | xargs git branch -d'
To discard all unstaged files in current working directory,
git checkout -- .
For a specific file, use
git checkout -- path/to/file/to/revert
The --
is to remove argument ambiguation.
Step 1: Rename your local branch
If you are on the branch you want to rename:
git branch -m <new-name>
If you are on a different branch:
git branch -m <old-name> <new-name>
Step 2: Delete the <old-name>
remote branch and push the <new-name>
local branch
git push origin :<old-name> <new-name>
Step 3: Reset the upstream branch for the <new-name>
local branch
Switch to the branch and then:
git push origin -u <new-name>
You can format your Git log to look like below and set an alias for it.
Step 1: Set up the following alias in your global Git config file
git config --global alias.lg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative"
Step 2: Append additional flags if needed
# filter by start date
--after="2016-01-31"
--since="2016-01-31"
# filter by end date
--before="2017-03-10"
--until="2017-03-10"
# filter by author
--author="Zean Qin"
My most commonly used command is
git lg --after="yesterday" --author="Zean"
Before merging one branch into another, you might want to get an overview of the commits to be merged.
git log --oneline --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --decorate --abbrev-commit <destination_branch>..<source_branch>
I use diff-so-fancy to make the diffs more readable. Follow the official setup steps and then just run
git diff
Without git fetch --prune
, remote-tracking branches for a branch
the other side already has removed will stay forever.
To always --prune
for git fetch
and git pull
in all your Git repositories:
git config --global fetch.prune true
To always --prune
but from one single repository,
git config remote.origin.prune true
#^^^^^^
#replace with your repo name
If you want to set the editor only for Git, do either (you don’t need both):
core.editor
in your Git config: git config --global core.editor "vim"
GIT_EDITOR
environment variable: export GIT_EDITOR=vim
If you want to set the editor for Git and also other programs, set the standardized VISUAL
and EDITOR
environment variables:
VISUAL
.
export VISUAL=vim
export EDITOR="$VISUAL"
# revert the commit and create a new commit
git revert <commit-id> -m <parent-number>
# push the new, revert commit to remote
git push
# other people can then pull the new commit
git pull
The -m
option specifies the parent number. This is because a merge commit has more than one parent, and Git does not know automatically which parent was the mainline, and which parent was the branch you want to un-merge.
When you view a merge commit in the output of git log
, you will see its parents listed on the line that begins with Merge
:
commit 35b4b1355e5dbfeece0121cff2c89ec574da2a29
Merge: 420dacb2 beca933d
Author: Alexander<alex@gmail.com>
Date: Fri Jan 22 16:42:36 2021 +1100
Merge branch 'feature/RUM-649-redux' into development
In this situation, git revert 35b4b13 -m 1
will get you the tree as it was in 420dacb2
, and git revert -m 2
will reinstate the tree as it was in beca933d
.