# 작업 지시 — MergeHub 9차 (두 칸이 무엇과 견주는지 사실대로 · 8차에서 남긴 것) 대상: `D:\Sorce\MergeTool\MergeHub` (플러그인) · `D:\Sorce\MergeTool\UbisamPlatform` (셸) 전제: 1~8차 지시서는 모두 끝났다([../진행상황.md](../진행상황.md)). **이번 지시서가 나온 곳** — 8차 E-1 에서 시험 저장소를 길마다 새로 만들어 **병합 · pull · rebase · cherry-pick · revert** 를 파일 비교 탭을 미리 열지 않고 MergeHub 만으로 끝까지 했다. 다섯 길 모두 커밋까지 갔고 줄끝 · BOM 바뀐 파일 · 충돌 표식 · class 이름 다른 파일이 모두 0 이었다. **새로 걸린 것은 하나(N1)와 그 곁가지 하나**다. 파일을 망가뜨리지는 않지만, 화면이 **줄 수를 무엇과 견줬는지 틀리게 말한다.** 근거와 수치는 [../history/2026-09-16-8차.md](../history/2026-09-16-8차.md) 의 E-1 에 있다. | 8차 E-1 에서 잰 것 | 병합 | pull | rebase | cherry-pick | revert | |---|---|---|---|---|---| | 끝낸 커밋 | 부모 둘 | 부모 둘 | rebase 완료 1/1 | 부모 하나 · 원래 메시지 · 작성자 박지훈 | Revert "내 쪽 작업" | | 줄끝 · BOM 바뀐 파일 | 0 / 33 | 0 / 33 | 0 / 31 | 0 / 33 | 0 / 36 | | 충돌 표식 · class 이름 다른 파일 | 0 · 0 | 0 · 0 | 0 · 0 | 0 · 0 | 0 · 0 | | 마지막 Save 뒤 두 칸의 기준(BASE) | HEAD | HEAD | HEAD | **이력에서 고른 커밋** | (마지막 파일은 파일 단위라 안 봄) | | 커밋 본문 해결 내역(8차 F-1) | 26개 | 26개 | 해당 없음 | 해당 없음 | 해당 없음 | --- ## 공통 규칙 - **A → B → C → D 순서로 진행한다.** A 는 화면이 사실과 다르게 말하는 것이라 먼저다. - **항목 하나를 끝낼 때마다** 빌드하고 실제로 실행해 화면을 확인한 뒤 보고한다. - **항목 하나가 끝나면 기록을 세 군데에 남기고 로컬 커밋한다**(4차 D-2 규칙). 1. **상세**는 `doc/history/YYYY-MM-DD-9차.md` — 원인 · 판단 · 확인한 결과 2. [../진행상황.md](../진행상황.md) 은 **대기 → 완료로 상태만** 3. [../history/changelog.md](../history/changelog.md) 에 한 줄 — 날짜 · 무엇을 왜 · 커밋 - **푸쉬하지 않는다.** - **실제 소스를 열지 않는다**(2026-09-11 결정). 시험 재료는 `C1Repo` 로 만든 저장소로 한다. 씨앗이 고정돼 몇 번을 만들어도 내용은 같다 (커밋 해시는 만든 시각에 따라 달라진다 — 기록에는 해시보다 커밋 제목을 적는다). 고치기 전에 문제가 **다시 나는 것부터 보이고**, 고친 뒤 안 나는 것을 보인다. - 기존 검사 하네스(22벌 1,094건)는 계속 통과해야 한다. 로직을 건드리면 **테스트를 먼저 늘린다.** - 빌드 경고 0 · 오류 0 을 유지한다. 앱이 실행 중이면 `UbisamBase.Shell` 을 먼저 종료한다. - 사용자 설정 파일(`D:\UbisamConfig\Settings\MergeHubSettings.json`)은 시험 전에 백업하고, 끝나면 **바이트 그대로** 되돌린다. 창 기억(`ShellWindowPlacement.json`)은 시험 뒤 "기억 없음" 으로 둔다. - **자동 조작으로 확인할 때는 사람이 갈 수 있는 길만 쓴다.** 켤 때 뜨는 이름 창은 [저장] 으로 닫고, 접힌 원격 영역은 [펴기] 로 연다. 파일 비교 탭은 **미리 열지 않는다**(`D7_NO_PREOPEN=1`). - **문서 글을 PowerShell 로 넣을 때는 작은따옴표 문자열만 쓴다**(8차에서 배움 — 큰따옴표 안의 백틱이 이스케이프로 먹혀 changelog 줄이 깨졌다). - **결과 확인은 줄끝만 보지 않는다.** 충돌 표식과 `UnitN.cs` 안의 class 이름도 본다. - 플랫폼을 고치면 다른 소비 프로그램에 미치는 영향을 함께 적고 `UbisamPlatform/doc/history/changelog.md` 에 남긴다. **배포는 사용자 확인 뒤.** --- ## A. 두 칸이 무엇과 견주는지 사실대로 ### A-1. cherry-pick 마지막 저장 뒤 "내 쪽 대비" 라고 하지만 실제 기준은 이력에서 고른 커밋이다 (8차 E-1 N1) — **먼저 정한다** - **다시 내는 순서**(8차 E-1 에서 따로 재 봄): 1. 새 저장소를 열고 이력 탭 [모든 브랜치] 를 켠 뒤 `상대 쪽 작업` 커밋을 골라 [Cherry-pick]. 2. 충돌 탭에서 `Weld/Unit1.cs` 만 남기고 나머지를 파일 단위 Accept Theirs. 3. `Weld/Unit1.cs` 를 [3분할로 열기] → 충돌마다 Take Theirs → [Save]. 4. 파일 비교 탭이 두 칸으로 떨어진다. 제목은 `(가져온 커밋 짧은해시) · Weld/Unit1.cs`, 요약은 **"충돌 정리 끝 · [커밋] 으로 cherry-pick 을 끝냅니다 · 내 쪽 대비 가져온 변경 N줄"**. HEAD 는 다른 커밋이다. - 제목은 사실(고른 커밋)을 말하는데 요약은 HEAD 와 견준 것처럼 말한다. **두 글이 서로 다른 기준을 말한다.** 8차 B-1 기록의 "cherry-pick 제목에 꼬리가 없는 것은 맞다" 는 제목만 본 판단이었다. - 짚이는 곳(코드를 읽어 짚은 것 — 원인부터 확인할 것): - `HomeViewModel.cs` 의 BASE 제목은 `commit.ShortSha == _workspace.HeadSha` 일 때만 작업 글("가져오기 전 내 쪽")을 쓰고, 아니면 `짧은해시 · 경로` 다. - 같은 파일의 요약(`UpdateSummaries`)은 `OperationLabels.ResolvedSummary` 를 **선택 커밋이 HEAD 인지 보지 않고** 쓴다. 그래서 "내 쪽 대비" 가 붙는다. - 선택 커밋은 이력 탭과 함께 쓰는 `_workspace.SelectedCommit` 이다(`GitViewModel.cs` 에서 이력 선택이 넣음). 새로고침 뒤에는 비어 있을 때만 `Commits[0]` 으로 채운다(`GitWorkspace.cs`). 병합 · rebase 는 이력에서 커밋을 고르지 않아 HEAD 로 남고, **cherry-pick · revert 는 이력에서 커밋을 골라 시작하므로 그 커밋이 남는다.** - revert 도 같은 길일 것이다. 8차 C-1 · E-1 의 revert 는 마지막 파일을 파일 단위로 풀어 두 칸을 보지 않았다. - **고치기 전에 사용자에게 두 가지를 보이고 정한다**(스크린샷과 함께). 1. **작업 중 충돌을 다 풀고 두 칸으로 돌아갈 때 기준을 HEAD 로 옮긴다** — 병합 · rebase 와 같아지고 "내 쪽 대비 가져온 변경 N줄" 이 사실이 된다. 대신 이력 탭의 선택도 HEAD 로 움직인다(같은 선택을 쓰므로). 이력 선택을 두고 파일 비교 쪽만 HEAD 로 볼 수 있는지도 함께 본다. 2. **기준은 고른 커밋 그대로 두고 글을 맞춘다** — 요약은 기준이 HEAD 일 때만 작업 글, 아니면 "충돌 정리 끝 · [커밋] 으로 cherry-pick 을 끝냅니다 · `짧은해시` 대비 N줄". - **판정 기준**: - 정한 대로 cherry-pick · revert 마지막 [Save] 뒤 **제목과 요약이 같은 기준**을 말한다. 줄 수가 그 기준과 실제로 견준 수와 같다(git 으로 같은 두 쪽을 diff 해 대조). - 병합 · pull · rebase 의 요약 · 제목은 8차 B-1 그대로(하네스로 확인). - 작업이 없을 때 이력에서 커밋을 골라 보는 보통 비교는 지금 그대로. ### A-2. 한 번은 기준이 HEAD 도 가져온 커밋도 아닌 다른 브랜치 커밋이었다 (8차 E-1 N1-덧) — 원인부터 - 8차 E-1 cherry-pick 에서 마지막 [Save] 뒤 제목이 `f310f49 · Weld/Unit1.cs` 였다. HEAD(`b7ac29b`)도 가져온 커밋(`68fe17f`)도 아니었고, 요약의 줄 수(3줄)로 보면 [모든 브랜치] 목록의 다른 브랜치 커밋(`뒤이은 수정`)으로 보인다. **같은 순서로 따로 다시 재니 나지 않았다.** - 짚이는 곳: 새로고침 때 커밋 목록을 갈아 끼우면(`Replace(Commits, …)`) 이력 목록이 고른 줄을 **위치(순번)로** 다시 잡을 수 있다. [모든 브랜치] 를 켜면 cherry-pick 뒤 목록 순서가 바뀐다. 선택 커밋이 목록에 없는 옛 객체로 남는 경우도 본다. - 방향: 1. 원인부터 — 새로고침 전후로 선택 커밋 · 목록 순번 · 이력 탭 선택 줄을 로그로 남겨 cherry-pick 길(8차 E-1 순서 그대로)을 **다섯 번 이상** 되풀이한다. 작업 순서(파일 단위 Accept 여러 번 · [3분할로 열기] · 저장 뒤 저절로 다음 파일 열기)가 새로고침을 겹치게 하는지 본다. 2. 다시 나면 원인을 적고 고친다 — 새로고침 뒤에도 선택은 **같은 해시의 커밋**으로 돌아가야 한다. 3. 다섯 번 넘게 해도 안 나면, 코드로 짚은 만큼과 되풀이한 횟수를 적고 사용자에게 보고한 뒤 닫는다(짐작으로 고치지 않는다). - **판정 기준**: 새로고침(작업 시작 · 충돌 해결 · 커밋) 뒤 선택 커밋의 해시가 새로고침 전과 같다. 목록 순서가 바뀌는 [모든 브랜치] 에서도. 하네스로 "목록 순서가 바뀐 새로고침 뒤 선택 복원" 을 만든다. --- ## B. 전에 남겨 둔 작은 것 ### B-1. MERGED 칸에서 반영하며 넣은 주석 줄이 다시 정렬하면 "무시" 색이 된다 (6차 기록) — **먼저 정한다** - 6차 기록([../history/2026-09-14-6차.md](../history/2026-09-14-6차.md)): 네 칸에서 줄을 가져오며 들어간 머지 주석 줄이, 다시 정렬하면(타이핑 멈춤 · 규칙 변경) "무시" 색으로 바뀐다. 차이 수에는 원래도 세지 않던 줄이다. - 8차 B-3 에서 MERGED 번호를 결과 파일 번호로 바꿨다. 주석 줄은 결과에 들어가는 줄이라 번호가 붙는다 — 색과 번호가 서로 다른 말을 하는지 본다. - 방향: 만든 저장소에서 다시 내 스크린샷으로 보이고 **사용자와 정한다.** ① 주석 줄은 처음 넣었을 때 색 그대로 ② 지금처럼 "무시" 색(비교에서 무시하는 줄이라는 뜻). 정한 뒤 고친다면 차이 수 · 번호 · [다음 충돌] 이동은 그대로여야 한다. - **판정 기준**: 정한 대로 색이 다시 정렬해도 바뀌지 않는다(또는 그대로 두기로 한 까닭을 적는다). 차이 수 · MERGED 번호 · 저장된 파일은 8차 결과 그대로. ### B-2. 폴더 비교 뒤 화면 트리를 세우는 데 1초 남짓 (5차 B-2 기록) — 재고 정한다 - 5차 기록([../history/2026-09-11-5차.md](../history/2026-09-11-5차.md)): "지금도 1초 남짓이고, 건드리면 트리 동작이 바뀔 위험이 있다. 더 줄일 자리로 적어 둔다." - 방향: 만든 폴더 두 벌(파일 수를 정해 적는다)로 **비교 · 트리 세우기 · 첫 화면까지**를 나눠 잰다. 트리 세우기가 대부분이면 줄일 방법과 위험을 적어 사용자에게 보이고 정한다. 트리 동작(펼침 · 선택 · 필터 · 끌어 놓기)이 바뀌는 방법이면 하지 않는다. - **판정 기준**: 잰 값(세 번 평균)을 적는다. 고쳤다면 같은 폴더로 전후를 견주고 트리 동작 확인 목록이 모두 그대로다. 안 고치기로 했다면 까닭을 적고 "미룬 것" 으로 옮긴다. --- ## C. 문서 ### C-1. 웹 문서를 8차 끝 · 9차에 맞게 - `doc\web\index.html` 은 8차 D-1(E-1 · F-1 전)에서 멈춰 있다. - 개요 숫자가 "7차 끝 · 8차 진행" · "22벌 · 1,073건" 이다(지금 1,094건). - **8차 F-1(병합 커밋 본문에 해결 내역)이 매뉴얼에 없다**(`본문` 0건). 파일 단위 Accept 의 기록이 어디 남는지 알려 줄 곳이다. - 남은 일의 "8차에 남은 것" 에 끝난 E-1 이 남아 있다. - A · B 를 고친 뒤 한 번에 맞춘다. 지난 기록(history)은 그때 이름 그대로 둔다. - **판정 기준**: 문서의 단추 이름 · 요약 글이 지금 화면과 같다(화면 문구를 grep 으로 대조). F-1 이 매뉴얼에 있다(본문 예시 포함). "알아 둘 한계" · 남은 일이 9차 끝 기준이다. 태그 짝이 맞는다. 발행된 아티팩트도 같은 내용으로 갱신. --- ## D. 확인 ### D-1. cherry-pick · revert 를 마지막 파일까지 네 칸으로 끝까지 (+ 병합 · rebase 회귀) - A · B 를 고친 뒤 저장소를 새로 만들어 한다. 파일 비교 탭은 미리 열지 않는다. - **cherry-pick · revert 는 마지막 파일을 네 칸 [Save] 로 푼다** — 8차 E-1 revert 는 마지막을 파일 단위로 풀어 두 칸의 기준을 보지 못했다. 둘 다 [모든 브랜치] 를 켠 채로 한다(A-2 를 밟는 순서). - 병합 · rebase 는 마지막 [Save] 뒤 요약 · 제목만 다시 본다(8차 B-1 회귀). - 8차 E-1 과 **같은 표로** 적는다. 새로 걸린 것은 고치지 말고 적는다 — 그 목록이 10차가 된다. - **판정 기준**: 네 길 모두 MergeHub 만으로 끝까지. 줄끝 · BOM 바뀐 파일 0 · 충돌 표식 0 · class 이름 다른 Unit 파일 0. 마지막 [Save] 뒤 제목 · 요약 · 실제 기준이 서로 같다. 8차 A-1 · B-1 · B-2 · F-1 이 다시 나지 않는다. --- ## 이번 지시서에서 하지 않는 것 - **실제 소스로 병합해 보기** — 실제 소스는 열지 않는다(2026-09-11 결정). - **빈 cherry-pick 을 커밋으로 남기는 길**(`--allow-empty`) — 두지 않기로 했다(2026-09-16 사용자 결정). - **비교할 때만 C# 스타일을 맞추고 저장은 원래대로 하는 선택지** — 만들지 않기로 했다(2026-09-17 사용자 결정). - **MergeHub 밖(터미널)에서 푼 충돌을 병합 본문에 적기** — 알 길이 없다. 본문 건수가 처음 충돌 수보다 적으면 그만큼은 밖에서 푼 것이다(8차 F-1). - 셸 창 스냅이 화면 반쪽이 안 되는 것 — 최소 크기(1280×720 DIP)가 반쪽보다 크다. 최소 크기를 줄이지 않는 한 그대로(8차 C-3). 왼쪽 스냅에서 Win+→ 가 가끔 복원되지 않는 것은 Windows 쪽 동작이라 두고 본다. 1px 테두리는 그대로(사용자 결정). - 화면 잠금 확인 창의 가운데 맞춤을 자동으로 재기 — 잠그면 사람이 풀어야 해서 확인이 멈춘다. 이름 창과 같은 길(`OwnerCentering`)이라 함께 맞는다(8차 C-3). - 빠른 비교(크기 · 수정일)가 내용만 바뀐 파일을 놓치는 것 — 폴더 비교의 알려진 한계로 둔다. - 같은 줄 접기(4차 B-2) · 외부 편집기(4차 B-4) · 로그인·권한 · Gitea PR — 미룬 그대로 둔다. --- ## 보고 형식 항목마다 이렇게 적는다. - 고치기 전에 문제가 **다시 나는 것**을 어떻게 보였는지 (만든 저장소의 어느 파일로) - 무엇이 원인이었는지 한두 줄 - 어떤 파일을 어떻게 고쳤는지 - 실제로 실행해 확인한 결과 (줄 수 · 해시 · 줄끝 · 충돌 수 · class 이름처럼 **눈이 아닌 값**으로) - 커밋 해시