Kan ik een git-commit verwijderen maar de wijzigingen behouden?

In een van mijn ontwikkelingsafdelingen heb ik enkele wijzigingen aangebracht in mijn codebase. Voordat ik de features waar ik aan werkte kon voltooien, moest ik mijn huidige branch omschakelen naar master om een aantal features te demonstreren. Maar door gewoon een “git checkout master” te gebruiken, bleven de wijzigingen behouden die ik ook in mijn ontwikkelingsbranch had aangebracht, waardoor een deel van de functionaliteit in master werd verbroken. Dus wat ik deed, was de wijzigingen op mijn ontwikkelingstak vastleggen met een vastleggingsbericht “tijdelijke vastlegging” en vervolgens de master afrekenen voor de demo.

Nu ik klaar ben met de demo en weer aan het werk ben aan mijn ontwikkelingsbranch, wil ik de “tijdelijke commit” die ik heb gemaakt verwijderen, terwijl ik de wijzigingen die ik heb aangebracht behoudt. Is dat mogelijk?


Antwoord 1, autoriteit 100%

Het is zo simpel als dit:

git reset HEAD^

Opmerking: sommige shells behandelen ^als een speciaal teken (bijvoorbeeld sommige Windows-shells of ZSH met globbing ingeschakeld), dus in die gevallen moet u wellicht "HEAD^"citeren.

git resetzonder een --hardof --softverplaatst je HEADom naar de gespecificeerde commit, zonder bestanden te wijzigen. HEAD^verwijst naar de (eerste) parent-commit van je huidige commit, wat in jouw geval de commit is vóór de tijdelijke.

Merk op dat een andere optie is om gewoon door te gaan, en dan op het volgende vastleggingspunt in plaats daarvan uit te voeren:

git commit --amend [-m … etc]

die in plaats daarvan de meest recente commit bewerkt, met hetzelfde effect als hierboven.

Merk op dat dit (zoals bij bijna elk git-antwoord) problemen kan veroorzaken als je de slechte commit al naar een plek hebt gepusht waar iemand anders het vandaan heeft gehaald. Probeer dat te vermijden


Antwoord 2, autoriteit 11%

Er zijn twee manieren om dit aan te pakken. Wat gemakkelijker is, hangt af van uw situatie

Resetten

Als de commit die je kwijt wilt de laatste commit was, en je hebt geen extra werk gedaan, kun je gewoon git-reset

gebruiken

git reset HEAD^

Brengt je branch terug naar de commit net voor je huidige HEAD. Het verandert echter niet echt de bestanden in uw werkboom. Als gevolg hiervan worden de wijzigingen die in die commit waren, weergegeven als gewijzigd – het is als een ‘uncommit’-commando. In feite heb ik een alias om precies dat te doen.

git config --global alias.uncommit 'reset HEAD^'

Dan kun je in de toekomst gewoon git uncommitgebruiken om een back-up te maken van één commit.

Plakken

Het platdrukken van een commit betekent het combineren van twee of meer commits in één. Ik doe dit best vaak. In jouw geval heb je een half voltooide functie vastgelegd, en dan zou je het afmaken en opnieuw vastleggen met het juiste, permanente vastleggingsbericht.

git rebase -i <ref>

Ik zeg hierboven omdat ik duidelijk wil maken dat dit een willekeurig aantal commits kan zijn. Voer git loguit en zoek de commit die je wilt verwijderen, kopieer de SHA1 en gebruik deze in plaats van <ref>. Git brengt je naar de interactieve rebase-modus. Het toont alle commits tussen je huidige status en wat je ook in plaats van <ref>plaatst. Dus als <ref>10 commits geleden is, zal het je alle 10 commits tonen.

Voor elke commit staat het woord pick. Zoek de commit waar je vanaf wilt en verander deze van pickin fixupof squash. Door fixupte gebruiken, wordt dat commit-bericht gewoon weggegooid en worden de wijzigingen samengevoegd met zijn directe voorganger in de lijst. Het sleutelwoord squashdoet hetzelfde, maar stelt je in staat om het commit-bericht van de nieuw gecombineerde commit te bewerken.

Merk op dat de commits opnieuw worden vastgelegd in de volgorde waarin ze in de lijst verschijnen wanneer je de editor verlaat. Dus als je een tijdelijke commit hebt gemaakt, dan ander werk aan dezelfde branch hebt gedaan en de functie in een latere commit hebt voltooid, dan zou het gebruik van rebase je in staat stellen om de commits opnieuw te sorteren en ze te pletten.

WAARSCHUWING:

Rebasen wijzigt de geschiedenis – doe dit NIET met commits die je al met andere ontwikkelaars hebt gedeeld.

Opbergen

Om dit probleem in de toekomst te voorkomen, kunt u overwegen git stashte gebruiken om tijdelijk niet-toegewezen werk op te slaan.

git stash save 'some message'

