Rollback to an old Git commit in a public repo

Learn rollback to an old git commit in a public repo with practical examples, diagrams, and best practices. Covers git, git-checkout, git-revert development techniques with visual explanations.

How to Rollback to an Old Git Commit in a Public Repository

Hero image for Rollback to an old Git commit in a public repo

Learn safe and effective methods to revert changes in a public Git repository, focusing on git revert for maintaining history and git reset for local cleanups.

Rolling back changes in Git is a common task, but it requires careful consideration, especially when dealing with public repositories. Unlike local repositories where you might freely rewrite history, public repositories demand a different approach to avoid disrupting collaborators' work. This article will guide you through the safest and most recommended methods for reverting to an older commit in a public Git repository, primarily focusing on git revert.

Understanding the Impact of History Rewriting

In Git, every commit is a snapshot of your project at a specific point in time. When you push commits to a public repository, other developers may pull those changes and build their work on top of them. Rewriting history (e.g., using git reset --hard followed by a force push) can cause significant problems for collaborators, as their local histories will diverge from the remote, leading to complex merge conflicts and lost work. For this reason, rewriting history on shared branches is strongly discouraged.

flowchart TD
    A[Local Commit] --> B[Push to Public Repo]
    B --> C[Collaborator Pulls]
    C --> D[Collaborator Builds on C]
    D -- "History Rewritten (e.g., git reset)" --> E{Conflict!}
    E --> F[Collaborator's Work Disrupted]
    B -- "Safe Revert (git revert)" --> G[New Revert Commit]
    G --> H[Collaborator Pulls Revert]
    H --> I[History Preserved, Changes Undone]

Comparison of history rewriting vs. safe revert in a public repository.

The Safe Approach: git revert

The git revert command is the recommended way to undo changes in a public repository. Instead of deleting commits from history, git revert creates a new commit that undoes the changes introduced by one or more previous commits. This preserves the project's history, making it safe for shared branches and public repositories.

1. Identify the Commit to Revert

First, you need to find the hash of the commit you want to undo. You can use git log to view your commit history. For example, if you want to revert the commit where a bug was introduced.

2. Perform the Revert

Once you have the commit hash (e.g., abcdef1), execute the git revert command. Git will open your default editor to allow you to modify the commit message for the new revert commit. It's good practice to keep the default message, which clearly states what commit is being reverted.

3. Push the Revert Commit

After saving the commit message, Git creates the new revert commit locally. You then need to push this commit to your public repository. This makes the undo operation visible to all collaborators without rewriting history.

# 1. View commit history to find the commit hash
git log --oneline

# Example output:
# abcdef1 (HEAD -> main) Add new feature X
# 1234567 Fix bug in feature Y
# fedcba9 Initial commit

# 2. Revert the commit (e.g., commit 'abcdef1')
git revert abcdef1

# Git will open an editor for the commit message. Save and close it.

# 3. Push the new revert commit to the remote repository
git push origin main

Using git revert to undo a specific commit.

Reverting Multiple Commits

You can also revert a range of commits. When reverting a range, Git applies the reverts in reverse order of how they appear in history. For example, git revert HEAD~3..HEAD would revert the last three commits, starting from the most recent and working backwards. This ensures that dependencies between commits are handled correctly.

# Revert the last three commits (HEAD, HEAD~1, HEAD~2)
git revert HEAD~3..HEAD

# Git will prompt you for a commit message for each revert commit.
# Alternatively, to combine them into a single revert commit:
git revert -n HEAD~3..HEAD
git commit -m "Revert last three commits: Feature X, Bug Fix Y, Refactor Z"

Reverting a range of commits, with and without combining into a single revert commit.

When git reset is Acceptable (Locally)

While git reset is generally discouraged for public repositories, it's perfectly fine and often preferred for cleaning up your local history before pushing. If you've made a mistake in a commit that hasn't been pushed yet, git reset allows you to move your branch pointer to an earlier commit, effectively discarding subsequent commits or moving their changes to your staging area or working directory.

# Move HEAD and branch pointer back to the commit before the last one, 
# keeping changes in the staging area (index).
git reset --soft HEAD~1

# Move HEAD and branch pointer back, keeping changes in the working directory.
git reset --mixed HEAD~1

# Move HEAD and branch pointer back, discarding all changes.
# USE WITH EXTREME CAUTION - data loss can occur.
git reset --hard HEAD~1

Different modes of git reset for local history manipulation.