Jak mogę cofnąć git reset --hard HEAD~1?

Czy możliwe jest cofnięcie zmian wywołanych poniższym poleceniem? Jeśli tak, to w jaki sposób?

git reset --hard HEAD~1
Author: jubobs, 2008-08-08

13 answers

Pat Notz ma rację. Możesz odzyskać commit tak długo, jak to było w ciągu kilku dni. git zbiera tylko śmieci po około miesiącu, chyba że wyraźnie każesz mu usunąć nowsze obiekty BLOB.

$ git init
Initialized empty Git repository in .git/

$ echo "testing reset" > file1
$ git add file1
$ git commit -m 'added file1'
Created initial commit 1a75c1d: added file1
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file1

$ echo "added new file" > file2
$ git add file2
$ git commit -m 'added file2'
Created commit f6e5064: added file2
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file2

$ git reset --hard HEAD^
HEAD is now at 1a75c1d... added file1

$ cat file2
cat: file2: No such file or directory

$ git reflog
1a75c1d... HEAD@{0}: reset --hard HEAD^: updating HEAD
f6e5064... HEAD@{1}: commit: added file2

$ git reset --hard f6e5064
HEAD is now at f6e5064... added file2

$ cat file2
added new file

W przykładzie widać, że plik2 został usunięty w wyniku twardego resetu, ale został przywrócony podczas resetowania przez reflog.

 1433
Author: Brian Riehman,
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
2009-01-29 05:35:42

To, co chcesz zrobić, to określić sha1 commitu, do którego chcesz przywrócić. Możesz uzyskać sha1, sprawdzając reflog (git reflog), a następnie wykonując

git reset --hard <sha1 of desired commit>

Ale nie czekaj zbyt długo... po kilku tygodniach git w końcu zobaczy ten commit jako niezrealizowany i usunie wszystkie bloby.
 318
Author: Pat Notz,
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
2008-08-09 05:30:13

Odpowiedź jest ukryta w szczegółowej odpowiedzi powyżej, możesz po prostu zrobić:

$> git reset --hard HEAD@{1}

(Zobacz wyjście git reflog show )

 127
Author: markmc,
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-02-26 15:13:20

Jest możliwe odzyskanie go, jeśli Git jeszcze nie zebrał śmieci.

Uzyskaj przegląd zwisających commitów za pomocą fsck:

$ git fsck --lost-found
dangling commit b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf

Odzyskaj zwisający commit za pomocą rebase:

$ git rebase b72e67a9bb3f1fc1b64528bcce031af4f0d6fcbf
 83
Author: sverrejoh,
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-07-13 19:51:59

Jeśli masz naprawdę szczęście, tak jak ja, możesz wrócić do edytora tekstu i nacisnąć "Cofnij".

Wiem, że to nie jest właściwa odpowiedź, ale zaoszczędziło mi to pół dnia pracy, więc mam nadzieję, że zrobi to samo dla kogoś innego!

 34
Author: Chris,
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-01-13 00:48:48

Przykład sprawy IRL:

$ git fsck --lost-found

Checking object directories: 100% (256/256), done.
Checking objects: 100% (3/3), done.
dangling blob 025cab9725ccc00fbd7202da543f556c146cb119
dangling blob 84e9af799c2f5f08fb50874e5be7fb5cb7aa7c1b
dangling blob 85f4d1a289e094012819d9732f017c7805ee85b4
dangling blob 8f654d1cd425da7389d12c17dd2d88d318496d98
dangling blob 9183b84bbd292dcc238ca546dab896e073432933
dangling blob 1448ee51d0ea16f259371b32a557b60f908d15ee
dangling blob 95372cef6148d980ab1d7539ee6fbb44f5e87e22
dangling blob 9b3bf9fb1ee82c6d6d5ec9149e38fe53d4151fbd
dangling blob 2b21002ca449a9e30dbb87e535fbd4e65bac18f7
dangling blob 2fff2f8e4ea6408ac84a8560477aa00583002e66
dangling blob 333e76340b59a944456b4befd0e007c2e23ab37b
dangling blob b87163c8def315d40721e592f15c2192a33816bb
dangling blob c22aafb90358f6bf22577d1ae077ad89d9eea0a7
dangling blob c6ef78dd64c886e9c9895e2fc4556e69e4fbb133
dangling blob 4a71f9ff8262701171d42559a283c751fea6a201
dangling blob 6b762d368f44ddd441e5b8eae6a7b611335b49a2
dangling blob 724d23914b48443b19eada79c3eb1813c3c67fed
dangling blob 749ffc9a412e7584245af5106e78167b9480a27b
dangling commit f6ce1a403399772d4146d306d5763f3f5715cb5a    <- it's this one

