Windows Git Bash 심볼릭 링크 설정하기

요약. Git Bash 에서 ln -s 를 실행했는데 링크가 아니라 파일 복사본이 생긴 적이 있으실 겁니다. 리눅스에서 잘 쓰던 dotfiles 를 Windows 로 가져왔더니 링크가 전부 텍스트 파일로 바뀌어 있는 경우도 같은 원인입니다. 설정 네 곳을 맞추면 해결됩니다. 이 글은 그 네 단계와, 설정을 빠뜨렸을 때 나타나는 증상을 다룹니다.

도토리 블루투스 넘패드 - 폰을 PC 의 17키 숫자패드로

제가 만든 무료 앱입니다. 많이 써 주세요.

심볼릭 링크는 대상 경로를 적어 둔 이정표입니다

심볼릭 링크는 파일의 사본이 아니라 "실제 파일은 저기에 있다" 는 경로 문자열을 담은 특수 파일입니다. 원본을 한 곳에만 두고 여러 위치에서 같은 파일처럼 참조할 때 씁니다. 원본을 고치면 링크로 접근한 쪽에도 즉시 반영됩니다.

Git 도 심볼릭 링크를 그대로 저장합니다. 일반 파일이 100644 모드로 기록되는 것과 달리 링크는 120000 모드로 들어가고, 내용은 대상 경로 문자열 하나입니다.

$ git ls-files -s
120000 c9c61fe1fb4b3b... 0	alias.txt
100644 10622902e19e73... 0	real.txt

문제는 Windows 쪽입니다. Windows 에도 심볼릭 링크가 있지만 생성하려면 SeCreateSymbolicLinkPrivilege 권한이 필요하고, 이 권한은 기본적으로 관리자에게만 부여됩니다. 아래 설정들은 전부 이 제약을 우회하기 위한 것입니다.

네 단계를 모두 맞춰야 링크가 만들어집니다

  1. Git 설치 시, 맨 마지막 화면에서 Enable symbolic links 를 체크합니다.
  2. Git Bash 를 관리자 권한으로 실행합니다.
  3. export MSYS=winsymlinks:nativestrict 를 셸 환경에 넣습니다.
  4. ~/.gitconfig 의 [core] 에 symlinks = true 를 추가합니다.

3번과 4번은 명령 두 줄로 끝납니다.

echo 'export MSYS=winsymlinks:nativestrict' >> ~/.bashrc
git config --global core.symlinks true

MSYS 변수가 핵심입니다. 기본값은 deepcopy 라서 링크를 만들지 못하면 조용히 파일을 복사합니다. nativestrict 는 네이티브 링크만 만들고, 권한이 없으면 오류를 냅니다. 실패를 감추지 않기 때문에 원인을 바로 알 수 있습니다. 새 터미널을 연 뒤 아래처럼 확인합니다.

$ ln -s real.txt alias.txt
$ ls -l alias.txt
lrwxrwxrwx 1 dualk 197609 8  8월 27 16:59 alias.txt -> real.txt

맨 앞 글자가 l 이고 화살표가 보이면 성공입니다. -rw-r--r-- 로 나오면 복사본입니다.

바로가기 대신 원본 exe 속성을 바꿉니다

매번 우클릭해서 관리자로 실행하는 것은 번거롭습니다. Git Bash 바로가기를 따라가 원래 실행 파일을 찾은 뒤, 그 파일에 상시 관리자 권한을 걸어 둡니다.

  1. Git Bash 바로가기에서 원본 .exe 를 추적한 뒤 우클릭하고 속성 을 선택합니다.
  2. 호환성 탭에서 관리자 권한으로 실행 을 체크합니다.

관리자 권한 셸을 상시 띄우는 것이 부담스럽다면 대안이 있습니다. Windows 10 Creators Update(1703) 부터는 개발자 모드를 켜면 일반 사용자 계정도 심볼릭 링크를 만들 수 있습니다. 설정 > 개인 정보 및 보안 > 개발자용 에서 켠 뒤 재부팅하면 3번 항목만으로 동작합니다.

설정이 빠지면 링크가 조용히 텍스트 파일이 됩니다

가장 곤란한 상황은 오류가 나지 않는 경우입니다. core.symlinks 가 꺼진 상태로 저장소를 클론하면, 링크 자리에 경로 문자열이 내용인 일반 파일이 놓입니다.

상태ls -l 앞부분cat alias.txt 결과
정상 링크lrwxrwxrwx ... -> real.txt원본 파일의 내용
깨진 링크-rw-r--r-- (8바이트)real.txt (경로 문자열)

더 나쁜 점은 git status 가 깨끗하게 나온다는 것입니다. Git 은 이것을 변경으로 보지 않기 때문에 그대로 커밋되어도 알아채기 어렵습니다. 그리고 클론 시점의 core.symlinks=false 값은 그 저장소의 .git/config 에 박제됩니다. 나중에 전역 설정을 켜도 로컬 설정이 우선하므로 그 저장소만 계속 깨진 상태로 남습니다.

git config --local --get core.symlinks    # false 가 나오면 이것이 원인입니다
git config --local --unset core.symlinks  # 로컬 설정을 지웁니다
git checkout -- .                          # 작업 트리를 다시 펼칩니다

정리

심볼릭 링크는 대상 경로를 담은 파일이고, Windows 에서는 생성에 별도 권한이 필요합니다. 설치 옵션, 관리자 권한, MSYS=winsymlinks:nativestrict, core.symlinks=true 네 가지가 모두 맞아야 합니다. 하나라도 빠지면 오류 대신 복사본이 생기고 git status 도 조용합니다.

지금 Git Bash 를 열어 echo $MSYS 와 git config --get core.symlinks 를 실행해 보시기 바랍니다. 두 값이 비어 있다면 위 두 줄부터 실행하면 됩니다.