Como forço corretamente um push do Git?

1274

Configurei um repositório "principal" remoto e não clonado e o clonei no meu computador. Fiz algumas alterações locais, atualizei meu repositório local e enviei as alterações de volta ao repositório remoto. As coisas estavam bem até esse ponto.

Agora, tive que mudar alguma coisa no repositório remoto. Então mudei algo no meu repositório local. Percebi que a alteração no repositório remoto não era necessária. Então, tentei git pushdo meu repositório local para o meu repositório remoto, mas recebi um erro como:

Para impedir que você perca o histórico, as atualizações de avanço rápido não foram rejeitadas Mesclar as alterações remotas antes de enviar novamente. Consulte a seção "Observação sobre avanço rápido" git push --helppara obter detalhes.

Eu pensei que provavelmente um

git push --force

forçaria minha cópia local a enviar alterações para a remota e torná-la a mesma. Força a atualização , mas quando eu volto ao repositório remoto e faço uma confirmação, percebo que os arquivos contêm alterações desatualizadas (que o repositório remoto principal tinha anteriormente).

Como mencionei nos comentários a uma das respostas :

[I] tentei forçar, mas, ao voltar ao servidor mestre para salvar as alterações, fico com a preparação desatualizada. Assim, quando eu comprometo os repositórios não são os mesmos. E quando tento usar o git push novamente, recebo o mesmo erro.

Como posso corrigir esse problema?

Spyros
fonte
4
Em breve (git1.8.5, quarto trimestre de 2013), você poderá fazer umgit push -force procedimento com mais cuidado .
VonC 10/09/13
6
Como detalho em minha própria resposta , git push --forceé de fato outra maneira válida de forçar push, e empurrará ramificações da mesma forma que git push origin master --forcecom o padrão do Git push.default config settings, embora quais ramificações forçadas especificamente sejam diferentes das versões do Git antes da versão 2.0 e depois da 2.0.
2
git push --forcefunciona bem nos dias de hoje, FWIW ...
rogerdpack
git push --force-with-leasefunciona ainda melhor :), ele se recusará a atualizar um ramo, a menos que seja o estado que você espera. (consulte developer.atlassian.com/blog/2015/04/force-with-lease )
spoorcc 14/01/19

Respostas:

2309

Apenas faça:

git push origin <your_branch_name> --force

ou se você tiver um repositório específico:

git push https://git.... --force

Isso excluirá o (s) seu (s) commit (s) anterior (es) e enviará o seu atual.

Pode não ser adequado, mas se alguém deparar com esta página, pensou que poderia querer uma solução simples ...

Bandeira curta

Observe também que -fé abreviação de --force, então

git push origin <your_branch_name> -f

também irá funcionar.

Katie
fonte
58
Em git push origin +mastervez disso, você pode usar , o que permite enviar vários refspecs sem forçar todos eles.
nickgrim
5
Esteja ciente de que, se você acidentalmente basta git push --force, você pode acabar atrapalhando você branch master (dependendo do seu comportamento padrão push) .. Que pode chupar .. um pouco ..: D
Jeewes
9
@Jeewes, começando com o Git versão 2.0, o comportamento padrãogit push --force é basicamente forçar o envio da ramificação atualmente em check-out para a parte do contador remoto; portanto, se você tiver a ramificação principal em check-out, será idêntica git push origin master --force. Será diferente se você estiver usando a matchingconfiguração para push.default, que é o padrão para as versões do Git anteriores à 2.0. matchingempurra todos os habitantes locais ramos para as remotas que têm o mesmo nome, então força empurrando, então definitivamente poderia não ser o que você quer fazer ...
@ Jeewes Mas com o Git 2.0, o padrão é mais seguro, ou pelo menos não é mais perigoso do que git push origin master --forceé.
2
push -f é bom, mas não é recomendado para o mestre, pois a maioria dos repositórios corporativos -f desabilitou para o mestre. o merge -s oursfuncionou para mim
mihai
247

