- 사용자 결정: 줄 간격만 줄이고 선택 사항(단추 · 설정)은 만들지 않음 - 12 → 16, 1920x1080 두 칸 40 → 50줄, 네 칸 17 · 18 → 22 · 23줄 - 북마크 표식 높이도 줄에 맞춤 - FontTest 144(1,572건), E-1 회귀 없음 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
91 KiB
11차 진행 기록 (2026-09-18 ~)
지시서: ../작업지시/11차.md
A-1. 변경분 추출을 먼저 뽑아 보고 적는다 (2026-09-18, 완료 · 고치지 않음)
지시서대로 고치지 않고 적기만 했다. 제품 코드는 바꾸지 않았다.
무엇으로 했나
C1Repo로 저장소를 새로 만든 뒤e11-a1-setup.sh로 추출 시험용 커밋을 더 쌓았다(전부 지어낸 파일).
| 커밋 | 무엇 |
|---|---|
4eb9ece base |
내 쪽 작업 (C1Repo 의 feature/mine) |
d3eb15b c1 |
새 파일 Extract/Temp.cs · Io/Unit12.cs 한 줄 더함 |
f884ed1 c2 |
Recipe/Unit11.cs 지움 · Motion/Unit16.cs → Motion/Renamed16.cs(내용 그대로) · 이진 Extract/logo.bin · 한글폴더/깊은/경로/아래/설명.cs |
cbcad8a c3 |
Io/Unit12.cs 를 c1 전으로 되돌림 · Extract/Temp.cs 지움 (범위 안에서 생겼다 사라짐) |
f702996 side · 58d5f7f merge |
base 에서 갈라진 옆가지에 Side/SideOnly.cs, 그것을 --no-ff 로 병합 |
- 화면은 사람 순서로: Git 탭 → 이력에서 줄을 마우스로 고르고 [여기부터] · [해제] · [변경분 추출], 폴더 창에는 경로를 쳐 넣고 Enter.
- 뽑은 폴더는
git diff -M --name-status의 기대 목록과 견주고, 파일마다git hash-object --no-filters로 바이트(blob 해시) 를 대조했다.
아홉 경우의 결과
| # | 경우 | 알림 | 뽑힌 것 | git 과 견주면 |
|---|---|---|---|---|
| 1 | 커밋 하나(시작점 없음, c1) | "2개 파일 추출" | Extract/Temp.cs · Io/Unit12.cs |
같음 · 바이트 같음 |
| 2 | 범위 [여기부터] base → c3 | "3개 파일 추출 (삭제되어 건너뜀 1개)" | Extract/logo.bin · Motion/Renamed16.cs · 한글폴더/…/설명.cs |
같음 — 범위 안에서 생겼다 사라진 Temp.cs, 바뀌었다 되돌아온 Unit12.cs 는 들어가지 않는다(맞다) |
| 3 | 지운 파일이 있는 범위 | 위와 같은 알림 | — | 건너뛴 개수만 알린다. Recipe/Unit11.cs 라는 것은 화면 · 로그 · 폴더 어디에도 없다 |
| 4 | 이름 바뀐 파일 | — | Motion/Renamed16.cs (새 이름) |
새 경로로 바이트 그대로. 옛 경로(Motion/Unit16.cs)를 알 길이 없다 — 장비에 덮어 넣으면 옛 파일이 남는다 |
| 5 | 병합 커밋 하나(merge) | "1개 파일 추출" | Side/SideOnly.cs |
첫 부모(c3)와만 견준다. 둘째 부모(옆가지)와 견주면 4개인데, 지금 무엇과 견주는지는 화면에 없다 |
| 6 | 거꾸로 범위 [여기부터] c3 → base | "2개 파일 추출 (삭제되어 건너뜀 2개)" | Motion/Unit16.cs · Recipe/Unit11.cs |
git 의 diff c3 base 와 같음(되돌리는 방향으로 동작). 경고나 방향 표시는 없다 |
| 7 | 이진 · 한글 · 깊은 경로 | 2 와 같음 | logo.bin 278B · 설명.cs 50B |
바이트 · 경로 그대로 |
| 8 | 이미 파일이 있는 폴더 | "3개 파일 추출 (삭제되어 건너뜀 1개)" | 폴더 안 6개 | 묻지 않고 덮어쓴다. 앞서 뽑아 둔 Extract/Temp.cs · Io/Unit12.cs(c1 것)와 사람이 넣어 둔 사용자메모.txt 가 그대로 남아 섞인다 |
| 9-a | 대상 파일이 읽기 전용 | "변경분 추출 실패: … 액세스가 거부되었습니다" | 2개(logo.bin + 읽기 전용 그대로) | 반쯤 뽑힌 채 멈춘다 — 앞 순서 logo.bin 은 써졌고 뒤 순서 한글…설명.cs 는 빠졌다. 몇 개까지 됐는지는 알림에 없다 |
| 9-b | 대상 파일이 다른 프로그램에 열려 있음 | "… 다른 프로세스에서 사용 중이므로 …" | 2개 | 9-a 와 같은 모양 |
- 알림과 같은 글이 Git 탭 로그에도 남는다 — 성공은
변경분 추출: N개 파일 → 경로 (삭제되어 건너뜀 M개), 실패는[변경분 추출] 실패: …. - 범위 표시는 제대로 바뀐다: 시작점이 없으면
부모 → 고른 커밋, [여기부터] 를 누르면4eb9ece → 고른 커밋. - 폴더 창은 늘 저장소가 있는 폴더에서 열린다.
- 저장소 워킹트리는 아홉 경우 내내 Clean 이었다(추출은 읽기만 한다).
이걸로 확정된 것 (A-2 ~ A-4 로 넘긴다)
| 번호 | 확정된 문제 | 어디로 |
|---|---|---|
| ① | 지운 파일 · 이름 바뀐 옛 경로가 결과에 남지 않는다(경우 3 · 4) | A-2 |
| ② | 무엇과 무엇 사이를 뽑았는지 폴더에 남지 않는다(경우 5 · 6 — 병합 커밋은 첫 부모, 거꾸로 범위도 말없이 됨) | A-2 |
| ③ | 비어 있지 않은 폴더에 묻지 않고 덮어쓰고 옛 파일이 섞인다(경우 8) | A-3 |
| ④ | 쓰다 막히면 반쯤 뽑힌 채 멈추고, 어디까지 됐는지 알 수 없다(경우 9-a · 9-b) | A-3 에 덧 — 먼저 쓸 수 있는지 보고 시작할지, 실패해도 나머지를 계속할지 정한다 |
맞게 도는 것(고칠 것 없음): 파일 고르기(1 · 2 · 5 · 6 모두 git 과 같은 목록) · 바이트 보존(이진 · 한글 · 깊은 경로 포함) · 범위 표시 · 로그.
남긴 것 (시험 도구 쪽, 제품 아님)
화면 자동 조작에서 세 번 막혔다. 모두 스크립트 문제였고 제품과 무관하다.
- 함수 이름
History가 PowerShell 기본 별칭(history=Get-History)과 겹쳐, 내 함수 대신 그것이 불렸다 →GoHistory로 바꿈. - 폴더 창(
#32770)은 데스크톱 바로 아래가 아니라 본 창 아래에 붙는다 → 본 창의 자손에서 찾게 고침. - 폴더 창의 경로 칸(
id 1152)과 [이 폴더 선택](id 1)은 UIA 에서 Pane 으로 보이고, 같은 id 를 가진 다른 칸이 먼저 잡혔다 → id + 클래스(Edit·Button)로 고르고, 경로를 한 글자씩 친 뒤 Enter 로 닫게 함. - 백그라운드로 돌리면 앱 창이 앞으로 나오지 못해 마우스가 다른 창을 누른다 → 앞에서 돌린다.
A-2. 뽑은 폴더 옆에 "무엇을 뽑았는지" 안내를 남긴다 (2026-09-18, 완료)
사용자 결정(2026-09-18): 안내는 뽑은 폴더 밖(옆) 에 두고, 장비에서 지울 파일은 목록으로만 적는다(지우는 배치 파일은 만들지 않는다).
왜
A-1 에서 값으로 확인한 것 — 지운 파일은 "삭제되어 건너뜀 1개" 라고 개수만 알리고 어느 파일인지 아무 데도 없었다. 이름이 바뀐 파일은 새 이름만 뽑혀, 그 폴더를 장비에 덮어 넣으면 옛 파일이 그대로 남는다. 무엇과 무엇 사이를 뽑았는지도 폴더만 보고는 알 수 없었다.
고친 것
| 자리 | 한 일 |
|---|---|
Services/ExportReport.cs (새 파일) |
안내 글을 만든다. 머리글(만든 때 · 만든 사람 · 저장소 · 뽑은 곳 · 범위 두 줄) · 뽑은 파일 목록(추가 · 수정 · 이름 바뀜은 옛 이름을 괄호로) · 장비에서 지워야 할 파일 목록(지워진 파일 · 이름 바뀐 옛 경로). PathFor 가 폴더 옆 이름을 정한다 — …\변경분 → …\변경분_변경분안내.txt, 드라이브 뿌리처럼 옆자리가 없으면 폴더 안에 |
Services/GitService.cs |
ExportChangedFiles 가 (뽑은 수, 건너뛴 수, **무엇을 어떻게 했는지 목록**) 을 돌려준다. git 의 상태 글자(Added · Renamed · Copied …)를 안내 글의 말로 옮기고, 이름이 바뀐 파일은 옛 경로를 함께 들고 온다 |
Services/IGitService.cs |
같은 서명으로 |
ViewModels/GitViewModel.cs |
뽑은 뒤 안내를 폴더 옆에 쓴다(TextFile.Write). 범위 줄은 이력에 있는 커밋이면 제목과 날짜까지, 시작점을 안 잡았으면 "(고른 커밋의 부모)" 를 붙인다. 안내 파일 경로를 로그에 남기고, 알림도 "지워야 할 파일 N개는 안내에" 로 바꿈. 안내를 못 써도 추출 자체는 실패로 만들지 않는다(파일은 이미 다 뽑힌 뒤다) |
하네스 ReportTest |
+14건(31 → 45) — 머리글 · 범위 두 줄 · 요약 수 · 이름 바뀜 표기 · 지울 목록 · 지운 파일이 뽑은 목록에 없음 · 한글 경로 · 빈 목록 · 만든 사람 없음 · 폴더 옆 이름 세 가지 |
확인한 것 — 화면에서 뽑아 git 과 대조
| 경우 | 안내에 적힌 것 | git diff -M --name-status |
|---|---|---|
범위 4eb9ece → cbcad8a |
뽑은 3개(추가 Extract/logo.bin · 이름 바뀜 Motion/Renamed16.cs (옛 이름 Motion/Unit16.cs) · 추가 한글폴더/깊은/경로/아래/설명.cs) · 지울 2개(옛 이름 Motion/Unit16.cs · 지워짐 Recipe/Unit11.cs) |
A logo.bin · R100 Unit16.cs → Renamed16.cs · D Unit11.cs · A 설명.cs — 같음 |
| 병합 커밋(시작점 없음) | 범위 cbcad8a … (고른 커밋의 부모) → 58d5f7f … · 뽑은 1개 Side/SideOnly.cs · 지울 0개 |
같음 |
- 안내 파일은 폴더 옆에 생긴다(
note2b_변경분안내.txt·note5_변경분안내.txt). 폴더 안에는 뽑은 파일만 있다. - 알림: "3개 파일 추출 (지워야 할 파일 1개는 안내에)" · "1개 파일 추출 · 안내 note5_변경분안내.txt". Git 탭 로그에 안내 경로도 남는다.
- 하네스 22벌 1,173건 통과(1,159 → +14) · 빌드 경고 0 · 오류 0.
남긴 것 (시험 도구 쪽)
- 화면 잠금이 걸린 동안에는 마우스가 데스크톱에 닿지 않는다(커서 좌표가 0,0 으로 돌아가고 화면 캡처가 실패한다). 잠긴 줄 모르고 "클릭이 안 먹는다" 로 두 번 헤맸다 — 앞으로는 커서 자리와 맨 앞 창부터 본다.
- 목록에서 스크롤이 필요한 줄은 누를 때마다 자리를 다시 읽어야 한다. 옛 자리로 누르면 조용히 빗나가고, 그 뒤 [여기부터] 가 엉뚱한 커밋(HEAD)으로 잡혀 범위가 거꾸로 됐다.
- PowerShell 변수는 대소문자를 안 가린다 —
$S(경로)와$s(파일 글)가 겹쳐 경로가 깨졌다(9차 A-2 와 같은 종류).
A-3. 이미 파일이 있는 폴더 · 쓰다 막힐 때 (2026-09-18, 완료)
사용자 결정(2026-09-18): 고른 폴더 아래 새 폴더를 만든다 · 쓰다 막히면 먼저 보고 시작한다(하나라도 못 쓰면 아무것도 쓰지 않는다).
고친 것
| 자리 | 한 일 |
|---|---|
Services/ExportPlan.cs (새 파일) |
FolderName — 변경분_4eb9ece..cbcad8a_2026-09-18 처럼 범위와 날짜가 들어간 이름. UniquePath — 같은 이름이 있으면 _2 · _3. Blocked — 쓰기 전에 읽기 전용 · 다른 프로그램이 잡고 있는 파일을 걸러 목록으로. BlockedMessage — 사람에게 보일 글(앞 다섯 개 + "외 N개") |
Services/GitService.cs |
뽑기 전에 ExportPlan.Blocked 로 먼저 본다. 하나라도 막히면 폴더도 만들지 않고 IOException 으로 멈춘다 — 예전에는 앞 순서만 써진 반쯤 뽑힌 폴더가 남았다(A-1 경우 9) |
ViewModels/GitViewModel.cs |
고른 폴더에 바로 쏟지 않고 그 아래 새 폴더를 만들어 거기에 뽑는다. 안내 글은 그 폴더 옆(= 고른 폴더 안)에 붙는다. 알림도 폴더 이름을 앞에 — "변경분_4eb9ece..cbcad8a_2026-09-18 에 3개 (지워야 할 파일 1개는 안내에)" |
하네스 ReportTest |
+12건(45 → 57) — 폴더 이름 · _2 · _3 · 읽기 전용은 막힘 · 아직 없는 파일은 막힘 아님 · 열려 있는 파일은 막힘 · 보일 글의 개수와 줄임 |
확인한 것 — 화면에서
이미 파일이 있는 폴더(사람이 넣어 둔 사용자메모.txt · 옛 폴더 옛자료)를 골라 같은 범위를 두 번 뽑았다.
| 때 | 결과 |
|---|---|
| 첫 번째 | …\a3\변경분_4eb9ece..cbcad8a_2026-09-18 에 3개 · 안내는 그 옆에 |
| 두 번째 | …_2 폴더가 새로 생기고 거기에 3개 · 안내도 …_2_변경분안내.txt |
| 고른 폴더 안 | 새 폴더 둘 · 안내 둘 · 사용자메모.txt 와 옛자료 그대로 — 섞이지 않았다 |
- 먼저 보기(
Blocked)는 하네스 12건으로 확인했다. 화면에서는 재현되지 않는데, 뽑을 때마다 비어 있는 새 폴더를 만들기 때문이다 — A-1 경우 9(반쯤 뽑힌 폴더)가 애초에 생기지 않는다. 남겨 둔 까닭은 폴더가 이미 있는 드문 경우(다른 프로그램이 같은 이름을 방금 만든 경우)와, 나중에 폴더를 다시 쓰게 고칠 때를 위한 것이다. - 하네스 22벌 1,185건 통과(1,173 → +12) · 빌드 경고 0 · 오류 0.
남은 것
- A-4(ZIP)는 아래(09-22).
- 매뉴얼 · 웹 문서의 변경분 추출 설명(새 폴더 · 안내 파일)은 E-2 에서 함께 고쳤다.
A-4. 변경분을 ZIP 으로도 (2026-09-22, 완료)
사용자 결정: 폴더에 더해 ZIP 도(권장안). 장비에는 폴더를 넣고, 메일 · 메신저로 보낼 때 ZIP 을 쓴다.
만든 것
| 자리 | 한 일 |
|---|---|
Services/ExportZip.cs (새) |
PathFor — 뽑은 폴더 옆, 폴더 이름 + .zip. Create — 안에 뽑은 폴더와 안내 파일을 나란히 넣는다(풀면 폴더로 뽑은 것과 같은 모양, 안내가 소스 틈에 섞이지 않는 A-2 결정 그대로). 파일은 바이트 그대로 · 경로는 / · 수정 시각 그대로. .part 이름에 쓰고 다 되면 옮겨, 쓰다 막혀도 반쯤 된 ZIP 이 남지 않는다 |
Services/ExportPlan.cs |
UniquePath 가 같은 이름의 .zip 이 남아 있어도 그 이름을 쓴 것으로 본다 — 폴더만 지우고 ZIP 을 남긴 채 다시 뽑으면 옛 ZIP 을 덮을 뻔했다 |
ViewModels/GitViewModel.cs |
폴더 · 안내를 쓴 뒤 ZIP 을 만든다. 못 만들어도 폴더는 이미 다 뽑혔으므로 추출은 성공(안내와 같은 규칙), 로그에 까닭. 알림 끝에 "· ZIP 도" / "· ZIP 은 못 만듦(로그)" |
MergeHub.csproj |
System.IO.Compression 참조 — .NET Framework 에 들어 있어 배포 묶음 파일이 늘지 않는다(빌드 출력에 새 dll 없음) |
하네스 ReportTest |
+13건(57 → 70) — ZIP 자리 · 넣은 수 · 풀면 같은 이름 폴더 · 경로 · 해시 목록이 폴더와 같음 · 안내는 폴더 밖 · 안내 바이트 · 빈 파일 · / 경로 · 한글 경로 · 한글 이름 UTF-8 표시(bit 11) · 같은 이름 ZIP 이 있으면 _2(폴더가 없어도). 고치기 전에 넣어 "폴더 없이 ZIP 만 남은 경우" 가 실패하는 것을 보고 시작 |
확인 — 화면에서 아홉 경우 다시 (e11-a1-setup.sh · e11-e1-a.ps1 · e11-a4-verify.sh)
- 모든 경우 알림 끝에 "· ZIP 도". 새 폴더 8개마다 옆에 ZIP.
- ZIP 을 앱과 다른 도구(Windows
tar.exe)로 풀어 뽑은 폴더와 견줌 — 8/8 경로 · SHA-256 목록 같음, 안내 파일 바이트 같음 · 폴더 밖. - 앱(.NET Framework 4.8)이 만든 ZIP 의 이름 칸 —
변경분_…/한글폴더/깊은/경로/아래/설명.cs까지 모두 UTF-8 표시(bit 11) 켜짐. 하네스는 .NET 8 에서 돌므로 이 표시는 실제 앱이 만든 파일에서 따로 확인했다. - 하네스 22벌 1,260건(1,247 → +13) · 빌드 경고 0 · 오류 0 · 설정 해시 같음.
문서
- 웹 문서(버전 14): 매뉴얼 "변경분 추출" 에 ZIP 한 단계, 남은 일 A-4 완료, "기획안에서 아직 안 한 것" 에서 ZIP 뺌, 기획안 v2 표 변경분 추출 완료, 숫자 1,260건 · 하네스 막대 폭 다시 잼.
- 기획안: 변경분 파일 추출 "일부" → 완료, Git 작업 버튼 줄 완료, 1,260건. 8쪽 A4 높이 그대로. 원문(
plan/mergetool.html, 비교 원본mergetool-0922.html)만 고쳐 두었다. - 웹 문서 · 기획안은 11차가 끝날 때 한 번에 반영 · 잠금 · 발행한다(2026-09-22 사용자: "11차 끝내기 전에는 웹문서 업데이트하지마", "11차 끝나면 한번에 잠글게"). 버전 14 는 그 말 전에 올라간 것이라 그대로 둔다.
- ZIP 안이 텍스트로 바뀌는지 물음이 있어 앱이 만든 ZIP 두 개를 풀어 git 의 그 커밋과 파일마다 대조 —
.cs·.bin이 원래 이름 · 확장자 · 폴더 · BOM · 줄끝 그대로 바이트 같음. 텍스트는 폴더 옆 안내 파일 한 장뿐.
11차 끝에 웹 문서에 넣을 것 (모아 둠)
- 개요 "로컬 커밋" 숫자(버전 14 는 129).
- 이 뒤 11차 항목(F 등)에서 바뀌는 화면 · 설정 · 숫자.
- F-1: 칸 이름
LOCAL(Mine)·REMOTE(Theirs), 칸 머리 "어느 쪽 · 어느 파일"(MERGED · 두 칸 LOCAL 은 "(저장할 파일)", mergetool 은 임시 파일 이름), 긴 이름은 가운데 줄임 · 툴팁. 머지 주석 모양[사람] 날짜 출처 설명(출처 = 로그의 말 — Theirs(…) · Mine(…) · REMOTE(…) · BASE(…)), Take Mine 도 주석, 두 칸 로그BASE(해시) 반영· 브랜치 3-Way 로그REMOTE(브랜치) 반영. 매뉴얼의 주석 예시 · 칸 설명 · 해결 기록이 남는 곳 표. 숫자 1,312건. - F-2: [이 메서드 반영](C# · C/C++, 클래스 멤버 통째, 단추 아래 한 줄에 잡은 범위 · 못 잡은 까닭), 덩어리 · 메서드 반영은 주석 한 줄 · 로그 한 줄 · Undo 한 번. 매뉴얼의 반영 단추 설명에. 숫자 23벌 1,395건.
- F-3: 매뉴얼 "탐색기에서 열기" — 여러 개를 골라 보내면 앞의 둘(3개 이상은 알림), 폴더 둘은 바로 폴더 비교, 260자 넘는 경로는 열지 못함(알림), 배포 묶음을 옮겨도 켜면 보내기 바로가기가 따라옴, 설치 파일 필요 없음. 알아 둘 한계에 "떠 있어도 새 창". 숫자 23벌 1,411건.
- F-4: 매뉴얼 파일 비교 화면 — [ACTIONS 감추기] · F9, 아래 탭 줄 [탭 접기] · 띠 · F11(플랫폼), 단축키 표에 F9 · F11. 숫자 23벌 1,414건 · 플랫폼 31건.
- F-5: 매뉴얼 설정 표 "보기 > 코드 글자 크기", 파일 비교 화면 Ctrl+휠 · Ctrl++/- · Ctrl+0 · 상태 줄
글자 N, 단축키 표. 숫자 24벌 1,538건. - F-6: 줄 간격을 좁혀 1920 × 1080 두 칸 40 → 50줄(매뉴얼의 화면 설명 · 그림이 있으면 새로). 숫자 24벌 1,572건.
B-1. 배포 묶음을 다시 만들고 꼭 필요한 파일을 가림 (2026-09-22, 완료)
고치기 전 — 매뉴얼이 가리키는 Release 는 09-07 것
| 무엇 | 값 |
|---|---|
bin\Release\net48 |
65개 · 96MB. MergeHub.dll 09-07 14:11, 셸 09-07 13:41 (플랫폼은 그 뒤 09-16 에 다시 배포됨) |
| 옛 Release 로 켜면 | 오류 없이 켜지지만 본 탭이 3개(지금은 4개 — 폴더 비교 탭이 없음). 지금 소스의 형식 142개 가운데 74개가 옛 dll 에 없다 — 폴더 비교(FolderView · FolderComparer), 3분할(ThreeWayAligner), 병합 저장 판단(MergeSavePlan), 단축키(ShortcutMap), 변경분 안내(ExportReport · ExportPlan), 커밋 수정 판단(CommitSelection · CommitReword) 등 6차 이후 것 (e11-b1-old.ps1, 이름 대조) |
무엇이 필요한지 가린 길
- 참조로 — 셸 · MergeHub 에서 시작해 dll 이 부르는 dll 을 따라갔다. 어디서도 닿지 않는 것 7개:
GLWpfControl·OpenTK·SkiaSharp.Views.WPF·SkiaSharp.Views.Desktop.Common·LiveChartsCore.SkiaSharpView.WPF·Microsoft.Extensions.Options·…Options.ConfigurationExtensions. 플랫폼 dll 안에 이 이름이 글자로도 없다(XAML 로 부르는 것도 아님). - 플랫폼이 쓰는 것 —
UbisamBase.Core가SkiaSharp·LiveChartsCore·LiveChartsCore.SkiaSharpView를 직접 참조한다(Charting/ChartTheme.cs, 테마를 바꿀 때UiSettingsService가 부름). MergeHub 는 안 쓰지만 플랫폼 몫이라 남긴다(사용자 결정 2026-09-22 — 빼면 약 8MB 가 되지만 플랫폼이 바뀔 때마다 다시 재야 한다). - 셸이 켜질 때 하는 일 — 셸은 폴더의
*.dll을 모두Assembly.LoadFrom으로 열어IAppSetup을 찾는다(AppSetupLoader.cs:16). 쓰지 않는 dll 도 이름 순서상MergeHub.dll앞이면 켤 때마다 읽힌다 — 빼면 그만큼 덜 읽는다.Lang폴더는 없으면 플랫폼이 만든다(LanguageService.cs), 지금은 비어 있다. - 다른 OS · CPU — 맥용 dylib 3개(17.5MB), 리눅스 · 맥용 libgit2 9개(약 19MB), ARM 용(Skia · HarfBuzz 11MB, libgit2). 이 PC 에서 셸은 64비트로 뜬다. x86 은 32비트 Windows 를 위해 남긴다.
- 지워 보고 켜서 — 통째 복사본(65개 · 97MB)과 줄인 묶음(41개 · 44MB)을
%TEMP%에 따로 두고 켰다. 둘 다 오류 없이 켜지고 본 탭 4개가 모두 열렸다(UIA 로만 이동,e11-b1-run.ps1).
빈 폴더에서 병합 한 길 (e11-b1-merge.ps1 — 10차 E-1 의 병합 길 그대로, 실행 파일만 묶음으로)
| 무엇 | 결과 |
|---|---|
| 실행 파일 | %TEMP%\mergehub-beta\UbisamBase.Shell.exe (줄인 묶음) |
| 병합 | feature/theirs → feature/mine 충돌 24건 (머지 주석만 다른 2건 자동) |
| 풀기 | 파일 단위 15 · 줄 단위 7 · 파일 지우기 · 남기기 · 누른 Take 18번 = 줄 고른 로그 18줄 |
| 병합 커밋 | 647f1f8 부모 둘 · 본문 "충돌 해결 26개" · 줄끝 · BOM · 인코딩 바뀐 파일 0 · 충돌 표식 0 · 워킹트리 깨끗 |
| 두 탭 | Git 탭에서 고른 커밋을 파일 비교 탭이 따라감(10차 B-1) |
| 걸린 시간 | 304초 |
만든 것
| 자리 | 한 일 |
|---|---|
scripts\make-bundle.ps1 (새) |
Release 빌드(vswhere 로 MSBuild 를 찾음, -NoBuild 로 건너뜀) → 뺄 것 24개를 까닭과 함께 한 표에서 빼고 → -Out(기본 %TEMP%\mergehub-beta)에 옮기고 → 꼭 있어야 할 것(셸 · Core · MergeHub · LibGit2Sharp · git2 x64)을 확인하고 → 묶음 안에 배포묶음.txt(파일 · 크기 · 까닭, 뺀 것 · 까닭, 만든 시각 · 커밋)를 쓴다. 다른 파일이 든 폴더는 비우지 않고 멈춘다(배포묶음.txt 가 있는 폴더 · 빈 폴더만) — 남의 파일을 넣어 둔 폴더로 확인함 |
매뉴얼(doc/web/index.html 켜기와 탭 구성) |
"Release 로 다시 빌드해야 최신" · 다른 PC 에는 스크립트로 묶음을 만들어 폴더째 복사 · 배포묶음.txt 설명 |
- 스크립트로 만든 묶음이 손으로 만들어 시험한 묶음과 파일 목록이 같고, 다시 켜도 오류 없이 네 탭이 열렸다.
- Release 빌드 경고 0 · 오류 0. 제품 코드 변경 없음(스크립트 · 문서만).
배포 묶음 (41개 · 43.5MB)
| 묶음 | 파일 | 크기 | 까닭 |
|---|---|---|---|
| 셸 · 플랫폼 | UbisamBase.Shell.exe · .exe.config · UbisamBase.Core.dll |
0.7MB | 켜는 것 · .NET 4.8 · 버전 맞춤 · 플랫폼 |
| MergeHub | MergeHub.dll |
0.6MB | 셸이 폴더의 dll 을 훑어 찾는다 |
| Git | LibGit2Sharp.dll · lib\win32\x64\git2-*.dll · lib\win32\x86\git2-*.dll |
4.0MB | Git 조작 · 네이티브 |
| MVVM · 인코딩 | CommunityToolkit.Mvvm.dll · System.Text.Encoding.CodePages.dll |
0.8MB | 플랫폼 · MergeHub · CP949 판별 |
| 플랫폼 설정 · DI | Microsoft.Extensions.* 11개 |
0.5MB | 플랫폼 |
| .NET 보강 | System.* 9개 · Microsoft.Bcl.AsyncInterfaces |
1.1MB | 플랫폼 · Json |
| 차트(플랫폼 몫) | LiveChartsCore 둘 · SkiaSharp 둘 · HarfBuzzSharp · 네이티브 6개(루트 · x64 · x86) |
35.8MB | 플랫폼 Core 가 참조(ChartTheme) |
남은 것
- 묶음은
%TEMP%에 있다. 다른 PC 에 줄 자리(공유 폴더 · 문서 폴더)는 베타 때 정한다. - 지시서의 "다섯 탭" 은 지금 본 탭 4개(폴더 비교 · 파일 비교 · Git · 설정)다 — 지시서 글이 옛 것.
- 웹 문서 발행(아티팩트)은 E-2 에서.
- 플랫폼 배포 폴더(
D:\UbisamPlatform\bin)는 손대지 않았다. 플랫폼 README 가 "UbisamBase.Shell 을 Release 로 빌드하면 이 폴더를 갱신" 한다고 하므로, 플랫폼을 새로 배포하면 이 스크립트를 다시 돌려야 한다.
B-2. D 드라이브가 없는 PC · 설정이 없는 첫 실행 (2026-09-22, 완료 — 플랫폼에서 고치고 확인 뒤 배포)
지시서대로 D 드라이브는 건드리지 않았다. D:\UbisamConfig 는 먼저 통째로 백업하고(20개, 파일마다 SHA256 · 크기 · 수정 시각 목록) 이름만 잠시 바꿔 재고, 끝날 때마다 되돌려 목록과 대조했다(두 번 모두 같음). 시험은 모두 UIA 로만 누르고 읽었다(마우스 · 키보드 · 화면 찍기 없음).
설정이 없는 첫 실행 (배포 묶음 %TEMP%\mergehub-beta, e11-b2.ps1)
| 볼 것 | 결과 |
|---|---|
| 오류 창 | 없음 |
| 이름 창 | 빈 칸으로 뜬다 · 빈 채로 [저장] 하면 "이름을 입력하세요." 로 막힘 · 이름을 넣고 [저장] 하면 닫힘 |
| 켜는 순간 생기는 것 | Settings\MergeHubSettings.json · Settings\UiSettingsService.json. 이름을 저장하면 CurrentUserService.json, 첫 기록 때 Log\ |
| 기본값 | MergeHubSettings.json 이 매뉴얼 설정 표와 모두 같다 — 원격 이름 origin · 줄 필터 켬 · 단어 단위 · 문법 강조 켬 · 커밋 조회 200 · 머지 주석 남기기 · 무시 켬 · C# 스타일 1(AURORA, F-12) · 공백 단계 0 · 나머지 비움 |
| 창 위치 | 주 모니터에 최대화(2560×1600). 닫으면 ShellWindowPlacement.json(보통 크기 2048×1222 · Maximized true) |
| 네 탭 | 모두 열림, 오류 글 없음 |
D 드라이브가 없을 때 — 코드로 따라가고, 같은 줄에서 실패하게 해 봄
- 셸
App.OnStartup→UbisamAppBuilder.Run의 첫 줄UiSettingsService.Initialize(D:\UbisamConfig)→Directory.CreateDirectory(D:\UbisamConfig\Settings)(UiSettingsService.cs:86)에 감싼 곳이 없다. 드라이브가 없으면DirectoryNotFoundException. 로그 서비스는 그보다 뒤에 준비된다. - 드라이브를 없애는 대신
D:\UbisamConfig자리에 같은 이름의 빈 파일을 두면 같은 줄이IOException으로 실패한다. - 결과: 셸의 공용 예외 창 "문제가 생겼습니다 — 작업 중 문제가 생겨 이 동작을 멈췄습니다. 프로그램은 계속 쓸 수 있습니다 … 자세한 내용은 D:\UbisamConfig\Log 아래 로그 파일에 남았습니다." 두 말 모두 사실이 아니다(본 창 없음 · 로그 없음). [확인] 을 누르면 창 없는 프로세스가 30초 뒤에도 남았다. 다시 켜면 하나씩 더 쌓인다.
정한 것 (2026-09-22 사용자) · 고친 것 — 플랫폼
- D 를 못 쓰면
%LOCALAPPDATA%\UbisamConfig에 쓴다(권장안). 켜는 중 실패는 알리고 끝낸다(권장안). - 플랫폼 커밋
377ffd3—Bootstrap/ConfigLocation(새) ·Bootstrap/StartupMessages(새) ·UbisamAppBuilder.ConfigRoot를const→ 속성(+ConfigFallbackReason), 로그를 가장 먼저 준비 ·LockConfirmDialog의 ScreenSaver 자리 ·LogService.LogDirectory· 셸App.OnStartup에서 켜는 중 실패를 받아Shutdown(1). 플랫폼changelog.md에 다른 소비 프로그램 영향과 함께 적음,platform-guide.md11장 · 세 곳 고침. - 하네스
PlatformCfgTest(새, 플랫폼 두 파일을 엮음) 24건 — 자리 고르기 · 둘 다 안 될 때 · 실제 임시 폴더 · 같은 이름 파일 · 없는 드라이브 글자로 실제로 다른 자리를 고름 · 실패 글(켜는 중에는 "계속 쓸 수 있습니다" 를 안 함 · 로그가 없으면 "남았습니다" 를 안 함). - 플랫폼은 Debug 로만 빌드했다(경고 0 · 오류 0). Release 는 빌드 후 단계가 곧바로
D:\UbisamPlatform\bin을 덮어쓰기 때문이다 — 배포 폴더는 그대로(09-16).
고친 뒤 (배포 묶음에 고친 Debug Core · Shell 두 파일만 바꿔 넣은 %TEMP%\mergehub-beta-b2)
| 경우 | 결과 |
|---|---|
| D:\ 에 만들 수 있을 때 | 예전처럼 D:\UbisamConfig · %LOCALAPPDATA% 에 아무것도 안 생김 · 경고 없음 |
| D:\ 자리가 막혔을 때 | C:\Users\Ubisam\AppData\Local\UbisamConfig 에 Settings 넷 · Log 가 생기고 이름 창 → 네 탭 → 정상 종료. 로그 첫 줄 [W] Platform: D:\UbisamConfig 를 쓸 수 없어 C:\Users\Ubisam\AppData\Local\UbisamConfig 에 설정 · 로그를 둡니다 (같은 이름을 가진 파일 또는 디렉터리가 이미 있어서 …) |
| 두 자리 모두 막혔을 때 | 창 "켜지 못했습니다" — "프로그램을 켜지 못해 끝냅니다. 설정 폴더를 만들 수 없습니다. D:\UbisamConfig : … / C:\Users\Ubisam\AppData\Local\UbisamConfig : …" (로그가 없으니 로그 얘기는 없음) → [확인] 뒤 프로세스 끝남 |
- MergeHub 는 이전 Core 로 빌드된 그대로 새 Core 위에서 돌았다(바뀐 것은 속성 추가뿐, MergeHub 는
ConfigRoot를 읽지 않는다). - MergeHub 쪽: 매뉴얼 "설정 — … MergeHubSettings.json 에 저장된다" 에 D 없는 PC 의 자리를 덧붙이고,
MergeHubSettings.cs주석을 사실대로. 하네스 22벌 1,247건 그대로 · 빌드 경고 0 · 오류 0.
배포 (2026-09-22 사용자 확인 뒤)
publish-platform.ps1로D:\UbisamPlatform\bin갱신(배포 시각 11:27:25, 경고 0 · 오류 0). 48개 가운데 바뀐 것은UbisamBase.Core.dll·UbisamBase.Shell.exe·README.txt셋, 없어진 파일 없음(배포 전 목록 · 해시와 대조).- MergeHub 를 다시 빌드하고
make-bundle.ps1로 묶음을 다시 만듦(41개 · 43.5MB). 묶음 · Debug 출력의 Core · Shell 이 배포 폴더와 해시가 같다. 새 묶음으로 켜 네 탭 오류 없음 · 로그에 자리 경고 없음(D 를 씀). - 시험이 남긴 것(시험용 설정 폴더 셋 · 빈 파일 셋 ·
%LOCALAPPDATA%쪽 폴더 · 시험 묶음 둘)은 사용자 말대로 모두 지움.D:\UbisamConfig원본만 남음.
남은 것
- 드라이브는 있는데 읽기 전용(CD · 쓰기 막힌 USB)인 경우도 같은 길(
CreateDirectory실패 → 다른 자리)로 가지만 재 보지는 않았다. 폴더는 있는데 파일만 못 쓰는 경우(권한)는 이번에 다루지 않았다.
C-1. 있는 [커밋 수정] 을 다시 내 보고 바로잡음 (2026-09-18, 완료 — 8 만 이번 범위 밖)
고치기 전에 여덟 가지를 화면에서 다시 냈다
시험 저장소: C1Repo 위에 amend 브랜치를 만들고 작성자 박지훈인 커밋을 HEAD 로, 다른 브랜치(feature/revert)에는 더 새 커밋을, 그리고 bare 저장소를 원격으로 걸어 upstream 을 두었다(e11-c1-setup.sh).
| # | 고치기 전에 본 것 |
|---|---|
| 1 | [모든 브랜치] 켠 채 [마지막 메시지] → 칸에 딴 브랜치 최신 작업(HEAD 아님). 그대로 [커밋 수정] 하니 HEAD 제목이 그 메시지로 바뀌었다 |
| 2 | 앱에서 [전체 스테이징] 한 파일이 말없이 커밋에 들어갔다(남은 변경 없음). 알림은 "커밋 수정" 뿐 |
| 3 | 작성자 박지훈 · 작성 2026-09-15 10:00 → 시험 · 2026-09-18 15:48 로 바뀜 |
| 4 | 충돌 24개가 남은 채로도 단추가 켜져 있고, 누르면 [커밋 수정] 실패: cannot create a tree from a not fully merged index |
| 5 | 병합 커밋을 고쳐도 부모 둘 · 본문(충돌 해결 26개 · 29줄) 그대로 |
| 6 | 원격에 이미 올라간 커밋도 막지 않고 고쳐졌고, 그 뒤 [Push] 가 cannot push non-fastforwardable reference 로 거부됨 |
| 7 | 알림 · 로그에 새 해시만(커밋: 61653f5 …). 고치기 전 해시는 어디에도 없음 |
| 8 | 커밋 메시지 칸이 한 줄짜리라 여러 줄 메시지를 아예 칠 수 없다. # 로 시작하는 글자는 그대로 들어간다 |
고친 것 (1 · 3 · 4 · 7)
| 자리 | 한 일 |
|---|---|
Services/CommitSelection.cs |
MessageOfHead — [마지막 메시지] 는 HEAD 커밋의 메시지를 읽는다(목록 순서와 무관). HEAD 가 목록에 없으면 아무것도 주지 않는다. CanAmend — 작업 중이면 끈다. AmendHint — 꺼진 까닭을 단추 설명으로. AmendDone — "커밋 수정 완료 (옛 abc1234 → 새 def5678) · 파일 N개 포함" |
Services/GitService.cs |
고쳐 쓸 때 원래 작성자 · 작성 시각을 그대로 쓴다(git 과 같게). 커밋한 사람 · 시각만 지금 |
Services/GitWorkspace.cs |
HeadFullSha 를 들고 있는다 — 이력 목록의 Sha 와 맞춰 보려면 짧은 해시로는 모자란다 |
ViewModels/GitViewModel.cs |
위 판단을 붙이고, 고치기 전 해시 · 함께 들어간 파일 수를 알림에. 작업이 시작 · 끝날 때 단추 설명도 다시 그린다 |
Views/GitView.xaml |
[커밋 수정] 설명을 상황에 따라 바뀌는 값으로 |
하네스 MergeSaveTest |
+15건(210 → 225) — HEAD 메시지 읽기(맨 위가 딴 브랜치여도 · 대소문자 · HEAD 가 목록에 없음 · 빈 목록) · 켜는 조건 넷 · 꺼진 까닭 · 알림 글 셋 |
고친 뒤 같은 순서로 다시
| # | 결과 |
|---|---|
| 1 | 칸에 남이 만든 커밋(HEAD 것) |
| 3 | 고친 뒤에도 작성자 박지훈 · 작성 2026-09-15 10:00 그대로, 커밋한 사람 · 시각만 지금 |
| 4 | 충돌 24개가 남은 동안 단추 꺼짐 — 누를 수 없고, 누른 뒤 실패 알림도 없다 |
| 7 | 알림 커밋 수정 완료 (옛 bcd2c43 → 새 fd7810c) · 파일 1개 포함 |
- 하네스 22벌 1,200건 통과(1,185 → +15) · 빌드 경고 0 · 오류 0.
이어서 고친 것 (2 · 6) — "먼저 묻기" (2026-09-18 사용자 결정)
두 가지 모두 막지 않고 먼저 묻는다. 막으면 정말로 그러려는 사람(빠뜨린 파일을 같이 넣기 · 아직 남이 안 받은 커밋 고치기)까지 못 하게 되고, 그대로 두면 모르는 새 벌어진다.
| 자리 | 한 일 |
|---|---|
Services/CommitSelection.cs |
AmendWarning(스테이징 수, 이미 올림, 원격 브랜치) — 물을 것이 없으면 null(안 묻는다). 있으면 해당하는 줄만 모아 "… ¶ 계속할까요?" 한 글로 |
ViewModels/GitViewModel.cs |
StagedFileCount(충돌 뺀 스테이징 수) · HeadTrackedBranch · IsHeadAlreadyPushed(추적 브랜치가 있고 앞선 커밋 0개). 물을 것이 있으면 MessageUtil.ShowYesNo 로 먼저 묻고, [아니오] 면 커밋도 메시지 칸도 그대로 두고 아무 일도 하지 않는다 |
하네스 MergeSaveTest |
+7건(225 → 232) — 안 묻는 경우 · 스테이징만 · 올린 것만 · 둘 다 · 브랜치 이름을 모를 때 "원격" · "Push 가 거부됩니다" · 끝이 늘 "계속할까요?" |
앞선 커밋 수는 마지막 fetch 시점 기준이라, fetch 전에 남이 받아 간 것까지는 알 수 없다. 그래서 막지 않고 묻기만 한다(주석에 남김).
고친 뒤 화면에서 (e11-c1g.ps1)
스테이징 1개를 만들어 두고, HEAD 가 origin/amend 와 같은 자리인 채로 냈다 — 두 가지가 겹치는 자리다.
| 무엇 | 결과 |
|---|---|
| [커밋 수정] 누름 | 확인 창 커밋 수정 — "스테이징해 둔 파일 1개도 이 커밋에 들어갑니다. / 이 커밋은 origin/amend 에 이미 올라가 있습니다. 고치면 다음 Push 가 거부됩니다. / 계속할까요?" · 단추 [아니오] [예] (e11-c1g-ask.png) |
| [아니오] | HEAD 62dd57f 그대로 · 스테이징 Recipe/Unit19.cs 그대로 · 메시지 칸 묻는지 확인 그대로 · 창 닫힘 |
| 다시 누르고 [예] | HEAD 62dd57f → 6207b26 · 알림 커밋 수정 완료 (옛 62dd57f → 새 6207b26) · 파일 1개 포함 |
| 스테이징 없음 · 원격보다 앞선 자리에서 다시 | 안 묻고 바로 고침 (ceaab5f, 작성자 박지훈 그대로) (e11-c1g-done.png) |
- 하네스 22벌 1,207건 통과(1,200 → +7) · 빌드 경고 0 · 오류 0 · 설정 파일 해시 같음.
남은 것
- 8. 여러 줄 커밋 메시지 — 칸이 한 줄이라 본문을 칠 수 없다. 이번 범위 밖으로 적어 둔다(병합 커밋 본문은 앱이 저절로 붙인다). C-2 의 [메시지 바꾸기] 창은 여러 줄을 받는다.
- C-2 는 아래(2026-09-22 완료).
C-2. 마지막이 아닌 커밋의 메시지 바꾸기 (2026-09-18 ~ 09-22, 완료 — 좁은 범위)
사용자 결정(2026-09-18): 한다 — 좁은 범위로. 화면은 기획안 문구대로 이력 줄 우클릭 메뉴.
고치기 전
- 이력 줄을 우클릭해도 메뉴가 없고, 이력 탭 단추는 Revert · Cherry-pick · Reset · 여기부터 · 해제 · 변경분 추출뿐이었다(
e11-c2-before.ps1). 고른 커밋의 메시지를 바꿀 길이 없었다. - 메시지는 커밋 해시에 들어가므로, HEAD 가 아닌 커밋을 바꾸면 그 커밋부터 HEAD 까지가 새 해시로 다시 써진다. 아직 안 올린 커밋이면 브랜치가 새 줄기로 옮겨 갈 뿐이지만, 올린 뒤라면 남의 이력과 갈라진다(사용자에게 설명함).
만든 것
| 자리 | 한 일 |
|---|---|
Services/CommitReword.cs (새) |
막을 까닭 — 고른 커밋 없음 · 작업 중 · 커밋 안 한 변경 · 지금 브랜치 조상 아님 · 원격에 올라감 · 다른 로컬 브랜치도 품음 · 구간에 태그 · 사이에 병합 커밋. 먼저 풀어야 할 것부터 말하고 푸는 길까지 적는다. 확인 글 · 완료 알림 · 메뉴 설명. Clean — 새 메시지를 git -m 처럼 다듬는다(아래) |
Services/GitService.cs · IGitService.cs · Models/GitModels.cs |
InspectReword — 저장소에서 사실만 읽는다(다시 쓸 수 · 병합 수 · 올라간 원격 브랜치 · 다른 브랜치 · 태그). RewordCommit — LibGit2Sharp Refs.RewriteHistory 로 고른 커밋의 메시지만 갈고 트리 · 작성자 · 작성 시각 · 부모 관계는 그대로. 바꾸기 전 자리는 refs/original/날짜-시각/ 에 남긴다(같은 자리에 두 번 쓰면 libgit2 가 막아서 시각을 붙임). 고친 커밋의 새 해시도 돌려준다 |
Views/RewordWindow.xaml(.cs) (새 창) |
새 메시지를 받는 창. 고친 커밋 한 줄(해시 · 작성자 · 날짜) · 몇 개가 다시 써지는지를 늘 보이고, 여러 줄을 받는다. 지금 메시지를 미리 넣어 전체를 골라 둔다. [바꾸기] 는 기본 단추가 아니다(Enter 는 줄바꿈) |
Views/GitView.xaml(.cs) |
이력 목록의 우클릭 메뉴 [메시지 바꾸기...] — MergeHub 의 첫 우클릭 메뉴. 목록은 오른쪽 누름으로 선택이 안 바뀌므로 우클릭한 줄을 먼저 고른다(10차 B-1 처럼 저장 안 한 편집이 있으면 먼저 묻고 [취소] 면 메뉴도 안 연다) |
ViewModels/GitViewModel.cs |
막힐 자리면 메뉴를 끄지 않고 눌렀을 때 까닭을 알림으로 — 까닭은 저장소를 읽어 봐야 알고, 꺼 두면 왜 안 되는지 알 길이 없다. 되면 창 → 확인 창 → 실행 → 고른 커밋이 새 해시를 따라간다 |
하네스 MergeSaveTest |
+40건(232 → 272) — 막는 여덟 가지와 보는 순서 · 확인 글 · 완료 알림 · 빈 메시지 · 안 바뀐 메시지 · 다듬기 아홉 |
화면에서 찾아 고친 것 — 끝 줄바꿈
첫 회차에 새 메시지가 줄바꿈 없이 저장됐다(셋 으로 끝남). git 이 만든 커밋은 늘 \n 으로 끝나고, MergeHub 의 [커밋] · [커밋 수정]도 libgit2 가 다듬는다. 칸을 어떻게 고쳤느냐에 따라 끝 줄바꿈이 있다 없다 했다.
libgit2 의 다듬기(PrettifyMessages)를 켜면 손대지 않은 뒤 커밋들 메시지까지 다듬어지므로, 새 메시지 하나만 CommitReword.Clean 으로 다듬는다(줄 끝 공백 · 앞뒤 빈 줄 없앰, 빈 줄 여럿은 하나, 끝은 줄바꿈 하나, # 줄 · 들여쓰기는 둠). 검사 9건을 먼저 넣어 실패를 보고 고쳤다.
같은 회차의 다른 둘은 스크립트 탓으로 가렸다(e11-c2-probe.ps1): 첫 우클릭이 안 먹은 것은 창을 앞으로 부르는 도우미가 다른 프로그램 창을 앞으로 가져와 클릭이 앱에 안 닿은 것, 한글이 한 글자만 들어간 것은 8ms 간격으로 몰아 친 것. 150ms 간격으로 치면 그대로 들어갔다.
고친 뒤 화면에서 (e11-c2-setup.sh · e11-c2a.ps1 · e11-c2b.ps1 · e11-c2c.ps1)
시험 저장소: reword 브랜치에 커밋 넷(작성자 박지훈 · 이수진, 셋째는 일부러 "셋제 커밋" 오타). 막힐 자리로 pushed(bare 원격에 올림) · merged(사이에 병합) · shared + shared-copy · tagged(v9.9).
되는 자리 — "셋제 커밋" 우클릭 → [메시지 바꾸기...]
| 무엇 | 결과 |
|---|---|
| 우클릭 | 그 줄이 먼저 골라지고 메뉴 메시지 바꾸기... |
| 창 | 83ed0b2 · 박지훈 · 2026-09-16 11:00 · "이 커밋과 그 뒤 1개, 모두 2개가 새 해시로 다시 써집니다" · 칸에 셋제 커밋 (e11-c2-window.png) |
| [취소] | HEAD 4c0263e 그대로 |
| "셋째 커밋" 치고 [바꾸기] | 확인 창 "83ed0b2 "셋제 커밋" 의 메시지를 바꿉니다. 이 커밋과 그 뒤 1개, 모두 2개가 새 해시로 다시 써집니다. 내용 · 작성자 · 작성 시각은 그대로입니다. 바꾸기 전 HEAD 4c0263e 는 로그에 남겨…" (e11-c2-confirm.png) |
| [예] | 알림 메시지 바꿈 완료 (옛 HEAD 4c0263e → 새 HEAD 1b11c03) · 커밋 2개 다시 씀 · 로그 … · 되돌릴 자리 refs/original/20260922-102604/ |
| git 대조 | 넷째 · 셋째: 트리 해시 · 작성자 · 작성 시각 같음, 해시만 새것. 제목은 셋째만 바뀜. 둘째 아래는 해시까지 그대로 · 커밋 수 같음 · 워킹트리 깨끗 |
| 메시지 끝 | 셋째 커밋\n — 손 안 댄 넷째(넷째 커밋\n)와 같은 꼴 |
| 고른 커밋 | 새 해시 b2d9880 을 따라감 |
| 되돌리기 | git reset --hard refs/original/20260922-102604/heads/reword → 4c0263e … 셋제 커밋 이 그대로 돌아옴 |
막히는 자리 — 모두 창이 안 뜨고 HEAD 그대로, 알림에 까닭
| 자리 | 알림 |
|---|---|
| 올린 커밋 | "이 커밋은 origin2/pushed 에 이미 올라가 있습니다. 올린 커밋을 다시 쓰면 남의 이력과 갈라져 막습니다." |
| 사이에 병합 | "고른 커밋과 HEAD 사이에 병합 커밋이 1개 있습니다. 병합 이력은 다시 쓰지 않습니다." |
| 다른 브랜치도 품음 | "이 커밋을 다른 브랜치도 품고 있습니다(shared-copy). 그 브랜치까지 다시 써야 해서 막습니다." |
| 구간에 태그 | "다시 쓸 구간에 태그가 있습니다(v9.9). 태그가 가리키는 커밋이 사라져 막습니다." |
| 작업 중(병합 충돌 26개) | "병합 · rebase · cherry-pick · revert 를 끝낸 뒤에 쓸 수 있습니다." |
| 커밋 안 한 변경 | "커밋하지 않은 변경이 있습니다. 먼저 커밋하거나 stash 한 뒤에 바꾸세요." |
| 다른 브랜치에만([모든 브랜치]) | "지금 브랜치에서 닿지 않는 커밋입니다. 그 커밋이 있는 브랜치로 체크아웃한 뒤에 바꾸세요." (e11-c2-other.png) |
| 파일 비교 탭에 저장 안 한 편집 | 우클릭하자 저장하지 않은 편집 창("Common/Util/Unit103.cs 에 저장하지 않은 편집이 있습니다. 다른 커밋을 봅니다.") → [취소] 면 메뉴도 안 열리고 선택 그대로 (e11-c2-unsaved.png) |
- 하네스 22벌 1,247건 통과(1,207 → +40) · 빌드 경고 0 · 오류 0 · 설정 파일 해시 같음.
알아 둘 것
- 판단은 마지막 fetch 시점 기준이다. fetch 전에 남이 올린 것까지는 모른다(C-1 과 같음).
- 되돌릴 자리
refs/original/…은 이력 목록에 안 보인다(목록은 브랜치만 훑음). 지우는 단추는 두지 않았다 — 되돌릴 일이 없으면 그대로 두어도 된다. - HEAD 커밋도 이 메뉴로 바꿀 수 있다. [커밋 수정] 과 달리 스테이징한 파일이 들어가지 않는 메시지만 고치는 길이다.
D-1. 시험 도구 둘 (2026-09-22, 완료 — 제품 코드 변경 없음)
| 도구 | 고치기 전 | 고친 것 |
|---|---|---|
d1-verify.ps1 (줄끝 · BOM · 표식 검사) |
부모 하나인 커밋(rebase · cherry-pick · revert)에도 없는 둘째 부모로 git merge-base 를 불러 사용법 글 · null 오류를 찍었다(판정 숫자는 맞았음) |
부모가 하나면 첫 부모와만 견준다고 적고 merge-base 를 부르지 않는다. 견줄 부모 쪽 파일이 없는 새 파일은 가운데 BOM · 줄끝 섞임만 본다 |
d7lib.ps1 의 FileState (파일 비교 탭 요약 읽기) |
요약 글을 "남은 충돌 · 충돌 정리 끝 · 남은 차이" 로만 찾아, 제품이 쓰는 "차이 없음"(편집이 있으면 "차이 없음 · 편집 N건 …")을 못 읽고 커밋 뒤 요약을 빈칸으로 적었다 | "차이 없음*" 도 요약으로 읽는다 (HomeViewModel.cs:3486 의 글과 맞춤) |
확인:
- 앱 없이 — 시험 저장소 HEAD(revert 커밋
d59bc42, 부모 하나)에 돌려 오류 · 사용법 줄 0, 결과는 E-1 revert 때와 같음(36개 · 다른 파일 0). - 판정대로 rebase 한 길을 다시(
e11-e1-merge.ps1 -Way rebase, 298초) — 오류 줄 0,[계속]뒤 파일 비교 탭 요약 "차이 없음", "부모: … 하나 — 첫 부모와만 견준다", 누른 Take 18 = 로그 18 · 줄끝 · BOM 0/31 · 표식 0 · class 0 · 워킹트리 Clean · 설정 해시 같음. - 고치기 전 두 파일은
*.d1bak로 남김(시험 도구 폴더, 저장소 밖).
E-1. 바꾼 길을 다시 끝까지 (2026-09-22, 완료 — 새로 걸린 것 없음)
11차에서 바뀐 것에 맞춰 넷을 돌렸다. A(변경분 추출) · C-1 · C-2 를 고쳤고, F-12 가 비교 · 저장에 걸리는 C# 스타일 기본값을, B-2 가 플랫폼 시작부를 바꿨으므로 다섯 길 + pull 도 다시 했다. 모두 Debug 출력(배포한 플랫폼 09-22 11:27 과 해시 같음), 사람 순서로(마우스 · 키보드).
1. A-1 의 아홉 경우 (e11-a1-setup.sh · e11-e1-a.ps1 · e11-e1-a-verify.sh)
모두 첫 회차에 끝. 뽑은 곳은 고른 폴더 아래 새 폴더, 안내는 그 옆(A-2 · A-3 설계대로).
| # | A-1 때 | 지금 |
|---|---|---|
| 1 커밋 하나 | 2개 · 바이트 같음 | 변경분_228995f..8145f3b_2026-09-22 에 2개 · 바이트 같음 · 안내 범위 "(고른 커밋의 부모)" |
| 2 범위 | 3개 · 바이트 같음 | 3개 · 바이트 같음 · 안내에 이름 바뀜 "(옛 이름 Motion/Unit16.cs)" |
| 3 지운 파일 | 어디에도 없음 | 안내 "장비에서 지워야 할 파일" 에 지워짐 Recipe/Unit11.cs |
| 4 이름 바뀐 옛 경로 | 알 길이 없음 | 같은 목록에 옛 이름 Motion/Unit16.cs (→ Motion/Renamed16.cs 로 바뀜) — git 기대 지울 것 2개와 같음 |
| 5 병합 커밋 | 첫 부모와만 · 화면에 없음 | 같은 동작(1개) · 안내에 범위 37a2ced … (고른 커밋의 부모) → 84961da 로 무엇과 견줬는지 남음 |
| 6 거꾸로 범위 | 말없이 됨 | 같은 동작(2개 · 지울 것 3개) · 안내에 방향 그대로(37a2ced → 228995f) |
| 7 이진 · 한글 · 깊은 경로 | 바이트 그대로 | 바이트 그대로 |
| 8 이미 파일이 있는 폴더 | 옛 추출 · 사용자 파일과 섞임 | 두 번 뽑으니 새 폴더 둘(범위별 이름) · 사용자메모.txt 그대로 |
| 9-a · 9-b 읽기 전용 · 잠긴 파일 | 반쯤 뽑힌 채 멈춤 | 새 폴더에 써서 막힘 없이 3개 · 미리 둔 파일은 손대지 않음 |
- 대조 스크립트가 경우 8 의 첫 폴더(c1 범위)를 둘째 범위와 견줘 "다름" 이라고 찍었다 — 그 폴더는 안내대로 c1 범위이고 경우 1 과 같은 내용이다(스크립트가 폴더마다 범위를 따로 안 봄).
- 저장소 워킹트리 내내 Clean.
2. C-1 의 여덟 경우 (e11-c1-setup.sh · e11-e1-c.ps1 · e11-e1-c1again.ps1)
| # | C-1 고치기 전 | 지금 |
|---|---|---|
| 1 | [모든 브랜치] 에서 [마지막 메시지] 가 딴 브랜치 메시지 | 목록 맨 위 딴 브랜치 최신 작업 인데 칸에 남이 만든 커밋(HEAD) |
| 2 | 스테이징 파일이 말없이 들어감 | 확인 창 "스테이징해 둔 파일 1개도 이 커밋에 들어갑니다" → [예] → 알림 "… · 파일 1개 포함" |
| 3 | 작성자 · 작성 시각이 바뀜 | 두 번 고쳐도 작성자 박지훈 · 작성 2026-09-15 10:00 그대로 |
| 4 | 작업 중에도 켜져 실패 | 병합 충돌 26개 동안 꺼짐 · 설명 "병합 · rebase · cherry-pick · revert 를 끝낸 뒤에 쓸 수 있습니다" |
| 5 | (부모 둘 그대로) | [마지막 메시지] 가 Merge branch e1-side · 고쳐도 부모 둘 |
| 6 | 막지 않고 Push 거부 | 확인 창 "이 커밋은 origin/amend 에 이미 올라가 있습니다. 고치면 다음 Push 가 거부됩니다" → [예] 뒤 [Push] cannot push non-fastforwardable reference (정한 대로 묻기만) |
| 7 | 새 해시만 | 알림 "커밋 수정 완료 (옛 4816f3e → 새 953816a)" |
| 8 | 한 줄 칸 | 그대로(범위 밖으로 둠) |
3. C-2 로 이력을 다시 쓴 저장소에서 병합 한 길 (e11-e1-merge.ps1 -Way reword)
새 저장소의 feature/mine 에 커밋 둘(박지훈 · 이수진)을 얹고, 앞 커밋 첫 추가 커밋(오타 잇음) 을 우클릭 → [메시지 바꾸기...] 로 첫 추가 커밋 으로 고친 뒤 그대로 병합.
- 확인 창 "… 이 커밋과 그 뒤 1개, 모두 2개가 새 해시로 다시 써집니다 …" → 알림
메시지 바꿈 완료 (옛 HEAD e1d924c → 새 HEAD 3145f3f) · 커밋 2개 다시 씀. - 앞 네 커밋의 작성자 · 작성 시각 · 트리 4/4 같음, 제목은 고른 것만. 되돌릴 자리
refs/original/20260922-115615/heads/feature/mine. - 병합: 충돌 24(+자동 2) → 누른 Take 18 = 줄 고른 로그 18 → 병합 커밋
ae20f56(부모 첫째 = 다시 쓴3145f3f) · 줄끝 · BOM 바뀐 파일 0 · 충돌 표식 0 · class 0 · 워킹트리 Clean · 두 탭 같은 커밋.
4. 다섯 길 + pull (e11-e1-merge.ps1 -Way merge|pull|rebase|pick|revert — 10차 E-1 과 같은 순서)
| 길 | 누른 Take = 로그 | 마지막 Save 뒤 기준 | 커밋 | 줄끝 · BOM 바뀐 파일 | 충돌 표식 · class | 두 탭(10차 B-1) | 걸린 시간 |
|---|---|---|---|---|---|---|---|
| 병합 | 18 = 18 | HEAD · N=3 = git | cac5366 부모 둘 · 본문 해결 26개 |
0/33 | 0 · 0 | 같음 | 303초 |
| pull | 18 = 18 | 같음 | 1b32e2f "Merge remote-tracking branch 'origin/feature/mine' …" |
0/33 | 0 · 0 | 같음 | 303초 |
| rebase | 18 = 18 | 같음 | b108182 부모 하나 · "내 쪽 작업" |
0/31 | 0 · 0 | 같음 | 302초 |
| cherry-pick | 18 = 18 | 같음 | 631234e "상대 쪽 작업" · 빈 cherry-pick 은 [커밋] 꺼짐 → [작업 취소] (8차 B-2) |
0/33 | 0 · 0 | 같음 | 350초 |
| revert | 6 = 6 | HEAD · N=6 = git | d59bc42 Revert "내 쪽 작업" · REVERT_HEAD 안 남음 |
0/36 | 0 · 0 | 같음 | 199초 |
- 10차 E-1 과 숫자가 같다. 새로 걸린 것 없음.
시험 도구 쪽에서 고친 것 (제품 아님)
-
창을 앞으로 부르는 도우미가 최대화를 풀었다 —
ShowWindow(SW_RESTORE)를 늘 불러, 첫 누름 때 창이 복원 크기로 줄고 옛 자리를 눌러 로그 칸에 떨어졌다(누르기 전 · 뒤 사진으로 확인). 경우 1 이 처음에 "칸이 빔" 으로 나온 까닭이다. 최소화돼 있을 때만 되살리게 고쳤다(e11-c1lib.ps1·e11-e1-a.ps1). 앞선 차수의 결과는 누른 뒤 자리를 다시 읽어 눌렀으므로 그대로 믿을 수 있다. -
C-1 시험 저장소의 "다른 브랜치의 더 새 커밋" 날짜가 09-18 이라 오늘(09-22)에는 목록 맨 위가 HEAD 가 되어 경우 1 이 성립하지 않았다 → 12-31 로.
-
rebase · cherry-pick · revert 뒤
d1-verify.ps1이 부모가 하나인 커밋에도git merge-base를 불러 사용법 글을 찍는다 — 판정에는 영향 없음(10차와 같음). -
이 PC 의 Caps Lock 이 켜져 있어 영문 입력이 대소문자 뒤집혀 들어갔다(경우 5 의 메시지). 키보드 상태라 바꾸지 않았다 — 판정에는 영향 없음.
-
하네스 22벌 1,247건 · 플랫폼 24건 그대로 · 빌드 경고 0 · 오류 0 · 설정 파일 되돌림 해시 매번 같음. 제품 코드 변경 없음.
E-2. 웹 문서 · 기획안을 11차에 맞게 (2026-09-22, 완료)
MergeHub 문서 (doc/web/index.html, 아티팩트 "MergeHub 문서" 버전 11 → 13)
- 올리기 전에 발행본(버전 11)을 받아 로컬과 견줌 — 09-17 에 올린 그대로였고(다른 사람 손 없음), 그 뒤 로컬에서만 바뀐 것은 11차 F-12 · B-1 · B-2 문장뿐.
- 고친 것:
- 개요 — 09-22 기준 · 22벌 1,247건 · 11차 · 커밋 129 · 지시서 11차.
- 매뉴얼 — Git 탭 표에 우클릭 [메시지 바꾸기...] 와 아래 두 절 연결, "커밋 메시지 고치기"(두 길을 한 표로 — 고치는 커밋 · 메시지 넣기 · 함께 들어가는 것 · 이미 올린 커밋 · 남는 것 · 꺼지는 때, 되돌리는 길), "변경분 추출"(새 폴더 · 옆 안내 파일 · 먼저 보고 쓰기 · 병합 커밋 · 거꾸로 범위), 목차 둘, 알아 둘 한계 셋(메시지 칸 한 줄 · 올렸는지는 마지막 Fetch 기준 · D 없는 PC 는 계정마다 설정). 실행 위치(B-1) · 설정 위치(B-2) · C# 스타일 기본 AURORA(F-12)는 먼저 적어 둔 것이 함께 올라감.
- 남은 일 — 11차 표(완료 · 대기 · 진행).
- 지금까지 만든 것 — 09-22 11차 기록 · 커밋 129 · 1,247건 · 하네스 막대 11차(폭을 새 최댓값으로 다시 잼) · 기능 목록 Git 한 줄 · 배포 한 줄.
- 기획안 v2 — 커밋 메시지 수정 완료, 변경분 추출 설명, 3단계에 11차, 4단계 진행(베타 준비).
- WinMerge 쪽 숫자 1,247건.
- 대조: 문서의 단추 이름 91개를 소스(MergeHub · 플랫폼)에서 찾음 — "맞추지 않음"(09-18 F-12 때 적은 말)이 실제 콤보 글자 "C# 스타일 끔" 과 달라 문서 두 곳 · 이 기록 한 곳을 고침. 남은 하나(
비교 규칙 펴기의 공백 두 칸)는 화면에 보이는 글자가 같다. 태그 짝 모두 맞음. - 공유 링크를 받은 사람에게는 고정된 옛 버전이 보이도록 되어 있다 — 새 버전을 보이려면 페이지 Share 메뉴에서 사용자가 바꾼다.
기획안 v1.2 (잠금 아티팩트 "UbiSam MergeTool 개발 기획안" 버전 17)
- 발행본을 받아 로컬 잠금 파일(09-17 17:06)과 견줌 — 암호문 · salt · IV 가 같음. 그러므로 고칠 원문은 09-17 원문(
plan/mergetool.html). - 원문에서 고친 것: 3.2 Git 작업 UI화의 커밋 메시지 수정 → 완료("마지막 커밋은 [커밋 수정], 앞 커밋은 트리에서 우클릭 → [메시지 바꾸기]"), 변경분 파일 추출 설명(새 폴더 · 지울 파일 안내, ZIP 이 없어 "일부" 그대로), 일정 요약(09-22 기준 · 1,247건 · 4단계 베타 준비 중), 3단계 "Git 작업 버튼" 한 줄, 4단계 상태 "대기" → "준비 중", 4단계 베타 줄, 개정일 09-22.
- A4 쪽 높이: 고치기 전 · 뒤 원문을 헤드리스 Edge 로 재니 8쪽 모두 1123px · 넘침 없음으로 같다. 기능 목록 쪽 그림으로 한 줄씩인 것 확인.
- 잠금은 사용자가 했다(
lock-plan.js, 비밀번호는 화면에 안 보이게 받아 어디에도 남기지 않음 · 비교할 원본은 09-17 원문). 첫 "잠갔어" 때는 잠금 파일이 09-17 것 그대로여서 올리지 않고 멈췄다(PowerShell 문법을 CMD 에서 돌린 것으로 보임). 두 번째에 새 salt · IV 의 잠금 파일(13:12)이 생겨 올렸고, 발행본의 암호문이 그 파일과 같음을 되읽어 확인했다. 스크립트 출력은 다른 창이라 직접 보지 못했다.
F-1. 칸 이름을 맞추고 칸마다 어느 파일인지 · 머지 주석에 어디서 가져왔는지 (2026-09-22, 완료)
사용자 결정(2026-09-22): 칸 이름은 표준 용어 + 영문 쪽 이름(LOCAL(Mine) · REMOTE(Theirs) — 4차 · 6차의 "표준 용어 그대로" 를 이어 가고 로그의 Mine/Theirs 와 맞춤), 주석 출처는 쪽 이름 + 브랜치/해시, 설명이 있으면 출처 먼저, 설명 뒤.
고치기 전 — 화면에서 (f1-probe.ps1)
| 길 | 칸 머리에 보인 것 |
|---|---|
| 병합 네 칸 | BASE (merge base) Weld/Unit1.cs · LOCAL (Mine) feature/mine · MERGED feature/mine · REMOTE (Theirs) REMOTE · feature/theirs — 파일 이름은 BASE 칸에만, REMOTE 칸은 제목의 말을 되풀이 |
| 두 칸 | BASE 9b064cc · Weld/Unit1.cs · LOCAL feature/mine — 저장하는 칸에 파일이 없음 |
git mergetool · --merge (코드로) |
Mine 칸이 MERGED 칸과 같은 값(저장할 파일 이름)을 써서, 실제로 읽은 --local 임시 파일과 다른 이름이 보였다 |
머지 주석은 // [김승준] 2026-09-22 뿐이고 Take Mine 은 주석을 남기지 않았다(로그에만 "정함").
고친 것
- 칸 머리 — 칸마다 한 줄 "어느 쪽 · 어느 파일"(
PaneHeaders). 네 칸:feature/mine · Weld/Unit1.cs·(merge base) Weld/Unit1.cs·Weld/Unit1.cs (저장할 파일)·feature/theirs · Weld/Unit1.cs. 두 칸:3a12077 · Weld/Unit1.cs·feature/mine · Weld/Unit1.cs (저장할 파일). mergetool ·--merge: 네 칸이 제 임시 파일 이름(Mine 칸은 새MineHeader). rebase 는올릴 자리 …, cherry-pick · revert 는가져오는 커밋 …·되돌리는 커밋 …에 파일이 붙는다. - 제목
LOCAL (Mine)·REMOTE (Theirs)→LOCAL(Mine)·REMOTE(Theirs). 네 칸 머리 글씨를 모두 BASE 와 같은 모양(읽으라고 쓰는 글씨)으로. - 한 줄 · 가운데 줄이기 — WPF 끝 자르기는 파일 이름부터 잘라서, 폭에 맞게 가운데를
…로 줄이는MiddleTrim(앞 조각 굵게는 그대로). 전체는 툴팁. - 머지 주석 출처 —
[사람] 날짜 출처 설명(MergeNote.Build에 출처). 출처는 로그와 같은 말(MergeNames.TheirsSource·MineSource·BaseSource): 네 칸Theirs(feature/theirs)·Mine(feature/mine), rebase · cherry-pick · revertTheirs(커밋 42e68b2), 브랜치 3-WayREMOTE(develop), 두 칸BASE(3a12077)(Git 아니면 왼쪽 파일 이름). - 로그도 같은 말로 — 두 칸
9행 BASE 반영→9행 BASE(af3925e) 반영, 브랜치 3-Way7행 develop 반영→7행 REMOTE(develop) 반영. 네 칸 로그는 원래 같은 말이라 그대로. - Take Mine 도 주석을 남긴다(지시서 판정 기준) — 병합의 두 쪽에서 내 것으로 정하면
Mine(…)주석 한 줄. 같은 줄을 또 눌러도 쌓이지 않고(처음 한 번), 되돌리기가 주석 줄까지 뺀다. 브랜치 3-Way 의 "내 원본으로 되돌림" 은 되돌리기라 주석 없음(그대로). - 무시 조건 — 알아보는 규칙(
[사람] 날짜뒤는 따지지 않음)이 원래 출처를 받아들이는 모양이라NoteBody·LooksLikeNote·TailStart·CompareRules·FolderComparer·NoteConflict·NoteRows는 코드를 바꾸지 않았다. 대신 옛 모양 · 새 모양 · 출처만 다른 모양을 하네스로 굳힘.
확인한 것
- 하네스: NoteTest(출처 자리 · 옛 모양 바이트 같음 · XAML 닫는 기호 · 줄 끝 조각 · 무시 키 · 출처만 다른 충돌 자동 해결 두 주석 다 남김 · 코드가 다르면 안 풂) · RulesTest(무시 · 규칙 끄면 차이) · FolderTest(출처만 다름 · 옛↔새 → 같음(머지 주석만 다름), 규칙 끄면 다름(코드는 같음)) · MergeSaveTest(출처 = 로그의 말 · 칸 머리 · 가운데 줄이기). 22벌 1,312건 통과(1,260 → +52) · 빌드 경고 0 · 오류 0.
- 화면(
f1-verify.ps1·f1-trim.ps1, UIA 만 — 마우스 안 씀):
| 길 | 칸 머리 | 누른 것 → 로그 | 파일에 남은 주석 |
|---|---|---|---|
| 병합 네 칸 | feature/mine · Weld/Unit1.cs · (merge base) Weld/Unit1.cs · Weld/Unit1.cs (저장할 파일) · feature/theirs · Weld/Unit1.cs |
101행 Theirs(feature/theirs) 반영 · 802행 Mine(feature/mine) 으로 정함 (Take Mine 한 번 더 → 단추 꺼짐) |
// [김승준] 2026-09-22 Theirs(feature/theirs) · … Mine(feature/mine) — 범례 무시 2 |
| 두 칸 | af3925e · Weld/Unit1.cs · feature/mine · Weld/Unit1.cs (저장할 파일) |
9행 BASE(af3925e) 반영 |
화면의 주석 줄 // [김승준] 2026-09-22 BASE(af3925e)(두 칸은 Save & Commit 뿐이라 커밋하지 않고 화면에서 읽음) |
--merge |
Unit1_LOCAL_4321.cs · Unit1_BASE_4321.cs · Unit1.cs (저장할 파일) · Unit1_REMOTE_4321.cs |
Theirs(Unit1_REMOTE_4321.cs) 반영 · Mine(Unit1_LOCAL_4321.cs) 으로 정함 |
같은 말 두 줄 |
git mergetool (git -c 로만 도구 설정 — 설정 파일에 안 남음 확인) |
Unit1_LOCAL_290.cs · Unit1_BASE_290.cs · Unit1.cs (저장할 파일) · Unit1_REMOTE_290.cs |
Theirs(Unit1_REMOTE_290.cs) 반영 |
같은 말 |
- 칸 머리는 모두 한 줄(높이 21). 117자 파일 이름으로
--merge:WeldSequenceController_Laser…ipeParameterValidation_Unit1_LOCAL_4321.cs처럼 가운데가 줄고 끝(쪽 · 파일 이름)이 남음, 툴팁에 전체. 창 폭을 UIA 로 줄이는 것은 이 창에서 먹지 않아 긴 이름으로 대신 봄. - 회귀: 11차 E-1 병합 길(
e11-e1-merge.ps1 -Way merge, 마우스 확인 B-1 · 스크린숏만 끔) — 누른 Take 18 = 로그 18, 병합 커밋 본문 26개, 줄끝 · BOM 바뀐 파일 0 · 충돌 표식 0 · class 검사 0, 옛 모양 주석만 다른 2건 자동 해결 그대로. 결과 파일의 Take Mine 줄 위에Mine(feature/mine)주석이 새로 들어간다(이번 변경).- 첫 번째 회차는 1) 파일 여러 개 골라 Accept Theirs 가 한 개만 골라져(24 → 23, 20초) 줄 단위로 처음 가 보는 파일들에서 Take 가 꺼져 있었다. 그 파일들을 새로 열어 보면 Take 둘 다 켜짐(
f1-take-probe.ps1), 두 번째 회차는 1) 이 24 → 9(1초)로 예전과 같아 끝까지 — 시험 도구의 여러 개 고르기가 한 번 빗나간 것으로 본다.
- 첫 번째 회차는 1) 파일 여러 개 골라 Accept Theirs 가 한 개만 골라져(24 → 23, 20초) 줄 단위로 처음 가 보는 파일들에서 Take 가 꺼져 있었다. 그 파일들을 새로 열어 보면 Take 둘 다 켜짐(
알아 둘 것
- Take Mine 주석이 새로 들어가므로 같은 순서로 풀어도 결과 파일이 전보다 주석 줄 수만큼 길다(무시 규칙이 켜져 있으면 차이로 세지 않음). 코드 줄 · 줄끝 · BOM 은 그대로.
- 파일 단위 Accept(충돌 탭)는 여전히 소스에 주석을 남기지 않는다 — 병합 커밋 본문(8차 F-1)이 그 기록이다.
F-2. 메서드 단위로 골라 반영 · 덩어리 반영의 주석 한 줄 (2026-09-22, 완료)
사용자 결정(2026-09-22): 언어는 C# + C/C++, "메서드" 는 클래스 멤버 전부(메서드 · 생성자 · 소멸자 · 속성 · 인덱서 · 이벤트 · 연산자 · 필드 · enum — 로컬 함수 · 람다 안이면 감싸는 멤버 통째), 덩어리 반영의 주석도 첫 줄 위 한 줄로.
고치기 전 — 화면에서 (f2-probe.ps1)
- 지시서에는 "덩어리를 반영하면 머지 주석은 덩어리 첫 줄 위에 한 줄" 이라고 적었지만 사실과 달랐다 — 이어진 두 줄 차이에 [이 덩어리 반영] → 주석이 줄마다 하나씩 두 줄.
AcceptBlock이 줄마다Apply를 불러 줄마다 주석 · 로그 · 되돌리기 한 건씩이었다. - 메서드 단위 반영은 없었다.
만든 것
MemberRanges(새 서비스, Roslyn 없음) — 파일 전체를 훑어 주석 · 문자열을 가리고(C# 축자 · 보간 · raw""", C++ rawR"x(...)x"· 숫자 구분자1'000· 문자'{'), 중괄호 짝으로 멤버 범위(시작 · 이름 줄 · 끝)를 잡는다.#if는 갈래(#elif · #else)마다#if자리의 상태에서 다시 읽고#endif뒤에는 첫 갈래 상태로 잇는다 — 여는 줄만 갈린 메서드도 짝이 맞고, 갈래마다 따로 있는 메서드는 따로 잡힌다.- 멤버 몸통이 아닌 중괄호: 필드 초기화(
= new X { }) · 람다 · switch 식(=>뒤) · 속성 초기화({ get; set; } = 1;) · C++ 생성자 초기화 목록(items_{1, 2}) · 특성 안. - 시작은 바로 위 설명 주석(
///·//) · 특성 · 감싸는#if까지. 머지 주석에서 멈춘다(이력이라 반영으로 지우면 안 됨). 클래스 · 네임스페이스 선언 줄은 어느 멤버에도 들지 않는다. 짝이 틀어져 겹치면 뒤의 것을 버린다(틀린 범위 대신 없음).
- [이 메서드 반영](덩어리 반영 아래) — 캐럿이 놓인 멤버를 반영해 올 쪽(두 칸 BASE · 네 칸 REMOTE)에서 찾아, 그 범위의 행(사이의 내 쪽에만 있는 줄 포함)을 덩어리 반영과 같은 규칙으로 반영. 네 칸은 Take Theirs 와 같아 저쪽이 바꾼 줄 · 충돌 줄만, 내 쪽만 고친 줄은 그대로.
- 단추 아래 한 줄: 잡으면
Target · BASE 7~17행 · 바뀐 줄 4, 못 잡으면 까닭(캐럿이 BASE 쪽 메서드 안에 있지 않습니다·C# · C/C++ 파일에서만·… 안에 가져올 차이가 없습니다) — 단추는 꺼지고 툴팁도 같은 말.
- 단추 아래 한 줄: 잡으면
- 묶음 반영(
ApplyGroup) — 덩어리 · 메서드 모두: 머지 주석은 한 줄(메서드는 이름 줄 위, 덩어리는 첫 줄 위, 출처는 F-1 과 같은 말), 로그도 한 줄(7~11행 메서드 Target BASE(left.cs) 반영 (4줄)·10~11행 덩어리 BASE(left.cs) 반영 (3줄)), Undo · Redo 한 번에 통째로(편집에 묶음 번호). 주석만 든 편집(NoteOnly)은 "직접 수정" · "편집 N건" 에 세지 않는다. 머지 주석 줄은 건드리지 않는다.
확인한 것
- 하네스 MemberTest(새, 83건): C# 시험 파일 29개 멤버 · C++ 13개 멤버의 시작 · 이름 줄 · 끝이 표시 주석과 모두 같다(한 줄 메서드 · 중첩 중괄호 · 문자열 · 축자 · 보간 · raw 안 중괄호 · 주석 안 중괄호 ·
#if로 여는 줄이 갈린 메서드 · 갈래마다 다른 메서드 · 로컬 함수 · 람다 필드 · switch 식 · 속성 초기화 · 이벤트 · 인덱서 · 연산자 · 머지 주석 위 멤버 · 설명 주석 · 중첩 클래스 · C++ 템플릿 · 초기화 목록 ·operator=· raw 문자열 · 숫자 구분자 ·extern "C"·enum class·#ifdef), 기대하지 않은 범위 없음 · 겹침 없음, 이름, 캐럿 행 → 멤버 · 멤버 → 화면 행, 짝이 틀어진 파일에서 멈추지 않음. 23벌 1,395건(1,312 → +83) · 플랫폼 24건 · 빌드 경고 0 · 오류 0. - 화면(
f2-verify.ps1,--diff·--merge로 C# 짝, BOM · CRLF):
| 길 | 결과 |
|---|---|
| 두 칸 · 주석 켬 | 연 직후 단추 꺼짐 + 캐럿이 BASE 쪽 메서드 안에 있지 않습니다…, [다음 차이] 뒤 Target · BASE 7~17행 · 바뀐 줄 4 · 켜짐. 반영 → 머지 주석 1줄(설명 주석과 선언 줄 사이, 메서드 이름 위) · 범례 반영 4 · 직접 수정 0 · 편집 4건. Undo 한 번 → 주석 0 · 남은 차이 5줄(처음과 같음), Redo 한 번 → 다시. 저장한 파일: Target 은 BASE 그대로, 다른 메서드 Other 는 내 쪽 그대로 |
| 두 칸 · 주석 끔 | 메서드 반영 저장본 = 같은 네 줄을 하나씩 골라 Accept 한 저장본 = 기대(Target = BASE, 나머지 = 내 쪽, BOM · CRLF 그대로) — SHA-256 같음 |
| 두 칸 · 덩어리 | [이 덩어리 반영] 세 줄 → 머지 주석 1줄, Undo 한 번에 처음으로 |
세 칸 --merge |
Target · REMOTE 7~18행 · 바뀐 줄 2 → 주석 Theirs(Station_REMOTE_1.cs) 한 줄, 저장본 Target = REMOTE(limit = 150 · Trace(power);), 내가 고친 Other(return 2;)는 그대로 |
- 회귀: 11차 E-1 병합 길(마우스 확인 B-1 · 스크린숏만 끔) — 누른 Take 18 = 로그 18, 병합 커밋 본문 26개, 줄끝 · BOM 바뀐 파일 0 · 충돌 표식 0 · class 검사 0.
- E-1 의 1) "15개 골라 Accept Theirs" 가 가끔 24 → 23 에서 멈췄다(F-1 · F-2 회차에 모두 12번 중 3번). 따로 재 보니(
f2-multisel.ps1) 첫 Select 뒤 AddToSelection 이 하나도 안 먹은 것 — 충돌 목록에서 고를 때 앱은 단추 상태만 새로 고치고 F-1 · F-2 가 고친 파일 비교 쪽은 타지 않는다. F-1 전 빌드(2f36f1b, 임시 폴더에 꺼내 빌드) 5번 · 지금 빌드 5번 모두 15개 골라짐. 병합 직후 목록이 한 번 더 그려지며 시험 도구가 잡아 둔 항목이 낡은 것으로 보고, 시험 도구가 고른 수를 세어 모자라면 목록을 다시 잡아 다시 고르게 고쳤다(d7lib.ps1, 제품 아님).
- E-1 의 1) "15개 골라 Accept Theirs" 가 가끔 24 → 23 에서 멈췄다(F-1 · F-2 회차에 모두 12번 중 3번). 따로 재 보니(
남은 것 · 알아 둘 것
- [전체 반영](두 칸) · [자동 병합](네 칸)은 지금도 줄마다 주석이 붙는다 — 이번에 정한 것은 덩어리 · 메서드. 같은 규칙(한 줄)으로 맞출지는 정하지 않았다.
- 범위는 반영해 올 쪽(BASE · REMOTE) 글로 잡는다. 그쪽에 없는 메서드(내 쪽에서만 새로 만든 메서드)는 잡히지 않아 단추가 꺼진다.
- XAML · 그 밖의 언어는 단추가 꺼지고 까닭을 말한다(사용자 결정: C# + C/C++).
F-3. 탐색기에서 폴더 두 개를 [보내기] 로 바로 비교 · 설치 없이 되는지 (2026-09-22, 완료)
어떻게 쟀나 — 사용자의 보내기 메뉴는 건드리지 않고
탐색기 [보내기] 는 SendTo 폴더의 바로가기에 고른 항목들을 떨어뜨리는 것(바로가기의 IDropTarget::Drop)이다. 같은 셸 길을 부르는 도구(SendToSim — 고른 항목의 데이터 개체를 임시 폴더의 바로가기에 Drop)와 받은 명령줄을 적기만 하는 ArgsEcho 로 쟀다. 바로가기는 [탐색기 보내기 등록] 과 같은 모양(대상 · 작업 폴더).
| 경우 | 탐색기가 넘긴 것 | 고치기 전 MergeHub |
|---|---|---|
| 파일 2개 | 프로세스 1개에 인자 2개 | 파일 비교로 열림 |
| 폴더 2개 | 프로세스 1개에 인자 2개 | 창 하나에 왼쪽 · 오른쪽 폴더, 폴더 비교까지(전체 1개 · 같음 1) |
| 폴더 1개 | 인자 1개 | 폴더 비교, 왼쪽만 채움(오른쪽은 사용자가 고름) |
| 3개 이상 | 프로세스 1개에 인자 3개 | 앞의 둘만 비교, 셋째는 말없이 버림 |
| 경로에 공백 | 그대로(left side) |
폴더 비교까지 |
| 한글 | 그대로(왼쪽 폴더) |
폴더 비교까지 |
| 260자 넘는 경로 | 8.3 짧은 이름(123자, ME0359~1\긴폴더~1\…\RIGHTL~1) |
아무것도 안 열림 — 로그엔 폴더인데 "파일 비교 요청" |
- 탐색기는 여러 개를 한 번, 프로세스 하나로 넘긴다 — "두 번 뜬 프로세스를 하나로 모으는 길" 은 필요 없다.
- 긴 경로: net48 에서 짧은 이름을
Path.GetFullPath가 긴 이름(277자)으로 펼친 뒤 못 찾는다(Directory.Exists거짓,\\?\를 붙이면 "잘못된 문자" —LongPathProbe). 열려면 플랫폼 실행 파일 설정(긴 경로 스위치)을 바꿔야 한다. - MergeHub 가 이미 떠 있을 때 보내면 창이 하나 더 뜬다(프로세스 2개).
정한 것 (2026-09-22 사용자)
- 긴 경로: 열 수 없다고 알린다(지원은 플랫폼 설정을 바꿔야 해서 하지 않음).
- 3개 이상: 앞의 둘 + 알림.
- 배포 묶음을 옮겨 바로가기가 옛 자리를 가리키면: 켜질 때 저절로 고친다.
- 이미 떠 있을 때: 지금처럼 새 창(하나로 모으려면 플랫폼에 한 번만 실행 · 창 사이 전달이 필요 — 남은 것).
고친 것
StartupArgs— 셋째부터는Extra, 앞의 둘 가운데 파일도 폴더도 아닌 것은Missing(있으면 아무것도 열지 않는다). 알림 한 줄Notice:3개를 골랐습니다 - 앞의 둘만 비교하고 1개(Third)는 두었습니다·LeftLong 외 1개 - 경로가 277자라 열 수 없습니다(260자가 넘는 경로는 아직 열지 못합니다)· 그 밖은… - 찾을 수 없습니다. 이름표 붙은 경로(git difftool의 지워진 쪽)는 따지지 않는다.GitWorkspace— 켤 때 넘어온 것 · 끌어다 놓은 것 모두 같은 말로 로그 한 줄 + 경고 알림. 켤 때는 사용자 이름 창(모달)이 먼저 떠서 그 뒤로 알림이 지나가 버렸다 — 본 창이 활성이 된 뒤에 띄운다(이름 창을 닫고 0.4초 뒤에 보임).ShellIntegration.RepairIfMoved— 등록해 둔 사람만, 바로가기 대상이 지금 실행 파일과 다르면 바로가기 파일만 다시 쓰고 로그 한 줄(보내기 바로가기가 옛 자리(…)를 가리켜 지금 실행 파일로 고쳤습니다). 레지스트리는 손대지 않는다. 이미 맞으면 파일을 건드리지 않는다.
설치 파일 없이 되는가
된다. 보내기는 %APPDATA%\Microsoft\Windows\SendTo 에 바로가기 하나를 두는 것이 전부다(관리자 권한 · HKLM · 설치 관리자 없음). 배포 묶음을 옮기면 켤 때 바로가기가 따라온다. 레지스트리에 닿는 것은 [탐색기 보내기 등록] 을 누를 때 예전 판이 HKCU 에 남긴 항목이 있으면 지우는 것 하나뿐이다(새로 쓰지 않음).
확인한 것
- 하네스 ArgsTest +16(52건): 3개 → 앞의 둘 · 남은 것 · 알림 글, 2개 · 1개 → 알림 없음, 없는 경로 → 안 열고 그 경로 · "찾을 수 없습니다", 260자 넘는 경로 → 안 열고 "260자", 이름표 붙은 difftool 경로는 안 따짐, 빈 인자, 바로가기 대상 판정(같은 곳 · 대소문자 · 빈 대상 · 지금 실행 파일 모름). 23벌 1,411건 · 빌드 경고 0 · 오류 0.
- 화면(
f3-sendto.ps1·f3-e2e.ps1·f3-e2e2.ps1·f3-toast.ps1·f3-second.ps1, 바로가기 대상을 실제 MergeHub Debug 로):- 폴더 2개 · 공백 · 한글 → 창 하나에서 폴더 비교까지(로그
폴더 비교: 왼쪽 ↔ 오른쪽 · 전체 1개 · 같음 1). 파일 2개 → 파일 비교. - 3개 → 폴더 비교(앞의 둘) + 로그 · 알림
3개를 골랐습니다 - …1개(Third)는 두었습니다, 알림은 이름 창을 닫은 직후. - 긴 경로 → 아무것도 열지 않고 로그 · 알림
LeftLong 외 1개 - 경로가 277자라 열 수 없습니다…. - 바로가기 저절로 고침: 사용자의 실제 바로가기를 바이트 그대로 떠 두고 대상을
D:\옛자리\bin\…로 바꿈 → 켜자 지금 실행 파일 · 작업 폴더로 고쳐지고 로그 한 줄, 한 번 더 켜도 파일 그대로 → 원래 파일 바이트 그대로 되돌림(원래 대상이 이미 Debug 실행 파일이라 평소 시험으로는 바뀌지 않는다).
- 폴더 2개 · 공백 · 한글 → 창 하나에서 폴더 비교까지(로그
- 시험 재료(
%TEMP%\mergehub-f3, 긴 경로 포함)는 지웠다.
사용자가 실제 탐색기에서 찾은 것 — 왼쪽 칸이 기본 저장소로 덮임 (2026-09-22, 고침)
사용자: "폴더 2개를 선택해 보내기에서 머지허브를 켰는데 한개의 폴더만 읽혀 기능이 안된거같아".
- 받은 인자를 파일 로그에 남기게 한 뒤(
켤 때 받은 인자 N개: …) 다시 해 받아, 떠 있는 프로세스의 명령줄 · 파일 로그 · 폴더 비교 탭 칸을 읽기만 했다(업무 폴더의 파일은 열지 않음). 탐색기는 두 폴더를 모두 넘겼고StartupArgs도 왼쪽 · 오른쪽을 맞게 잡았다. 그런데 왼쪽 칸이 설정의 기본 저장소C:/Users/Ubisam/AppData/Local/Temp/plain-compare였고 결과가 "왼쪽만" 투성이였다. - 원인:
FolderViewModel생성자가 넘어온 요청을 먼저 받아 비교를 시작한 뒤에 "열어 둔 저장소를 왼쪽 기본값으로" 가 왼쪽을 덮어썼다. 비교는 비동기라 덮인 왼쪽을 읽을 수 있다. 위 시험(f3-e2e.ps1)에서는 로그가 맞게 나와 지나쳤다 — 칸 값을 읽는 필터가 기대 경로만 골라 덮인 왼쪽 칸이 안 보였다(시험이 모자랐다). - 고침: 기본값을 먼저 두고 요청을 나중에 받는다 — 요청이 늘 이긴다. 폴더 하나만 보낸 경우도 같이 고쳐진다.
- 확인(
f3-fix.ps1, 기본 저장소 설정 그대로): 폴더 2개 → 칸…\Left·…\Right, 요약전체 3개 · 다름 1 · 왼쪽만 1 · 같음 1(재료와 같음). 폴더 1개 → 왼쪽 칸 = 보낸 폴더, 오른쪽 빈 칸 + "오른쪽 폴더를 고르고 비교를 누르세요". - 켤 때 받은 인자를 파일 로그(
D:\UbisamConfig\Log)에 남기는 한 줄은 그대로 둔다 — 다음에 같은 말이 나오면 무엇이 넘어왔는지 바로 안다. 커밋c35280a. - 사용자가 같은 두 폴더로 다시 보내기 → "잘되네"(2026-09-22).
남은 것
- 이미 떠 있는 창으로 보내기(한 번만 실행 · 창 사이 전달) — 플랫폼 일이라 이번 범위 밖.
- 260자 넘는 경로를 여는 것 — 플랫폼 실행 파일의 긴 경로 설정과 전체 시험이 필요.
- 여러 개를 골랐을 때 어느 것이 왼쪽인지는 탐색기가 넘기는 순서를 따른다(도구는 고른 순서대로 넘겼다). 실제 탐색기 창에서 누른 순서와의 관계는 재지 않았다.
F-4. 툴박스(ACTIONS) 감추기 + 아래 탭 줄 접기 (2026-09-22, 완료 — 플랫폼 배포함)
사용자: F-4 에 더해 "밑에 탭화면도 접을 수 있게 해줘 머지 메인 화면이 더 많이 나와야해".
먼저 본 것
- 파일 비교 화면(HomeView) 안에는 아래쪽 탭이 없다. 화면에서 아래에 있는 것은 플랫폼 창의 탭 줄(
NavList— 파일 비교 · Git · 폴더 탭과 화면 잠금 · 바탕화면 · 종료 동작 항목), 1440p 150% 에서 높이 95px. 플랫폼에는 탭 줄 위치(아래 · 왼쪽 · 오른쪽) 설정은 있었지만 접는 기능은 없었다. - ACTIONS 칸은 "접기" 가 있어도 폭은 그대로였다(4차 C-5).
정한 것 (2026-09-22 사용자)
탭 줄은 얇은 띠 + 펴기 단추 + 키, 아래 탭 줄만(위 로고 · 시계 줄은 창 손잡이라 둠), 플랫폼에 넣되 모든 소비 프로그램이 쓰게 · 기본은 펼침. ACTIONS 는 단추 + F9.
만든 것
- 플랫폼: 탭 줄 끝 동작 항목 [탭 접기](새 아이콘), 접으면 16 DIP 띠
탭 펴기 · F11, F11 로 접고 폄(잠금 중 제외), 상태는UiSettingsService.NavCollapsed— 그 항목만 파일에 고쳐 씀(UiSettingsFile). 왼쪽 · 오른쪽 탭 줄이면 세로 띠. 전체 단추 스타일의MinHeight 38때문에 띠가 처음엔 57px 로 두꺼워 최소 크기를 0 으로. - MergeHub: 위 상태 바에 [ACTIONS 감추기 ▶ (F9)] / [◀ ACTIONS 보이기 (F9)], 단축키 표에 F9(도움말에도 나옴). 감추면 ACTIONS 칸과 앞 구분선 폭을 0 으로 해 코드 칸이 넓어지고, 펴면 끌어 둔 폭 그대로 돌아온다(폭을 Style 로 쥐지 않는 까닭 — 구분선을 끌면 로컬 값이 박힌다). 상태는 설정
ActionsHidden(설정 화면에는 안 나옴).
확인한 것
- 하네스: PlatformCfgTest +7(31건 — 옛 파일 · 망가진 글은 펼침, 접기 항목만 바뀌고 다른 값 · 모르는 항목 그대로), ShortcutTest +3(F9 = ACTIONS, F11 은 머지툴 표에 없음). MergeHub 23벌 1,414건 · 빌드 경고 0 · 오류 0(플랫폼 Debug · MergeHub Debug).
- 화면(
f4-verify.ps1— MergeHub Debug 를 임시 폴더에 복사하고 플랫폼 Core · Shell 만 고친 Debug 로 바꿔 띄움, 배포 폴더 · 사용자 Debug 폴더 안 건드림, 화면 설정 파일은 바이트 그대로 되돌림):
| 한 것 | 결과(1440p · 150%) |
|---|---|
| [ACTIONS 감추기] | 코드 칸 두 칸이 각각 +163~164px(1083 → 1247 · 985 → 1148), 단추 글 ◀ ACTIONS 보이기 (F9) |
| 감춘 채 Alt+↓ · Alt+→ · Ctrl+S | 차이로 가서 반영하고 저장됨(파일에 반영 줄 · 주석) |
| F9 | 원래 폭으로 |
| [탭 접기] · F11 | 탭 줄 95px → 띠 24px, 코드 칸 +71px(1198 → 1269, 약 2줄). 설정 파일에 "NavCollapsed": true 한 항목만 더해지고 나머지 그대로 |
| 띠 [탭 펴기] · F11 다시 | 원래대로 |
| 둘 다 감추고 다시 켬 | 두 상태 모두 남음 |
| 탭 줄 왼쪽 | 세로 띠 24px 로 접히고 폄. 왼쪽 탭 줄에서 코드 칸 자리는 고친 플랫폼 · 지금 플랫폼이 같다 |
남은 것
플랫폼 배포— 사용자 "배포해줘" 뒤publish-platform.ps1(16:22, 경고 0 · 오류 0, 48개 가운데 Core · Shell · README 셋 바뀜). MergeHub Debug 를 다시 빌드해 두 파일 해시가 배포본과 같음, 배포본으로 [탭 접기] → 24px 띠 → 띠로 펴기 확인(f4-deployed.ps1, 화면 설정 · MergeHub 설정 바이트 그대로 되돌림).- F-6(넓게 보기)에서 몇 줄이 늘었는지 1920 × 1080 기준으로 다시 잰다.
F-5. 코드 글자 크기 조절 (2026-09-22, 완료)
사용자: "모니터 해상도와 관계없이 모든 모니터에 적용될 수 있도록 하면 좋겠는데".
먼저 본 것
- 코드 칸은
Consolas 12· 줄 높이 20 으로 박혀 있었다 — 행 템플릿 넷 · 편집기 ·CodeLineHeight리소스(StaticResource) ·MergeLine.MinimumRowHeight = 20상수. 여백도 번호 46(LOCAL 은 표식 6 + 번호 40) + 단추 20 = 66, 단추 높이 14 · 글자 9 로 박혀 있어 글자만 키우면 번호가 잘리고, 줄이면 단추가 줄보다 커지고 행이 20 아래로 줄지 않는다. - 플랫폼은 PerMonitorV2 라 WPF 단위(1/96 인치)의 크기는 창이 있는 모니터의 Windows 배율에 맞춰 다시 그려진다.
정한 것 (2026-09-22 사용자)
한 값을 모든 모니터에(모니터 배율은 플랫폼이 맞춤), 코드 칸만(앱 전체는 이미 UI Setting 화면 배율), Ctrl+휠 · Ctrl++/- · Ctrl+0 + 설정, 8~24.
만든 것
CodeFontMetrics(새) — 글자 크기 하나에서 줄 높이 · 여백 · 번호 칸 · 좁은 번호 칸 · 표식 · 단추 칸 · 단추 높이 · 단추 글자를 같은 비율로. 12 에서 지금 값과 정확히 같다(20 · 66 · 46 · 40 · 6 · 20 · 14 · 9).- 화면: 이 값들을 DynamicResource 로(행 템플릿 넷 · 편집기 · 줄 컨테이너 · 편집기 여백),
ApplyCodeFont가 한 벌로 갈아 끼운다.MergeLine.MinimumRowHeight를 설정할 수 있는 값으로 바꾸고 바뀌면 모든 행을 다시 잰다. - 줄 번호에 코드와 같은 줄 높이 규칙(
LineHeight·BlockLineHeight) — 원래 번호가 코드보다 몇 px 위에 떠 있었는데(12 에서 약 6px), 글자를 키우면 그만큼 커져 24 에서 눈에 띄었다. 이제 기준선이 같다. - 설정 "보기 > 코드 글자 크기 (8~24, 기본 12)"(
CodeFontSize). 바꿀 때마다 저장, 설정 화면에서 바꾸고 돌아오면 따라감. 단축키 Ctrl+= · Ctrl+숫자판 + · Ctrl+- · Ctrl+숫자판 - · Ctrl+0 · Ctrl+숫자판 0, Ctrl+휠. 상태 줄 커서 위치 옆에 기본이 아닐 때만글자 14(누르면 기본).
확인한 것
- 하네스 FontTest(새, 110건 — 8~24 모든 크기에서 여백 합 · 단추 ≤ 줄 · 번호 다섯 자리 · 정수 줄 높이, 끝에서 멈춤, NaN · 0 은 기본) · ShortcutTest +14(85건 — 새 키 · 수식키 없는 +/- 는 편집기 몫). 24벌 1,538건 · 빌드 경고 0 · 오류 0.
- 화면(
f5-verify.ps1, 1440p · 150%, 코드 칸만 창 그림(PrintWindow)으로 — 다른 창이 찍히지 않게):
| 크기 | 두 칸 행 높이(BASE · LOCAL) | 네 칸 행 높이(Mine · BASE · REMOTE · MERGED) | 여백 단추 |
|---|---|---|---|
| 8 | 19 · 20 번갈아(13 DIP × 1.5) — 두 칸 같음 | 넷 모두 같은 순서로 19 · 20 | 행 안 |
| 12 | 30 | — | 행 안 |
| 24 | 60 | 넷 모두 60 | 행 안 |
- 상태 줄
글자 8·글자 24, 12 는 비움. 그림: 줄 번호 · 여백 단추 · 코드 · 편집기 글자가 행마다 맞음(24 에서 번호가 뜨던 것을 고친 뒤 다시 찍음). - 키 시험 — 처음 두 번은 시험 도구가 앱 창을 앞으로 올리지 못했다(화면이 꺼져 있었다). 사용자가 화면을 켠 뒤(
f5-keys2.ps1, 1440p · 150%):- Ctrl+휠: 위 한 칸 12 → 13(행 30 → 33px) · 아래 한 칸 → 12 · 위 → 13, 매번 설정에 저장, 껐다 켜도 13.
- 편집기에 포커스가 있으면 Ctrl+= 13 → 14(행 34px) · Ctrl+- → 13 · Ctrl+0 → 기본(12, 행 30px), 매번 저장.
- 켜자마자는 포커스가 아무 데도 없어(
FocusedElement빈 값) Ctrl+= 뿐 아니라 F9 같은 다른 단축키도 듣지 않는다 — F-5 가 아니라 원래 있던 동작(코드 칸을 한 번 누르면 된다). 고칠지는 사용자에게 물음.
이어서 고친 것 — 켜자마자 단추키가 안 듣던 것 (2026-09-22 사용자 "응 고쳐줘")
HomeView.FocusEditorWhenIdle— 화면이 처음 뜰 때 · 파일 비교 탭으로 돌아올 때 · 창이 활성이 될 때, 키보드 포커스가 비어 있거나 이 화면 밖(아래 탭 줄 등)이면 편집기로 준다. 이 화면 안(찾기 칸 · 가는 줄 칸 등)이나 다른 창(대화상자)에 있는 포커스는 건드리지 않는다. 켤 때는 사용자 이름 창이 먼저 떠 있으므로 논리 포커스만 정해 두고, 본 창이 활성이 되면 WPF 가 거기로 돌려준다.- 확인(
f5-focus.ps1): 켠 직후 아무 데도 안 누르고 포커스LocalEditor· F9 들음, Git 탭(포커스는 탭 줄 항목)에 갔다 돌아오면LocalEditor· F9 들음, Ctrl+F 뒤FindBox가 2초 뒤에도 그대로. 빌드 경고 0 · 오류 0. - 회귀: 11차 E-1 병합 길(마우스 확인 B-1 · 스크린숏만 끔) — 1) 24 → 9 · 누른 Take 18 = 로그 18 · 병합 커밋 본문 26개 · 줄끝 · BOM 바뀐 파일 0 · 충돌 표식 0 · class 검사 0.
- 첫 회차는 "다음 충돌 안 보임" 으로 멈췄다 — 사용자가 그 사이 직접 MergeHub 를 켜 글자 9 · ACTIONS 감춤으로 바꿔 두었고, 시험 도구는 설정을 그대로 썼다. 시험 도구(
d7lib.ps1WithSettings)가 시험하는 동안만 ACTIONS 보임 · 글자 12 로 두고 끝나면 바이트 그대로 되돌리게 고쳤다(제품 아님). - 같은 때 시험 스크립트가 사용자가 켜 둔 MergeHub 를 강제로 껐다(16:55). 앞으로 시험 전에 떠 있는 창을 보고, 있으면 먼저 묻는다.
- 첫 회차는 "다음 충돌 안 보임" 으로 멈췄다 — 사용자가 그 사이 직접 MergeHub 를 켜 글자 9 · ACTIONS 감춤으로 바꿔 두었고, 시험 도구는 설정을 그대로 썼다. 시험 도구(
F-6. 글자를 되도록 많이 보이게 — 줄 간격 좁힘 (2026-09-22, 완료)
지시서는 "한 단추로 넓게 보기" 를 방향으로 적었지만, 사용자는 넓게 보기라는 기능이 아니라 넓게 보기 위한 방향을 물은 것이었다. 그래서 방법마다 1920 × 1080 에서 몇 줄이 느는지 재서 드렸고, 사용자가 "줄 간격 줄여주고 선택 사항은 만들지 마" 로 정했다.
잰 것 (f6-measure.ps1 — 두 번째 모니터 1920 × 1080(WPF 단위, 물리 2880 × 1620 · 150%)에 최대화, 글자 12)
| 방법 | 두 칸 | 네 칸(위 세 칸 · 아래 MERGED) | 상태 |
|---|---|---|---|
| 고치기 전 | 40줄 | 17 · 18 | — |
| 아래 탭 줄 접기(F11) | 42 | 18 · 19 | 이미 있음(F-4) |
| 글자 12 → 10(Ctrl+-) | 47 | 20 · 22 | 이미 있음(F-5) |
| 줄 간격 좁힘(줄 높이 20 → 16) | 약 50 | 22 · 23 | 새로 |
| 칸 제목 두 줄 → 한 줄 | 약 +0.7 | 약 +1.4 | 새로(안 함) |
| 색 범례 줄 감추기 | 약 +1 | 약 +1 | 새로(안 함) |
| ACTIONS 감추기(F9) | 0(칸 폭 +163px 씩) | 0 | 이미 있음(F-4) |
고친 것
- 줄 높이를 글자의 1.67배 → 1.33배로(
CodeFontMetrics, 12 → 16 · 8 → 11 · 24 → 32). 켜고 끄는 단추 · 설정은 만들지 않았다(사용자 결정). 여백 · 번호 칸 · 단추 비율은 그대로. MergeLine.MinimumRowHeight·CodeLineHeight기본값 · 화면의 줄 높이 대체값을 16 으로.- 북마크 표식(위아래 여백 3 + 높이 14 = 20)이 16 줄을 넘으므로 표식 높이도 줄에 맞춤(
BookmarkHeight= 줄 높이 − 6, 12 에서 10).
확인한 것
- 하네스 FontTest 144건(+34 — 8
24 모든 크기에서 줄 높이 1.31.4배, 북마크가 줄 안, 기본 12 의 값). 24벌 1,572건 · 빌드 경고 0 · 오류 0. - 화면(1920 × 1080, 글자 12): 두 칸 40 → 50줄(탭 줄까지 접으면 53), 네 칸 17 · 18 → 22 · 23줄(탭 줄 접으면 23 · 24). 행 높이 24px(16 DIP × 1.5).
- 8 · 12 · 24 (
f5-verify.ps1, 한글 주석 든 코드): 두 칸 행 높이 서로 같음(8 은 16 · 17 번갈아, 12 는 24, 24 는 48), 여백 단추 행 안, 그림에서 한글이 잘리거나 위아래 줄이 겹치지 않고 줄 번호 · 편집기 커서가 행에 맞음. - 회귀: 11차 E-1 병합 길 — 24 → 9 · 누른 Take 18 = 로그 18 · 병합 커밋 본문 26개 · 줄끝 · BOM 바뀐 파일 0 · 충돌 표식 0 · class 검사 0.
F-12. C# 코드 스타일 맞춤의 기본값을 AURORA 로 (2026-09-18, 완료)
사용자: "기본값은 원본형태를 따르고 C#인 경우에 AURORA 스타일로 하자" → 물어서 정한 것은 제품 기본값 AURORA · C# 파일만 · 저장 동작은 지금 그대로(켜져 있으면 저장도 그 스타일로 쓴다).
알아본 것
- C/C++ · XAML 은 고칠 것이 없었다. 스타일 맞춤은
CSharpStyle.Applies가 확장자.cs만 보므로(Services/CSharpStyle.cs:60) 설정이 무엇이든 다른 파일은 원본 그대로 견준다. - 그래서 바뀐 것은 설정 기본값 한 줄뿐이다.
고친 것
| 자리 | 고친 것 |
|---|---|
MergeHubSettings.cs:77 |
CSharpBraceStyle 기본값 None → Aurora. 왜 그렇게 정했는지와 "C# 파일에만 걸린다" 를 주석으로 남김 |
| 웹 문서 매뉴얼 | "기본은 끔" → "기본은 AURORA(2026-09-18 결정) · 끄려면 콤보에서 [C# 스타일 끔]" · "C# 파일에만 걸린다" 한 줄 더함 |
| 웹 문서 설정 표 | 기본값 칸 끔 → AURORA, ".cs 파일에만 걸린다" |
| 웹 문서 시연 대본 | "스타일 맞춤은 끔으로 둔다" → "기본이 AURORA 이므로 시연 전에 [C# 스타일 끔] 으로 바꿔 둔다" |
하네스 StyleTest |
+12건(78 → 90) — 설정 기본값이 AURORA 인지, .cpp · .h · .hpp · .c · .xaml · .py · .txt · .cs.txt 는 안 걸리는지, .cs · .CS · 한글 경로 .cs 는 걸리는지. 고치기 전에 먼저 넣어 기본값 검사만 실패하는 것을 보고 시작했다 |
확인한 것 — 설정 파일이 없는 첫 실행 (e11-f12.ps1)
설정 파일을 백업해 치우고, 중괄호 자리만 다른 짝 두 벌을 명령줄(--diff)로 열었다.
| 무엇 | 결과 |
|---|---|
C# 짝(left.cs Allman · right.cs AURORA) |
요약 "차이 없음" · 상태바 무시: 머지 주석 · C# AURORA (e11-f12-cs.png) |
C++ 짝(left.cpp · right.cpp, 같은 모양의 중괄호 차이) |
요약 "남은 차이 4줄" — 원본 그대로 (e11-f12-cpp.png) |
| 앱이 새로 만든 설정 파일 | "CSharpBraceStyle": 1 (= Aurora) |
| 설정 파일 되돌림 | 해시 같음 |
- 하네스 22벌 1,159건 통과(1,147 → +12) · 빌드 경고 0 · 오류 0.
- 이미 설정 파일이 있는 PC 는 그 값을 그대로 쓴다. 이번 변경은 설정이 없는 첫 실행에만 닿는다.