한 줄로
skip-worktree 는 git status 에서만 로컬 변경을 가린다. merge 할 때는 git 이 그 변경을 그대로 보고 local changes would be overwritten 으로 거부한다. dotfiles 자동 동기화에 stash 가 계속 쌓이던 이유가 이것이었다. 근본 원인은 install.sh 가 실행될 때마다 공유 설정 파일을 고치던 것이었다.
skip-worktree 가 가리는 범위
skip-worktree 는 git 이 특정 파일의 로컬 변경을 못 본 척하게 만드는 플래그다.
핵심은 “못 본 척”이 어디까지냐다. 가려지는 곳은 git status 하나다. 원격에서 같은 파일이 바뀌어 merge 해야 하면 git 은 로컬 변경을 그대로 본다. 그리고 그 변경을 덮어쓰지 않으려고 merge 를 거부한다.
local changes would be overwritten
이 동작은 격리 레포를 따로 만들어 재현해 확인했다.
처음 세운 전제가 틀렸다
처음에는 “skip-worktree 를 걸었는데 왜 stash 가 생기나”를 물었다. skip-worktree 가 걸린 파일이면 로컬 변경이 동기화를 방해하지 않을 거라고 생각했기 때문이다.
실제로는 이렇게 흘러간다.
- 자동 동기화가 merge 를 시도한다.
- skip-worktree 가 걸린 파일에 로컬 변경이 있어서 merge 가
local changes would be overwritten으로 거부된다. - 무인 AI 해소가 지시받은 대로 로컬 변경을 stash 에 넣는다.
stash 가 생기는 것 자체는 설계대로 돌아간 결과다. 그러니 찾아야 할 것은 “왜 stash 가 생기나”가 아니었다. “누가 그 파일을 계속 바꾸나”였다.
진짜 원인: install.sh 가 공유본을 고치고 있었다
install.sh 에 claude plugins enable -s user 가 들어 있었다. 이 명령은 Claude Code 사용자 설정 파일인 settings.json 을 고친다. 그런데 이 파일은 dotfiles 레포의 공유본을 가리키는 심링크(원본을 가리키는 바로가기 파일)다. 그래서 install.sh 가 돌 때마다 공유본이 바뀌었다.
게다가 이 쓰기는 아무 효과도 없었다. company-mac 프로파일이 document-skills 를 false 로 덮어쓰고 있었기 때문이다. company-pro 에는 true 로 되어 있다. 이 플러그인을 도입한 커밋 9557c64 도 프로파일마다 켠다고 적어 두었다. 그러니 company-mac 의 false 는 잘못 적힌 값이다.
정리하면 이렇다. install.sh 는 효과도 없는 설정을 공유 파일에 매번 쓰고 있었다. 그 쓰기가 로컬 변경으로 남아 merge 를 막았다. merge 가 막히면 무인 AI 해소가 stash 를 하나 더 만들었다.
무인 동기화 기록에 남은 흔적
회사 머신에서 13:10 에 돈 무인 동기화 기록을 보면 이 흐름이 그대로 드러난다.
-
scripts/weekly-report*.sh의 미커밋 변경은 stash 했다가 다시 꺼내 되돌렸다. -
settings.json에 자동으로 들어간 값(herdr hook,model: "opus",document-skills)은stash@{0}에 넣어 두었다. - 그 상태에서
f9a969e까지 fast-forward 했다.
고친 것 (a4ede58)
-
company-mac/settings.local.json:false→true -
install.sh:plugins enable -s user를 지우고 설치 단계만 남겼다 -
CLAUDE.md: “skip-worktree 는 status 만 가린다, merge 는 거부한다”를 적어 두었다
검증은 install.sh 를 두 번 연달아 실행하는 방식으로 했다. 두 번 다 공유본이 바뀌지 않았다. 드리프트(공유본과 로컬 값이 어긋난 상태) 키는 2개에서 1개로 줄었다. 이 커밋은 push 했다.
남은 하나: herdr 가 넣는 절대경로 훅
남은 드리프트 키 하나는 herdr 가 넣는 절대경로 훅이다.
로컬 전용 값이니 settings.local.json 으로 옮기면 될 것처럼 보인다. 하지만 실제로 해 보니 훅만 settings.local.json 으로 옮기면 실행되지 않았다. advisorModel·theme 같은 값은 local 에 있어도 적용된다. 반면 훅 배열은 두 파일 사이에서 병합되지 않는다.
그래서 원격에서 settings.json 이 바뀌는 날에는 stash 가 다시 생길 수 있다. 그래도 pull 은 정상으로 끝나므로, 피해는 stash 가 쌓이는 것에 그친다.
선택지는 세 가지였다. 파일을 미추적으로 바꾸기, herdr 연동 끊기, 그대로 두기다. 결국 그대로 두기로 했고, 지금은 손댈 것이 없다.
정리
- skip-worktree 는
git status만 가린다. merge 는 로컬 변경을 보고 거부한다. - 자동 동기화가 stash 를 쌓는 것은 증상이다. 원인은 그 파일에 계속 쓰는 쪽에 있다. 이번에는 심링크를 거쳐 공유본을 고치던
install.sh였다. - 훅처럼 병합되지 않는 설정은
settings.local.json으로 옮겨도 동작하지 않는다. 그런 값은 공유본에 남아 드리프트가 된다.