$ git show f6ce1a403399772d4146d306d5763f3f5715cb5a

commit f6ce1a403399772d4146d306d5763f3f5715cb5a
Author: Stian Gudmundsen Høiland <[email protected]>
Date:   Wed Aug 15 08:41:30 2012 +0200

    *MY COMMIT MESSAGE IS DISPLAYED HERE*

diff --git a/Some.file b/Some.file
new file mode 100644
index 0000000..15baeba
--- /dev/null
+++ b/Some.file
*THE WHOLE COMMIT IS DISPLAYED HERE*

$ git rebase f6ce1a403399772d4146d306d5763f3f5715cb5a

First, rewinding head to replay your work on top of it...
Fast-forwarded master to f6ce1a403399772d4146d306d5763f3f5715cb5a.
 28
Author: Stian Høiland,
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-08-20 01:39:49

Z tego co wiem, --hard odrzuci niezakontraktowane zmiany. Ponieważ nie są śledzone przez git. ale możesz cofnąć discarded commit.

$ git reflog

Listy:

b0d059c HEAD@{0}: reset: moving to HEAD~1
4bac331 HEAD@{1}: commit: added level introduction....
....

Gdzie 4bac331 jest discarded commit.

Teraz przesuń głowę do tego commita::

$ git reset --hard 4bac331
 26
Author: simple_human,
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-04-02 08:57:22

W większości przypadków tak.

W zależności od stanu, w jakim znajdowało się Twoje repozytorium podczas uruchamiania polecenia, efekty działania git reset --hard mogą wahać się od trywialnych przez cofnięcie, po praktycznie niemożliwe.

Poniżej wymieniłem szereg różnych możliwych scenariuszy, i jak można odzyskać z nich.

Wszystkie moje zmiany zostały popełnione, ale teraz commity zniknęły!

Ta sytuacja zwykle występuje, gdy uruchamiasz {[3] } z argumentem, jak w git reset --hard HEAD~. Nie martw się, to jest łatwe do / align = "left" /

Jeśli pobiegłeś git reset i nie zrobiłeś nic więcej od tego czasu, możesz wrócić do tego, gdzie byłeś z tym jednym linerem:

git reset --hard @{1}

Resetuje bieżącą gałąź bez względu na stan, w którym była przed ostatnią modyfikacją (w Twoim przypadku, ostatnią modyfikacją gałęzi będzie twardy reset, który próbujesz cofnąć).

Jeśli jednak dokonałeś innych modyfikacji w swojej gałęzi od czasu resetu, powyższa jedna linijka nie praca. Zamiast tego powinieneś uruchomić git reflog <branchname> aby wyświetlić listę wszystkich ostatnich zmian wprowadzonych w gałęzi (w tym resetów). Lista ta będzie wyglądała mniej więcej tak:

7c169bd master@{0}: reset: moving to HEAD~
3ae5027 master@{1}: commit: Changed file2
7c169bd master@{2}: commit: Some change
5eb37ca master@{3}: commit (initial): Initial commit

Znajdź operację na tej liście, którą chcesz "cofnąć". W powyższym przykładzie byłaby to pierwsza linia, ta z napisem " reset: moving to HEAD~". Następnie skopiuj reprezentację commit przed (poniżej) tej operacji. W naszym przypadku byłoby to master@{1} (lub 3ae5027, obie reprezentuj ten sam commit) i uruchom git reset --hard <commit>, aby zresetować bieżącą gałąź z powrotem do tego commita.

