Ubisam-MergeTool/doc/history/2026-09-18-11차.md
ksj09406 a99ca970e9 11차 A-4: 변경분을 폴더에 더해 ZIP 으로도
사용자 결정대로 뽑은 폴더 옆에 같은 이름 .zip 을 만든다. 안에 폴더와 안내 파일을 나란히 넣어 풀면 폴더로 뽑은 것과 같은 모양이고, 파일은 바이트 그대로 · 경로는 / · 한글 이름은 UTF-8 표시. .part 에 쓰고 옮겨 반쯤 된 ZIP 을 남기지 않고, 못 만들어도 추출은 성공으로 둔다. UniquePath 는 같은 이름 .zip 이 남아 있어도 그 이름을 쓴 것으로 본다.

하네스 ReportTest +13 (70건, 22벌 1,260건) · 빌드 경고 0 · 오류 0. 아홉 경우를 화면에서 다시 뽑아 ZIP 8/8 을 Windows tar 로 풀어 폴더와 경로 · 해시가 같음, 앱이 만든 ZIP 의 한글 이름 UTF-8 표시 확인. 웹 문서 버전 14. 기획안은 사용자 잠금 대기.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 13:34:39 +09:00

55 KiB
Raw Blame History

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 높이 그대로. 잠금은 사용자(대기).

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, 이름 대조)

무엇이 필요한지 가린 길

  1. 참조로 — 셸 · MergeHub 에서 시작해 dll 이 부르는 dll 을 따라갔다. 어디서도 닿지 않는 것 7개: GLWpfControl · OpenTK · SkiaSharp.Views.WPF · SkiaSharp.Views.Desktop.Common · LiveChartsCore.SkiaSharpView.WPF · Microsoft.Extensions.Options · …Options.ConfigurationExtensions. 플랫폼 dll 안에 이 이름이 글자로도 없다(XAML 로 부르는 것도 아님).
  2. 플랫폼이 쓰는 것 — UbisamBase.Core 가 SkiaSharp · LiveChartsCore · LiveChartsCore.SkiaSharpView 를 직접 참조한다(Charting/ChartTheme.cs, 테마를 바꿀 때 UiSettingsService 가 부름). MergeHub 는 안 쓰지만 플랫폼 몫이라 남긴다(사용자 결정 2026-09-22 — 빼면 약 8MB 가 되지만 플랫폼이 바뀔 때마다 다시 재야 한다).
  3. 셸이 켜질 때 하는 일 — 셸은 폴더의 *.dll 을 모두 Assembly.LoadFrom 으로 열어 IAppSetup 을 찾는다(AppSetupLoader.cs:16). 쓰지 않는 dll 도 이름 순서상 MergeHub.dll 앞이면 켤 때마다 읽힌다 — 빼면 그만큼 덜 읽는다. Lang 폴더는 없으면 플랫폼이 만든다(LanguageService.cs), 지금은 비어 있다.
  4. 다른 OS · CPU — 맥용 dylib 3개(17.5MB), 리눅스 · 맥용 libgit2 9개(약 19MB), ARM 용(Skia · HarfBuzz 11MB, libgit2). 이 PC 에서 셸은 64비트로 뜬다. x86 은 32비트 Windows 를 위해 남긴다.
  5. 지워 보고 켜서 — 통째 복사본(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.md 11장 · 세 곳 고침.
  • 하네스 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-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 는 그 값을 그대로 쓴다. 이번 변경은 설정이 없는 첫 실행에만 닿는다.