Hello! Welcome back to our module on version control with Git.
In our last lesson, you learned how to navigate one of the most common hurdles in collaborative development: resolving merge conflicts. You saw how Git marks conflicting changes and how to manually resolve them to successfully merge branches.
Today, we'll shift our focus from combining changes to undoing them. Mistakes happen, requirements change, and sometimes you just need to go back. This lesson will equip you with two essential tools for safely managing and reversing changes in your repository.
This lesson is dedicated to the learning outcome: Discard local, uncommitted changes using git checkout and safely reverse published commits using git revert. We will explore:
- How to discard modifications in your working directory before you've even committed them.
- The safe, professional way to undo a commit that has already been shared with others, without rewriting project history.
1. Undoing Before You Commit: Discarding Local Changes
Imagine you're working on a file, you've made some experimental changes, and you realize they're not going in the right direction. The changes are not yet staged (git add) or committed. You simply want to throw them away and go back to the version that's in the last commit. This is a very common scenario.
The command for this is git checkout. While we've used git checkout before to switch branches, it has another powerful function when used with a file path.
The syntax is:git checkout -- <file_path>
The -- is important. It's a standard convention in command-line tools to separate command options from arguments (like file paths). It explicitly tells Git that what follows is a file path, not a branch name, preventing any ambiguity.
Let's see this in action.
DevOps | Git Revert, Reset, Checkout | git tutorial for beginners | Git Undo Changes
This short video from Java Home Cloud provides a clear, practical demonstration of using git checkout to discard changes in your working directory.
Watch from 00:54 to 03:24. Pay attention to how git status reflects the changes before the checkout, and how the working tree becomes clean afterward. The video shows how to discard changes for a single file and for all modified files using ..
Hands-on Practice
Let's try this yourself. In a practice repository:
- Open a file that is already tracked by Git.
- Add a few lines of text and save the file.
- Run
git status. You'll see the file listed under "Changes not staged for commit". - Now, discard those changes by running:
git checkout -- <your_file_name>. - Run
git statusagain. It should report that your working tree is clean. If you open the file, you'll see your recent changes are gone.
A Note on Modern Git: git restore
In recent versions of Git (2.23+), a new command, git restore, was introduced to make these actions more explicit. The git checkout command does many different things (switch branches, restore files), which can be confusing. git restore is designed specifically for undoing changes in the working directory.
To do the same thing we did above, you would use:git restore <file_path>
While the learning outcome focuses on checkout—a command you must know as it's ubiquitous in older tutorials and codebases—it's good practice to start using git restore for this task. It's clearer and less prone to mistakes. The article "A Comprehensive Guide to Undoing Changes In Git" from Initial Commit provides a quick reference for this. It notes that you can discard all local changes with git restore . or unstage a file with git restore --staged <file>.
2. Undoing After You Commit: Safely Reversing Public Commits
Now for a more complex scenario. What if you've already committed your changes? And worse, what if you've already pushed them to a shared remote repository like GitHub?
You cannot simply delete the commit. That would rewrite the project's history. If a teammate has already pulled your changes and started building their own work on top of it, deleting the commit from the history would cause massive problems and conflicts for them. This is the cardinal rule of Git collaboration: do not rewrite public history.
So, how do you undo a bad commit that's already public? You revert it.
The git revert command is the safe, non-destructive way to undo a commit. It works by creating a brand new commit that does the exact opposite of the commit you want to undo.
- If the original commit added a line, the revert commit will remove that line.
- If the original commit removed a file, the revert commit will add that file back.
The original, problematic commit remains in the project history, but its effects are canceled out by the new revert commit. This keeps the history intact and transparent.
Resetting, Checking Out & Reverting
The Atlassian Git Tutorial provides an excellent, concise explanation of why revert is the safe choice for public branches. Please read the section on undoing public commits.
In the article, find the section titled "Undo public commits with revert". Read this section carefully to understand why revert is considered safe and how it contrasts with reset (which we will cover later).
To use it, you need the hash of the commit you want to revert. You can find this using git log.
The syntax is:git revert <commit_hash>
Let's watch a demonstration.
Beginner Git and GitHub #5 - Undo Changes (checkout, revert, reset)
This video segment from Becoming a Data Scientist clearly demonstrates the revert process. Notice how the original commit remains in the log, and a new 'Revert' commit appears at the top.
Watch from 02:30 to 05:55. The presenter does a great job of showing the state of the files before and after the revert, and how the git log reflects the new commit that undoes the previous one.
When you run git revert, Git will open your configured text editor to let you write a commit message for the new revert commit. The default message is usually sufficient (e.g., "Revert 'Add feature X'"). After you save and close the editor, the new commit is created.
Test your understanding!
You just pushed a commit to the main branch that accidentally introduced a serious bug. Your team lead tells you to "undo it safely." Which command should you use, and what will its effect be on the project's history?
Show answer
You should use git revert <commit_hash>. This will create a new commit that reverses the changes from the buggy commit. The original buggy commit will remain in the history, but the new revert commit will cancel out its effects, preserving a clean and accurate record of the project's timeline. This is safe for a shared branch like main.
Summary: checkout vs. revert
It's crucial to understand the difference between these two ways of undoing things. The Atlassian article you read earlier contains a handy table summarizing the use cases.
| Action | Command | Stage of Change | Impact |
|---|---|---|---|
| Discard local, uncommitted changes | git checkout -- <file> |
Working Directory | Destructive to local work, but doesn't affect project history. |
| Undo a published commit | git revert <commit> |
Commit History | Non-destructive to history. Creates a new commit. Safe for shared branches. |
As a DevOps professional, knowing when to use a history-preserving command like revert versus a history-altering command (which you'll learn about next) is fundamental to maintaining a healthy and reliable version control workflow for your team.
Conclusion
In this lesson, you've learned two distinct but equally important methods for undoing work in Git.
Key Takeaways:
- To discard local, uncommitted changes in a file, use
git checkout -- <file>(or the more moderngit restore <file>). This reverts the file to its state at the last commit. - To safely undo a commit that has been shared or published, use
git revert <commit_hash>. git revertdoes not delete or change history; it creates a new commit that applies inverse changes, making it the standard and safe method for reversing changes on collaborative branches.
In our next lesson, we will explore a powerful, but more advanced, way to undo changes: git reset. Unlike revert, reset actually rewrites commit history, making it incredibly useful for cleaning up your local, un-pushed commits, but dangerous to use on shared branches. Understanding the difference between revert and reset is a key step toward Git mastery.