19 Commits

Author SHA1 Message Date
5710e522bb 9차 A-2: HEAD 를 보고 있었으면 커밋 뒤 새 HEAD 를 따라간다
8차 E-1 에서 한 번 다른 브랜치 커밋이 기준이 된 것은 A-1 과 뿌리가 같았다
(새로고침에서 선택을 놓치면 목록 맨 위로 채움). A-1 대로 해시만 지키자
cherry-pick [커밋] 뒤 선택이 옛 HEAD 에 남아 방금 커밋한 줄이 "남은 차이 6줄" 로 보였다.

- CommitSelection.Choose(previousHeadSha): HEAD 를 보다가 HEAD 가 움직이면 새 HEAD
- GitWorkspace: 지난 새로고침의 HEAD 를 들고 있다
- 하네스 MergeSaveTest +5 (206건), 22벌 1,117건 통과, 빌드 경고 0 오류 0

확인: 8차 E-1 cherry-pick 순서([모든 브랜치] 켬)를 여섯 번 - 시작 · 파일 단위 = 고른 커밋,
마지막 Save 뒤 = HEAD, [커밋] 뒤 = 새 HEAD · 차이 없음. 다른 브랜치 커밋이 잡힌 회차 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 11:31:30 +09:00
9fffc40dbe 9차 A-1: 작업 중 충돌을 다 풀면 두 칸 기준을 HEAD 로 · 요약이 기준과 같은 말
cherry-pick 마지막 [Save] 뒤 두 칸의 기준이 고른 커밋 · 다른 브랜치 커밋 · HEAD 중
하나로 그때그때 달랐는데 요약은 늘 "내 쪽 대비" 라고 했다(8차 E-1 N1 · N1-덧).
새로고침이 이력 목록을 갈아 끼우며 선택을 놓치면 목록 맨 위로 채웠고,
[모든 브랜치] 에서 맨 위는 HEAD 가 아니었다.

- CommitSelection: 작업 중 충돌이 막 0 이 되면 HEAD, 아니면 해시로 되찾고 없으면 HEAD
- GitWorkspace.ReadState: 목록을 갈아 끼우기 전에 고른 해시를 적어 둔다
- ResolvedSummary(baseIsHead): 기준이 HEAD 일 때만 작업 글
- 하네스 MergeSaveTest +18 (201건), 22벌 1,112건 통과, 빌드 경고 0 오류 0

확인: cherry-pick([모든 브랜치]) · revert 마지막 Save 뒤 기준 HEAD, 제목 "가져오기 전 내 쪽",
요약 "내 쪽 대비 … 6줄" = git diff 대조. 사람이 고른 커밋은 새로고침 세 번에도 그대로.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 10:57:57 +09:00
d25f374a0e 8차 F-1: 병합 커밋 본문에 충돌 해결 내역을 자동으로 적기
충돌 탭 파일 단위 Accept 는 소스에 주석이 안 남고, 병합 커밋 본문은 비어 있었고,
Git 탭 로그는 끄면 사라져 누가 어느 파일을 어떻게 풀었는지 남는 곳이 없었다(사용자 요청).

- MergeResolutionLog: 기록 파일(첫 줄 MERGE_HEAD) 읽기 · 쓰기, 본문 만들기, 메시지에 붙이기
- GitService: 병합 중일 때만 .git/MERGEHUB_RESOLUTIONS 에 적고, CommitMerge 가 본문을 붙인다.
  병합 커밋 · 작업 취소 · 새로고침 때 쓸모없는 기록을 치운다
- 충돌 탭 Accept Mine/Theirs/Both · [Save] · Save & Commit · 파일 남기기/지우기 · 머지 주석 자동이 적는다
- Git 탭 메시지 칸에 본문을 미리 채우고, 풀 때마다 새로 채운다(사람이 고치면 두고 커밋 때 붙임)
- 하네스 MergeSaveTest 183건(21건 추가), 22벌 1,094건 통과

확인: 병합 "충돌 해결 26개 · 김승준"(줄 단위 7 · Theirs 15 · 남기기 1 · 지우기 1 · 주석 자동 2),
pull 26개, Accept Mine 기록 뒤 [작업 취소] 로 기록 파일 없음. 줄끝 · BOM 0/33, 회귀 없음.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 09:33:32 +09:00
90f662ba9b 8차 B-2: 가져올 것이 없으면 [커밋] 을 끄고 나가는 길을 말한다
이미 들어 있는 커밋을 cherry-pick 하면 [커밋] 이 켜졌고, 누르면 로그에
"[cherry-pick 커밋] 실패: No changes; nothing to commit." 만 남았다. 진행 줄도 그대로였다.

