Git: Gelöschten (entfernten) Zweig wiederherstellen

94

Ich muss zwei Git-Zweige wiederherstellen, die ich während eines Pushs irgendwie gelöscht habe.

Diese beiden Zweige wurden auf einem anderen System erstellt und dann in mein "freigegebenes" (Github) Repository verschoben.

Auf meinem System habe ich (anscheinend) die Zweige während eines Abrufs abgerufen:

~/myfolder> git fetch
remote: Counting objects: 105, done.
remote: Compressing objects: 100% (58/58), done.
remote: Total 62 (delta 29), reused 0 (delta 0)
Unpacking objects: 100% (62/62), done.
From github.com:mygiturl
 * [new branch]      contact_page -> origin/contact_page
   731d1bb..e8b68cc  homepage   -> origin/homepage
 * [new branch]      new_pictures -> origin/new_pictures

Gleich danach habe ich versucht, meine lokalen Änderungen an das zentrale Repo zu senden. Aus irgendeinem Grund wurden diese Zweige sowohl aus meinem lokalen System als auch aus dem zentralen Repo gelöscht:

~/myfolder> git push
Counting objects: 71, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (43/43), done.
Writing objects: 100% (49/49), 4.99 KiB, done.
Total 49 (delta 33), reused 0 (delta 0)
To [email protected]:mygiturl.git
 - [deleted]         contact_page
 + e8b68cc...731d1bb homepage -> homepage (forced update)
   bb7e9f2..e0d061c  master -> master
 - [deleted]         new_pictures
   e38ac2e..bb7e9f2  origin/HEAD -> origin/HEAD
   731d1bb..e8b68cc  origin/homepage -> origin/homepage
   e38ac2e..bb7e9f2  origin/master -> origin/master
 * [new branch]      origin/contact_page -> origin/contact_page
 * [new branch]      origin/new_pictures -> origin/new_pictures

Es ist nicht besonders einfach, die Zweige von ihrer Geburtsortmaschine zu entfernen, daher würde ich gerne versuchen, sie nach Möglichkeit von meinem lokalen Standort zu retten.

Alle von mir gegoogelten "Rückgängig" -Informationen müssen dazu führen, dass verlorene Commits wiederhergestellt werden. Ich denke nicht, dass dies hier zutrifft, da ich keine Commit-UIDs für diese Zweige habe.

Ich würde gerne wissen, wie ich diese zurückbekommen kann. Ich würde auch gerne wissen, wie sie überhaupt gelöscht wurden und wie ich dies in Zukunft vermeiden kann.

EDIT: auf Anfrage hier meine Repo-Konfiguration

