WindowsのGit Symlinks


246

私たちの開発者は、WindowsとUnixベースのOSを組み合わせて使用​​しています。したがって、UNIXマシンで作成されたシンボリックリンクは、Windows開発者にとって問題になります。Windows(msysgit)では、シンボリックリンクは、それが指すファイルへのパスを含むテキストファイルに変換されます。代わりに、シンボリックリンクを実際のWindowsシンボリックリンクに変換したいと思います。

私がこれに持っている(更新された)解決策は:

  • 「symlink」テキストファイルを再帰的に探すチェックアウト後のスクリプトを記述します。
  • それらを、ダミーの「シンボリックリンク」と同じ名前と拡張子を持つWindowsシンボリックリンク(mklinkを使用)に置き換えます。
  • .git / info / excludeにエントリを追加して、これらのウィンドウのsymlinkを無視します

私はこれを実装していませんが、これはこの問題へのしっかりしたアプローチだと思います。

質問:

  1. このアプローチには、どんな欠点があると思いますか?
  2. このチェックアウト後のスクリプトは実装可能ですか?つまり、gitが作成するダミーの「symlink」ファイルを再帰的に見つけることができますか?
  3. 誰かがそのようなスクリプトにすでに取り組んでいますか?

3
Gitはシンボリックリンクをサポートしていますが、特に Windowsでそのコードを使用している場合は、それらをリンクとしてリポジトリに保存しないことを強くお勧めします。
グレッグヒューギル

2
@グレッグヒューギル-私はあなたに完全に同意します。残念ながら、コードベースの性質上、シンボリックリンクが必要です...したがって、それらを削除することは私たちにとって選択肢ではありません。
平川健

12
また、msysgitメーリングリストで、そもそもなぜそのように実装しなかったのかを質問することもできます。
2011年

8
@GregHewgillどうして?Windowsは、シンボリックリンクとジャンクションの両方をサポートしています-これは、GitのWindowsバージョンに欠けている機能のようです...
BrainSlugs83

6
Windows 10で「開発者モード」が有効になっている場合、シンボリックリンクを作成するために管理者権限は必要ありません。(他の人はあまり投票されていない回答について同じくらいコメントしましたが、私はそれらを見ませんでした。このコメントが将来の読者にもっと見られることを望んでいます。)
Dave Pascua 2018

回答:


105

120000次のコマンドを使用して、モードがのファイルを探すことでシンボリックリンクを見つけることができます。

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

リンクを置き換えたらgit update-index --assume-unchanged、それらをにリストするのではなく、で未変更としてマークすることをお勧めします.git/info/exclude


2
msysgitでは、awkをgawkに置き換える必要がありましたが、それ以外の場合は完全に機能しました。ありがとう!
平川健

6
helo ken。シンボリックリンクテキストファイルをチェックし、mklinkを使用してウィンドウ上でシンボリックリンクに置き換えるスクリプトを共有していただけませんか。これは実際には機能しますが、--assume-unchanged部分は機能しません。別のブランチに切り替えると、gitはシンボリックリンクファイルが変更され、最初にコミットする必要があると表示しますが、git statusは変更がないと表示します。
joreg

6
これが私がまとめたPowerShellの1つです-gist.github.com/ferventcoder/7995025
ferventcoder

3
@flungo GNU awkを使用するよりも、4番目の列を印刷する移植性の高い方法があります。例:git ls-files -s | grep '^12' | cut -f2(2番目のタブ区切りの列。他の列はスペースで区切られています)
Zenexer

1
Cygwin / bashの1つのライナーですべてのシンボリックリンクを未変更としてマーク:for f in `git ls-files -s | awk '/120000/{print $4}'`; do git update-index --assume-unchanged $f; done
DaveAlden

187

私はしばらく前にこれとまったく同じ質問をしていましたが(ここではなく、一般的に)、OPの提案に対する非常に類似した解決策が思い付きました。最初に、質問1、2、3に直接回答します。次に、使用してしまったソリューションを投稿します。

  1. 実際、提案されたソリューションには、主にリポジトリ汚染の可能性の増加、または「Windowsシンボリックリンク」状態の間に誤って重複ファイルを追加することに関して、いくつかの欠点があります。(これについては、以下の「制限事項」で詳しく説明します。)
  2. はい、チェックアウト後のスクリプトを実装できます!多分文字通りのポストgit checkoutステップとしてではないかもしれませんが、以下の解決策は十分に私のニーズを満たし、文字通りのポストチェックアウトスクリプトは不要でした。
  3. はい!

ソリューション:

