An Advanced Guide to Git: Practical Tips and Best Practices
Even after using git
for many years, it's common to
encounter situations where certain operations are unclear or hard to
remember. Sometimes, even if you know what to do, the infrequency of
using certain features may cause hesitation, fearing that one wrong
move could erase your existing changes. This article compiles some
common but easily forgotten git
operations to help you
overcome these challenges.
⚠️ Note: This article is intended for readers who are
already familiar with git
. If you're new to
git
and need to learn the basics, please check out my
"Git Beginner's Guide"
first.
Table of Contents
- Does Git Have a Undo Button? Can You Go Back After a Mistake?
- How to Delete All Commit History?
- How to Modify the Latest Commit?
- How to Reapply Your Commits After Significant Upstream Changes?
- What to Do When You Need a Shared Repo?
Does Git Have a Undo Button? Can You Go Back After a Mistake?
Everyone makes mistakes, especially when using a powerful and flexible
tool like git
. A single misstep can lead to unintended
consequences. Fortunately, git
comes with a built-in
"undo button," allowing us to revert errors and restore a
previous state.
⚠️ Note: The following
git reset --hard
command will discard any uncommitted
changes in your working directory. If you have any uncommitted
modifications, make sure to stash them first using
git stash
, and then restore them afterward with
git stash pop
.
Steps:
# Show the complete git operation history (including reset, checkout, merge, etc.)
git reflog
# Find the commit before the mistake (using the commit hash from reflog) and reset
git reset --hard <commit-hash>
git reflog
is a powerful command that keeps track of all
HEAD
movements in the repository, including deleted
commits. This means that even if you mistakenly run
git reset --hard
or git rebase
, which can
overwrite history, you can often recover lost commits using
reflog
.
How to Delete All Commit History?
Deleting all commit history is not a common scenario, and it is not recommended for open-source projects with multiple collaborators. Even for personal projects, caution should be exercised. If your goal is to clean up part of your commit history, refer to this GitLab article: “How (and why!) to keep your Git commit history clean”.
⚠️ Note: Even after using this method to clear commit
history, it is still theoretically possible to recover it. This is a
deliberate design choice of git
. If your goal is to
permanently remove sensitive information that was accidentally
committed, the best practice is to delete the repository and create a
new one.
Steps:
# Create a new orphan branch
git checkout --orphan tmp_branch
# Add all files
git add -A
# Commit as the new initial commit
git commit -am "Initial commit"
# Delete the old master branch
git branch -D master
# Rename the current branch to master
git branch -m master
# Force push to the remote repository
git push -f origin master
After executing these steps, your repository will retain only a single fresh commit. It feels as refreshing as emptying the recycle bin! However, please proceed with caution.
How to Modify the Latest Commit?
Often, after making a commit, you may realize that some details need
correction. Fortunately, git
provides a convenient way to
update the latest commit without adding a new commit entry.
Steps:
git add . # Add changes
git commit --amend --no-edit # Amend commit without changing the message
⚠️ Note: If this commit has already been pushed to a
remote repository, using --amend
will require a force
push (git push --force
), which could impact
collaboration. Proceed with caution.
If you also want to modify the commit message, simply omit the
--no-edit
option:
git commit --amend
This will open the default text editor, allowing you to edit the commit message.
How to Reapply Your Commits After Significant Upstream Changes?
When contributing to open-source projects, you may encounter situations where the upstream repository has undergone significant changes, leaving your fork outdated. If your commits have not yet been pushed to a remote repository, instead of dealing with complex merge conflicts, you can simply reapply your commits on top of the latest upstream version.
Steps:
⚠️
Before proceeding, make a note of the commit hash you want to keep!
If you forget, you can retrieve it using
git reflog
.
# Ensure you are on the branch where you want to retain commits
git checkout your-feature-branch
# Fetch the latest changes from upstream and reset your branch
# The upstream here is a remote we set up ourselves, and it can be replaced with any remote.
# Here, we assume that we want to update to the upstream master branch, but it can actually be any branch.
git fetch upstream
git reset --hard upstream/master
# Reapply your previous commit using its hash
git cherry-pick <your-modified-commit-hash>
# Force push the changes to your remote repository
git push --force
This method allows your commit to be neatly placed on top of the latest upstream commit without introducing unnecessary merge conflicts.
What to Do When You Need a Shared Repo?
One of the main use cases of git
is collaborating with
others on coding projects. People often rely on existing online
services, but what if we want to create our own shared repo? In
git
, a bare repo is a repository without a working
directory, typically used as a shared remote repo. For example, when a
team needs a central repository to synchronize their changes, they can
set up a bare repo to serve as the remote repo.
Steps:
# Create a bare repository
git init --bare my_project.git
After execution, the my_project.git
directory will
contain HEAD
, objects/
, refs/
,
and other git
-related files, but it will not have an
actual working directory, meaning code cannot be edited directly.
Using it is straightforward—just treat it as a remote repo, and
developers can interact with it using git clone
or
git push
. For example:
# Push a local repo to the bare repository
git remote add origin /path/to/my_project.git
git push -u origin master
Since a bare repo lacks a working directory, you cannot directly
perform operations like git commit
or
git checkout
within it. This is why it is best suited as
a remote repo rather than for daily development.
In team collaborations or self-hosted git
servers, bare
repos are a common architecture choice, enabling development teams to
share code and manage version control more efficiently.
I hope these git
techniques help you manage version
control more efficiently! In git
, there are often
multiple ways to achieve the same goal, and different situations may
call for different approaches. By applying these techniques flexibly,
understanding the underlying principles, and thinking critically, you
can truly harness the power of git
and make version
control more efficient and seamless! (^u^)