전체 글 31

[Git] stash pop 하다 충돌나면 stash는 어디 있나

git stash pop 이 충돌로 멈췄다. 순간 치워 뒀던 작업이 날아간 줄 알았다. 안 날아간다. pop 이 실패하면 stash 는 스택에 그대로 남는다. 대신 성공했을 때와 달리 자동으로 안 지워지므로, 충돌을 푼 뒤 직접 지워야 한다.현상Auto-merging f.txtCONFLICT (content): Merge conflict in f.txtOn branch mainUnmerged paths: (use "git restore --staged ..." to unstage) (use "git add ..." to mark resolution) both modified: f.txtno changes added to commit (use "git add" and/or "git commit -..

Git 2026.09.18

[React] key를 바꾸면 state가 초기화되는 이유

탭을 바꿨더니 입력하던 값이 사라졌다. 컴포넌트는 같은 컴포넌트였고, 조건부 렌더 한 줄만 바꿨을 뿐이다. 값이 남을 때와 사라질 때를 가르는 게 컴포넌트가 아니라면 대체 무엇인지 알아야 했다.배경1편에서 훅이 호출 순서로 슬롯을 찾는다는 데까지 갔다. useState 를 조건문 안에 넣으면 안 되는 이유가 거기 있었다. 그런데 그 글은 한 컴포넌트 안쪽 이야기였다. 그 슬롯 덩어리 자체가 어디에 매달려 있는지는 안 다뤘다.이번에 만난 문제가 그 바깥이었다. 같은 를 렌더하는데 어떤 때는 값이 남고 어떤 때는 0으로 돌아갔다. 조건부 렌더의 두 갈래에 같은 컴포넌트를 뒀는데도 그랬다.질문: React 는 어떤 컴포넌트의 state 를 어디에 붙여 두고, 언제 버리는가?개념 — state는 컴포넌트에 붙..

React 2026.09.17

[Git] 브랜치 전략은 팀 크기가 정하지 않는다

혼자 만드는 앱 프로젝트에 브랜치 전략을 얹은 적이 있다. 기능 묶음마다 브랜치를 따고, 끝나면 main 에 합치는 식이었다. 마일스톤 세 개를 그렇게 진행했다.중간에 Git Flow 를 제대로 도입할까 고민했다. develop, feature/*, release/*, hotfix/* 를 다 갖추는 구성이다. 검색하면 가장 많이 나오는 그림이고, 제대로 된 팀은 다 이렇게 한다는 인상을 받았다.그런데 혼자인 프로젝트에 release 브랜치를 만들어 두면 무슨 일이 벌어지는지 생각해 봤다. 릴리스를 준비하는 동안 다른 사람이 develop 에 계속 커밋하는 상황을 막으려고 만든 게 release 브랜치다. 그 다른 사람이 없다. 나 혼자 두 브랜치를 오가며 머지 커밋을 만들 뿐이었다.그래서 안 했다. 대신..

Git 2026.09.15

[Git] cherry-pick 이 중복 커밋을 만드는 이유

운영에서 급한 버그가 나서 develop 에 고친 커밋을 release 브랜치로 cherry-pick 했다. 배포는 잘 됐다. 문제는 그다음이었다. 릴리스가 끝나고 develop 을 release 에 정식으로 합쳤더니, 같은 수정이 커밋 목록에 두 번 나왔다.파일 내용은 멀쩡했다. 충돌도 안 났다. 그런데 히스토리에는 같은 제목의 커밋이 두 개 남았다. 나중에 "이 수정이 언제 들어갔지" 를 찾을 때 어느 쪽을 봐야 하는지 알 수 없었다.같은 변경을 cherry-pick 했을 뿐인데 왜 커밋이 두 개가 되는가?환경항목버전Git2.50.1 (Apple Git-155)확인한 문서git-scm.com git-cherry-pick, git-merge (2026-08-10 기준)cherry-pick 은 커밋을 옮..

Git 2026.09.14

[Git] detached HEAD 가 뭐고 왜 생기나

배포된 버전에서 버그를 재현하려고 태그를 체크아웃했다. 그때 이런 경고가 나왔다.You are in 'detached HEAD' state. You can look around, make experimentalchanges and commit them, and you can discard any commits you make in thisstate without impacting any branches by switching back to a branch."둘러보고, 실험적인 변경을 하고, 커밋할 수 있다" 까지 읽고 넘겼다. 그래서 거기서 수정하고 커밋했다. 그리고 브랜치로 돌아왔더니 그 커밋이 어디에도 없었다.경고문 뒷부분에 답이 있었다. 브랜치로 돌아가면 그 상태에서 만든 커밋을 "버릴 수 있다" ..

Git 2026.09.12

[Git] force push 로 남의 커밋을 날렸다

git push --force 는 원격 브랜치를 내 히스토리로 통째로 덮는다. 그 사이 남이 올린 커밋이 있었다면 아무도 가리키지 않는 상태가 되어 사라진다. 공식 문서도 이걸 경고 문장으로 적어 뒀다.되살리는 건 대개 가능하다. 다만 원격이 아니라 커밋을 만든 사람의 로컬에서 꺼내야 한다. 그리고 애초에 --force 대신 --force-with-lease 를 쓰면 이 상황 자체가 막힌다.현상브랜치를 정리하려고 rebase 한 뒤 밀어 넣었다. 잠시 뒤 동료가 자기 커밋이 없어졌다고 했다.$ git push --force origin feature/checkout + a1b2c3d...9f8e7d6 feature/checkout -> feature/checkout (forced update)+ 기호와 ..

Git 2026.09.11

[Git] 충돌은 왜 나고, 나는 뭘 고르는 건가

충돌이 나면 파일에 로 시작하는 덩어리가 생긴다. 위쪽이 내 것, 아래쪽이 상대 것이라는 건 알고 있었다. 그런데 정작 고를 때마다 막혔다. 둘 다 말이 되는 코드였고, 어느 쪽이 "맞는" 건지 판단할 근거가 화면에 없었다.한동안은 감으로 골랐다. 내가 방금 쓴 쪽을 남기거나, 최신 커밋 쪽을 남기거나. 그러다 남의 수정을 통째로 덮어 버린 걸 나중에 발견한 적이 있다. 그때부터 이 화면이 정확히 뭘 보여주는 건지 알아야겠다고 생각했다. 와 >>>>>>> 사이에 놓인 것은 정확히 무엇이고, 나는 무엇을 고르고 있는 건가?환경항목버전Git2.50.1 (Apple Git-155)확인한 문서git-scm.com git-merge (2026-08-10 기준)충돌은 두 쪽을 비교해서 나는 게 아니다merge 는..

Git 2026.09.10

[Git] 커밋을 날렸을 때 reflog 로 되살리기

git reset --hard 로 커밋을 날렸다면, 그 커밋은 아직 지워지지 않았다. 브랜치가 가리키던 손가락만 옮겨졌을 뿐 커밋 객체는 그대로 남아 있다. git reflog 로 옛 위치를 찾아 되돌리면 된다.git reflog # 옛 해시를 찾고git reset --hard # 거기로 되돌린다현상브랜치를 정리하다가 되돌릴 지점을 잘못 세었다.$ git reset --hard HEAD~3HEAD is now at 8f2a1c9 로그인 폼 마크업$ git log --oneline -38f2a1c9 로그인 폼 마크업1d40b77 프로젝트 초기 설정세 시간짜리 작업 세 개가 목록에서 사라졌다. git log 어디를 봐도 없다.환경항목버전Git2.50.1 (Apple Git-155)확인한 문서git-scm...

Git 2026.09.09

[Git] .gitignore 에 넣었는데 계속 올라가는 이유

.gitignore 에 분명히 적었는데 git status 에 계속 뜬다면, 규칙이 틀린 게 아니다. 그 파일이 이미 Git 의 추적 대상이기 때문이다. .gitignore 는 아직 추적하지 않는 파일에만 적용된다. 이미 인덱스에 들어간 파일은 규칙을 무시하고 계속 따라온다.해결은 인덱스에서 빼는 것이다. git rm --cached .현상.env 를 커밋에서 빼려고 .gitignore 에 추가했다. 그런데 상태를 보면 여전히 잡힌다.$ cat .gitignore.env$ git statusOn branch mainChanges not staged for commit: (use "git add ..." to update what will be committed) (use "git restore .....

Git 2026.09.08

[AI 도구] claude -p 로 PR 리뷰 자동화하기

배경대화형으로 쓰다 보면 "이 검사는 왜 매번 내가 시작해야 하나" 싶은 지점이 온다.내 블로그 파이프라인에도 발행 전 검증 단계가 있다. 사실 확인, 문체 점검, SEO 체크. 절차는 이미 스킬로 정리돼 있는데 시작 버튼은 늘 내가 누른다. 커밋할 때마다 알아서 돌면 좋겠다고 생각했다.-p 를 붙이면 비대화형으로 돌아간다는 건 알고 있었다. 그래서 그대로 스크립트에 넣어봤다. 내 기계에서는 잘 됐다. 그런데 이건 내 기계에서만 잘 되는 명령이었다.터미널 밖에서 Claude Code 를 돌릴 때 무엇이 달라지나?개념 — -p 는 대화형의 축소판이 아니다claude -p "..." 는 비대화형 실행이다. 프롬프트를 주고 결과를 받는다. 모든 CLI 옵션이 그대로 동작한다.문제는 기본 상태의 -p 가 대화형..