사용자 결정(2026-09-18): 제품 기본값 AURORA · C# 파일만 · 저장 동작은 지금 그대로. - MergeHubSettings.CSharpBraceStyle 기본값 None → Aurora (한 줄, 까닭 주석) - C/C++ · XAML 은 고칠 것 없음 - CSharpStyle.Applies 가 확장자 .cs 만 본다 - 하네스 StyleTest +12 (78 → 90): 기본값 · 확장자별 적용 여부. 먼저 넣어 기본값 검사만 실패하는 것을 보고 시작 - 설정 파일 없는 첫 실행: 상태바 'C# AURORA' · C# 짝 차이 없음 · C++ 짝 남은 차이 4줄 · 새로 만든 설정에 1 - 웹 문서 매뉴얼 · 설정 표 · 시연 대본의 '기본은 끔' 을 고침 - 22벌 1,159건 통과 · 빌드 경고 0 오류 0 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
34 KiB
작업 지시 — MergeHub 11차 (변경분 추출을 믿고 들고 가게 · 베타 전에 깨지는 것 · 남은 기획 범위)
대상: D:\Sorce\MergeTool\MergeHub (플러그인) · D:\Sorce\MergeTool\UbisamPlatform (셸)
전제: 1~10차 지시서는 모두 끝났다(../진행상황.md).
이번 지시서가 나온 곳 — 10차 E-1 에서 다섯 길(병합 · pull · rebase · cherry-pick · revert)을 다시 끝까지 했고 새로 걸린 것은 없었다. 그래서 11차는 "고칠 버그" 가 아니라 기획안 v1.2 에서 아직 "일부" 인 것과 사내 베타(기획 4단계, 09.29 ~ 10.02) 전에 막아야 할 것에서 나왔다. 근거는 코드를 읽고 적은 것이다 — 실제로 해 보기 전의 짐작이므로 항목마다 먼저 다시 내고 시작한다.
| 어디서 | 무엇을 봤나 | 근거 |
|---|---|---|
| 변경분 추출 (기획안 "일부") | 지운 파일은 개수만 알리고 목록이 어디에도 안 남는다(코드 주석은 "목록에만 남긴다") · 어느 범위를 뽑았는지 폴더에 안 남는다 · 이미 파일이 있는 폴더에 묻지 않고 덮어쓰고 옛 파일이 섞인다 · ZIP 없음 | GitService.ExportChangedFiles · GitViewModel.ExportChangesAsync |
| 배포 폴더 | 매뉴얼이 가리키는 bin\Release\net48 의 MergeHub.dll 이 09-07 14:11, 셸이 09-07 13:41 — 10일 동안 Debug 로만 빌드했다. 폴더 크기 96MB(LiveCharts · Skia · OpenTK 등 플랫폼 런타임 포함) |
파일 시각 · README.txt |
| 설정 · 로그 위치 | 플랫폼이 D:\UbisamConfig 를 고정으로 쓴다. D 드라이브가 없는 PC 에서 어떻게 되는지 모른다 |
UbisamAppBuilder.ConfigRoot · LogService · LockConfirmDialog |
| 커밋 메시지 수정 (기획안 "일부") | 마지막 커밋만 커밋 수정. 기획안은 "커밋 우클릭 → 이름 변경". 있는 [커밋 수정] 에도 걸리는 것이 보인다 — [마지막 메시지] 가 HEAD 가 아니라 이력 목록 맨 위 메시지를 가져옴([모든 브랜치] 면 다른 브랜치 커밋) · 스테이징해 둔 파일이 말없이 같이 들어감 · 원래 작성자 · 작성 시각을 지금 사람으로 바꿈(git 은 남김) · 병합 · rebase 중에도 켜짐 · 확인 창 · 되돌릴 옛 해시 없음 · 하네스에 amend 검사 0건 | GitViewModel.AmendAsync · LoadLastMessage · GitService.Commit |
| 10차 E-1 시험 도구 | 줄끝 검사 스크립트가 부모 하나인 커밋에서 오류를 찍음 · 요약 읽는 함수가 "차이 없음" 을 못 읽음 | ../history/2026-09-17-10차.md E-1 "남긴 것" |
공통 규칙
- A → B → C → D → E → F 순서로 진행한다. A 는 사용자가 물어 본 것이라 먼저다. B 는 베타 날짜가 있어 C 보다 앞이다. F(2026-09-18 추가 요청)는 앞의 것을 끝낸 뒤 하나씩 올린다 — 급한 것이 있으면 사용자가 순서를 바꿔 말한다.
- 항목 하나를 끝낼 때마다 빌드하고 실제로 실행해 화면을 확인한 뒤 보고한다.
- 항목 하나가 끝나면 기록을 세 군데에 남기고 로컬 커밋한다(4차 D-2 규칙).
- 상세는
doc/history/YYYY-MM-DD-11차.md— 원인 · 판단 · 확인한 결과 - ../진행상황.md 은 대기 → 완료로 상태만
- ../history/changelog.md 에 한 줄 — 날짜 · 무엇을 왜 · 커밋
- 상세는
- 푸쉬하지 않는다.
- 실제 소스를 열지 않는다(2026-09-11 결정). 시험 재료는
C1Repo(병합 저장소) ·FolderPerf/Corpus.cs(폴더 묶음) · 직접 만든 파일로 만든다. 고치기 전에 문제가 다시 나는 것부터 보이고, 고친 뒤 안 나는 것을 보인다. 다시 나지 않으면 짐작으로 고치지 않고 되풀이한 횟수와 짚은 곳을 적어 보고한다. - 기존 검사 하네스(22벌 1,147건)는 계속 통과해야 한다. 로직을 건드리면 테스트를 먼저 늘린다.
- 빌드 경고 0 · 오류 0 을 유지한다. 앱이 실행 중이면
UbisamBase.Shell을 먼저 종료한다. - 사용자 설정 파일(
D:\UbisamConfig\Settings\MergeHubSettings.json)은 시험 전에 백업하고, 끝나면 바이트 그대로 되돌린다. 창 기억(ShellWindowPlacement.json)은 시험 뒤 "기억 없음" 으로 둔다. - 자동 조작으로 확인할 때는 사람이 갈 수 있는 길만 쓴다. 이름 창은 [저장], 접힌 영역은 [펴기], 이력 줄은 마우스로(10차 B-1 은 누르기 전에 묻는 길).
- 문서 글을 PowerShell 로 넣을 때는 작은따옴표 문자열만 쓴다(8차). PowerShell 변수 이름은 대소문자를 가리지 않는다 — 매개변수와 겹치는 이름을 쓰지 않는다(9차 A-2).
- 앱 안에 임시 측정 코드를 넣었다면 커밋하지 않고 잰 뒤 되돌리고 다시 빌드한다(9차 B-2).
- 레지스트리 HKLM · 셸 확장 · 보안(백신) 설정은 건드리지 않는다. 시스템 설정을 바꿔야만 재볼 수 있는 것은 재지 않고 적는다.
- 플랫폼을 고치면 다른 소비 프로그램에 미치는 영향을 함께 적고
UbisamPlatform/doc/history/changelog.md에 남긴다. 배포는 사용자 확인 뒤.
A. 변경분 추출을 믿고 들고 가게
기획안: "장비에 소스를 통째로 넣지 못하는 현장에서 바뀐 파일만 들고 간다." 들고 간 폴더만 보고 무엇이 바뀌고 무엇을 지워야 하는지 알 수 있어야 쓸 수 있다.
A-1. 먼저 뽑아 보고 적는다 (고치지 않음)
C1Repo로 저장소를 새로 만들고 Git 탭 → 이력에서 사람 순서로 뽑는다. 경우마다 뽑은 폴더를git diff --name-status·git show <커밋>:<경로>바이트와 견준다.
| # | 경우 | 볼 것 |
|---|---|---|
| 1 | 커밋 하나(시작점 없음) | 뽑은 파일 수 = git diff --name-status 부모 커밋 의 A · M 수, 바이트 같음 |
| 2 | [여기부터] 로 범위 | 범위 안 중간 커밋에서만 바뀌고 되돌려진 파일이 들어가는지 |
| 3 | 지운 파일이 있는 범위 | 알림 "삭제되어 건너뜀 N개" 뒤 어느 파일인지 알 길이 있는지 |
| 4 | 이름 바뀐 파일 | 새 경로로 뽑히는지 · 옛 경로를 알 길이 있는지 |
| 5 | 병합 커밋 하나 | 첫 부모와만 견주는지(상대 브랜치에서 들어온 파일이 모두 나오는지) |
| 6 | 시작점이 고른 커밋보다 뒤 | 무엇이 뽑히는지 · 경고가 있는지 |
| 7 | 이진 파일 · 한글 경로 · 깊은 폴더 | 바이트 · 경로 그대로인지 |
| 8 | 이미 파일이 있는 폴더에 다시 뽑기 | 덮어쓰기 · 옛 파일이 남아 섞이는지 · 묻는지 |
| 9 | 뽑는 중 대상 파일이 읽기 전용 · 열려 있음 | 오류 문구 · 반쯤 뽑힌 채 남는지 |
- 판정 기준: 9가지 경우의 결과를 값(파일 수 · 해시 · 알림 문구)으로 표에 적는다. 걸린 것은 A-2 ~ A-4 에 붙이거나 새로 적는다.
A-2. 뽑은 폴더에 "무엇을 뽑았는지" 를 남긴다 — 먼저 정한다
- A-1 의 3 · 4 · 6 결과를 보인 뒤 사용자에게 형식을 정한다.
- 뽑은 폴더 안에 안내 파일 하나(예:
_변경분.txt) — 범위(커밋 해시 · 제목 · 날짜) · 뽑은 사람 · 뽑은 파일 목록(추가 / 수정 / 이름 바뀜 옛 경로) · 지워야 할 파일 목록 - 폴더 밖(옆)에 같은 내용 — 장비에 폴더째 넣을 때 안내 파일이 섞이지 않게
- 파일은 만들지 않고 화면(Git 탭 로그 · 결과 창)에만
- 뽑은 폴더 안에 안내 파일 하나(예:
- 결과 내보내기(3차)와 보고서의 머리글(만든 사람 · 만든 때, 4차 A-2)과 같은 꼴을 쓴다.
- 판정 기준: 정한 대로 뽑은 결과만 보고 지워야 할 파일 · 이름 바뀐 옛 경로 · 범위를 알 수 있다. A-1 의 1 · 2 · 7 바이트 결과가 고치기 전과 같다. 하네스로 "지운 파일 · 이름 바뀜 · 병합 커밋" 목록을 만든다.
A-3. 이미 파일이 있는 폴더에 뽑을 때 — 먼저 정한다
- A-1 의 8 결과를 보인 뒤 정한다.
- 비어 있지 않으면 묻는다(덮어쓰기 · 취소)
- 고른 폴더 아래에 새 폴더를 만든다(예:
변경분_ace42e3..f310f49_2026-09-17) - 그대로 둔다(한계로 매뉴얼에 적음)
- 판정 기준: 정한 대로 옛 파일과 새 파일이 말없이 섞이지 않는다. [취소] 뒤 파일이 하나도 바뀌지 않았다.
A-4. ZIP 으로 뽑기 — 할지 먼저 정한다
- 폴더로만 뽑는다(기획안 "폴더·ZIP"). 필요한지 사용자에게 묻는다. 한다면 A-2 안내 파일이 ZIP 안에 들어가고, 풀었을 때 바이트 · 경로가 폴더로 뽑은 것과 같아야 한다.
- 판정 기준: 안 하기로 하면 기획안 · 웹 문서에 "폴더로만" 을 까닭과 함께 적는다. 하면 폴더 결과와 ZIP 을 푼 결과의 해시 목록이 같다.
B. 사내 베타 전에 깨지는 것
기획 4단계(09.29 ~ 10.02) 에 다른 사람 PC 에서 처음 켠다. 지금까지는 이 PC · 이 경로 · 이 설정에서만 켰다.
B-1. 배포 폴더가 10일 전 것이다 — 다시 만들고 무엇이 들어가야 하는지 정한다
- 매뉴얼("개발 PC 에서는
src\MergeHub\bin\Release\net48\UbisamBase.Shell.exe")이 가리키는 Release 출력의MergeHub.dll이 2026-09-07 이다. 먼저 지금 Release 로 켜면 무엇이 다른지(예: 6차 이후 기능이 없는지)를 한 번 확인해 적는다. - Release 로 다시 빌드하고, 배포 묶음에 꼭 필요한 파일을 가린다: 셸 · 플러그인 · LibGit2Sharp 네이티브(
lib\win32·win-x64) · CommunityToolkit · 설정 기본값 ·Lang. LiveCharts · Skia · OpenTK 가 MergeHub 에 필요한지는 지워 보고 켜서 가린다(플랫폼이 쓰는지 같이 본다). - 빈 폴더(예:
%TEMP%\mergehub-beta)에 묶음만 복사해 켜고, 다섯 탭 · 병합 한 길(C1Repo)을 끝까지 한다. - 판정 기준: 배포 묶음 목록(파일 · 크기 · 왜 필요한지)과 총 크기를 적는다. 빈 폴더에서 켜 병합 커밋까지 된다. 매뉴얼의 실행 위치 문장이 사실과 같다. 플랫폼 배포 폴더를 바꿔야 하면 사용자 확인 뒤.
B-2. D 드라이브가 없는 PC · 설정 파일이 없는 첫 실행
- 플랫폼이 설정 · 로그 · 화면 잠금 기록을
D:\UbisamConfig에 고정으로 쓴다. D 드라이브를 없애는 시험은 하지 않는다(디스크 설정). 대신 코드로 "D:\ 가 없을 때 어느 줄에서 무엇이 되는지" 를 따라가 적고, 설정 파일 · 폴더가 없는 첫 실행은 백업 뒤 폴더 이름을 잠시 바꿔 재 본다(끝나면 바이트 그대로 되돌림). - 첫 실행에서 볼 것: 이름 창 · 기본 설정 값 · 창 위치 · 로그 폴더 생성 · 오류 창 여부.
- 방향: D 드라이브가 없을 때 켜지지 않는다면 플랫폼 문제다. 고치는 길(예: 없으면 사용자 폴더로)을 다른 소비 프로그램 영향과 함께 사용자에게 보이고 정한다.
- 판정 기준: 첫 실행이 오류 창 없이 켜지고 기본값이 매뉴얼 설정 표와 같다. D 드라이브 없는 경우의 결과를 코드 근거로 적었다(고쳤다면 플랫폼 changelog).
C. 커밋 메시지 수정 — 기획 범위에서 "일부" 로 남은 것
기획안 1차 범위 "커밋 메시지 수정 — 커밋 우클릭 → 이름 변경. 명령어와 옵션을 외울 필요 없음". 기획안 v1.2 · 웹 문서에는 "마지막 커밋만 커밋 수정" 으로 일부라고 적었다. 그런데 코드를 다시 읽으니 있는 [커밋 수정] 도 믿고 쓰기 어려운 곳이 있다. 새 기능(C-2)을 정하기 전에 있는 길부터 바로잡는다.
지금 모양 (Git 탭 → 변경 · 커밋, 아래 줄 커밋 메시지 [칸] [마지막 메시지] [커밋] [커밋 수정]):
- [커밋 수정] =
GitService.Commit(message, amend: true)→ LibGit2SharpRepo.Commit(message, 지금 사람, 지금 사람, AmendPreviousCommit). 켜지는 조건은 저장소가 열려 있고 메시지 칸이 비어 있지 않음 뿐이다. - [마지막 메시지] =
_workspace.Commits[0].Message— 이력 목록의 맨 위 커밋 메시지. - 이력 탭에서 고른 커밋과는 상관없이 늘 HEAD 를 고친다. 우클릭 메뉴는 없다.
- 하네스(
GitOpTest등)에 amend 를 재는 검사가 없다.
C-1. 있는 [커밋 수정] 을 다시 내 보고 바로잡는다 (원인부터)
C1Repo로 저장소를 새로 만들어 사람 순서로 한다. 경우마다 고치기 전 결과를git log -1 --format="%H %an %ae %ad %cn %s"·git show --stat·git status로 적는다.
| # | 짚이는 것 | 다시 내는 순서 | git 은 어떻게 하나 |
|---|---|---|---|
| 1 | [마지막 메시지] 가 다른 커밋 메시지를 가져온다 | 이력 [모든 브랜치] 켬(9차 A-2: 맨 위가 다른 브랜치 커밋) → 변경 · 커밋 [마지막 메시지] → 칸의 글이 HEAD 메시지인지 → 그대로 [커밋 수정] 하면 HEAD 가 다른 커밋의 메시지로 바뀌는지 | git commit --amend 는 HEAD 메시지를 편집기에 띄운다 |
| 2 | 스테이징해 둔 파일이 같이 들어간다 | 파일 하나 고쳐 [스테이징] → 메시지만 고칠 생각으로 [마지막 메시지] → [커밋 수정] → 그 파일이 HEAD 에 들어갔는지 · 알림에 그런 말이 있는지 | 같이 들어간다(--only 없이). 다만 편집기 화면에 바뀔 파일 목록이 보인다 |
| 3 | 원래 작성자 · 작성 시각이 바뀐다 | 8차 C-2 처럼 작성자 박지훈 인 커밋을 cherry-pick 해 HEAD 로 만든 뒤 [커밋 수정] → %an · %ad |
작성자 · 작성 시각은 그대로, 커밋한 사람 · 시각만 바뀐다(--reset-author 를 줄 때만 바뀜) |
| 4 | 작업 중에도 켜진다 | 병합 충돌 중 · rebase 중 · cherry-pick / revert 중에 메시지 칸에 글을 넣고 [커밋 수정] 이 켜지는지 · 누르면 무엇이 되는지(부모 수 · MERGE_HEAD · rebase-merge 가 남는지) |
병합 중에는 막는다("You are in the middle of a merge -- cannot amend") · rebase 중에는 멈춘 커밋을 고치는 뜻이 된다 · cherry-pick / revert 중은 재어 적는다 |
| 5 | 병합 커밋을 고치면 | 병합 커밋이 HEAD 일 때 [커밋 수정] → 부모 둘이 남는지 · 8차 F-1 본문(충돌 해결 내역)이 사라지는지 | 부모는 그대로 |
| 6 | 이미 올린 커밋 | pull 길(10차 E-1)의 원격을 흉내 낸 bare 저장소로 push 한 뒤 [커밋 수정] → 막거나 알리는지 · 그 뒤 Push 가 어떻게 되는지 | 막지 않는다. 다음 push 가 거부된다 |
| 7 | 되돌리는 길 | 수정 뒤 알림 · 로그에 고치기 전 해시가 남는지 | reflog 에 남는다 |
| 8 | 메시지 칸 · 첫 줄 | 여러 줄 메시지 · 빈 줄 · # 로 시작하는 줄이 그대로 들어가는지(6차 B-3 은 병합 메시지의 # 줄을 뺐다) |
편집기를 거치면 # 줄이 빠진다 |
- 원인이 확인된 것만 고친다. 고칠 방향(사용자에게 보이고 정할 것은 정함 으로 표시):
- 1 — [마지막 메시지] 는 HEAD 커밋의 메시지를 읽는다(목록 순서와 무관).
- 2 — 정함: [커밋 수정] 을 누를 때 스테이징된 파일이 있으면 "파일 N개도 이 커밋에 들어갑니다" 를 묻는다 / 메시지만 고치는 길을 따로 둔다 / 그대로 두고 매뉴얼에 적는다.
- 3 — 작성자 · 작성 시각은 원래 커밋 것을 쓴다(git 과 같게). 커밋한 사람만 지금 사람.
- 4 — merge · rebase · cherry-pick · revert 진행 중에는 [커밋 수정] 을 끈다(단추 설명에 까닭).
- 5 — 병합 커밋 본문이 사라진다면 [마지막 메시지] 가 본문까지 가져오는지 보고 적는다.
- 6 — 정함: 원격 추적 브랜치에 이미 있는 커밋이면 묻는다 / 막는다 / 매뉴얼에만 적는다.
- 7 — 알림 · 로그에 "커밋 수정 완료 (옛 abc1234 → 새 def5678)".
- 판정 기준: 여덟 가지 모두 고치기 전 · 뒤 결과를 값으로 적는다. 고친 것은 하네스에 먼저 넣는다 — HEAD 메시지 읽기([모든 브랜치] 목록에서도) · 작성자 · 작성 시각 보존 · 작업 중 꺼짐 · 병합 커밋 부모 둘 유지. 파일 비교 탭에 저장 안 한 편집이 있을 때 먼저 묻는 것(5차 A-2)이 그대로다.
C-2. 마지막 커밋이 아닌 커밋의 메시지 수정 — 할지 먼저 정한다
- C-1 을 끝낸 뒤 정한다. 기획안은 "커밋 우클릭 → 이름 변경" 이고, 이력 탭에서 고른 커밋의 메시지를 바꾸는 일이다.
- HEAD 가 아니면 그 뒤 커밋을 모두 다시 쓴다(해시가 모두 바뀜 ·
git rebase -i의 reword). 사용자에게 보일 것:- 되는 범위: 현재 브랜치의 조상 커밋 · 원격에 없는 커밋 · 그 사이에 병합 커밋이 없을 때
- 막을 것: 원격에 올라간 커밋 · 사이에 병합 커밋 · 작업 중(merge · rebase · cherry-pick · revert) · 워킹트리에 커밋 안 한 변경 · 파일 비교 탭에 저장 안 한 편집 · 다른 브랜치에만 있는 커밋([모든 브랜치])
- 지켜야 할 것: 다시 쓴 커밋들의 트리 · 작성자 · 작성 시각 그대로, 메시지는 고른 커밋만
- 되돌리는 길: 바꾸기 전 HEAD 해시를 알림 · 로그에 남긴다
- 화면: 이력 줄 우클릭 메뉴 또는 이력 탭 단추 — 10차 B-1 대로 두 탭이 같은 커밋을 보는지
- 판정 기준: 안 하기로 하면 기획안 · 웹 문서에 "마지막 커밋만" 을 까닭과 함께 적고 닫는다. 하면 하네스로 "세 커밋 앞 커밋 메시지 바꾸기 → 그 뒤 커밋 수 같음 · 커밋마다 트리 해시 · 작성자 · 작성 시각 같음 · 고른 커밋 메시지만 바뀜" 을 보이고, 막을 경우 여섯 가지가 실제로 막힌다. 바꾼 뒤 두 탭의 고른 커밋이 새 해시를 따라간다(9차 A-1 · A-2 규칙).
D. 시험 도구 정리 (제품 아님)
D-1. 10차 E-1 에서 남긴 둘
- 줄끝 검사 스크립트(
d1-verify.ps1)가 부모 하나인 커밋(rebase · cherry-pick · revert)에서 둘째 부모가 없어git merge-base오류를 찍는다 — 부모 하나면 첫 부모와만 견준다고 적고 오류 없이. - 파일 비교 탭 요약을 읽는 함수(
FileState)가 "차이 없음" 을 못 읽어 커밋 뒤 요약이 빈칸으로 적힌다. - 판정 기준: 10차 E-1 의 rebase 한 길을 다시 돌려 오류 줄 0 · 커밋 뒤 요약 "차이 없음" 이 적힌다. 제품 코드는 바꾸지 않는다.
E. 확인 · 문서
E-1. 바꾼 길을 다시 끝까지
- F 에서 화면 · 저장을 건드렸으면 그 길도 함께 본다. A 를 고쳤으면 A-1 의 9가지를 다시 돌려 표를 채운다. C-1 을 고쳤으면 C-1 의 여덟 가지를 다시, C-2 를 했으면 메시지를 바꿔 이력을 다시 쓴 저장소로 병합 한 길을 끝까지.
- 제품의 병합 · 저장 코드를 건드렸다면 10차 E-1 처럼 다섯 길(+ pull) 을 다시 한다. 안 건드렸다면 병합 한 길만(회귀).
- 판정 기준: 줄끝 · BOM 바뀐 파일 0 · 충돌 표식 0 · class 이름 다른 Unit 파일 0 · 누른 수 = 줄 고른 로그. 10차 B-1(두 탭 같은 커밋)이 다시 나지 않는다.
E-2. 웹 문서 · 기획안을 11차에 맞게
- MergeHub 문서(
doc/web/index.html, 아티팩트 "MergeHub 문서"): 매뉴얼 변경분 추출 · 실행 위치(B-1) · 설정 위치(B-2) · F 에서 바뀐 화면(칸 이름 · 감추기 · 글자 크기 · 백업 저장 · 보내기) · 알아 둘 한계 · 남은 일 · 지금까지 만든 것. 발행본을 먼저 읽고 합쳐 올린다. - 기획안 v1.2(잠금 아티팩트 "UbiSam MergeTool 개발 기획안"): 3.2 기능 목록의 변경분 추출 · 커밋 메시지 수정 상태, 4단계 진행. 원문은 로컬에서 고치고 A4 쪽마다 원본과 같은 높이인지 그림으로 견준다. 잠금은 사용자가 비밀번호로 한다 — 잠그지 않은 파일은 올리지 않는다(공유 링크가 열린 사내 문서).
- 판정 기준: 문서의 단추 이름 · 흐름이 지금 화면과 같다(grep 대조). 태그 짝 맞음. 기획안 새 잠금 파일을 풀면 고친 원문과 바이트가 같다.
F. 추가 요청 (2026-09-18, 사용자)
열한 가지를 한꺼번에 받았다. 다 하는 것이 아니라 하나씩 올린다 — F-1 · F-2 · F-3 은 화면과 저장에 바로 닿고, F-4 ~ F-7 은 보이는 양을 늘리는 한 묶음, F-8 ~ F-11 은 저장 · 확인이다. 아래 "지금은" 은 코드를 읽고 적은 것이다(2026-09-18). 항목마다 화면에서 먼저 다시 보이고 시작한다.
F-1. LOCAL · REMOTE · MERGED 이름을 맞추고, 그 칸이 어느 파일인지 보이게
- 지금은: 칸 이름이
BaseTitle => "BASE"·LocalTitle => IsThreeWay ? "MERGED" : "LOCAL"(HomeViewModel.cs:2393)뿐이고, "한글 풀이를 붙이지 않는다" 는 판단이 바로 위 주석(:2389)에 적혀 있다. 파일 경로는 맨 위 한 줄에 한 번만 나온다(4차 C-1 에서 세 곳 → 한 곳으로 줄였다). BASE 칸에만(merge base) 경로, REMOTE 칸에는 브랜치 · 커밋이 붙는다. - 그래서
git mergetool로 열었을 때처럼 네 칸이 서로 다른 파일(임시--base·--local·--remote·--merged)을 볼 때 어느 칸이 어느 파일인지 화면에 없다. - 방향: 칸 머리마다 한 줄로 무엇 · 어느 파일 · 어느 커밋/브랜치. 예)
MERGED · Weld/Unit1.cs (저장할 파일)·REMOTE(Theirs) · feature/theirs · Weld/Unit1.cs. 긴 경로는 가운데를 줄이고 전체는 마우스를 올리면 보이게. 로그 · 보고서 · 매뉴얼에서 쓰는 말도 같은 말로 맞춘다. - 정할 것: 이름을 표준 용어 그대로 둘지(
LOCAL(Mine)), 한글 풀이를 함께 붙일지(LOCAL(내 쪽)). 4차 · 6차에 "표준 용어 그대로" 로 정한 적이 있어 뒤집는 결정이다. - 판정 기준: 두 칸 · 네 칸 ·
git mergetool·--merge네 길에서 칸마다 파일 이름이 보이고, 그 파일이 실제로 읽은 · 저장할 파일과 같다(8차 A-1 의 "화면에 실린 파일" 과 같은 값). 좁은 폭에서도 줄이 늘어나지 않는다.
F-2. 메서드 단위로 골라 반영 (지금은 줄 · 덩어리 · 전체)
- 지금은: 반영 단위가 줄(
[>]) · 이어진 차이 덩어리(이 덩어리 반영) · 전체뿐이다. 덩어리를 반영하면 머지 주석은 덩어리 첫 줄 위에 한 줄 붙는다. - 요청: 메서드를 통째로 고르고, 머지 주석은 메서드 이름 위에 한 줄만.
- 방향: Roslyn 없이
CodeTokenizer로 중괄호 짝과 시작 줄을 찾아 메서드 범위를 잡는다. 문자열 · 주석 · 전처리기(#if) 안의 중괄호에 속지 않아야 한다. 캐럿이 놓인 메서드를 잡아 [이 메서드 반영]. 범위를 잡지 못하면 단추를 끄고 까닭을 알린다(틀린 범위를 반영하는 것보다 낫다). - 정할 것: C# 만 먼저 할지(XAML · C/C++ 은 뒤로), 속성 · 로컬 함수 · 생성자도 "메서드" 로 볼지.
- 판정 기준: 시험 파일에서 메서드 20개(한 줄 메서드 · 중첩 중괄호 · 문자열 안 중괄호 ·
#if로 갈린 메서드 · 주석 안 중괄호 포함)의 범위를 정확히 잡는다(하네스). 반영한 뒤 저장 결과가 줄 단위로 같은 범위를 반영한 것과 바이트가 같다. 머지 주석은 메서드 이름 위 한 줄.
F-3. 탐색기에서 폴더 두 개를 골라 [보내기] 로 바로 비교
- 지금은: 보내기 등록은
%APPDATA%\Microsoft\Windows\SendTo에 바로가기 하나를 두는 것이 전부다(ShellIntegration.cs:18, 관리자 권한 · 레지스트리 없음). 명령줄 쪽은 폴더 두 개를 받으면 폴더 비교로 연다(StartupArgs.cs:118~122). 그런데 탐색기가 여러 개를 고른 보내기를 어떻게 넘기는지(한 번에 인자 둘 / 프로세스를 두 번)는 재 보지 않았다. - 확인할 것: 파일 2개 · 폴더 2개 · 폴더 1개 · 3개 이상 · 경로에 공백 · 한글 · 아주 긴 경로. 프로세스가 두 번 뜨면 하나로 모으는 길(이미 떠 있는 창으로 보내기)을 정한다.
- 설치 파일 없이 되는지도 여기서 답한다 — 지금 구조(바로가기 하나 · HKCU/HKLM 안 씀)면 설치 관리자가 필요 없다. 다만 배포 묶음을 옮기면 바로가기 경로가 어긋나므로 [탐색기 보내기 등록] 을 다시 눌러야 하는지, 켤 때 저절로 고칠지 정한다(B-1 배포 묶음과 함께).
- 판정 기준: 폴더 두 개를 골라 보내기 → 창 하나에 왼쪽 · 오른쪽 폴더가 들어가 비교까지 간다. 위 일곱 경우의 결과를 값으로 적는다. 레지스트리를 쓰지 않는다.
F-4. 파일 비교 탭의 툴박스(ACTIONS)를 감추는 단추
- 지금은: ACTIONS 칸은 접어도 폭이 그대로다(4차 C-5 결정,
HomeView.xaml:864). 접기는 "한 번 정하는 것"(저장 형식 · 비교 규칙)에만 걸려 있다. - 방향: 칸 전체를 감춰 코드 폭을 넓히는 단추(또는
F9같은 키). 감춘 상태를 설정에 기억. 감춘 채로도 저장 · 반영 키는 살아 있어야 한다. - 판정 기준: 감추면 코드 칸 폭이 그만큼 늘고, 다시 펴면 원래대로. 앱을 껐다 켜도 상태가 남는다. 감춘 상태에서
Ctrl+S·Alt+←/→가 그대로 듣는다.
F-5. 글자 크기 조절
- 지금은: 코드 칸은
Consolas 12로 XAML 에 박혀 있고(HomeView.xaml:163등), 설정에 글자 크기 항목이 없다. - 방향: 설정 값 하나 +
Ctrl+ 휠 ·Ctrl++/-로. 코드 칸 · 줄 번호 · 미니맵이 같이 커지고 줄 높이도 따라야 한다. - 판정 기준: 8pt ~ 24pt 에서 줄 번호 · 여백 단추 · 미니맵 자리가 어긋나지 않는다. 바꾼 크기가 앱을 껐다 켜도 남는다. 네 칸에서 세 칸의 줄 높이가 서로 맞는다.
F-6. 글자를 되도록 많이 보이게
- 지금은: 6차에서 셸 상 · 하단 띠를 줄여 코드가 3줄 더 보이게 했다. 그 뒤로는 더 재지 않았다.
- 방향: 한 단추(또는 키)로 넓게 보기 — 색 구분 범례 줄 접기 · ACTIONS 감추기(F-4) · 위 줄 한 줄로 · 줄 간격 좁히기.
- 판정 기준: 1920 × 1080 에서 지금 몇 줄이 보이는지 재고, 넓게 보기로 몇 줄이 늘었는지 값으로 적는다(예: 34줄 → 44줄). 글자 크기(F-5)와 섞어 써도 깨지지 않는다.
F-7. 어느 모니터에서든 제대로 뜨게
- 지금은: 창 자리 기억은 플랫폼이 한다(
ShellWindow.xaml.cs:475PreparePlacement· 모니터 작업 영역과 배율로 최소 크기를 다시 계산). 8차 C-3 에서 첫Win+↓와 확인 창 가운데 맞춤을 고쳤다. - 먼저 증상부터 적는다 — 어느 모니터에서 무엇이 잘못되는지(창이 화면 밖 · 너무 작음 · 글자만 크게 · 두 번째 모니터에서 안 뜸 · 배율 150% 에서 잘림). 재현되지 않으면 고치지 않는다.
- 플랫폼을 고치면 다른 소비 프로그램에 영향이 있다 — 영향과 함께 사용자 확인 뒤 배포.
- 판정 기준: 증상과 조건(모니터 수 · 해상도 · 배율 · 주 모니터 위치)을 적는다. 고쳤다면 같은 조건에서 창이 보이는 자리에 뜨고, 기억한 자리가 사라진 모니터면 주 모니터로 온다.
F-8. 저장한 뒤에도 되돌리기가 되게
- 지금은: 저장하는 네 길이 모두 되돌리기 스택을 비운다 —
SaveResolvedAsync:977·SaveAndCommitAsync:896·SavePlainAsync:2686·SaveWorkingCopy:2836. 저장한 글이 새 기준(_originalLocalText)이 되기 때문이다. - 방향: 스택을 비우는 대신 저장 지점을 표시한다. 그 아래로 되돌리면 다시 "저장할 것 있음" 이 되고, 다시 저장 지점으로 오면 없어진다.
- 정할 것: 병합 중 [Save] 까지 되돌릴지. 이 저장은 git 인덱스에 "해결" 로 등록하므로, 되돌리면 인덱스를 어떻게 할지 함께 정해야 한다(되돌리면 다시 충돌로 / 화면만 되돌리고 인덱스는 그대로 · 알림).
- 판정 기준: 저장 → Undo → 화면이 저장 전으로, 상태가 "저장할 것 있음". Redo 로 다시 저장 후로. [전체 되돌리기] 의 기준이 정한 대로 움직인다. 하네스로 "저장 표시가 있는 스택" 을 먼저 만든다.
F-9. 백업본으로 저장 — 원본을 건드릴지 고르게
- 지금은: 저장은 늘 원본 파일을 덮어쓴다.
.bak도, 다른 이름으로 저장도 없다. - 방향: [저장] 옆에 [다른 이름으로 저장], 또는 설정 "저장할 때 원본을
파일명.bak으로 남기기". 남긴 백업의 이름 규칙(날짜 · 번호)과 지우는 시점을 정한다. - 정할 것: 병합 중 · Git 저장소에서도 같게 할지. 병합 중 [Save] 는 git 인덱스에 등록하는 일이라 "원본을 건드리지 않음" 과 어울리지 않는다 — Git 아닐 때만 둘지 정한다.
- 판정 기준: 켠 채로 저장하면 원본과 백업이 둘 다 남고, 백업은 저장 전 바이트 그대로(해시 대조). 끄면 지금과 같다. 폴더 비교 · 변경분 추출이 백업 파일을 결과에 섞지 않는다.
F-10. 덩어리(블록)가 어디로 갔는지 UI 로 잇기
- 지금은: 자리만 옮긴 덩어리를 찾아 "자리 옮김" 색으로 칠한다(
MoveDetector). 하지만 어디에서 어디로 갔는지는 색만으로 알기 어렵다. 줄 위치가 많이 벌어지거나 순서가 바뀌면 두 칸을 눈으로 따라가야 한다. - 방향: 두 칸 사이에 잇는 선(또는 같은 번호표)을 그려 짝을 보이게. 미니맵에도 같은 표시. 고른 덩어리의 짝으로 한 번에 건너뛰는 단추.
- 판정 기준: 메서드 세 개의 순서를 바꾼 시험 파일에서 세 짝이 모두 선으로 이어지고, 잇는 선이 잘못 짝지은 것 0. 스크롤 · 접기 · 글자 크기(F-5)를 바꿔도 선이 제자리. 차이 수 · 저장 내용은 그대로.
F-11. Git 계정 · URL · 암호가 한 번 쓰면 저장되는지 확인
- 지금은: 서버 주소와 계정은 설정 파일에 저장된다(
MergeHubSettings.cs:40GiteaUrl·:44GiteaUserName). 암호 · 토큰은 저장되지 않는다 — 화면의 PasswordBox 에서 받아 메모리(GitWorkspace.Password:154)에만 두고, Fetch · Pull · Push 직전에 붙인다(ApplyCredentials:519). 그래서 앱을 껐다 켜면 토큰을 다시 넣어야 한다. - 먼저 화면으로 확인해 적는다: 껐다 켠 뒤 주소 · 계정이 남는지, 암호 칸이 비는지, 그 상태로 Fetch 를 누르면 무엇이라 하는지.
- 정할 것: 토큰을 저장할지. 저장한다면 평문은 안 된다 — 윈도 자격 증명 관리자(DPAPI) 에 사용자 계정으로 묶어 넣는다. 저장하지 않기로 하면 매뉴얼에 그렇게 적는다.
- 판정 기준: 확인한 결과를 적는다. 저장하기로 하면 설정 파일 어디에도 토큰 글자가 없고(파일 grep 0), 껐다 켜도 Push 가 다시 묻지 않는다. 지우는 단추가 있다.
F-12. C# 코드 스타일 맞춤의 기본값을 AURORA 로 (2026-09-18, 사용자 결정 · 완료)
- 사용자: "기본값은 원본형태를 따르고 C#인 경우에 AURORA 스타일로 하자" → 물어 정한 것: 제품 기본값 AURORA · C# 파일만 · 저장 동작은 지금 그대로(켜져 있으면 저장도 그 스타일로 쓴다).
- 지금은:
MergeHubSettings.CSharpBraceStyle기본값이None(끔). C/C++ · XAML 은CSharpStyle.Applies가 확장자.cs만 보므로 어느 값이어도 원본 그대로다 — 따로 고칠 것이 없다. - 2026-09-17 에 "비교할 때만 맞추고 저장은 원본대로" 하는 선택지는 만들지 않기로 했다. 이번 결정도 그 위에 선다.
- 판정 기준: 설정 파일이 없는 첫 실행에서 AURORA 로 시작한다. 중괄호 자리만 다른 C# 짝이 "차이 없음", 같은 모양의 C/C++ 짝은 차이가 그대로 남는다. 하네스에 기본값 · 확장자 검사를 넣는다. 매뉴얼 · 설정 표 · 시연 대본의 "기본은 끔" 을 고친다.
이번 지시서에서 하지 않는 것
- 실제 소스로 해 보기 — 실제 소스는 열지 않는다(2026-09-11 결정).
- 느린 디스크(HDD)에서 폴더 비교 재기 — 이 PC 에는 NVMe 뿐이다. 사내 베타 때 그 PC 에서 잰다(10차 D-1).
- 사내 베타 배포 자체 · 푸시 — 사내 Gitea 저장소와 대상 PC 가 정해지면 따로 지시한다. B 는 배포 전 확인까지.
- D 드라이브를 없애거나 디스크 · 백신 · 레지스트리(HKLM) 설정을 바꿔 보는 시험 — 보안 · 시스템 설정이라 하지 않는다.
- 빈 cherry-pick 을 커밋으로 남기는 길 — 두지 않기로 했다(2026-09-16 사용자 결정).
- 비교할 때만 C# 스타일을 맞추는 선택지 — 만들지 않기로 했다(2026-09-17 사용자 결정).
- MergeHub 밖에서 푼 충돌을 병합 본문에 적기 — 알 길이 없다(8차 F-1).
- 셸 창 반쪽 스냅 · 1px 테두리 — 8차 C-3 결정 그대로.
- 로그인·권한 · Gitea PR 코멘트 · 멀티 레포 · Roslyn · 같은 줄 접기(4차 B-2) · 외부 편집기(4차 B-4) · 창 여러 개 — 미룬 그대로 둔다.
보고 형식
항목마다 이렇게 적는다.
- 고치기 전에 문제가 다시 나는 것을 어떻게 보였는지 (만든 저장소 · 묶음의 어느 파일로, 몇 번 되풀이해서)
- 무엇이 원인이었는지 한두 줄 (코드 · 로그 근거)
- 사용자에게 정해 달라고 한 것과 정한 것
- 어떤 파일을 어떻게 고쳤는지
- 실제로 실행해 확인한 결과 (파일 수 · 해시 · 크기 · 알림 문구 · ms 처럼 눈이 아닌 값으로)
- 커밋 해시