Git Symlinks no Windows


246

Nossos desenvolvedores usam uma mistura de sistemas operacionais baseados em Windows e Unix. Portanto, links simbólicos criados em máquinas Unix se tornam um problema para desenvolvedores do Windows. No Windows (msysgit), o link simbólico é convertido em um arquivo de texto com um caminho para o arquivo para o qual aponta. Em vez disso, gostaria de converter o link simbólico em um link simbólico real do Windows.

A solução ( atualizada ) que tenho para isso é:

  • Escreva um script pós-checkout que procure recursivamente os arquivos de texto "link simbólico".
  • Substitua-os pelo link simbólico do Windows (usando mklink) com o mesmo nome e extensão que o "link simbólico" fictício
  • Ignore o link simbólico do Windows adicionando entrada em .git / info / exclude

Eu não implementei isso, mas acredito que essa é uma abordagem sólida para esse problema.

Questões:

  1. Quais são as desvantagens que você vê nessa abordagem?
  2. Esse script pós-checkout é implementável? ou seja, posso descobrir recursivamente os arquivos fictícios "link simbólico" que o git cria?
  3. Alguém já trabalhou nesse script?

3
Embora o Git ofereça suporte a links simbólicos, eu recomendaria fortemente não armazená-los como links no seu repositório, especialmente se você também estiver trabalhando com esse código no Windows.
Greg Hewgill

2
@ Greg Hewgill - concordo totalmente com você. Infelizmente, a natureza de nossa base de código requer links simbólicos ... portanto, removê-los não é uma opção para nós.
Ken Hirakawa

12
Você também pode perguntar na lista de discussão do msysgit por que eles não a implementaram dessa maneira em primeiro lugar.
Drizzd

8
@GregHewgill por que não? Windows suporta ambos os links simbólicos e junções - isso realmente parece ser uma característica ausente nas versões Windows do Git para mim ...
BrainSlugs83

6
Com o "Modo de desenvolvedor" ativado no Windows 10, a criação de links simbólicos não requer direitos de administrador! (Outros comentaram tanto nas respostas menos votado, mas eu não vê-los Esperando este comentário é mais visível para futuros leitores..)
Dave Pascua

Respostas:


105

Você pode encontrar os links simbólicos procurando arquivos que possuam um modo de 120000, possivelmente com este comando:

git ls-files -s | awk '/120000/{print $4}'

Depois de substituir os links, recomendo marcá-los como inalterados git update-index --assume-unchanged, em vez de listá-los .git/info/exclude.


2
Eu tive que substituir o awk pelo gawk pelo msysgit, mas, caso contrário, funcionou perfeitamente. Obrigado!
Ken Hirakawa

6
helo ken. você se importaria de compartilhar seu script que verifica arquivos de texto com link simbólico e os substitui por links simbólicos no Windows usando o mklink. enquanto isso realmente funciona para nós, a parte - assumida inalterada não funciona. ao mudar para outra ramificação, o git diz que os arquivos de link simbólico são alterados e precisam ser confirmados primeiro, enquanto o status do git diz que não há alterações. Alguma idéia?
joreg

6
Aqui está um do PowerShell que acabei de montar - gist.github.com/ferventcoder/7995025
ferventcoder

3
@flungo Existem maneiras mais portáteis de imprimir a quarta coluna do que usar o GNU awk. Por exemplo: git ls-files -s | grep '^12' | cut -f2(segunda coluna delimitada por tabulação; outras colunas são delimitadas por espaço)
Zenexer 05/04

1
Um liner para que o Cygwin / bash marque todos os links simbólicos inalterados:for f in `git ls-files -s | awk '/120000/{print $4}'`; do git update-index --assume-unchanged $f; done
DaveAlden

187

