제품 코드 변경 없음. doc/web/index.html 이 6차에서 멈춰 있었다. - 매뉴얼: 창 크기 조절 · 이름 창 잠금 · 폴더 끌어다 놓기 차례 · 작업별 네 칸 제목과 머리 글 · MERGED 줄 번호(결과 파일 번호) · pull · rebase · cherry-pick · revert 가 같은 길 · 빈 cherry-pick 안내 - "알아 둘 한계": 7차 · 8차에서 사라진 네 줄을 빼고, 파일 단위 Accept 의 줄끝 · 스냅 한계를 넣음 - 남은 일: 7차에서 고친 것 · 8차에서 고친 것 두 표 + 8차에 남은 것(E-1) - 숫자: 하네스 22벌 1,073건 · 로컬 커밋 94 · 문서 기준일 2026-09-16 - 발행된 아티팩트도 같은 내용으로 갱신(버전 7) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
347 lines
27 KiB
Markdown
347 lines
27 KiB
Markdown
# 8차 — 고른 파일에 고른 내용을 · 작업마다 화면이 사실대로 (2026-09-16 ~)
|
||
|
||
지시서: [../작업지시/8차.md](../작업지시/8차.md). 7차 D-1 에서 새로 걸린 넷과 7차에서 남긴 것 · 웹 문서.
|
||
|
||
## A-1. 고른 충돌 파일 대신 다른 파일이 보이고, 그 화면을 저장하면 고른 파일에 써진다 (2026-09-16, 완료)
|
||
|
||
### 고치기 전에 다시 났다 (새로 만든 저장소, MergeHub 로 병합)
|
||
|
||
파일 비교 탭을 **한 번도 열지 않은 채** Git 탭 충돌 목록에서 `Common/Util/Unit47.cs` 를 고르고 [3분할로 열기].
|
||
|
||
| 확인 | 결과 |
|
||
|---|---|
|
||
| 파일 비교 탭 화면 | **`(merge base) Common/Util/Unit15.cs`** — 고른 파일이 아니라 첫 충돌 파일 |
|
||
| [다음 충돌] → Take Theirs → [Save] | 눌린다 |
|
||
| git | **`M Common/Util/Unit47.cs`** · `UU Common/Util/Unit15.cs` |
|
||
| 스테이징된 `Unit47.cs` 내용 | **123줄 · `public sealed class Unit15`** — Unit15 의 내용(고른 줄 · 머지 주석까지)이 Unit47 에 써졌다 |
|
||
| 로그 | `충돌 해결(직접 편집, UTF-8 (BOM) · CRLF): Common/Util/Unit47.cs` |
|
||
| 저장 뒤 화면 | 30초 동안 Unit15 · "남은 충돌 1개" 그대로 |
|
||
|
||
7차 D-1 에서 병합 · pull 둘 다 이렇게 났다(그때는 파일 비교 탭을 먼저 열어 두고 네 길을 확인했다).
|
||
|
||
### 원인
|
||
|
||
파일 비교 화면은 **탭을 처음 열 때 만들어진다.** 그때 두 가지가 겹친다.
|
||
|
||
1. 목록 세우기(`RebuildListAfterRefreshAsync` → `LoadCommitAsync`)가 첫 파일(`Unit15`)을 읽는다.
|
||
2. 넘겨받은 요청(`DeliverPendingOpenConflict` → `OpenConflictAsync`)이 고른 파일(`Unit47`)을 고른다.
|
||
|
||
`LoadFileAsync` 는 읽기가 끝난 뒤 **늦게 끝난 결과를 `IsGitMode` 로만 버렸다.** 읽기 시작한 경로가 지금 고른 파일과 같은지는 보지 않았다
|
||
(같은 자리 주석이 "경로는 새 파일인데 내용은 옛 파일" 을 이미 겪었다고 적고 있었다 - 데모 전환에서).
|
||
그래서 Unit15 의 내용이 화면을 덮었고, [Save] 는 화면 내용을 **지금 고른 파일**(Unit47)에 썼다.
|
||
|
||
### 고친 것
|
||
|
||
| 파일 | 무엇 |
|
||
|---|---|
|
||
| `Services/MergeSavePlan.cs` | `IsStaleLoad(읽은 경로 · 읽은 커밋, 지금 경로 · 지금 커밋)` — 읽는 사이에 파일 · 커밋이 바뀌었으면 버린다. `ShownFileMismatch(화면에 실린 파일, 저장할 파일)` — 다르거나 실린 것이 없으면 까닭을 돌려준다 |
|
||
| `ViewModels/HomeViewModel.cs` | `_shownFile` — **화면에 실제로 실린 파일**. `LoadFileAsync` 는 행을 만들기 전과 화면에 옮기기 직전 두 곳에서 `IsStaleLoad` 로 버리고, 실을 때 `_shownFile` 을 적는다. 버린 뒤 화면이 지금 고른 파일과 다르면 `ReloadWhenShownIsStale` 로 **한 번 더 읽는다**(되풀이 방지 플래그). `ClearPanes` 는 `_shownFile` 을 지운다 |
|
||
| 〃 | 쓰기 세 길(`SaveAndCommitAsync` · `SaveResolvedAsync` · `DecideDeletionAsync`)이 **아무것도 쓰기 전에** `ShownFileMismatch` 로 막고 알린다 |
|
||
| 하네스 `MergeSaveTest` | 검사 15건 — 같은 파일 · 다른 파일 · 다른 커밋 · 선택 없음 · 경로 구분자 · 대소문자 · 해시 대소문자, 저장 막기(같음 · 다름 · 두 이름이 까닭에 들어감 · 화면이 빔 · 저장할 파일이 빔) |
|
||
|
||
읽기 쪽만 고치고 끝내지 않았다. 되돌릴 수 없는 쓰기 앞에 문을 하나 더 뒀다.
|
||
|
||
**고치는 중에 한 번 더 걸렸다.** 버리기만 했더니 [3분할로 열기] 로 처음 열 때 **화면이 빈 채로** 남았다(단추도 없음).
|
||
버린 뒤 다시 읽는 `ReloadWhenShownIsStale` 을 넣어 고쳤다.
|
||
|
||
### 확인한 것 (길마다 저장소를 새로 만들어, 파일 비교 탭을 미리 열지 않고)
|
||
|
||
| 길 | [3분할로 열기] 뒤 화면 | Save 뒤 git | 스테이징된 Unit47 안의 class |
|
||
|---|---|---|---|
|
||
| 병합 | **`(merge base) Common/Util/Unit47.cs`** · 남은 충돌 1개 · REMOTE `feature/theirs` | `M Unit47.cs` · `UU Unit15.cs` | **Unit47** |
|
||
| pull | 같음 | 같음 | **Unit47** |
|
||
| rebase | 같음 · REMOTE `다시 올리는 내 커밋 1839bd3` | 같음 | **Unit47** |
|
||
| cherry-pick | 같음 · REMOTE `가져오는 커밋 f707175` | 같음 | **Unit47** |
|
||
|
||
이어서 **병합을 사람 순서 그대로 끝까지**(파일 비교 탭을 미리 열지 않고) 했다.
|
||
|
||
| 확인 | 결과 |
|
||
|---|---|
|
||
| 파일 단위 Accept Theirs 15개 | 24 → 9, 1.0초 |
|
||
| 3분할로 푼 파일 | NewPanel · Unit47 · 한글설명 · LineEnding · Unit0(6) · 띠 둘 · View250 · Unit1(6) — 저장할 때마다 다음 파일이 저절로 열림 |
|
||
| 마지막 Save 뒤 | `12b0402 · Weld/Unit1.cs · 병합 전 내 쪽` · 충돌 정리 끝 · 병합 커밋을 할 수 있습니다 · 내 쪽 대비 받은 변경 3줄 (7차 A-1 그대로) |
|
||
| 병합 커밋 | `3ba6314` 부모 둘 · `Merge branch 'feature/theirs' into feature/mine` · 워킹트리 Clean |
|
||
| 줄끝 · BOM · 인코딩이 첫 부모와 다른 파일 | **0 / 33** · 충돌 표식 0줄 |
|
||
| class 이름이 파일 이름과 다른 Unit 파일 | **0** |
|
||
|
||
하네스 18벌 906건 통과(MergeSaveTest 140). 빌드 경고 0 · 오류 0. 설정 파일은 바이트 그대로 되돌림.
|
||
|
||
### 남긴 것
|
||
|
||
- 자동 조작 쪽: Save 직후 찍은 화면이 Git 탭이라 파일 비교 탭 제목이 빈 것으로 읽혔다. 화면은 제대로였다(스크린샷).
|
||
- 7차 D-1 때 넣은 우회(파일 비교 탭을 먼저 한 번 열기)는 스위치(`D7_NO_PREOPEN`)로 껐다 켤 수 있게 두었다. 8차 E-1 은 끈 채로 한다.
|
||
|
||
## B-1. rebase · cherry-pick 에서 마지막 저장 뒤 "남은 차이" 가 뜬다 (2026-09-16, 완료)
|
||
|
||
### 고치기 전에 다시 났다 (길마다 저장소를 새로 만들어)
|
||
|
||
마지막 한 파일(`Weld/Unit1.cs`)만 남기고 23개를 파일 단위로 풀고, 남은 하나를 네 칸에서 Take Theirs 6번 → [Save].
|
||
|
||
| 길 | 파일 비교 탭 | 충돌 탭 |
|
||
|---|---|---|
|
||
| rebase | `bbdc66e · Weld/Unit1.cs` · **남은 차이 6줄** | 충돌 정리 끝 - [계속] 으로 rebase 를 이어 갑니다 |
|
||
| cherry-pick | `30c2133 · Weld/Unit1.cs` · **남은 차이 6줄** | 충돌 정리 끝 - [커밋] 으로 cherry-pick 을 끝냅니다 |
|
||
| 병합 (회귀) | `c3691b2 · Weld/Unit1.cs · 병합 전 내 쪽` · 충돌 정리 끝 · 병합 커밋을 할 수 있습니다 · 내 쪽 대비 받은 변경 6줄 | 같은 말 |
|
||
|
||
두 화면이 다른 말을 한다. 방금 받아 놓은 6줄이 "아직 할 일" 로 읽힌다 — 7차 A-1 과 같은 증상인데 병합에서만 고쳐져 있었다.
|
||
|
||
### 원인
|
||
|
||
7차 A-1 에서 만든 `MergeSavePlan.ResolvedMergeSummary` · `MergeBaseHeader` 가 **병합 전용**이었다.
|
||
화면도 `_workspace.IsMergeInProgress`(MERGE_HEAD 기준)로 물었다. rebase 는 MERGE_HEAD 가 없고 cherry-pick 은 `CHERRY_PICK_HEAD` 라 둘 다 "병합 중이 아님" 이 되어 보통 요약("남은 차이 N줄")으로 떨어졌다.
|
||
7차 C-2 에서 만든 작업 상태(`GitOperationState` · `OperationLabels`)를 쓰지 않고 있었다.
|
||
|
||
### 고친 것
|
||
|
||
| 파일 | 무엇 |
|
||
|---|---|
|
||
| `Services/OperationLabels.cs` | `ResolvedSummary(작업, 남은 충돌, 차이 줄)` — 끝말은 진행 줄과 같은 `FinishHint`(병합 커밋 · [계속] · [커밋])를 쓴다. 차이 줄은 작업마다 무엇인지 적는다(받은 변경 · 올린 변경 · 가져온 변경 · 되돌린 변경). `BaseHeader(작업, 짧은해시, 경로)` — 병합 "병합 전 내 쪽", rebase **"올릴 자리"**, cherry-pick "가져오기 전 내 쪽", revert "되돌리기 전 내 쪽" |
|
||
| `Services/MergeSavePlan.cs` | 병합 전용이던 `ResolvedMergeSummary` · `MergeBaseHeader` 를 걷어냈다(글은 위로 옮김) |
|
||
| `ViewModels/HomeViewModel.cs` | 요약 · BASE 제목이 `IsMergeInProgress` 대신 **`IsOperationInProgress` · `OperationState.Kind`** 를 본다 |
|
||
| 하네스 `MergeSaveTest` | 병합 글이 예전과 같은지 6건 + 작업별 요약 · 제목 10건 |
|
||
|
||
### 확인한 것 (같은 순서로 다시)
|
||
|
||
| 길 | 마지막 Save 뒤 파일 비교 탭 | 충돌 탭 |
|
||
|---|---|---|
|
||
| rebase | **`3e51519 · Weld/Unit1.cs · 올릴 자리`** · **충돌 정리 끝 · [계속] 으로 rebase 를 이어 갑니다 · 올릴 자리 대비 올린 변경 6줄** | 같은 말 |
|
||
| cherry-pick | **충돌 정리 끝 · [커밋] 으로 cherry-pick 을 끝냅니다** | 같은 말 |
|
||
| 병합 (회귀) | `d091ca2 · Weld/Unit1.cs · 병합 전 내 쪽` · 충돌 정리 끝 · 병합 커밋을 할 수 있습니다 · 내 쪽 대비 받은 변경 6줄 | 같은 말 |
|
||
|
||
cherry-pick 의 BASE 제목에 꼬리가 없는 것은 맞다 — 그때 BASE 는 HEAD 가 아니라 **이력에서 고른 가져올 커밋**이라
|
||
"가져오기 전 내 쪽" 이라고 하면 틀린 말이 된다(제목은 `14a9476 · Weld/Unit1.cs`, HEAD 는 `45bdbf5`).
|
||
|
||
하네스 18벌 914건 통과(MergeSaveTest 148). 빌드 경고 0 · 오류 0. 설정 파일은 바이트 그대로 되돌림.
|
||
|
||
## B-2. 바뀌는 것 없는 cherry-pick 에서 [커밋] 이 켜지고 누르면 실패한다 (2026-09-16, 완료)
|
||
|
||
### 고치기 전에 다시 났다 (새로 만든 저장소, 이력에서 HEAD 커밋을 골라 [Cherry-pick])
|
||
|
||
| 때 | 결과 |
|
||
|---|---|
|
||
| [Cherry-pick] | 로그 `cherry-pick 적용됨 - 확인한 뒤 충돌 탭의 [커밋] 으로 끝냅니다.` · `.git` 에 `CHERRY_PICK_HEAD` |
|
||
| 충돌 탭 | 머리 `cherry-pick 진행 중` · 진행 줄 **`충돌 정리 끝 - [커밋] 으로 cherry-pick 을 끝냅니다`** · **[커밋] 켜짐** |
|
||
| [커밋] 을 눌러 봄 | 로그 **`[cherry-pick 커밋] 실패: No changes; nothing to commit.`** · HEAD 그대로 · 알림은 읽히지 않음 |
|
||
| 그 뒤 | 진행 줄 · [커밋] 이 그대로라 **같은 단추를 또 누르게 된다.** [작업 취소] 로는 빠져나온다 |
|
||
|
||
### 원인
|
||
|
||
- 끝내기 단추(`CanFinishOperation`)는 "작업이 진행 중 · 충돌 0" 만 봤다. **커밋할 것이 있는지는 보지 않았다.**
|
||
- 진행 줄(`OperationLabels.ProgressText`)도 충돌이 0 이면 무조건 "끝낼 수 있다" 고 말했다.
|
||
- 시작 로그(`BuildPatchResult`)는 적용 결과가 `Applied` 면 늘 "확인한 뒤 [커밋] 으로 끝냅니다" 였다.
|
||
- 실제로 막은 것은 libgit2 였고, 그 말(`No changes; nothing to commit.`)이 로그에 그대로 나왔다.
|
||
|
||
### 고친 것
|
||
|
||
| 파일 | 무엇 |
|
||
|---|---|
|
||
| `Services/GitService.cs` | `HasStagedChanges()` — 인덱스가 HEAD 와 다른가. cherry-pick 적용 로그가 이걸 보고 **"cherry-pick 했지만 가져올 변경이 없습니다 - [작업 취소] 로 끝냅니다."** 로 적는다(revert 는 "되돌릴"). `CommitPendingOperation` 은 커밋 전에 같은 것을 보고 사람 말로 막는다 |
|
||
| `Services/IGitService.cs` | 선언 |
|
||
| `Services/GitWorkspace.cs` | `PendingHasChanges` — 상태를 읽을 때 함께 읽어 둔다. 진행 줄이 이 값을 쓴다 |
|
||
| `Services/OperationLabels.cs` | `ProgressText(…, hasChanges)` — 충돌 0 인데 가져올 것이 없는 cherry-pick · revert 는 **"가져올(되돌릴) 변경이 없습니다 - [작업 취소] 로 끝냅니다"**. 병합 · rebase 는 따지지 않는다(병합 커밋은 트리가 같아도 정상이다) |
|
||
| `ViewModels/GitViewModel.cs` | `CanFinishOperation` — cherry-pick · revert 는 커밋할 것이 있어야 켜진다 |
|
||
| 하네스 `MergeSaveTest` | 진행 줄 검사 7건(없음 · revert · 있음 · 충돌 남음 · 병합 · rebase · 기본값이 예전과 같은지) |
|
||
|
||
**병합 커밋에는 걸지 않았다.** 처음에 `CommitMerge` 에도 같은 막음을 넣었다가 뺐다 — 병합은 가져올 변경이 없어도(양쪽이 같게 고친 경우 등) 커밋이 정상이다.
|
||
|
||
### 확인한 것 (저장소를 새로 만들어)
|
||
|
||
| 경우 | 결과 |
|
||
|---|---|
|
||
| ① HEAD 커밋을 다시 [Cherry-pick] | 로그 **`cherry-pick 했지만 가져올 변경이 없습니다 - [작업 취소] 로 끝냅니다.`** · 진행 줄 **`가져올 변경이 없습니다 - [작업 취소] 로 끝냅니다`** · **[커밋] 꺼짐** · [작업 취소] 켜짐 |
|
||
| ① [작업 취소] | `CHERRY_PICK_HEAD` 없어짐 · 머리 표시 · 진행 줄 사라짐 |
|
||
| ② 회귀 - 충돌 24건짜리 보통 cherry-pick | 충돌 중 [커밋] 꺼짐 → 다 풀면 진행 줄 `충돌 정리 끝 - [커밋] 으로 cherry-pick 을 끝냅니다` · [커밋] 켜짐 → 누르면 `cherry-pick 커밋: e35f7b7 상대 쪽 작업`(부모 하나 · 원래 메시지) |
|
||
|
||
하네스 18벌 921건 통과(MergeSaveTest 155). 빌드 경고 0 · 오류 0. 설정 파일은 바이트 그대로 되돌림.
|
||
|
||
### 정하지 않은 것
|
||
|
||
- git 의 `--allow-empty` 처럼 **빈 cherry-pick 을 커밋으로 남기는 길**은 지시서대로 두지 않았다. 사용자와 정한 뒤에 넣는다.
|
||
|
||
## B-3. MERGED 칸 줄 번호가 결과 파일 번호가 아니다 (2026-09-16, 완료)
|
||
|
||
**정한 것 (2026-09-16, 사용자)** — 두 가지를 보이고 골랐다. ① 결과 파일 번호로(고름) ② 지금처럼 내 쪽 번호로 두고 그렇다고 적기.
|
||
결과 파일 번호는 상태바 · [이동] 칸 · 코드 검사의 "N행" 과 같은 기준이다.
|
||
|
||
### 고치기 전에 다시 났다 (새로 만든 저장소, 병합 중 `Motion/Unit0.cs` 를 네 칸으로)
|
||
|
||
충돌 6개를 Take Theirs 하면 고른 줄 · 머지 주석으로 결과가 늘어난다.
|
||
|
||
| 확인 | 값 |
|
||
|---|---|
|
||
| 상태바 | **총 3369줄** |
|
||
| [이동] 칸에 3369 | 3369행으로 감 |
|
||
| **MERGED 칸 끝 번호** | **3363** — 여섯 줄이 모자란다 |
|
||
| LOCAL (Mine) 칸 끝 번호 | 3361 (내 파일 그대로 · 맞다) |
|
||
|
||
### 원인
|
||
|
||
MERGED 칸 번호는 `MergeLine.LocalNumber` 인데, 이 값은 **정렬기가 짝지을 때 한 번 정해지고 그대로**다.
|
||
머지 주석 줄은 새로 끼워 넣으면서 번호를 주지 않았고(`Lines.Insert`), 그 뒤의 줄들도 번호를 다시 매기지 않았다.
|
||
그래서 결과가 길어질수록 어긋난다.
|
||
|
||
### 고친 것
|
||
|
||
| 파일 | 무엇 |
|
||
|---|---|
|
||
| `Services/MergedNumbering.cs` (새 파일) | `Assign(결과에 들어가는가[])` — 결과에 들어가는 줄만 1부터 센다. `Count` — 결과 줄 수 |
|
||
| `ViewModels/HomeViewModel.cs` | `RenumberMerged(rows)` — 줄 목록에 결과 번호를 다시 매긴다. 두 줄 만들기(두 칸 · 네 칸) 끝과 **요약을 그릴 때마다**(고르기 · 편집 · 되돌리기 · 주석 끼우기 뒤) 부른다 |
|
||
| 하네스 `MergeSaveTest` | 번호 검사 7건(결과에 없는 줄 · 끝 번호 = 결과 줄 수 · 빈 목록 · null 등) |
|
||
|
||
결과 파일은 `BuildLocalText` 가 `HasLocal` 인 줄만 이어 붙인 것이라, 번호도 같은 기준으로 센다.
|
||
LOCAL (Mine) 칸은 `OriginalLocalNumber`(내 파일 번호)를 그대로 쓴다 — 바꾸지 않았다.
|
||
|
||
### 확인한 것 (같은 순서로 다시)
|
||
|
||
| 확인 | 값 |
|
||
|---|---|
|
||
| 상태바 | 총 3369줄 |
|
||
| **MERGED 칸 끝 번호** | **3369** (3352 ~ 3369) |
|
||
| [이동] 칸에 3369 | 3369행 |
|
||
| **[Save] 한 뒤 워킹트리 파일** | **3369줄** — 화면 번호와 같다 |
|
||
| LOCAL (Mine) 칸 | 3346 ~ 3361 그대로 |
|
||
|
||
하네스 18벌 928건 통과(MergeSaveTest 162). 빌드 경고 0 · 오류 0. 설정 파일은 바이트 그대로 되돌림.
|
||
|
||
## C-1. revert 충돌을 화면으로 끝까지 (2026-09-16, 완료)
|
||
|
||
7차 C-2 에서 revert 는 rebase · cherry-pick 과 같은 길을 쓰게 했지만 **화면으로 끝까지 해 본 적이 없었다.**
|
||
|
||
### 시험 재료를 먼저 만들었다 (생성기 `C1Repo`, 같은 씨앗)
|
||
|
||
revert 가 충돌을 내려면 되돌릴 줄을 **뒤이어 또 고친 커밋**이 있어야 한다. 갈래를 하나 더했다.
|
||
|
||
- `feature/revert` = `내 쪽 작업` 위에 `뒤이은 수정` 하나. 같은 줄 충돌 15개 파일과 큰 파일 `Motion/Unit0.cs` 의 같은 자리를 또 고친다.
|
||
- 기존 경우(병합 · pull · rebase · cherry-pick)는 그대로다 — `feature/mine` · `feature/theirs` 를 건드리지 않았다.
|
||
- git 으로 미리 재 보니 그 위에서 `내 쪽 작업` 을 revert 하면 **충돌 16개**다.
|
||
|
||
### 확인한 것 (MergeHub 만으로)
|
||
|
||
| 때 | 결과 |
|
||
|---|---|
|
||
| 이력에서 `내 쪽 작업` 을 골라 [Revert] | 알림 **`충돌 16건 - … 다 풀면 [커밋] 으로 revert 를 끝냅니다.`** · 로그 `revert 시작: c579a81 내 쪽 작업` → `revert 충돌 16건 - 풀고 나서 충돌 탭의 [커밋] 으로 끝냅니다.` |
|
||
| 충돌 중 | 머리 **`revert 진행 중`** · [작업 취소] 켜짐 · 진행 줄 `남은 충돌 16개` · 끝내기 단추 **[커밋]**(꺼짐) |
|
||
| 네 칸 (`Motion/Unit0.cs`) | LOCAL `feature/revert` · REMOTE **`REMOTE · 되돌리는 커밋 c579a81 내 쪽 작업`** · 머리 글 **`revert 충돌 · REMOTE = 되돌리는 커밋 c579a81`** · "3-Way 안 씀" 없음 |
|
||
| 줄을 고르면 | 로그 **`101행 Theirs(커밋 c579a81) 반영`** (6줄) |
|
||
| 나머지 15개 파일 단위 Accept Theirs | git 충돌 15 → **0** |
|
||
| 다 푼 뒤 | 진행 줄 **`충돌 정리 끝 - [커밋] 으로 revert 를 끝냅니다`** · [커밋] 켜짐 · 커밋 메시지 칸 **`Revert "내 쪽 작업"` + `This reverts commit c579a81…`** |
|
||
| [커밋] | 로그 `revert 커밋: acefbcd Revert "내 쪽 작업"` · 부모 하나 · 진행 표시 · [작업 취소] 사라짐 · 워킹트리 Clean |
|
||
| 결과 | `Common/Util/Unit15.cs` 가 **바탕과 같아짐** · 되돌린 글("내가 고침") 0개 파일 · `REVERT_HEAD` 없음 |
|
||
| 바이트 | 바뀐 파일 36개 · **줄끝 · BOM · 인코딩이 부모와 다른 파일 0** · 충돌 표식 0줄 · class 이름이 다른 Unit 파일 **0** |
|
||
|
||
### 알게 된 것 · 남긴 것
|
||
|
||
- **충돌 난 16개 파일에서는 `뒤이은 수정` 의 글도 함께 사라진다.** 그 줄들을 전부 Accept Theirs(되돌리는 쪽)로 골랐기 때문이다 — 고른 대로다.
|
||
뒤 커밋의 글을 지키려면 그 줄만 Take Mine 으로 고르면 된다.
|
||
- 자동 조작 쪽: 첫 확인에서 파일 단위 Accept Theirs 가 15개 중 1개만 풀었다(목록 선택이 앱에 안 닿음 - 7차 C-2 와 같은 증상).
|
||
충돌이 0 이 될 때까지 되풀이하도록 스크립트를 고쳐 다시 했다. 제품 결함이 아니다.
|
||
- 제품 코드는 한 줄도 바꾸지 않았다. 7차 C-2 에서 만든 길이 revert 에서도 그대로 동작했다.
|
||
|
||
## C-2. cherry-pick 이 원래 작성자를 남기는지 눈으로 (2026-09-16, 완료)
|
||
|
||
7차 C-2 에서는 시험 저장소의 커밋 작성자가 모두 같아(`시험`) **코드로만** 확인했다.
|
||
|
||
### 시험 재료 (생성기 `C1Repo`, 같은 씨앗)
|
||
|
||
`상대 쪽 작업` 커밋만 **다른 사람이 쓴 것**으로 뒀다 — 작성자 `박지훈 <jihoon@localhost>` · 커밋한 사람 `시험 <test@localhost>`.
|
||
저장소의 `user.name` 은 그대로 `시험` 이라, 앱이 커밋하면 커밋한 사람은 `시험` 이 된다.
|
||
|
||
### 확인한 것 (같은 저장소를 새로 만들어, MergeHub 와 git 을 따로)
|
||
|
||
| 무엇 | 작성자 | 커밋한 사람 |
|
||
|---|---|---|
|
||
| 가져올 커밋 (`상대 쪽 작업`) | **박지훈** `<jihoon@localhost>` | 시험 |
|
||
| **MergeHub** cherry-pick → [커밋] | **박지훈** `<jihoon@localhost>` | 시험 `<test@localhost>` |
|
||
| **git** cherry-pick (사본에서 같은 순서) | **박지훈** `<jihoon@localhost>` | 시험 `<test@localhost>` |
|
||
| **MergeHub** revert → [커밋] | 시험 `<test@localhost>` | 시험 `<test@localhost>` |
|
||
| **git** revert (사본에서) | 시험 `<test@localhost>` | 시험 `<test@localhost>` |
|
||
|
||
**둘이 같다.** cherry-pick 은 원래 작성자를 남기고 커밋한 사람만 지금 사용자로 바뀐다. revert 는 둘 다 지금 사용자다 — git 과 같은 규칙이다.
|
||
|
||
이력 목록에도 그 커밋이 `상대 쪽 작업 dddd515 · 박지훈` 으로 보여, 고를 때 누가 쓴 것인지 화면에서 읽힌다.
|
||
|
||
제품 코드는 바꾸지 않았다.
|
||
|
||
### 남긴 것
|
||
|
||
- 자동 조작 쪽: git 으로 revert 를 견줄 때 **MergeHub 가 이미 revert 한 뒤의 저장소를 복제해** git 이 되돌릴 것이 없었다.
|
||
저장소를 새로 만들어 git 쪽만 다시 쟀다(위 표의 값).
|
||
|
||
## C-3. 창 크기 조절에서 안 본 것 (2026-09-16, 완료 · 플랫폼)
|
||
|
||
7차 E-4 에서 "스냅 · 첫 Win+↓ · 덮는 창 가운데 · 1px 테두리" 네 가지를 남겨 뒀다. 실제 픽셀로 재고, 정할 것은 사용자와 정했다.
|
||
|
||
**정한 것 (2026-09-16, 사용자)**
|
||
- 첫 Win+↓ 는 두 번 누르기 복원과 **같은 크기 · 자리**로.
|
||
- 최대화일 때 덮는 창(이름 · 확인 · 잠금 확인)도 **창 가운데**로.
|
||
- 보통 크기 창의 1px 테두리 선은 **그대로 둔다**(Windows 가 그리는 선 - 창 경계가 보여 끌기 쉽다).
|
||
|
||
### 고치기 전에 쟀다 (2560×1600@150% · 1920×1080@100% 두 모니터)
|
||
|
||
| 확인 | 값 |
|
||
|---|---|
|
||
| 첫 Win+↓ (기억 없음) | **2400×1350px @(266,266)** — 1600×900 DIP(XAML 기본). 아래로 **16px 화면 밖**, 작업 표시줄도 가림 |
|
||
| 이름 창 (최대화 창 2560×1600) | 가운데에서 **세로 36px 위** — 작업 표시줄 높이(72px)의 절반 |
|
||
| 이름 창 (보통 크기 창) | 어긋남 0 (이때는 맞았다) |
|
||
| Win+← 주 모니터(150%) | 1920×1528px = 1280×1018.7 DIP — 화면 반(1280px)이 아니라 **75%**. 최소 폭 1280 DIP 때문 |
|
||
| Win+← 옆 모니터(100%) | 1280×1032px — 반(960px)보다 큼. 같은 까닭 |
|
||
| Win+↑ (왼쪽 스냅 상태에서) | 1280×720px — Windows 11 의 네 분할 자리인데 최소 크기라 그만큼 커진다 |
|
||
|
||
### 고친 것 (플랫폼)
|
||
|
||
| 파일 | 무엇 |
|
||
|---|---|
|
||
| `Shell/ShellWindow.xaml.cs` | 최대화로 **들어갈 때** 기억 여부를 잡아 둔다(`normalBeforeMaximize`) — 복원할 때 보면 늦다. 크기 알림이 상태 알림보다 먼저 와서 방금 내려온 기본 크기가 "사용자가 고른 보통 크기" 로 기억돼 버린다. 기억이 없던 복원은 `RestoreTarget(work, useRemembered: false)` 로 **작업 영역 80% · 가운데**. 기억이 있어도 화면 밖으로 걸치면 `KeepInside` 로 끌어들인다 |
|
||
| `Shell/OwnerCentering.cs` (새 파일) | 덮는 창을 본 창의 **실제 사각형** 가운데에 놓는다. WPF 의 `CenterOwner` 는 최대화 창의 "복원 자리" 를 기준 삼아 어긋난다. 맞출 창이 없으면(켤 때 이름 창이 셸보다 먼저 뜬다) **모니터 전체** 가운데 — 셸의 최대화가 작업 표시줄까지 덮으므로 그 가운데와 같다 |
|
||
| `Settings/UserNameDialog.xaml.cs` · `Messaging/MessageDialog.xaml.cs` · `Locking/LockConfirmDialog.xaml.cs` | 다 그려진 뒤(`ContentRendered`) 위 도우미를 부른다. `Loaded` 때는 높이가 아직 없어(SizeToContent) 그냥 돌아갔다 |
|
||
|
||
### 확인한 것 (실제 픽셀 · 배포본으로 다시)
|
||
|
||
| 확인 | 고치기 전 | 고친 뒤 |
|
||
|---|---|---|
|
||
| 첫 Win+↓ (기억 없음) | 2400×1350 @(266,266) · 화면 밖 16px | **2048×1222 @(256,153)** = 작업 영역 80% · 가운데 · 화면 밖 0 |
|
||
| 두 번 누르기 복원 | 작업 영역 80% | 같음 (둘이 같아졌다) |
|
||
| 이름 창 · 최대화 창 | 세로 36px 위 | **어긋남 가로 0 · 세로 0** |
|
||
| 이름 창 · 보통 크기 창 | 0 | **0** (그대로) |
|
||
| 보통 크기로 [종료] → 다시 켜기 | - | 기억 `{256,153,2048,1222,최대화 false}` 대로 뜬다 |
|
||
| 화면 이동 | DIP 크기 지킴 | 같음(1280×1019 DIP) |
|
||
|
||
PlacementTest 37건 통과. 플랫폼 빌드 경고 0 · 오류 0. **배포는 사용자 확인 뒤 `publish-platform.ps1`** 로 했고,
|
||
MergeHub 를 다시 빌드해 배포본으로 같은 값을 다시 쟀다(앱 폴더 Core = 배포본 확인).
|
||
|
||
### 남긴 것 (고치지 않음)
|
||
|
||
- **스냅은 화면 반쪽이 될 수 없다.** 최소 크기(1280×720 DIP)가 반쪽보다 크기 때문이다 — 주 모니터에서 75%, 옆 모니터에서 67%.
|
||
최소 크기를 줄이지 않는 한 그대로다. Windows 11 의 네 분할도 같은 까닭으로 1280×720 이 된다.
|
||
- 왼쪽 스냅 상태에서 Win+→ 는 스냅을 풀지 않고 그대로 있었다(잰 두 번 중 한 번은 복원됐다). Windows 쪽 동작이라 두고 본다.
|
||
- 1px 테두리 선은 사용자 결정대로 그대로 둔다.
|
||
- **화면 잠금은 재지 않았다.** 잠그면 사람이 직접 풀어야 해서 확인이 멈춘다. 잠금 확인 창은 이름 창과 같은 길(`OwnerCentering`)을 쓰므로 함께 맞는다.
|
||
|
||
## D-1. 웹 문서를 7차 · 8차에 맞게 (2026-09-16, 완료)
|
||
|
||
`doc/web/index.html` 이 6차에서 멈춰 있었다. 7차 · 8차에서 바뀐 화면과 말을 맞추고, "알아 둘 한계" 를 지금 기준으로 다시 썼다.
|
||
|
||
### 고친 것
|
||
|
||
| 어디 | 무엇 |
|
||
|---|---|
|
||
| 개요(숫자) | 검사 하네스 **22벌 · 1,073건**(948건에서), 로컬 커밋 **94**(75에서), "7차 끝 · 8차 진행 · 네 길 줄끝 바뀐 파일 0". 출처를 `작업지시/8차.md` 로 |
|
||
| 매뉴얼 · 켜기 | 이름을 저장하기 전에는 그 창이 닫히지도 움직이지도 않는다(7차 E-3). **창 크기** 문단 추가 — 끌어 조절(최소 1280 × 720) · 두 번 누르기 · <kbd>Win</kbd>+<kbd>↑</kbd>/<kbd>↓</kbd> · 최대화는 작업 표시줄까지 덮음 · 크기 · 모니터 기억 · [화면 이동] 이 크기를 지킴(7차 E-4 · 8차 C-3) |
|
||
| 매뉴얼 · 폴더 비교 | 끌어다 놓기 **첫 칸 → 둘째 칸 차례**, 두 칸이 차면 바로 비교(7차 E-2) |
|
||
| 매뉴얼 · 네 칸 | 네 칸이 뜨는 경우를 작업별로 — rebase 는 LOCAL 이 올릴 자리 · REMOTE 가 다시 올리는 내 커밋, cherry-pick 은 가져오는 커밋, revert 는 되돌리는 커밋. 3-Way 콤보 자리의 머리 글. **MERGED 번호는 결과 파일 번호**(8차 B-3)와 줄 고른 로그 문구(7차 A-2) |
|
||
| 매뉴얼 · 병합 순서 | 마지막 [Save] 뒤 화면이 작업에 맞게 말한다(7차 A-1 · 8차 B-1). **pull · rebase · cherry-pick · revert 도 같은 길** 문단 — 다른 것은 끝내는 단추뿐. 가져올 변경이 없는 cherry-pick 안내(8차 B-2)와 이력 [모든 브랜치](7차 C-2) |
|
||
| 매뉴얼 · Git 탭 | 충돌 탭 끝내기 단추가 작업에 따라 병합 커밋 · 계속 · 커밋. 이력 탭에 [모든 브랜치] |
|
||
| 매뉴얼 · 알아 둘 한계 | 7차 · 8차에서 사라진 네 줄(주석 자동 풀기가 Merge 에만 · rebase · cherry-pick 미확인 · "3-Way 안 씀" 로그 · 마지막 저장 뒤 "남은 차이")을 빼고, 지금 남은 것으로 — 파일 단위 Accept 는 고른 쪽 줄끝을 그대로 가져온다 · 빠른 비교 · 코드 검사 · **스냅이 반쪽이 안 됨**(8차 C-3) · 로그인 · 권한 |
|
||
| 남은 일 | "7차 재료" 표를 **7차에서 고친 것** · **8차에서 고친 것** 두 표로. "6차에서 남긴 것" 을 **8차에 남은 것**(E-1 다섯 길 재확인 · 빈 커밋을 두지 않기로 한 결정)으로 |
|
||
| 지금까지 만든 것 | 09-15(7차) · 09-16(8차) 두 줄 추가, 기획 3단계 칸을 6차 → 7차 → 8차로 |
|
||
| 발표 자료 | 17장의 "7차: …" 줄을 "7차 · 8차: 다른 충돌 길 · 셸 창 크기 조절 — 끝" 으로 |
|
||
| 머리 | 문서 기준 날짜 2026-09-14 → **2026-09-16** |
|
||
|
||
### 확인한 것
|
||
|
||
- 화면 문구와 대조: "해결로 저장" · "3-Way 안 씀" · "948건" 같은 옛말이 문서에 하나도 없다(grep).
|
||
- 태그 짝 세기: section 26/26 · div 188/188 · table 26/26 · ul 35/35 · ol 11/11 · li 193/193 · tr 212/212 · td 520/520.
|
||
- 발행: 같은 주소의 아티팩트를 **버전 7** 로 갱신했다(읽어서 옛 내용을 확인한 뒤 올림). 저장소의 `doc/web/index.html` 과 같은 파일이다.
|
||
|
||
제품 코드는 바꾸지 않았다.
|