Como corrigir o comprometimento com o ramo Git errado?

621

Acabei de me comprometer perfeitamente com o ramo errado. Como faço para desfazer o último commit no meu ramo principal e depois fazer essas mesmas alterações e colocá-las no meu ramo de atualização?

mikewilliamson
fonte

Respostas:

975

Se você ainda não enviou suas alterações, também pode fazer uma redefinição suave:

git reset --soft HEAD^

Isso reverterá a confirmação, mas colocará as alterações confirmadas novamente em seu índice. Supondo que as ramificações estejam relativamente atualizadas uma com a outra, o git permitirá que você faça uma verificação geral na outra ramificação, com a qual você pode simplesmente confirmar:

git checkout branch
git commit

A desvantagem é que você precisa digitar novamente sua mensagem de confirmação.

Blair Holloway
fonte
10
observe que a redefinição suave deixa suas alterações preparadas e prontas para confirmação. fiquei um pouco confuso quando meu IDE não mostrou que os arquivos retornam ao estado modificado após a reinicialização suave.
mtjhax
9
Perfect Fix, na verdade, tinha um par commits assim como CABEÇA ^^ e Bam tudo é gravy
pablo
8
Obrigado. Isso me salvou duas vezes. Se as ramificações forem um pouco diferentes, após a redefinição e antes da finalização da compra, você poderá ocultar suas alterações antes de finalizar a compra em outra ramificação. Reaplicar o estoque após a finalização da compra
Kirby
17
usuários do zsh: você pode achar que precisa escapar do ^ da seguinte maneira:git reset --soft HEAD\^
Stephen Fuhry 11/12/12
54
Se você receber mais? em sua linha de comando do Windows, use aspas para CABEÇA envolvente ^ assim: git reset --soft "CABEÇA ^"
Nate Cozinhe
141

4 anos atrasado sobre o assunto, mas isso pode ser útil para alguém.

Se você esqueceu de criar uma nova ramificação antes de confirmar e confirmar tudo no mestre, não importa quantas confirmações, a seguinte abordagem é mais fácil:

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

Agora você tem sua ramificação principal igual a origin/mastere todas as novas confirmações estão ativadas my_feature. Observe que my_featureé uma filial local, não remota.

fotanus
fonte
Obrigado pela resposta. Agora estou usando o egit e estou pensando se posso realizar a mesma coisa, fazendo o seguinte: 1) Renomeie o 'master' atual para 'my_feature'. 2) Recrie o 'mestre' local de 'origem / mestre'. Eu não tenho certeza do que está fazendo egit sob o capô para essas operações, mas esta parece ser uma solução viável
mjj1409
por que a fusão? você pode criar a ramificação diretamente mastere redefinir masterpara origin/master.
Caesarsol
1
Essa é a parte mais interessante: você não precisa de um número de confirmação, porque origin/masterjá está no commit que deseja redefinir! O crédito para a ponta é no entanto esta página: github.com/blog/...
caesarsol
4
Essa deve ser a resposta aceita. Simples, óbvio, direto, funciona independentemente do número de confirmações e usando apenas a funcionalidade básica do Git. Eu fiz estes passos com o TortoiseGit. Obrigado! :)
Ian Grainger
1
Eu pensei que essa era a melhor resposta, mas tem uma limitação. Só ajuda se você retirou recentemente do controle remoto. E assume que você tem um controle remoto para começar. Se você tiver apenas ramificações locais "mestre" e seu novo recurso for corrigido, a única resposta certa é uma redefinição definitiva no mestre, contando um certo número de confirmações.
pauljohn32
111

Se você possui uma cópia de trabalho limpa (não modificada)

Para reverter uma confirmação (verifique o hash da confirmação na próxima etapa):

git reset --hard HEAD^

Para puxar esse commit para um ramo diferente:

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

Se você modificou ou não as alterações

Observe também que as alterações não rastreadas e modificadasgit reset --hard serão eliminadas , por isso, se você tiver as que preferir:

