11 Git tips to level up your workflow

Becoming a Git power user is on the bucket list of every developer. Today we prepared 11 Git tips that will help you level up your workflow and bring you one step closer to Git mastery.
Tip #1
Keep your commits organized
You just wanted to fix that one feature, but in the meantime got into the flow, took care of a tricky bug and spotted a very annoying typo. One thing led to another, and suddenly you realised that you’ve been coding for hours without actually committing anything. Now your changes are too vast to squeeze in one commit…
git add -p <filename>
With git add -p
(or git add --patch
) you can choose which parts of code from a file you want to include in your commit. After running the command you will get the list of the options you can add to git add -p
By choosing s
you can split the hunk into smaller pieces. From there you can simply choose the chunks you want to stage for commit (and omit those you don’t) by navigating with y
and n
(or go for any other option from the list).
Tip #2
View branch sorted by date
display a list of all local branches and sort them based on the date of their last commit.
# sort desc (-committerdate)
git branch --sort=-committerdate# sort asc (committerdate)
git branch --sort=-committerdate
If you’d like to make a custom format you can use for-each-ref
with --sort
option and--format
option to write your format.
git for-each-ref --sort='-committerdate' --format='%(refname)%09%(committerdate)' refs/heads
In the above command, I print the refname
first then commitdate
in --format
option the output will be like this
refs/heads/branch_name commitdate
refs/heads/branch_name2 commitdate# real output
refs/heads/new_design Wed Apr 20 12:24:21 2022 +0200refs/heads/design_assets Wed Apr 20 11:30:30 2022 +0200
If you want to print the date
first then refname
the option format will be like this --format='%(committerdate)%09%(refname)%'
Let’s say you don’t want to print refs/heads
and want o print just the branch name each time, how we can do this? by using sed
, let’s see how we can do this.
git for-each-ref --sort='-committerdate' --format='%(refname)%09%(committerdate)' refs/heads | sed 's-refs/heads/--'#output
branch_name commitdate
branch_name2 commitdate#real output
new_design Wed Apr 20 12:24:21 2022 +0200design_assets Wed Apr 20 11:30:30 2022 +0200
I find these commands incredibly helpful when returning to work from a weekend or just jumping from project to project. Hopefully, you can use these commands too!
to display a list of all local branches and sort them based on the date of their last commit, you can do this
Tip #3
View merged or un-merged branches
If you want to see a list of all merged local branches into a specific branch (master - main- etc…), in the following snippet I see all branches that merged into master
git branch --merged master
If you want to see a list of all merged local branches into HEAD
git branch --merged
If you want to see a list of branches that have not been merged
git branch --no-merged
if you used -a
option you’ll list all branches including remote branches
git branch -a --no-merged
Tip #4
Creating aliases
Use the command below to create aliases, replacing <alias>
with the name of the alias and <command>
with the command to be aliased:
git config --global alias.<alias> <command># Exgit config --global alias.s 'git status'
Useful aliases
https://gist.github.com/AbdlrahmanSaberAbdo/1afa6fe548a939859f23efa20cad3066
Tip #5
Create a commit with a different date
Sometimes, you might run into a situation where you need to create a commit with a different date than the current one. Luckily, you can handle this using GIT_AUTHOR_DATE
and GIT_COMMITTER_DATE
:
GIT_AUTHOR_DATE='Mon May 18 19:32:10 2020 -0400' \
GIT_COMMITTER_DATE='Mon May 18 19:32:10 2020 -0400'\
git commit -m 'Commit from the past'
As shown in the example above, you can set both values to any date you like and your code will be committed on that date. Note that the format for the values above is 'date +"%s %z"'
, also referred to as internal raw git format, but you can also use other formats, such as RFC 2822 ('Mon, 18 May 2020 19:32:10 -0400'
), ISO 8601 ('2020-05-18 19:32:10 -0400'
), local ('Mon May 18 19:32:10 2020'
), short ('2020-05-18'
) or relative (5.seconds.ago
, 2.years.3.months.ago
, '6am yesterday'
).
Tip #6
Create a commit by a different author
Creates a new commit by the specified author, actually, I don’t know the purpose of it but it’s also a trick you should know, be careful while reviewing the code, it might not the developer who’s pushed the code 😅, I made a post on LinkedIn wondering what’s the purpose of it with video, you can see it from here
- Use
git commit -m <message>
to create a new commit with the specified<message>
. - Use the
--author
option to change the<name>
and<email>
of the commit's author.
git commit -m <message> --author="<name> <email>"git commit -m "Fix the network bug" --author="Duck Quackers <cool.duck@qua.ck>"
Tip #7
View differences in changes
Displays differences between staged or unstaged changes and the last commit.
- Use
git diff
to view the differences between your unstaged changes and the last commit. - You can use the
--staged
option to view differences between your staged changes and the last commit instead.
git diff [--staged]# Displays the differences between unstaged changes and the last commit
git diff# Displays the differences between staged changes and the last commit
git diff --staged
Tip #8
Take me back (when everything worked!)
Not your best day. You made changes you shouldn’t have and now everything is broken… Is there a way to undo those commits?
Git keeps track of updates to the tip of branches using a mechanism called referencelogs
, orreflogs
Many Git commands accept a parameter for specifying a reference or “ref”, which is a pointer to a commit. Common examples include git checkout
or git reset
.
git reflog
you can get the record of all the commits done in Git.

