Como posso implantar / enviar apenas um subdiretório do meu repositório git para o Heroku?

121

Eu tenho um projeto que usa o Serve e é controlado por versão usando o Git. Servir cria uma outputpasta com arquivos estáticos que eu quero implantar no Heroku.

Não quero implantar o projeto Serve, pois a pilha Heroku Cedar não parece gostar muito dele, mas o mais importante é que eu quero aproveitar o excelente suporte do Heroku para sites estáticos.

Existe uma maneira de implantar uma subpasta em um git remote? Devo criar um repositório Git na outputpasta (isso parece errado) e enviá-lo para o Heroku?

Olivier Lacan
fonte
1
Você pode estar procurando por submódulos: book.git-scm.com/5_submodules.html
greg0ire

Respostas:

220

Existe uma maneira ainda mais fácil via git-subtree . Supondo que você queira enviar a saída da pasta como raiz para o Heroku, você pode:

git subtree push --prefix output heroku master

Atualmente, parece que a subárvore git está sendo incluída no git-core, mas não sei se essa versão do git-core já foi lançada.

anshumans
fonte
1
Sim, mas a subárvore ainda (a partir do 1.8.0.2) não está incluída no instalador do git . Felizmente, instalar a partir do código-fonte é rápido e direto, esta página funcionou para mim no mac.
dribnet
14
Se você precisar --force, use git push heroku `git subtree split --prefix output master`:master --force. Consulte stackoverflow.com/a/15623469/2066546 .
Fiedl
2
Mas qual é a maneira correta de enviar uma tag específica. Eu pensei que deveria ser git subtree push --prefix output heroku +refs/tags/v1.0.0:refs/heads/master. Mas isso não funciona e volta com +refs/tags/v1.0.0:refs/heads/master does not look like a ref. Preciso desse tipo de funcionalidade para poder voltar a tags específicas mais tarde. Qual é a maneira correta de fazer isso?
Denis #
1
Eu recebo o erro 'As atualizações foram rejeitadas porque uma ponta de ramificação empurrada está por trás do controle remoto'
Ally
2
@ and-dev @Eric Burel Enviei com êxito a outputpasta que estava presente apenas na minha developramificação para a heroku masterramificação sem a necessidade de especificar develop:master, portanto, aparentemente, ela é direcionada para a ramificação de destino especificada na ramificação que está sendo registrada no momento.
Cprcrack
9

Eu tive uma questão semelhante. No meu caso, nunca foi um problema afastar tudo no repositório heroku e substituí-lo pelo que estiver no meu subdiretório. Se este for o seu caso, você pode usar o seguinte script bash. Basta colocá-lo no diretório do aplicativo Rails.

#!/bin/bash

#change to whichever directory this lives in
cd "$( dirname "$0" )"

#create new git repository and add everything
git init
git add .
git commit -m"init"
git remote add heroku [email protected]:young-rain-5086.git

#pull heroku but then checkback out our current local master and mark everything as merged
git pull heroku master
git checkout --ours .
git add -u
git commit -m"merged"

#push back to heroku, open web browser, and remove git repository
git push heroku master
heroku open
rm -fr .git

#go back to wherever we started.
cd -

Tenho certeza de que há muitas maneiras de melhorar isso - fique à vontade para me dizer como!

JnBrymn
fonte
+1Obrigado. Essa solução funciona muito bem se você não se importa com os logs do git no Heroku. É possível ajustar o script acima, caso haja algumas pastas que você deseja ignorar, dentro do subcaminho do aplicativo a ser implantado. Por exemplo, eu não queria specpasta no heroku. Exemplo Gist
ch4nd4n
+1mas você pode simplificar por não puxar e fundindo-se mestre heroku e em vez disso simplesmentegit push --force heroku master
MK Safi
9

Comecei com o que John Berryman colocou, mas na verdade pode ser mais simples se você não se importar com a história do heroku git.

cd bin
git init
git add .
git commit -m"deploy"
git push [email protected]:your-project-name.git -f
rm -fr .git

Acho que oficial git subtreeé a melhor resposta, mas tive problemas para fazer com que a subárvore funcione no meu mac.

LessQuesar
fonte
4

Depois de um mês longo e difícil, tentando coisas diferentes e sendo mordido toda vez que percebi,

só porque o Heroku usa um repositório git como um mecanismo de implantação, você não deve tratá-lo como um repositório git

poderia ter sido rsync também, eles foram para o git, não se distraiam por causa disso

