Git was released on April 7, 2005, which is exactly 20 years ago! To celebrate this milestone, I have compiled 20 git tips helping you to become a more effective gitter!
I also did the same on git's 16th and 17th birthday, but I missed the time git could start drinking alcohol:
The tips are not in any particular order, and vary from beginner to advanced. I hope you find them useful!
0. Set Up Your Personal Info Properly
Start by configuring your name and email globally:
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
Also, you can configure these per repository if you need to use different emails (e.g., work vs. personal):
git config user.email "work.email@company.com"
Bonus: Set up GPG signing too to verify your commits! Signing makes your commits more secure, as it verifies that they were made by you. To learn more, you can refer to my book Docker and Kubernetes Security.
1. Use .mailmap
to Clean Up Author Names
Git tracks authors by name and email. It's possible that someone mistakenly committed with a different name or email. This can clutter your commit history.
In this situation, we can use git's mailmap feature to unify them. Create a file named .mailmap
in the root of your repository and add entries like this:
Proper Name
Now git shortlog
and other commands show clean author lists.
Learn more about mailmap here:
2. Always Branch for New Features
Avoid committing directly to main
or master
. Create small topic branches for features and fixes:
git switch -c feature/new-login
I would personally use my GitHub handle, issue number, and a short description for the branch name:
git switch -c aerabi/1234-new-login
You can later mention the issue number in the commit message, and GitHub or GitLab will automatically link it to the issue. You can also close the issue automatically by adding Fixes #1234
in the commit message:
Add new login page
Closes #1234
Committing like this, the readers can later get the context of the commit by looking at the issue.
3. Cherry-Pick Commits Across Branches
If you want to get one commit from a branch to another one, you can use cherry-picking. First, note the commit hash you want to cherry-pick. This is done by doing a git log
and copying the hash of the commit you want.
Then, switch to the branch you want to apply it to:
git cherry-pick
The commit is added to the new branch, and you can continue working from there.
4. Cherry-Pick Commits from Another Repository
You can even cherry-pick commits from another repo:
git remote add other-repo
git fetch other-repo
git cherry-pick
Remove the remote afterward if you want.
5. Use git switch
and git restore
Instead of git checkout
Checkout was an overused command back in the day. It was used for switching branches, restoring files, and more. Now, we have git switch
and git restore
to make things clearer:
git switch branch-name # To switch branches
git switch -c new-branch # To create and switch to a new branch
git restore file.txt # To discard changes to a file
git restore --staged file.txt # To unstage a file
It's more explicit and user-friendly!
Learn more about the new commands here:
6. Understand Three Types of Merge
- Three-way merge: Regular merge that creates a merge commit.
- Fast-forward merge: Happens automatically when there's no divergence, i.e. the branch is ahead of the base branch.
- Squash merge: Combine all commits into one before merging (great for PRs).
In GitHub and GitLab, you can configure the default merge method for pull requests.
If you're not sure which one to use, use squash merge. It keeps the history clean and makes it easier to understand.
If you're a pro, make rebase and fast-forward your default merge methods. Then, before merging, rebase your branch onto the base branch:
git pull --rebase origin master
Using rebase and fast-forward, you should keep your feature branch history clean.
Learn more here:
7. Stage Changes Selectively with git add -p
Instead of staging everything, selectively stage chunks of changes:
git add -p
Interactive and safe!
8. Undo a Rebase Safely
If you mess up a rebase, you can undo it:
git reflog
Find the commit before the rebase started, then reset:
git reset --hard
Learn more about undoing a rebase here:
9. Interactive Rebase to Clean Up History
Use interactive rebase to reorder, squash, or edit commits:
git rebase -i HEAD~5
It's the secret to beautiful commit histories. Using interactive rebase, you can:
- Squash commits together
- Remove commits
- Reorder commits
- Reword commit messages
10. Speed Up Rebase with --autosquash
When adding a commit to fix a previous one, you can commit it as a "fixup" or "squash" commit:
git commit --fixup
When doing so, the commit message should start with fixup!
or squash!
, respectively. This allows you to automatically squash them during a rebase.
When doing an interactive rebase on commits, you can use the --autosquash
option:
git rebase -i --autosquash
Git will move those commits automatically to the right place and mark them for squashing or fixing up.
Learn more here:
11. Handle Chains of Branches with --update-refs
If you branch from a branch and rebase the base branch, you usually have to manually rebase all dependent branches. Not with:
git rebase --update-refs
It automatically updates the child branches.
Learn more about this here:
12. Use git stash --keep-index
Need to stash only your unstaged changes? Use:
git stash push --keep-index
It leaves your staged work intact.
13. Make Empty Commits
Sometimes you want to create empty commits for testing or triggering CI/CD pipelines. You can do this with:
git commit --allow-empty -m "Trigger deployment"
If you're using them to create markers for deployment, you can use tags instead:
git tag -a v1.0 -m "Deployment marker for version 1.0"
14. Clean Up Untracked Files
Quickly remove untracked files (be careful!):
git clean -fd
Add -n
for a dry run first:
git clean -fdn
This command will show you what would be deleted without actually deleting anything.
15. Fetch All Remotes Simultaneously
If you have multiple remotes:
git fetch --all
Very useful for forks.
16. View Visual Branch History
Use this to see a graph of branches:
git log --oneline --graph --all --decorate
You can also create an alias for it:
git config --global alias.graph "log --oneline --graph --all --decorate"
Then you can do:
git graph
17. Add Aliases to Save Time
Tired of typing long git commands? Add aliases:
git config --global alias.enforce "push --force-with-lease"
Now git enforce
is equivalent to git push --force-with-lease
, which is used to push changes while ensuring that you don't overwrite any changes made by others.
Never do
git push --force
!
18. Use git worktree
for Multi-Branch Work
Instead of switching back and forth, you can check out multiple branches simultaneously:
git worktree add ../branch-folder branch-name
Worktrees are great for testing multiple branches at once without needing to switch back and forth.
19. Use git bisect
to Find Bugs
If you have a bug in your code, you can use git bisect
to find the commit that introduced it. This is a binary search through your commit history.
git bisect start
git bisect bad # The current commit is bad
git bisect good # The last known good commit
Then, git will check out commits in between. You can test each one and mark it as good or bad:
git bisect good # If the commit is good
git bisect bad # If the commit is bad
You can for example run the tests to see if the bug is present. Once you find the commit that introduced the bug, you can reset the bisect:
git bisect reset
This will return you to the original branch.
20. Read the Previous Tips
Happy 20th birthday, git! 🎉
If you want to read more tips, check out my previous articles!
Which tip was new to you? Or do you have your own pro-tip? I'd love to hear!