50 Commits

Author SHA1 Message Date
9d0cbb7ff8 11차 F-2: 메서드 단위로 골라 반영 · 덩어리 반영의 주석 한 줄
- [이 메서드 반영]: 캐럿이 놓인 클래스 멤버를 통째로(사용자 결정: C# + C/C++,
  메서드 · 생성자 · 속성 · 이벤트 · 연산자 · 필드 · enum, 로컬 함수 안이면 감싸는 멤버)
- MemberRanges: Roslyn 없이 주석 · 문자열(축자 · 보간 · raw · C++ raw · 숫자 구분자)을
  가리고 #if 갈래마다 다시 읽어 중괄호 짝으로 범위. 못 잡으면 단추를 끄고 까닭 한 줄
- 덩어리 · 메서드 반영(ApplyGroup): 머지 주석 한 줄(메서드 이름 위 · 덩어리 첫 줄 위),
  로그 한 줄, Undo · Redo 한 번(LineEdit.Group). 덩어리가 줄마다 주석을 달던 것도 고침.
  주석만 든 편집(NoteOnly)은 직접 수정 · 편집 수에 안 셈
- 메서드 반영 저장본 = 같은 줄 줄 단위 반영 저장본(바이트). MemberTest 83건(23벌 1,395건)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 15:38:04 +09:00
aafd7a5a6f 11차 F-1: 칸 이름 · 칸마다 어느 파일인지 · 머지 주석에 어디서 가져왔는지
- 칸 이름 LOCAL(Mine) · REMOTE(Theirs)(사용자 결정: 표준 용어 + 영문 쪽 이름)
- 칸 머리마다 한 줄 "어느 쪽 · 어느 파일"(PaneHeaders). MERGED · 두 칸 LOCAL 은
  "(저장할 파일)", mergetool · --merge 는 제 임시 파일 이름 - Mine 칸이 MERGED 이름을
  보이던 것(MineHeader) 고침. 좁으면 가운데를 줄이고 툴팁에 전체(MiddleTrim)
- 머지 주석 [사람] 날짜 출처 설명(사용자 결정: 쪽 이름 + 브랜치/해시, 출처 먼저).
  출처는 로그와 같은 말 - 두 칸 로그 BASE(해시) 반영, 브랜치 3-Way 로그 REMOTE(브랜치) 반영
- Take Mine 도 주석(처음 한 번, 되돌리면 함께 빠짐)
- 무시 조건은 [사람] 날짜 뒤를 따지지 않아 코드 그대로 - 옛 · 새 · 출처만 다른 주석을
  하네스로 굳힘(NoteTest · RulesTest · FolderTest · MergeSaveTest, 1,312건)
- 네 길 화면 확인 · E-1 병합 길 회귀 없음

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 14:31:57 +09:00
588f3d75e9 11차 C-2: 이력 줄 우클릭으로 마지막이 아닌 커밋의 메시지를 바꾼다
기획안 1차 범위 "커밋 우클릭 -> 이름 변경". 사용자 결정대로 좁은 범위에서만 한다.

HEAD 가 아닌 커밋의 메시지를 바꾸면 그 커밋부터 HEAD 까지가 새 해시로 다시
써진다. 고른 커밋의 메시지만 갈고 뒤 커밋은 트리 · 작성자 · 작성 시각 ·
부모 관계를 그대로 두어(LibGit2Sharp Refs.RewriteHistory) 해시만 바뀐다.
바꾸기 전 자리는 refs/original/날짜-시각/ 에 남긴다.

막는 자리(메뉴는 켜 두고 눌렀을 때 까닭과 푸는 길을 알림으로):
작업 중 · 커밋 안 한 변경 · 지금 브랜치 조상 아님 · 원격에 올라감 ·
다른 로컬 브랜치도 품음 · 구간에 태그 · 사이에 병합 커밋.
파일 비교 탭의 저장 안 한 편집은 우클릭해 줄을 고를 때 기존 창으로 묻는다.

- CommitReword (새): 막을 까닭 · 확인 글 · 완료 알림 · 새 메시지 다듬기
- GitService.InspectReword / RewordCommit, RewordInfo
- RewordWindow (새): 여러 줄 입력, [바꾸기] 는 기본 단추가 아님
- GitView: MergeHub 첫 우클릭 메뉴, 우클릭한 줄을 먼저 고른다
- 선택이 고친 커밋의 새 해시를 따라간다
- 화면에서 찾아 고침: 새 메시지가 끝 줄바꿈 없이 저장됐다 -> git -m 처럼
  다듬는다(뒤 커밋까지 다듬지 않게 새 메시지 하나만)

하네스 MergeSaveTest +40 (272건, 22벌 1,247건) · 빌드 경고 0 · 오류 0.
화면 확인: 되는 자리 1(트리 · 작성자 · 작성 시각 같음, 되돌리기 확인) ·
막는 자리 8 모두 막힘.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 10:34:58 +09:00
aa3f179390 11차 C-1(일부): [커밋 수정] 을 다시 내 보고 넷을 바로잡음
화면에서 여덟 가지를 먼저 재현하고, 방향이 정해진 1 · 3 · 4 · 7 만 고쳤다.

- [마지막 메시지] 는 이력 맨 위가 아니라 HEAD 커밋 메시지를 읽는다 (CommitSelection.MessageOfHead)
- 고쳐 써도 원래 작성자 · 작성 시각을 지킨다 (git 과 같게, 커밋한 사람만 지금)
- 병합 · rebase · cherry-pick · revert 중에는 단추를 끈다 (CanAmend) · 꺼진 까닭을 단추 설명으로
- 알림에 '커밋 수정 완료 (옛 bcd2c43 → 새 fd7810c) · 파일 1개 포함'
- GitWorkspace 가 HeadFullSha 를 들고 있는다
- 하네스 MergeSaveTest +15 (210 → 225), 22벌 1,200건 통과, 빌드 경고 0 오류 0

남은 결정: 2(스테이징 파일이 함께 들어가는 것) · 6(이미 올린 커밋). 8(여러 줄 메시지)은 범위 밖으로 적어 둠.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 16:58:59 +09:00
fadc000081 10차 F-3: 폴더 비교 "주석만 다름" 을 "다름(코드는 같음)" 으로
주석 · 공백을 걷어내고 견주는 판정이라 BOM · 줄끝 · 인코딩 · 끝 공백 · 빈 줄 · 들여쓰기만
다른 파일도 "주석만 다름" 이었다. 사용자: "이름을 바꿔줘". 판정 · 수는 그대로.

