DevOps · Git · Collaboration

오래 사는 브랜치 - 미룬 만큼 한꺼번에 온다

합치기를 미루면 비용은 미룬 시간에 비례해서 늘지 않는다. 충돌 면적·리뷰 크기·늦게 오는 답이 어떻게 함께 자라는지, 그리고 짧게 유지하는 값은 무엇인지 본다.

·갈래와 합류 4편
목차
  1. 이 주에 끝낼 일이 세 주가 됐다
  2. 미룬 값은 시간에 비례하지 않는다
  3. 충돌을 푸는 건 새 코드를 쓰는 일이다
  4. 리뷰가 커지면 리뷰가 아니게 된다
  5. 늦게 합칠수록 답을 늦게 안다
  6. 짧게 사는 지선도 공짜는 아니다
  7. 실무에서: 줄여야 할 건 브랜치가 아니라 일의 크기
  8. 브랜치를 아예 안 파는 경우 - 이 블로그
  9. 정리

지선은 왕복표다. 돌아오는 날이 밀릴수록 표값이 오른다.

이 주에 끝낼 일이 세 주가 됐다

사흘이면 끝날 줄 알았다. 지선을 하나 내고 일을 시작했다.

이틀째에 급한 게 하나 끼어들어 하루를 썼다. 다시 붙잡았더니 생각보다 손댈 데가 많았다. 다 만들어놓고 리뷰를 올렸는데 리뷰어가 바빠 이틀이 지났다. 고치라는 걸 고치고 다시 올렸다. 그렇게 세 주가 됐다.

이제 합치려고 보니 그동안 본선에는 다른 사람들 변경이 예순 개쯤 들어와 있다. 내가 고친 파일 중 여럿을 남도 고쳤다. 그리고 내가 사흘째에 세워둔 전제 하나가 지난주에 본선에서 바뀌어 있다.

이 상황의 원인은 세 주를 쓴 게 아니다. 세 주 동안 한 번도 안 합친 것이다.

미룬 값은 시간에 비례하지 않는다

합칠 때 손대야 할 자리는 두 가지가 겹치는 곳이다. 내 지선이 바꾼 것과 그동안 본선이 바뀐 것. 어느 한쪽만 바뀐 자리는 자동으로 처리된다.

그런데 이 둘이 양쪽 다 시간에 따라 자란다. 내가 오래 일할수록 내 쪽이 커지고, 그동안 남들도 일하니 본선 쪽도 커진다. 겹치는 면적은 그 둘을 곱한 만큼이다.

하루 뒤에 합치면

본선 2 × 지선 1 = 손댈 자리 2

사흘 뒤에 합치면

본선 6 × 지선 3 = 손댈 자리 18

엿새 뒤에 합치면

본선 12 × 지선 6 = 손댈 자리 72

가로 = 그동안 본선이 바뀐 것 · 세로 = 내 지선이 바꾼 것 · 칸 하나 = 사람이 직접 맞춰야 할 자리

미룬 시간이 여섯 배인데 손댈 자리는 여섯 배가 아니다. 두 변이 함께 자라서 서른여섯 배가 된다.

시간이 여섯 배면 손댈 자리는 여섯 배가 아니다. 그림처럼 양쪽이 함께 자라니 훨씬 크게 온다.

참고

이건 계산식이 아니라 방향이다. 실제로는 서로 다른 파일만 건드렸다면 아무리 오래 갈라져 있어도 겹치지 않는다. 다만 오래 걸리는 일일수록 건드리는 범위가 넓고, 넓을수록 남과 겹칠 확률이 올라간다. 방향은 늘 같은 쪽이다.

충돌을 푸는 건 새 코드를 쓰는 일이다

겹친 자리는 사람이 푼다. 그런데 이 작업은 생각보다 성질이 나쁘다.

풀려면 양쪽의 의도를 다 알아야 한다. 내가 왜 이렇게 고쳤는지, 그리고 남이 왜 저렇게 고쳤는지. 사흘 전 일이면 내 것은 기억나고 남의 것은 물어보면 된다. 세 주 전 일이면 내 기억도 흐릿하고, 남이 왜 그렇게 했는지는 아예 모른다.

