Git push error '[remoto rejeitado] master -> master (o ramo está atualmente com check-out)'


961

Ontem, postei uma pergunta sobre como clonar um repositório Git de uma das minhas máquinas para outra. Como posso 'clonar git' de outra máquina? .

Agora, consigo clonar com êxito um repositório Git da minha fonte (192.168.1.2) para o meu destino (192.168.1.1).

Mas quando eu fiz uma edição em um arquivo, a git commit -a -m "test"e a git push, recebo este erro no meu destino (192.168.1.1):

git push                                                
hap@192.168.1.2's password: 
Counting objects: 21, done.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (11/11), 1010 bytes, done.
Total 11 (delta 9), reused 0 (delta 0)
error: refusing to update checked out branch: refs/heads/master
error: By default, updating the current branch in a non-bare repository
error: is denied, because it will make the index and work tree inconsistent
error: with what you pushed, and will require 'git reset --hard' to match
error: the work tree to HEAD.
error: 
error: You can set 'receive.denyCurrentBranch' configuration variable to
error: 'ignore' or 'warn' in the remote repository to allow pushing into
error: its current branch; however, this is not recommended unless you
error: arranged to update its work tree to match what you pushed in some
error: other way.
error: 
error: To squelch this message and still keep the default behaviour, set
error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To git+ssh://hap@192.168.1.2/media/LINUXDATA/working
! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'git+ssh://hap@192.168.1.2/media/LINUXDATA/working'

Estou usando duas versões diferentes do Git (1.7 no controle remoto e 1.5 na máquina local). Essa é uma razão possível?


5
Qualquer veterano pode alterar a resposta aceita para stackoverflow.com/a/9283833/397872 e mover o encadeamento para arquivar ou algo assim? Ou mudar de propriedade ou o que seja?
rishta 16/09/12

9
Na verdade, agora você tem uma maneira segura de enviar para um git config receive.denyCurrentBranch=updateInstead
repositório

Esse é o novo link do livro que @stigi mencionou: git-scm.com/book/en/v1/Git-on-the-Server
Abdelilah El Aissaoui


Mas não entendo por que e como funciona? Está funcionando, sim, mas é tudo.
usar o seguinte

Respostas:


1149

Você pode simplesmente converter seu repositório remoto em repositório vazio (não há cópia de trabalho no repositório vazio - a pasta contém apenas os dados reais do repositório).

Execute o seguinte comando na pasta do repositório remoto:

git config --bool core.bare true

Em seguida, exclua todos os arquivos, exceto .gitnessa pasta. E então você poderá executar git pushno repositório remoto sem erros.


4
Obrigado. Eu também precisava disso. Eu estava seguindo o tutorial de submódulos do Git Community Book e encontrei esse obstáculo.
Shiki

6
Eu não tinha certeza se você pretendia excluir arquivos no servidor ou no cliente ... então eu não excluí nada, e o problema desaparece depois de fazer isso git config --bool core.bare true. Existe algum motivo específico para a exclusão de alguns arquivos? Em caso afirmativo, você pode ser mais preciso sobre o que precisa ser excluído?
22711 Brian Vandenberg

24
É a melhor resposta possível e ninguém mais a forneceu no buraco da Interwebs. Acho que todos pesquisamos a mesma mensagem de erro no Google e ficamos extremamente felizes em ler isso.
Sebastián Grignoli 16/07/2012

40
Embora tenha recebido muitos votos, não acho que seja uma resposta realmente adequada a essa pergunta específica. Instruir o usuário a criar de maneira limpa um repositório vazio seria metade do problema, mas e se os arquivos precisassem permanecer em check-out, por exemplo, quando é o repositório com o qual o usuário está trabalhando em dois computadores?
Nowhere Man

9
Alterar o repositório de origem para bare é um exagero. Tudo o que você precisa fazer é enviar para uma nova ramificação no repositório de origem, como @Robert aponta: stackoverflow.com/a/2933656/402949 .
quer

708

Eu apenas tive o mesmo erro quando comecei a aprender Git . Algumas das outras respostas claramente não são para alguém novo no Git!

(Vou usar termos não técnicos para transmitir a ideia.) De qualquer forma, o que está acontecendo é que você tem dois repositórios, um é o original que você criou primeiro e o outro o trabalho que você acabou de fazer.

No momento, você está no seu repositório de trabalho e está usando o ramo "principal". Mas você também está "logado" no seu repositório original na mesma ramificação "principal". Agora que você está "logado" no original, o Git teme que você estrague tudo, porque pode estar trabalhando no original e estragar tudo. Então você precisa retornar ao repositório original e fazer um "git checkout someotherbranch", e agora você pode enviar sem problemas.

Eu espero que isso ajude.


76
+1 Muito mais útil, obrigado Robert. Não fazia sentido converter para um repositório simples no meu caso. Simplesmente tem que 'desativar' o ramo que você está tentando empurrar. Faz sentido.
Eric Muyser

32
@ FMaz008: basta criar um ramo fictício (git checkout -b simulado)
Dror Cohen

14
Cara, isso é muito melhor do que a resposta mais votada :) Obrigado. Embora o outro resposta faz bom ponto também :)
Ivan Ivanić