私たちの開発者はOPとほとんど同じ状況にあります:WindowsとUnixのようなホスト、リポジトリとサブモジュールの多くのgitシンボリックリンクが混在しており、リリースバージョンのMsysGitには(まだ)Windowsホストでこれらのシンボリックリンクをインテリジェントに処理するためのネイティブサポートがありません。 。

gitが特別なファイルモードでシンボリックリンクをコミットするという事実を指摘してくれたJosh Leeに感謝し120000ます。この情報を使用して、Windowsホストでのgitシンボリックリンクの作成と操作を可能にするいくつかのgitエイリアスを追加できます。

  1. Windowsでのgitシンボリックリンクの作成

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

    使用法:git add-symlink <source_file_or_dir> <target_symlink>、ここで、ソースファイルまたはディレクトリに対応する引数は、ターゲットシンボリックリンクに対する相対パスの形式をとる必要がありますこのエイリアスは、通常使用するのと同じ方法で使用できますln

    たとえば、リポジトリツリー:

    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-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.
    

    使用法:

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

    このエイリアスは、git symlinkを1つずつ、または一度にすべて削除することができます。シンボリックリンクは、NTFSハードリンク(ファイルの場合)またはNTFSジャンクション(ディレクトリの場合)に置き換えられます。「真の」NTFSシンボリックリンクよりもハードリンク+ジャンクションを使用する利点は、それらを作成するために高度なUACアクセス許可が必要ないことです。

    サブモジュールからシンボリックリンクを削除するには、gitの組み込みサポートを使用して、それらを反復処理します。

    git submodule foreach --recursive git rm-symlinks
    

    しかし、このようなすべての抜本的なアクションについては、逆転が必要です...

  3. Windowsでのgitシンボリックリンクの復元

    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'
    

    使用法:git checkout-symlinks [symlink] [symlink] [...]、元に戻すgit rm-symlinks効果(変更を除きその自然状態にリポジトリを復元し、必要がありそのままとどまります)。

    そしてサブモジュールの場合:

    git submodule foreach --recursive git checkout-symlinks
    
  4. 制限:

    • パスにスペースが含まれているディレクトリ/ファイル/シンボリックリンクは機能するはずです。しかしタブか改行か?YMMVは...(これによって私は意味:それをしない、ので、それはないだろう作品。)

    • 自分や他の人がのよう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ユーザーが実行する手順としてこれらのエイリアスを含めると便利です。しかし、それぞれの状況は異なります。これらのエイリアスは私にとって十分に有用であり、実際のチェックアウト後のソリューションは必要ありませんでした。

お役に立てば幸いです。

参照:

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

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

最終更新:2019-03-13

  • POSIX準拠(もちろん、これらのmklink呼び出しを除いて)— バシズムはもうありません!
  • スペースを含むディレクトリとファイルがサポートされています。
  • ゼロおよびゼロ以外の終了ステータスコード(それぞれ、要求されたコマンドの成功/失敗を伝えるため)が適切に保存/返されるようになりました。
  • add-symlink別名は現在、より多くのと同じように動作LN(1)とリポジトリだけでなく、リポジトリのルートディレクトリにある任意のディレクトリから使用することができます。
  • rm-symlinkエイリアス(単数形)は取って代わられているrm-symlinksNTFSハードリンク+接合に選択的変換のGitシンボリックリンクのために(以前のように、リポジトリ全体にシンボリックリンクの全てを検索し、または全く引数)が複数の引数を受け付ける別名(複数) 。
  • checkout-symlinksエイリアスは、(==、まったくまたはnoneすべて)複数の引数を受け入れるために、前述の変換の選択的な反転のために更新されています。

最後の注意:いくつかの理由でこのような古いバージョンで立ち往生している可能性がある人のために、Bash 3.2(さらには3.1)を使用してこれらのエイリアスのロードと実行をテストしましたが、これらの古いバージョンはパーサーで悪名高いことに注意してくださいバグ。これらのエイリアスのいずれかをインストールしようとしたときに問題が発生した場合、最初に調べる必要があるのはシェルのアップグレードです(Bashの場合は、CTRL + X、CTRL + Vでバージョンを確認してください)。あるいは、それらをターミナルエミュレータに貼り付けてインストールしようとしている場合、それらをファイルに貼り付けて、代わりにそれを調達するなどの幸運があるかもしれません。

. ./git-win-symlinks.sh

幸運を!


こちらでご覧いただけますか?stackoverflow.com/questions/21403772/…–
グーフィー、

これは素晴らしいスクリプトですが、git add-symlinkを使用して作成したファイルの最後にランダムに「git」という単語を付ける必要がある理由はありますか?
Peter Turner

