Usando o git, como ignoro um arquivo em um ramo, mas ele foi confirmado em outro ramo?

157

Eu tenho um projeto que estou implantando no Heroku . A árvore do código-fonte inclui um monte de arquivos mp3 (o site será para um projeto de gravação com o qual eu estava muito envolvido).

Eu gostaria de colocar o código-fonte no GitHub , mas o GitHub tem um limite de 300 MB em suas contas gratuitas. Não quero usar 50 MB do meu limite em vários arquivos mp3. Obviamente, eu poderia adicioná-los ao .gitignorearquivo para mantê-los fora do meu repositório.

No entanto, eu implanto no Heroku usando git push heroku. Os arquivos mp3 devem estar presentes no ramo que envio ao Heroku para que eles sejam implantados.

Idealmente, eu gostaria .gitignoredos arquivos mp3 em minha ramificação principal local, para que quando eu enviar isso para o GitHub, os mp3s não sejam incluídos. Então, eu manteria um ramo de produção local que tenha os mp3s confirmados em vez de ignorados. Para implantar, eu mesclaria o mestre na produção e depois enviaria o ramo de produção para o Heroku.

Não consigo fazer isso funcionar direito.

Aqui está um exemplo do que estou tentando fazer ...

$ git init git-ignore-test
$ cd git-ignore-test
$ echo "*.ignored" >> .gitignore
$ git add .gitignore && git commit -m "Ignore .ignored files"
$ touch Foo.ignored

Neste ponto, Foo.ignored é ignorado em minha ramificação principal, mas ainda está presente, para que meu projeto possa usá-lo.

$ git checkout -b unignored
$ cat /dev/null > .gitignore
$ git add Foo.ignored .gitignore && git commit -m "Unignore .ignored files"

Agora eu tenho uma ramificação com esses arquivos confirmados, como eu quero. No entanto, quando volto ao meu ramo principal, o Foo.ignored se foi.

Alguém tem alguma sugestão para uma maneira melhor de configurar isso?

Editar: apenas para esclarecer, quero que os arquivos mp3 estejam presentes nos dois ramos para que, quando eu executo o site localmente (usando um dos ramos), o site funcione. Eu só quero que os arquivos sejam ignorados em uma ramificação; portanto, quando eu envio para o GitHub, eles também não são enviados. Normalmente, o .gitignore funciona bem para esse tipo de coisa (ou seja, manter uma cópia local de um arquivo que não é incluído em um envio para um controle remoto), mas quando eu alterno para o ramo com os arquivos verificados e, em seguida, de volta ao arquivo Quando os arquivos são ignorados, os arquivos desaparecem.

Myron Marston
fonte
Por que os arquivos MP3 precisa estar comprometido com o repositório?
Dan Loewenherz 03/12/2009
4
Com o heroku, comprometer-se com seu repositório é a única maneira de incluir arquivos no aplicativo quando você implanta. A única alternativa é usar algo como o Amazon S3 para servir os mp3s, mas eu prefiro evitar isso.
Myron Marston
Parece que você está tropeçando em dólares para salvar tostões ... A Rackspace Cloud é muito simples para obter a configuração, e custaria muito pouco a loja <1 GB de arquivos lá ...
gahooa
3
Percebo que você marcou uma resposta como correta, mas pelo que li, pode não estar correta. Você já tentou a resposta e funcionou para você?
loop
2
Off Topic: Você já pensou em usar outro host de repositório de código aberto? O BitBucket não tem limite de tamanho em seus repositórios Git, independentemente de estarem em uma conta gratuita ou não (eles mencionam manter o tamanho dentro do razoável). Contanto que seu repositório não cresça fora de controle, isso pode ser uma opção. NOTA: Não estou associado ao BitBucket, apenas um cliente satisfeito.
NightOwl888

Respostas:

84

Esta solução parece funcionar apenas para determinadas versões corrigidas do git. Veja uma nova resposta apontando para soluções alternativas e outra resposta e comentários subseqüentes para obter uma dica de quais versões podem funcionar.

Eu escrevi um post no blog sobre como usar efetivamente o excludesfilepara diferentes ramos, como um para o github público e outro para a implantação do heroku.

Aqui está o rápido e sujo:

$ git branch public_viewing
$ cd .git/
$ touch info/exclude_from_public_viewing
$ echo "path/to/secret/file" > info/exclude_from_public_viewing 

depois, no arquivo .git / config, adicione estas linhas:

[core]
excludesfile = +info/exclude


[branch "public_viewing"]
excludesfile = +info/exclude_from_public_viewing

Agora, todo o material de ignorado global está no info/excludearquivo e o ramo específico está noinfo/exclude_from_public_viewing

