Git Символы в Windows

Наши разработчики используют сочетание ОС Windows и Unix. Поэтому символические ссылки, созданные на машинах Unix, становятся проблемой для разработчиков Windows. В windows (msysgit) символическая ссылка преобразуется в текстовый файл с указанием пути к файлу, на который он указывает. Вместо этого я хотел бы преобразовать символическую ссылку в символическую ссылку Windows.

Решение (обновлено), которое у меня есть:

  • Напишите post-checkout script, который будет рекурсивно искать текстовые файлы symlink.
  • Замените их символической ссылкой Windows (используя mklink) с тем же именем и расширением, что и фиктивная "символическая ссылка"
  • Игнорировать эти символические ссылки Windows, добавив запись в .git/info/exclude

Я не реализовал это, но считаю, что это надежный подход к этой проблеме.

Вопросы:

  • Что, если таковые имеются, то вы видите этот подход?
  • Является ли этот пост-checkout script даже выполнимым? то есть я могу рекурсивно узнать фиктивные "символические" файлы git создает?
  • Кто-нибудь уже работал над такими script?

Ответ 1

Вы можете найти символические ссылки, ища файлы с режимом 120000, возможно, с помощью этой команды:

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

После того, как вы замените ссылки, я бы рекомендовал маркировать их как неизменные с помощью git update-index --assume-unchanged, а не перечислять их в .git/info/exclude.

Ответ 2

Я задавал этот один и тот же вопрос некоторое время назад (не здесь, как правило, вообще), и в итоге получилось очень похожее решение предложения OP. Сначала я дам прямые ответы на вопросы 1 2 и 3, а затем опубликую решение, которое я использовал.

  1. В предлагаемом решении действительно несколько недостатков, главным образом в отношении увеличения потенциала загрязнения репозитория или случайного добавления дубликатов файлов, когда они находятся в состоянии "символической ссылки Windows". (Подробнее об этом см. Ниже "Ограничения").
  2. Да, сценарий проверки post- можно реализовать! Возможно, это не так, как буквальный шаг post- git checkout, но приведенное ниже решение удовлетворило мои потребности достаточно хорошо, чтобы буквальный post- скрипт проверки не был необходим.
  3. Да!

Решение:

Наши разработчики в той же ситуации, что и OP: смесь Windows и Unix-хостов, репозиториев и подмодулей со многими символическими ссылками git, а также нет встроенной поддержки в выпуске MsysGit для интеллектуальной обработки этих символических ссылок на хостах Windows,