103
Apenas para tornar isso mais claro, no repo que é o alvo do push: git checkout -b tmp. Em seguida, na fonte de repo: git push. Depois, de volta ao alvo (opcional):git checkout master; git branch -d tmp
Hari Karam Singh

18
O comentário de Hari é a receita mais simples. Eu apenas tenho que dizer que, embora o git possa ser ótimo de várias maneiras, vindo do svn ou provavelmente de qualquer outro rvs, tudo isso é surpreendentemente não intuitivo.
precisa

128

A mensagem de erro descreve o que aconteceu. Versões mais modernas do Git se recusam a atualizar um ramo por meio de um push, se esse ramo estiver com check-out.

A maneira mais fácil de trabalhar entre dois repositórios não-nua é

  1. sempre atualize os repositórios por pull (ou busca e mesclagem) ou, se necessário,

  2. empurrando para uma ramificação separada (uma ramificação de importação) e depois mesclando essa ramificação na ramificação mestre na máquina remota.

O motivo dessa restrição é que a operação push opera apenas no repositório Git remoto, não tem acesso ao índice e à árvore de trabalho. Portanto, se permitido, um push na ramificação de check-out mudaria HEAD para ser inconsistente com o índice e a árvore de trabalho no repositório remoto.

Isso tornaria muito fácil confirmar acidentalmente uma alteração que desfaz todas as alterações enviadas e também torna muito difícil distinguir entre as alterações locais que não foram confirmadas e as diferenças entre a nova HEADárvore, o índice e a árvore de trabalho que foram causada pelo movimento do impulso HEAD.


1
Obrigado. Então, como posso resolver meu problema? Na minha caixa 192, fiz '$ cd (diretório do projeto) $ git init $ (adicione alguns arquivos) $ git add.' e então na minha caixa 191, eu fiz um 'git clone' e editei alguns arquivos e depois tentei 'git push'.
Hap497

16
Bem, eu descrevi as possibilidades na minha resposta. Você pode ir para a caixa 192 e buscar na caixa 191 (você pode adicionar a caixa 191 como um controle remoto nomeado - veja git remote add box191 <191url>) ou pode empurrar da caixa 191 para uma ramificação com nome alternativo (por exemplo git push origin master:refs/heads/upload) e, em seguida, para a caixa 192 e mesclar (por exemplo git merge upload).
CB Bailey

3
Agora você tem uma maneira segura de enviar para um repositório não-nua com o Git 2.3.0 (fevereiro de 2015) e git config receive.denyCurrentBranch=updateInstead: stackoverflow.com/a/28262104/6309 : você não precisa mais da opção 2.
VonC

122

Sumário

Você não pode enviar para a ramificação com check-out de um repositório, pois isso interferiria com o usuário desse repositório de uma maneira que provavelmente terminaria com a 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 por push para qualquer ramificação de um repositório bare.

Existem várias soluções, dependendo de suas necessidades.

Solução 1: Use um repositório vazio

Como sugerido, se em uma máquina você não precisar do diretório ativo, poderá mudar para um repositório vazio. Para evitar mexer com o repositório, você pode apenas cloná-lo:

machine1$ cd ..
machine1$ mv repo repo.old
machine1$ git clone --bare repo.old repo

Agora você pode enviar tudo o que deseja para o mesmo endereço de antes.

Solução 2: enviar para uma ramificação sem check-out

Mas se você precisar verificar o código no seu controle remoto <remote>, poderá usar uma ramificação especial para enviar por push. Digamos que em seu repositório local você tenha chamado seu controle remoto origine esteja no ramo principal. Então você poderia fazer

machine2$ git push origin master:master+machine2

Então você precisa mesclá-lo quando estiver no originrepositório remoto:

machine1$ git merge master+machine2

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 .


3
Uma correção técnica para a "autópsia": o git não será realmente desanexado HEADno repositório enviado por push. HEADainda apontará para a ramificação, e a ramificação, por sua vez, apontará para os novos commits enviados; mas o diretório de trabalho e a área de indexação / preparação não serão modificados. Quem trabalha no repositório enviado agora precisa se esforçar muito para se recuperar dos efeitos do envio: descubra se há alguma alteração a ser salva e, se for o caso, organize-a com cuidado.
torek 23/02

Para adicionar informações adicionais à sua resposta, há muito poucas razões pelas quais você deseja que um repositório remoto não seja desencapado pelas pessoas, portanto, usar um repositório desencapado é a melhor solução.

2
Na verdade, encontrei muitas situações em que preciso enviar para um repositório não-nua, e uso bastante a solução 2. Além disso, o ramo em que pressiono o repositório não nu não é de forma alguma um ramo temporário, ele serve a um propósito semelhante ao de um ramo de rastreamento remoto.
Nowhere Man

Criei uma pasta GIT no meu servidor que hospedará TODOS os repositórios criados por vários usuários usando o SourceTree. Eu criei um masterrepositório no meu PC local. Adicionei o arquivo remotesà pasta do servidor e tentei enviar meu repositório para o servidor, para que outro usuário o puxasse / buscasse para trabalhar. Eu recebo o seguinte erro: ! [remote rejected] master -> master (branch is currently checked out)Como posso fazer check-in?
SearchForKnowledge