Now you just need to find the commit prior to the one that caused all the hassle. HEAD@{index}
represents the specified commit, so just replace the index with the correct number and run:
git reset HEAD@{index}
The default action for git reset
is git reset --mixed
. It means that the changes in your working directory will be preserved but not staged (since the index was modified to match the chosen commit, the changes are not in the index anymore).
Other options are:
# Doesn’t modify the index or the working tree, leaving your changes staged for commit.git reset --soft# Use with caution, as it resets both the index and working tree. Uncommitted changes and all commits after will be removed.git reset --hard
And now, you can start over from the point when everything in your repository worked like a charm. Remember to use it only locally, as modifying a shared repository is considered a serious crime.
Tip #9
View a visual graph of the repository
Prints a visual graph of all commits and branches in the repository.
- Use
git log --pretty=oneline --graph --decorate --all
to view a visual graph of the whole repository's history.
git log --pretty=oneline --graph --decorate --allgit log --pretty=oneline --graph --decorate --all
# * 3050fc0de Fix typo
# * c191f90c7 Initial commit
Tip #10
See commits in a specific date range
If you’re looking for a commit and don’t want to search between all commits you can search by date by using the following command
- Use
git log --since=<date-from> --until=<date-to>
to view a log of all commits between<date-from>
and<date-to>
. - You can use it only
--since=<date-from>
to see all commits since a specific date or only--until=<date-to>
to view all commits up to a specific date.
git log [--since=<date-from>] [--until=<date-to>]git log --since='Apr 1 2021' --until='Apr 4 2021'
# commit c191f90c7766ee6d5f24e90b552a6d446f0d02e4
# Author: 30 seconds of code
# Date: Tue Apr 6 11:11:08 2021 +0300
# [...]
git log --since='2 weeks ago'
# commit c191f90c7766ee6d5f24e90b552a6d446f0d02e4
# Author: 30 seconds of code
# Date: Tue Apr 6 11:11:08 2021 +0300
# [...]
Tip #11
Merges a branch into the current branch, creating a merge commit.
- Use
git checkout <target-branch>
to switch to the branch into which you want to merge. - Use
git merge --no-ff -m <message> <source-branch>
to merge a branch into the current branch, creating a merge commit with the specified<message>
. - The
--no-ff
flag preventsgit merge
from executing a "fast-forward" if it detects that your currentHEAD
is an ancestor of the commit you're trying to merge. A fast-forward is when, instead of constructing a merge commit, git just moves your branch pointer to point at the incoming commit. This commonly occurs when doing agit pull
without any local changes.
So when I can use --no-ff
?
Occasionally you want to prevent this behavior from happening, typically because you want to maintain a specific branch topology (e.g. you’re merging in a topic branch and you want to ensure it looks that way when reading history). In order to do that, you can pass the --no-ff
flag and git merge
will always construct a merge instead of fast-forwarding.
Similarly, if you want to execute a git pull
or use git merge
in order to explicitly fast-forward, and you want to bail out if it can't fast-forward, then you can use the --ff-only
flag. This way you can regularly do something like git pull --ff-only
without thinking, and then if it errors out you can go back and decide if you want to merge or rebase.
Let’s know the difference between non-fast-forward merge and fast-forward merge, rebase, squash.
Explicit Merge (aka non-fast-forward): Creates a new merge commit. (This is what you will get if you used --no-ff
.)

Fast Forward Merge: Forward rapidly, without creating a new commit:

Rebase: Establish a new base level:

Squash: Crush or squeeze (something) with a force so that it becomes flat:

Might be you’re asking now what’s the difference between fast-forward and rebase merge?
I’ll make another blog explain each one in-depth, but let me give you a quick answer now to sure you fully understand.
Fast-Forward maintains the same base and tries to merge all file changes from the same changes after the shared base.
Rebase “detaches” your branch, and then applies commit after commit on top of the base (as if you just checked out a fresh e.g. master branch), and THEN, tries to, apply the changes done on the new base. The rebase is usually used before you’d want to merge into master, so that it applies the topic-commits on top of master, without merge conflicts.
Hope this article is useful.