また、ファイル名に「-h」が含まれている場合は、使用方法が表示されます。それでも非常に便利なスクリプトです!
Peter Turner

あなたのgit add-symlinkレシピは私にとって非常に貴重でした。どうもありがとう。
Dan Lenski 2015

1
フックを使用してこれらのスクリプトを自動的に実行する方法はありますか?
ARF

74

最新バージョンのgit scm(testet 2.11.1)では、シンボリックリンクを有効にできます。しかし、再びシンボリックリンクでリポジトリを複製する必要がありますgit clone -c core.symlinks=true <URL>。このコマンドは、管理者権限で実行する必要があります。Windowsでmklinkを使用してシンボリックリンクを作成することもできます。wikiをチェックしてください。

ここに画像の説明を入力してください


1
これは私にはうまくいきませんでした。git for Windowsを再インストールしました。symlinkチェックボックスをオンにして、プロジェクトのクローンを再度作成してください。私のtslint.json親ディレクトリ内のファイルを参照するファイルがまだ含まれてい../tslint.json。残念ですが、これはそこで提案されているソリューションの中で最も簡単なもののように見えました。
Jan Aagaard 2017

8
@JanAagaard次のようにクローンを作成するgit clone -c core.symlinks=true <URL> 必要があります。Windowsでは、管理者権限で実行する必要があります。
sirlunchalot 2017

6
@ARF "gpedit.msc(つまり、グループポリシーエディター)を起動し、アカウントをコンピューターの構成\ Windowsの設定\セキュリティの設定\ローカルポリシー\ユーザー権利の割り当て\シンボリックリンクの作成に追加します。"
sirlunchalot 2017年

2
@sirlunchalot助けてくれてありがとう。その後、私の問題は自分のユーザーがAdministratorsグループの一部であり、このプロパティがこれらのユーザーに影響を与えないことであることに気付きました。gitが行わないUAC昇格が必要です。
ARF

9
Windows 10 Creators Updateの「開発者モード」では、管理者権限は不要です。コメントで @dennisに感謝します。
ドミニク2017

16

msysgitで実装する必要がありますが、2つの欠点があります。

  • 古いバージョンはディレクトリジャンクションのみをサポートしているため、シンボリックリンクはWindows Vista以降でのみ使用できます(2011年には問題にならないはずですが、まだ問題です)。
  • Microsoftはシンボリックリンクをセキュリティリスクと見なしているため、デフォルトで作成できるのは管理者だけです。作業しているすべてのマシンでこの動作を変更するには、gitプロセスの権限を昇格するか、fstoolを使用する必要があります。

私はクイック検索を行いましたが、これに関して積極的に行われている作業があります。問題224を参照してください。


2
更新:上記の理由により、問題はwontfixとしてクローズされました。ディスカッションは、修正がパッチでのいくつかの作業で受け入れられる可能性があることを示しています(たとえば、シンボリックリンクは使用できる場合にのみ使用します)。
Blaisorblade、2012

2
A.)現在、msysgitはシンボリックリンクをまったくサポートしていません。「ああ、NTFSでビスタにいるなら、シンボリックリンクを使用させて」または「ああ、NTFSとのジャンクションをサポートするOSである」を検出しないようにしてください。それらを使用させて」または「ああ、あなたはWindows 98 / fat32を使用しています。この機能を持たず、代わりに警告を表示することにフォールバックさせてください!」B)マイクロソフトの開発者のほとんどすべて。ツールを管理者として実行しないと、ツールは正しく機能しません(少なくともすべての機能に対してではありません)。開発者は自分のボックスの管理者である必要があることをITの誰もが知っています。
BrainSlugs83 2013

1
私は特定のマシンを管理者アカウントで実行していますが、開発マシンではその哲学に従っていません。私は常にUACが有効な通常のユーザーとして実行しています。管理者特権を必要とする操作のために、別のコンソールを開いたままにします。これを実装することに関しては、それを実装するために志願する誰か(あなたのような)にかかっています。msysgit開発者は慈善活動で知られていません...
djs

@djsユーザーは、「管理者として実行」でコマンドプロンプトを開く必要があります。ほとんど完全に文字通り、環境を完全に変更する管理者ユーザーとして実行されています。管理者グループにも属しているユーザーとして「mklink / d」を実行する方法はありません。UACプロンプトは表示されません。常に失敗します。それが機能する方法は2つだけです。文字通り、管理者ユーザー(RunAs動詞)として、またはグループポリシーが変更された非管理者ユーザーです。ジャンクションはデフォルトであり、すべてのツールで認識される必要があります。「セキュリティリスク」は、Windows上のシンボリックリンクがSMB共有を「リダイレクト」できることです。これは苦痛で残酷です。
Andrew T Finnell 2016

