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>
82 lines
6.0 KiB
Markdown
82 lines
6.0 KiB
Markdown
# 6차 — 병합을 끝까지 믿고 쓸 수 있게
|
|
|
|
지시서: [../작업지시/6차.md](../작업지시/6차.md) · 재료: [2026-09-11-5차.md](2026-09-11-5차.md) 의 C-1
|
|
|
|
확인은 5차 C-1 과 같은 시험 저장소로 한다. 생성기(`C1Repo`)는 씨앗이 고정돼 있어 몇 번을 만들어도 같다.
|
|
만든 뒤 `feature/mine` 에서 `feature/theirs` 를 병합해 **충돌 22개** 상태로 두고 시작한다. 실제 소스는 열지 않는다.
|
|
|
|
---
|
|
|
|
## A-2. Save & Commit 이 "실패" 라는데 파일은 이미 써지고 스테이징됐다 (2026-09-14, 완료)
|
|
|
|
지시서 순서는 A-1 이 먼저지만 A-2 를 먼저 했다. 둘은 뿌리가 같다 - 병합 중에 "파일 하나만 풀어서 저장"
|
|
하는 길이 없고 커밋까지 묶여 있다. 그 길을 먼저 만들어야 A-1(줄끝)을 고칠 자리가 한 곳으로 정해진다.
|
|
|
|
### 고치기 전에 다시 났다
|
|
|
|
`Io/Unit12.cs` 의 충돌 하나를 3분할에서 Take Theirs 로 정하고 Save & Commit 을 눌렀다.
|
|
|
|
| 본 것 | 값 |
|
|
|---|---|
|
|
| 화면 | `Save & Commit 실패: 아직 해결되지 않은 충돌이 21건 있습니다.` |
|
|
| git 충돌 수 | 22 → **21** (실패라면서 줄었다) |
|
|
| 그 파일 상태 | `M` — 이미 써지고 스테이징됐다 |
|
|
| 편집 상태 | 여전히 "편집 1건", Save & Commit 단추 켜짐 |
|
|
|
|
### 무엇이 원인이었나
|
|
|
|
`SaveAndCommitAsync` 가 **쓰기 → 스테이징 → 커밋** 을 한 덩어리로 돌렸다. 남은 충돌은 마지막 커밋 단계
|
|
(`GitService.CommitMerge`)에서야 예외로 막혔다. 그 앞 두 단계는 되돌릴 수 없는 일인데 이미 끝난 뒤였다.
|
|
실패로 끝났으니 편집 상태도 안 치웠다 - 그래서 다른 파일을 고를 때마다 확인 창이 다시 떴다.
|
|
|
|
그리고 Git 모드에는 커밋 없이 저장하는 길이 **아예 없었다.** Ctrl+S 도 Save & Commit 이었다.
|
|
|
|
### 고친 것
|
|
|
|
| 자리 | 무엇 |
|
|
|---|---|
|
|
| `Services/MergeSavePlan.cs` (새 파일) | "지금 커밋해도 되는가" 를 가르는 판단만 따로 뺐다. 지금 저장하는 파일은 셈에서 빼고, 그 밖에 하나라도 남으면 막는다. 화면 코드에 두면 또 순서가 뒤바뀌기 쉬워서 뺐다 |
|
|
| `SaveAndCommitAsync` | 병합 중이면 **아무것도 쓰기 전에** 먼저 판단하고, 막히면 그대로 멈춘다. 알림은 "커밋하지 않았습니다. 파일은 바꾸지 않았습니다. [해결로 저장] 으로…" |
|
|
| `SaveResolvedAsync` (새 명령) · [해결로 저장] 단추 | 병합 중에만 보인다. 이 파일만 쓰고 스테이징한다. 커밋은 안 한다. 저장한 내용을 새 "원본" 으로 삼아 편집 상태를 치운다 |
|
|
| Ctrl+S | 병합 중이면 [해결로 저장]. 병합이 아니면 지금까지와 같다 |
|
|
| 확인 창의 "저장하고 계속" | 병합 중 충돌 파일이면 워킹트리에만 쓰지 않고 충돌까지 푼다. 예전에는 충돌 표시만 사라지고 git 은 여전히 충돌로 보는 어정쩡한 상태가 됐다 |
|
|
|
|
### 화면에서 해 보다 둘이 더 나왔다
|
|
|
|
**① 저장하자 파일 목록이 0개가 됐다.** 로그에 `[파일 목록] 다른 작업 진행 중이라 건너뜀`.
|
|
|
|
`LoadCommitAsync` 가 게이트에 막혀 건너뛰고도 **빈 결과로 목록을 갈아엎었다.** 본문 로드(`LoadFileAsync`)는
|
|
이미 `if (!loaded) return;` 으로 막고 있었는데 목록만 빠져 있었다.
|
|
새로고침은 저장소 상태를 읽는 도중(게이트를 쥔 채) 화면 목록을 바꾸고, 그 변화가 목록 다시 세우기를 부르므로
|
|
이 건너뜀은 **새로고침이 있을 때마다 난다.** 5차 C-1 의 "병합 뒤 파일 목록이 비어 있다"(6차 B-1)도 같은 원인으로 보인다.
|
|
|
|
- 건너뛰면 지금 목록을 그대로 둔다(`listed` 를 보고 돌아간다).
|
|
- 해결로 저장 뒤에는 **게이트가 풀릴 때까지 기다렸다가**(`GitWorkspace.WhenIdleAsync`) 목록을 다시 세운다.
|
|
처음에는 새로고침 직후 곧바로 불렀는데 5ms 뒤에도 또 건너뛰었다 - 다른 화면이 게이트를 잠깐 쥔다.
|
|
- 방금 푼 파일은 충돌 목록에서 빠지므로 **남은 충돌의 첫 파일이 저절로 열린다.**
|
|
|
|
**② 충돌을 전부 "내 것" 으로 정하면 저장할 수가 없었다.** Take Mine 은 글을 바꾸지 않는다(이미 내 것이다).
|
|
그래서 "고친 것 없음" 이 되어 단추가 꺼지고, git 은 계속 충돌로 봤다.
|
|
충돌로 열린 파일이고 3분할에서 충돌을 다 정했으면 고친 글이 없어도 저장할 수 있게 했다.
|
|
3분할이 아닐 때는 켜지 않는다 - 충돌 수를 셀 수 없는데 내 것으로 덮으면 안 된다.
|
|
|
|
### 확인한 것 (새로 만든 저장소, 충돌 22개에서 시작)
|
|
|
|
| 확인 | 결과 |
|
|
|---|---|
|
|
| 다른 충돌이 남은 채 Save & Commit | "커밋하지 않았습니다 · 파일은 바꾸지 않았습니다". git 충돌 **22 그대로**, 파일 `UU` 그대로, 커밋 없음, 편집 남음 |
|
|
| [해결로 저장] | "해결로 저장 · Unit12.cs · 남은 충돌 21건". git 충돌 **21**, 파일 `M`, 커밋 없음, 편집 상태 깨끗 |
|
|
| 저장 뒤 파일 목록 | **21개**로 다시 서고, 남은 충돌 첫 파일(`Common/Util/Unit15.cs`)이 세 칸으로 열림 |
|
|
| 그 뒤 다른 파일 고르기 | 확인 창 안 뜸, 파일 열림 |
|
|
| Take Mine 만 하고 저장 | 단추가 켜지고 저장됨. git 충돌 **20**, 내 줄이 들어감 |
|
|
| 병합 중 Ctrl+S | 해결로 저장이 불림. git 충돌 **19**, 커밋 없음, 목록 19개 |
|
|
| Git 탭 충돌 목록 | 푼 세 파일이 빠짐 |
|
|
|
|
화면 확인 **25건 통과**. 검사 하네스는 `MergeSaveTest` 18건을 새로 만들어 **21벌 716건 통과** · 빌드 경고 0 · 오류 0.
|
|
|
|
### 이번에 안 한 것
|
|
|
|
- **줄끝(CRLF → LF)은 그대로다.** 해결로 저장도 지금은 `ResolveConflictWithContent` 를 거치므로 A-1 이 남아 있다.
|
|
저장 길이 한 곳으로 모였으니 A-1 은 거기서 고친다.
|
|
- 로그의 첫 번째 "건너뜀" 은 여전히 찍힌다. 기다렸다 다시 세우므로 화면에는 티가 안 난다.
|
|
새로고침 도중에 목록을 다시 세우려는 것 자체는 B-1 에서 본다. |