update - git教學




在Git存儲庫中查找並恢復已刪除的文件 (14)

說我在Git存儲庫中。 我刪除了一個文件並提交了更改。 我繼續工作,並做了一些更多的提交。 然後,我發現我需要恢復該文件。

我知道我可以使用git checkout HEAD^ foo.bar簽出文件,但我真的不知道該文件何時被刪除。

  1. 找到刪除給定文件名的提交的最快方法是什麼?
  2. 將該文件恢復到我的工作副本的最簡單方法是什麼?

我希望我不必手動瀏覽我的日誌,檢查整個項目的給定SHA,然後手動將該文件複製到我的原始項目結帳中。


git undelete path/to/file.ext

  1. 將它放在.bash_profile (或打開命令shell時加載的其他相關文件)中:

    git config --global alias.undelete '!sh -c "git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1" -'
    
  2. 然後使用:

    git undelete path/to/file.ext
    

此別名首先檢查以查找此文件存在的最後一次提交,然後從該文件存在的最後一次提交執行該文件路徑的git檢出。 source


  1. 使用git log --diff-filter=D --summary來獲取已刪除文件和刪除文件的所有提交;
  2. 使用git checkout $commit~1 filename恢復已刪除的文件。

其中$commit是您在步驟1中找到的提交值,例如e4cf499627


在許多情況下,將coreutils (grep,sed等)與Git結合使用會很有用。 我已經非常了解這些工具了,但是Git不那麼了。 如果我想搜索已刪除的文件,我會執行以下操作:

git log --raw | grep -B 30 $'D\t.*deleted_file.c'

當我找到修訂/提交時:

git checkout <rev>^ -- path/to/refound/deleted_file.c

就像其他人在我面前所說的那樣。

該文件現在將恢復到刪除之前的狀態。 如果要保留它,請記住將其重新提交到工作樹。


如果你瘋了,請使用git-bisect 。 這是做什麼的:

git bisect start
git bisect bad
git bisect good <some commit where you know the file existed>

現在是時候運行自動化測試了。 如果存在foo.bar ,則shell命令'[ -e foo.bar ]'將返回0,否則返回1。 git-bisect的“run”命令將使用二進制搜索自動查找測試失敗的第一個提交。 它從給定範圍的中間開始(從好到壞),並根據指定測試的結果將其減半。

git bisect run '[ -e foo.bar ]'

現在你正處於刪除它的提交中。 從這裡開始,您可以跳回到未來並使用git-revert撤消更改,

git bisect reset
git revert <the offending commit>

或者您可以返回一個提交並手動檢查損壞:

git checkout HEAD^
cp foo.bar /tmp
git bisect reset
cp /tmp/foo.bar .

如果您知道刪除文件的提交,請運行此命令,其中<SHA1_deletion>是刪除文件的提交:

git diff --diff-filter=D --name-only <SHA1_deletion>~1 <SHA1_deletion> | xargs git checkout <SHA1_deletion>~1 --

管道前面的部分列出了提交中刪除的所有文件; 它們都是從上一次提交結賬以恢復它們。


如果您知道文件名,這是使用基本命令的簡單方法:

列出該文件的所有提交。

git log -- path/to/file

最後一次提交(最頂層)是刪除文件的提交。 所以你需要恢復倒數第二次提交。

git checkout {second to last commit} -- path/to/file

我最喜歡的別名,基於bonyiii的answer (upvoted),以及我自己的回答“ 將參數傳遞給Git alias命令 ”:

git config alias.restore '!f() { git checkout $(git rev-list -n 1 HEAD -- $1)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- $1)~1 | grep '^D' | cut -f 2); }; f'

我丟失了一個文件,錯誤刪除了一些提交之前?
快:

git restore my_deleted_file

危機避免了。

Robert Dailey 在評論中提出以下別名:

restore-file = !git checkout $(git rev-list -n 1 HEAD -- "$1")^ -- "$1"

而jegan 在評論中補充道:

為了從命令行設置別名,我使用了以下命令:

git config --global alias.restore "\!git checkout \$(git rev-list -n 1 HEAD -- \"\$1\")^ -- \"\$1\"" 

我有這個解決方案

  1. 使用以下方法之一獲取文件被刪除的提交的ID。

    • git log --grep=*word*
    • git log -Sword
    • git log | grep --context=5 *word*
    • git log --stat | grep --context=5 *word* git log --stat | grep --context=5 *word* #推薦,如果你幾乎記不起來的話
  2. 你應該得到類似的東西:

提交bfe68bd117e1091c96d2976c99b3bcc8310bebe7作者:Alexander Orlov日期:2011年5月12日星期四23:44:27 +0200

replaced deprecated GWT class
- gwtI18nKeySync.sh, an outdated (?, replaced by a Maven goal) I18n generation script

commit 3ea4e3af253ac6fd1691ff6bb89c964f54802302作者:Alexander Orlov日期:2011年5月12日22:10:22 +0200

3 。 現在使用提交ID bfe68bd117e1091c96d2976c99b3bcc8310bebe7做:

git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java

由於提交id引用了已經刪除文件的提交,因此您需要在bfe68b之前引用提交,您可以通過附加^1來執行提交。 這意味著:在bfe68b之前給我提交。


所以我不得不從特定的提交中恢復一堆已刪除的文件,並使用兩個命令進行管理:

git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git checkout <rev>^ -- 
git show <rev> --diff-filter=D --summary --name-only --no-commit-id | xargs git reset HEAD 

(注意每個命令末尾的尾隨空格。)

這些文件已經添加到.gitignore文件中,然後用git rm清除,我需要恢復文件,然後取消它們。 我有幾百個要恢復的文件,為每個文件手動輸入內容,因為在其他示例中這將太慢。


查找影響給定路徑的最後一次提交。 由於該文件不在HEAD提交中,因此該提交必須已將其刪除。

git rev-list -n 1 HEAD -- <file_path>

然後使用插入符號( ^ )符號檢查之前提交的版本:

git checkout <deleting_commit>^ -- <file_path>

或者在一個命令中,如果$file是有問題的文件。

git checkout $(git rev-list -n 1 HEAD -- "$file")^ -- "$file"

如果您使用zsh並啟用了EXTENDED_GLOB選項,則插入符號將不起作用。 您可以使用~1代替。

git checkout $(git rev-list -n 1 HEAD -- "$file")~1 -- "$file"

要還原已刪除和已提交的文件:

git reset HEAD some/path
git checkout -- some/path

它在Git 1.7.5.4版本上進行了測試。


要還原文件夾中的所有已刪除文件,請輸入以下命令。

git ls-files -d | xargs git checkout --

git checkout /path/to/deleted.file





git-checkout