8
2016年12月に発表されたWindows 10のSymlinksは、管理者による操作ではなくなりました。 blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/...
デニス

16

これらの回答の多くがここに投稿されてからGITで状況が変化したため、シンボリックリンクをWindowsで正しく機能させるための正しい手順です

2018年8月


1. gitがsymlinkサポート付きでインストールされていることを確認します

Windowsへのgitのインストール中

2.シンボリックリンクの代わりにハードリンクを作成するようにBashに指示します

編集-(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.すべてのシンボリックリンクをリセットする(オプション)既存のリポジトリがある場合、またはサブモジュールを使用している場合は、シンボリックリンクが正しく作成されていないため、これらのコマンドを実行して、リポジトリ内のすべてのシンボリックリンクを更新できます。

find -type l -delete
git reset --hard

注:これにより、最後のコミット以降の変更がリセットされるため、最初にコミットしたことを確認してください


15

短い答え:開発者モードを有効にできる場合、これらは適切にサポートされます。

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

現在、Windows 10 Creators Updateでは、(管理者権限を持つ)ユーザーが最初に開発者モードを有効にしてから、マシン上のすべてのユーザーがコマンドラインコンソールを昇格せずにmklinkコマンドを実行できます。

この変化の原因は何ですか?シンボリックリンクの可用性と使用は、現代の開発者にとって大きな問題です。

gitのような多くの一般的な開発ツールとnpmのようなパッケージマネージャーは、それぞれリポジトリまたはパッケージを作成するときにシンボリックリンクを認識して永続化します。これらのリポジトリまたはパッケージが他の場所に復元されると、シンボリックリンクも復元され、ディスク容量(およびユーザーの時間)が無駄にならないようにします。

「Creator's update」の他のすべてのアナウンスで見落としがちですが、開発者モードを有効にすると、昇格した権限なしでシンボリックリンクを作成できます。デフォルトでは有効になっていないため、gitを再インストールして、symlinkサポートが有効になっていることを確認する必要がある場合があります。

シンボリックリンクはデフォルトでは有効になっていません


1
gpedit.msc-> Local Computer Policy-> Computer Configuration-> Windows Settings-> Security Settings-> Local Policies-> User Rights AssignmentSeCreateSymbolicLink、年齢に応じてユーザーの権利や友達を割り当てるための標準的な方法です。以外にntrights.exe...リソースキットまたはPowerShellのから
0xC0000022L

11

2020回答

  1. Windows 10で「開発者モード」を有効にします- mklinkアクセス許可を与えます
  2. gitでシンボリックリンクが有効になっていることを確認してください
    • git config --global core.symlinks true
    • または msysgitのインストール時にチェックボックスをオンにします

ブランチを切り替えると、見つからないシンボリックリンクが強制的に再作成されます。

注意してください。他のGitクライアントを使用したWindowsでのSymlinkのサポートは完全ではありません。特にGitKraken。


私のすべてのローカルリポジトリには、ソリューションを上書きするcore.symlinks = falseがあります。このローカル構成を自動的に生成しているものは何ですか?チェックボックスをチェックせずにGit for Windowsをインストールする可能性はありますか?
gravidThoughts

@gravidThoughtsどのgitクライアントをインストールしましたか?多分いくつかのツールがこれをやっていますか?これは新しいクローンに当てはまりますか?
Cameron Tacklind

10

リポジトリ内でシンボリックリンクを使用しないことをお勧めします。実際のコンテンツをリポジトリ内に保存し、コンテンツをポイントするシンボリックリンクをリポジトリ外に配置します。

それでは、リポジトリを使用して* nixでのサイトのホスティングとwinでのホスティングを比較するとします。コンテンツをリポジトリに保存します」/httpRepoContentと言いましょう。c:\httpRepoContentこれは、GIT、SVNなどを介して同期されるフォルダーです。

次に、Webサーバーのコンテンツフォルダーを置き換えます(/var/wwwそして、c:\program files\web server\www{名前は実際には重要ではなく、必要に応じて編集します})、リポジトリ内のコンテンツへのシンボリックリンクに置き換えます。Webサーバーはコンテンツを実際には「正しい」場所にあるように見えますが、ソース管理を使用することができます。

ただし、リポジトリでシンボリックリンクを使用する必要がある場合は、なんらかの事前/事後コミットスクリプトのようなものを調べる必要があります。たとえば、フォーマッタを介してコードファイルを解析するなどの目的でそれらを使用できるため、プラットフォーム間でシンボリックリンクを変換できるはずです。

一般的なソース管理、SVN GIT MGのこれらのスクリプトを実行する方法を学ぶのに適した場所を誰かが知っている場合は、コメントを追加してください。


最後に、symlink-outフォルダーを作成し、元のファイルがあった場所へのシンボリックリンクを作成するために、このアプローチを選択しました。.git / config設定のcore.symlinks = trueを変更した後でも、他のアプローチは機能しませんでした。シンボリックリンクファイルのみがリポジトリに保存され、データは保存されませんでした。また、シンボリックリンクのフォルダータイムスタンプに問題があったため、フォルダー内でファイルが変更されたときにgit bashがそれを見ることはありませんでした。

@Eggsは、おそらくリンクがリポジトリ内にあったため、gitがリンクを保存したと思います。ただし、問題はターゲットがリポジトリの外にあり、gitがターゲットデータへのリンクをたどらないことです。Linuxでは、このために機能するリンクのタイプがあります。基本的には、ディスクに保存されている同じデータへの2つのパスがあるとします。新しいウィンドウでこれができるようになったような気がします。いずれにせよ、私はまだそれが人々の望むことをするつもりはないと思います。
thecoshman

@thecoshmanこれは解決策ではありませんが、回避策です。ただし、これがオプションにならない場合もあります。私はgit-annexのリポジトリを持っていますが、そのすべてのアーキテクチャはシンボリックリンクのために機能します。
marcelo.guedes 2018

8

Vista、Win7、またはそれ以上でCygWinを使用している場合、ネイティブgitコマンドは、Android StudioなどのWindowsアプリで認識される「適切な」シンボリックリンクを作成できます。CYGWIN含めるwinsymlinks:nativeか、またはwinsymlinks:nativestrictそのように環境変数を設定するだけです:

export CYGWIN="$CYGWIN winsymlinks:native"

これの欠点(およびその重要な点)は、CygWinシェルがこれらの種類のシンボリックリンクを作成するために必要なOS権限を持つために、「管理者として実行」である必要があることです。ただし、いったん作成されるとそれらを使用するために特別な権限は必要ありません。それらが別の開発者によってリポジトリで変更されない限り、gitその後は通常のユーザー権限で正常に実行されます。

個人的には、この追加の難しさのために、Windowsアプリ(つまり、CygWin以外)によってナビゲートされるシンボリックリンクにのみ使用します。

このオプションの詳細については、このSOの質問を参照してください:Windows 7でcygwinを使用してシンボリックリンクを作成する方法


6

Josh Leeの回答に基づいて、ファイルのみのリポジトリでシンボリックリンクを変換するためのバッチスクリプトを次に示します。管理者権限の追加のチェックがあるスクリプトは、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

文書化されていない回答は、そのような長く冗長な回答がすでに存在する場合、実際にはあまり役に立ちません。
Xennex81

4

私はドキュメントルートとgit repoディレクトリの間で常にsymリンクを使用しています。それらを分離しておくのが好きです。Windowsではmklink / jオプションを使用します。ジャンクションはgitを正常に動作させるようです:

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

例えば:

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


2
Windowsエクスプローラーとジャンクションには十分注意してください。ジャンクションとベースの場所を区別せず、削除はターゲットに再帰してそのコンテンツを削除しますが、シンボリックリンクを削除するとシンボリックリンクが削除されるだけです。不注意のためのただのわな。
Lawrence Dol 2015

5
実際、これを最新のWindows7でテストしただけで、テストは行われなくなったため、ジャンクションの処理は過去数年の間に改善されました。
Lawrence Dol 2015

3

WindowsのUNIXシンボリックリンクを処理する簡単なソリューションを探していました。上記のGitエイリアスをありがとうございました。rm-symlinksに実行できる1つの小さな最適化があり、エイリアスが誤って2回実行された場合に宛先フォルダー内のファイルを削除しません。ループの新しい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 

2

単純なトリックの1つは、git add --all2回続けて呼び出すことです。

たとえば、Windows 7のコミットスクリプトは次のように呼び出します。

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

最初の追加はリンクをテキストとして扱い、削除するフォルダを追加します。

2番目の追加はリンクを正しくトラバースし、ファイルを復元して削除を取り消します。

他のいくつかの提案されたソリューションよりもエレガントではありませんが、シンボリックリンクが追加されたレガシー環境の一部に対する単純な修正です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.