Zainscenizowałem moje zmiany git add, ale nigdy się nie zobowiązałem. Teraz moje zmiany zniknęły!

To jest trochę trudniejsze do odzyskania. git czy posiada kopie plików, które dodałeś, ale ponieważ te kopie nigdy nie były powiązane z żadnym zatwierdzeniem, nie możesz przywrócić wszystkich zmian na raz. Zamiast tego musisz zlokalizować poszczególne pliki w bazie danych Gita i przywrócić je ręcznie. Możesz to zrobić za pomocą git fsck.

Szczegółowe informacje na ten temat można znaleźć w Undo Git reset --hard with uncommitted files in the staging area .

Miałem zmiany w plikach w moim katalogu roboczym, których nigdy nie wystawiałem z git add i nigdy nie popełniałem. Teraz moje zmiany zniknęły!

Uh oh. Przykro mi to mówić, ale pewnie nie masz szczęścia. git nie przechowuje zmian, których nie dodajesz lub nie zatwierdzasz, a zgodnie z dokumentacją dla git reset:

--hard

Resetuje indeks i drzewo robocze. wszelkie zmiany śledzonych plików w drzewie roboczym od {[15] } są odrzucane.

Jest możliwe, że możesz być w stanie odzyskać swoje zmiany za pomocą jakiegoś narzędzia do odzyskiwania dysku lub profesjonalnej usługi odzyskiwania danych, ale w tym momencie jest to prawdopodobnie więcej kłopotów niż jest warte.

 24
Author: Ajedi32,
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-05-23 11:47:36

Jeśli nie zebrałeś jeszcze śmieci w repozytorium (np. używając git repack -d lub git gc, ale zauważ, że zbieranie śmieci może również odbywać się automatycznie), To twój commit nadal tam jest – po prostu nie jest już dostępny przez głowicę.

Możesz spróbować znaleźć swój commit, przeglądając Wyjście git fsck --lost-found.

Nowsze wersje Git mają coś o nazwie "reflog" , który jest logiem wszystkich zmian, które są wprowadzane do refs (w przeciwieństwie do zmian, które są wprowadzane do zawartość repozytorium). Tak więc, na przykład, za każdym razem, gdy zmienisz głowę (tj. za każdym razem, gdy wykonasz git checkout, Aby zmienić gałęzie), które będą rejestrowane. I, oczywiście, twoja git reset również manipulowała głową, więc była również rejestrowana. Możesz uzyskać dostęp do starszych Stanów refów w podobny sposób, jak możesz uzyskać dostęp do starszych Stanów repozytorium, używając znaku @ zamiast znaku ~, jak git reset HEAD@{1}.

Zajęło mi trochę czasu, aby zrozumieć, jaka jest różnica między HEAD@{1} i HEAD~1, więc oto małe wyjaśnienie:

git init
git commit --allow-empty -mOne
git commit --allow-empty -mTwo
git checkout -b anotherbranch
git commit --allow-empty -mThree
git checkout master # This changes the HEAD, but not the repository contents
git show HEAD~1 # => One
git show HEAD@{1} # => Three
git reflog

Zatem HEAD~1 oznacza "przejdź do zatwierdzenia przed zatwierdzeniem, na które wskazuje obecnie głowa", podczas gdy HEAD@{1} oznacza "przejdź do zatwierdzenia, na które wskazała Głowa, zanim wskazała tam, gdzie obecnie wskazuje".

To z łatwością pozwoli Ci odnaleźć utracony commit i go odzyskać.

 20
Author: Jörg W Mittag,
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
2008-08-29 01:49:54

Wiem, że to stary wątek... ale ponieważ wiele osób szuka sposobów na cofnięcie rzeczy w Git, nadal uważam, że dobrym pomysłem może być kontynuowanie dawania wskazówek tutaj.

Gdy wykonasz "git add" lub przeniesiesz cokolwiek z lewego górnego rogu do lewego dolnego rogu w GUI git, zawartość pliku jest przechowywana w obiekcie blob i zawartość pliku jest możliwa do odzyskania z tego obiektu blob.

