Znajdź i przywróć usunięty plik w repozytorium Git

Powiedzmy, że jestem w repozytorium Git. Usuwam plik i zatwierdzam tę zmianę. Kontynuuję pracę i robię kolejne commity. Potem muszę przywrócić ten plik.

Wiem, że mogę pobrać plik za pomocą git checkout HEAD^ foo.bar, ale tak naprawdę Nie wiem, kiedy ten plik został usunięty.

  1. jak najszybciej znaleźć commit, który usunął daną nazwę pliku?
  2. Jaki byłby najprostszy sposób, aby dostać ten plik z powrotem do mojej kopii roboczej?

Mam nadzieję, że nie muszę ręcznie przeglądaj moje dzienniki, checkout cały projekt dla danego SHA, a następnie ręcznie skopiuj ten plik do mojego oryginalnego projektu checkout.

Author: 7ochem, 2009-06-05

19 answers

Znajdź ostatni commit, który wpłynął na podaną ścieżkę. Ponieważ plik nie znajduje się w zatwierdzeniu głównym, musi on zostać usunięty.

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

Następnie sprawdź wersję przed zatwierdzeniem, używając symbolu caret (^):

git checkout <deleting_commit>^ -- <file_path>

Lub jednym poleceniem, Jeśli $file jest danym plikiem.

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

Jeśli używasz zsh i masz włączoną opcję EXTENDED_GLOB, symbol karetki nie będzie działał. Możesz zamiast tego użyć ~1.

git checkout $(git rev-list -n 1 HEAD -- "$file")~1 -- "$file"
 2768
Author: CB Bailey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-03 17:11:57
  1. Użyj git log --diff-filter=D --summary, aby uzyskać wszystkie commity, które usunęły pliki i pliki usunięte;
  2. Użyj git checkout $commit~1 filename, aby przywrócić usunięty plik.

Gdzie $commit jest wartością commita znalezionego w kroku 1, np. e4cf499627

 736
Author: Robert Munteanu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-23 14:58:03

Aby przywrócić wszystkie usunięte pliki w folderze, wprowadź następujące polecenie.

git ls-files -d | xargs git checkout --
 306
Author: Manu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-20 21:49:17

Zadałem sobie to pytanie, chcąc przywrócić plik, który właśnie usunąłem, ale jeszcze nie wprowadziłem zmiany. Na wypadek, gdybyś znalazł się w tej sytuacji, wszystko, co musisz zrobić, to:

git checkout HEAD -- path/to/file.ext

 105
Author: Brett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-10 00:03:18

Jeśli jesteś szalony, użyj git-bisect. Oto co zrobić:

git bisect start
git bisect bad
git bisect good <some commit where you know the file existed>
Teraz czas na automatyczny test. Polecenie powłoki '[ -e foo.bar ]' zwróci 0, Jeśli foo.bar istnieje, a 1 w przeciwnym razie. Polecenie " run " git-bisect użyje wyszukiwania binarnego, aby automatycznie znaleźć pierwszy commit, w którym test się nie powiedzie. Rozpoczyna się w połowie danego zakresu (od dobrego do złego) i tnie go na pół na podstawie wyniku określonego testu.
git bisect run '[ -e foo.bar ]'

Teraz jesteś w commit, który go usunął. Stąd możesz wrócić do przyszłości i użyć git-revert aby cofnąć zmianę,

git bisect reset
git revert <the offending commit>

Albo możesz cofnąć jeden commit i ręcznie sprawdzić obrażenia:

git checkout HEAD^
cp foo.bar /tmp
git bisect reset
cp /tmp/foo.bar .
 84
Author: Josh Lee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-28 19:10:53

Mój nowy ulubiony alias, oparty na bonyiii 'S answer (upvoted) i mojej własnej odpowiedzi na temat" podaj argument do komendy 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'

Zgubiłem plik, usunięty przez pomyłkę kilka commitów temu?
Szybko:

git restore my_deleted_file
Kryzys zażegnany.

Robert Dailey proponuje w komentarzach następujący pseudonim:

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

I jegan dodaje w komentarzach:

Do Ustawienia alias z linii poleceń, użyłem tego polecenia:

git config --global alias.restore "\!git checkout \$(git rev-list -n 1 HEAD -- \"\$1\")^ -- \"\$1\"" 
 63
Author: VonC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-10 06:03:55

Jeśli znasz nazwę pliku, jest to łatwy sposób z podstawowymi poleceniami:

Wypisuje wszystkie commity dla tego pliku.

git log -- path/to/file

Ostatni commit (najwyższy) to ten, który usunął plik. Więc musisz przywrócić przedostatni commit.

git checkout {second to last commit} -- path/to/file
 43
Author: wisbucky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-15 11:48:31

Przywracanie usuniętego i zatwierdzonego pliku:

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

Został przetestowany na Git w wersji 1.7.5.4.

 28
Author: Fedir RYKHTIK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-14 20:26:38

Jeśli tylko wprowadziłeś zmiany i usunąłeś plik, ale nie zatwierdziłeś go, a teraz zerwałeś ze swoimi zmianami

git checkout -- .

Ale usunięte pliki nie powróciły, wystarczy wykonać następujące polecenie:

git checkout <file_path>
Presto, Twoje akta wróciły.
 22
Author: Paulo Linhares - Packapps,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-02 15:30:19

