Erro Git Push: recusando-se a atualizar o ramo com check-out

196

Resolvi alguns conflitos de mesclagem, confirmei e tentei enviar por push minhas alterações e recebi o seguinte erro:

c:\Program Files (x86)\Git\bin\git.exe push --recurse-submodules=check "origin" master:master
Done
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error: 
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error: 
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To C:/Development/GIT_Repo/Project
 ! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'C:/Development/GIT_Repo/Project'

Alguém sabe o que poderia estar causando esse erro?

Funky
fonte
3
duplicado: stackoverflow.com/questions/2816369/…
cregox 10/10/12
6
Agora você realmente tem uma maneira segura de enviar para um git config receive.denyCurrentBranch=updateInstead
repositório
Possível duplicata do erro de push
Sören

Respostas:

229

Motivo: você está enviando para um repositório não bare

Existem dois tipos de repositórios: simples e não básicos

Os repositórios vazios não têm uma cópia de trabalho e você pode enviar por push para eles. Esses são os tipos de repositórios que você obtém no Github! Se você deseja criar um repositório vazio, pode usar

git init --bare

Então, resumindo, você não pode enviar para um repositório não-nua(Editar: Bem, você não pode enviar por push para a ramificação de check-out de um repositório atualmente. Com um repositório nu, você pode enviar por push para qualquer ramificação, pois nenhuma está com check-out. Embora possível, empurrar para repositórios não-nua não é comum) . O que você pode fazer é buscar e mesclar no outro repositório. É assim pull requestque funciona o que você pode ver no Github. Você pede que eles se afastem de você e não força a força neles.


Atualização : Obrigado ao VonC por apontar isso, nas versões mais recentes do git (atualmente 2.3.0), é possível avançar para o ramo de check-out de um repositório não nu . No entanto, você ainda não pode enviar para uma árvore de trabalho suja , o que não é uma operação segura.

Shahbaz
fonte
1
Sim! Isso está correto, obrigado! Como tenho cerca de um milhão de coisas para fazer, clonei acidentalmente o diretório de trabalho .... doh!
Funky
25
Na verdade, você pode enviar por push para um repositório não nu, mas não pode enviar por push para o ramo que está atualmente com check-out .
Nowhere Man
1
Existem dezenas de outros cenários, na verdade. Por exemplo, alguns dos meus repositórios estão apenas na minha estação de trabalho e no meu laptop (não código, mas anotações). Em cada um eu tenho dois ramos, "estação de trabalho" e "laptop". Na estação de trabalho, só faço check-out da "estação de trabalho" e só envio à ramificação "estação de trabalho" do laptop (e vice-versa).
Nowhere Man
8
Na verdade, agora você tem uma maneira segura de enviar para um git config receive.denyCurrentBranch=updateInstead
repositório
1
@ skelly Seu clone não está vazio, enquanto a cópia no github. Portanto, enquanto os dois clones têm todo o histórico, a cópia no github não tem nenhum commit verificado, mas sua cópia, para permitir que você trabalhe!
Shahbaz
115

Resolvi esse problema, verificando primeiro se o controle remoto não tinha nada com check-out (realmente não deveria) e depois o deixei exposto com:

$ git config --bool core.bare true

Depois desse git push funcionou bem.

Sasha Pachev
fonte
3
Esta é a correção de uma linha que eu estava procurando .. mas talvez explique repos não-nuas nuas como a resposta @shahbaz
Mr5o1
Isso permitirá que o histórico de alterações seja enviado por push, mas essas alterações não serão refletidas no repo non-bare.
precisa saber é o seguinte
você vai git config core.bare falsee git reset --hard ?
aeronaves
1
Como mencionado acima, o controle remoto não será modificado quando você pressioná-lo.
user1097111 26/03
46

Resumo

Você não pode enviar para a ramificação com check-out de um repositório, porque isso interferiria com o usuário desse repositório de uma maneira que provavelmente terminaria com perda de dados e histórico . Mas você pode enviar para qualquer outra ramificação do mesmo repositório.

Como os repositórios bare nunca têm nenhuma ramificação com check-out, você sempre pode enviar para qualquer ramificação de um repositório bare.

Autópsia do problema

Quando uma ramificação é retirada, a confirmação adicionará uma nova confirmação com o cabeçalho da ramificação atual como pai e moverá a cabeça da ramificação para esse novo commit.

assim

A ← B
    ↑
[HEAD,branch1]

torna-se

A ← B ← C
        ↑
    [HEAD,branch1]

Mas se alguém pudesse passar para o ramo intermediário, o usuário entraria no que o git chama de modo de cabeça desanexada :

A ← B ← X
    ↑   ↑
[HEAD] [branch1]

Agora, o usuário não está mais no ramo1, sem ter solicitado explicitamente o check-out de outro ramo. Pior, agora o usuário está fora de qualquer ramo e qualquer novo commit estará apenas dangling :

      [HEAD]
        ↓
        C
      ↙
A ← B ← X
        ↑
       [branch1]