1
@SearchForKnowledge, você percebe que está fazendo exatamente a pergunta que estou respondendo ?!
Homem nenhum lugar

65

Você pode contornar essa "limitação" editando o .git/configservidor de destino. Adicione o seguinte para permitir que um repositório git seja enviado por push, mesmo que esteja com check-out:

[receive]
denyCurrentBranch = warn

ou

[receive]
denyCurrentBranch = false

O primeiro permitirá o empurrão enquanto avisa sobre a possibilidade de atrapalhar o galho, enquanto o segundo o permitirá apenas silenciosamente.

Isso pode ser usado para "implantar" o código em um servidor que não se destina à edição. Essa não é a melhor abordagem, mas rápida para implantar código.


7
Usar isso para "implantar" o código em um servidor não funcionará. Mesmo se você desabilitar o aviso para poder enviar para a ramificação com check-out, a cópia de trabalho NUNCA será atualizada por push.
Arrowmaster

10
Estou usando o método acima com cd .. && git reset --hardgancho pós-recebimento para implantar. Hackish, mas funciona.
Jholster 23/03

9
a versão de linha de comando do último seriagit config receive.denyCurrentBranch warn
Andre Holzner

4
Essa deve ser a resposta aceita. Alguns de nós sabem o que estão fazendo e não são iniciantes no Git. Esta é a resposta para essas pessoas.
Qix - MONICA FOI ERRADA EM

2
Ah, mas a pergunta não foi feita por essas pessoas.
Homem nenhum lugar

46

git config --local receive.denyCurrentBranch updateInstead

https://github.com/git/git/blob/v2.3.0/Documentation/config.txt#L2155

Use isso no repositório do servidor e também atualiza a árvore de trabalho se nenhuma substituição não rastreada acontecer.

Foi adicionado no Git 2.3, como mencionado por VonC nos comentários.

Eu compilei o Git 2.3 e tentei. Uso da amostra:

git init server
cd server
touch a
git add .
git commit -m 0
git config --local receive.denyCurrentBranch updateInstead

cd ..
git clone server local
cd local
touch b
git add .
git commit -m 1
git push origin master:master

cd ../server
ls

Resultado:

a
b

Yay, bfui empurrado!


@VonC thanks! É minha obsessão com exemplos mínimas no trabalho :-)
Ciro Santilli郝海东冠状病六四事件法轮功

Isso tem algum problema ao confirmar alterações que não estão atualizadas com o servidor?
akozi

@akozi Não sei ao certo o que você quer dizer, se você se comprometer localmente antes de puxar, ele se comportará exatamente como um --bareclone tradicional que eu penso: --forceé necessário empurrar e fará com que você "perca" os commits no controle remoto.
Ciro Santilli adicionou uma nova foto

1
@CiroSantilli 法轮功 改造 中心 六四 事件 法轮功 Não se preocupe agora. Eu procurei o significado das opções. Eu pensei que updateInstead era sinônimo de força.
akozi

updateInstead não é mais um valor válido para receive.denyCurrentBranch
Xalorous

41

Eu gosto da idéia de ainda ter um repositório utilizável na caixa remota, mas em vez de um ramo fictício, eu gosto de usar:

git checkout --detach

Este parece ser um recurso muito novo do Git - estou usando a versão 1.7.7.4 do git.


8
E depois de fazer as alterações, você pode usar: git checkout masterpara voltar ao ramo principal. É só então que suas alterações estão sendo aplicadas.
MAZDAK

30

Eu tive o mesmo problema. Para mim, eu uso o Git push para mover o código para meus servidores. Eu nunca altero o código no lado do servidor, portanto isso é seguro.

No repositório, você está pressionando para digitar:

git config receive.denyCurrentBranch ignore

Isso permitirá que você altere o repositório enquanto ele é uma cópia de trabalho.

Depois de executar um push do Git, vá para a máquina remota e digite:

git checkout -f

Isso fará com que as alterações enviadas sejam refletidas na cópia de trabalho da máquina remota.

Observe que isso nem sempre é seguro se você fizer alterações na cópia de trabalho para a qual está empurrando.


graças um registro, eu fundir você sugestão denyCurrentBranche colocar git checkout -fdentro hooksda pasta como @ jack-Senechal postado aqui
Éderson T. Szlachta

Existe uma maneira de fazer com que os arquivos apareçam no repositório remoto sem precisar fazer esse comando? Ou seja, por um comando do local?
Royi 8/03/16

24

Você pode recriar o repositório do servidor e enviar do mestre da filial local para o mestre do servidor.

No seu servidor remoto:

mkdir myrepo.git
cd myrepo.git
git init --bare

OK, na sua filial local:

git push origin master:master

3
Obrigado, esta foi a solução para mim, pois eu havia omitido '--bare' no servidor remoto. Parece que as respostas a esta pergunta dependem de você estar usando o repositório do servidor remoto como um diretório de trabalho ou não e, no caso posterior, esta é a resposta correta.
12122 Cas