- 목록 · 범례(설명 붙임) · 요약 "다름 N(코드는 같음 M)" · 비교 결과 보고서
- 웹 문서의 이름도 바꿈(지난 기록은 그대로, 발행은 E-2)
- 하네스 FolderTest +1 (78건), 22벌 1,147건 통과, 빌드 경고 0 오류 0

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 16:05:13 +09:00
ccc657803b 10차 F-1 · F-2: 폴더 비교 "같은 것만" 에 다른 것처럼 보이던 줄
사용자가 시험 묶음 측정 화면에서 "같은 것만" 에 내용이 다른 파일이 보인다고 알림.
비교 판정은 설계대로(코드 값이 다르면 어느 설정에서도 다름)였고, 화면에서
- F-1: 같은 파일을 품은 폴더 줄이 폴더 자신의 상태 "다름"(주황)으로 보였다
- F-2: 설정(C# 스타일 맞춤 · 머지 주석 무시)으로 같음이 된 파일이 크기가 달라도 그냥 "같음"

- FolderComparer: SameReason 을 남기고 FolderStatusText 로 글자를 정함
- FolderViewModel: 같은 것만 · 왼쪽에만 · 오른쪽에만이면 폴더 줄을 "같음 122개" 처럼 걸린 수와 그 갈래 색으로
- FolderView: 줄 색이 DisplayStatus, 상태 칸 90 → 200
- 사용자 결정: 같음으로 두고 "같음(스타일만 다름)" · "같음(머지 주석만 다름)" 으로 표시
- 하네스 FolderTest +15 (77건), 22벌 1,146건 통과, 빌드 경고 0 오류 0

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 16:00:56 +09:00
5eaf6011dd 10차 B-1: Git 탭과 파일 비교 탭이 고른 커밋을 서로 바로 따라간다
두 탭이 같은 고른 커밋 값을 쓰는데 표시는 새로고침 전까지 안 따라왔다. 파일 비교 탭에서
'바탕' 을 고르면 Git 탭은 '내 쪽 작업' 에 선택 표시가 남은 채 [Revert] 가 '바탕' 을 되돌렸다.
사용자 결정: 바로 따라간다(양방향) · 저장 안 한 편집이 있으면 고르는 순간 묻는다.

- GitWorkspace: CommitChosen 알림, ConfirmLeaveCommit(null 안 물음 / true 계속 / false 취소)
- CommitSelection.IsOtherCommit (하네스 +4, MergeSaveTest 210)
- HomeViewModel: 다른 쪽이 고르면 게이트가 빈 뒤 목록 · 두 칸을 다시 세움, WillAskBeforeDiscard
- GitViewModel: 파일 비교 탭이 고르면 선택 표시 · 단추 따라감, 커밋 내용은 탭이 다시 보일 때
- GitView: 이력 목록이 선택을 바꾸기 전에(마우스 · 방향키) 묻고 [취소] 면 누름을 막음,
  물은 뒤 [계속] 이면 직접 고름

확인: 두 방향 · BASE 까지 따라감, 편집 있음 [취소] 두 탭 제자리 · 창 한 번,
[계속] 따라감 · 편집 버려짐, 방향키 같음, [Revert] 는 보이는 커밋, 9차 A-2 흐름 그대로.
22벌 1,126건 통과, 빌드 경고 0 오류 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 14:54:29 +09:00
aebfd6b089 7차 C-2: rebase · cherry-pick 충돌을 작업에 맞게 부르고 MergeHub 만으로 끝까지
화면이 모든 충돌을 "병합" 으로 불렀다 - rebase REMOTE 가 "THEIRS", cherry-pick 에 "병합 진행 중",
다 풀면 cherry-pick 을 끝낼 단추가 없고, 로그에 RebaseContinue() · Commit(), 다른 브랜치 커밋은 고를 수 없었다.
GitOperationState 로 칸 제목(올릴 자리 · 다시 올리는 내 커밋 · 가져오는 커밋) · 머리 글 · 진행 표시 ·
끝내기 단추(병합 커밋 · 계속 · 커밋)를 정한다. cherry-pick · revert 는 원래 메시지 · 작성자로 커밋.
머지 주석 자동 풀기 · 알림도 같은 뒷일. 이력 탭 [모든 브랜치].
rebase · cherry-pick 모두 줄끝 바뀐 파일 0, MergeSaveTest 125건 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 16:03:42 +09:00
1db788f1a0 7차 A-2: 병합 충돌 네 칸의 로그와 머리가 실제 쪽을 말한다
Take Theirs 로그가 3-Way 콤보 값을 써서 "10행 (3-Way 안 씀) 반영" 이었고, Take Mine 은 로그가 없었다.
이제 "10행 Theirs(feature/theirs) 반영" · "10행 Mine(feature/mine) 으로 정함".
충돌 네 칸이면 3-Way 콤보 대신 "병합 충돌 · REMOTE = 상대". 브랜치 3-Way 문구는 그대로.
MergeSaveTest 82건 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 17:24:10 +09:00
cbaf0996be 7차 E-2: 폴더 비교 화면에 폴더를 하나씩 놓으면 첫 칸 → 둘째 칸 차례로
화면 아무 데나 폴더 하나를 놓으면 늘 첫 칸에 들어가 두 번째 폴더가 첫 폴더를 덮어썼다.
DropSlotOrder 로 놓는 차례를 두고, 양쪽이 차면 바로 비교한다. 경로 칸 위에 놓은 것도 차례에 친다.
탐색기에서 끌어다 놓아 다섯 경우 확인. PathTest 62건 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 17:00:41 +09:00
26d9d042bf 7차 지시서 · E-1: 병합 중 [해결로 저장] 단추를 [Save] 로
LOCAL 칸을 이 파일에만 쓰고 스테이징하는 단추라 Save & Commit 과 짝이 되게 이름만 바꿈.
알림 · 막힘 안내 · 웹 문서도 Save. 하는 일은 그대로(충돌 24 → 23, 커밋 없음 확인).
7차 지시서: 6차 D-1 에서 걸린 세 가지(마지막 저장 뒤 남은 차이 · 로그 3-Way 안 씀 · 기록 파일 남음)와
pull · rebase · cherry-pick 충돌.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 16:35:41 +09:00
5856ca0436 6차 C-1: 결과 로그 한 번, 충돌 목록에 종류와 푼 개수
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 16:07:56 +09:00
aed24b9bfa C# 스타일 Default 를 Allman 으로 이름 바꿈 · 웹 문서(매뉴얼·발표·기획안·시연) 원본
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 14:09:50 +09:00
6bd2bb7619 C# 코드 스타일 맞춤(AURORA · Default)과 발표 시연 재료 demo 폴더
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 14:05:50 +09:00
eb43385e14 6차 B-6: 충돌 탭에서 여러 파일을 골라 Accept 를 한 번에, 다시 읽기는 끝에 한 번
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:55:53 +09:00
de097da2ff 6차 B-4 발견 두 건: 멀리 건너뛰어도 네 칸이 안 밀리고 mergetool 세 벌을 네 칸으로 연다
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:07:46 +09:00
ddce51d375 6차 B-4: 네 칸 줄 여백을 66px 로 넓혀 MERGED 줄 번호가 잘리지 않게 한다
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 12:47:34 +09:00
9b597fc50f 6차 B-1: 병합 뒤 목록이 바로 서고 충돌 목록에서 3분할로 연다
병합하고 파일 비교 탭으로 오면 목록이 병합 전 커밋 파일(304개) 그대로
였고, [새로고침] 을 한 번 더 눌러야 충돌 23개가 나왔다. 충돌 탭 목록을
두 번 눌러도 아무 일이 없었고, 안내 글은 없는 "홈 탭" 을 가리켰다.

원인: 새로고침은 게이트를 쥔 채 화면 목록을 갈아 끼우고, 끝나자마자
Git 탭이 게이트를 다시 잡는다. 파일 비교 화면이 그 틈에 목록을 세우려다
"다른 작업 진행 중" 으로 건너뛰었다.

- OnWorkspaceRefreshed: 게이트가 풀릴 때까지 기다렸다 목록을 세운다
- GitWorkspace.RequestOpenConflict: 충돌 파일을 파일 비교 탭에서 열어
  달라는 요청을 남겨 두고 탭을 옮긴다(폴더 비교의 넘겨주기와 같은 방식)
- OpenConflictAsync: 목록에 설 때까지 기다렸다 고른다. 이 요청 때문에
  화면이 새로 만들어졌으면 기본 저장소를 새로 열지 않는다
- 충돌 목록: 두 번 누르기(MouseDoubleClick), Enter, [3분할로 열기]
- 안내 글과 병합 알림의 "홈 탭" 을 실제 탭 이름으로

화면 확인 17건 통과(병합 뒤 목록 23개, 두 번 누르기와 단추와 Enter 로
네 칸, 파일 비교 탭을 안 연 새 앱에서도 열림, 병합 취소 뒤 Git 탭
새로고침만으로 목록 304개). 경고 0, 오류 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 11:36:16 +09:00
04b8ef8a60 6차 A-5: Accept Both 는 글로 이어 붙이고 누르기 전에 묻는다
양쪽이 같은 이름으로 새로 만든 파일에 Accept Both 를 누르면 묻지 않고
두 blob 을 바이트째 이어 붙였다. 결과 파일 한가운데에 BOM 이 하나 더
들어갔고 같은 class 가 두 번 나와 빌드가 안 됐다.

- BothJoin: 두 벌을 각자 제 인코딩으로 글로 풀어 이어 붙인 뒤 내 쪽
  형식(인코딩, BOM, 줄끝)으로 다시 쓴다. 규칙은 A-1 의 TextFile.Encode
- ResolveConflict(Both): 바이트 이어 붙이기 대신 BothJoin
- Git 탭 Accept Both: 먼저 묻는다(무엇이 일어나는지, 줄 단위로 둘 다
  넣으려면 3분할에서). 단추 도움말

Both 는 없애지 않았다. 이어 붙이는 게 맞는 파일도 있다.

화면 확인 14건 통과(묻기, 아니오면 그대로, 예면 BOM 1개와 CRLF 한
가지, 보통 충돌도 같음). EncTest 10건 추가. 21벌 785건 통과
(새로 빌드한 실행 파일). 경고 0, 오류 0. A 묶음 끝.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 11:06:14 +09:00
27798fa145 6차 A-4: 한쪽이 지운 충돌은 [파일 남기기] · [파일 지우기] 로 푼다
상대가 지운 파일(UD)이나 내가 지운 파일(DU)을 열면 줄 단위 3분할로
끌고 가서 지운 쪽 칸이 통째로 비었다. 범례는 내 쪽에만 있는 줄 89개를
"Theirs only 89" 라고 거꾸로 말했고, 정할 것인 "남길까 지울까" 는
화면 어디에도 없었다. 파일 단위 해결은 이미 바르게 동작했다.

- DeletionConflict: 어느 쪽이 지웠는지, 남기기와 지우기가 각각 어느
  쪽을 고르는 것인지(UD 는 남기기=내 것, DU 는 남기기=상대 것)
- LoadFileAsync: 지운 충돌이면 남은 파일을 BASE 와 두 칸으로 보인다.
  칸 제목이 누가 지웠는지 말하고, BASE 제목은 (merge base)
- 범례 위 띠: 누가 지웠고 누가 고쳤는지, [파일 남기기] [파일 지우기]
- 남기기는 고친 것이 있으면 고친 대로 남기고, 지우기는 고친 것이
  있으면 한 번 묻는다. 푼 뒤 남은 충돌 첫 파일로 간다
- 해결로 저장과 같은 뒷정리를 ReloadAfterResolveAsync 로 모았다

시험 저장소 생성기에 DU 경우를 넣었다(충돌 23개). 뿌리 폴더를 잡고
있는 셸 때문에 다시 만들기가 멈춰서 안만 비우게 고쳤다.

화면 확인 23건 + BASE 제목 고친 뒤 5건 통과. MergeSaveTest 16건 추가.
21벌 775건 통과(새로 빌드한 실행 파일). 경고 0, 오류 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 11:00:10 +09:00
0485c60745 6차 A-2: 병합 중에는 [해결로 저장] 을 따로 둔다
Save & Commit 이 쓰기, 스테이징, 커밋을 한 덩어리로 돌려서 남은
충돌은 마지막 커밋 단계에서야 막혔다. 화면은 실패라는데 파일은
이미 써지고 스테이징됐고(충돌 22 -> 21), 편집 상태도 안 치워서
다른 파일을 고를 때마다 확인 창이 다시 떴다.

- MergeSavePlan: 지금 커밋해도 되는지 판단만 따로 뺐다
- Save & Commit: 병합 중 다른 충돌이 남으면 아무것도 쓰기 전에 멈춘다
- [해결로 저장]: 병합 중에만 보인다. 이 파일만 쓰고 스테이징한다
- Ctrl+S: 병합 중이면 해결로 저장
- 확인 창의 "저장하고 계속": 병합 중 충돌 파일이면 충돌까지 푼다

화면에서 해 보다 둘이 더 나왔다.
- 게이트에 막혀 건너뛴 목록 불러오기가 빈 결과로 목록을 비웠다.
  건너뛰면 그대로 두고, 해결로 저장 뒤에는 게이트가 풀릴 때까지
  기다렸다 다시 세운다(WhenIdleAsync). 남은 충돌 첫 파일이 열린다.
- 충돌을 전부 Take Mine 으로 정하면 글이 안 바뀌어 저장할 수 없었다.
  3분할에서 충돌을 다 정했으면 고친 글이 없어도 저장할 수 있다.

화면 확인 25건 통과. MergeSaveTest 18건 추가, 21벌 716건 통과.
경고 0, 오류 0. 줄끝(A-1)은 아직 그대로다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 10:22:48 +09:00
26446d5e6b 5차 B-1: XAML 태그·속성·값을 갈라 칠한다
실제 소스에 XAML 이 400개 42,477줄인데 여태 주석과 따옴표만 알아봐서
사실상 평문이었다. 마크업 전용 토크나이저를 따로 뒀다.

기존 토크나이저에 못 얹은 까닭은 규칙이 다르기 때문이다. 그쪽은 낱말을
읽어 예약어 표와 맞춰 보는데, 마크업은 같은 Content 가 꺾쇠 안에서는
속성 이름이고 밖에서는 그냥 글자다. 낱말이 무엇이냐가 아니라 어디에
있느냐로 갈린다.

줄 넘김 상태를 bool 하나에서 깃발 묶음(CarryOver)으로 넓혔다. XAML 은
여는 태그가 여러 줄에 걸치는 것이 보통이라 - 시험에 쓴 실제 파일은 첫
태그 하나가 14줄이다 - "지금 꺾쇠 안이다"를 안 넘기면 이어지는 줄의
속성이 그냥 글자로 보인다. 부르는 자리 다섯을 모두 바꿨다.

색은 새로 만들지 않고 이미 있는 갈래에 얹었다. 태그는 예약어 색,
속성 이름은 메서드 색, 값은 문자열 색, 앞가지는 타입 색이다. 태그
밖의 본문은 일부러 안 칠한다.

붙이는 중에 파일 비교 화면이 통째로 비어서 뜨는 일이 있었다. 의존
속성 타입을 bool 에서 CarryOver 로 바꾸면서 기본값 false 를 같이 안
고쳤다. 빌드도 통과하고 로그에도 안 남는다. 같은 주의를 코드 옆에
적어 뒀다.

실제 저장소 XAML 사본(638줄)으로 화면 확인. C# 색칠은 그대로.
MarkupTest 65건. 전체 688건 통과(하네스 20벌). 경고 0 · 오류 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 16:01:58 +09:00
bad30f50e4 4차 C-5: ACTIONS 칸을 자주 쓰는 것과 한 번 정하는 것으로 나눔
저장 형식·비교 규칙·편집 잠금을 한자리에 모아 접었다. 차이 이동을 개수 옆으로 옮겼다.
지시서의 "폭이 넓어진다"는 틀렸다. 폭을 정하는 단추들이 접어도 남는 쪽이다.
2026-09-10 22:39:26 +09:00
27a8bfb275 C-4 다시: 범례가 눌러진다는 사실이 안 보였다
새 단추가 아니라 원래 항목이 눌러지는 것이라 찾을 수가 없었다.
항목마다 테두리를 주면 시끄러우므로 줄 머리에서 한 번만 말한다 - 색 구분 (눌러서 이동).
2026-09-10 22:29:57 +09:00
bc92676a49 4차 C-4: 색 구분 범례를 이동 도구로
개수를 누르면 그 갈래 줄로 가고 다시 누르면 다음 줄로 간다. 차이 이동과 같은 방식이다.
0건은 흐리게만 하고 숨기지 않는다. 자리가 움직이면 다시 찾아야 한다.
2026-09-10 22:18:06 +09:00
06d018742a C-3 다시: 접힌 것이 있다는 사실이 안 보였다
11px 회색에 화살표 하나로는 여기 접힌 것이 있다는 게 전해지지 않았다.
글자에 펴기/접기를 넣고 굵은 강조색으로 키웠다.
2026-09-10 22:10:11 +09:00
d8c8d6c6f7 4차 C-3: Git 탭의 원격 칸을 접는다
원격 저장소가 없어 전부 비활성인 세 줄이 위쪽 4분의 1을 차지했다. 지우지 않고 접었다.
새로고침은 로컬 작업이라 로컬 경로 줄로 옮겼다.
펼침 상태는 설정에 남기되 Browsable(false) 로 설정 화면에는 안 내놓는다.
2026-09-10 22:06:44 +09:00
cbf9e64539 4차 C-2: 아래쪽 정보를 창 아래 한 줄로
같은 뜻의 숫자가 세 군데에 있었다. 왼쪽은 어디, 가운데는 얼마나 남았나, 오른쪽은 무슨 파일인가.
패널 밖으로 나오면서 두 패널 코드 영역 높이가 저절로 같아진다.
2026-09-10 21:40:28 +09:00
9f0802e58f C-1: 경로를 읽으라고 적는다
늘 똑같은 BASE/LOCAL 이 크고 정작 경로가 회색 작은 글씨였다. 뒤집었다.
접두사를 빼고 본문 색 고정폭 12px 로, 갈리는 첫 칸만 굵은 강조색.
2026-09-10 21:30:29 +09:00
9d9fa40ddf 4차 C-1: 같은 경로가 세 군데 나오던 것
패널의 경로 줄과 위 툴바의 잘린 경로를 없애고 머리글 툴팁으로 모았다.
복사는 우클릭 메뉴로, 끌어다 놓는 자리는 단추로 옮겨 둘 다 지켰다.
2026-09-10 21:15:40 +09:00
8083075ece 4차 B-3: 폴더 비교에서 다음 다른 파일로
훑는 중인 목록을 GitWorkspace 에 두고 파일 비교 화면에서 이전/다음으로 딛는다.
화면에 보이는 순서를 따르고, 찾은 줄 목록도 같은 방식으로 훑는다.
먼저 묻고 자리를 옮긴다. Ctrl+PageUp/PageDown.
2026-09-10 20:49:46 +09:00
b9456b7f14 4차 B-1: 최근 비교 목록
파일 짝과 폴더 짝을 따로 15개까지 기억한다. 탭으로 나눈 글로 설정 폴더에 둔다.
없는 경로는 흐리게 보여 주고 지우지 않는다. 검사 33건 추가.
2026-09-10 20:43:14 +09:00
196af0a913 D-7 끌어다 놓기를 화면에서 확인하고 세 군데를 고쳤다
경로 칸(TextBox)이 Drop 을 먼저 먹어 놓아도 아무 일이 없었다 - Preview 로 옮겼다.
파일 비교의 경로 글자는 Background 가 없어 놓을 자리 자체가 없었다.
칸에 놓아도 다시 견주지 않던 것을 DropFile / DropFolder 로 고쳤다.
파일을 하나씩 놓아 짝을 만들 수 있게 했다.
검색 결과 칸에 머리글을 넣고 줄 간격을 목록과 맞췄다.
2026-09-09 15:32:52 +09:00
373990b3b6 D-7, D-3: 끌어다 놓기 · 폴더 안 전체 검색
D-7 은 코드만 끝났다. 화면이 잠겨 탐색기에서 끄는 확인을 못 했다.
D-3 은 UI 자동화로 검색·결과 열기·취소까지 확인했다.
2026-09-09 15:16:19 +09:00
ee5d34c2a6 D-6: 비교 결과 텍스트 내보내기
결과를 남에게 보내거나 결재에 붙일 때 화면을 캡처하는 것 말고는 방법이 없었다.
캡처는 검색도 안 되고 줄 번호를 짚어 말하기도 어렵다.

Services/CompareReport.cs 신설. 파일 비교와 폴더 비교 양쪽에서 쓴다. 글을
만드는 일만 여기서 하고, 어디에 저장할지 묻는 것은 화면 쪽 일이다. 그래야
화면 없이 검사한다.

파일 쪽은 요약과 다른 줄 목록을 적는다. 줄 번호는 양쪽을 다 적는다. 한쪽에만
있는 줄이 있어 번호가 어긋나므로 하나만 적으면 파일에서 그 줄을 찾을 수 없다.
폴더 쪽은 상태와 상대 경로를 줄마다 적는다. 폴더 자체는 적지 않는다. 그 안의
파일이 이미 다 적혀 있다.

곁들여 요약에 주석만 다른 수를 덧붙였다. "다름 3(주석만 1)". D-1 로 새로 생긴
갈래가 요약에는 안 보였다.

확인: 두 화면에서 각각 뽑아 메모장으로 열었다. ReportTest 23건 신설.
전체 451건 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 14:49:02 +09:00
451b6245cb D-1: 주석만 다른 파일을 다른 색으로
폴더 비교에 "주석만 다름" 상태를 새로 두었다. 코드는 같고 주석/공백만 다른
파일이다. 봐야 할 성격이 다르다. 주석만 손댄 파일은 눈으로 훑고 넘길 수
있는데 다른 것과 같은 색으로 섞여 있으면 전부 열어 봐야 한다.

판단은 주석 토큰을 걷어내고 공백을 지운 뒤 견주는 것이다. 주석 기호는 언어마다
다르므로 확장자로 고른 언어표를 따르고, 언어를 모르는 파일은 하지 않는다.
양쪽 확장자가 다르면 같은 언어로 볼 근거가 없으니 역시 하지 않는다.
줄 구분은 코드가 있는 줄에만 남긴다. 큰 파일은 건너뛴다.

곁들여 색 뜻풀이 줄을 목록 위에 붙이고, 보기 필터에 "코드가 다른 것만"을
더했다. 주석만 다른 것을 빼고 보는 쪽이 실제로 필요한 동작이다.

확인: 주석만 고친 .cs 는 회색 "주석만 다름", 값이 바뀐 .cs 와 평문 .txt 는
노란 "다름". "코드가 다른 것만"을 고르면 앞의 것이 빠진다.
FolderTest 4건 추가. 전체 428건 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 14:33:25 +09:00
4f33cacd4f E-5, E-6: 반영 색 유지 · 차이 이동 시 코드 겹침
E-5. 줄을 반영한 뒤 비교 규칙을 하나 건드리면 초록(머지 반영함)이던 줄이
보라(직접 수정)로 바뀌었다.

반영 표시가 되돌리기 스택에만 있었다. 규칙을 바꾸면 화면을 통째로 다시
만들면서 그 스택을 비운다. 그러면 표시가 사라지고 남는 단서는 "글이 원본과
다르다"뿐이라 직접 수정으로 칠해진다. B-3 에서 Take Mine 이 충돌을 못 지우던
것과 같은 뿌리다.

- 반영할 때 줄 번호로도 남긴다. BASE 줄 번호, 없으면 MINE 줄 번호.
- 다시 만들 때 반영 여부를 먼저 본다. 반영한 줄은 직접 수정 조건에도 걸린다.
- 되돌리면 그 기록도 함께 지운다.

곁들여 머지 주석 줄도 같은 이유로 보라색이 됐다. 주석 줄이라는 표시 역시 줄
객체에만 있어서 다시 만들면 사라진다. 글을 보고 알아보게 했다
(MergeNote.LooksLikeNote).

E-6. Alt+위/아래로 차이를 옮겨 다니면 칸 아래 상태바 위에 코드가 겹쳐
그려졌다. 표시층은 편집기 글자와 눈높이를 맞추려고 RenderTransform 으로 살짝
밀어 두는데, 그건 배치가 아니라 그리기라 칸 밖으로 나가도 막는 것이 없다.
격자의 행도 자기 칸 밖으로 나가는 자식을 자르지 않는다. 코드가 놓이는 자리를
자르는 상자로 감쌌다. 네 칸 모두.

확인: 반영 후 공백/Aa 규칙을 눌러도 머지 반영함 2 · 직접 수정 0 그대로.
Alt+아래 8회, Alt+위 6회 눌러도 마지막 줄이 경계에서 깨끗이 잘린다.
NoteTest 13건 추가. 전체 399 -> 412건 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 13:50:13 +09:00
05c74fcb0e C 묶음: 코드 툴팁 · 글자 잘림 · 폴더 복사 확인 창
C-1. 코드 위에 마우스를 올리면 그 줄 내용이 그대로 툴팁으로 다시 떴다. 글이
이미 보이는데 같은 글이 상자로 겹쳐 뜨니 가리기만 한다. 원본 세 칸에서 뺐다.
버튼과 상태 아이콘 툴팁은 그대로 둔다. 그쪽은 화면에 없는 정보를 알려 준다.

C-2. Git 탭 목록의 글자가 ... 없이 중간에서 뚝 끊겼다. 줄임표 설정은 이미
있었는데 듣지 않았다. 목록의 가로 스크롤이 켜져 있으면 항목이 제 글 길이만큼
넓게 잡히고, 그러면 잘릴 일이 없으니 줄임표도 나오지 않는다. 가로 스크롤을
끄면 항목이 칸 너비에 갇히고 그때 비로소 줄임표가 나온다. 커밋/변경 파일/
브랜치/충돌/태그/서브모듈 여섯 목록에 같이 걸었다.

"작업 취소" 버튼과 Git 탭 입력 칸이 잘리는 것은 재현하지 못했다. 2560x1600 과
1920x1080 에서 배율 100%/120% 로 여섯 하위 탭을 모두 봤지만 멀쩡했다.

C-3. 폴더 복사 확인 창을 윈도우 기본 대화상자에서 플랫폼 것으로 바꿨다.
글꼴도 색도 배치도 혼자 달라 "이 프로그램이 묻는 것"으로 읽히지 않았다.
묻는 것 자체는 없애지 않았다. 복사/삭제는 되돌릴 수 없다.

확인: 코드 위 3초 머물러도 툴팁 없음. 이력 목록이 ... 로 줄어듦. 폴더 복사
확인 창과 완료 토스트가 프로그램의 다른 알림과 같은 모양.
테스트 399건 그대로 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 13:24:03 +09:00
8def1add2a E-4: 2-Way 로 돌아오면 LOCAL 옆에 빈 칸이 남던 문제
3-Way 에서 구분선을 끌어 칸 폭을 바꾼 뒤 2-Way 로 돌아오면 LOCAL 오른쪽에 칸
하나만 한 빈 자리가 남았다. 구분선을 건드리지 않으면 멀쩡했다.

GridSplitter 는 끌고 나면 양옆 칸을 비율(star)이 아니라 고정 픽셀로 바꿔 놓는다.
그러면 창 크기가 바뀌어도 칸이 따라 늘지 않고, 2-Way 로 돌아와 REMOTE 칸이
접히면서 생긴 자리를 아무도 채우지 않는다. 늘어날 star 칸이 없기 때문이다.

- 구분선을 놓는 순간 고정 픽셀을 같은 비율의 star 로 되돌린다. 잡아 놓은 폭은
  유지되면서 창 크기를 따라간다.
- 2-Way <-> 3-Way 를 오갈 때는 세 칸의 폭 지정을 놓아준다. 배치가 통째로 다르고,
  REMOTE 칸은 폭을 Style 이 정하는데 끌어서 생긴 값이 남으면 2-Way 에서 접히지
  않는다.

확인: 3-Way 에서 구분선을 끌고 2-Way 로 돌아와도 두 칸이 폭을 꽉 채운다.
테스트 399건 그대로 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 11:40:07 +09:00
9a9c431b43 E 묶음: 세로 막대 · 폭 되돌림 · 머리 빈 공간
E-1. 원본 세 칸에 세로 스크롤 막대를 켰다.
가로와 달리 세로는 이 칸들이 실제로 굴러가므로 ScrollViewer 가 주는 막대를
그대로 쓴다. 대신 막대가 자리를 차지하는 만큼 여백 보정을 걷어냈다. 전에는
편집기 막대 폭만큼 오른쪽 여백을 줘서 글자 폭을 맞췄는데, 이제 진짜 막대가 그
자리를 차지하므로 여백까지 주면 글자 폭이 좁아져 접히는 자리가 어긋난다.

E-2. 칸 폭을 줄였다 늘리면 행 높이가 돌아오지 않던 문제.
행 높이는 각 칸이 알려 온 글 높이 중 가장 큰 것을 쓴다. 그런데 글자를 그리는
칸이 세로로 늘어나 있어서(WPF 기본값 Stretch) 행이 한 번 커지면 그 다음부터는
"행 높이만큼 높다"고 되돌려 보냈다. 자기가 만든 값을 자기가 다시 읽는 셈이라
높이가 올라가기만 하고 내려오지 않았다. 글자 칸을 위로 붙여 자기 글 높이만
알리도록 고쳤다.

E-3. 경로 줄과 코드 사이의 빈 공간.
패널 머리 높이를 상수로 못 박아 두어(124 / 74) 실제 내용보다 훨씬 컸다.
상수를 없애고 내용에 맞춰 줄어들게 한 뒤, 나란히 놓인 칸끼리는 SharedSizeGroup
으로 가장 큰 것에 맞춘다(REMOTE 만 Conflict 줄이 하나 더 있다). 2-Way 에서는
MERGED 머리도 같은 무리에 넣고 3-Way 에서는 뺀다.
2-Way 에서 한 화면에 보이는 코드가 29줄에서 34줄로 늘었다.

확인: 세로 막대를 끌면 세 칸이 함께 움직인다. 2560x1600 <-> 1920x1080 을
오가도, 가운데 구분선을 끌었다 되돌려도 처음과 같은 화면이 된다.
테스트 399건 그대로 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 11:29:56 +09:00
179dffb1ad B 묶음: 3-Way 화면 세 가지
B-1. 원본 세 칸에 가로 스크롤 막대 신설.
이 칸들은 ScrollViewer 를 가로로 굴리지 않고(줄 번호까지 밀려 나간다) 글자만
SourceShiftX 로 민다. 그래서 ScrollViewer 가 만드는 막대는 움직이지 않는
막대가 되어 감춰 두고 있었고, 긴 줄이 있다는 사실 자체를 알 수 없었다.
막대를 따로 놓고 SourceShiftX 와 값을 서로 맞춘다.

B-2. 워드랩을 켠 3-Way 에서 세로 스크롤이 아예 안 되던 문제.
원인이 둘이었다.
- 메아리를 막는 자물쇠를 try/finally 로 그 자리에서 풀고 있었다. 목록의 스크롤
  알림은 배치가 끝난 다음에 오므로 그때는 이미 열려 있었고, 그 메아리가 다시
  편집기를 굴렸다. 이제 그 일로 밀려서 오는 알림이 다 지나간 뒤에 푼다.
- 두 좌표계를 픽셀로 환산하고 있었는데, 목록이 가상화라 안 그려진 행의 높이를
  알 수 없어 환산이 어긋났다. 워드랩일 때는 행 단위로 굴려 "몇 번째 행이 맨
  위인가"만 주고받는다.
곁들여, 편집기 맨 위 행을 스크롤 값 나눗셈이 아니라 좌표로 물어본다.

B-3. Take Mine 을 눌러도 남은 충돌이 줄지 않던 문제.
"내 것으로 간다"는 결정은 글을 바꾸지 않아 되돌리기 스택에 남지 않는데,
RefreshAppliedFlags 가 스택만 보고 반영 표시를 다시 칠하면서 그 표시를 지웠다.
줄 번호로 기억해 둔 결정을 같이 보도록 고치고, 같은 판단을 IsDecidedAsMine
하나로 합쳤다.

확인: 막대 끌기/가로 휠/워드랩 토글, 워드랩 켠 채 네 칸이 같은 행을 맨 위에
놓는 것, 충돌 6개를 Take Mine/Theirs 번갈아 눌러 "충돌 정리 끝"까지.
테스트 399건 그대로 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 11:10:40 +09:00
93a507e3e8 A-5: Git 저장소 최상위를 고를 수 없던 문제
두 가지가 겹쳐 있었다.

하나. Git 탭의 폴더 고르기가 WinForms FolderBrowserDialog 였다. net48 에서는
주소 칸이 없는 옛날 트리 창이라 경로를 붙여넣을 수 없고, 지난번에 골랐던 깊은
폴더에서 최상위까지 손으로 거슬러 올라가야 했다.

둘. .git 은 최상위에만 있는데 LooksLikeRepository 가 고른 폴더 바로 밑만 봤다.
사람은 지금 보고 있던 깊은 폴더를 고르기 마련이라 멀쩡한 저장소를 두고
"저장소가 아니다"가 됐다.

- Services/FolderPicker.cs 신설. 폴더 고르기를 한 군데로 모았다(폴더 비교
  왼쪽/오른쪽, Git 저장소 경로, 변경분 추출 대상 폴더).
- PathUtil.FindRepositoryRoot 신설. 고른 자리에서 위로 올라가며 .git 을 찾는다.
  워크트리/서브모듈은 .git 이 파일이라 둘 다 본다. 안쪽에 저장소가 또 있으면
  가장 가까운 것을 잡는다.
- Git 탭과 시작 시 자동 열기가 같은 규칙을 쓴다.

확인: src\MergeHub\Views\GitView.xaml (네 단계 아래)을 골랐더니 경로가
D:\Sorce\MergeTool\MergeHub 로 바로잡히고 저장소가 열렸다.
PathTest 12건 추가(31 -> 43건). 전체 399건.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 09:52:17 +09:00
4029336b88 밖에서 부르기: 명령줄 인자 수신 · 탐색기 보내기 등록
git config 에 mergetool/difftool 로 등록하는 쪽은 전부터 있었는데 정작 그 인자를
받는 쪽이 없어 다리가 반만 놓여 있었다. 나머지 반쪽을 놓고, 탐색기에서도 부를 수 있게 했다.

- Services/StartupArgs: 켤 때 넘어온 인자를 읽는다.
  이름표 붙은 것(--merge --base B --local L --remote R --merged M)과 그냥 넘어온 경로
  둘 다 받는다. 경로가 폴더면 폴더 비교로, 파일이면 파일 비교로 보낸다.
  difftool 의 LOCAL/REMOTE 와 셸이 주는 "먼저 고른 것/나중 것" 은 뜻이 달라 따로 담는다 -
  이 도구의 왼쪽은 늘 "기준"이라 difftool 에서는 REMOTE 가 왼쪽이 된다.

- Services/ShellIntegration: 탐색기 "보내기" 메뉴에 바로가기를 둔다.
  처음에는 우클릭 메뉴에 바로 넣으려고 레지스트리에 정적 verb 를 등록했다
  (HKCU\Software\Classes\AllFilesystemObjects\shell\...). 키는 제대로 들어갔고
  HKEY_CLASSES_ROOT 에도 병합돼 보였는데 탐색기 메뉴에는 뜨지 않았다.
  확인해 보니 이 PC 에서 우클릭 메뉴에 나오는 다른 프로그램(Notepad++ · Git Bash ·
  WinMerge)은 전부 HKLM 에 등록돼 있었고, HKCU 에 넣은 것은 - 우리 것이든 확인용으로
  넣어 본 메모장 항목이든 - 하나도 그려지지 않았다. HKLM 은 관리자 권한이 필요해 쓸 수 없다.

  그래서 보내기(SendTo)로 갔다. %APPDATA%\Microsoft\Windows\SendTo 에 바로가기 파일
  하나를 두는 것이 전부라 레지스트리도 권한도 필요 없고 윈도우 판을 타지 않는다.
  한 단계 더 들어가는 것이 유일한 단점인데, 대신 여러 개를 골라 한 번에 보낼 수 있어
  미뤄 두었던 "파일 두 개 골라 비교" 가 덤으로 따라왔다.
  등록/해제할 때 예전 판이 레지스트리에 남긴 흔적도 같이 지운다.

  셸 확장 DLL 은 쓰지 않았다 - DLL 은 탐색기 프로세스 안에서 돌아 잘못되면 탐색기가 죽는다.

- GitWorkspace.RouteStartupArgs 가 요청을 화면으로 보낸다. 창이 다 만들어진 뒤에 탭을
  옮겨야 해서 ApplicationIdle 로 미루고, 요청 자체는 남겨 두어 늦게 만들어진 화면이
  스스로 집어 가게 했다(폴더 비교 쪽도 파일 비교와 같은 방식으로 추가).

- 곁들여: 파일 비교가 "양쪽 경로가 모두 있을 때만" 열리고 있었다. 셸은 하나만 줄 수도
  있으므로 한쪽만 있어도 열도록 고쳤다 - 없는 쪽은 빈 내용이 되어 전부 추가로 보인다.

ArgsTest 26건 신설. 전체 356건 통과.
실행 확인: 폴더 경로로 켜면 폴더 비교 탭에 그 폴더가 왼쪽에, 파일 두 개로 켜면 파일 비교
탭에 나란히. 등록 버튼을 누르면 보내기 메뉴에 항목이 생기고 버튼 이름이 "탐색기 보내기
해제" 로 바뀐다(실제 탐색기 메뉴에서 확인).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 17:25:42 +09:00
49a05a0628 밖에서 부르기: 명령줄 인자 수신 · 탐색기 우클릭 등록
git config 에 mergetool/difftool 로 등록하는 쪽은 전부터 있었는데 정작 그 인자를
받는 쪽이 없어 다리가 반만 놓여 있었다. 나머지 반쪽을 놓는다.

- Services/StartupArgs: 켤 때 넘어온 인자를 읽는다.
  이름표 붙은 것(--merge --base B --local L --remote R --merged M)과 그냥 넘어온 경로
  둘 다 받는다. 탐색기는 "%1" 하나만 주므로 후자가 그 자리다. 경로가 폴더면 폴더 비교로,
  파일이면 파일 비교로 보낸다.
  difftool 의 LOCAL/REMOTE 와 탐색기의 "먼저 고른 것/나중 것" 은 뜻이 달라 따로 담는다 -
  이 도구의 왼쪽은 늘 "기준"이라 difftool 에서는 REMOTE 가 왼쪽이 된다.

- Services/ShellIntegration: 탐색기 우클릭 메뉴를 파일·폴더·폴더 배경 세 자리에 넣는다.
  HKEY_CURRENT_USER 에만 쓰므로 관리자 권한이 필요 없고, 지울 때도 이 사람 것만 지운다 -
  사내 PC 에 권한 없이 깔리는 것이 전제다. 셸 확장 DLL 을 만들지 않은 것도 같은 이유로,
  DLL 은 탐색기 프로세스 안에서 돌아 잘못되면 탐색기가 통째로 죽는다.
  폴더 배경에서는 %1 이 아니라 %V 가 그 폴더다.

- GitWorkspace.RouteStartupArgs 가 요청을 화면으로 보낸다. 창이 다 만들어진 뒤에 탭을
  옮겨야 해서(그 전에는 옮길 곳이 없다) ApplicationIdle 로 미루고, 요청 자체는 남겨 두어
  늦게 만들어진 화면이 스스로 집어 가게 했다(폴더 비교 쪽도 파일 비교와 같은 방식으로 추가).

- 곁들여: 파일 비교가 "양쪽 경로가 모두 있을 때만" 열리고 있었다. 탐색기는 하나만 주므로
  한쪽만 있어도 열도록 고쳤다 - 없는 쪽은 빈 내용이 되어 전부 추가로 보인다.

ArgsTest 26건 신설. 전체 356건 통과.
실행 확인: 폴더 경로로 켜면 폴더 비교 탭에 그 폴더가 왼쪽에, 파일 두 개로 켜면
파일 비교 탭에 나란히. 등록 버튼을 누르면 레지스트리 3개 키가 생기고 버튼 이름이
"탐색기 우클릭 해제" 로 바뀐다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 16:56:56 +09:00
55d9deb418 이진 파일·그림 비교 (Services/BinaryCompare)
"줄 단위로 비교할 수 없습니다" 한 줄로 끝내면 정작 알고 싶은 "같은지 다른지" 를
모른 채 화면을 닫게 된다. 답이 있는 화면으로 바꿨다.

- 크기 · SHA-1 · 처음 갈리는 바이트 위치를 한 줄로 알려 준다. 크기가 같아도 내용이
  다를 수 있어 해시로 본다. 앞부분이 같고 길이만 다르면 짧은 쪽이 끝나는 자리가
  갈리는 지점이다.
- 그림(.png/.jpg/.bmp/.gif/.ico/.tif)이면 나란히 띄운다 - 16진으로 보는 것보다 훨씬 빠르다.
- 그 밖에는 앞 4KB 를 16진으로 나란히 놓고, 16바이트 단위로 다른 줄에만 색을 준다.
  볼 수 있는 글자는 오른쪽 칸에 그대로 적는다 - 16진만 보면 무슨 파일인지 모른다.
  수십 MB 짜리를 전부 그리면 화면이 굳으므로 앞부분만 그리고 잘렸다고 알린다.

BinaryTest 25건 신설(같음·가운데 다름·길이 다름·16진 표기·줄 수 제한·글자 칸·
없는 파일·그림 판별). 전체 330건 통과.

실행 확인: .bin 두 개 -> "다릅니다 · 왼쪽 17 B · 오른쪽 19 B · 처음 갈리는 곳 0x10"
+ 16진 두 줄(0x10 줄만 색). .png 두 개 -> 나란히 표시.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 14:50:11 +09:00
de1a43cc70 파일 비교: 바꾸기(Ctrl+H) · 덩어리 단위 반영 · 저장 형식 고르기
- 바꾸기: 찾기 칸 아래에 바꿀 말 줄이 붙는다. Ctrl+F 로 열면 안 뜬다 -
  찾기만 할 때 자리를 뺏지 않기 위해서다. "바꾸기" 는 고른 자리가 찾는 말일 때만
  바꾸고 다음으로 넘어간다 - 엉뚱한 자리를 덮어쓰는 것보다 한 번 더 누르게 하는 편이 낫다.
  "모두" 는 한 번에 바꾸고 몇 개인지 알려 준다(되돌리기는 편집기의 Ctrl+Z 가 맡는다).
- 덩어리 단위 반영: 줄 하나씩만 되면 연속 다섯 줄을 다섯 번 눌러야 한다.
  WinMerge·Beyond Compare 가 덩어리를 기본 단위로 쓰는 이유다. 덩어리는
  "차이로 잡힌 줄이 이어지는 구간"이고, 캐럿이 그 안에 있을 때만 켜진다. Alt+Shift+→.
- 저장 형식: 사내 소스에 CP949 로 저장된 파일이 섞여 있어 새로 만드는 파일과 형식이
  갈린다. 읽어서 보여 주기만 하면 그 갈림을 못 고치므로 저장할 때 고를 수 있게 했다.
  기본값 "원본 유지" 라 지금까지와 동작이 같다. Save & Commit 경로도 같은 값을 쓴다
  (전에는 File.WriteAllText 로 UTF-8 고정이었다).

실행 확인: PulseUs → PulseMicros 2개 바꿈 · 마지막 차이에서 2줄 한 번에 반영.
단축키 61 → 63건, 전체 305건 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 14:44:08 +09:00
524a6a715d 폴더 비교: 폴더째 복사·삭제 · 보기 필터 · 비교 취소
비교만 되고 정리는 안 되던 화면이었다. 셋을 채워 "보고 → 고르고 → 맞춘다" 까지 닫는다.

- 폴더째 복사·삭제: 파일 하나씩만 되던 것을 폴더에도 열었다. 확인 창에 안에 든
  파일 수를 적는다 - "폴더 하나"라고만 물으면 몇 개가 덮이는지 모르는 채 확인을
  누르게 된다. 복사는 겹치는 파일만 덮고 대상에만 있던 파일은 남긴다(동기화가 아니다).
- 보기 필터: 다른 것만 / 전체 / 왼쪽에만 / 오른쪽에만 / 같은 것만.
  다시 비교하지 않고 마지막 결과로 목록만 다시 그린다 - 큰 폴더를 다시 훑는 것은
  필터를 만지는 값으로 너무 비싸다. 기존 "같은 파일도 보기" 체크는 이 필터가 대신한다.
- 비교 취소: FolderComparer.Compare 에 CancellationToken 을 넣고 항목마다 확인한다.
  누르는 즉시 멈추고, 앞서 본 결과는 그대로 둔다(실패가 아니라 사용자의 결정이다).

설계 하나 - 파일을 실제로 옮기고 지우는 부분을 Services/FileOps.cs 로 뺐다.
되돌릴 수 없는 일이라 화면 없이 검사할 수 있어야 한다.

실행 확인: sub(파일 2개) 폴더째 복사 → b\sub\deep\two.txt 까지 따라옴.
목록 15개 → "왼쪽에만" 5개(요약 줄은 그대로 = 다시 비교하지 않음).
FolderTest 27 → 37건(취소 3 · 파일 세기 2 · 폴더 복사 5). 전체 300건 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 11:20:55 +09:00
85c5e9e085 3-Way 를 "끝낼 수 있게" 만들기 (자동 병합 · 충돌만 이동 · 완료 판정)
지금까지는 안 겹치는 변경까지 사람이 하나씩 눌러야 해서, 정작 판단이 필요한
서너 줄이 그 속에 묻혔다. git merge 가 자동으로 해 주는 일을 여기서도 해 준다.

- 자동 병합: 저쪽만 고친 줄(ThreeWayState.RemoteChanged)을 한 번에 가져온다.
  충돌과 내가 고친 줄은 건드리지 않는다. 이미 가져온 줄은 더 이상 RemoteChanged 가
  아니므로 여러 번 눌러도 안전하다.
- 충돌만 이동: Alt+Shift+↑↓. "다음 차이" 와 달리 아직 안 정한 충돌만 딛는다.
- 완료 판정: ACTIONS 에 "남은 충돌 N개"(빨강) → "충돌 정리 끝"(초록).

판단이 하나 필요했다 - 충돌 여부는 BASE·MINE·REMOTE 를 견주면 저절로 나오지만,
"내 것으로 간다"고 정한 줄은 내용이 그대로라 여전히 충돌로 보인다. 그래서
MergeLine.NeedsDecision(충돌이면서 반영·수정 표시가 없는 줄)을 따로 두었다.
그 결정은 글을 바꾸지 않아 편집 뒤 재정렬하면 사라지므로, 얼어 있는 BASE 줄 번호
(없으면 MINE 줄 번호)로 붙들어 되살린다.

곁들여 고친 것: Take Mine / Take Theirs 버튼이 줄을 옮겨도 켜짐·꺼짐이 그대로였다.
CommunityToolkit 커맨드는 CommandManager 를 구독하지 않는데 이 둘만 갱신 목록에서
빠져 있었다 - 키보드(Alt+←/→)로는 되고 버튼만 안 되던 이유다.

실행 확인(mergehub-demo, 3-Way = feature/cooling): 자동 병합으로 Theirs only 1→0,
다음 충돌+Take Theirs 를 반복해 남은 충돌 3→2→1→"충돌 정리 끝".
테스트 290 → 293건 전부 통과(단축키 3건 추가).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 10:49:28 +09:00
9956567bf8 Git 탭에 다섯 기능 추가 (amend · stash 목록 · 커밋 간 비교 · blame · 변경분 추출)
기획안 4p 의 "Git 조작" 항목 중 화면에 없던 것들을 채웠다. 다섯 중 넷은
GitService 에 이미 구현돼 있었고 버튼만 없던 것이라, 서비스를 새로 만든 것은
변경분 추출 하나뿐이다.

- 커밋 수정(amend): 오타 난 메시지나 빠뜨린 파일을 새 커밋을 쌓지 않고 바로잡는다.
  고쳐 쓸 메시지를 처음부터 다시 치지 않게 "마지막 메시지" 버튼을 곁들였다.
- stash 목록: 저장/적용만 있어 "맨 위 것"에만 손이 닿았다. 골라서 적용·삭제한다.
  하나 꺼내면 번호가 한 칸씩 당겨지므로, 목록이 바뀌면 고른 항목을 다시 잡는다 -
  안 그러면 다음 삭제가 엉뚱한 것을 지운다.
- 두 커밋 사이 비교: "여기부터" 로 시작점을 잡으면 그 뒤 고르는 커밋이 끝점이 된다.
  안 잡으면 지금까지처럼 부모와 비교한다(기존 동작 유지).
- blame: 머지 중에 "이 줄 왜 이렇게 됐지"를 묻게 되는데, 이력을 뒤지는 것보다 빠르다.
- 변경분 파일 추출: 장비에 소스를 통째로 넣지 못하는 현장에서 바뀐 것만 들고 갈 때 쓴다.
  텍스트로 다시 쓰면 줄바꿈과 인코딩이 바뀌므로 바이트 그대로 옮긴다.

곁들여 고친 것: 상태 배지 줄의 ItemHeight 가 24 로 묶여 있어 "mergetool 등록"
버튼이 반쯤 잘려 보였다. 줄 높이는 내용이 정하게 두었다.

실행 확인(데모 저장소): 메시지 수정으로 sha 가 바뀜 · stash 저장→목록→적용으로
워킹트리 복구 · 헤더가 "2766bc5 → 6e6bb78 (2개 파일)" · blame 31줄 전부 표시 ·
변경분 2개 파일 추출.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 10:35:45 +09:00
7719094edf 최초 커밋: MergeHub (사내 Git Merge/Diff 도구)
UbisamBase 플랫폼 위에서 도는 플러그인. 지금까지 만든 것을 그대로 담는다.
- 폴더 비교 / 파일 비교(부분 수용·워드랩·찾기) / 3-Way 병합 / Git 조작
- 비교 엔진: histogram 정렬 · 이동 블록 감지 · 무시 규칙 · 13개 언어 토크나이저
- doc/ 에 작업 지시서와 진행 기록

빌드 산출물(bin/obj)은 추적하지 않는다 - 플랫폼 런타임이 빌드 때마다
D:\UbisamPlatform\bin 에서 복사되어 들어오므로 저장소에 담을 이유가 없다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 10:13:27 +09:00