Vraag Hoe een Git-repository terug te zetten naar een vorige commit


Hoe kan ik terugkeren van mijn huidige staat naar een momentopname gemaakt op een bepaalde commit?

Als ik doe git log, dan krijg ik de volgende uitvoer:

$ git log
commit a867b4af366350be2e7c21b8de9cc6504678a61b`
Author: Me <me@me.com>
Date:   Thu Nov 4 18:59:41 2010 -0400

blah blah blah...

commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4
Author: Me <me@me.com>
Date:   Thu Nov 4 05:13:39 2010 -0400

more blah blah blah...

commit 0766c053c0ea2035e90f504928f8df3c9363b8bd
Author: Me <me@me.com>
Date:   Thu Nov 4 00:55:06 2010 -0400

And yet more blah blah...

commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Author: Me <me@me.com>
Date:   Wed Nov 3 23:56:08 2010 -0400

Yep, more blah blah.

Hoe terug te keren naar de commit vanaf 3 november, d.w.z. commit 0d1d7fc?


6011
2017-11-06 16:58


oorsprong


antwoorden:


Dit hangt sterk af van wat je bedoelt met "terugdraaien".

Tijdelijk overschakelen naar een andere commit

Als je tijdelijk terug wilt gaan, rondkijken, kom dan terug naar waar je bent, het enige wat je hoeft te doen is de gewenste commit bekijken:

# This will detach your HEAD, that is, leave you with no branch checked out:
git checkout 0d1d7fc32

Of als je commits wilt maken terwijl je daar bent, ga je gang en maak je een nieuwe branch terwijl je erbij bent:

git checkout -b old-state 0d1d7fc32

Om terug te gaan naar waar je was, bekijk je gewoon de vestiging waar je was. (Als je wijzigingen hebt aangebracht, zoals altijd bij het wisselen van takken, zul je ze moeten aanpakken waar nodig. Je zou kunnen resetten om ze weg te gooien, je zou kunnen stashen, uitchecken, pop opslaan om ze mee te nemen, je zou je kunnen binden ze naar een tak daar als je daar een tak wilt.)

Hard verwijderen van ongepubliceerde commits

Als je daarentegen echt alles kwijt wilt wat je sindsdien hebt gedaan, zijn er twee mogelijkheden. Ten eerste, als je geen van deze commits hebt gepubliceerd, reset je gewoon:

# 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.

Als je het verprutst, heb je je lokale wijzigingen al weggegooid, maar kun je op zijn minst teruggaan naar waar je was door opnieuw te resetten.

Maak gepubliceerde commits ongedaan met nieuwe commits

Aan de andere kant, als je het werk hebt gepubliceerd, wil je waarschijnlijk het filiaal niet opnieuw instellen, omdat dat de geschiedenis effectief herschrijft. In dat geval zou je inderdaad de commits kunnen terugdraaien. Met Git heeft terugzetten een heel specifieke betekenis: maak een commit met de omgekeerde patch om het te annuleren. Op deze manier herschrijf je geen enkele geschiedenis.

# This will create three separate revert commits:
git revert a867b4af 25eee4ca 0766c053

# It also takes ranges. This will revert the last two commits:
git revert HEAD~2..HEAD

#Similarly, you can revert a range of commits using commit hashes:
git revert a867b4af..0766c053 

# Reverting a merge commit
git revert -m 1 <merge_commit_sha>

# To get just one, you could use `rebase -i` to squash them afterwards
# Or, you could do it manually (be sure to do this at top level of the repo)
# get your index and work tree into the desired state, without changing HEAD:
git checkout 0d1d7fc32 .

# Then commit. Be sure and write a good message describing what you just did
git commit

De git-revert manpage bedekt eigenlijk veel van dit in zijn beschrijving. Een andere nuttige link is deze sectie git-scm.com bespreekt git-revert.

Als u besluit dat u toch niet wilt teruggaan, kunt u de terugzetting herstellen (zoals hier beschreven) of terugzetten naar vóór het terugzetten (zie de vorige sectie).

U vindt dit antwoord misschien ook nuttig in dit geval:
Hoe HEAD terug naar een vorige locatie te verplaatsen? (Vrijstaande kop)


7825
2017-11-06 17:04



Werkkopie terugzetten naar meest recente commit

Om terug te keren naar een vorige commit en alle wijzigingen te negeren:

git reset --hard HEAD

waar HEAD de laatste commit is in je huidige branch

Het werkkopie terugzetten naar een oudere taak

Om terug te keren naar een commit die ouder is dan de meest recente commit:

# Resets index to former commit; replace '56e05fced' with your commit code
git reset 56e05fced 

# Moves pointer back to previous HEAD
git reset --soft HEAD@{1}

git commit -m "Revert to 56e05fced"

# Updates working copy to reflect the new commit
git reset --hard

Credits gaan naar een vergelijkbare Stack Overflow-vraag, Terug naar een commit door een SHA-hash in Git?.


1260
2017-08-21 06:19



Veel gecompliceerde en gevaarlijke antwoorden hier, maar het is eigenlijk eenvoudig:

git revert --no-commit 0766c053..HEAD
git commit

Hierdoor wordt alles van de HEAD teruggezet naar de commit-hash, wat betekent dat het die commit-status in de werkende structuur opnieuw zal creëren alsof elke commit sinds was teruggelopen. Je kunt dan de huidige boom vastleggen, en het zal een geheel nieuwe commit creëren die in essentie gelijk is aan de commit waar je "teruggekeerd" naar bent.

(De --no-commit flag laat git alle commits in één keer terugdraaien - anders wordt u gevraagd om een ​​bericht voor elke commit in het bereik, waarbij u uw geschiedenis overspoelt met onnodige nieuwe commits.)

Dit is een veilige en gemakkelijke manier om terug te gaan naar een vorige staat. Geen enkele geschiedenis is vernietigd, dus het kan worden gebruikt voor commits die al openbaar zijn gemaakt.


1221
2018-02-12 04:18



De beste optie voor mij en waarschijnlijk anderen is de Git-resetoptie:

git reset --hard <commidId> && git clean -f

Dit was de beste optie voor mij! Het is eenvoudig, snel en effectief!


Notitie :  Zoals vermeld in reacties, doe je dit niet als je je branch deelt met andere mensen die kopieën hebben van de oude commits

Ook uit de reacties, als je een minder 'ballzy' methode wilde die je kon gebruiken

git clean -i 


153
2017-10-22 11:53



Als u "uncommit" wilt, het laatste commit-bericht wilt wissen en de gewijzigde bestanden terug in de stage wilt plaatsen, gebruikt u de opdracht:

git reset --soft HEAD~1
  • --soft geeft aan dat de niet-gecommitteerde bestanden moeten worden bewaard als werkbestanden in tegenstelling tot --hard wat hen zou verwijderen.
  • HEAD~1 is de laatste commit. Als je 3 commits terug wilt draaien die je zou kunnen gebruiken HEAD~3. Als u terug wilt draaien naar een specifiek revisienummer, kunt u dat ook doen met de SHA-hash ervan.

Dit is een uiterst nuttig commando in situaties waarin je het verkeerde hebt gedaan en je die laatste commit ongedaan wilt maken.

Bron: http://nakkaya.com/2009/09/24/git-delete-last-commit/


102
2018-03-04 17:25



Voordat we gaan antwoorden, voegen we wat achtergrond toe en leggen we uit wat dit is HEAD is.

First of all what is HEAD?

HEAD is gewoon een verwijzing naar de huidige commit (laatste) op de huidige branch. Er kan alleen een single zijn HEAD op een bepaald moment (exclusief git worktree).

De inhoud van HEAD is binnenin opgeslagen .git/HEADen bevat de 40 bytes SHA-1 van de huidige commit.


detached HEAD

Als je niet op de laatste commit zit - wat dat betekent HEAD verwijst naar een eerdere commit in de geschiedenis die het heet detached HEAD.

Enter image description here

Op de commandolijn ziet het er zo uit: SHA-1 in plaats van de filternaam sinds de HEAD wijst niet naar de punt van de huidige tak:

Enter image description here


Een paar opties om te herstellen van een losgemaakte HEAD:


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

Hiermee wordt de nieuwe tak afgemeld naar de gewenste commit. Deze opdracht zal uitchecken naar een bepaalde commit.

Op dit punt kun je een filiaal maken en vanaf dit punt beginnen werken:

# 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

U kunt altijd de reflog ook. git reflog zal elke verandering weergeven die de HEAD en het uitchecken van de gewenste reflog-invoer stelt de HEAD terug naar deze commit.

Telkens wanneer de HEAD wordt gewijzigd, verschijnt er een nieuw item in de reflog

git reflog
git checkout HEAD@{...}

Dit zal je terugbrengen naar je gewenste commit

Enter image description here


git reset HEAD --hard <commit_id>

"Verplaats" je hoofd terug naar de gewenste commit.

# 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.
  • Notitie: (Sinds Git 2.7) u kunt ook de git rebase --no-autostash ook.

Dit schema illustreert welk commando doet wat. Zoals je daar kunt zien reset && checkout wijzig het HEAD.

Enter image description here


101
2018-02-05 21:56



Ik heb een heleboel manieren geprobeerd om lokale wijzigingen in Git terug te zetten, en het lijkt erop dat dit het beste werkt als je gewoon terug wilt naar de laatste commit-status.

git add . && git checkout master -f

Korte beschrijving:

  • Het zal GEEN commits aanmaken zoals git revert doet.
  • Het maakt je HEAD NIET los zoals git checkout <commithashcode> doet.
  • Het zal alle lokale wijzigingen overschrijven en alle toegevoegde bestanden verwijderen sinds de laatste commit in de branch.
  • Het werkt alleen met namen van takken, dus je kunt op deze manier alleen terugkeren naar de laatste commit in de branche.

Ik vond een veel handigere en eenvoudigere manier om de bovenstaande resultaten te behalen:

git add . && git reset --hard HEAD

waar HEAD verwijst naar de laatste commit op jouw huidige branch.

Het is dezelfde code als boulder_ruby suggereerde, maar ik heb toegevoegd git add . voor git reset --hard HEAD om alle nieuwe bestanden te wissen die zijn gemaakt sinds de laatste commit, omdat dit is wat de meeste mensen verwachten dat ik geloof wanneer ik terugga naar de laatste commit.


96
2017-07-29 11:01



U kunt dit doen met de volgende twee opdrachten:

git reset --hard [previous Commit SHA id here]
git push origin [branch Name] -f

Het zal je vorige Git commit verwijderen.

Als u uw wijzigingen wilt behouden, kunt u ook het volgende gebruiken:

git reset --soft [previous Commit SHA id here]

Dan slaat het uw wijzigingen op.


76
2017-12-12 06:52



Stel dat je de volgende commits hebt in een tekstbestand met de naam ~/commits-to-revert.txt (Ik gebruikte git log --pretty=oneline om ze te pakken)

fe60adeba6436ed8f4cc5f5c0b20df7ac9d93219
0c27ecfdab3cbb08a448659aa61764ad80533a1b
f85007f35a23a7f29fa14b3b47c8b2ef3803d542
e9ec660ba9c06317888f901e3a5ad833d4963283
6a80768d44ccc2107ce410c4e28c7147b382cd8f
9cf6c21f5adfac3732c76c1194bbe6a330fb83e3
fff2336bf8690fbfb2b4890a96549dc58bf548a5
1f7082f3f52880cb49bc37c40531fc478823b4f5
e9b317d36a9d1db88bd34831a32de327244df36a
f6ea0e7208cf22fba17952fb162a01afb26de806
137a681351037a2204f088a8d8f0db6e1f9179ca

Maak een Bash shell-script om elk van hen terug te zetten:

#!/bin/bash
cd /path/to/working/copy
for i in `cat ~/commits-to-revert.txt`
do
    git revert $i --no-commit
done

Hiermee wordt alles teruggezet naar de vorige staat, inclusief bestands- en mapcreaties en deleties, wordt dit vastgelegd in uw filiaal en behoudt u de geschiedenis, maar wordt deze teruggezet naar dezelfde bestandsstructuur. Waarom Git geen a heeft git revert --to <hash> is mij een raadsel.


51
2017-10-13 21:51



Extra alternatieven voor Jefromi's oplossingen

De oplossingen van Jefromi zijn absoluut de beste, en je moet ze zeker gebruiken. Voor de volledigheid wilde ik echter ook deze andere alternatieve oplossingen laten zien die ook kunnen worden gebruikt om een ​​commit terug te draaien (in de zin dat u maak een nieuwe commit die veranderingen in vorige commit ongedaan maakt, net zoals wat git revert doet).

Voor alle duidelijkheid, deze alternatieven zijn niet de beste manier om commits terug te draaien, De oplossingen van Jefromi zijn dat, maar ik wil er alleen op wijzen dat je deze andere methoden ook kunt gebruiken om hetzelfde te bereiken git revert.

Alternatief 1: Harde en zachte resets

Dit is een licht gewijzigde versie van de oplossing van Charles Bailey voor Terug naar een commit door een SHA-hash in Git?:

# Reset the index to the desired commit
git reset --hard <commit>

# Move the branch pointer back to the previous HEAD
git reset --soft HEAD@{1}

# Commit the changes
git commit -m "Revert to <commit>"

Dit werkt in feite door het feit te gebruiken dat zachte resets de status van de vorige commit geënsceneerd in het index / staging-gebied verlaten, die je vervolgens kunt vastleggen.

Alternatief 2: verwijder de huidige structuur en vervang deze door de nieuwe

Deze oplossing is afkomstig van de oplossing van svick voor Controleer oude commit en maak er een nieuwe commit van:

git rm -r .
git checkout <commit> .
git commit

Vergelijkbaar met alternatief # 1 reproduceert dit de status van <commit> in de huidige werkkopie. Het is noodzakelijk om te doen git rm eerst omdat git checkout zal bestanden die sindsdien zijn toegevoegd niet verwijderen <commit>.


48
2018-02-29 08:40