2
Eu não entendo: o SI tentou criar e clonar um repo bare, mas o clone não baixou nada e o push não carregou nada, então isso não está funcionando ... :-) Eu li tutoriais sobre repo bare, mas eles disseram que um repo bare não contém arquivos ... Isso definitivamente não é o que eu estou procurando ...
inf3rno

22

O que você provavelmente fez para causar isso:

Esse tipo de coisa acontece quando você inicia um pequeno programa. Você está prestes a mudar algo que já estava funcionando, por isso lança seu feitiço de invalidez perpétua nível 3:

machine1:~/proj1> git init

e você começa a adicionar / confirmar. Mas então , o projeto começa a se envolver mais e você deseja trabalhar com ele em outro computador (como o PC ou laptop em casa), para fazer algo como

machine2:~> git clone ssh://machine1/~/proj1

e ele clona e tudo fica bem, e você trabalha no seu código da machine2.

Então ... você tenta enviar por push as confirmações da máquina2 e recebe a mensagem de aviso no título.

O motivo dessa mensagem é que o repositório git do qual você retirou era destinado a ser usado apenas para essa pasta na máquina1. Você pode clonar muito bem, mas pressionar pode causar problemas. A maneira "adequada" de gerenciar o código em dois locais diferentes é com um repositório "vazio", como foi sugerido. A repo nua não é projetado para ter qualquer trabalho que está sendo feito no -lo, que se destina a coordenar os commits a partir de múltiplas fontes. É por isso que a resposta com a melhor classificação sugere excluir todos os arquivos / pastas que não sejam a pasta .git depois de você git config --bool core.bare true.

Esclarecendo a resposta mais bem classificada: Muitos dos comentários a essa resposta dizem algo como "Eu não excluí os arquivos não .git da máquina1 e ainda consegui confirmar na máquina2". Está certo. No entanto, esses outros arquivos estão completamente "divorciados" do repositório git, agora. Vá tentar git statuslá e você verá algo como "fatal: Esta operação deve ser executada em uma árvore de trabalho". Portanto, a sugestão de excluir os arquivos não é para que o commit da máquina2 funcione ; é para que você não fique confuso e pense que o git ainda está rastreando esses arquivos. Mas excluir os arquivos é um problema se você ainda deseja trabalhar nos arquivos da máquina1, não é?

Então, o que você realmente deve fazer?

Depende de quanto você planeja continuar trabalhando na máquina1 e na máquina2 ...

Se você terminou de desenvolver a partir da máquina1 e mudou todo o seu desenvolvimento para a máquina2 ... faça o que a resposta mais votada sugere: git config --bool core.bare truee, opcionalmente, exclua todos os arquivos / pastas que não sejam .git dessa pasta, pois eles é rastreado e provavelmente causará confusão.

Se o seu trabalho no machine2 foi algo único e você não precisa continuar o desenvolvimento por lá ... não se preocupe em fazer um repo; apenas ftp / rsync / scp / etc. seus arquivos da máquina * 2 * sobre os arquivos da máquina * 1 *, confirme / envie da máquina * 1 * e exclua os arquivos da máquina * 2 *. Outros sugeriram a criação de um ramo, mas acho que é um pouco confuso se você apenas deseja mesclar algum desenvolvimento que você fez de uma só vez a partir de outra máquina.

Se você precisar continuar o desenvolvimento na máquina1 e na máquina2 ... precisará configurar as coisas corretamente. Você precisa converter seu repositório para um simples, então você precisa criar um clone disso no machine1 para trabalhar . Provavelmente, a maneira mais rápida de fazer isso é fazer

machine1:~/proj1> git config --bool core.bare true
machine1:~/proj1> mv .git/ ../proj1.git
machine1:~/proj1> cd ..
machine1:~> rm -rf proj1
machine1:~> git clone proj1.git
machine1:~> cd proj1

Muito importante: porque você mudou o local do repositório de proj1 para proj1.git, é necessário atualizá-lo no arquivo .git / config na máquina2 . Depois disso, você pode confirmar suas alterações no machine2. Por fim, tento manter meus repositórios nus em um local central, longe das minhas árvores de trabalho (ou seja, não coloque 'proj1.git' na mesma pasta pai que 'proj1'). Aconselho que você faça o mesmo, mas queria manter os passos acima o mais simples possível.


Muito detalhado e útil. Meu caso foi o último, e suas instruções funcionaram como um encanto.
Pojda

Estou no caso 3 e fiz algo ligeiramente diferente: mk git-server; mv .git git-server / proj.git e, em seguida, git clone git-server / proj.git para 1 e 2 (ou origem remota git ...), usando um prefixo ssh: // adequado para a máquina 2. Desta forma Manterei uma cópia principal simples, como a que normalmente está no GH ou em outro servidor HTTP, e continuarei usando push / pull nas duas máquinas.
Zakmck 16/05/19

18

Com algumas etapas de configuração, você pode implantar facilmente alterações no seu site usando uma linha como

git push production

O que é legal e simples, e você não precisa fazer login no servidor remoto e fazer um puxão ou algo assim. Observe que isso funcionará melhor se você não usar o checkout de produção como um ramo de trabalho! (O OP estava trabalhando em um contexto um pouco diferente, e acho que a solução de @Robert Gould abordou bem isso. Essa solução é mais apropriada para implantação em um servidor remoto.)

