Force o "git push" para substituir arquivos remotos

768

Quero enviar meus arquivos locais e tê-los em um repositório remoto, sem precisar lidar com conflitos de mesclagem. Eu só quero que minha versão local tenha prioridade sobre a remota.

Como posso fazer isso com o Git?

opensas
fonte
106
Não git push origin --forcefuncionou para você?
Não está claro se você deseja substituir apenas os arquivos .git ou a cópia de trabalho associada. Se for o repositório git, git push é a resposta. Se você deseja atualizar a cópia de trabalho remoto, você tem que usar um post-receive gancho
Pierre-Olivier Vares
@ Mike que funciona para mim por alguma razão ... maravilha o que estava acontecendo com o OP
Uma causa provável: o push de força não funciona é que ele pode ter sido explicitamente desativado no repositório remoto (para garantir que nada seja perdido devido a contribuidores idiotas e / ou malignos): use config receive.denyNonFastforwardspara descobrir.
precisa

Respostas:

1088

Você deve poder forçar sua revisão local ao repositório remoto usando

git push -f <remote> <branch>

(por exemplo git push -f origin master). Sair <remote>e <branch>forçará o envio de todos os ramos locais que foram definidos --set-upstream.

Apenas esteja avisado, se outras pessoas estiverem compartilhando este repositório, o histórico de revisões entrará em conflito com o novo. E se eles tiverem confirmações locais após o ponto de mudança, elas se tornarão inválidas.

Atualização : Pensei em acrescentar uma nota lateral. Se você estiver criando alterações que outros revisarão, não é incomum criar uma ramificação com essas alterações e fazer uma nova reformulação periódica para mantê-las atualizadas com a ramificação principal de desenvolvimento. Deixe que outros desenvolvedores saibam que isso acontecerá periodicamente para que eles saibam o que esperar.

Atualização 2 : devido ao número crescente de espectadores, gostaria de adicionar algumas informações adicionais sobre o que fazer quando upstreamocorrer um impulso de força.

Digamos que eu tenha clonado seu repositório e adicionamos alguns commits dessa forma:

            D ---- E tópico
           /
Desenvolvimento A ---- B ---- C

Porém, mais tarde, o developmentramo é atingido com a rebase, o que fará com que eu receba um erro assim quando executar git pull:

Desempacotando objetos: 100% (3/3), pronto.
De <repo-location>
 * desenvolvimento da filial -> FETCH_HEAD
Mesclagem automática de <files>
CONFLITO (conteúdo): Mesclar conflito em <locations>
Falha na mesclagem automática; conserte conflitos e depois confirme o resultado.

Aqui eu poderia resolver os conflitos e commit, mas isso me deixaria com uma história de submissão realmente feia:

       C ---- D ---- E ---- F tópico
      / /
A ---- B -------------- C 'desenvolvimento

Pode parecer atraente de usar, git pull --forcemas tenha cuidado, pois isso deixará você com confirmações ociosas:

            D ---- E tópico

A ---- B ---- C 'desenvolvimento

Então provavelmente a melhor opção é fazer a git pull --rebase. Isso exigirá que eu resolva conflitos como antes, mas para cada etapa, em vez de confirmar, eu usarei git rebase --continue. No final, o histórico de consolidação ficará muito melhor:

            Tópico D '--- E'
           /
A ---- B ---- C 'desenvolvimento

Atualização 3: Você também pode usar a --force-with-leaseopção como um impulso de força "mais seguro", conforme mencionado por Cupcake em sua resposta :

O envio forçado com uma "concessão" permite que o envio forçado falhe se houver novas confirmações no controle remoto que você não esperava (tecnicamente, se você ainda não as tiver buscado no ramo de rastreamento remoto), o que é útil se você não deseja substituir acidentalmente os commits de outra pessoa que você ainda não conhecia e apenas deseja substituir o seu:

git push <remote> <branch> --force-with-lease

Você pode aprender mais detalhes sobre como usar --force-with-leaselendo qualquer um dos seguintes:

Trevor Norris
fonte
5
Como esta é a resposta selecionada, vou comentar aqui. Usar força não é um problema ao trabalhar sozinho. Por exemplo, meu host na nuvem começa com seu próprio git. Se trabalho localmente e construo um projeto, e quero colocá-lo no meu host de nuvem (OpenShift), tenho dois projetos git separados. Meu local e meu OpenShift. Eu obtenho meu local exatamente como eu gosto, mas agora quero visualizá-lo no meu OpenShift. Você então pressiona para o OpenShift pela primeira vez, usando o -fsinalizador. Basicamente, colocando seu git local no OpenShift.
Wade
128

Você quer forçar push

O que você basicamente quer fazer é forçar o envio de sua filial local para substituir a remota.

Se você quiser uma explicação mais detalhada de cada um dos seguintes comandos, consulte a minha seção de detalhes abaixo. Você basicamente tem 4 opções diferentes para empurrar com força com o Git:

git push <remote> <branch> -f
git push origin master -f # Example

git push <remote> -f
git push origin -f # Example

git push -f

git push <remote> <branch> --force-with-lease

Se você quiser uma explicação mais detalhada de cada comando, consulte a minha seção de respostas longas abaixo.

Aviso: o empurrão forçado substituirá o ramo remoto pelo estado do ramo que você está empurrando. Certifique-se de que é isso que você realmente deseja fazer antes de usá-lo; caso contrário, poderá substituir as confirmações que realmente deseja manter.

Forçar empurrando detalhes

Especificando o controle remoto e a ramificação