Eu estava fazendo essa mesma pergunta há algum tempo (não aqui, apenas em geral) e acabei encontrando uma solução muito semelhante à proposta do OP. Primeiro, fornecerei respostas diretas às perguntas 1 2 e 3 e depois publicarei a solução que acabei usando.

  1. Na verdade, existem algumas desvantagens na solução proposta, principalmente em relação a um potencial maior de poluição do repositório ou na adição acidental de arquivos duplicados enquanto eles estão no estado "link simbólico do Windows". (Mais sobre isso em "limitações" abaixo).
  2. Sim, um script pós-checkout é implementável! Talvez não como um pós- git checkoutpasso literal , mas a solução abaixo atendeu às minhas necessidades o suficiente para que um script literal de pós-checkout não fosse necessário.
  3. Sim!

A solução:

Nossos desenvolvedores estão praticamente na mesma situação dos OP: uma mistura de hosts do Windows e do tipo Unix, repositórios e sub-módulos com muitos links simbólicos git e nenhum suporte nativo (ainda) na versão de lançamento do MsysGit para lidar com esses links simbólicos de forma inteligente nos hosts Windows .

Obrigado a Josh Lee por apontar o fato de que o git comete links simbólicos com um modo de arquivo especial 120000. Com essas informações, é possível adicionar alguns aliases do git que permitem a criação e manipulação de links simbólicos do git nos hosts do Windows.

  1. Criando links simbólicos git no Windows

    git config --global alias.add-symlink '!'"$(cat <<'ETX'
    __git_add_symlink() {
      if [ $# -ne 2 ] || [ "$1" = "-h" ]; then
        printf '%b\n' \
            'usage: git add-symlink <source_file_or_dir> <target_symlink>\n' \
            'Create a symlink in a git repository on a Windows host.\n' \
            'Note: source MUST be a path relative to the location of target'
        [ "$1" = "-h" ] && return 0 || return 2
      fi
    
      source_file_or_dir=${1#./}
      source_file_or_dir=${source_file_or_dir%/}
    
      target_symlink=${2#./}
      target_symlink=${target_symlink%/}
      target_symlink="${GIT_PREFIX}${target_symlink}"
      target_symlink=${target_symlink%/.}
      : "${target_symlink:=.}"
    
      if [ -d "$target_symlink" ]; then
        target_symlink="${target_symlink%/}/${source_file_or_dir##*/}"
      fi
    
      case "$target_symlink" in
        (*/*) target_dir=${target_symlink%/*} ;;
        (*) target_dir=$GIT_PREFIX ;;
      esac
    
      target_dir=$(cd "$target_dir" && pwd)
    
      if [ ! -e "${target_dir}/${source_file_or_dir}" ]; then
        printf 'error: git-add-symlink: %s: No such file or directory\n' \
            "${target_dir}/${source_file_or_dir}" >&2
        printf '(Source MUST be a path relative to the location of target!)\n' >&2
        return 2
      fi
    
      git update-index --add --cacheinfo 120000 \
          "$(printf '%s' "$source_file_or_dir" | git hash-object -w --stdin)" \
          "${target_symlink}" \
        && git checkout -- "$target_symlink" \
        && printf '%s -> %s\n' "${target_symlink#$GIT_PREFIX}" "$source_file_or_dir" \
        || return $?
    }
    __git_add_symlink
    ETX
    )"
    

    Uso:, em git add-symlink <source_file_or_dir> <target_symlink>que o argumento correspondente ao arquivo ou diretório de origem deve assumir a forma de um caminho relativo ao link simbólico de destino. Você pode usar esse alias da mesma maneira que usaria normalmenteln .

    Por exemplo, a árvore do repositório:

    dir/
    dir/foo/
    dir/foo/bar/
    dir/foo/bar/baz      (file containing "I am baz")
    dir/foo/bar/lnk_file (symlink to ../../../file)
    file                 (file containing "I am file")
    lnk_bar              (symlink to dir/foo/bar/)
    

    Pode ser criado no Windows da seguinte maneira:

    git init
    mkdir -p dir/foo/bar/
    echo "I am baz" > dir/foo/bar/baz
    echo "I am file" > file
    git add -A
    git commit -m "Add files"
    git add-symlink ../../../file dir/foo/bar/lnk_file
    git add-symlink dir/foo/bar/ lnk_bar
    git commit -m "Add symlinks"
    
  2. Substituindo links simbólicos git por links físicos + junções NTFS

    git config --global alias.rm-symlinks '!'"$(cat <<'ETX'
    __git_rm_symlinks() {
      case "$1" in (-h)
        printf 'usage: git rm-symlinks [symlink] [symlink] [...]\n'
        return 0
      esac
      ppid=$$
      case $# in
        (0) git ls-files -s | grep -E '^120000' | cut -f2 ;;
        (*) printf '%s\n' "$@" ;;
      esac | while IFS= read -r symlink; do
        case "$symlink" in
          (*/*) symdir=${symlink%/*} ;;
          (*) symdir=. ;;
        esac
    
        git checkout -- "$symlink"
        src="${symdir}/$(cat "$symlink")"
    
        posix_to_dos_sed='s_^/\([A-Za-z]\)_\1:_;s_/_\\\\_g'
        doslnk=$(printf '%s\n' "$symlink" | sed "$posix_to_dos_sed")
        dossrc=$(printf '%s\n' "$src" | sed "$posix_to_dos_sed")
    
        if [ -f "$src" ]; then
          rm -f "$symlink"
          cmd //C mklink //H "$doslnk" "$dossrc"
        elif [ -d "$src" ]; then
          rm -f "$symlink"
          cmd //C mklink //J "$doslnk" "$dossrc"
        else
          printf 'error: git-rm-symlink: Not a valid source\n' >&2
          printf '%s =/=> %s  (%s =/=> %s)...\n' \
              "$symlink" "$src" "$doslnk" "$dossrc" >&2
          false
        fi || printf 'ESC[%d]: %d\n' "$ppid" "$?"
    
        git update-index --assume-unchanged "$symlink"
      done | awk '
        BEGIN { status_code = 0 }
        /^ESC\['"$ppid"'\]: / { status_code = $2 ; next }
        { print }
        END { exit status_code }
      '
    }
    __git_rm_symlinks
    ETX
    )"
    
    git config --global alias.rm-symlink '!git rm-symlinks'  # for back-compat.
    

    Uso:

    git rm-symlinks [symlink] [symlink] [...]
    

    Esse alias pode remover os links simbólicos do git um por um ou todos de uma vez de uma só vez. Os links simbólicos serão substituídos por links físicos NTFS (no caso de arquivos) ou junções NTFS (no caso de diretórios). O benefício do uso de links físicos + junções sobre links simbólicos NTFS "verdadeiros" é que não são necessárias permissões UAC elevadas para que elas sejam criadas.

    Para remover links simbólicos dos submódulos, use o suporte interno do git para iterá-los:

    git submodule foreach --recursive git rm-symlinks
    

    Mas, para toda ação drástica como essa, é bom ter uma reversão ...

  3. Restaurando links simbólicos do git no Windows

    git config --global alias.checkout-symlinks '!'"$(cat <<'ETX'
    __git_checkout_symlinks() {
      case "$1" in (-h)
        printf 'usage: git checkout-symlinks [symlink] [symlink] [...]\n'
        return 0
      esac
      case $# in
        (0) git ls-files -s | grep -E '^120000' | cut -f2 ;;
        (*) printf '%s\n' "$@" ;;
      esac | while IFS= read -r symlink; do
        git update-index --no-assume-unchanged "$symlink"
        rmdir "$symlink" >/dev/null 2>&1
        git checkout -- "$symlink"
        printf 'Restored git symlink: %s -> %s\n' "$symlink" "$(cat "$symlink")"
      done
    }
    __git_checkout_symlinks
    ETX
    )"
    
    git config --global alias.co-symlinks '!git checkout-symlinks'
    

    Uso git checkout-symlinks [symlink] [symlink] [...]:, que desfaz git rm-symlinks, restaura efetivamente o repositório para seu estado natural (exceto as alterações, que devem permanecer intactas).

    E para submódulos:

    git submodule foreach --recursive git checkout-symlinks
    
  4. Limitações:

    • Diretórios / arquivos / links simbólicos com espaços em seus caminhos devem funcionar. Mas guias ou novas linhas? YMMV ... (Com isso eu quero dizer: não faça isso, porque não vai funcionar.)

    • Se você ou outras pessoas esquecerem git checkout-symlinksantes de fazer algo com conseqüências potencialmente abrangentes git add -A, o repositório local pode acabar em um estado poluído.

      Usando nosso "repositório de exemplo" de antes:

      echo "I am nuthafile" > dir/foo/bar/nuthafile
      echo "Updating file" >> file
      git add -A
      git status
      # On branch master
      # Changes to be committed:
      #   (use "git reset HEAD <file>..." to unstage)
      #
      #       new file:   dir/foo/bar/nuthafile
      #       modified:   file
      #       deleted:    lnk_bar           # POLLUTION
      #       new file:   lnk_bar/baz       # POLLUTION
      #       new file:   lnk_bar/lnk_file  # POLLUTION
      #       new file:   lnk_bar/nuthafile # POLLUTION
      #
      

      Opa ...

      Por esse motivo, é bom incluir esses aliases como etapas a serem executadas para os usuários do Windows antes e depois da criação de um projeto, em vez de após o checkout ou antes do envio. Mas cada situação é diferente. Esses aliases foram úteis o suficiente para mim, não sendo necessária uma solução verdadeira após o checkout.

Espero que ajude!

Referências:

http://git-scm.com/book/en/Git-Internals-Git-Objects

http://technet.microsoft.com/en-us/library/cc753194

Última atualização: 2019-03-13

  • Conformidade com POSIX (bem, exceto para essas mklinkchamadas, é claro) - não mais Bashisms !
  • Diretórios e arquivos com espaços neles são suportados.
  • Códigos de status de saída zero e diferente de zero (para comunicar sucesso / falha do comando solicitado, respectivamente) agora são preservados / retornados corretamente.
  • O add-symlinkalias agora funciona mais como ln (1) e pode ser usado em qualquer diretório do repositório, não apenas no diretório raiz do repositório.
  • O rm-symlinkalias (singular) foi substituído pelo rm-symlinksalias (plural), que agora aceita vários argumentos (ou nenhum argumento), que encontra todos os links simbólicos em todo o repositório, como antes) para transformar seletivamente os links simbólicos do git em links físicos NTFS + junções .
  • O checkout-symlinksalias também foi atualizado para aceitar vários argumentos (ou nenhum, == tudo) para reversão seletiva das transformações mencionadas acima.

Nota final: Embora eu tenha testado o carregamento e a execução desses aliases usando o Bash 3.2 (e até 3.1) para aqueles que ainda podem estar presos a versões antigas por várias razões, lembre-se de que versões tão antigas como essas são notórias por seu analisador insetos. Se você tiver problemas ao tentar instalar qualquer um desses aliases, a primeira coisa a se considerar é atualizar seu shell (para o Bash, verifique a versão com CTRL + X, CTRL + V). Como alternativa, se você estiver tentando instalá-los colando-os no emulador de terminal, poderá ter mais sorte colando-os em um arquivo e adquiri-lo, por exemplo, como

. ./git-win-symlinks.sh

Boa sorte!


você pode dar uma olhada aqui? stackoverflow.com/questions/21403772/…
Pateta

esse é um ótimo e maravilhoso script, mas existe alguma razão para que isso afixe ​​a palavra "git" aleatoriamente no final de alguns dos meus arquivos criados com o git add-symlink?
Peter Turner

Além disso, se o nome do arquivo contiver "-h", você obterá o uso. Ainda é um script muito útil!
Peter Turner

Sua git add-symlinkreceita foi extraordinariamente valiosa para mim. Muito Obrigado.
21915 Dan Lenski

1
Existe alguma maneira de executar automaticamente esses scripts usando ganchos?
ARF

74

A versão mais recente do git scm (testet 2.11.1) permite ativar links simbólicos. Mas você precisa clonar o repositório com os links simbólicos novamente git clone -c core.symlinks=true <URL>. Você precisa executar este comando com direitos de administrador. Também é possível criar links simbólicos no Windows com o mklink. Confira o wiki .

insira a descrição da imagem aqui


1
Isso não funcionou para mim. Reinstalei o git para Windows, lembre-se de marcar a caixa de seleção do link simbólico e clonar meu projeto novamente. Meu tslint.jsonarquivo que faz referência ao arquivo no diretório pai ainda contém ../tslint.json. Pena, porque realmente parecia a mais fácil de todas as soluções propostas lá.
Jan Aagaard

8
@ JanAagaard Você precisa cloná-lo assim: git clone -c core.symlinks=true <URL> e no Windows, você deve executá-lo com direitos de administrador.
precisa saber é o seguinte

6
@ARF "Inicie o gpedit.msc (isto é, o editor de políticas de grupo) e adicione as contas em Configuração do computador \ Configuração do Windows \ Configurações de segurança \ Diretivas locais \ Atribuição de direitos do usuário \ Criar links simbólicos."
precisa saber é o seguinte

2
@sirlunchalot Obrigado pela ajuda. Desde então, percebi que meu problema é que meu usuário faz parte do grupo Administradores e que essa propriedade não tem efeito para esses usuários. Eles exigem elevação do UAC que o git não faz.
ARF

9
Os direitos de administrador não são necessários no "Modo de desenvolvedor" na Atualização de criadores do Windows 10. Obrigado @dennis no seu comentário .
Dominik

16

Ele deve ser implementado no msysgit, mas existem duas desvantagens:

  • Links simbólicos estão disponíveis apenas no Windows Vista e posterior (não deve ser um problema em 2011, e ainda é ...), pois as versões mais antigas suportam apenas junções de diretório.
  • (a grande) A Microsoft considera os links simbólicos um risco à segurança e, portanto, apenas os administradores podem criá-los por padrão. Você precisará elevar os privilégios do processo git ou usar o fstool para alterar esse comportamento em todas as máquinas em que trabalha.

Fiz uma pesquisa rápida e há trabalho sendo feito ativamente sobre isso, veja o número 224 .


2
Atualização: pelos motivos acima, o problema foi encerrado como wontfix. A discussão indica que uma correção pode ser aceita com mais trabalho no patch (por exemplo, usando links simbólicos apenas se eles funcionarem).
Blaisorblade 10/08/2012

2
R.) Atualmente, o msysgit não suporta links simbólicos - por que não detectar "oh, você está no Vista com NTFS, deixe-me usar links simbólicos" ou "oh, você está em um sistema operacional que suporta junções com o NTFS, deixe-me usar esses ", ou" oh, você está no Windows 98 / FAT32, deixe-me recuar por não ter esse recurso e emitir um aviso! " e depois B.) Praticamente todos os desenvolvedores da Microsoft. as ferramentas não funcionam corretamente (pelo menos não para todos os recursos) se você não as executa como administrador - todos na equipe de TI sabem que os desenvolvedores precisam ser administradores em suas próprias caixas.
BrainSlugs83

1
Embora eu execute certas máquinas na conta de administrador, não sigo essa filosofia na minha máquina de desenvolvimento. Eu sempre corro como um usuário comum com o UAC ativado. Eu mantenho um console separado aberto para operações que exigem privilégios elevados. Quanto à implementação, tudo depende de alguém (como você) se voluntariar para implementá-lo. Os desenvolvedores msysgit não são conhecidos para a caridade ...
djs

@djs Um usuário precisa abrir um prompt de comando com "Executar como Administrador". Está quase literalmente funcionando como Usuário Administrador, o que altera completamente o Ambiente. Não existe uma maneira de executar 'mklink / d' como um Usuário que também esteja no grupo Admin. Não será solicitado pelo UAC. Sempre falhará. Funciona apenas de duas maneiras: Literalmente como usuário Administrador (RunAs Verb) ou Usuário não administrador com alteração de diretiva de grupo. As junções devem ser o padrão e devem ser reconhecidas por todas as ferramentas. O "risco à segurança" é que os links simbólicos no Windows podem "redirecionar" compartilhamentos SMB. Isso é uma dor e cruel.
Andrew T Finnell

8
Anunciado em dezembro de 2016, o Symlinks no Windows 10 não é mais uma ação do administrador. blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/…
Dennis

16

então, como as coisas mudaram com o GIT desde que muitas dessas respostas foram postadas aqui, estão as instruções corretas para que os links simbólicos funcionem corretamente no Windows a partir de

AGOSTO 2018


1. Verifique se o git está instalado com o suporte de link simbólico

Durante a instalação do git no windows

2. Diga ao Bash para criar links físicos em vez de links simbólicos

EDIT - (pasta git) /etc/bash.bashrc

ADICIONAR AO INFERIOR - MSYS=winsymlinks:nativestrict

3. Defina git config para usar links simbólicos

git config core.symlinks true

ou

git clone -c core.symlinks=true <URL>

NOTA: Tentei adicionar isso à configuração global do git e, no momento, ele não está funcionando para mim, então eu recomendo adicionar isso a cada repo ...

4. puxe o repositório

NOTA: A menos que você tenha ativado o modo de desenvolvedor na versão mais recente do Windows 10, é necessário executar o bash como administrador para criar links simbólicos

5. Redefinir todos os links simbólicos (opcional) Se você possui um repositório existente ou está usando sub-módulos, pode achar que os links simbólicos não estão sendo criados corretamente. Para atualizar todos os links simbólicos no repositório, você pode executar esses comandos.

find -type l -delete
git reset --hard

OBSERVAÇÃO: isso redefinirá todas as alterações desde a última confirmação, portanto, confirme primeiro


15

Resposta curta: agora eles são compatíveis, se você puder ativar o modo de desenvolvedor.

De https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/

Agora, no Windows 10 Creators Update, um usuário (com direitos de administrador) pode primeiro ativar o Modo de desenvolvedor e, em seguida, qualquer usuário na máquina pode executar o comando mklink sem elevar um console de linha de comando.

O que levou essa mudança? A disponibilidade e o uso de links simbólicos é importante para os desenvolvedores modernos:

Muitas ferramentas de desenvolvimento populares, como o git e os gerenciadores de pacotes, como o npm, reconhecem e persistem links simbólicos ao criar repositórios ou pacotes, respectivamente. Quando esses repositórios ou pacotes são restaurados em outro local, os links simbólicos também são restaurados, garantindo que o espaço em disco (e o tempo do usuário) não sejam desperdiçados.

Fácil de ignorar com todos os outros anúncios da "Atualização do criador", mas se você ativar o Modo de desenvolvedor, poderá criar links simbólicos sem privilégios elevados. Talvez você precise reinstalar o git e verifique se o suporte ao link simbólico está ativado, pois não é por padrão.

Links simbólicos não estão ativados por padrão


1
gpedit.msc-> Local Computer Policy-> Computer Configuration-> Windows Settings-> Security Settings-> Local Policies-> User Rights Assignmenttem sido a maneira canônica de atribuir direitos de usuário SeCreateSymbolicLinke amigos por muito tempo. Diferente ntrights.exedo Resource Kit ou do PowerShell ...
0xC0000022L

11

Resposta 2020

  1. Ativar "Modo de desenvolvedor" no Windows 10 - concede mklinkpermissões
  2. Verifique se os links simbólicos estão ativados no git
    • git config --global core.symlinks true
    • ou marque a caixa de seleção ao instalar o msysgit

A troca de ramificações forçará a recriação de links simbólicos ausentes.

Cuidado, o suporte ao Symlinks no Windows com outros clientes Git não está completo. Notavelmente GitKraken.


Todos os meus repositórios locais têm core.symlinks = false, que substituiriam sua solução. Alguma idéia do que está produzindo essa configuração local automaticamente? Possivelmente instalando o Git for Windows sem marcar a caixa de seleção?
gravidThoughts 25/02

@gravidPensando em quais clientes git você instalou? Talvez algumas ferramentas estejam fazendo isso? Isso é verdade em um novo clone?
Cameron Tacklind

10

Eu sugiro que você não use links simbólicos no repositório '. Armazene o conteúdo real dentro do repositório 'e coloque links simbólicos ao lado do repositório' que apontam para o conteúdo.

Digamos que você esteja usando um repositório para comparar a hospedagem do seu site no * nix com a hospedagem no win. Armazene o conteúdo em seu repo ', digamos /httpRepoContentec:\httpRepoContent sendo esta a pasta que é sincronizado via GIT, SVN etc.

Em seguida, substitua a pasta de conteúdo do seu servidor web (/var/www ec:\program files\web server\www {os nomes não importam, edite se necessário}) por um link simbólico para o conteúdo do seu repositório '. Os servidores da Web verão o conteúdo como realmente no lugar 'certo', mas você poderá usar seu controle de origem.

No entanto, se você precisar usar links simbólicos no repositório ', precisará procurar algo como algum tipo de script de confirmação pré / pós. Eu sei que você pode usá-los para fazer coisas, como analisar arquivos de código por meio de um formatador, por exemplo, para que seja possível converter os links simbólicos entre plataformas.

se alguém conhece um bom lugar para aprender como executar esses scripts para os controles de origem comuns, SVN GIT MG, adicione um comentário.


No final, escolhi essa abordagem para criar uma pasta de ligação simbólica e criar os links simbólicos para onde costumava estar o arquivo original. A outra abordagem não funcionou mesmo depois que eu mudei a configuração .git / config core.symlinks = true. Somente o arquivo de link simbólico foi salvo no repositório e não nos dados. Também teve problemas com os carimbos de data e hora da pasta no link simbólico, de modo que o git bash nunca viu quando um arquivo foi alterado dentro da pasta.
Eggs

@ Egg, o que você pode estar vendo, eu acho, é que o link estava dentro do repositório e, portanto, o git o salvou, simples. O problema, porém, é que o destino estava fora do repositório e o git não segue o link para os dados do destino. No linux, você tem um tipo de link que funcionaria para isso, basicamente temos dois caminhos para os mesmos dados armazenados no disco; Tenho a sensação de que janelas novas podem fazer isso agora. De qualquer forma, ainda não acho que isso fará o que as pessoas querem.
Thecoshman

@thecoshman Esta não é uma solução, mas uma solução alternativa. No entanto, às vezes isso não é uma opção. Eu tenho um repositório com git-anexo e toda sua arquitetura funciona por causa de links simbólicos.
Marcelo.guedes

8

Para aqueles que usam o CygWin no Vista, Win7 ou superior, o gitcomando nativo pode criar links simbólicos "adequados" que são reconhecidos por aplicativos do Windows, como o Android Studio . Você só precisa definir a CYGWINvariável de ambiente para incluir winsymlinks:nativeou winsymlinks:nativestrictcomo tal:

export CYGWIN="$CYGWIN winsymlinks:native"

A desvantagem disso (e uma significativa) é que o shell do CygWin precisa ser "Executar como Administrador" para ter as permissões de SO necessárias para criar esse tipo de links simbólicos. Porém, uma vez criados, nenhuma permissão especial é necessária para usá- los. Desde que não sejam alterados no repositório por outro desenvolvedor,git partir de então funcionará bem com permissões normais de usuário.

Pessoalmente, eu uso apenas isso para links simbólicos que são navegados por aplicativos do Windows (ou seja, não CygWin) devido a essa dificuldade adicional.

Para obter mais informações sobre esta opção, consulte esta pergunta do SO: Como fazer um link simbólico com o cygwin no Windows 7


6

Aqui está um script em lote para converter links simbólicos no repositório, apenas para arquivos, com base na resposta de Josh Lee. O script com alguma verificação adicional dos direitos de administrador está em https://gist.github.com/Quazistax/8daf09080bf54b4c7641 .

@echo off
pushd "%~dp0"
setlocal EnableDelayedExpansion

for /f "tokens=3,*" %%e in ('git ls-files -s ^| findstr /R /C:"^120000"') do (
     call :processFirstLine %%f
)
REM pause
goto :eof

:processFirstLine
@echo.
@echo FILE:    %1

dir "%~f1" | find "<SYMLINK>" >NUL && (
  @echo FILE already is a symlink
  goto :eof
)

for /f "usebackq tokens=*" %%l in ("%~f1") do (
  @echo LINK TO: %%l

  del "%~f1"
  if not !ERRORLEVEL! == 0 (
    @echo FAILED: del
    goto :eof
  )

  setlocal
  call :expandRelative linkto "%1" "%%l"
  mklink "%~f1" "!linkto!"
  endlocal
  if not !ERRORLEVEL! == 0 (
    @echo FAILED: mklink
    @echo reverting deletion...
    git checkout -- "%~f1"
    goto :eof
  )

  git update-index --assume-unchanged "%1"
  if not !ERRORLEVEL! == 0 (
    @echo FAILED: git update-index --assume-unchanged
    goto :eof
  )
  @echo SUCCESS
  goto :eof
)
goto :eof

:: param1 = result variable
:: param2 = reference path from which relative will be resolved
:: param3 = relative path
:expandRelative
  pushd .
  cd "%~dp2"
  set %1=%~f3
  popd
goto :eof

Uma resposta não documentada não é realmente muito útil quando já existem respostas longas e detalhadas.
Xennex81

4

Eu uso links sym o tempo todo entre a raiz do documento e o diretório git repo. Eu gosto de mantê-los separados. No Windows eu uso a opção mklink / j. A junção parece permitir que o git se comporte normalmente:

>mklink /j <location(path) of link> <source of link>

por exemplo:

>mklink /j c:\gitRepos\Posts C:\Bitnami\wamp\apache2\htdocs\Posts


2
Tenha muito cuidado com o Windows Explorer e junções; ele não diferencia as junções do local base e uma exclusão recuará no destino e excluirá seu conteúdo, enquanto a exclusão de um link simbólico apenas removerá o link simbólico. Apenas uma armadilha para os incautos.
Lawrence Dol

5
Na verdade, apenas testei isso no Windows7 mais recente, e ele não o faz mais, então o manuseio de junções foi aprimorado em algum momento nos últimos anos.
Lawrence Dol

3

Eu estava procurando uma solução fácil para lidar com os links simbólicos unix no Windows. Muito obrigado pelos aliases do Git acima. Há uma pequena otimização que pode ser feita nos rm-symlinks, para que não exclua os arquivos na pasta de destino, caso o alias seja executado uma segunda vez acidentalmente. Observe a nova condição if no loop para garantir que o arquivo ainda não seja um link para um diretório antes da execução da lógica.

git config --global alias.rm-symlinks '!__git_rm_symlinks(){
for symlink in $(git ls-files -s | egrep "^120000" | cut -f2); do
    *if [ -d "$symlink" ]; then
      continue
    fi*
    git rm-symlink "$symlink"
    git update-index --assume-unchanged "$symlink"
done
}; __git_rm_symlinksenter 

2

Um truque simples que usamos é chamar apenas git add --allduas vezes seguidas.

Por exemplo, nosso script de confirmação do Windows 7 chama:

$ git add --all
$ git add --all

A primeira adição trata o link como texto e adiciona as pastas para exclusão.

A segunda adição percorre o link corretamente e desfaz a exclusão restaurando os arquivos.

É menos elegante do que algumas das outras soluções propostas, mas é uma correção simples para alguns de nossos ambientes legados que adicionaram links simbólicos.

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.