학습 자료

실무에서 꼭 만나는 상황 네 가지 — 구급상자


Article

집에 구급상자가 하나씩 있습니다. 열어보면 다 들어 있는 것도 아니고, 딱 자주 나는 상처에 맞는 것들만 있습니다. 반창고, 소독약, 체온계. 평소에는 쓸 일이 없다가 필요할 때 없으면 곤란한 물건들입니다.

오늘이 그 상자를 채우는 강입니다. 깃을 쓰다 보면 반드시 만나는 상황 네 가지를 미리 한 번씩 겪어둡니다. 그때 가서 검색하면 답이 너무 많이 나와 오히려 헤맵니다. 지금 해두면 "아 그거" 하고 꺼내 쓰게 됩니다.

오늘 채울 네 칸
  1. 하던 작업을 급히 치워야 할 때커밋하긴 애매하고 버릴 수도 없다
  2. 올리면 안 될 파일을 올렸을 때9강에서 감췄던 그 파일이다
  3. 커밋을 잘못했다는 걸 뒤늦게 알았을 때이미 올려버린 뒤다
  4. 권한이 없는 남의 프로젝트에 기여할 때25강 끝에서 미뤄둔 것
네 개가 서로 이어지지 않는다. 상자에 칸이 넷 있다고 보면 된다

① 하던 작업을 잠깐 치워둡니다

밥상을 차리는 중인데 손님이 옵니다. 반쯤 차린 상을 치우자니 아깝고, 그대로 두자니 자리가 없습니다. 이럴 때 하는 게 상을 통째로 들어서 방에 잠깐 밀어넣는 것입니다. 손님 보내고 다시 꺼내면 됩니다.

새 기능을 반쯤 만들었는데 급한 게 들어올 때가 딱 이렇습니다. 커밋하기엔 어정쩡하고 버릴 수도 없습니다. 이때 쓰는 게 git stash 입니다.

터미널
  • $ git status --short
  • M README.md
  • $ git stash
  • Saved working directory and index state WIP on master: 5f2c1a9 소개 문단 추가
  • $ git status
  • nothing to commit, working tree clean
  • # 방금 고친 게 통째로 사라졌다. 없어진 게 아니라 치워둔 것이다
  • $ git stash pop
  • M README.md
  • Dropped refs/stash@{0}
  • # 급한 일을 끝내고 도로 꺼냈다

nothing to commit — 6강부터 계속 보던 그 문장입니다. 고치기 전 상태로 돌아갔습니다. 치워둔 사이에는 가지를 옮겨도 되고 pull 을 받아도 됩니다. 급한 일이 끝나면 git stash pop 으로 도로 꺼냅니다. pop꺼내면서 서랍을 비운다는 뜻입니다. 뭘 치워뒀는지 궁금하면 git stash list 를 칩니다.

② 올리면 안 될 파일을 올렸습니다

9강에서 secret.txt 를 만들고 .gitignore 로 제외했습니다. 그때 "파일을 만들자마자 적습니다. 커밋한 뒤에 적으면 늦습니다" 라고 했고, 늦었을 때는 26강에서 다룬다고 미뤄뒀습니다.

늦었을 때가 이렇습니다. .gitignore 에 이름을 적었는데도 그 파일이 계속 따라다닙니다. .gitignore 는 아직 안 담긴 파일에만 듣기 때문입니다. 한 번 커밋된 파일은 깃이 이미 "내가 보는 파일" 로 등록해뒀습니다. 못 본 척하라는 규칙이지, 봤던 걸 잊으라는 규칙이 아닙니다.

그래서 먼저 등록을 취소하고, 그다음에 .gitignore 가 일하게 합니다.

터미널
  • $ git rm --cached secret.txt
  • rm 'secret.txt'
  • $ git status --short
  • D secret.txt
  • $ ls
  • README.md secret.txt
  • # 깃 목록에서는 빠졌는데 파일은 폴더에 그대로 있다. 이게 --cached 의 뜻이다

--cached 가 핵심입니다. 이걸 빼고 git rm secret.txt 를 치면 파일이 진짜 지워집니다. 우리가 하려는 건 "깃에서만 빼기" 지 "파일 삭제" 가 아닙니다. 한 글자 차이입니다.

다음은 .gitignoresecret.txt 가 적혀 있는지 확인하는 것입니다. 이게 있어야 다음 git add . 때 또 안 담깁니다. 확인했으면 git add .git commitgit push 로 마무리합니다. 깃허브 화면에서 파일이 사라집니다. 그런데 여기서 끝이 아닙니다.