se você faz isso, você se abre para todo tipo de mágoa. Todas as soluções mencionadas falham miseravelmente em algum lugar:

  1. requer que algo seja feito toda vez, ou periodicamente, ou coisas inesperadas acontecem (empurrando submódulos, sincronizando subárvores, ...)
  2. se você usar um mecanismo, por exemplo, para modularizar seu código, o Bundler o comerá vivo, é impossível descrever a quantidade de frustração que tive com esse projeto durante a busca para encontrar uma boa solução para isso.
    • você tenta adicionar o mecanismo como git repo link + bundle deploy- falhar, é necessário empacotar atualizações sempre
    • você tenta adicionar o mecanismo como uma falha :path+ bundle deploy-, a equipe de desenvolvimento considera a :pathopção como "você não está usando o Bundler com esta opção de gema" para que ele não seja agregado para produção
    • Além disso, toda atualização do mecanismo deseja atualizar sua pilha de trilhos -_-
  3. A única solução que encontrei é usar o mecanismo como um /vendorlink simbólico no desenvolvimento e copiar os arquivos para produção

A solução

O aplicativo em questão possui 4 projetos no git root:

  1. api - dependendo do perfil será executado em 2 hosts heroku diferentes - upload e api
  2. web - o site
  3. web-old - o site antigo, ainda em migração
  4. comum - os componentes comuns extraídos em um mecanismo

Todos os projetos têm um vendor/commonlink simbólico para a raiz do commonmecanismo. Ao compilar o código-fonte para implantação no heroku, precisamos remover o link simbólico e o rsync para que ele esteja fisicamente na pasta do fornecedor de cada host separado.

  1. aceita uma lista de nomes de host como argumentos
  2. executa um push git no seu repositório de desenvolvimento e, em seguida, executa um pull limpo do git em uma pasta separada, garantindo que nenhuma alteração suja (não confirmada) seja enviada automaticamente aos hosts
  3. implanta os hosts em paralelo - todos os repositórios heroku git são extraídos, novo código é sincronizado nos lugares certos, confirmado com informações básicas de push no comentário git commit,
  4. no final, enviamos um ping com ondulação para dizer aos anfitriões do hobby que acordem e seguimos os logs para ver se tudo deu certo
  5. também funciona bem com jenkins: D (envio automático de código para testar servidores após testes bem-sucedidos)

Funciona muito bem na natureza com problemas mínimos (não?) Há 6 meses

Aqui está o script https://gist.github.com/bbozo/fafa2bbbf8c7b12d923f

Atualização 1

@AdamBuczynski, nunca é tão direto.

Em primeiro lugar, você sempre terá pelo menos um ambiente de produção e teste - e um monte de clusters específicos de funções, na pior das hipóteses - de repente 1 pasta precisa mapear para n projetos heroku como um requisito bastante básico e tudo precisa ser organizado de alguma forma para que o script "sabe" qual fonte você deseja implantar onde,

Segundo, você desejará compartilhar código entre projetos - agora vem a sync_commonparte, os shennanigans com links simbólicos no desenvolvimento sendo substituídos pelo código rsynced real no Heroku porque o Heroku requer uma certa estrutura de pastas e bundler e rubygems realmente tornam as coisas muito feias muito mal se você deseja extrair os threads comuns em uma gema

Terceiro, você desejará conectar o CI e isso mudará um pouco a forma como as subpastas e o repositório Git precisam ser organizados; no final, no caso de uso mais simples possível, você acaba com a essência mencionada acima.

Em outros projetos, eu preciso conectar as compilações Java; ao vender software para vários clientes, você precisará filtrar os módulos que serão instalados, dependendo dos requisitos de instalação e outros enfeites,

Eu realmente deveria considerar explorar coisas em um Rakefile ou algo assim e fazer tudo dessa maneira ...

bbozo
fonte
Olá @bbozo, você se importaria em condensar um pouco sua solução e torná-la específica para o caso de uso de implantar uma subpasta específica em um projeto heroku específico e remover todas as coisas que não são necessárias / específicas para o Heroku?
Adam Reis
Obrigado por atualizar sua resposta. Eu acho que vou morder a bala e dividir meu código do lado do cliente e do servidor em repositórios separados. Não é o ideal para a nossa situação, mas vai superar os impulsos forçados da subárvore que temos que fazer agora e, pelo que entendi, também será muito mais simples do que tentar usar links simbólicos.
Adam Reis
Não tenha medo de um "script de implementação", vale a pena
bbozo