Primeiro, você precisa configurar um repositório vazio em algum lugar do seu servidor, fora do seu webroot.

mkdir mywebsite.git
cd mywebsite.git
git init --bare

Em seguida, crie o arquivo hooks/post-receive:

#!/bin/sh
GIT_WORK_TREE=/path/to/webroot/of/mywebsite git checkout -f

E torne o arquivo executável:

chmod +x hooks/post-receive

Na sua máquina local,

git remote add production git@myserver.com:mywebsite.git
git push production +master:refs/heads/master

Tudo pronto! Agora, no futuro, você pode usar git push productionpara implantar suas alterações!

O crédito dessa solução está disponível em http://sebduggan.com/blog/deploy-your-website-changes-using-git/ . Procure uma explicação mais detalhada do que está acontecendo.


Sua sugestão me ajudou muito, mas eu não usei bare, eu sigo isso e me fundo com hooks(que você sugeriu) e funcionou perfeitamente.
Éderson T. Szlachta

11

Você só deve enviar para um repositório vazio. Um repositório vazio é um repositório que não possui ramificações com check-out. Se você fizesse um cd para um diretório de repositório vazio, veria apenas o conteúdo de um diretório .git.


9
Não há nada errado em enviar para uma ramificação não registrada em um repositório não armazenado. Esta é uma maneira perfeitamente válida de trabalhar.
CB Bailey

Justo, isso funcionaria. Mas não é isso que o usuário está fazendo.
RibaldEddie

13
Não é o fato de ele não estar usando um repositório vazio que está "errado"; é o fato de que ele está empurrando para um ramo com check-out. Não há evidências de que ele tenha ou queira um repositório vazio separado, de modo que sua declaração geral de que ele deve enviar apenas para um repositório não nu não está dando ao solicitante todas as opções; um dos quais poderia resolver mais facilmente seu problema imediato.
CB Bailey

10

Você tem 3 opções

  1. Puxe e empurre novamente:

    git pull; git push
    
  2. Empurre para ramo diferente:

    git push origin master:foo
    

    e mesclá-lo no controle remoto (por solicitaçãogit ou pull )

    git merge foo
    
  3. Force-o (não recomendado, a menos que você altere deliberadamente as confirmações via rebase):

    git push origin master -f
    

    Se ainda recusar, desative denyCurrentBranch no repositório remoto:

    git config receive.denyCurrentBranch ignore
    

A opção 2 funciona para mim. git remoto o init mestre local git push origin: filial remota merge git FEITO
Jacky Chong

7

De fato, definir o controle remoto para uma ramificação sem check-out é suficiente. Depois de fazer o check-out do controle remoto em uma ramificação diferente, você pode pressionar.


7

Verifique o seu .git/configno projeto de destino:

$ cat .git/config 
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[receive]
    denyCurrentBranch = updateInstead

Se core. barefor falso, você pode configurá-lo como verdadeiro:

$ git config core.bare true

e, em seguida, no seu envio local para remoto:

git push remote_repo   // suppose the destination repo is remote_repo

terá sucesso, no remote_repo você pode verificar a versão do git.

$ git log -1
commit 0623b1b900ef7331b9184722a5381bbdd2d935ba
Author: aircraft < aircraft_xxx@126.com>
Date:   Thu May 17 21:54:37 2018 +0800

e agora você não pode usar o git no seu "espaço de trabalho":

$ git status
fatal: This operation must be run in a work tree

você deve bare.barevoltar para false.

$ git config core.bare false

5

Eu tive o mesmo problema ao usar o Git para sincronizar repositórios no meu telefone e laptop Android. A solução para mim foi fazer um pull em vez de um push, como sugeriu @CharlesBailey.

git push origin master no repositório Android falha para mim com as mesmas mensagens de erro que @ hap497 recebeu por causa de um envio para um checkout não nítido de um repositório + cópia de trabalho.

git pull droid masterno repositório do laptop e a cópia de trabalho funciona para mim. Claro, você precisa ter executado algo comogit remote add droid /media/KINGSTON4GB/notes_repo/ .


4

As versões mais antigas do Git eram usadas para permitir transferências para a ramificação com check-out atualmente de um repositório não-nua.

Acontece que isso era uma coisa terrivelmente confusa para permitir. Então eles adicionaram a mensagem de aviso que você vê, o que também é terrivelmente confuso.

Se o primeiro repositório estiver apenas atuando como servidor, converta-o em um repositório simples, conforme as outras respostas recomendam e pronto.

Se, no entanto, você precisar ter uma ramificação compartilhada entre dois repositórios em uso, poderá obtê-lo com a seguinte configuração

Repo1 - atuará como servidor e também será usado para desenvolvimento

Repo2 - será apenas para desenvolvimento

Configure o Repo1 da seguinte maneira

Crie uma filial para compartilhar o trabalho.

git branch shared_branch

Para estar seguro, você também deve criar um $ (REPO) .git / hooks / update que rejeite qualquer alteração em algo que não seja shared_branch, porque você não quer que as pessoas mexam com suas filiais particulares.

