Restoring deleted files in Git: Difference between revisions

No edit summary
Tag: wikieditor
mNo edit summary
 
Line 1: Line 1:
= Recovering GIT Accidentally Deleted Files =
= Restoring Deleted Files in Git =


{{LanguageSwitcher | content = [[Restoring deleted files in Git | EN]], [[Restoring deleted files in Git in Mandarin | 漢字]] }}
{{LanguageSwitcher | content = [[Restoring deleted files in Git | EN]], [[Restoring deleted files in Git in Mandarin | 漢字]] }}
Line 5: Line 5:
== Recovery Methods ==
== Recovery Methods ==


=== Method 1: Via Fork Right-Click Menu ===
=== Method 1: Use the Fork Context Menu ===


Using [https://git-fork.com/ Fork Git client], right-click on <code>Deleted.file</code> and select '''Reset File to'''.
In the [https://git-fork.com/ Fork Git client], find the commit that deleted the file.


# Right-click the deleted file
# Right-click the deleted file <code>Deleted.file</code>.
# Select '''Reset File to''' → <code>State at Commit...</code> or <code>State Before Commit...</code>
# Select '''Reset File to''', then choose the option that matches the commit you selected.
* <code>State at Commit...</code> → Restore to the state at a specific commit
#* <code>State at Commit...</code> restores the version of the file from the selected commit. Choose a commit in which the file still existed.
* <code>State Before Commit...</code> → Restore to the state before that commit
#* <code>State Before Commit...</code> restores the file as it was before the selected commit. Use this option when you select the commit that deleted the file.


> '''Tip:''' Use the menu directly and click <code>State Before Commit...</code> to quickly restore the file to its state before deletion.
=== Method 2: Use the Command Line ===


=== Method 2: Command Line ===
Run these commands from the repository root. The file path must match the path in the source commit, including capitalization and directory structure. If you have uncommitted changes at the same path, back them up first because restoring the file will overwrite them.


> '''Note:''' The file path must match exactly (case-sensitive, directory levels must be consistent).
==== The file still exists in HEAD ====
 
If you deleted the file locally and it still exists in <code>HEAD</code>, restore it directly from <code>HEAD</code>:


# Restore from the latest commit:
<pre lang="bash">
<pre lang="bash">
git checkout HEAD -- sub_folder/Deleted.file
git restore --source=HEAD -- 'sub_folder/Deleted.file'
</pre>
</pre>


# Or restore from a specific commit (using commit hash):
==== You know a commit in which the file still existed ====
 
Replace <code>&lt;commit_hash&gt;</code> with the hash of a commit that contains the file. For example, you can use the commit that originally added the file:
 
<pre lang="bash">
git restore --source='<commit_hash>' -- 'sub_folder/Deleted.file'
</pre>
 
==== You only know the commit that deleted the file ====
 
If the deletion commit has one parent, append <code>^</code> to its hash to restore the file from the parent commit:
 
<pre lang="bash">
<pre lang="bash">
git checkout <commit_hash> -- sub_folder/Deleted.file
git restore --source='<commit_hash>^' -- 'sub_folder/Deleted.file'
</pre>
</pre>


=== Method 3: Restore from Local Changes ===
If the deletion occurred in a merge commit, <code>^</code> selects the first parent. Check which parent contains the version you want to restore.
 
==== Verify the result and stage the file if needed ====


If the file still appears as deleted in '''Local Changes''':
The <code>git restore --source</code> commands above write the file to the working tree. Review the file contents and check its Git status:


# Click '''Local Changes''' in the left panel
<pre lang="bash">
# Locate the file
git status --short -- 'sub_folder/Deleted.file'
# Right-click → '''Discard Changes'''
</pre>


== Frequently Asked Questions ==
To include the restored file in your next commit, stage it:
 
<pre lang="bash">
git add -- 'sub_folder/Deleted.file'
</pre>


=== A file was deleted long ago and I can't quickly find which commit hash deleted it in Fork ===
==== Use an older version of Git ====


If you remember the filename (case must match, but you're unsure which directory it's in):
If your version of Git predates <code>git restore</code>, use <code>git checkout</code> with a source commit and a file path. This form updates both the working tree and the staging area:


<pre lang="bash">
<pre lang="bash">
git log --all --full-history -- "**/Deleted.file"
git checkout HEAD -- 'sub_folder/Deleted.file'
git checkout '<commit_hash>' -- 'sub_folder/Deleted.file'
</pre>
</pre>


Explanation of <code>**</code> and <code>*</code> wildcards:
Run the command that matches your source. For the second command, replace <code>&lt;commit_hash&gt;</code> with the hash of a commit that contains the file.
# <code>**</code> matches any number of directory levels (including zero)
 
# <code>*</code> matches only a single directory level or any characters within a filename
=== Method 3: Restore from Local Changes in Fork ===
 
If Fork still lists the file as deleted under '''Local Changes''':


When unsure about path depth, use <code>**</code>.
# Select '''Local Changes''' in the sidebar.
# Find the deleted file.
# Right-click the file and select '''Discard Changes'''.


If you're unsure about the filename's case, use <code>grep -i</code> for case-insensitive search:
== Frequently Asked Questions ==
 
=== How do I find the commit for a file deleted a long time ago? ===
 
If you remember the filename but have forgotten its directory, search the history reachable from your local Git references. The following command lists matching commits, file paths, and change types:


<pre lang="bash">
<pre lang="bash">
git log --all --full-history --name-only --format="" | grep -i "deleted.file"
git -c core.quotePath=false log --all --full-history --name-status -- ':(glob)**/Deleted.file'
</pre>
</pre>


If the result appears N times, it means the file has been modified N times in Git history and has many versions to restore from. Once you find the correct path, use the full exact path to restore it.
<code>:(glob)</code> enables glob matching. <code>**/</code> matches zero or more directory levels, while <code>*</code> matches characters within a single path component.


To find the commit hash to restore from:
If you are unsure about capitalization, add <code>icase</code>:


<pre lang="bash">
<pre lang="bash">
git log --all --full-history -- "**/Deleted.file"
git -c core.quotePath=false log --all --full-history --name-status -- ':(glob,icase)**/deleted.file'
</pre>
</pre>


=== Why does <code>git show HEAD --name-only | grep Deleted.file</code> return no results? ===
In the output, <code>A</code> means added, <code>M</code> means modified, and <code>D</code> means deleted. Once you find the version you want, use the full path shown in the output. If you found a deletion entry, follow the steps under “You only know the commit that deleted the file.”


<code>git show HEAD --name-only</code> only lists '''files changed in the most recent commit''', not all files — so the file not appearing doesn't mean it doesn't exist.
=== Why can't I find the file with <code>git show HEAD --name-only</code>? ===


Possible reasons:
<code>git show HEAD --name-only</code> lists paths changed by the <code>HEAD</code> commit. A file can still be present in <code>HEAD</code> even if that commit did not change it.
* The file hasn't been modified recently and the latest commit didn't touch it
* The file has already been deleted
* The path is incorrect


=== First, confirm where the file exists ===
=== How do I check where the file exists? ===


Check whether it currently exists in the working tree:
Check for the file in the working tree:


<pre lang="bash">
<pre lang="bash">
find . -name "Deleted.file"
find . -type f -name 'Deleted.file'
</pre>
</pre>


Check whether the file exists in the current HEAD (regardless of whether it's been modified):
Check whether the current <code>HEAD</code> snapshot contains the path:


<pre lang="bash">
<pre lang="bash">
git ls-files | grep Deleted.file
git -c core.quotePath=false ls-tree -r --name-only HEAD -- 'sub_folder/Deleted.file'
</pre>
</pre>
You can replace <code>HEAD</code> with the hash of any commit you want to check.
=== Why do Chinese filenames appear as backslashes and numbers? ===
Git may display Chinese filenames using escape sequences. Set <code>core.quotePath=false</code> for a single command to see the actual filenames:
<pre lang="bash">
git --no-pager -c core.quotePath=false show --name-only --format= '<commit_hash>'
</pre>
Use the actual filename in the restore command. To check whether a path exists in the commit's snapshot, use <code>git ls-tree</code> as shown in the previous section.


== References ==
== References ==


* [https://git-scm.com/docs/git-restore Git Official Docs - git-restore]
* [https://git-scm.com/docs/git-restore Git documentation for git-restore]
* [https://git-scm.com/docs/git-log Git Official Docs - git-log]
* [https://git-scm.com/docs/git-log Git documentation for git-log]
* [https://www.git-tower.com/learn/git/faq/restoring-deleted-files How to Restore a Deleted File in Git - git-tower]
* [https://git-scm.com/docs/git-ls-tree Git documentation for git-ls-tree]
* [https://rewind.com/blog/recovering-deleted-files-in-github/ Recovering Deleted Files in GitHub - Rewind]
* [https://www.git-tower.com/learn/git/faq/restoring-deleted-files How to Restore a Deleted File in Git – Tower]
* [https://www.smashingmagazine.com/2023/12/recovering-deleted-files-git-working-tree/ Recovering Deleted Files From Your Git Working Tree - Smashing Magazine]
* [https://rewind.com/blog/recovering-deleted-files-in-github/ Recovering Deleted Files in GitHub – Rewind]
* [https://www.atlassian.com/git/tutorials/git-log Advanced Git Log - Atlassian]
* [https://www.smashingmagazine.com/2023/12/recovering-deleted-files-git-working-tree/ Recovering Deleted Files From Your Git Working Tree – Smashing Magazine]
* [https://github.blog/open-source/git/gits-database-internals-iii-file-history-queries/ Git's database internals III: file history queries - GitHub Blog]
* [https://www.atlassian.com/git/tutorials/git-log Advanced Git Log – Atlassian]
* [https://github.blog/open-source/git/gits-database-internals-iii-file-history-queries/ Git's Database Internals III: File History Queries – GitHub Blog]


[[Category: Git]]
[[Category: Git]]
[[Category: Revised with LLMs]]
[[Category: Revised with LLMs]]