더 나쁜 게 하나 있다. 충돌을 푼 결과는 어느 쪽에도 없던 새 코드다. 내 코드도 아니고 남의 코드도 아닌, 그 자리에서 급하게 만들어낸 제3의 코드다. 그러니 어느 쪽 테스트도 이 코드를 통과시켜 본 적이 없다.

합치기를 미루는 것은 결국 이 거래다. 지금의 집중을 사고, 나중의 판단력을 판다. 그리고 판단력이 가장 필요한 순간에 가장 흐릿한 상태로 도착한다.

리뷰가 커지면 리뷰가 아니게 된다

지선이 오래 살면 변경이 커지고, 변경이 커지면 리뷰가 나빠진다. 이건 리뷰어의 성실함 문제가 아니라 크기의 문제다.

변경 크기리뷰어가 실제로 하는 일
50줄줄마다 읽는다. 이름 하나, 조건 하나까지 본다
300줄중요해 보이는 곳을 골라 읽는다
2000줄훑는다. “큰 문제 없어 보인다”로 끝난다

여기에 더 나쁜 게 겹친다. 큰 변경일수록 리뷰어가 근본적인 지적을 하기 어려워진다. 설계가 틀렸다고 말하는 건 3주치를 되돌리라는 말이 되고, 그 말을 꺼내려면 각오가 필요하다. 그런데 그 지적이 가장 값진 순간이 바로 큰 변경일 때다.

작은 변경이면 “이건 이렇게 하는 게 낫겠다”가 가벼운 말이 된다. 고치는 데 30분이면 되니까. 같은 말이 3주짜리 앞에서는 사고가 된다.

리뷰의 질은 리뷰어가 아니라 지선의 수명이 정한다. 리뷰를 잘하게 만들려면 리뷰 방법을 고치기 전에 리뷰에 올라오는 덩어리를 줄이는 게 먼저다.

늦게 합칠수록 답을 늦게 안다

합치기는 코드를 하나로 만드는 작업이기도 하지만, 답을 받는 순간이기도 하다.

내 변경이 남의 변경과 함께 돌아가는지는 합쳐봐야 안다. 내가 세운 전제가 아직 유효한지도 합쳐봐야 안다. 그 전에는 아무리 확신해도 확인된 게 아니다.

세 주 뒤에 합치면 어떻게 되나. 세 주 전에 틀어진 것을 세 주 뒤에 안다. 그동안 그 틀어진 전제 위에 세 주치를 더 쌓아뒀다. 고쳐야 할 게 틀어진 그 지점만이 아니라 그 위에 얹은 전부다.

CI/CD 글에서 CI를 “자주 합치고 합칠 때마다 검증한다”로 정리했는데, 그 문장의 앞부분이 여기 걸린다. 자주 합치는 건 부지런함의 문제가 아니다. 답을 일찍 받으려는 것이다. 틀렸다는 답은 빨리 올수록 싸다.

짧게 사는 지선도 공짜는 아니다

여기까지 읽으면 답이 “무조건 짧게”로 보이는데, 반대편도 정직하게 적어야 한다.

지선을 하루 만에 되돌리려면 일이 하루치로 쪼개져 있어야 한다. 그런데 모든 일이 그렇게 쪼개지지는 않는다. 그리고 쪼갠 조각들에는 조건이 붙는다.

  • 각 조각이 그 자체로 말이 되어야 한다. 반쯤 만든 채 본선에 있어도 아무것도 안 깨뜨려야 한다.
  • 감출 수단이 필요하다. 앞 글에서 본 기능 플래그가 그 자리를 맡는데, 플래그를 넣고 걷는 일이 새로 생긴다.
  • 깨지 않는 순서를 지켜야 한다. 남이 쓰는 것을 바꿀 때 특히 그렇다. 더하기 먼저, 빼기는 나중이라는 API 계약의 순서가 같은 이유에서 나온다.
  • 쪼개는 데도 시간이 든다. 하나로 하면 안 했을 일을 하는 것이다.