repo1/.git/hooks  (GIT_DIR!)$ cat update
#!/bin/sh
refname="$1"
oldrev="$2"
newrev="$3"

if [ "${refname}" != "refs/heads/shared_branch" ]
then
   echo "You can only push changes to shared_branch, you cannot push to ${refname}"
   exit 1
fi

Agora crie uma filial local no repo1 onde você fará seu trabalho real.

git checkout -b my_work --track shared_branch
Branch my_work set up to track local branch shared_branch.
Switched to a new branch 'my_work'

(pode ser preciso git config --global push.default upstreampara que git pusha obra)

Agora você pode criar repo2 com

git clone path/to/repo1 repo2 
git checkout shared_branch 

Nesse ponto, você tem a configuração repo1 e repo2 para trabalhar em ramificações locais que são shared_branchenviadas e enviadas no repo1, sem precisar se preocupar com a mensagem de erro ou com o diretório de trabalho fora de sincronia no repo1. Qualquer fluxo de trabalho normal que você usa deve funcionar.


3

OK, caso você queira um repositório remoto normal, crie uma ramificação extra e confira. Empurre-o em uma ramificação (que não está com check-out) e mescle-a com uma que está ativa no momento mais tarde depois de pressionar localmente.

Por exemplo, em um servidor remoto:

git branch dev
git checkout dev

Na configuração local:

git push 

No servidor remoto:

git merge dev

2

Aqui está um teste que você pode fazer para ver como o barematerial do servidor funciona:

Imagine que você tem uma estação de trabalho e um servidor com site ativo hospedado e deseja atualizá-lo de tempos em tempos (isso também se aplica a uma situação em que dois desenvolvedores estão enviando seu trabalho para frente e para trás através de um intermediário).

Inicialização

Crie um diretório no seu computador local e, cdem seguida, execute estes comandos:

# initialization
git init --bare server/.git
git clone server content
git clone server local
  1. Primeiro, você cria um serverdiretório simples (observe o .git no final). Este diretório servirá como um contêiner apenas para os arquivos do repositório.
  2. Em seguida, clone o repositório do servidor em um contentdiretório recém-criado . Este é o diretório ao vivo / produção que será atendido pelo software do servidor.
  3. Os dois primeiros diretórios residem no seu servidor, o terceiro é um diretório local na sua estação de trabalho.

Fluxo de trabalho

Agora, aqui está o fluxo de trabalho básico:

  1. Entre no localdiretório, crie alguns arquivos e confirme-os. Por fim, envie-os para o servidor:

    # create crazy stuff
    git commit -av
    git push origin master
    
  2. Agora digite o contentdiretório e atualize o conteúdo do servidor:

    git pull
    
  3. Repita 1-2. Aqui contentpode haver outro desenvolvedor que também pode enviar por push para o servidor e localcomo você pode obter dele.


2

Usar isso para enviá-lo para a filial remota do upstream resolveu esse problema para mim:

git push <remote> master:origin/master

O controle remoto não tinha acesso ao repositório upstream, portanto, era uma boa maneira de obter as alterações mais recentes nesse controle remoto.


1
De maneira mais geral (como esse é o efeito líquido do comando), use git push <remote> master:newbranch. A idéia é que você envie uma nova ramificação para o controle remoto, que poderá ser mesclada. Dessa forma, evite os problemas de inconsistência mencionados na mensagem de erro.
argila

1

Eu tive que executar novamente git --initem um repositório bare existente, e isso criou um .gitdiretório dentro da árvore do repositório bare - percebi isso depois de digitar git statuslá. Eu apaguei isso e estava tudo bem novamente :)

(Todas essas respostas são ótimas, mas no meu caso, era algo completamente diferente (tanto quanto posso ver), conforme descrito.)


1

Tenho certeza de que a maioria das pessoas que visualiza essa pergunta irá parar nas duas primeiras respostas enormes, mas eu ainda gostaria de oferecer minha solução.

Eu tive uma configuração de projeto da web Eclipse + EGit ao encontrar o erro descrito. O que me ajudou foi simplesmente usar o aplicativo GitHub, que parecia resolver magicamente o problema. Embora o EGit sempre recuse o envio, o aplicativo GitHub para desktop encolhe os ombros e pressiona minhas alterações. Talvez ele lide com a situação de login múltiplo mais graciosamente.


1

Um artigo que achei útil para outras pessoas é o Git em 5 minutos .

Eu tinha um projeto Xcode sob o controle de versão Git que queria enviar para um VDE ( Virtual Distributed Ethernet ) que tenho em um controlador de domínio . O VDE executa o Centos 5.

Nenhum dos artigos que li sobre o Git falou sobre repositórios vazios. Tudo parecia tão simples até que eu tentei o que achava que deveria ser fácil, vindo de um plano de fundo do SVN .

As sugestões aqui para deixar o repositório remoto funcionando. Ainda melhor para meus requisitos era clonar o projeto Xcode projectname.git, copiá-lo para o servidor remoto; então empurra magicamente trabalhado. O próximo passo será fazer o Xcode enviar sem erros sobre confirmações, mas por enquanto estou bem em fazê-lo no Terminal.

