다른 저장소에서 가져온 코드 뭉치가 프로젝트 안에 들어 있었다. 그 부분을 고쳐야 할 일이 생겼는데 원래 어디 것인지 아무도 몰랐다. 파일은 src/Common/Utils/ 아래 DateHelper.php 와 CryptoHelper.php 로 우리가 쓴 것처럼 보였는데 스타일이 달랐고 주석이 @package internal-tools 를 가리켰다. git log --diff-filter=A 로 들어온 시점까지는 나왔지만 커밋 메시지가 「공통 유틸 추가」뿐이라 어느 저장소인지는 없었다.
Table of contents
Open Table of contents
문제 — 출처를 찾는 데 든 시간
여러 저장소를 뒤져 원본을 찾는 데 반나절이 걸렸다. 받아서 diff 를 떠 보니 그 저장소의 현재 판과 우리 것이 여러 곳 달라져 있었다.
우리가 고친 것인지 원본이 그 뒤에 바뀐 것인지를 구분할 방법이 없었다. 어느 시점의 무엇을 가져왔는지 안 남겨 두면 나중에 이 대조가 불가능해진다. 찾는 데 든 시간보다 대조하는 데 든 시간이 훨씬 길었다.
이름과 기록에 남기기
그래서 가져온 코드는 src/Vendor/internal-tools/ 처럼 폴더 이름에 출처를 넣어 파일 목록만 봐도 우리 것이 아니라는 것이 드러나게 했다.
그리고 그 폴더의 README.md 에 어느 저장소의 어느 판과 커밋인지를 적었다.
출처 git@git.internal:common/internal-tools.git
판 v1.4.2 (커밋 8f2a1c3)
가져온 날 2019-01-12
## 고친 것
- DateHelper::toKst() 에 시간대 인자 추가 (2019-01-12)
## 원본과 맞출 때
원본이 갱신되면 이 폴더를 통째로 다시 받고 위 "고친 것"을 다시 적용한다.
그 해시만 있으면 나중에 git diff 로 원본과 비교할 때 기준점이 생긴다. 이름은 눈에 띄게 하고 기록은 대조를 가능하게 하는 것이라 둘 다 필요했다.
고친 것을 따로 적었다
README.md 의 「고친 것」에 DateHelper::toKst() 처럼 무엇을 왜 고쳤는지 한 줄씩 남기고 코드에도 표시를 달았다.
그러면 원본이 갱신됐을 때 우리 수정만 다시 얹으면 된다. 목록이 없으면 diff 로 두 판을 통째로 비교해서 우리 것을 골라내야 한다. 이 목록이 있고 없고가 원본 갱신을 따라갈 수 있는지를 정했다.
고치는 대신 감싸기
더 나은 방법은 원본을 아예 안 고치고 필요한 동작이 다르면 감싸는 코드를 우리 쪽에 두는 것이었다.
그러면 원본을 통째로 갈아 끼워도 우리 코드가 그대로 산다. 실제로 몇 군데를 그렇게 바꿔 놓으니 갱신이 훨씬 쉬워졌다. 고칠 수밖에 없는 곳만 고치고 나머지는 감싸는 것이 기준이 됐다.
원본 갱신과 다른 복사본
원본 저장소의 HEAD 가 움직였는지 git ls-remote 로 cron 에서 주기적으로 확인하게 걸어서 갱신이 있으면 알림을 받고 그때 반영할지 판단하게 했다.
그리고 같은 방식으로 들어온 다른 코드가 더 있는지 찾아봤더니 몇 개 더 나왔다. 그중 두 개는 같은 원본을 서로 다른 자리에 복사한 것이었다. 왜 가져왔는지와 언제 다시 볼지도 함께 적어 두어야 그 판단을 다음 사람이 할 수 있었다.
정리
- 가져온 코드는 어디서 언제 가져왔는지 남긴다
- 폴더 이름에 출처를 넣으면 우리 것이 아님이 드러난다
- 기준 커밋 해시가 없으면
diff로 대조할 수 없다 - 고친 것을 목록으로 적고 코드에도 표시한다
- 목록이 있어야 원본 갱신을 따라갈 수 있다
- 고치는 것보다 감싸는 쪽을 우선한다
git ls-remote로 원본이 갱신됐는지 주기적으로 확인한다- 같은 원본이 여러 자리에 복사돼 있을 수 있다