Come risolvere il commit nel ramo Git sbagliato?


621

Ho appena preso un impegno perfetto per il ramo sbagliato. Come posso annullare l'ultimo commit nel mio ramo master e quindi prendere le stesse modifiche e inserirle nel mio ramo di aggiornamento?

Risposte:


975

Se non hai ancora inviato le modifiche, puoi anche eseguire un ripristino software:

git reset --soft HEAD^

Questo ripristinerà il commit, ma rimetterà le modifiche impegnate nel tuo indice. Supponendo che le filiali siano relativamente aggiornate l'una rispetto all'altra, git ti consentirà di effettuare un checkout nell'altra filiale, dopodiché puoi semplicemente impegnarti:

git checkout branch
git commit

Lo svantaggio è che è necessario reinserire il messaggio di commit.


10
notare che il soft reset lascia le modifiche in scena e pronte per il commit. mi ha fatto un po 'confuso quando il mio IDE non ha mostrato che i file tornano allo stato modificato dopo il soft reset.
mtjhax,

9
soluzione perfetta, in realtà un paio si è impegnato, così ha fatto HEAD ^^ e bam è tutto sugo
pablo

8
Grazie. Questo mi ha salvato due volte. Se i rami sono in qualche modo diversi, dopo il ripristino e prima del checkout potresti dover riporre le modifiche prima di poter effettuare il checkout di un altro ramo. Riapplica la scorta dopo il checkout
Kirby,

17
Utenti zsh: potresti scoprire che devi scappare dal ^ in questo modo:git reset --soft HEAD\^
Stephen Fuhry,

54
Se ottieni un altro? nella riga di comando di Windows, usa le virgolette per circondare HEAD ^ in questo modo: git reset --soft "HEAD ^"
Nate Cook

142

4 anni di ritardo sull'argomento, ma questo potrebbe essere utile a qualcuno.

Se hai dimenticato di creare una nuova filiale prima di eseguire il commit e il commit di tutti i master, indipendentemente da quanti commit hai eseguito, il seguente approccio è più semplice:

git stash                       # skip if all changes are committed
git branch my_feature
git reset --hard origin/master
git checkout my_feature
git stash pop                   # skip if all changes were committed

Ora hai il tuo ramo principale uguale a origin/mastere tutti i nuovi commit sono attivi my_feature. Si noti che my_featureè un ramo locale, non remoto.


Grazie per la risposta. Ora sto usando egit e mi chiedo se posso ottenere la stessa cosa facendo quanto segue: 1) Rinomina l'attuale "master" in "my_feature". 2) Ricreare "master" locale da "origin / master". Non sono sicuro di cosa stia facendo l'egit per queste operazioni, ma questa sembra essere una soluzione praticabile
mjj1409

perché l'unione? è possibile creare il ramo direttamente master, quindi azzerare mastera origin/master.
Caesarsol,

1
Questa è la parte più interessante: non è necessario un numero di commit, perché origin/masterè già sul commit che si desidera ripristinare! Il merito del suggerimento è tuttavia questa pagina: github.com/blog/…
caesarsol,

4
Questa dovrebbe essere la risposta accettata. Semplice, ovvio, diretto, funziona indipendentemente dal numero di commit e utilizza solo la funzionalità Git di base. Ho fatto questi passaggi con TortoiseGit. Grazie! :)
Ian Grainger,

1
Ho pensato che questa fosse la risposta migliore, ma ha un limite. Aiuta solo se hai recentemente estratto dal telecomando. E si presume che tu abbia un telecomando per cominciare. Se hai solo le filiali locali "master" e la tua nuova correzione di funzionalità, l'unica risposta corretta è un hard reset sul master che conta un certo numero di commit.
pauljohn32

111

Se si dispone di una copia di lavoro pulita (non modificata)