Благодаря Джошу Ли за то, что git совершает символические ссылки со специальным файловым номером 120000. С помощью этой информации можно добавить несколько git-псевдонимов, которые позволяют создавать и манипулировать символическими ссылками git на хостах Windows.

  1. Создание символических ссылок git в Windows

    ОБНОВЛЕНО 2014-11-12 (см. Ниже)

    git config --global alias.add-symlink '!__git_add_symlink(){
        argv=([email protected])
        argc=${#argv[@]}
    
        # Look for options
        options=(" -h")
        o_help="false"
        case "${argv[@]}" in *" -h"*) o_help="true" ;; esac
        if [ "$o_help" == "true" -o "$argc" -lt "2" ]; then
            echo "\
    Usage: git add-symlink <target> <link>
    
    * <target> is a RELATIVE PATH, respective to <link>.
    * <link> is a RELATIVE PATH, respective to the repository'\' root dir.
    * Command must be run from the repository'\' root dir."
            return 0
        fi
    
        target_arg=${argv[0]}
        link_arg=${argv[1]}
    
        if [ ! -e "$target_arg" ]; then
            echo "ERROR: Target $target_arg does not exist; not creating invalid symlink."
            return 1
        fi
    
        hash=$(echo -n "$target_arg" | git hash-object -w --stdin)
        git update-index --add --cacheinfo 120000 "$hash" "$link_arg"
        git checkout -- "$link_arg"
    
    }; __git_add_symlink "[email protected]"'
    

    Использование: git add-symlink <src> <dst>, где <src> - относительная ссылка (по отношению к <dst>) к текущему местоположению файла или каталога для ссылки, а <dst> - относительная ссылка (в отношении корня репозитория) к ссылке желаемого адресата.

    Например, дерево репозитория:

    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/)
    

    Может быть создан в Windows следующим образом:

    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. Замена символических ссылок git на жесткие ссылки NTFS + переходы

    git config --global alias.rm-symlink '!__git_rm_symlink(){
        git checkout -- "$1"
        link=$(echo "$1")
        POS=$'\''/'\''
        DOS=$'\''\\\\'\''
        doslink=${link//$POS/$DOS}
        dest=$(dirname "$link")/$(cat "$link")
        dosdest=${dest//$POS/$DOS}
        if [ -f "$dest" ]; then
            rm -f "$link"
            cmd //C mklink //H "$doslink" "$dosdest"
        elif [ -d "$dest" ]; then
            rm -f "$link"
            cmd //C mklink //J "$doslink" "$dosdest"
        else
            echo "ERROR: Something went wrong when processing $1 . . ."
            echo "       $dest may not actually exist as a valid target."
        fi
    }; __git_rm_symlink "$1"'
    
    git config --global alias.rm-symlinks '!__git_rm_symlinks(){
        for symlink in $(git ls-files -s | egrep "^120000" | cut -f2); do
            git rm-symlink "$symlink"
            git update-index --assume-unchanged "$symlink"
        done
    }; __git_rm_symlinks'
    

    Применение:

    git rm-symlink dir/foo/bar/lnk_file
    git rm-symlink lnk_bar
    git update-index --assume-unchanged dir/foo/bar/lnk_file
    git update-index --assume-unchanged lnk_bar
    

    Это удаляет git-символические ссылки один за другим, заменяя их жесткими ссылками NTFS (в случае файлов) или соединениями NTFS (в случае каталогов). Преимущество использования ссылок hardlinks + над "истинными" символическими ссылками NTFS заключается в том, что для того, чтобы они могли быть созданы, не требуются повышенные права UAC. Наконец, на собственном отдыхе вы можете отключить -A s-модифицированные (или не) "удаленные" символические ссылки с помощью git update-index.

    Для удобства вы также можете запустить:

    git rm-symlinks
    

    Это удаляет ВСЕ ссылки git symlinks в текущем репозитории, заменяя их жесткими ссылками + переходы по мере необходимости и автоматически помещая изменения, которые следует игнорировать по git status.

    Чтобы удалить символические ссылки из подмодулей, просто используйте встроенную поддержку git для итерации по ним:

    git submodule foreach --recursive git rm-symlinks
    

    Но, для каждого такого радикального действия, как это, обратное приятно иметь...

  3. Восстановление символических ссылок git в Windows

    git config --global alias.checkout-symlinks '!__git_checkout_symlinks(){
        POS=$'\''/'\''
        DOS=$'\''\\\\'\''
        for symlink in $(git ls-files -s | egrep "^120000" | cut -f2); do
            git update-index --no-assume-unchanged "$symlink"
            dossymlink=${symlink//$POS/$DOS}
            cmd //C rmdir //Q "$dossymlink" 2>/dev/null
            git  checkout -- "$symlink"
            echo "Restored git symlink $symlink <<===>> $(cat $symlink)"
        done
    }; __git_checkout_symlinks'
    

    Использование: git checkout-symlinks, который отменяет git rm-symlinks, эффективно восстанавливая хранилище до его естественного состояния (за исключением ваших изменений, которые должны оставаться неизменными).

    А для подмодулей:

    git submodule foreach --recursive git checkout-symlinks
    
  4. Ограничения:

    1. Может быть запущен только из корня репо, иначе произойдет странность...
    2. Автоматическое заполнение на основе табуляции нарушается при вводе одного из этих псевдонимов
    3. Если люди забывают git checkout-symlinks прежде чем делать что-то вроде git add -A, они могут загрязнить репо!

      Используя наш "пример репо" от:

      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
      #
      

      Упс...

      По этой причине приятно включить эти псевдонимы в качестве шагов для выполнения для пользователей Windows до того, как -A nd -A создаст проект, а не после проверки или до нажатия. Но каждая ситуация другая. Эти псевдонимы были достаточно полезны для меня, что настоящая post- проверка не требовалась.