③ 커밋을 잘못했습니다

8강에서 배운 restore커밋 전에 쓰는 것이었습니다. 이미 커밋해서 올렸으면 다른 걸 씁니다. 여기서 갈림길이 하나 있습니다.

없던 일로 만들기 vs 되돌리는 걸 기록하기

기록을 지운다

이미 올린 뒤라면 하지 않습니다

  • 잘못한 커밋 자체를 없앱니다
  • 같이 쓰는 사람의 기록과 어긋납니다
  • "어제 있던 커밋이 없어졌다" 는 소동이 납니다
  • 혼자 쓰는 저장소가 아니면 사고입니다

git revert

되돌린다는 사실을 기록으로 남깁니다

  • 되돌리는 커밋을 새로 하나 쌓습니다
  • 옛 커밋은 그대로 남습니다
  • 남의 기록과 어긋나지 않습니다
  • 올린 뒤라면 이쪽이 정답입니다
회계 장부를 떠올리면 쉽다. 틀린 줄을 지우개로 지우지 않고, 취소한다는 줄을 아래에 새로 적는다

revert 를 쓰려면 되돌릴 커밋을 알려줘야 합니다. 7강의 git log --oneline 으로 앞의 짧은 글자를 봅니다.

터미널
  • $ git log --oneline
  • 9c31f04 실수로 지운 문단
  • 5f2c1a9 소개 문단 추가
  • $ git revert --no-edit 9c31f04
  • [master 2a70b18] Revert "실수로 지운 문단"
  • 1 file changed, 3 insertions(+)
  • $ git log --oneline
  • 2a70b18 Revert "실수로 지운 문단"
  • 9c31f04 실수로 지운 문단
  • 5f2c1a9 소개 문단 추가

두 가지를 봅니다. 잘못한 커밋 9c31f04 가 그대로 있고, 그 위에 Revert 커밋이 하나 새로 생겼습니다. 파일 내용은 잘못하기 전으로 돌아왔고, 그렇게 되돌렸다는 사실까지 기록에 남았습니다.

--no-edit 는 붙이는 게 편합니다. 안 붙이면 메시지를 적으라고 편집기가 열리는데, 처음 보면 나가는 법을 몰라 당황합니다. 되돌린 것도 커밋이니 git push 로 올려야 반영됩니다.

④ 권한이 없는 남의 프로젝트에 기여합니다

마지막 칸입니다. 25강에서는 짝이 나를 협업자로 불러줬습니다. 그런데 인터넷에 공개된 프로젝트를 고치고 싶을 때는 그럴 수가 없습니다. 주인을 알지도 못하는데 열쇠를 달라고 할 수는 없고, 오타 하나 고치겠다는 사람에게 주인이 창고 열쇠를 내주지도 않습니다.

그래서 깃허브가 다른 길을 냈습니다. fork 입니다. 남의 저장소를 통째로 복사해 내 계정에 하나 만드는 겁니다. 복사본의 주인은 나니까 마음대로 push 할 수 있고, 다 고친 뒤 원본 주인에게 "이거 어떠냐" 고 PR 을 보냅니다.

fork 로 기여하는 길
  1. 원본 저장소에서 Fork 를 누른다내 계정에 똑같은 저장소가 하나 생긴다
  2. 내 것이 된 복사본clone 한다주소가 내 계정으로 시작하는지 확인한다
  3. 가지를 만들어 고치고 커밋한다21강 그대로다
  4. 내 복사본으로 push 한다내 저장소니까 403 이 안 난다
  5. 원본으로 PR 을 연다깃허브가 방향을 알아서 잡아준다
  6. 원본 주인이 보고 결정한다합칠 수도, 안 합칠 수도 있다
명령은 25강과 똑같다. 다른 건 push 하는 곳이 내 복사본이라는 것 하나뿐이다
협업자 초대 vs fork

협업자 초대 (25강)

아는 사이, 같은 팀

  • 주인이 나를 등록해줘야 합니다
  • 저장소가 하나입니다
  • 원본에 바로 push 할 수 있습니다
  • 회사 팀 저장소가 보통 이 방식입니다

fork

모르는 사이, 공개 프로젝트

  • 허락을 안 받아도 됩니다
  • 저장소가 입니다 — 원본과 내 복사본
  • 원본에는 PR 로만 말을 겁니다
  • 오픈소스가 전부 이 방식입니다
