Como enviar para um repositório Git não-nua?

150

Normalmente trabalho em um servidor remoto via ssh (screen e vim), onde tenho um repositório Git. Às vezes, não estou online, por isso tenho um repositório separado (clonado do meu controle remoto) no meu laptop.

No entanto, não posso extrair deste repositório no lado remoto, porque geralmente estou atrás de um firewall ou não tenho um IP público.

Eu li que devo enviar apenas para um repositório vazio. Como devo enviar minhas alterações ao meu repositório remoto?

woky
fonte
3
tenha 2 repositórios remotos, um simples e um normal, e use ganchos. parece um aborrecimento, mas de acordo com o git ready e o wiki oficial do git , você deve apenas passar para um repositório simples . provavelmente é por isso que a maioria dos hosts de repositório git (por exemplo, GitHub, Bitbucket) inclui ganchos pós-recebimento, para que você possa POSTAR para uma URL no servidor que executa um script que é executado, por exemplo git pull github master.
Jake Berger

Respostas:

137

receive.denyCurrentBranch updateInstead

Essas opções foram adicionadas no Git 2.3 e fazem com que o servidor atualize sua árvore de trabalho, se estiver limpo.

Portanto, se você garantir que você sempre confirme antes de obter localmente e mantenha uma árvore de trabalho limpa no servidor (o que você deve fazer para evitar conflitos de mesclagem), essa opção é uma boa solução.

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
Ciro Santilli adicionou uma nova foto
fonte
é possível empurrar sem criar um repo nua como heroku faz
ANinJa
2
@ANinJa Eu não entendo, não é exatamente isso que meu exemplo faz?
Ciro Santilli escreveu:
é --localopcional?
Yukulélé
@ Yukulélé --localafeta apenas o diretório atual, --globalafeta todos os repositórios git ~/.gitconfig, veja man git-config.
Ciro Santilli resolveu
1
obrigado @CiroSantilli 法轮功 改造 中心 六四 事件 法轮功 depois de ler o documento, confirmo que não é necessário "(você pode dizer --local, mas esse é o padrão)"
Yukulélé
146

Melhor opção

Provavelmente, a maneira mais limpa, menos confusa e mais segura de acessar seu repositório remoto não-nua, é enviando para ramificações dedicadas no controle remoto que representam as ramificações de seu laptop.

Vejamos o caso mais simples e suponha que você tenha apenas uma ramificação em cada repositório: master. Quando você envia para o repositório remoto a partir do seu laptop, em vez de pressionar master -> master, pressione master -> laptop-master (ou um nome semelhante). Dessa forma, o envio não afeta a ramificação principal com check-out no momento no repositório remoto. Para fazer isso no laptop, o comando é bastante simples:

git push origin master:laptop-master

Isso significa que a ramificação principal local será enviada para a ramificação denominada "laptop-master" no repositório remoto. Em seu repo remoto, você terá uma nova ramificação chamada "laptop-master" que poderá ser mesclada ao seu mestre remoto quando estiver pronto.

Opção Alternativa

Também é possível simplesmente enviar master -> master, mas enviar para o ramo atualmente com check-out de um repo non-bare geralmente não é recomendado, porque pode ser confuso se você não entender o que está acontecendo. Isso ocorre porque enviar para uma ramificação com check-out não atualiza a árvore de trabalho; portanto, git statuso check-in na ramificação com check-out transferido mostrará exatamente as diferenças opostas às que foram enviadas mais recentemente. Ficaria especialmente confuso se a árvore de trabalho estivesse suja antes do envio, o que é um grande motivo para isso não ser recomendado.

Se você quiser apenas pressionar master -> master, o comando é apenas:

git push origin

Mas, quando você voltar ao repositório remoto, provavelmente desejará fazer um git reset --hard HEADpara sincronizar a árvore de trabalho com o conteúdo enviado. Isso pode ser perigoso , porque se houver alguma alteração não confirmada na árvore de trabalho remota que você deseja manter, ela será eliminada. Certifique-se de saber quais são as consequências disso antes de tentar ou, pelo menos, faça um backup primeiro!

EDIT Desde o Git 2.3, você pode usar o git push "push-to-deploy": https://github.com/blog/1957-git-2-3-has-been-released . Mas empurrar para um ramo separado e depois mesclar é geralmente melhor, pois ele faz uma mesclagem real (portanto, funciona com alterações não confirmadas, assim como a mesclagem).

Dan Moulding
fonte
1
É possível automatizar a ramificação depois de pressionar o laptop-master?
Rdoubleui
3
@rdoubleui: Você quis dizer "automatizar a fusão "? Nesse caso, não, não é possível automatizar a mesclagem porque não é garantido que as mesclagens sejam possíveis sem a intervenção humana. Pode haver conflitos que precisam ser resolvidos.
Dan Molding
7
em versões posteriores (?), git config receive.denyCurrentBranch ignoretem que ser feito antes de enviar para
repositórios
3
Ótima resposta @DanMoulding, obrigado. @rdoubleui: você sempre pode salvar uma linha de comando como a seguinte como uma função bash:git push origin master:laptop-master && ssh user@remotemachine 'cd repos_path && git merge laptop-master'
Rich
@rdoubleui para automatizar a mesclagem, você pode usar o gitolite e configurá-lo (um pouco complicado) para tornar o não-nua comprometer tudo e enviá-lo para a versão gitolita (nua) usando o gatilho pré-git. Depois disso, se a mesclagem não puder ser resolvida de maneira simples, ela rejeitará seu envio, para que você saiba que precisa puxar primeiro, resolver as mesclagens e enviar novamente. Ainda não o configurei, mas estou no processo e acho que pode funcionar.
17

Eu sugeriria ter um repositório vazio e um repositório local de trabalho (não nu) em seu servidor. Você pode enviar alterações do laptop para o repo bare do servidor e, em seguida, extrair desse repo nu para o repo funcional do servidor. A razão pela qual digo isso é porque você pode ter muitas ramificações completas / incompletas no servidor que deseja replicar no laptop.

Dessa forma, você não precisa se preocupar com o estado da ramificação efetuada check-out no repositório de trabalho do servidor enquanto realiza alterações no servidor.

Manish
fonte
4

Outra opção é configurar um túnel ssh reverso para que você possa puxar em vez de empurrar.

# start the tunnel from the natted box you wish to pull from (local)
$ ssh -R 1234:localhost:22 user@remote

# on the other box (remote)
$ git remote add other-side ssh://user@localhost:1234/the/repo
$ git pull other-side

E se você quiser que o túnel seja executado em segundo plano

$ ssh -fNnR 1234:localhost:22 user@remote
Todd Freed
fonte
1

Você pode fazer:

$git config --bool core.bare true

isso pode ser feito no repositório vazio ou central, para que ele aceite todos os arquivos enviados por repositórios não vazios. Se você fizer isso no repositório não nu, não poderemos enviar nenhum arquivo do repositório não nu para o nu.

Se você estiver praticando o GIT criando um repositório central e não bare no PC, ele pode não mostrar os arquivos enviados em alguns PCs, mas foi enviado. você pode verificá-lo executando.

$git log no repositório central.

Caso contrário, se você pressionar o GitHub, ele mostrará os arquivos lá.

vidwan reddy
fonte