Надеюсь, это поможет!

Рекомендации:

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

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

UPDATE 2014-11-12: потому что я лично только когда-либо очень активно использовал псевдонимы rm-symlinks и checkout-symlinks выше, мне удалось упустить довольно неприятную ошибку в псевдониме add-symlink. Ранее -n не получалось передаваться в echo оператор, ответственный за создание файла ссылки git, который позже будет добавлен в промежуточную область как часть операции add-symlink. Это означает, что конечная 0x0D 0x0A (0x0D 0x0A на хостах Windows) добавлялась ко всем символическим ссылкам git, созданным с помощью add-symlink. Хотя эти символические ссылки git по-прежнему будут "удаляться" на хостах Windows с помощью rm-symlinks просто отлично, если они когда-либо были преданы публичному репо и позже клонированы в подлинной системе на основе posix, эти ссылки всегда будут нарушены на другом боковая сторона. Эта проблема исправлена, и add-symlink теперь должен работать так, как ожидалось.

Ответ 3

Самая последняя версия git scm (testet 2.11.1) позволяет включить символические ссылки. Но вы снова должны клонировать репозиторий с символическими ссылками git clone -c core.symlinks=true <URL>. Вам нужно запустить эту команду с правами администратора. Также возможно создать символические ссылки на Windows с помощью mklink. Проверьте wiki.

enter image description here

Ответ 4

Он должен быть реализован в msysgit, но есть два недостатка:

  • Символьные ссылки доступны только в Windows Vista и более поздних версиях (это не должно быть проблемой в 2011 году, и все же это...), поскольку более старые версии поддерживают только ссылки на каталоги.
  • (большой) Microsoft рассматривает символические ссылки как угрозу безопасности, поэтому только администраторы могут создавать их по умолчанию. Вам нужно будет повысить привилегии процесса git или использовать fstool, чтобы изменить это поведение на каждом компьютере, на котором вы работаете.

Я сделал быстрый поиск, и там активная работа над этим, см. вопрос 224.

Ответ 5

Я бы предположил, что вы не используете символические ссылки в репо. Храните фактический контент внутри репо ', а затем разместите символические ссылки на стороне репо', указывающей на содержимое.

Итак, скажем, вы используете репо ', чтобы сравнить хостинг вашего сайта на * nix с хостингом на выигрыше. Сохраните содержимое в своем репо ', скажем /httpRepoContent и c:\httpRepoContent, поскольку это папка, которая синхронизируется через GIT, SVN и т.д.

Затем замените папку содержимого вашего веб-сервера (/var/www и c:\program files\web server\www {имена действительно не имеют значения, отредактируйте, если нужно}) с символической ссылкой на контент вашего репо. Веб-серверы будут видеть контент как на самом деле в "правильном" месте, но вы можете использовать свой источник управления.

Однако, если вам нужно использовать символические ссылки в репо ', вам нужно будет изучить нечто вроде скриптов pre/post commit. Я знаю, что вы можете использовать их, чтобы делать что-то, например, файлы кода синтаксического анализа через форматирование, например, чтобы было возможно преобразовать символические ссылки между платформами.

если кто-то знает хорошее место, чтобы узнать, как делать эти сценарии для общих элементов управления источником, SVN GIT MG, то добавьте комментарий.

Ответ 6

Для тех, кто использует CygWin в Vista, Win7 или выше, команда native git может создавать "правильные" символические ссылки, которые распознаются приложениями Windows, такими как Android Studio. Вам просто нужно установить переменную среды CYGWIN, чтобы включить winsymlinks:native или winsymlinks:nativestrict как таковой:

export CYGWIN="$CYGWIN winsymlinks:native"

Недостатком этого (и значительного в этом) является то, что оболочка CygWin должна быть "Запуск от имени администратора", чтобы иметь разрешения ОС, необходимые для создания подобных символических ссылок. Однако, если они созданы, для их использования не требуются специальные разрешения. До тех пор, пока они не будут изменены в репозитории другим разработчиком, git после этого будет нормально работать с обычными правами пользователя.