git reset HEAD^
git checkout .
Michael Mrozek
fonte
git rev-parse BRANCH_NAMEpara pegar o sha.
Wilhelmtell
12
Se você esquecer de observar o hash primeiro, basta usar git reflog show <branch>!
Cascabel
2
@ Jeffromi, fiquei com medo por um minuto.
Ian Hunter
13
Para uma sensação extra segura, faça primeiro a coleta de cereja no galho correto e só depois redefina o galho errado.
Age Mooij
1
Também em caso de alterações untracked, uma lata git stashantes da reinicialização e uso git stash popdepois de restaurá-los, por isso não há necessidade de ter medo da --hardparte
Clemens Klein-Robbenhaar
20

Se você já enviou suas alterações, precisará forçar seu próximo envio após redefinir o HEAD.

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

Aviso: uma redefinição física desfaz todas as modificações não confirmadas em sua cópia de trabalho, enquanto um push forçado substitui completamente o estado da ramificação remota pelo estado atual da ramificação local.

Apenas no caso (no Windows (usando a linha de comando do Windows, não o Bash), na verdade são quatro em ^^^^vez de um, então é

git reset --hard HEAD^^^^
Igor Zevaka
fonte
6
Observe que você não deve forçar push a um ramo que outras pessoas estejam usando, a menos que seja absolutamente necessário - caso contrário, eles não poderão fazer push até que se recuperem. Se você é o único desenvolvedor usando git, no entanto, tudo bem.
Blair Holloway
2
Ou, a menos que você perceba com rapidez suficiente antes que alguém faça os commit errados.
Michael Mior
Se houver mais de uma confirmação, você poderá especificar a confirmação de que precisa: git reset --hard COMMIT_HASH git push --force
David Cramblett
17

Recentemente, fiz o mesmo, onde acidentalmente cometi uma mudança de mestre, quando deveria ter me comprometido com outro ramo. Mas eu não forcei nada.

Se você acabou de se comprometer com a ramificação errada e não mudou nada desde então, e não enviou o repositório ao repositório, você pode fazer o seguinte:

// 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: no exemplo acima, eu estava rebobinando 1 commit com git reset HEAD ~ 1. Mas se você quiser retroceder n commits, poderá fazer o git reset HEAD ~ n.

Além disso, se você acabou se comprometendo com a ramificação errada e também acabou escrevendo um pouco mais de código antes de perceber que se comprometeu com a ramificação errada, você pode usar o git stash para salvar seu trabalho em andamento:

// 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: Eu usei este site como referência https://www.clearvision-cm.com/blog/what-to-do-when-you-commit-to-the-wrong-git-branch/

Ali Mizan
fonte
Aconteceu algo semelhante comigo, cometeu algumas alterações no master, mas deveria ter feito em uma nova ramificação e enviar PR, acabei fazendo apenas a git checkout -b new_branchpartir daí, os commits estavam intactos, apenas foram pressionados e criaram um PR, não ' Não precisa se comprometer novamente.
Nishchal Gautam
11

Portanto, se o seu cenário é que você se comprometeu, mastermas pretende se comprometer another-branch(que pode ou não já não existir), mas ainda não o fez, isso é muito fácil de corrigir.

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

Agora todos os seus compromissos masterestarão ativados another-branch.

Originado com amor em: http://haacked.com/archive/2015/06/06/git-migrate/

Lorcan O'Neill
fonte
parece ser a abordagem mais direta! Não sei por que tão pouco amor e upwotes
keligijus
4
Isso não pareceu funcionar para mim. another-branchjá existia. Nesse caso, apenas anulou os commits que fiz para dominar e não os colocou another-branch.
Giselle Serate
6

Para elaborar esta resposta, caso você tenha vários commits para mudar, por exemplo, developpara 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
arsênio
fonte
1
Eu tinha três compromissos para reverter, e essa pergunta parece ter me tirado do fogo. Obrigado!
holdenweb
3

Se você enfrentar esse problema e tiver o Visual Studio, poderá fazer o seguinte:

Clique com o botão direito do mouse em sua filial e selecione View History:

insira a descrição da imagem aqui

Clique com o botão direito do mouse em confirmar para o qual deseja voltar. E reverter ou redefinir, conforme necessário.

insira a descrição da imagem aqui

Trevor
fonte
3

Para várias confirmações no ramo errado

Se, para você, é apenas uma confirmação, existem muitas outras soluções de redefinição mais fáceis disponíveis. Para mim, tive cerca de 10 confirmações feitas acidentalmente em mastervez de, vamos chamá-lo branch_xyz, e não queria perder o histórico de confirmação.

O que você poderia fazer e o que me salvou estava usando esta resposta como referência, usando um processo de 4 etapas, que é -

  1. Crie uma nova ramificação temporária a partir de master
  2. Mesclar no ramo originalmente destinado a confirmações, ou seja, branch_xyz
  3. Desfazer confirmações em master
  4. Exclua a ramificação temporária.

Aqui estão as etapas acima em detalhes -

  1. Crie uma nova ramificação a partir de master(onde acidentalmente cometi muitas alterações)

    git checkout -b temp_branch_xyz
    

    Nota: -bflag é usado para criar uma nova ramificação
    Apenas para verificar se acertamos, eu faria uma rápida git branchpara garantir que estamos na temp_branch_xyzramificação e uma git logpara verificar se acertamos os commits.

  2. Mesclar a ramificação temporária na ramificação originalmente destinada às confirmações, ou seja branch_xyz.
    Primeiro, mude para a ramificação original, ou seja branch_xyz(você pode precisar git fetchse não tiver)

    git checkout branch_xyz
    

    Nota: Não usando -bsinalizador
    Agora, vamos mesclar a ramificação temporária na ramificação que atualmente efetuamos checkoutbranch_xyz

    git merge temp_branch_xyz
    

    Talvez você precise resolver alguns conflitos aqui, se houver. Você pode pressionar (eu faria) ou seguir para as próximas etapas, depois de mesclar com êxito.

  3. Desfazer o acidental compromete-se a masterusar esta resposta como referência, primeiro mude para omaster

    git checkout master
    

    desfaça-o de volta para corresponder ao controle remoto (ou a um commit específico, se você quiser)

    git reset --hard origin/master
    

    Novamente, eu faria o git logantes e o depois apenas para garantir que as alterações pretendidas entrassem em vigor.

  4. Apagando as evidências, isso está excluindo a ramificação temporária. Para isso, primeiro você precisa fazer check-out do ramo no qual a temperatura foi mesclada, ou seja, branch_xyz(se você permanecer masterativado e executar o comando abaixo, poderá obter um error: The branch 'temp_branch_xyz' is not fully merged), então vamos

    git checkout branch_xyz
    

    e exclua a prova desse acidente

    git branch -d temp_branch_xyz
    

Ai está.

Mitali Cyrus
fonte
1

Se o ramo ao qual você deseja aplicar suas alterações já existe ( desenvolvimento do ramo , por exemplo), siga as instruções fornecidas pelo fotanus abaixo e:

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, obviamente, você pode usar tempbranch ou qualquer outro nome de filial em vez de my_feature, se desejar.

Além disso, se aplicável, adie o pop-stash (aplicar) até depois da mesclagem no ramo de destino.

fbicknel
fonte
Eu acho que o primeiro comando (desenvolvimento de checkout) é desnecessário ... o rebase fará checkout de "my_feature" como a primeira coisa que ele faz.
JoelFan
Além disso, você pode deixar de fora o parâmetro "my_feature" do comando "rebase" (já que você já fez check-out de "my_feature"). você também pode deixar de fora o parâmetro "develop" da "mesclagem" (uma vez que você já fez check-out de "develop") #
911 JoelFan
1

Para mim, isso foi resolvido revertendo o commit que eu havia enviado e, em seguida, escolhendo o commit para o outro 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

Você pode usar git logpara encontrar o hash correto e enviar essas alterações sempre que quiser!

arr0nax
fonte