Espero que ajude!

http://cogniton-mind.tumblr.com/post/1423976659/howto-gitignore-for-different-branches

Cognition.Mind
fonte
1
Desculpe por demorar tanto ... mas se você não excluir os arquivos .gitignore, os padrões serão os primeiros.
precisa
4
Isso não funciona para mim, mesmo quando o projeto não usa .gitignore. Você se importa em fornecer uma transcrição de comandos configurando isso do zero ( git init, ...) e a versão do Git que você usou?
Davor Cubranic
34
Esta solução não funciona. Houve alguma discussão no blog, e ninguém lá também foi capaz de fazer esse trabalho.
Spuder #
2
No Git de baunilha, tenho certeza de que isso não funciona e nunca funcionou. Aqueles de vocês que conseguiram reproduzir isso, podem compartilhar sua versão do Git e outras informações relevantes em seu ambiente? Talvez você tenha uma versão corrigida dos mantenedores de pacotes Git da sua distribuição.
Palec
20

Dica importante : a resposta aceita pelo Cognition.Mind não funciona (mais, há vários anos, ou talvez para versões baunilha do git); veja os comentários. Uma resposta válida e uma solução alternativa podem ser encontradas aqui:

https://stackoverflow.com/a/29583813/2157640

Outra solução alternativa (trabalhando para o meu problema específico, mas exigindo operações manuais de stash ou implementação de um gancho) seria git stash -u -a. Isso é entediante quando as diferenças são grandes.

E, finalmente, a solução com a qual estou indo agora é bifurcar minha VM em que mantemos nosso ambiente de desenvolvimento e configurá-lo info/excludesadequadamente para a filial, excluindo respectivamente os arquivos / pastas ofensivos e não confirmados.

Murphy
fonte
14

Eu recomendaria fortemente considerar colocar esses arquivos MP3 no S3. Fazer com que eles façam parte do seu impulso Heroku (e, portanto, parte da sua lesma Heroku) diminuirá bastante o tempo de inicialização do dinamômetro. Como o Heroku usa o EC2, se os arquivos estiverem no S3 e forem acessados ​​apenas pelo seu aplicativo (se os usuários não estiverem diretamente vinculados ao S3), você nem pagará nenhuma taxa de largura de banda, apenas a taxa para armazenar 50 MB.

David Dollar
fonte
13

Digamos que queremos ignorar a buildpasta de todas as outras ramificações, exceto productionramificação. Como queremos empurrar buildpasta na produção.

1) Não inclua buildno .gitignore. Se você fizer isso, será sempre ignorado em todos os ramos.

2) Crie um arquivo exclude_from_public_viewingdentro da ./.git/infopasta (Esta pasta já existe)touch ./.git/info/exclude_from_public_viewing

3) Dentro, exclude_from_public_viewingescreva uma linha (como você está tentando ignorar buildpara todos os ramos). !build

4) Existe um arquivo existente .git/info/exclude. Precisamos adicionar a seguinte linha.

 build

Queremos ignorar a buildpasta, mas não a adicionamos ao .gitignore. Então, como o git saberá o que ignorar? A resposta é que estamos adicionando-o ao excludearquivo e passando condicionalmente esse arquivo paragit config

5) Agora temos que cancelar o registro condicional da buildpasta para productionramificação. para fazer isso, execute os seguintes

6) Existe um arquivo existente chamado ./.git/configprecisamos adicionar o seguinte -

a) excludesfile = +info/excludeabaixo[core]

[core]
     excludesfile = +info/exclude

b) Criar uma nova seção no final de ./.git/configcomo

[branch "production"]
    excludesfile = +info/exclude_from_public_viewing

Solução 2

Existe uma solução alternativa inteligente. Vamos dizer que você deseja adicionar uma build/pasta na productionramificação e ignorá-la em todas as outras ramificações.

1) Adicione-o ao seu gitignorearquivo.

2) No ramo de produção, enquanto estiver fazendo git add, force a adição de buildpasta:git add -f --all build/

sapy
fonte
E isso difere da solução aceita como? Com qual versão do git você testou? Como a resposta vinculada declara, ela falha porque não há suporte para o branch.<name>.excludesfilegit (mais?), Apenas para core.excludesfile, e meus próprios testes pareciam afirmar isso.
Murphy
Murphy @ ele funciona bem git version 2.7.4 (Apple Git-66)e eu não usei branch.<name>.excludesfile na minha solução.
sapy
4
@sapy: Eu tentei isso de acordo com o caso de uso do OP, e o arquivo ainda desaparece quando eu alterno da produção para o mestre. Observe que a pasta "build" deve ser confirmada na ramificação "produção". (Além disso, notei que, se eu não confirmar a pasta "build" na ramificação "produção", a ramificação "produção" ignorará a presença da pasta "compilação" - ou seja, a [ramificação "produção"] exclui a configuração do arquivo não funciona). Eu uso exatamente a mesma versão do git que a sua. Também tentei a abordagem [branch "production"] para ignorar o arquivo apenas no ramo de produção, mas também não funciona, como Murphy disse.
justhalf 6/09/16
Solução 2 era algo que eu estava procurando. Obrigado!
Vyacheslav Cotruta
4