Лично я использую это только для символических ссылок, которые перемещаются приложениями Windows (т.е. не CygWin) из-за этой дополнительной трудности.

Для получения дополнительной информации об этой опции см. этот вопрос SO: Как сделать символическую ссылку с cygwin в Windows 7

Ответ 7

Вот пакет script для преобразования символических ссылок в репозиторий, только для файлов, основанных на ответе Джоша Ли. script с дополнительной проверкой прав администратора на 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

Ответ 8

Короткий ответ: теперь они хорошо поддерживаются, если вы можете включить режим разработчика.

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

Теперь в Windows 10 Creators Update пользователь (с правами администратора) может сначала включить режим разработчика, а затем любой пользователь на машине может запустить команду mklink без повышения командной строки.

Что привело к этому изменению? Доступность и использование символических ссылок - это большое дело для современных разработчиков:

Многие популярные инструменты разработки, такие как git и менеджеры пакетов, такие как npm, распознают и сохраняют символические ссылки при создании репозиториев или пакетов соответственно. Когда эти репозитории или пакеты затем восстанавливаются в другом месте, символические ссылки также восстанавливаются, обеспечивая свободное пространство на диске (и время пользователя).

Легко упускать из виду все другие анонсы "Творческого обновления", но если вы включите режим разработчика, вы можете создавать символические ссылки без повышенных привилегий. Возможно, вам придется переустановить и убедиться, что поддержка включена, так как она не по умолчанию.

Symbolic Links aren't enabled by default

Ответ 9

Я искал легкое решение для решения символических ссылок unix на окнах. Большое спасибо за вышеупомянутые псевдонимы Git. Существует одна небольшая оптимизация, которая может быть выполнена с помощью rm-symlinks, чтобы она не удаляла файлы в целевой папке в случае, если псевдоним запускается во второй раз случайно. Пожалуйста, соблюдайте новое условие if в цикле, чтобы убедиться, что файл еще не является ссылкой на каталог до запуска логики.

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 

Ответ 10

Я использую сим-ссылки все время между моим корнем документа и каталогом git repo. Мне нравится держать их в покое. В окнах я использую параметр mklink/j. Соединение, кажется, позволяет git вести себя нормально:

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

например:

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

Ответ 11

Один простой трюк, который мы используем, - просто называть git add --all дважды подряд.

Например, наш скрипт фиксации Windows 7 вызывает:

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

Первое добавление рассматривает ссылку как текст и добавляет папки для удаления.

Второе добавляет правильную трассировку ссылки и отменяет удаление путем восстановления файлов.

Он менее изящный, чем некоторые другие предлагаемые решения, но это простое решение для некоторых из наших устаревших сред, которые добавили символические ссылки.

Ответ 12

так как все изменилось с GIT, поскольку многие из этих ответов были опубликованы здесь, являются правильными инструкциями по правильному отображению символических ссылок в окнах с

АВГУСТ 2018


1. Убедитесь, что git установлен с поддержкой symlink

During the install of git on windows

2. Скажите Bash, чтобы создать жесткие ссылки вместо символических ссылок

EDIT - (папка git)/etc/bash.bashrc

ДОБАВИТЬ В НОМЕР - MSYS=winsymlinks:nativestrict

3. Установите git config для использования символических ссылок

git config core.symlinks true

или

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

ПРИМЕЧАНИЕ. Я попытался добавить это в глобальную конфигурацию git, и в настоящий момент он не работает для меня, поэтому я рекомендую добавить это к каждому репо...

4. Потяните репо

ПРИМЕЧАНИЕ. Если вы не включили режим разработчика в последней версии Windows 10, вам нужно запустить bash как администратор для создания символических ссылок

5. Сбросьте все Symlinks (необязательно). Если у вас есть существующее репо или вы используете подмодули, вы можете обнаружить, что символические ссылки создаются неправильно, поэтому для обновления всех символических ссылок в репо вы можете запускать эти команды.

find -type l -delete
git reset --hard

ПРИМЕЧАНИЕ. Это приведет к сбросу любых изменений с момента последнего фиксации, поэтому убедитесь, что вы совершили первый