E se push --forcenão funcionar, você pode fazer push --delete. Olhe para 2 nd linha nesta instância:

git reset --hard HEAD~3  # reset current branch to 3 commits ago
git push origin master --delete  # do a very very bad bad thing
git push origin master  # regular push

Mas cuidado...

Nunca mais volte para uma história pública de git!

Em outras palavras:

  • Nunca forceforce um repositório público.
  • Não faça isso ou qualquer coisa que possa quebrar a de alguém pull.
  • Nunca resetou a rewritehistória em um repo alguém já pode ter puxado.

É claro que existem exceções excepcionalmente raras até mesmo para essa regra, mas na maioria dos casos não é necessário fazer isso e isso gerará problemas para todos os outros.

Faça uma reversão.

E sempre tenha cuidado com o que você envia a um repositório público . Revertendo:

git revert -n HEAD~3..HEAD  # prepare a new commit reverting last 3 commits
git commit -m "sorry - revert last 3 commits because I was not careful"
git push origin master  # regular push

Com efeito, os dois HEADs de origem (da reversão e da reinicialização incorreta ) conterão os mesmos arquivos.


edite para adicionar informações atualizadas e mais argumentos push --force

Considere empurrar força com concessão em vez de empurrar, mas ainda prefere reverter

Outro problema push --forcepode trazer é quando alguém pressiona alguma coisa antes de você, mas depois que você já buscou. Se você pressionar forçar sua versão rebaseada agora, substituirá o trabalho de outras pessoas .

git push --force-with-leaseintroduzido no git 1.8.5 ( graças ao comentário do @VonC sobre a pergunta) tenta resolver esse problema específico. Basicamente, ele trará um erro e não será enviado se o controle remoto tiver sido modificado desde a última busca.

Isso é bom se você realmente tem certeza de que push --forceé necessário, mas ainda deseja evitar mais problemas. Eu diria que deveria ser o push --forcecomportamento padrão . Mas ainda está longe de ser uma desculpa para forçar a push. As pessoas que buscaram antes da sua recuperação ainda terão muitos problemas, que poderiam ser facilmente evitados se você revertesse .

E já que estamos falando de git --pushinstâncias ...

Por que alguém iria querer forçar a pressão?

O @linquize trouxe um bom exemplo de força de pressão nos comentários: dados confidenciais . Você vazou erroneamente dados que não devem ser enviados. Se você for rápido o suficiente, poderá "consertá-* lo " forçando um empurrão no topo.

*Os dados ainda estarão no controle remoto, a menos que você também faça uma coleta de lixo ou limpe-a de alguma forma . Há também o potencial óbvio de que ele seja espalhado por outras pessoas que já o buscaram , mas você entendeu.

cregox
fonte
1
O problema, @rogerdpack, não é realizável. Isto é. Mas pode ser um grande desastre. Quanto mais alguém faz isso (forçar push) e com menos frequência você atualiza (puxa) a partir do repositório público, maior o desastre. Ele pode desmantelar o mundo como você o conhece !!! 111 Pelo menos o mundo que compreende esse repositório específico.
Cregox # 24/13
3
Se você tiver dados sigilosos, force forçá-lo
linquize
3
@ Cayas: Eu acho que ele quer dizer que se você está tentando remover dados confidenciais do repositório, deseja reescrever o histórico. Se você reverter, os dados confidenciais ainda estarão lá na confirmação anterior. Dito isto, se alguém já tiver retirado do repositório, a reescrita do histórico não ajudará a impedir que eles acessem os dados confidenciais - já é tarde demais nesse momento.
Stuart Golodetz
3
git push origin master --delete # do a very very bad bad thing git push origin master # regular pushisso realmente resolveu meu problema perfeitamente (em um repositório apenas comigo e com meu amigo). talvez seja errado para compromissos públicos, mas para um privado isso salva vidas.
Can Poyrazoğlu
1
isso acontece automaticamente com alguns gerentes de repo, também conhecido como empolhamento automático, etc., após o término de um ramo de recurso para reduzir confirmações é comum e esperado.
FlavorScape 11/01/19
18

