Git Restore File To Previous Commit

8 min read

How to Restore a File to a Previous Commit in Git

When working with Git, it’s common to realize that a file you modified should look exactly as it did in an earlier commit. Even so, whether you accidentally overwrote important code, need to compare changes, or simply want to roll back a single file without affecting the rest of the repository, knowing how to git restore file to previous commit is an essential skill. This guide walks you through the concepts behind Git’s history model, shows several reliable methods, and provides practical examples so you can choose the approach that best fits your workflow.

And yeah — that's actually more nuanced than it sounds.

Understanding Git’s History Model

Git stores snapshots of your entire project at each commit, not just the differences (deltas) between files. Also, every commit points to a tree object that contains references to the exact state of each tracked file at that moment. Because of this design, retrieving a previous version of a file is essentially a matter of pointing your working directory (or index) at the blob stored in a specific commit.

Key concepts to keep in mind:

  • Working tree – the files you see and edit on disk.
  • Index (staging area) – a snapshot of what will be included in the next commit.
  • HEAD – a symbolic reference to the current commit (usually the tip of the branch).
  • Commit hash – the 40‑character SHA‑1 (or shorter) identifier that uniquely names a commit.

When you want to restore a file to a previous commit, you are asking Git to copy the blob from that commit’s tree into either your working tree, your index, or both, depending on the command you use And it works..

Modern Approach: git restore

Introduced in Git 2.23, git restore is designed specifically for undoing changes in the working tree and the index. It separates the concerns of restoring files from resetting branches, making the intent clearer and reducing the chance of accidental history rewrites.

This is where a lot of people lose the thread.

Restoring a File to the State in a Specific Commit

git restore --source  -- 
  • --source <commit> tells Git which commit to read the file from. You can use a full hash, a short hash, a branch name, a tag, or a relative reference like HEAD~2.
  • -- <path-to-file> separates the options from the file path; it is required when the path could be mistaken for a branch name (e.g., a file named main).
  • Omitting --staged or --worktree defaults to restoring the file in the working tree only, leaving the index untouched.

Example: Restore src/utils.js to how it looked three commits ago Took long enough..

git restore --source HEAD~3 -- src/utils.js

After running this command, git status will show src/utils.js as modified (if the current version differs) and ready to be staged Surprisingly effective..

Restoring a File to the Index (Staging Area)

If you want the file to appear exactly as it was in the old commit and be ready for commit, add the --staged flag:

git restore --source  --staged -- 

This updates the index but leaves your working tree unchanged. Useful when you have already made other edits you want to keep but need to swap in a previous version for the upcoming commit Which is the point..

Restoring Both Working Tree and Index

To make the file match the old commit in both places, combine the flags:

git restore --source  --worktree --staged -- 

Or simply omit --worktree and --staged and run the command twice—once for each area—but the combined form is more explicit.

Classic Approach: git checkout

Before git restore, the go‑to command for retrieving an old file version was git checkout. It still works and is familiar to many developers, but it overloads the term “checkout” (which also switches branches), so use it with caution That's the part that actually makes a difference..

Checking Out a File from a Commit

git checkout  -- 
  • The double dash (--) separates the commit reference from the file path, preventing ambiguity.
  • This updates the working tree only; the index stays as it was.

Example: Retrieve README.md from the commit with hash a1b2c3d No workaround needed..

git checkout a1b2c3d -- README.md

Checking Out a File and Staging It

If you also want the index to reflect the old version, you can follow the checkout with git add:

git checkout  -- 
git add 

Or, in newer Git versions, you can use the --patch mode to interactively choose hunks, but for a full file restore the two‑step process is simplest Worth keeping that in mind..

Using git reset for File‑Level Restoration

git reset primarily moves the HEAD pointer and can alter the index and working tree depending on the mode (--soft, --mixed, --hard). While it’s often used to undo commits, you can also take advantage of it to restore a single file by resetting the index to a previous commit and then checking out the file The details matter here..

Reset Index to a Commit, Then Checkout the File

git reset  -- 
git checkout HEAD -- 
  • The first line copies the file from <commit> into the index (because -- limits the reset to paths).
  • The second line updates the working tree to match the index.

This method is equivalent to git restore --source <commit> --staged -- <path-to-file> followed by git restore --source HEAD -- <path-to-file>, but it shows the underlying mechanics.

When to Use git revert Instead

If your goal is to record a new commit that undoes the changes introduced by a specific earlier commit (rather than silently overwriting the file), git revert is the safer choice, especially in shared branches.

git revert  --no-edit
  • This creates a new commit that inverses the effect of <commit> across all files it touched.
  • If you only want to revert a single file from that commit, you can revert the whole commit and then reset the other files back, or simply use git restore as described above.

Practical Workflow Examples

Below are common scenarios and the exact commands you would run.

Scenario 1: Accidentally Overwrote a Configuration File

You edited config/production.yml and realized the previous version was correct And that's really what it comes down to. That's the whole idea..

# Look at recent commits to find the good version
git log -p -- config/production.yml   # shows diffs; note the commit hash

# Restore the file to that commit (working tree only)
git restore --source  --

### Restoring the Desired Version  

The command you started to type actually needs the path after the source option. The complete one‑liner looks like this:

```bash
git restore --source  -- config/production.yml

Running it copies the file from <good-commit> into both the index and the working tree, so the file is now exactly as it was in the earlier commit. If you only want the working tree to reflect the old version, you can keep the two‑step approach (git checkout followed by git add), but git restore with --source is the most concise method in modern Git And that's really what it comes down to. Which is the point..


Scenario 2 – Recovering a Deleted File

Imagine you accidentally removed src/legacy.py and have no backup other than an older commit where it still existed It's one of those things that adds up..

  1. Identify the commit that still contains the file

    git log --all --full-history -- src/legacy.py
    

    Note the hash of the commit where the file is present.

  2. Restore the file (both index and working tree)

    git restore --source  -- src/legacy.py
    

    This brings the file back into the repository as it was at <old-commit>.

  3. Stage the restored file if needed

    git add src/legacy.py
    

    Now the file is ready for a new commit, or you can simply leave it unstaged if you just need the code back.

If you prefer the classic checkout style, the equivalent steps are:

git checkout  -- src/legacy.py
git add src/legacy.py

Scenario 3 – Undoing a Recent Merge While Keeping One Side

Sometimes a merge introduces unwanted changes, but you want to keep the work from one of the parents. You can achieve this without a full revert by resetting the merge commit’s parent and then cherry‑picking the desired changes Easy to understand, harder to ignore. Surprisingly effective..

# Reset the branch to the first parent of the merge (discard the merge)
git reset --hard HEAD~1

# Cherry‑pick the specific commit that introduced the needed changes
git cherry-pick 

This sequence discards the merge’s combined history while preserving the individual commit you need, giving you a clean history with the desired changes.


Best Practices & Quick Reference

Goal Recommended Command(s) When to Use
Restore a single file from a past commit (working tree only) git checkout <commit> -- <path> Quick, temporary fixes; you don’t need the index to change. Think about it:
Restore a file and stage it git checkout <commit> -- <path><br>git add <path> You want the old version to be part of the next commit. In practice,
Restore a file using modern git restore git restore --source <commit> -- <path> When you have Git ≥ 2. 23 and want a single‑line solution.

This is where a lot of people lose the thread.

Just Dropped

Just Posted

If You're Into This

What Others Read After This

Thank you for reading about Git Restore File To Previous Commit. We hope the information has been useful. Feel free to contact us if you have any questions. See you next time — don't forget to bookmark!
⌂ Back to Home