Você pode especificar completamente ramificações específicas e um controle remoto. A -fbandeira é a versão curta do--force

git push <remote> <branch> --force
git push <remote> <branch> -f

Omitindo o ramo

Quando o ramo a ser enviado é omitido, o Git descobrirá isso com base nas suas configurações. Nas versões Git após a 2.0, um novo repositório terá configurações padrão para enviar por push a ramificação com check-out atualmente:

git push <remote> --force

enquanto antes da 2.0, novos repositórios terão configurações padrão para enviar várias ramificações locais. As configurações em questão são as configurações remote.<remote>.pushe push.default(veja abaixo).

Omitindo o controle remoto e a ramificação

Quando o controle remoto e o ramo são omitidos, o comportamento de just git push --forceé determinado pelas suas push.defaultdefinições de configuração do Git:

git push --force
  • A partir do Git 2.0, a configuração padrão, simplebasicamente enviará sua ramificação atual à sua contraparte remota upstream. O controle remoto é determinado pela branch.<remote>.remoteconfiguração da ramificação e, por padrão, o repositório de origem.

  • Antes do Git versão 2.0, a configuração padrão matchingbasicamente empurra todos os seus ramos locais para ramos com o mesmo nome no controle remoto (cujo padrão é origem).

Você pode ler mais push.defaultconfigurações lendo git help configou uma versão on-line da página de manual do git-config (1) .

Força forçando com mais segurança com --force-with-lease

O envio forçado com uma "concessão" permite que o envio forçado falhe se houver novas confirmações no controle remoto que você não esperava (tecnicamente, se você ainda não as tiver buscado no ramo de rastreamento remoto), o que é útil se você não deseja substituir acidentalmente os commits de outra pessoa que você ainda não conhecia e apenas deseja substituir o seu:

git push <remote> <branch> --force-with-lease

Você pode aprender mais detalhes sobre como usar --force-with-leaselendo qualquer um dos seguintes:

Comunidade
fonte
Você está certo, mas isso realmente só deve ser usado em situações excepcionais .
Scott Berrevoets
1
@ScottBerrevoets " Eu preferiria pressionar o que tenho e deixá-lo sobrescrever remotamente, em vez de integrar. " Dei ao OP exatamente o que ele pedia.
Eu sei, mas o OP pode não estar ciente das consequências de fazer isso. Você tecnicamente respondeu à pergunta, mas acho que um aviso para não fazer isso não está fora de lugar.
22814 Scott Berrevoets
1
@ScottBerrevoets Estou tentando ter um moderador mesclando minha resposta no canônico, porque mencionei a nova --force-with-leaseopção;)
1
FYI: mesclado de stackoverflow.com/questions/24768330/…
Shog9
32

Outra opção (para evitar qualquer pressão forçada que possa ser problemática para outros colaboradores) é:

  • coloque seus novos commits em um ramo dedicado
  • redefinir sua masteremorigin/master
  • mesclar seu ramo dedicado master, mantendo sempre as confirmações do ramo dedicado (ou seja, criar novas revisões sobre as masterquais espelhará seu ramo dedicado).
    Veja " comando git para criar um ramo como outro " para estratégias para simular a git merge --strategy=theirs.

Dessa forma, você pode enviar master para controle remoto sem precisar forçar nada.

VonC
fonte
Como o resultado difere de "push-force"?
alexkovelsky
6
@alexkovelsky Qualquer envio forçado reescreveria o histórico, forçando outros usuários do repositório a redefinir seu próprio repositório local para corresponder aos confirmados enviados recentemente. Essa abordagem cria apenas novos commit e não requer um push forçado.
VonC
1
Eu sugiro que você adicionar um título para a sua resposta: "Você não quer empurrar força" :)
alexkovelsky
@alexkovelsky Good point. Eu editei a resposta de acordo.
VonC 16/01/19
4

O git push -f é um pouco destrutivo, pois redefine todas as alterações remotas que foram feitas por qualquer outra pessoa da equipe. Uma opção mais segura é {git push --force-with-lease}.

O que {--force-with-lease} faz é recusar-se a atualizar uma ramificação, a menos que seja o estado que esperamos; ou seja, ninguém atualizou o ramo a montante. Na prática, isso funciona verificando se o ref upstream é o que esperamos, porque refs são hashes e codificam implicitamente a cadeia de pais em seu valor. Você pode dizer ao {--force-with-lease} exatamente o que verificar, mas por padrão verificará a referência remota atual. O que isso significa na prática é que, quando Alice atualiza sua ramificação e a envia para o repositório remoto, a cabeça indicadora da ramificação é atualizada. Agora, a menos que Bob faça uma busca no controle remoto, sua referência local ao controle remoto estará desatualizada. Quando ele for empurrar usando {--force-with-lease}, o git verificará o árbitro local contra o novo controle remoto e se recusará a forçar o empurrão. {--force-with-lease} efetivamente apenas permite forçar push se mais ninguém tiver enviado alterações até o controle remoto nesse meio tempo. É {--force} com o cinto de segurança.

Lando Ke
fonte
3

Funciona para mim:

git push --set-upstream origin master -f
Jithish PN
fonte
0

Etapas simples usando tortoisegit

GIT fornecendo arquivos locais confirmados e enviando para o repositório git.

Passos :

1) stash altera o nome do stash

2) puxar

3) esconderijo pop

4) confirmar 1 ou mais arquivos e fornecer autor e data do conjunto de descrição das alterações de confirmação

5) empurrar

Nagnath Mungade
fonte