Assim:

cd /tmp (or another other directory on your system)<br/>
git clone --bare /xcode-project-directory projectname.git<br/>
scp -r projectname.git sshusername@remotehost.com:repos/<br/>

Para enviar alterações do seu projeto do Xcode após a confirmação no Xcode:

cd /xcode-project-directory<br/>
git push sshusername@remotehost.com:repos/projectname.git<br/>

Estou certo de que há uma maneira mais suave e sofisticada de fazer o que foi dito acima, mas no mínimo isso funciona. Para que tudo fique claro, aqui estão alguns esclarecimentos: /xcode-project-directoryé o diretório em que o seu projeto xcode está armazenado. Provavelmente /Users/Your_Name/Documents/Project_Name. projectname é literalmente o nome do projeto, mas pode ser qualquer coisa que você queira chamar. Git não se importa, você vai.

Para usar o scp, você precisa ter uma conta de usuário no servidor remoto que tenha acesso SSH . Qualquer pessoa executando seu próprio servidor terá isso. Se você estiver usando hospedagem compartilhada ou algo semelhante, pode estar sem sorte.

remotehost.comé o nome do seu host remoto. Você poderia facilmente usar o endereço IP. Apenas para maior clareza, estou usando Gitosis no host remoto com chaves SSH, portanto, não sou solicitado a fornecer senhas quando pressiono. O artigo Hospedando repositórios Git, a maneira fácil (e segura) mostra como configurar tudo isso.


1

A melhor maneira de fazer isso é:

mkdir ..../remote
cd ..../remote
git clone --bare .../currentrepo/

Isso clonará o repositório, mas não fará nenhuma cópia de trabalho .../remote. Se você olhar para o controle remoto, verá um diretório criado, chamado currentrepo.git, que provavelmente é o que você deseja.

Em seguida, no seu repositório Git local:

git remote add remoterepo ..../remote/currentrepo.git

Depois de fazer alterações, você pode:

git push remoterepo master

1

Acabei de encontrar este problema com um repositório git de implantação no Heroku .

Não sei por que o Heroku tem um repositório não nu do lado deles, mas como solução alternativa pude redefinir o repositório remoto e recarregar novamente.

Você não deve usar a cópia do Heroku do seu repositório como seu único repositório git para colaboração, mas, para garantir , direi claramente: Não faça isso a menos que tenha certeza de que uma cópia completa do seu repositório está armazenada com segurança em algum lugar que não seja Heroku. A redefinição excluirá o conteúdo do repositório.

Reiniciar:

  1. Instale o cinto de ferramentas Heroku (que contém o cliente da linha de comando) se você ainda não o tiver.
  2. Instale o plugin heroku-repo se você ainda não o fez.

    heroku plugins:install https://github.com/heroku/heroku-repo.git
    
  3. Faça a redefinição, que exclui o repositório e cria um novo e vazio

    heroku repo:reset
    
  4. Empurre para o controle remoto Heroku como faria normalmente; ele irá reenviar tudo.


Pode ser necessário instalar as ferramentas de repoção Heroku para que isso funcione. Doheroku plugins:install https://github.com/heroku/heroku-repo.git
Noah

1

Você precisará alterar o arquivo de configuração no servidor remoto depois de criar o repositório vazio (vazio), por exemplo

root@development:/home/git/repository/my-project# cat config 

aí você vai ver

