Git for Windowsでシンボリックリンクを扱えるようにする


## 概要

[Git for Windows](https://git-for-windows.github.io/)はデフォルトでシンボリックリンクが扱えないようになっています。しかしそれではUnix系OSとリポジトリを共有して開発する場合などで不便なため、Unix系OSと同等にシンボリックリンクを扱えるように設定します。
内容としては、↓の元ネタを整理・補足するようなものとなります。

* 元ネタ：[Symbolic Links · git-for-windows/git Wiki](https://github.com/git-for-windows/git/wiki/Symbolic-Links)
* 元ネタ2：[Git for Windowsでのシンボリックリンク  | OPC Diary](https://opcdiary.net/?p=31100) ↑のページの日本語による解説

## 確認した環境

* Windows 10: build 14986.1001
* Git for Windows: 2.11.1.20170208
* Polsedit: 1.0.0.5

## 事前準備：一般ユーザにシンボリックリンクを作る権限を与える

Windowsでシンボリックリンクを作成するには管理者権限が必要なのですが、`git clone`や`ln -s`を実行するためにわざわざ管理者権限を付与したくないですよね。
元ネタにあるように、グループポリシーエディタがあれば、`SeCreateSymbolicLinkPrivilege `権限を一般ユーザに与えることによって、管理者権限不要でシンボリックリンクを作成することができるようになります。
しかし、グループポリシーエディタは、WindowsのProエディション以上にしか付属しておらず、おそらくほとんどの方が利用されているであろうHomeエディション以下には付属していないのです。
そこで、元ネタには[Polsedit](http://www.southsoftware.com/)というフリーのローカルポリシーエディタのクローンが紹介されています。
これを使うことで上記の権限設定を行うことができます。

追記1:
[@ubnt_intrepidさんのコメント](#comment-250af72ab706bd611549)にあるように、`editrights`コマンドを用いても`SeCreateSymbolicLinkPrivilege `権限を一般ユーザに付与することができるようです。

追記2:
同[@ubnt_intrepidさんのコメント](#comment-250af72ab706bd611549)にあるように、2017年3月に公開されると言われているWindows 10 Creators Updateでは、~~デフォルトの状態でも~~開発者モードにすることで管理者権限なしでシンボリックリンクが作成できるようになるようです。~~よって、Creators Update以降は、この節の作業は不要になりますね。~~ ただし、コメントにあるWindowsブログの記事によると、この変更自体はbuild 14972から提供されているのですが、管理者権限が不要になるのは、mklinkコマンドを使った場合と、CreateSymbolicLink APIを特別なフラグを付けて呼んだ場合だけのようです。git bashのlnコマンドはまだフラグに対応していないのか、この記事の作成時点で私が試した限りでは、管理者権限がなければシンボリックリンクが作成できませんでした。
（↑2017/03/05 22:59 開発者モードへの変更が必要なこと、lnコマンドにはまだ管理者権限が必要だったことを追記）

### Polseditで一般ユーザにシンボリックリンク作成権限を付与する

Polseditのzipを展開し、polsedit.exeを実行してください。
実行には管理者権限が必要です。

#### 1. Policy一覧から`Create symbolic links`を開く

画面の右ペインに編集可能なポリシーの一覧が表示されるので、その中から`Create symbolic links`ポリシーをダブルクリック等で開きます。

![Polsedit_policies_list.png](https://qiita-image-store.s3.amazonaws.com/0/5971/9aac66e1-323d-71e2-2bb6-13acd1befdab.png)

以下のようなダイアログが表示されます。
デフォルト状態では、Administratorsグループだけに権限が付与されています。

![Polsedit_Create_symbolic_links_Properties_before.png](https://qiita-image-store.s3.amazonaws.com/0/5971/128298a3-74fd-7353-ef7f-a5dc307edf09.png)

ここに、一般ユーザを表すUsersグループを追加することによって、一般ユーザでもシンボリックリンクを作成できるようにします。

#### 2. Usersグループに権限を与える

`Add User or Group...`ボタンをクリックすると、権限を与えるユーザとグループを選択するダイアログが表示されます。

![Polsedit_Select_Users_or_Groups.png](https://qiita-image-store.s3.amazonaws.com/0/5971/e5f0357b-9db9-1ac2-89b9-b6bc5c3120c0.png)

私が試したところでは、初期状態ではこの一覧にはグループが表示されておらず、`Object Types...`ボタンを押して表示されるダイアログで`Groups`にもチェックを入れる必要がありました。

![Polsedit_Object_Types.png](https://qiita-image-store.s3.amazonaws.com/0/5971/372970b8-efa9-2364-6a6f-e8a71176996f.png)

一覧から`Users`を選択し、`OK`ボタンを押します。
最初のダイアログが以下のような状態になっていれば成功です。

![Polsedit_Create_symbolic_links_Properties_after.png](https://qiita-image-store.s3.amazonaws.com/0/5971/00586b52-f1a1-87de-a79f-a5f0f62ef0be.png)

設定を反映するために一度サインオフすることが求められるので、サインオフして再度サインインしましょう。


## `git clone`でリポジトリに含まれるシンボリックリンクを正しく再現できるようにする

Git for Windowsで`git clone`を行うと、デフォルトではリポジトリに含まれるシンボリックリンクが、リンク先を示す文字列が書かれたただのテキストファイルになってしまいます。
gitconfigの`core.symlinks`を`true`に設定することで、リポジトリに含まれるシンボリックリンクがきちんとシンボリックリンクとして扱われるようになります。
元ネタでは、`git clone`時にオプションを渡す方法を解説していますが、gitconfigを設定してしまったほうが便利だと思います。

```shell-session
$ git config --global core.symlinks true
```

## git bashの`ln -s`コマンドでシンボリックリンクを作れるようにする

元ネタでは「`ln -s`コマンドではファイルのコピーを作るようになっているので、`mklink`コマンドを使ってね」とありますが、以下の設定をすれば`ln -s`でもシンボリックリンクが作成できるようになります。

### 環境変数`MSYS`に`winsymlinks:nativestrict`を設定する

MSYSでは上記見出しにあるような設定をすることで、Windowsネイティブのシンボリックリンクが作成できるようになります。git bashはMSYS由来の環境なので、同様の設定が有効のようです。
私はWindowsのユーザ環境変数に設定しましたが、システム環境変数やgit bashの環境変数に設定してもうまくいくと思います（未確認）。
Windowsの環境変数を設定する場合、コントロールパネルから環境変数のメニューを辿ってもいいのですが、`setx`コマンドを使うと一発で環境変数をセットできるのでオススメです。
`setx`コマンドを使ってユーザ環境変数へ上記設定を行うには以下のようにします。

```
> setx MSYS winsymlinks:nativestrict
```

参考：

* https://github.com/git-for-windows/git/issues/171
* http://appsweets.net/blog/2013/11/18/creating-ntfs-native-symbolic-link-in-cygwin/

### シンボリックリンクをコミットしても大丈夫

前述の方法で作成したシンボリックリンクをリポジトリにコミットし、他のマシン（Windows, Linux）で`git clone`したところ、正しくシンボリックリンクとして取り出せることを確認しました。
これでWindowsでも安心してシンボリックリンクが使えますね。