Você já tentou que o .gitignore fosse diferente em sua filial?

Você deve poder ignorar o que deseja com base na ramificação em que se encontra, desde que os arquivos não sejam rastreados nessa ramificação.

kEND
fonte
6
Eu tentei isso. Se você olhar para os comandos que eu postei acima, verá que foi exatamente o que eu fiz. O problema é que, quando alterno da ramificação com os arquivos registrados para a ramificação com os arquivos ignorados, o git descarta os arquivos. Quero manter os mp3s no meu ramo principal para que o site funcione corretamente no modo dev, mesmo que os arquivos sejam ignorados.
Myron Marston
1
ele já disse que foi o que ele fez. talvez apenas excluir esta resposta seja o melhor :-) esteja causando distração.
blamb
3

1. Resumo

  1. Eu uso o Travis CI para implantar ( ele suporta a implantação do Heroku )
  2. Eu adiciono ao meu .travis.yml:

    before_deploy:
    - mv misc/.gitignore .gitignore

    Onde misc- qualquer pasta, contém outra .gitignore.

    mvComando UNIX mover arquivo; substituir, se o arquivo já existir.

Quando o Travis CI implanta um projeto, o Travis CI não avança para a implantação de arquivos e pastas do provedor , que são ignorados misc/.gitignore(não no original .gitignoredas fontes).


2. Limitações

  1. Esta resposta pode não ser adequada para todas as condições do autor. Mas esta resposta responde à pergunta "Usando o git, como ignoro um arquivo em um ramo, mas ele foi confirmado em outro ramo?"
  2. Não sou usuário Heroku, meus exemplos para o GitHub , não para o Heroku. Os dados desta resposta funcionam para mim no GitHub, mas podem não funcionar no Heroku.

3. Relevância

Esta resposta é relevante para abril de 2018. No futuro, os dados desta resposta podem estar obsoletos.


4. Demonstração

meu projeto real .

Exemplo de implantação bem-sucedida .

4.1 Tarefa

Eu implanto meu projeto da ramificação src na ramificação dest do mesmo repositório.

Eu quero esse arquivo PaletteMira.suricate-profile:

  • Máquina local - existe para todas as filiais,
  • ramificação remota src - não existe,
  • filial remota dest - existe.

Se eu entendi corretamente o autor da pergunta, ele tem uma tarefa semelhante.

4.2 src

ramo de fontes - SashaYAML .

Parte de .travis.yml:

before_deploy:
- mv misc/.gitignore .gitignore

deploy:
  provider: pages
  on:
    branch: SashaYAML
  keep-history: true
  skip-cleanup: true
  target-branch: SashaDevelop
  repo: Kristinita/PaletteMira
  github-token: $GITHUB_TOKEN
  committer-from-gh: true
  project-name: PaletteMira
verbose: true

Parte de .gitignore:

*.sublime-snippet
*.suricate-profile

Parte de misc/.gitignore

*.sublime-snippet

*.suricate-profilenão em misc/.gitignore.

PaletteMira.suricate-profile não existe neste ramo remotamente, mas existe localmente.

4.3 dest

agência de destino - SashaDevelop

Parte de .gitignore:

*.sublime-snippet

*.suricate-profilenão em misc/.gitignore.

PaletteMira.suricate-profileexiste para esse ramo remotamente e localmente.

4.4 Passos para reproduzir

Habilito o repositório PaletteMira GitHub para o Travis CI Defino a variável de ambiente $GITHUB_TOKEN com valor - meu token GitHub → Faço qualquer confirmação para minha ramificação src.

Se não houver erros, devo obter o comportamento esperado .

Саша Черных
fonte
0

Você pode se comprometer e empurrar do Heroku?

Por exemplo, adicione o áudio, empurre-o para o github e para o heroku, remova os arquivos da cópia de trabalho no Heroku. Remova o áudio do repositório, mas não do disco, depois empurre essa alteração de volta para o github.

Tom
fonte
0

Agora o Github tem suporte para armazenamento de arquivos grandes, veja mais aqui https://git-lfs.github.com/

John Lozano
fonte