Stel dat ik in een Git repository ben. Ik verwijder een bestand en commit die verandering. Ik werk verder en maak nog wat commits. Dan, ontdek ik dat ik dat bestand moet terugzetten.
Ik weet dat ik een bestand kan checkouten met git checkout HEAD^ foo.bar
, maar ik weet niet echt wanneer dat bestand verwijderd was.
Ik'm hoop dat ik niet handmatig door mijn logs hoef te bladeren, het hele project voor een gegeven SHA moet checken en dan handmatig dat bestand in mijn originele projectcheckout moet kopiëren.
Zoek de laatste commit die het gegeven pad geraakt heeft. Omdat het bestand niet in de HEAD commit zit, moet deze commit het verwijderd hebben.
git rev-list -n 1 HEAD -- <file_path>
Check dan de versie bij de commit ervoor, door het caret (^
) symbool te gebruiken:
git checkout <deleting_commit>^ -- <file_path>
Of in één commando, als $file
het bestand in kwestie is.
git checkout $(git rev-list -n 1 HEAD -- "$file")^ -- "$file"
Als je zsh gebruikt en de EXTENDED_GLOB optie aan hebt staan, zal het caret symbool niet werken. Je kunt in plaats daarvan ~1
gebruiken.
git checkout $(git rev-list -n 1 HEAD -- "$file")~1 -- "$file"
git log --diff-filter=D --summary
om alle commits te krijgen die bestanden hebben verwijderd en de verwijderde bestanden;git checkout $commit~1 path/to/file.ext
om het verwijderde bestand terug te zetten.Waarbij $commit
de waarde is van de commit die je bij stap 1 hebt gevonden, bijv. e4cf499627
Als je gek bent, gebruik dan git-bisect
. Hier's wat je moet doen:
git bisect start
git bisect bad
git bisect good <some commit where you know the file existed>
Nu is het tijd om de geautomatiseerde test uit te voeren. Het shell commando '[ -e foo.bar ]'
zal 0 teruggeven als foo.bar
bestaat, en anders 1. Het "run" commando van git-bisect
zal binair zoeken gebruiken om automatisch de eerste commit te vinden waar de test faalt. Het begint halverwege het opgegeven bereik (van goed naar slecht) en knipt het in tweeën, gebaseerd op het resultaat van de gespecificeerde test.
git bisect run '[ -e foo.bar ]'
Nu ben je bij de commit die het verwijderd heeft. Vanaf hier kun je terugspringen naar de toekomst en git-revert
gebruiken om de verandering ongedaan te maken,
git bisect reset
git revert <the offending commit>
of je kunt een commit terug gaan en handmatig de schade inspecteren:
git checkout HEAD^
cp foo.bar /tmp
git bisect reset
cp /tmp/foo.bar .