그러니 이것도 거래다. 짧은 지선은 합치는 비용을 사고, 쪼개는 수고와 감추는 장치를 판다. 앞 글에서 본 그 저울이 여기서도 그대로 돈다.

실무에서: 줄여야 할 건 브랜치가 아니라 일의 크기

“브랜치를 짧게 유지하라”는 조언은 그 자체로는 실행할 수 없는 말이다. 브랜치는 원인이 아니라 결과라서 그렇다. 실제로 손댈 수 있는 자리는 따로 있다.

일을 작게 쪼갠다. 지선이 3주 사는 건 3주짜리 일을 통째로 맡았기 때문이다. 서두르라는 말이 아니라 되돌릴 수 있는 단위로 나누라는 말이다. 브랜치 규칙을 아무리 다듬어도 이걸 안 하면 안 줄어든다.

그래도 길어질 일이면 본선을 자주 끌어온다. 차이를 매일 조금씩 갚으면 마지막 날 한꺼번에 오지 않는다. 머지와 리베이스 가운데 무엇을 쓸지가 실제로 매일 벌어지는 자리가 여기다.

리뷰 대기가 수명의 대부분이면 브랜치 문제가 아니다. 코드는 하루에 다 됐는데 지선이 나흘을 살았다면 고쳐야 할 건 브랜치 규칙이 아니라 리뷰가 도는 속도다. 엉뚱한 데를 고치면 지표만 나빠진다.

돌아오지 않는 지선을 정리한다. 안 쓰는 지선이 쌓이면 목록을 볼 때마다 “이건 살아 있는 건가”를 판단해야 한다. 판단거리가 늘어나는 것 자체가 비용이다.

브랜치를 아예 안 파는 경우 - 이 블로그

이 저장소는 브랜치가 main 하나다. 작업 브랜치를 안 만든다. 발행을 미룰 글은 지선에 두는 게 아니라 front matter에 draft: true를 적어 표시하고, push하면 Cloudflare가 verify(타입 검사 → 빌드 → 링크 검사)를 돌려 통과한 것만 내보낸다.

이게 정답이라서가 아니라 조건이 그래서다. 글을 쓰는 사람이 하나다. 그러면 브랜치가 사는 것들이 대부분 사라진다.

  • 같은 파일을 동시에 고칠 사람이 없다.
  • 기다릴 리뷰가 없다. 지선이 살아 있을 이유의 큰 조각 하나가 없다.
  • “미완성이 남에게 보인다”의 그 남이 저장소 안에 없다.

그리고 감출 수단은 이미 있다. draft: true는 정확히 기능 플래그다. 글은 본선에 들어가 있고 독자는 못 본다. 브랜치가 하던 일을 데이터 한 줄이 하고 있으니 브랜치를 둘 이유가 남지 않는다.

사람이 둘만 돼도 이 답은 바뀐다. 그래서 여기서 가져갈 것은 “main 하나로 하라”가 아니다. 조건을 세어보고, 값을 못 하는 규칙은 세우지 않는다는 쪽이다. 브랜치 전략을 남에게서 가져다 쓰면 규칙만 오고 조건은 안 온다.

정리

브랜치를 얼마나 오래 둘지는 이렇게 갈린다.

조건짧게 유지할 이유가 커진다오래 둬도 되는 편이다
같은 코드를 만지는 사람여럿혼자에 가깝다
본선이 바뀌는 빈도하루에 여러 번며칠에 한 번
리뷰가 도는 속도몇 시간 안에 돈다어차피 며칠 걸린다
일을 쪼갤 수 있나쪼개진다통째로만 말이 된다
감출 수단플래그가 있다브랜치밖에 없다

그리고 이 시리즈가 계속 되돌아온 문장이 있다.

갈라놓는 건 거의 공짜고, 값은 전부 돌아올 때 치른다. 그러니 브랜치를 잘 쓴다는 말의 뜻은 잘 가르는 게 아니라 잘 돌아오는 것이다. 지선의 값은 놓는 데 있지 않고 본선에 다시 닿는 데 있다.