Hiermee worden uw huidige wijzigingen aan de zijkant in uw stashlijst opgeslagen. Hierboven staat de meest expliciete versie van het stash-commando, waarbij een opmerking mogelijk is om te beschrijven wat u aan het opbergen bent. Je kunt ook gewoon git stashuitvoeren en niets anders, maar er wordt geen bericht opgeslagen.

Je kunt door je stashlijst bladeren met…

git stash list

Dit laat je al je stash zien, op welke takken ze zijn gedaan, en het bericht en aan het begin van elke regel, en de identifier voor die stash die er zo uitziet stash@{#}waarbij # zijn positie is in de reeks stashes.

Om een stash te herstellen (wat op elke branch kan worden gedaan, ongeacht waar de stash oorspronkelijk is gemaakt), voer je gewoon uit…

git stash apply stash@{#}

Nogmaals, daar is # de positie in de reeks van stashes. Als de stash die u wilt herstellen in de positie 0– dat wil zeggen, als het de meest recente stash was. Dan kunt u gewoon de opdracht uitvoeren zonder de stashpositie op te geven, Git neemt aan dat u de laatste bedoelt: git stash apply.

Dus, bijvoorbeeld als ik vind dat ik aan de verkeerde tak werkt – mag ik de volgende volgorde van opdrachten uitvoeren.

git stash
git checkout <correct_branch>
git stash apply

In uw geval bent u een beetje meer door takken verplaatst, maar hetzelfde idee is nog steeds van toepassing.

Ik hoop dat dit helpt.


Antwoord 3, Autoriteit 8%

Ik denk dat u dit zoekt

git reset --soft HEAD~1

Het maakt de meest recente commit ongedaan tijdens het houden van de veranderingen die in die commit op basis worden gemaakt.


Antwoord 4, Autoriteit 4%

Ja, u kunt uw commit verwijderen zonder de wijzigingen te verwijderen:

git reset @~

Antwoord 5, Autoriteit 2%

U bent op zoek naar een git reset HEAD^ --softof git reset HEAD^ --mixed.

Er zijn 3 modi naar de opdracht Reset zoals vermeld in de DOCS :

git reset HEAD^ --soft

Maak de git commitongedaan maken. Wijzigingen bestaan ​​nog steeds in de werkboom (de projectmap) + de index (- gesteld)

git reset HEAD^ --mixed

Ongedaan maken git commit+ git add. Veranderingen bestaan ​​nog steeds in de werkboom

git reset HEAD^ --hard

Zoals u deze wijzigingen nooit hebt aangebracht in de codebase. Veranderingen zijn verdwenen uit de werkboom.


Antwoord 6

2020 eenvoudige manier:

git reset <commit_hash>

(de plegen hash van de laatste commit die u wilt behouden).

Als de commit werd geduwd, kunt u dan doen:

git push -f

U bewaart de nu niet-gecommitteerde wijzigingen lokaal


Antwoord 7

In mijn geval duwde ik al naar de repo. Ouch!

U kunt een specifieke commit terugdraaien terwijl u de wijzigingen in uw lokale bestanden bewaart door:

git revert -n <sha>

Op deze manier was ik in staat om de veranderingen te behouden die ik nodig hadden en een commit die al was geduwd.


Antwoord 8

Voor degenen die ZSH gebruiken, moet u het volgende gebruiken:

git reset --soft HEAD\^

hier uitgelegd: https://github.com/robbyrussell/oh-my -zsh / problemen / 449

Indien de URL dood wordt, is het belangrijke deel:

Ontsnap aan de ^ in uw opdracht

U kunt alternatief kunnen gebruiken, zodat u er telkens niet hoeft te ontsnappen.


Antwoord 9

Git 2.9 (precies 2.9.2.Windows.1) gebruiken
git reset HEAD^aanwijzingen voor meer; Weet je niet zeker wat hier wordt verwacht. Raadpleeg hieronder screenshot

vond andere oplossing git reset HEAD~#numberOfCommitsGebruiken die we kunnen kiezen om het aantal lokale commits te selecteren dat u wilt resetten door uw wijzigingen intact te houden. Vandaar dat we een kans krijgen om alle lokale commits weg te gooien, evenals een beperkt aantal lokale commits.

Verwijs hieronder screenshots met git reset HEAD~1in actie:


Antwoord 10

Nog een manier om het te doen.

Voeg commit toe aan de bovenkant van tijdelijke commit en Doe dan:

git rebase -i

Om twee commits in één te samenvoegen (opdracht opent het tekstbestand met expliciete instructies, bewerkt het).


Antwoord 11

In sommige gevallen wil ik alleen de wijzigingen op specifieke bestanden ongedaan maken over de eerste commit om ze toe te voegen aan een tweede commit en een schoner git-logboek hebben.

In dit geval is wat ik doe het volgende:

git checkout HEAD~1 <path_to_file_to_put_in_different_commit>
git add -u
git commit --amend --no-edit
git checkout HEAD@{1} <path_to_file_to_put_in_different_commit>
git commit -m "This is the new commit"

Natuurlijk werkt dit goed, zelfs in het midden van een rebase -imet een bewerkingsoptie op de committeel om te splitsen.

Other episodes