Mam To rozwiązanie .

  1. Uzyskaj identyfikator zatwierdzenia, w którym plik został usunięty, używając jednego z poniższych sposobów.

    • git log --grep=*word*
    • git log -Sword
    • git log | grep --context=5 *word*
    • git log --stat | grep --context=5 *word* # zalecane, jeśli trudno Zapamiętaj Wszystko
  2. Powinieneś dostać coś w stylu:

Commit bfe68bd117e1091c96d2976c99b3bcc8310bebe7 autor: Alexander Orlov Data: Thu May 12 23:44:27 2011 +0200

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

Commit 3ea4e3af253ac6fd1691ff6bb89c964f54802302 autor: Alexander Orlov Data: Thu May 12 22:10:22 2011 +0200

3. Teraz używając identyfikatora zatwierdzenia bfe68bd117e1091c96d2976c99b3bcc8310bebe7 do:

git checkout bfe68bd117e1091c96d2976c99b3bcc8310bebe7^1 yourDeletedFile.java

Ponieważ identyfikator commita odwołuje się do commita, w którym plik został już usunięty, musisz odwołać się do commita tuż przed bfe68b, co możesz zrobić, dodając ^1. Oznacza to: daj mi commit tuż przed bfe68b.

 21
Author: Alex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-25 18:07:17
git checkout /path/to/deleted.file
 14
Author: user1528493,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-25 18:05:51

W wielu przypadkach przydatne może być użycie coreutils (grep, sed, itp.) w połączeniu z Git. Znam już te narzędzia całkiem dobrze, ale Git mniej. Jeśli chciałbym wyszukać usunięty plik, wykonałbym następujące czynności:

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

Kiedy znajdę revision/commit:

git checkout <rev>^ -- path/to/refound/deleted_file.c
Tak jak inni mówili przede mną.

Plik zostanie przywrócony do stanu sprzed usunięcia. Pamiętaj o ponownym przypisaniu go do działającego drzewa, jeśli chcesz go zachować w pobliżu.

 10
Author: Thomas E,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-14 20:27:59

git undelete path/to/file.ext

  1. Umieść to w swoim .bash_profile (lub innym odpowiednim pliku, który ładuje się po otwarciu powłoki poleceń):

    git config --global alias.undelete '!sh -c "git checkout $(git rev-list -n 1 HEAD -- $1)^ -- $1" -'
    
  2. Następnie użyj:

    git undelete path/to/file.ext
    

Ten alias najpierw sprawdza, czy znajduje ostatni commit, w którym istniał ten plik, a następnie wykonuje polecenie git dla tej ścieżki z ostatniego commita, w którym istniał ten plik. źródło

 9
Author: Beau Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-08 01:13:40

Więc musiałem przywrócić kilka usuniętych plików z konkretnego commita i zarządzałem tym za pomocą dwóch komend:

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 

(zwróć uwagę na spację końcową na końcu każdego polecenia.)

Pliki zostały dodane do.plik gitignore, a następnie wyczyszczone z git rm, musiałem przywrócić pliki, ale następnie odinstalować je. Miałem setki plików do przywrócenia, wpisywanie rzeczy ręcznie dla każdego pliku, jak w innych przykładach, miało być zbyt wolne.

 6
Author: kzar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-15 11:49:46
user@bsd:~/work/git$ rm slides.tex
user@bsd:~/work/git$ git pull 
Already up-to-date.
user@bsd:~/work/git$ ls slides.tex
ls: slides.tex: No such file or directory

Przywróć usunięty plik:

user@bsd:~/work/git$ git checkout
D       .slides.tex.swp
D       slides.tex
user@bsd:~/work/git$ git checkout slides.tex 
user@bsd:~/work/git$ ls slides.tex
slides.tex
 4
Author: user1797498,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-29 16:35:45

Miałem to samo pytanie. Nie wiedząc o tym, stworzyłem zwisające.

Lista zwisających commitów

git fsck --lost-found

Sprawdź każdy zwisający commit

git reset --hard <commit id>

Moje pliki pojawiły się ponownie, gdy przeniosłem się do zwisającego commita.

git status z powodu:

“HEAD detached from <commit id where it detached>”

 4
Author: rustyMagnet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-04 17:08:40

W naszym przypadku przypadkowo usunęliśmy pliki w commicie, a niektóre z nich później zdaliśmy sobie sprawę z naszego błędu i chcieliśmy odzyskać wszystkie pliki, które zostały usunięte, ale nie te, które zostały zmodyfikowane.

Na podstawie doskonałej odpowiedzi Charlesa Baileya oto moja jedna linijka:

git co $(git rev-list -n 1 HEAD -- <file_path>)~1 -- $(git diff --name-status $(git rev-list -n 1 HEAD -- <file_path>)~1 head | grep '^D' | cut -f 2)
 3
Author: bonyiii,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-02 20:52:39

Jeśli znasz commit, który usunął plik(y), uruchom to polecenie, gdzie <SHA1_deletion> jest commitem, który usunął plik:

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

Część przed potokiem wyświetla listę wszystkich plików, które zostały usunięte w commicie; wszystkie są kasami z poprzedniego commitu, aby je przywrócić.

 3
Author: Tony Wickham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-08 19:27:52
$ git log --diff-filter=D --summary  | grep "delete" | sort
 -1
Author: kujiy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-05 01:01:30