Como eu digo ao git-svn sobre uma ramificação remota criada depois que eu busquei o repositório?

193

Estou usando git-svnpara trabalhar no repositório central do Subversion da minha empresa. Recentemente, criamos uma nova ramificação de recursos no repositório central.

Como digo ao Git sobre isso? Quando corro git branch -r, só consigo ver os ramos existentes quando corri fetchcontra o repositório Subversion para inicializar meu repositório Git?

Hank Gay
fonte
As respostas daqui: stackoverflow.com/questions/13376917/… também podem ser úteis.
Tomasz Gandor

Respostas:

294

Você pode adicionar manualmente a ramificação remota,

git config --add svn-remote.newbranch.url https://svn/path_to_newbranch/
git config --add svn-remote.newbranch.fetch :refs/remotes/newbranch
git svn fetch newbranch [-r<rev>]
git checkout -b local-newbranch -t newbranch
git svn rebase newbranch
vjangus
fonte
3
apenas adicionando este link aos documentos como uma referência kernel.org/pub/software/scm/git/docs/git-svn.html
slf
1
No .git / config, é muito fácil entender como as ramificações remotas podem ser configuradas a partir de repositórios únicos / múltiplos.
Mikael Lepistö
6
Se eu pudesse votar isso oito vezes, eu faria. Finalmente, uma maneira de adicionar um ramo svn adicionado em um local fora do padrão!
Tim Keating
7
Eu chego fatal: Cannot setup tracking information; starting point 'newbranch' is not a branch.na etapa de checkout do git.
Phpuru Apr
17
@phpguru Tente remover o sinalizador de opção -t para que se torne 'git checkout -b local-newbranch newbranch' não se esqueça de incluir o prefixo do controle remoto para newbranch (por exemplo, origin / newbranch).
Mj1531
96

Se você deseja rastrear TODAS as ramificações svn remotas, a solução é tão simples quanto:

git svn fetch

Isso buscará TODAS as ramificações remotas que ainda não foram buscadas.

Dica extra: se você fez check-out apenas do tronco primeiro e depois deseja rastrear TODAS as ramificações, edite .git/configpara ficar assim e execute novamente git svn fetch:

[svn-remote "svn"]
        url = https://svn/path_to_repo_root/
        fetch = path_to_trunk:refs/remotes/git-svn
        branches = path_to_branches/*:refs/remotes/*

Os pontos principais urldevem apontar para a raiz do repositório e os caminhos definidos em fetche branchesdevem ser relativos a url.

Se você deseja buscar apenas ramificações específicas em vez de ALL, há um bom exemplo em git svn --help:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        branches = branches/{red,green}/src:refs/remotes/branches/*
        tags = tags/{1.0,2.0}/src:refs/remotes/tags/*

Nas versões mais antigas de git-svn, depois de especificar ramos como este, talvez você não consiga obter novos ramos git svn fetch. Uma solução alternativa é adicionar mais fetchlinhas, assim:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        fetch = branches/blue:refs/remotes/branches/blue
        fetch = branches/yellow:refs/remotes/branches/yellow
        branches = branches/{red,green}/src:refs/remotes/branches/*

Outra solução alternativa de @AndyEstes: edite .git/svn/.metadatae altere o valor debranches-maxRev ou tags-maxRevpara uma revisão antes da criação de ramificações ou tags recém-especificadas. Depois de fazer isso, corra git svn fetchpara rastrear o novo ramo remoto svn.

janos
fonte
1
Se você já buscou a revisão na qual executou a ramificação svn antes de definir essas configurações, você pode fazer o git svn reset.
kcm1700
3
A edição .git/svn/.metadatafoi muito útil! Eu estava adicionando ramificações extras no meu .git/config, que git svn fetchnão continuaram - porque o número da revisão de metadados estava "muito adiantado". Em um caso, apenas a última confirmação de uma ramificação foi buscada. Eu me livrei manualmente do ramo defeituoso (renomeado .git/svn/refs/remotes/svn/qa/XYZpara .git/svn/refs/remotes/svn/qa/XYZ~, deixei sua existência em .git/packed-refsetc) ... escolhi um número de revisão "anterior" para os metadados ... corri git svn fetchpara finalmente obter um histórico completo com o gráfico correto e conectado.
starlocke
8
ESTA DEVE SER A RESPOSTA ACEITADA! @janos, você acabou de me salvar horas de dor de cabeça! Se você vier à Índia, eu levo você para tomar uma cerveja!
Roopesh Shenoy 22/10
1
Ou: git svn fetch --all.
kenorb
1
Esta resposta é incrível, porque responde a 7 perguntas às quais não encontro respostas e o faz sem escrever uma narrativa de 6 páginas.
Droj
53

Parece que eu só precisava git svn fetch; de alguma forma, eu tinha me convencido de que iria buscar o repositório inteiro em vez de apenas as alterações.

Hank Gay
fonte
7
@mitjak Por que não é a resposta correta, se é a solução? Não entendo a sutileza da resposta.
rholmes
'uma solução' talvez não 'a solução'
slf
1
@rholmes: Tenho certeza de que mitjak significa que essa é a solução para o seu problema, mas não a resposta para a pergunta que você fez. (Porque você fez a pergunta errada, como você interpretou mal a questão no momento.)
Mike Nelson
Isso funciona quando o ramo existia no momento em que você clonou o repositório svn no git. Não funcionará se o ramo no repositório svn foi criado posteriormente.
Petr Gladkikh
3
Funciona bem quando o ramo foi criado após o clone, eu faço isso o tempo todo.
Gautier
15

Talvez eu tenha estragado tudo de alguma forma, mas segui as instruções da resposta de vjangus e quase funcionou. O único problema era que o galho novo não parecia ramificado do tronco. No gitk, era meio que "flutuante" por si só; não tinha ancestral comum com o tronco.

A solução para isso foi:

  1. Encontre o SHA1 da última confirmação que ocorreu no tronco antes da criação da ramificação.
  2. Encontre o SHA1 do primeiro commit na nova ramificação (a mensagem provavelmente é "Nova ramificação criada, copiada do tronco @ 12345" ou algo assim)
  3. git diff-tree <sha1 from step 1> <sha1 from step 2>- não deve haver saída. Se houver saída, você pode ter selecionado as confirmações incorretas.
  4. git checkout local-newbranchentão git rebase <sha1 from step 1>. Isso será restaurado local-newbranchpara a nova árvore, mas remotes/newbranchainda será desconectado.
  5. Vá para o arquivo .git/refs/remotes/newbranche edite-o para conter o SHA1 completo do novo commit (no rebased newbranch) que corresponde ao commit antigo no qual ele está apontando. (Ou talvez use git-update-ref refs/remotes/newbranch <new-SHA>. Obrigado inger.)
  6. A próxima vez que você git svn dcommitpara newbranch, você vai ter um monte de mensagens sobre o assunto atualizando alguns log. Isso é normal, eu acho.

Eu recomendo manter gitk --allaberto o tempo todo e atualizá-lo frequentemente para acompanhar o que você está fazendo. Ainda sou um pouco novo no git e no git svn, por isso sugira melhorias nesse método.

MatrixFrog
fonte
2
Obrigado, isso parece útil. Aproximadamente 5. provavelmente 'git-update-ref refs / remotes / newbranch <new-SHA>' é a opção mais segura.
inger
Apenas tentei o caminho dos vjangus novamente e funcionou perfeitamente. Vou deixar isso aqui de qualquer maneira, uma vez que pode ser valioso para alguém ...
MatrixFrog
1
A solução vjangus sempre cria a nova ramificação desconectada do tronco. Suponho que isso seja devido à maneira como o próprio SVN não tem idéia de como o conteúdo real é copiado.
Bogdan.mustiata
Minha experiência com um grande repositório git-svn é que os ramos svn sempre são criados no git desconectado do tronco. Deve haver alguma maneira de conectá-los, mas não tomei tempo para descobrir isso. AFAIK, você não pode rebase o ramo git que está conectado ao ramo svn, porque isso atrapalha a lógica do dcommit. Acabamos de aprender a viver com isso.
Spencer #
7

Uma simplificação da resposta de vjangus:

Se você estiver usando o layout padrão no SVN e tiver feito o svn init usual, o git-svn fará as coisas de configuração para você. Somente:

  1. Localizar revisão de cópia de ramificação no SVN
  2. Busque essa revisão com git-svn
  3. Crie um novo controle remoto de rastreamento de filial local

Um exemplo. URL do SVN é svn+ssh://[email protected]/repo. O ramo SVN que estou procurando é newbranch. A ramificação git local (rastreamento remoto newbranch) serágit-newbranch .

Etapa 1: encontre a revisão da cópia da filial

    #  svn log - parada na cópia svn + ssh: //[email protected]/repo/branches/newbranch | cauda -4
    r7802 alguém | 2014-03-21 18:54:58 +0000 (sexta-feira, 21 de março de 2014) | 1 linha

    ramificando HEAD para newbranch
    -------------------------------------------------- ----------------------

Portanto, o ponto de ramificação no SVN é a revisão 7802.

Etapa 2: buscar a revisão

    # git svn fetch -r 7802
    Ponto de ramificação possível encontrado: svn + ssh: //[email protected]/repo/trunk => svn + ssh: //[email protected]/repo/branches/newbranch, 7801
    Pai encontrado da ramificação: (refs / remotes / trunk) 8dcf3c5793ff1a8a79dc94d268c91c2bf388894a
    Seguindo pai com do_switch
    Pai seguido com sucesso
    r7802 = 9bbd4194041675ca5c9c6f3917e05ca5654a8a1e (refs / remotes / newbranch)

O git-svn fez todo o trabalho e agora sabe sobre o controle remoto:

    # git show-ref | grep newbranch
    2df23af4733f36f5ad3c14cc1fa582ceeb3edb5c refs / remotes / newbranch

Etapa 3: Crie sua nova filial local rastreando a remota:

    # git checkout -b git-newbranch -t newbranch
    Verificando arquivos: 100% (413/413), concluído.
    A ramificação git-newbranch foi configurada para rastrear refs / remotes / newbranch locais.
    Mudou para um novo ramo 'git-newbranch'
Gil Hamilton
fonte
Após isso, finalmente, me permitiu entender ( show-refé inestimável)! Para qualquer pessoa com referências erradas às ramificações remotas, você pode excluí-las (eu tive que fazer git branch -d newbranche depois forçar a remoção do diretório ref .git/svn/refs/remotes/newbranch) e, em seguida, começar novamente na etapa 2 (acima).
tutuDajuju
5

Não encontrei nenhuma documentação sobre esse recurso, mas parece que a configuração do git svn suporta várias entradas de busca. Dessa forma, você também pode adicionar ramificações separadamente, sem precisar adicionar outra entrada remota do repositório svn à sua configuração nem usar caracteres curinga para obter todas as ramificações de determinado diretório.

Suponha que sua árvore SVN seja realmente desagradável, tendo muitas ramificações sem nenhuma lógica de como elas estão localizadas, por exemplo, tendo ramificações e subdiretórios contendo mais ramificações.

ie

trunk
branches
  -> branch1
  -> sub-dir1
    -> branch2
    -> branch3
  -> sub-dir2
    -> branch4
    -> sub-dir3
      -> branchX 
<... hundreds more ...>

e você só quer escolher alguns dos ramos a serem incluídos no seu repositório git.

Você pode primeiro iniciar seu repositório apenas com o tronco sem ramificações adicionais:

git svn clone -r 10000:HEAD https://svn.com/MyRepo myrepo --prefix=svn/ --trunk=trunk 

Depois disso, você deverá ver a seguinte configuração:

localhost: elhigu$ git config --get-regexp "svn-remote."
svn-remote.svn.url https://svn.com/MyRepo
svn-remote.svn.fetch trunk:refs/remotes/svn/trunk

sempre que quiser buscar uma nova ramificação do MyRepo, você pode adicionar novas entradas de busca à configuração:

git config --add svn-remote.svn.fetch branches/sub-dir2/branch4:refs/remotes/svn/branches/sub-dir2/branch4

Ou você pode editar a mesma configuração em .git / config

Para buscar os novos ramos após adicioná-los à configuração, basta executar:

git svn fetch -r 10000:HEAD

[Editar] Às vezes parece ser necessário executar a busca com o parâmetro --all para buscar ramificações adicionadas recentemente:

git svn fetch --all -r 10000:HEAD
Mikael Lepistö
fonte
4

Em vez de lidar com as peculiaridades do git-svn, você pode tentar o SubGit .

É preciso instalar o SubGit no repositório do Subversion. Depois disso, é possível usar o fluxo de trabalho padrão do git em vez de usar os comandos especiais git-svn:

  1. Enviando novos commits:

    git-svn:

    $ git commit
    $ git svn rebase
    $ git svn dcommit
    

    SubGit:

    $ git commit
    $ git push
    
  2. Buscando alterações recebidas

    git-svn:

    $ git svn rebase
    

    SubGit:

    $ git pull [--rebase]
    
  3. Criando uma nova ramificação:

    git-svn:

    $ git svn branch foo
    $ git checkout -b foo -t remotes/foo
    $ git commit
    $ git svn dcommit
    

    SubGit:

    $ git checkout -b foo
    $ git commit
    $ git push
    

Veja a documentação do SubGit para mais detalhes.

vadishev
fonte
1
O SubGit tem a desvantagem de criar dois repositórios - um svn e um repositório git "shadow". Isso pode ser um problema para grandes repositórios SVN ...
Udo
@Udo se o repositório SVN tiver alguns projetos, é possível especificar apenas um deles e sincronizá-lo com o repositório Git. Nesse caso, não há necessidade de converter todo o repositório Subversion em Git. Mas se houver um grande projeto SVN neste repositório, pode-se converter não todo o histórico desse repositório, mas o histórico a partir de uma revisão mínima. Isso permite diminuir o tamanho do repositório Git traduzido.
vadishev
1
@Udo - qualquer empresa que não esteja disposta a comprar um servidor de repositório no disco rígido tem suas prioridades desordenadas. Mas a maioria dos lugares com grandes repositórios leva seus repositórios muito a sério, e os requisitos de espaço em disco para os repositórios geralmente não são um problema importante, mesmo para empresas com décadas de história e dezenas de milhões de linhas de código e centenas de milhares de revisões. É a forma mais concreta da empresa de seus principais ativos intelectuais, e o espaço em disco é bastante barato. Pode desencadear uma necessidade de atualizar um controlador RAID, mas mesmo assim, o ganho em produtividade ...
Bob Kerns
@Bob Kerns - O ponto é que "tamanho sábio" SVN e Git e não é compatível. Não é uma questão de armazenamento em disco ou algo assim. Mas você pode trabalhar com um enorme repositório SVN, porque geralmente você precisa fazer check-out de apenas alguns arquivos / projetos. Mas você não pode clonar um enorme repositório Git - ele não tira sarro, pelo menos ;-) Por "enorme" eu quero dizer vários Gigs.
Udo
2

Para adicionar à resposta de vjangus, o que me ajudou, também achei útil adicionar enxertos de uso git para amarrar os galhos ao tronco no ponto apropriado - permitindo que o git veja o histórico e faça as mesclagens corretamente.

Este é simplesmente o caso de adicionar uma linha aos .git/info/graftshashes:

<initial branch commit> <parent commit in trunk>

por exemplo.

378b0ae0902f5c2d2ba230c429a47698810532e5 6c7144991381ce347d4e563e9912465700be0638

Crédito para http://evan-tech.livejournal.com/255341.html

(Eu adicionaria isso como um comentário, mas não tenho reputação suficiente.)

Haddon CD.
fonte
0

Se você não fizer o check-out com um layout válido, não poderá fazer check-out de uma filial remota.

Isto é o que eu faço:

git svn init -s <svn path with no trunk> local_repo
cd local_repo
git svn fetch 
## wait

Depois disso, você pode mudar para uma ramificação remota:

git checkout --track -b branch_name branch_name

Então você será automaticamente trocado para sua filial.

MikeHoss
fonte