Primeiro de tudo, eu não faria nenhuma alteração diretamente no repositório "principal". Se você realmente deseja ter um repositório "principal", deve empurrá-lo apenas, nunca alterá-lo diretamente.

Com relação ao erro que você está recebendo, você tentou git pullno repositório local e depois git pushno repositório principal? O que você está fazendo no momento (se eu entendi bem) é forçar o empurrão e depois perder as alterações no repositório "principal". Você deve mesclar as alterações localmente primeiro.

ubik
fonte
Sim, tentei puxar, mas estou perdendo a perda de dados por causa desse puxão. Quero fazer meus principais repositórios como meu local, sem primeiro atualizar a partir do principal.
Spyros
1
Nesse caso git push -f, use , mas se você alterar seu repositório principal novamente, precisará voltar ao repositório local e git pull, para que fique sincronizado com as alterações mais recentes. Então você pode fazer seu trabalho e pressionar novamente. Se você seguir esse fluxo de trabalho "push-pull", não receberá o tipo de erro que estava reclamando.
fácil
Sim, eu entendo que isso foi minha culpa: / eu vou tentar isso e voltar em pouco tempo thanx
Spyros
1
tentei forçar, mas, ao voltar ao servidor mestre para salvar as alterações, eu recebo um teste desatualizado. Assim, quando eu comprometo os repositórios não são os mesmos. E quando tento usar o git push novamente, recebo o mesmo erro.
Spyros
17

Se eu estiver no meu ramo local A e desejar forçar o envio do ramo local B para o IC do ramo de origem, use a seguinte sintaxe:

git push --force origin B:C
IcedDante
fonte
2
Eu descobri que mesmo eu estou no meu ramo local B, eu ainda preciso fazer git push --force origin B:C. No meu caso, parece que isso git push --force origin Cpassará apenas do mestre local para o ramo C remoto, independentemente de qual ramo eu esteja atualmente. git version 2.3.8 (Apple Git-58)
Weishi Zeng 10/10
12

use este comando a seguir:

git push -f origin master
mustafa Elsayed
fonte
1
Talvez dê mais explicações sobre por que essa resposta é preferível às outras e o que a diferencia.
Adam
ah, desculpe pelo transtorno, estava com o mesmo problema e esse comando resolveu, achei que deveria compartilhar.
Mustafa Elsayed
12
É exatamente o mesmo que os outros, você acabou de alterar a posição da -fbandeira ...
svelandiag
11

Eu realmente recomendo:

  • enviar apenas para o repositório principal

  • verifique se o repositório principal é um repositório simples , para nunca ter nenhum problema com a árvore de trabalho do repositório principal não estar sincronizada com sua .gitbase. Consulte " Como enviar um repositório git local para outro computador? "

  • Se você precisar fazer uma modificação no repositório principal (vazio), clone-o (no servidor principal), faça sua modificação e retorne a ele

Em outras palavras, mantenha um repositório simples acessível a partir do servidor principal e do computador local, a fim de ter um único repositório upstream do / para o qual extrair / extrair.

VonC
fonte
5

Esta foi a nossa solução para substituir o mestre em um repositório corporativo do gitHub, mantendo o histórico.

push -fdominar repositórios corporativos geralmente é desativado para manter o histórico da filial. Esta solução funcionou para nós.

git fetch desiredOrigin
git checkout -b master desiredOrigin/master // get origin master

git checkout currentBranch  // move to target branch
git merge -s ours master  // merge using ours over master
// vim will open for the commit message
git checkout master  // move to master
git merge currentBranch  // merge resolved changes into master

empurre sua filial desiredOrigine crie um PR

mihai
fonte
3

Eu tinha a mesma pergunta, mas finalmente entendi. O que você provavelmente precisa fazer é executar os dois comandos git a seguir (substituindo o hash pelo número de revisão de confirmação git):

git checkout <hash>
git push -f HEAD:master
Brian M.
fonte