[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true

Você tornará isso nu para falso e verdadeiro e eu removi logallrefupdates = true (não tenho certeza do seu uso!)

para

[core]
repositoryformatversion = 0
filemode = true
bare = true

Você pode testar a seguir

$ git remote show origin
* remote origin
Fetch URL: my-portal@development:/home/XYZ/repository/XYZ
Push  URL: my-portal@development:/home/XYZ/repository/XYZ
HEAD branch: (unknown)

Este ramo HEAD: (desconhecido) será mostrado se você não conseguir empurrar. Portanto, se a ramificação HEAD for desconhecida, você deve mudar nua para true e, depois de enviar com êxito, poderá reutilizar o

git remote show origin

e você verá

 HEAD branch: master

0

Para mim, a solução de trabalho é:

EM REMOTO:

git checkout -b some_tmp_name

NO LOCAL:

git push

EM REMOTO:

git checkout master
git branch -d some_tmp_name

Mas essa não é a solução real, é apenas uma solução alternativa.


Esta é uma solução válida se você não possui um repositório central.
19315 Rick

0

Apenas no caso de alguém achar útil. Para mim, foi um problema de permissões do servidor git. Fiz o check-out do projeto desde o início e enviei um arquivo simples e recebi a mensagem "Push rejeitado: o envio para origem / o mestre foi rejeitado"


-1

Com o Git, dois repositórios regulares (não bare) não podem enviar / receber arquivos diretamente. Deve haver um repositório intermediário. Aparentemente, é como um casal que tem um filho, e o casal está se divorciando. Os pais não conversam, mas se comunicam através da criança.

Portanto, você tem um repositório, clona-o em um repositório simples e clona-o em um terceiro. O primeiro e o terceiro podem trocar informações através do segundo repositório, o único. Eu acho que isso faz sentido, pois você não gostaria que alguém fosse capaz de verificar coisas no seu repositório sem o seu consentimento, pois isso poderia causar conflitos de mesclagem e coisas do tipo.

Então, aqui está um exemplo:

No PC, no ~ / espaço de trabalho

git init
echo "line 1" > afile.txt
git add .
git commit -m ‘initial import’
git clone --bare . ../remote-repository.git
git remote add origin ../remote-repository.git
git push --set-upstream origin master

No laptop, no ~ / espaço de trabalho (não faça git init, etc.)

git clone //LJZ-DELLPC/remote-repository.git/ .

// Em seguida, faça vários commits e pressione-os:

echo "line 2" > afile.txt
git add afile.txt
git commit -m 'added line 2'
git push    

Depois, de volta ao PC, em ~ / espaço de trabalho

git pull

// Em seguida, faça vários commits e pressione-os:

git push

No laptop git pull

e assim por diante..

Aqui está um exemplo concreto absoluto, tudo em uma máquina, copiado diretamente da janela de comando, para que possamos saber que nenhuma etapa foi deixada de fora, que realmente funcionou, etc:

lylez@LJZ-DELLPC ~
$ cd gitdir
/home/lylez/gitdir

lylez@LJZ-DELLPC ~/gitdir
$ ls

lylez@LJZ-DELLPC ~/gitdir
$ mkdir repo1

lylez@LJZ-DELLPC ~/gitdir
$ cd repo1
/home/lylez/gitdir/repo1

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git init
Initialized empty Git repository in /home/lylez/gitdir/repo1/.git/

lylez@LJZ-DELLPC ~/gitdir/repo1
$ echo "line 1" > afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git add afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git commit -m 'initial import'
[master (root-commit) f407e12] initial import
 1 file changed, 1 insertion(+)
 create mode 100644 afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git clone --bar . ../repo1-bare-clone
Cloning into bare repository '../repo1-bare-clone'...
done.

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git remote add origin ../repo1-bare-clone

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git push --set-upstream origin master
Branch master set up to track remote branch master from origin.
Everything up-to-date

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cd ..

lylez@LJZ-DELLPC ~/gitdir
$ ls
repo1  repo1-bare-clone

lylez@LJZ-DELLPC ~/gitdir
$ mkdir repo1-remote

lylez@LJZ-DELLPC ~/gitdir
$ cd repo1-remote
/home/lylez/gitdir/repo1-remote

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git clone ../repo1-bare-clone .
Cloning into '.'...
done.

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ ls
afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cat afile.txt
line 1

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ echo "line 2" >> afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git add afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git commit -m 'added line 2'
[master 5ad31e0] added line 2
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 260 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /home/lylez/gitdir/repo1-remote/../repo1-bare-clone
   f407e12..5ad31e0  master -> master

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cd ../repo1

lylez@LJZ-DELLPC ~/gitdir/repo1
$ ls
afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cat afile.txt
line 1

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git pull
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From ../repo1-bare-clone
   f407e12..5ad31e0  master     -> origin/master
Updating f407e12..5ad31e0
Fast-forward
 afile.txt | 1 +
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cat afile.txt
line 1
line 2

lylez@LJZ-DELLPC ~/gitdir/repo1
$ echo "line 3" >> afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git add afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git commit -m 'added line 3'
[master 3fa569e] added line 3
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 265 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To ../repo1-bare-clone
   5ad31e0..3fa569e  master -> master

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cd ../repo1-remote/

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ ls
afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cat afile.txt
line 1
line 2

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git pull
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/lylez/gitdir/repo1-remote/../repo1-bare-clone
   5ad31e0..3fa569e  master     -> origin/master
Updating 5ad31e0..3fa569e
Fast-forward
 afile.txt | 1 +
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cat afile.txt
line 1
line 2
line 3

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git --version
git version 2.1.1

lylez@LJZ-DELLPC ~/gitdir/repo1-remote

É um exemplo do que funciona e uma explicação do porquê. Não há informações erradas aqui, exceto o seu comentário.
Lyle Z

1
"Com o Git, dois repositórios regulares (não vazios) não podem enviar / receber arquivos diretamente" - exceto que podem.
Andrew C

Bem, publique um exemplo concreto em vez de um ataque.
Lyle Z

Ou você pode pesquisar no google? stackoverflow.com/questions/1764380/…
Andrew C

A primeira resposta no tópico em que você começa começa com "... mas de acordo com o git ready e o wiki oficial do git, você deve enviar apenas um repositório". A próxima resposta declara: "Se você deseja apenas pressionar master -> master, o comando é apenas: git push origin", e isso simplesmente não funciona, e há um zilhão de postagens para esse efeito. A última resposta começa com "Sugiro ter um repositório vazio e um repositório local de trabalho (não nu) em seu servidor.", Que é exatamente o que eu propus.
Lyle Z

-3

Minha solução (em uso)

  1. Caixa "master" no servidor remoto
  2. Trabalhe localmente na ramificação "dev"
  3. Enviar alterações para o desenvolvedor remoto
  4. Mesclar dev no master no controle remoto

Bingo

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.