Więc możliwe jest odzyskanie pliku, nawet jeśli nie został zatwierdzony, ale musi być dodano.

git init  
echo hello >> test.txt  
git add test.txt  

Teraz blob jest tworzony, ale odwołuje się do niego indeks, więc nie będzie wyświetlany w git fsck dopóki nie zresetujemy. Więc się resetujemy...

git reset --hard  
git fsck  

Dostaniesz zwisający blob ce013625030ba8dba906f756967f9e9ca394464a

git show ce01362  

Zwróci zawartość pliku "hello"

Aby znaleźć niezrealizowane commity znalazłem gdzieś wskazówkę sugerującą to.

gitk --all $(git log -g --pretty=format:%h)  

Mam go jako narzędzie w gui git i jest bardzo przydatny.

 10
Author: martin,
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-01-20 06:27:22

Zanim odpowiemy, dodajmy trochę tła, wyjaśniając, co to jest HEAD.

First of all what is HEAD?

HEAD jest po prostu odniesieniem do bieżącego commita (latest)w bieżącej gałęzi.
W danym momencie może istnieć tylko jedna HEAD. (z wyłączeniem git worktree)

Zawartość HEAD jest przechowywana wewnątrz .git/HEAD i zawiera 40 bajtów SHA-1 bieżącego commita.


detached HEAD

Jeśli nie jesteś na najnowszy commit-co oznacza, że HEAD wskazuje na poprzedni commit w historii o nazwie detached HEAD.

Tutaj wpisz opis obrazka

W wierszu poleceń będzie wyglądać tak - SHA-1 zamiast nazwy gałęzi, ponieważ HEAD nie wskazuje na końcówkę bieżącej gałęzi

Tutaj wpisz opis obrazka


Kilka opcji, jak odzyskać od odłączonej głowy:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

To będzie nowe gałąź wskazująca na żądany commit.
Polecenie to zostanie pobrane do danego commita.
W tym momencie możesz utworzyć gałąź i rozpocząć pracę od tego momentu.

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Zawsze możesz użyć reflog.
git reflog wyświetli każdą zmianę, która zaktualizowała HEAD, A sprawdzenie żądanego wpisu reflog ustawi HEAD z powrotem do tego commita.

Za każdym razem, gdy głowica zostanie zmodyfikowana, pojawi się nowy wpis w reflog

git reflog
git checkout HEAD@{...}

To przywróci Ci pożądany commit

Tutaj wpisz opis obrazka


git reset HEAD --hard <commit_id>

"Przenieś" głowę z powrotem do żądanego commita.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
  • Uwaga: (Od Git 2.7)
    możesz również użyć git rebase --no-autostash.


git revert <sha-1>

"Cofnij" dany commit lub zakres zmian.
Polecenie reset spowoduje "cofnięcie" wszelkich zmian dokonanych w danym zatwierdzeniu.
Nowy commit z łatką undo zostanie zatwierdzony, podczas gdy oryginalny commit pozostanie również w historii.

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Ten schemat ilustruje, które polecenie co robi.
Jak widać reset && checkout zmodyfikuj HEAD.

Tutaj wpisz opis obrazka

 5
Author: CodeWizard,
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-21 16:30:45

Zrobiłem mały skrypt, aby nieco ułatwić znalezienie poszukiwanego commita:

git fsck --lost-found | grep commit | cut -d ' ' -f 3 | xargs -i git show \{\} | egrep '^commit |Date:'

Tak, może być znacznie ładniejsza z awk lub coś podobnego, ale to proste i po prostu go potrzebowałem. To może zaoszczędzić komuś innemu 30 sekund.

 2
Author: neuron,
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-03-11 08:09:52

Właśnie zrobiłem twardy reset złego projektu. Uratowała mi życie lokalna historia Eclipse. Mówi się, że IntelliJ Idea też ma, więc może twój redaktor, warto sprawdzić:

  1. temat pomocy Eclipse na temat lokalnej historii
  2. http://wiki.eclipse.org/FAQ_Where_is_the_workspace_local_history_stored%3F
 2
Author: Maciek Łoziński,
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-07 08:59:29