Per ripristinare un commit (assicurati di annotare l'hash del commit per il passaggio successivo):

git reset --hard HEAD^

Per inserire quel commit in un altro ramo:

git checkout other-branch
git cherry-pick COMMIT-HASH

Se sono state apportate modifiche non modificate

Nota inoltre che git reset --hardverranno eliminate tutte le modifiche non monitorate e modificate che potresti avere, quindi se ne hai di quelle che preferisci:

git reset HEAD^
git checkout .

git rev-parse BRANCH_NAMEper ottenere lo sha.
Wilhelmtell,

12
Se dimentichi di annotare prima l'hash, basta usare git reflog show <branch>!
Cascabel,

2
@Jefromi Sono stato spaventato lì per un minuto.
Ian Hunter,

13
Per una sensazione ancora più sicura, esegui prima il cherry-pick sul ramo corretto e solo successivamente resetta il ramo sbagliato.
Età Mooij,

1
Anche in caso di modifiche non tracciate, è possibile git stashprima di ripristinare e utilizzare git stash popsuccessivamente per ripristinarle, quindi non è necessario aver paura della --hardparte
Clemens Klein-Robbenhaar,

20

Se hai già spinto le tue modifiche, dovrai forzare la tua prossima spinta dopo aver ripristinato HEAD.

git reset --hard HEAD^
git merge COMMIT_SHA1
git push --force

Avviso: un hard reset annullerà tutte le modifiche non confermate nella copia di lavoro, mentre un push forzato sovrascriverà completamente lo stato del ramo remoto con lo stato corrente del ramo locale.

Per ogni evenienza, su Windows (utilizzando la riga di comando di Windows, non Bash) in realtà sono quattro ^^^^anziché uno, quindi lo è

git reset --hard HEAD^^^^

6
Si noti che si dovrebbe non forzare-push per un ramo che altre persone stanno usando se non assolutamente necessario - altrimenti non saranno in grado di spingere fino a quando non aggiustano. Se sei l'unico sviluppatore che utilizza git, tuttavia, va bene.
Blair Holloway,

2
O a meno che non ti rendi conto abbastanza rapidamente prima che qualcun altro abbia eseguito gli errori.
Michael Mior,

Se hai commesso più di un commit, puoi specificare il commit di cui hai bisogno: git reset --hard COMMIT_HASH git push --force
David Cramblett,

17

Di recente ho fatto la stessa cosa, in cui ho commesso accidentalmente una modifica al master, quando avrei dovuto impegnarmi in un'altra filiale. Ma non ho spinto nulla.

Se ti sei appena impegnato nel ramo sbagliato e da allora non hai cambiato nulla e non hai inviato il repository, puoi eseguire le seguenti operazioni:

// rewind master to point to the commit just before your most recent commit.
// this takes all changes in your most recent commit, and turns them into unstaged changes. 
git reset HEAD~1 

// temporarily save your unstaged changes as a commit that's not attached to any branch using git stash
// all temporary commits created with git stash are put into a stack of temporary commits.
git stash

// create other-branch (if the other branch doesn't already exist)
git branch other-branch

// checkout the other branch you should have committed to.
git checkout other-branch

// take the temporary commit you created, and apply all of those changes to the new branch. 
//This also deletes the temporary commit from the stack of temp commits.
git stash pop

// add the changes you want with git add...

// re-commit your changes onto other-branch
git commit -m "some message..."

NOTA: nell'esempio sopra, stavo riavvolgendo 1 commit con git reset HEAD ~ 1. Ma se vuoi riavvolgere n commit, allora puoi fare git reset HEAD ~ n.

Inoltre, se hai finito per impegnarti nel ramo sbagliato, e hai anche finito per scrivere un po 'di codice prima di capire che ti sei impegnato nel ramo sbagliato, allora potresti usare git stash per salvare il tuo lavoro in corso:

// save the not-ready-to-commit work you're in the middle of
git stash 

// rewind n commits
git reset HEAD~n 

// stash the committed changes as a single temp commit onto the stack. 
git stash 

// create other-branch (if it doesn't already exist)
git branch other-branch

// checkout the other branch you should have committed to.
git checkout other-branch

// apply all the committed changes to the new branch
git stash pop

// add the changes you want with git add...

// re-commit your changes onto the new branch as a single commit.
git commit -m "some message..."

// pop the changes you were in the middle of and continue coding
git stash pop

NOTA: ho usato questo sito Web come riferimento https://www.clearvision-cm.com/blog/what-to-do-when-you-commit-to-the-wrong-git-branch/


Mi è successa una cosa simile, ho commesso alcune modifiche in master, ma avrei dovuto farlo in una nuova filiale e inviare PR, ho finito per fare proprio un git checkout -b new_branchdiritto da lì, gli impegni erano intatti, appena spinto e creato un PR, non è successo devo impegnarmi di nuovo.
Nishchal Gautam,

11

Quindi, se il tuo scenario è quello in cui ti sei impegnato masterma intendi impegnarti another-branch(che potrebbe non esistere già) ma che non hai ancora spinto, questo è abbastanza facile da risolvere.

// if your branch doesn't exist, then add the -b argument 
git checkout -b another-branch
git branch --force master origin/master

Ora tutti i tuoi impegni mastersaranno attivi another-branch.

Provenienti con amore da: http://haacked.com/archive/2015/06/29/git-migrate/


sembra essere l'approccio più diretto! Non sono sicuro del motivo per cui così poco amore e voti positivi
Keligijus,

4
Questo non sembra funzionare per me. another-branchesisteva già. In questo caso, ha semplicemente rovinato gli impegni che avevo fatto per padroneggiare e non li ha messi su another-branch.
Giselle Serate,

6

Per approfondire questo risposta, nel caso in cui si dispone di più impegna per spostarsi da, ad esempio, developa new_branch:

git checkout develop # You're probably there already
git reflog # Find LAST_GOOD, FIRST_NEW, LAST_NEW hashes
git checkout new_branch
git cherry-pick FIRST_NEW^..LAST_NEW # ^.. includes FIRST_NEW
git reflog # Confirm that your commits are safely home in their new branch!
git checkout develop
git reset --hard LAST_GOOD # develop is now back where it started

1
Ho avuto tre impegni da ripristinare, e questa domanda sembra aver tirato fuori il culo dal fuoco. Grazie!
holdenweb,

3

Se si verifica questo problema e si dispone di Visual Studio, è possibile effettuare le seguenti operazioni:

Fai clic con il tasto destro del mouse sul tuo ramo e seleziona View History:

inserisci qui la descrizione dell'immagine

Fare clic con il tasto destro del mouse su commit a cui si desidera tornare. E ripristina o ripristina secondo necessità.

inserisci qui la descrizione dell'immagine


3

Per più commit sul ramo sbagliato

Se per te è solo 1 commit, allora ci sono molte altre soluzioni di reimpostazione più facili disponibili. Per me, ho eseguito circa 10 commit per errore masterinvece di, chiamiamolo branch_xyz, e non volevo perdere la cronologia dei commit.

Quello che potresti fare e ciò che mi ha salvato è stato usare questa risposta come riferimento, usando un processo in 4 fasi, che è -

  1. Crea un nuovo ramo temporaneo da master
  2. Unisciti alla filiale originariamente destinata agli commit, ad es branch_xyz
  3. Annulla si impegna master
  4. Elimina il ramo temporaneo.

Ecco i passaggi precedenti in dettaglio -

  1. Crea una nuova filiale da master(dove avevo accidentalmente apportato molte modifiche)

    git checkout -b temp_branch_xyz
    

    Nota: -bflag viene utilizzato per creare una nuova filiale
    Solo per verificare se abbiamo ottenuto questo diritto, farei un rapido git branchper assicurarmi di essere nella temp_branch_xyzfiliale e un git logper verificare se abbiamo eseguito correttamente i commit.

  2. Unire il ramo temporaneo nel ramo originariamente destinato agli commit, ad es branch_xyz.
    Innanzitutto, passa al ramo originale branch_xyz(ad esempio, git fetchpotresti non averlo fatto)

    git checkout branch_xyz
    

    Nota: non usare -bflag
    Ora, uniamo il ramo temporaneo nel ramo che stiamo attualmente verificandobranch_xyz

    git merge temp_branch_xyz
    

    Potresti doverti occupare di alcuni conflitti qui, se ce ne sono. Puoi spingere (lo farei) o passare ai passaggi successivi, dopo aver eseguito correttamente l'unione.

  3. Annulla l'impegno accidentale masterutilizzando questa risposta come riferimento, per prima cosa passa amaster

    git checkout master
    

    quindi annullare tutto indietro per abbinare il telecomando (o per eseguire il commit particolare, se lo si desidera)

    git reset --hard origin/master
    

    Ancora una volta, farei un git logprima e un dopo solo per assicurarmi che le modifiche previste abbiano avuto effetto.

  4. Cancellare l'evidenza, che sta eliminando il ramo temporaneo. Per questo, prima devi controllare il ramo in cui è stata unita la temp, ovvero branch_xyz(se rimani masterattivo ed esegui il comando qui sotto, potresti ottenere un error: The branch 'temp_branch_xyz' is not fully merged), quindi cerchiamo di

    git checkout branch_xyz
    

    e quindi eliminare la prova di questo incidente

    git branch -d temp_branch_xyz
    

Ecco qua


1

Se il ramo a cui desideri applicare le modifiche esiste già ( sviluppo ramo , ad esempio), segui le istruzioni fornite da fotanus di seguito, quindi:

git checkout develop
git rebase develop my_feature # applies changes to correct branch
git checkout develop # 'cuz rebasing will leave you on my_feature
git merge develop my_feature # will be a fast-forward
git branch -d my_feature

E ovviamente potresti usare tempbranch o qualsiasi altro nome di filiale invece di my_feature se lo desideri.

Inoltre, se applicabile, ritarda il pop stash (applica) fino a quando non ti sei unito al ramo di destinazione.


Penso che il primo comando (sviluppo del checkout) non sia necessario ... il rebase eseguirà il checkout di "my_feature" come prima cosa che fa.
JoelFan,

Inoltre puoi tralasciare il parametro "my_feature" del comando "rebase" (poiché hai già estratto "my_feature"). puoi anche tralasciare il parametro "sviluppo" di "unione" (dato che hai già estratto "sviluppo")
JoelFan

1

Per me, questo è stato risolto ripristinando il commit che avevo spinto, quindi selezionando ciliegie quel commit sull'altro ramo.

git checkout branch_that_had_the_commit_originally
git revert COMMIT-HASH
git checkout branch_that_was_supposed_to_have_the_commit
git cherry pick COMMIT-HASH

Puoi usare git logper trovare l'hash corretto e puoi spingere queste modifiche quando vuoi!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.