- GitService.HasStagedChanges() 를 두고 적용 로그 · 커밋 앞 막음에 쓴다
- GitWorkspace.PendingHasChanges 를 상태로 들고, 진행 줄이 그 값을 본다
- CanFinishOperation 은 cherry-pick · revert 에서 커밋할 것이 있어야 켜진다
- 병합 커밋은 트리가 같아도 정상이라 걸지 않는다
- 하네스 MergeSaveTest 155건(진행 줄 7건), 18벌 921건 통과

확인: HEAD 커밋을 다시 cherry-pick → [커밋] 꺼짐 · "가져올 변경이 없습니다 - [작업 취소] 로 끝냅니다" ·
[작업 취소] 로 빠져나옴. 충돌 24건짜리 보통 cherry-pick 은 그대로 커밋까지(원래 메시지).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 13:44:07 +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
bb6bd655a5 7차 B-1: 병합이 끝나면 .git/MERGEHUB_CONFLICTS 를 치운다
병합 때 적는 처음 충돌 목록이 병합 커밋 · 작업 취소 · 터미널에서 끝낸 병합 뒤에도 남았다.
MERGE_HEAD 가 없거나 다른 병합의 것이면 병합 커밋 · 작업 취소 직후와 상태를 다시 읽을 때마다 지운다.
병합 중에는 그대로라 "푼 것 M개 (M/전체)" 는 이어진다. 세 경우 화면에서 확인, MergeSaveTest 88건 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 17:34:10 +09:00
5856ca0436 6차 C-1: 결과 로그 한 번, 충돌 목록에 종류와 푼 개수
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 16:07:56 +09:00
de097da2ff 6차 B-4 발견 두 건: 멀리 건너뛰어도 네 칸이 안 밀리고 mergetool 세 벌을 네 칸으로 연다
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 13:07:46 +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
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
238910634c 5차 A-2: Git 작업을 시작하는 자리에서 묻는다
커밋·체크아웃 뒤에 저장 안 한 편집이 말없이 사라지던 것을 막았다.

막는 자리를 옮겼다. 목록을 다시 세우는 자리(RefreshCommits →
LoadCommitAsync)가 아니라 Git 작업이 시작되는 문(GitWorkspace.
RunAndRefreshAsync)에서 묻는다. 그 순간에는 아직 아무것도 바뀌지
않았으므로 취소가 뜻을 가진다.

작업을 가려서 묻는 쪽은 접었다. fetch·태그·스테이징처럼 파일을 안
건드리는 열두 가지는 안 물으려 했는데, 해 보니 그런 작업 뒤에도
편집이 사라졌다. 파일이 그대로여도 저장소를 다시 읽으면서 본문을
새로 그리기 때문이다. 다시 그리지 않게 막는 쪽도 해 봤지만 고른
파일까지 바뀌는 경우가 있어 조건을 세울 수 없었다. 잃지 않는 쪽으로
갔다 - 확인 창은 고치던 것이 있을 때만 뜨고, 틀려도 한 번 더 묻는
것으로 끝난다. 알아낸 열두 이름은 KnownSafeCandidates 에 남겼다.

덤으로 4차 A-1 이 새던 자리 셋을 막았다. 목록을 다시 세우면 화면이
값을 되밀어 넣는데, 그것을 사람이 고른 것으로 보고 확인 창을 띄우고
있었다. OnSelectedNodeChanged(null·같은 커밋), OnRemoteBranchChanged
(_syncingBranches), Files.Clear()(_suspendGuard 안으로).

화면 시험 10건 통과(데모 저장소). GitOpTest 36건. 전체 623건 통과
(하네스 19벌). 빌드 경고 0 · 오류 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-11 13:21:33 +09:00
d8c8d6c6f7 4차 C-3: Git 탭의 원격 칸을 접는다
원격 저장소가 없어 전부 비활성인 세 줄이 위쪽 4분의 1을 차지했다. 지우지 않고 접었다.
새로고침은 로컬 작업이라 로컬 경로 줄로 옮겼다.
펼침 상태는 설정에 남기되 Browsable(false) 로 설정 화면에는 안 내놓는다.
2026-09-10 22:06:44 +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
373990b3b6 D-7, D-3: 끌어다 놓기 · 폴더 안 전체 검색
D-7 은 코드만 끝났다. 화면이 잠겨 탐색기에서 끄는 확인을 못 했다.
D-3 은 UI 자동화로 검색·결과 열기·취소까지 확인했다.
2026-09-09 15:16:19 +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
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
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