Jump to content

Restoring deleted files in Git: Difference between revisions

From LemonWiki共筆
Created page with "= 復原 GIT 誤刪除的檔案 = == 復原方法 == === 方法一:透過 Fork 右鍵選單 === 使用 [https://git-fork.com/ Fork Git 客戶端軟體],並且對 <code>Deleted.file</code> 右鍵選擇了 '''Reset File to'''。 # 右鍵點擊被刪除的檔案 # 選擇 '''Reset File to''' → <code>State at Commit...</code> 或 <code>State Before Commit...</code> #* <code>State at Commit...</code> → 還原到某個特定 commit 的狀態 #* <code>State Before Co..."
Tag: wikieditor
 
mNo edit summary
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
= 復原 GIT 誤刪除的檔案 =
= Restoring Deleted Files in Git =


== 復原方法 ==
{{LanguageSwitcher | content = [[Restoring deleted files in Git | EN]], [[Restoring deleted files in Git in Mandarin | 漢字]] }}


=== 方法一:透過 Fork 右鍵選單 ===
== Recovery Methods ==


使用 [https://git-fork.com/ Fork Git 客戶端軟體],並且對 <code>Deleted.file</code> 右鍵選擇了 '''Reset File to'''。
=== Method 1: Use the Fork Context Menu ===


# 右鍵點擊被刪除的檔案
In the [https://git-fork.com/ Fork Git client], find the commit that deleted the file.
# 選擇 '''Reset File to''' → <code>State at Commit...</code> 或 <code>State Before Commit...</code>
#* <code>State at Commit...</code> → 還原到某個特定 commit 的狀態
#* <code>State Before Commit...</code> → 還原到該 commit 之前的狀態


> '''建議:''' 直接用選單,點 <code>State Before Commit...</code> 即可快速還原到刪除前的狀態。
# Right-click the deleted file <code>Deleted.file</code>.
# Select '''Reset File to''', then choose the option that matches the commit you selected.
#* <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> restores the file as it was before the selected commit. Use this option when you select the commit that deleted the file.


=== 方法二:命令列 ===
=== Method 2: Use the 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.
 
==== 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>:


# 從最新 commit 還原
<pre lang="bash">
<pre lang="bash">
git checkout HEAD -- sub_folder/Deleted.file
git restore --source=HEAD -- 'sub_folder/Deleted.file'
</pre>
</pre>


# 或從特定 commit 還原(用 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">
<pre lang="bash">
git checkout <commit_hash> -- sub_folder/Deleted.file
git restore --source='<commit_hash>' -- 'sub_folder/Deleted.file'
</pre>
</pre>


=== 方法三:從 Local Changes 還原 ===
==== You only know the commit that deleted the file ====


如果檔案還在 '''Local Changes''' 裡顯示為已刪除:
If the deletion commit has one parent, append <code>^</code> to its hash to restore the file from the parent commit:


# 點左側 '''Local Changes'''
<pre lang="bash">
# 找到該檔案
git restore --source='<commit_hash>^' -- 'sub_folder/Deleted.file'
# 右鍵 → '''Discard Changes'''
</pre>


== 常見問題 ==
If the deletion occurred in a merge commit, <code>^</code> selects the first parent. Check which parent contains the version you want to restore.


=== 很久前刪除的檔案,無法從 Fork 快速找到刪除檔案的哪一筆紀錄 commit hash ===
==== Verify the result and stage the file if needed ====


如果還記得檔案名稱(大小寫要一致,但不清楚放在哪一個目錄):
The <code>git restore --source</code> commands above write the file to the working tree. Review the file contents and check its Git status:


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


<code>**</code> 與 <code>*</code> 符號說明:
To include the restored file in your next commit, stage it:
# <code>**</code> 匹配任意層數目錄(包含零層)
# <code>*</code> 只匹配單一層目錄或檔名中的任意字元


不確定路徑深度時建議用 <code>**</code>。
<pre lang="bash">
git add -- 'sub_folder/Deleted.file'
</pre>


如果不確定檔名大小寫,用 <code>grep -i</code> 做大小寫不敏感的搜尋:
==== Use an older version of Git ====
 
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 --name-only --format="" | grep -i "deleted.file"
git checkout HEAD -- 'sub_folder/Deleted.file'
git checkout '<commit_hash>' -- 'sub_folder/Deleted.file'
</pre>
</pre>


出現 N 次,代表這個檔案在 GIT 歷史中被修改過 N 次,有很多版本可以還原。找到正確路徑後,再用完整正確路徑去還原。
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.
 
=== Method 3: Restore from Local Changes in Fork ===
 
If Fork still lists the file as deleted under '''Local Changes''':


找到要復原的 commit hash:
# Select '''Local Changes''' in the sidebar.
# Find the deleted file.
# Right-click the file and select '''Discard Changes'''.
 
== 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">
git -c core.quotePath=false log --all --full-history --name-status -- ':(glob)**/Deleted.file'
</pre>
 
<code>:(glob)</code> enables glob matching. <code>**/</code> matches zero or more directory levels, while <code>*</code> matches characters within a single path component.
 
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>


=== 為什麼 <code>git show HEAD --name-only | grep Deleted.file</code> 沒有結果? ===
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.”
 
=== Why can't I find the file with <code>git show HEAD --name-only</code>? ===


<code>git show HEAD --name-only</code> 只會列出'''最新那一筆 commit 有變動的檔案''',不是所有檔案,所以沒出現不代表不存在。
<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.


可能原因:
=== How do I check where the file exists? ===
* 這個檔案很久沒被修改,最近的 commit 根本沒動到它
* 檔案已經被刪除了
* 路徑不對


=== 先確認檔案存在位置 ===
Check for the file in the working tree:
 
<pre lang="bash">
find . -type f -name 'Deleted.file'
</pre>


看它現在存不存在於 working tree:
Check whether the current <code>HEAD</code> snapshot contains the path:


<pre lang="bash">
<pre lang="bash">
find . -name "Deleted.file"
git -c core.quotePath=false ls-tree -r --name-only HEAD -- 'sub_folder/Deleted.file'
</pre>
</pre>


看目前 HEAD 裡有沒有這個檔案(不管有沒有被修改):
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">
<pre lang="bash">
git ls-files | grep Deleted.file
git --no-pager -c core.quotePath=false show --name-only --format= '<commit_hash>'
</pre>
</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.


* [https://git-scm.com/docs/git-restore Git 官方文件 - git-restore]
== References ==
* [https://git-scm.com/docs/git-log Git 官方文件 - git-log]
* [https://www.git-tower.com/learn/git/faq/restoring-deleted-files How to Restore a Deleted File in Git - git-tower]
* [https://rewind.com/blog/recovering-deleted-files-in-github/ Recovering Deleted Files in GitHub - Rewind]
* [https://www.smashingmagazine.com/2023/12/recovering-deleted-files-git-working-tree/ Recovering Deleted Files From Your Git Working Tree - Smashing Magazine]
* [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]


* [https://git-scm.com/docs/git-restore Git documentation for git-restore]
* [https://git-scm.com/docs/git-log Git documentation for git-log]
* [https://git-scm.com/docs/git-ls-tree Git documentation for git-ls-tree]
* [https://www.git-tower.com/learn/git/faq/restoring-deleted-files How to Restore a Deleted File in Git – Tower]
* [https://rewind.com/blog/recovering-deleted-files-in-github/ Recovering Deleted Files in GitHub – Rewind]
* [https://www.smashingmagazine.com/2023/12/recovering-deleted-files-git-working-tree/ Recovering Deleted Files From Your Git Working Tree – Smashing Magazine]
* [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]]

Latest revision as of 16:05, 10 November 2026

Restoring Deleted Files in Git[edit]

🌐 Switch language: EN, 漢字


Recovery Methods[edit]

Method 1: Use the Fork Context Menu[edit]

In the Fork Git client, find the commit that deleted the file.

  1. Right-click the deleted file Deleted.file.
  2. Select Reset File to, then choose the option that matches the commit you selected.
    • State at Commit... restores the version of the file from the selected commit. Choose a commit in which the file still existed.
    • State Before Commit... restores the file as it was before the selected commit. Use this option when you select the commit that deleted the file.

Method 2: Use the Command Line[edit]

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.

The file still exists in HEAD[edit]

If you deleted the file locally and it still exists in HEAD, restore it directly from HEAD:

git restore --source=HEAD -- 'sub_folder/Deleted.file'

You know a commit in which the file still existed[edit]

Replace <commit_hash> with the hash of a commit that contains the file. For example, you can use the commit that originally added the file:

git restore --source='<commit_hash>' -- 'sub_folder/Deleted.file'

You only know the commit that deleted the file[edit]

If the deletion commit has one parent, append ^ to its hash to restore the file from the parent commit:

git restore --source='<commit_hash>^' -- 'sub_folder/Deleted.file'

If the deletion occurred in a merge commit, ^ selects the first parent. Check which parent contains the version you want to restore.

Verify the result and stage the file if needed[edit]

The git restore --source commands above write the file to the working tree. Review the file contents and check its Git status:

git status --short -- 'sub_folder/Deleted.file'

To include the restored file in your next commit, stage it:

git add -- 'sub_folder/Deleted.file'

Use an older version of Git[edit]

If your version of Git predates git restore, use git checkout with a source commit and a file path. This form updates both the working tree and the staging area:

git checkout HEAD -- 'sub_folder/Deleted.file'
git checkout '<commit_hash>' -- 'sub_folder/Deleted.file'

Run the command that matches your source. For the second command, replace <commit_hash> with the hash of a commit that contains the file.

Method 3: Restore from Local Changes in Fork[edit]

If Fork still lists the file as deleted under Local Changes:

  1. Select Local Changes in the sidebar.
  2. Find the deleted file.
  3. Right-click the file and select Discard Changes.

Frequently Asked Questions[edit]

How do I find the commit for a file deleted a long time ago?[edit]

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:

git -c core.quotePath=false log --all --full-history --name-status -- ':(glob)**/Deleted.file'

:(glob) enables glob matching. **/ matches zero or more directory levels, while * matches characters within a single path component.

If you are unsure about capitalization, add icase:

git -c core.quotePath=false log --all --full-history --name-status -- ':(glob,icase)**/deleted.file'

In the output, A means added, M means modified, and D 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.”

Why can't I find the file with git show HEAD --name-only?[edit]

git show HEAD --name-only lists paths changed by the HEAD commit. A file can still be present in HEAD even if that commit did not change it.

How do I check where the file exists?[edit]

Check for the file in the working tree:

find . -type f -name 'Deleted.file'

Check whether the current HEAD snapshot contains the path:

git -c core.quotePath=false ls-tree -r --name-only HEAD -- 'sub_folder/Deleted.file'

You can replace HEAD with the hash of any commit you want to check.

Why do Chinese filenames appear as backslashes and numbers?[edit]

Git may display Chinese filenames using escape sequences. Set core.quotePath=false for a single command to see the actual filenames:

git --no-pager -c core.quotePath=false show --name-only --format= '<commit_hash>'

Use the actual filename in the restore command. To check whether a path exists in the commit's snapshot, use git ls-tree as shown in the previous section.

References[edit]