Hipoteticamente, se nesse momento o usuário fizer check-out de outra ramificação, esse commit pendente se tornará um jogo justo para o coletor de lixo do Git .

Homem de lugar nenhum
fonte
Eu expandi um pouco em stackoverflow.com/questions/2816369/…
Nowhere man
21

cd no diretório repo / no qual você está inserindo a máquina remota e insira

$ git config core.bare true
Ricky
fonte
Isso não funciona. O repositório permanece vazio depois de empurrá-lo.
Sören
como dito por jhil515 acima, os arquivos não vazios não são atualizados, apenas os bancos de dados.
Denis Cousineau
19

Para mim, o seguinte fez o truque:

git config --global receive.denyCurrentBranch updateInstead

Configurei a unidade F :, quase na totalidade, para sincronizar entre minha área de trabalho do Windows 10 e meu laptop com Windows 10, usando o Git. Acabei executando o comando acima em ambas as máquinas.

Primeiro, compartilhei a unidade F da área de trabalho na rede. Então eu consegui cloná-lo no meu laptop executando:

F: git clone 'file://///DESKTOP-PC/f'

Infelizmente, todos os arquivos acabaram em "F: \ f \" no meu laptop, e não em F: \ diretamente. Mas consegui recortá-los e colá-los manualmente. Git ainda trabalhava no novo local depois.

Depois tentei fazer algumas alterações nos arquivos do laptop, enviá-los e enviá-los de volta para a área de trabalho. Isso não funcionou até eu executar o comando git config mencionado acima.

Observe que eu executei todos esses comandos no Windows PowerShell, nas duas máquinas.

ATUALIZAÇÃO: Eu ainda tinha problemas para fazer alterações, em alguns casos. Finalmente, comecei a puxar as alterações, executando o seguinte no computador para o qual desejo extrair as mais recentes confirmações:

git pull --all --prune

Stephen G Tuggy
fonte
1
Eu prefiro este local ao git config receive.denyCurrentBranch updateInstead
repositório
14

Como já existe um repositório existente, executando

git config --bool core.bare true

no repositório remoto deve ser suficiente

Na documentação core.bare

Se true (bare = true), presume-se que o repositório esteja vazio sem um diretório ativo associado. Se esse for o caso, vários comandos que requerem um diretório ativo serão desativados, como git-add ou git-merge (mas você poderá enviá-lo a ele).

Essa configuração é adivinhada automaticamente pelo git-clone ou git-init quando o repositório é criado. Por padrão, um repositório que termina em "/.git" é assumido como não exposto (bare = false), enquanto todos os outros repositórios são assumidos como expostos (bare = true).

Johnny
fonte
12

TLDR

  1. Pull & empurrar novamente: git pull &&& git push.
  2. Ainda é um problema? Empurre para uma ramificação diferente: git push origin master:foomescle-a no repositório remoto.
  3. Como alternativa, force o envio adicionando -f( denyCurrentBranchprecisa ser ignorado).

Basicamente, o erro significa que seu repositório não está atualizado com o código remoto (seu índice e árvore de trabalho são inconsistentes com o que você pressionou).

Normalmente você deve pullprimeiro obter as alterações recentes e pushnovamente.

Se não ajudar, tente entrar em um ramo diferente, por exemplo:

git push origin master:foo

em seguida, mescle essa ramificação no repositório remoto com o master.

Se você alterou algum commit passado intencionalmente git rebasee deseja substituir o repositório por suas alterações, provavelmente deseja forçar o push adicionando -f/ --forceparameter (não recomendado se não o fez rebase). Se ainda assim não funcionar, você precisa configurá receive.denyCurrentBranch-lo ignorecomo remoto, conforme sugerido por uma mensagem git por meio de:

git config receive.denyCurrentBranch ignore
kenorb
fonte
3

Talvez o seu repo remoto esteja no ramo que você deseja enviar. Você pode tentar fazer check-out de outra filial em sua máquina remota. Fiz isso, que esses erros desapareceram e levei o sucesso ao meu repositório remoto. Observe que eu uso o ssh para conectar meu próprio servidor em vez do github.com.

JZAU
fonte
1

Eu tenho esse erro porque o repositório git foi (acidentalmente) inicializado duas vezes no mesmo local: primeiro como um repositório não-bare e logo depois como um repositório bare. Como a pasta .git permanece, o git assume que o repositório não está vazio. A remoção da pasta .git e dos dados do diretório de trabalho resolveu o problema.

xastor
fonte
1
Na minha situação, esse foi o caso. A remoção da .gitpasta no controle remoto permitiu que eu enviasse o commit inicial.
tim.rohrer
0

Eu recebi esse erro quando estava brincando enquanto lia progit. Fiz um repositório local, depois o busquei em outro repositório no mesmo sistema de arquivos, fiz uma edição e tentei enviar por push. Depois de ler a resposta do NowhereMan, uma solução rápida era ir para o diretório "remoto" e fazer check-out temporário de outra confirmação, enviar a partir do diretório em que fiz alterações e voltar e colocar a cabeça no mestre.

Nathan Chappell
fonte