둘 다 마지막은 PR 이다. 24강에서 배운 게 어느 쪽으로 가든 같은 문이었다

clone 할 때 주소를 잘 봅니다. 원본 주소를 받아오면 아무 소용이 없습니다. 고쳐서 push 하는 순간 16강의 403 을 또 만납니다. github.com/ 뒤가 내 계정인지 확인하고 받아옵니다. 헷갈리면 25강에서 쓴 git remote -v 를 칩니다.

여기까지가 상한선입니다

깃에는 명령이 훨씬 많습니다. 검색하면 rebase, reset --hard, cherry-pick 같은 게 계속 나옵니다.

오늘 채운 구급상자
상황꺼낼 것
하던 걸 잠깐 치워야 한다git stashgit stash pop
올리면 안 될 파일을 올렸다git rm --cached 파일 + .gitignore
올라간 비밀번호·토큰이 걱정된다지우지 말고 새로 발급받는다
커밋을 잘못했는데 이미 올렸다git revert --no-edit 해시
권한 없는 프로젝트에 기여한다Forkclone → PR
외울 필요는 없다. 그런 게 있었다는 것만 기억하면 그때 찾아 쓸 수 있다

정리하면

  • git stash 는 커밋하기 애매한 작업을 잠깐 치워두는 서랍입니다. git stash pop 으로 꺼냅니다
  • 치운 건 내 컴퓨터에만 있습니다. 컴퓨터를 옮길 때 쓰면 안 되고, 오늘 치운 건 오늘 꺼냅니다
  • .gitignore아직 안 담긴 파일에만 듣습니다. 이미 커밋된 파일은 git rm --cached 로 먼저 뺍니다
  • --cached 를 빼면 파일이 진짜 지워집니다. 한 글자 차이입니다
  • 빼내도 옛 기록에는 남습니다. 비밀번호나 토큰이 올라갔으면 지우려 하지 말고 새로 발급받습니다
  • 이미 올린 커밋은 지우지 않고 git revert되돌리는 커밋을 새로 쌓습니다. 장부에 취소 줄을 적는 것과 같습니다
  • --no-edit 를 붙이면 편집기가 안 열리고, 되돌린 것도 커밋이라 push 해야 반영됩니다
  • 권한 없는 남의 프로젝트에는 fork 로 기여합니다. 복사본은 내 것이라 push 가 됩니다
  • fork 는 저장소가 입니다. clone 할 때 주소가 내 계정인지 반드시 확인합니다
  • --force--hard 가 붙은 명령은 뜻을 알기 전에 치지 않습니다

Part 5 가 끝났습니다. 21강에서 가지를 처음 쳐보고, 합치고, 충돌을 풀고, PR 을 올리고, 남과 주고받고, 오늘 구급상자까지 채웠습니다.

스물여섯 강을 마칩니다

1강을 보고서_최종_최종2_진짜최종 이야기로 열었습니다. 그때는 터미널 창을 여는 것부터 낯설었을 겁니다. 지금은 20강에서 만든 URL 로 열리는 내 페이지, 19강에서 꾸민 프로필, 25강에서 남과 주고받은 PR 이력이 남아 있습니다. 이력서에 붙일 링크가 생긴 겁니다.

더 중요한 게 따로 있습니다. 에러를 만났을 때 겁먹지 않는 것입니다. 6강에서 add 없이 commit 해보고, 15·16강에서 인증이 거부당하고, 23강에서 충돌을 일부러 냈습니다. 그때마다 영어 몇 줄이 떴고, remote:error: 로 시작하는 줄만 보면 된다는 걸 배웠습니다. 앞으로 만날 에러도 대부분 같은 모양입니다.

이 편에서는 코드를 한 줄도 안 썼습니다. memo.txtmemo.mdREADME.md, 파일 하나를 끝까지 키운 게 전부입니다. 일부러 그랬습니다. 깃을 배우는 데 코드는 오히려 방해가 되기 때문입니다. 이제 여기에 무엇을 올리든 방식은 똑같습니다.

마지막으로 하나만 부탁합니다. 오늘부터 만드는 건 뭐가 됐든 git init 부터 하고 시작합니다. 연습 파일이어도 그렇게 합니다. 명령이 손에 붙는 건 강의를 다시 보는 걸로는 안 됩니다. 쓰면서 붙습니다.

고생했습니다.