user.name=Craig Walker
[email protected]
alias.unadd=reset HEAD
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
[email protected]:MyGitURL.git
remote.origin.mirror=true
branch.master.remote=origin
branch.master.merge=refs/heads/master
alias.undo=reset --hard
alias.test=push -f ci HEAD:master
alias.st=status
alias.ci=commit
alias.br=branch
alias.co=checkout
alias.ch=checkout
alias.df=diff
alias.lg=log -p
alias.who=shortlog -s --
remote.ci.url=ContinuousIntegrationGitURL
remote.ci.fetch=+refs/heads/*:refs/remotes/ci/*
branch.photo.remote=origin
branch.photo.merge=refs/heads/photos
remote.foo.url=FooGitURL
remote.foo.fetch=+refs/heads/*:refs/remotes/cynthia/*
branch.homepage.remote=origin
branch.homepage.merge=refs/heads/homepage
Craig Walker
quelle
Es sieht so aus, als hätten Sie eine "ungewöhnliche" oder nicht übereinstimmende Abruf- und Push-Konfiguration. Was wird git config -lfür das lokale Repository angezeigt?
CB Bailey
Möglicherweise; Ich habe es gepostet.
Craig Walker
2
Ihre remote.origin.fetchReferenz ist nicht für die Verwendung mit geeignet remote.origin.mirror = true. Möchten Sie spiegeln oder möchten Sie das GitHub-Repo als normale Fernbedienung verwenden? Meine Antwort sollte die Befehle enthalten, die Sie so oder so benötigen.
Chris Johnsen
Ich vermute, dass mit dem 2. Repository das Spiegeln keine Option mehr ist (dies hat wahrscheinlich das Löschen an erster Stelle verursacht).
Craig Walker

Antworten:

102

Ich bin kein Experte. Aber du kannst es versuchen

git fsck --full --no-reflogs | grep commit

um das HEAD-Commit des gelöschten Zweigs zu finden und sie zurückzubekommen.

iamamac
quelle
Ich habe es früher mit fsck versucht. Wissen Sie, wie Sie herausfinden können, welches Commit das richtige ist? Ich muss 20 versuchen.
Craig Walker
1
Das hat es geschafft; Sobald ich die Commit-Nachrichten hatte, git branch <uid>bekam ich sie zurück. Vielen Dank!
Craig Walker
Gut zu hören. Stellen Sie sicher, dass Sie auch den Konflikt zwischen Ihren remotes.origin.mirrorund den remotes.origin.fetchEinstellungen lösen , da Sie sonst erneut auf das Problem stoßen müssen (oder unbeabsichtigt von anderen Repos übertragene Clobber-Commits).
Chris Johnsen
@Craig: Freut mich, hilfreich zu sein :)
iamamac
3
Ich habe heute einen Zweig für Release-Kandidaten verloren. Wusste die Commit-ID nicht. git fsck --full --no-reflogs | cut -d' ' -f3 | xargs -P8 git log --oneline | grep 'Release 2.60.0.157'
Habe
23

Nur zwei Befehle retten mein Leben

1. Dadurch werden alle vorherigen KÖPFE aufgelistet

git reflog

2. Dadurch wird der von Ihnen gelöschte HEAD zurückgesetzt.

git reset --hard <your deleted commit>
ex. git reset --hard b4b2c02
Chinnawatp
quelle
1
Ich habe nie lokal in die Filiale eingecheckt, daher war mein HEAD noch nie dort, daher kann ich die Commit-ID mit nicht finden git reflog. Kann ich noch etwas ausprobieren?
Zyy
1
Wie @zyy Das Commit wurde von einem anderen Teammitglied in Remote gelöscht, daher muss ich es auf meinem lokalen Computer zurückholen (ich hatte dieses Commit nie lokal) und es zurückschieben ...
OmGanesh
11

Ihre gelöschten Zweige gehen nicht verloren, sie wurden durch den von Ihnen angezeigten Abruf in origin / contact_page und origin / new_pictures "Remote Tracking-Zweige" kopiert (sie wurden auch durch den von Ihnen angezeigten Push wieder herausgeschoben, aber sie wurden in refs / remotes / verschoben). Herkunft / statt Refs / Köpfe /). Überprüfen git log origin/contact_pageund git log origin/new_pictureszu sehen , ob Ihre lokalen Kopien sind „up to date“ mit dem, was denken Sie da sein sollte. Wenn zwischen dem von Ihnen angezeigten Abruf und Push neue Commits auf diese Zweige (von einem anderen Repo) verschoben wurden, haben Sie diese möglicherweise "verloren" (aber wahrscheinlich könnten Sie sie in dem anderen Repo finden, das diese Zweige zuletzt verschoben hat). .

Konflikt holen / pushen

Es sieht so aus, als würden Sie in einem normalen 'Remote-Modus' abrufen (Remote-Refs / Köpfe / werden lokal in Refs / Fernbedienungen / Ursprung / gespeichert), aber im 'Spiegel-Modus' drücken (lokale Refs / werden auf Remote-Refs / verschoben) . Überprüfen Sie Ihre .git / config und stimmen Sie die remote.origin.fetchund remote.origin.pushEinstellungen ab.

Erstelle eine Sicherung

Bevor Sie Änderungen versuchen, erstellen Sie ein einfaches Tar- oder Zip-Archiv oder Ihr gesamtes lokales Repo. Auf diese Weise können Sie es von einem wiederhergestellten Repo aus erneut versuchen, wenn Ihnen das, was passiert, nicht gefällt.

Option A: Als Spiegel neu konfigurieren

Wenn Sie beabsichtigen, Ihr Remote-Repo als Spiegel Ihres lokalen Repos zu verwenden, gehen Sie folgendermaßen vor:

git branch contact_page origin/contact_page &&
git branch new_pictures origin/new_pictures &&
git config remote.origin.fetch '+refs/*:refs/*' &&
git config --unset remote.origin.push &&
git config remote.origin.mirror true

Möglicherweise möchten Sie eventuell auch alle Ihre Refs / Fernbedienungen / Ursprünge / Refs löschen, da diese nicht nützlich sind, wenn Sie im Spiegelmodus arbeiten (Ihre normalen Zweige ersetzen die üblichen Fernverfolgungszweige).

Option B: Als normale Fernbedienung neu konfigurieren

Da Sie dieses Remote-Repo jedoch anscheinend mit mehreren "Arbeits" -Repos verwenden, möchten Sie den Spiegelmodus wahrscheinlich nicht verwenden. Sie könnten dies versuchen:

git config push.default tracking &&
git config --unset remote.origin.push
git config --unset remote.origin.mirror

Dann möchten Sie eventuell die gefälschten Refs / Fernbedienungen / Ursprungsreferenzen in Ihrem Remote-Repo löschen : git push origin :refs/remotes/origin/contact_page :refs/remotes/origin/new_pictures ….

Test Push

Versuchen Sie git push --dry-runzu sehen, was es git pushtun würde, ohne dass es Änderungen am Remote-Repo vornimmt. Wenn Ihnen das, was es verspricht, nicht gefällt, stellen Sie es von Ihrem Backup (tar / zip) wieder her und versuchen Sie es mit der anderen Option.

Chris Johnsen
quelle
1
Ich glaube nicht, dass die Fernverfolgungszweige beibehalten wurden, wenn sie überhaupt kopiert wurden. 'git branch -a' zeigt sie nicht an und ich kann auch keine Dateien mit diesen Namen im .git-Verzeichnis finden. Schließlich geben die von Ihnen empfohlenen "git log" -Befehle "fatal: mehrdeutiges Argument 'origin / contact_page': unbekannte Revision oder Pfad nicht im Arbeitsbaum" zurück: - \ Danke.
Craig Walker
1
Nun, diese Zweige waren da, Ihr Push-Protokoll zeigt es. Achten Sie bei der Suche nach Refs im .gitVerzeichnis darauf, .git/packed_refszusätzlich zu .git/refs/. git show-refwird alle Ihre lokalen Refs (verpackt oder "lose") entleeren. Sie sollten weiterhin in der Lage sein, die Refs im Repo zu finden, die sie ursprünglich in Ihr GitHub-Repo verschoben haben (auf einem anderen Computer? Das Repo eines anderen?). Andernfalls sollten Sie in der Lage sein git fsck, die baumelnden Commits zu überprüfen und wieder anzubringen, solange Sie kein GC oder Prune durchgeführt haben : git branch contact_page-recovered <SHA-1-of-dangling-commit>.
Chris Johnsen
packte_refs hatte es auch nicht. Die Commits baumelten definitiv; Keine Ahnung, wie das passiert ist. Vielen Dank für Ihre Hilfe!
Craig Walker
8

Wenn das Löschen aktuell genug ist (wie ein Oh-NEIN! -Moment), sollten Sie dennoch eine Nachricht haben:

Deleted branch <branch name> (was abcdefghi).

Sie können immer noch ausführen:

git checkout abcdefghi

git checkout -b <some new branch name or the old one>

Timmy
quelle
7
  1. Finden Sie die Coimmit-ID heraus

    git reflog

  2. Stellen Sie den versehentlich gelöschten lokalen Zweig wieder her

    git branch need-recover-branch-name commitId

  3. Drücken Sie Need-Recovery-Branch-Name erneut, wenn Sie zuvor auch den Remote-Zweig gelöscht haben

    git push origin need-recover-branch-name

JackChouMine
quelle
2
Das hat bei mir funktioniert. Ich bevorzuge die akzeptierte Antwort, weil es weit weniger Schritte waren. Ich konnte meine Commit-Nachricht von sehen git reflog, anstatt raten zu müssen und git show.
theUtherSide
3

Die Daten sind noch in Github vorhanden. Sie können aus den alten Daten einen neuen Zweig erstellen:

git checkout origin/BranchName #get a readonly pointer to the old branch
git checkout –b BranchName #create a new branch from the old
git push origin BranchName #publish the new branch
jhilden
quelle
1

Ich denke, dass Sie eine nicht übereinstimmende Konfiguration für 'Fetch' und 'Push' haben, so dass dies dazu geführt hat, dass das Standard-Fetch / Push nicht richtig umrundet. Glücklicherweise haben Sie die Zweige abgerufen, die Sie anschließend gelöscht haben, sodass Sie sie mit einem expliziten Push neu erstellen können sollten.

git push origin origin/contact_page:contact_page origin/new_pictures:new_pictures
CB Bailey
quelle
Wie bei meinem Kommentar zu @Chris Johnson scheint es, dass die Zweige lokal nicht mehr (nie?) Bestehen. Wenn ich das git push origin origin/contact_page:contact_pagebekomme: error: src refspec origin/contact_page does not match any
Craig Walker
OK, ich denke ich sehe was passiert ist (obwohl der vollständige Fehler hilfreich wäre). push hat den gelöschten Zweig aktualisiert und die Referenz lokal entfernt sowie eine Tracking-Referenz. Was git rev-parse refs/remotes/origin/origin/contact_pagesagt das aus? Aufgrund der falschen 'Spiegel'-Konfiguration kann der Zweig jetzt hier im lokalen Repository referenziert werden.
CB Bailey
Hallo Charles; Seit ich das geschrieben habe, habe ich meine Konfiguration munged (und repariert), so dass ich die (bedeutungsvolle) Rev-Parse-Ausgabe nicht mehr bekommen kann. Ich glaube jedoch nicht, dass es in Fernbedienungen ein doppelt verschachteltes "Ursprungs" -Verzeichnis gab.
Craig Walker
0

Wenn Ihre Organisation JIRA oder ein anderes ähnliches System verwendet, das an git gebunden ist, können Sie die auf dem Ticket selbst aufgeführten Commits finden und auf die Links zu den Codeänderungen klicken. Github löscht den Zweig, hat aber immer noch die Commits für die Kirschernte.

Roralee
quelle
-1

Es mag zu vorsichtig erscheinen, aber ich komprimiere häufig eine Kopie von allem, woran ich gearbeitet habe, bevor ich Änderungen an der Quellcodeverwaltung vornehme. In einem Gitlab-Projekt, an dem ich arbeite, habe ich kürzlich versehentlich einen Remote-Zweig gelöscht, den ich nach dem Zusammenführen einer Zusammenführungsanforderung beibehalten wollte. Es stellte sich heraus, dass alles, was ich tun musste, um es mit dem Commit-Verlauf zurückzubekommen, erneut Push war. Die Zusammenführungsanforderung wurde weiterhin von Gitlab verfolgt, sodass rechts neben dem Zweig weiterhin die blaue Bezeichnung "Zusammengeführt" angezeigt wird. Ich habe immer noch meinen lokalen Ordner komprimiert, falls etwas Schlimmes passiert ist.

Artorias2718
quelle