6차 B-3: 병합 커밋 메시지를 브랜치 이름으로 채우고 # 줄을 뺀다
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
c76e3d7aee
commit
21a2dc9b79
@ -426,3 +426,44 @@ B-1 확인 때는 늘 파일 비교 탭을 먼저 열어 두었다. 순서를
|
|||||||
| `Io/Unit20.cs` 를 고치고 `Io/Unit12.cs` 로 옮기며 [저장하고 계속] | 확인 창이 **Io/Unit20.cs** 이름을 댐. git 충돌 22, **풀린 것은 `Io/Unit20.cs`**(`M`, 안의 형식 `Unit20`, 상대 줄 들어감), **`Io/Unit12.cs` 는 `UU` 그대로**(안의 형식 `Unit12`), 그다음 `Io/Unit12.cs` 가 열림 |
|
| `Io/Unit20.cs` 를 고치고 `Io/Unit12.cs` 로 옮기며 [저장하고 계속] | 확인 창이 **Io/Unit20.cs** 이름을 댐. git 충돌 22, **풀린 것은 `Io/Unit20.cs`**(`M`, 안의 형식 `Unit20`, 상대 줄 들어감), **`Io/Unit12.cs` 는 `UU` 그대로**(안의 형식 `Unit12`), 그다음 `Io/Unit12.cs` 가 열림 |
|
||||||
|
|
||||||
화면 확인 **18건 통과**. 고친 파일(`HomeViewModel`)은 검사 하네스가 쓰지 않아 앞의 785건이 그대로 유효하다. 빌드 경고 0 · 오류 0.
|
화면 확인 **18건 통과**. 고친 파일(`HomeViewModel`)은 검사 하네스가 쓰지 않아 앞의 785건이 그대로 유효하다. 빌드 경고 0 · 오류 0.
|
||||||
|
|
||||||
|
## B-3. 커밋 메시지가 엉뚱하게 남는다 (2026-09-14, 완료)
|
||||||
|
|
||||||
|
### 고치기 전에 다시 났다
|
||||||
|
|
||||||
|
새로 만든 저장소(충돌 23개)를 MergeHub 로 병합했다.
|
||||||
|
|
||||||
|
| 본 것 | 값 |
|
||||||
|
|---|---|
|
||||||
|
| 파일 비교 탭에서 `Common/Util/Unit15.cs` 를 연 뒤 `Io/Unit12.cs` · `Motion/Unit0.cs` 로 옮김 | 메시지 칸이 끝까지 "**Merge: Common/Util/Unit15.cs 충돌 해결**" — 처음 연 파일 이름이 굳음 |
|
||||||
|
| 충돌을 다 풀고 앱을 다시 켠 뒤 충돌 탭 [병합 커밋] | 첫 줄 "**Merge commit 'fc8b8f8…'**", 그 아래 **`#` 로 시작하는 줄 24개**(`#Conflicts:` 와 파일 목록). 부모 2개 |
|
||||||
|
|
||||||
|
### 무엇이 원인이었나
|
||||||
|
|
||||||
|
- 파일 비교 탭은 메시지 칸이 **비어 있을 때만** 채웠다. 첫 파일에서 한 번 채우면 그 뒤로는 사람이 적은 글과 구별이 안 돼 그대로 남았다. 병합이 끝나도 지우는 곳이 없었다.
|
||||||
|
- 메시지 없이 커밋하면 git 이 남긴 `MERGE_MSG` 를 **그대로** 썼다. git 명령은 커밋할 때 `#` 줄을 지우지만 MergeHub 는 파일을 통째로 읽어 넣었다.
|
||||||
|
또 MergeHub 는 브랜치를 커밋으로 풀어 병합하므로(libgit2) git 이 첫 줄을 해시로 적는다 — 이력에서 무엇을 합쳤는지 안 보였다.
|
||||||
|
|
||||||
|
### 고친 것
|
||||||
|
|
||||||
|
| 자리 | 무엇 |
|
||||||
|
|---|---|
|
||||||
|
| `MergeNames.BranchMergeMessage` | 기본 메시지 `Merge branch '상대' into 내 브랜치`. 파일 이름은 넣지 않는다 — 병합 커밋은 병합 전체를 담는다 |
|
||||||
|
| `MergeNames.CleanMergeMessage` | `MERGE_MSG` 에서 `#` 줄을 빼고 앞뒤 빈 줄을 정리. 첫 줄이 `Merge commit '해시'` 이고 상대 브랜치 이름을 알면 브랜치 모양으로 바꾼다. 남는 것이 없으면 기본 메시지 |
|
||||||
|
| `GitService.CommitMerge` | 메시지가 비면 `CleanMergeMessage` 를 거친 것을 쓴다 |
|
||||||
|
| `HomeViewModel` | 스스로 채운 글을 `_autoCommitMessage` 로 기억한다. 칸이 비었거나 **내가 채운 글 그대로**일 때만 다시 채우고, 사람이 고친 글은 건드리지 않는다. 병합이 끝나면(새로고침에서 병합 중이 아님 · 병합 아닌 파일을 열 때 · 커밋 성공) 내가 채운 글만 지운다 |
|
||||||
|
|
||||||
|
`MergeSaveTest` 에 메시지 경우를 넣어 **62건 통과**.
|
||||||
|
|
||||||
|
### 확인한 것 (새로 만든 저장소)
|
||||||
|
|
||||||
|
| 확인 | 결과 |
|
||||||
|
|---|---|
|
||||||
|
| 병합 뒤 `Io/Unit12.cs` 를 엶 | 칸 `Merge branch 'feature/theirs' into feature/mine` |
|
||||||
|
| `Motion/Unit0.cs` 로 옮김 | 같은 글. 파일 이름 없음 |
|
||||||
|
| 칸에 "냉각 로직 병합 - 사람이 적음" 을 쓰고 `Io/Unit20.cs` 로 옮김 | 적은 글 그대로 |
|
||||||
|
| 칸을 비우고 `Io/Unit12.cs` 로 옮김 | 기본 메시지가 다시 채워짐 |
|
||||||
|
| 충돌을 git 으로 다 풀고 **앱을 다시 켠 뒤** 충돌 탭 [병합 커밋] | 커밋 메시지 `Merge branch 'feature/theirs' into feature/mine` 한 줄, `#` 줄 **0개**, 부모 2개, MERGE_HEAD 사라짐 |
|
||||||
|
| 저장소를 새로 만들어 병합 → 파일을 열어 칸이 채워진 채로 충돌을 풀고 **앱을 끄지 않고** [병합 커밋] | 커밋 메시지 같은 한 줄, `#` 줄 0개, 부모 2개. **파일 비교 탭 메시지 칸이 비워짐** |
|
||||||
|
|
||||||
|
화면 확인 **7건 통과**. 빌드 경고 0 · 오류 0.
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
| 날짜 | 항목 | 커밋 |
|
| 날짜 | 항목 | 커밋 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
| 2026-09-14 | **6차 B-3** — 병합 커밋 기본 메시지를 `Merge branch '상대' into 내 브랜치` 로. 첫 파일 이름이 굳어 남던 것, 커밋에 `#Conflicts:` 줄 24개와 해시 첫 줄이 들어가던 것을 고침. 병합이 끝나면 스스로 채운 글만 지운다 | 아래 |
|
||||||
| 2026-09-14 | **6차 B-2** — 파일을 바꿀 때 확인 창이 고친 파일 이름을 대고, [저장하고 계속] 이 엉뚱한 파일(새로 고른 파일)에 쓰던 것을 막음. [취소] 뒤 콤보가 제자리로. 저장소를 먼저 열면 목록이 0개이던 B-1 빈틈도 | 아래 |
|
| 2026-09-14 | **6차 B-2** — 파일을 바꿀 때 확인 창이 고친 파일 이름을 대고, [저장하고 계속] 이 엉뚱한 파일(새로 고른 파일)에 쓰던 것을 막음. [취소] 뒤 콤보가 제자리로. 저장소를 먼저 열면 목록이 0개이던 B-1 빈틈도 | 아래 |
|
||||||
| 2026-09-14 | **6차 B-1** — 새로고침 뒤 파일 목록을 게이트가 풀릴 때까지 기다렸다 세움(병합 뒤 304개 → 23개). 충돌 목록 두 번 누르기·Enter·[3분할로 열기] 로 파일 비교 탭 네 칸에서 연다. 없는 '홈 탭' 글을 고침 | 아래 |
|
| 2026-09-14 | **6차 B-1** — 새로고침 뒤 파일 목록을 게이트가 풀릴 때까지 기다렸다 세움(병합 뒤 304개 → 23개). 충돌 목록 두 번 누르기·Enter·[3분할로 열기] 로 파일 비교 탭 네 칸에서 연다. 없는 '홈 탭' 글을 고침 | 아래 |
|
||||||
| 2026-09-14 | **6차 A-5** — 파일 단위 Accept Both 가 두 벌을 글로 풀어 이어 붙이고 내 쪽 형식으로 쓴다(가운데 BOM 사라짐). 누르기 전에 무엇이 일어나는지 묻는다. A 묶음 끝 | 아래 |
|
| 2026-09-14 | **6차 A-5** — 파일 단위 Accept Both 가 두 벌을 글로 풀어 이어 붙이고 내 쪽 형식으로 쓴다(가운데 BOM 사라짐). 누르기 전에 무엇이 일어나는지 묻는다. A 묶음 끝 | 아래 |
|
||||||
|
|||||||
@ -105,7 +105,7 @@
|
|||||||
|---|---|
|
|---|---|
|
||||||
| **완료** | B-1 충돌 목록에서 3분할 화면까지 가는 길이 끊겨 있다 — 병합 뒤 목록이 바로 서고, 두 번 누르기·Enter·[3분할로 열기] |
|
| **완료** | B-1 충돌 목록에서 3분할 화면까지 가는 길이 끊겨 있다 — 병합 뒤 목록이 바로 서고, 두 번 누르기·Enter·[3분할로 열기] |
|
||||||
| **완료** | B-2 확인 창이 엉뚱한 파일 이름을 댄다 — 이름·[저장하고 계속] 모두 실린 파일 기준, [취소] 뒤 콤보도 돌아온다 |
|
| **완료** | B-2 확인 창이 엉뚱한 파일 이름을 댄다 — 이름·[저장하고 계속] 모두 실린 파일 기준, [취소] 뒤 콤보도 돌아온다 |
|
||||||
| 대기 | B-3 커밋 메시지가 엉뚱하게 남는다 |
|
| **완료** | B-3 커밋 메시지가 엉뚱하게 남는다 — 기본값 `Merge branch '상대' into 내 브랜치`, `#` 줄 뺌, 병합이 끝나면 칸을 비움 |
|
||||||
| 대기 | B-4 MERGED 칸 줄 번호가 네 자리에서 잘린다 |
|
| 대기 | B-4 MERGED 칸 줄 번호가 네 자리에서 잘린다 |
|
||||||
| 대기 | B-5 머지 주석은 소스에 넣고, 병합 뒤에는 그 줄을 무시한다 |
|
| 대기 | B-5 머지 주석은 소스에 넣고, 병합 뒤에는 그 줄을 무시한다 |
|
||||||
| 대기 | B-6 충돌 탭에서 하나씩 누를 때마다 오래 기다린다 |
|
| 대기 | B-6 충돌 탭에서 하나씩 누를 때마다 오래 기다린다 |
|
||||||
|
|||||||
@ -944,8 +944,11 @@ namespace MergeHub.Services
|
|||||||
if (remaining.Count > 0)
|
if (remaining.Count > 0)
|
||||||
throw new InvalidOperationException($"아직 해결되지 않은 충돌이 {remaining.Count}건 있습니다.");
|
throw new InvalidOperationException($"아직 해결되지 않은 충돌이 {remaining.Count}건 있습니다.");
|
||||||
|
|
||||||
|
// 사람이 적은 메시지가 없으면 git 이 남긴 병합 메시지를 <b>다듬어</b> 쓴다(6차 B-3).
|
||||||
|
// 예전에는 MERGE_MSG 를 통째로 써서 "Merge commit '해시'" 와 "#Conflicts:" 파일 목록이 이력에 남았다.
|
||||||
|
// MergeHub 는 브랜치를 커밋으로 풀어 병합하므로 git 이 첫 줄을 해시로 적는다 - 상대 이름으로 바꾼다.
|
||||||
if (string.IsNullOrWhiteSpace(message))
|
if (string.IsNullOrWhiteSpace(message))
|
||||||
message = ReadMergeMessage() ?? $"Merge into {Repo.Head.FriendlyName}";
|
message = MergeNames.CleanMergeMessage(ReadMergeMessage(), GetMergeTheirsName(), Repo.Head.FriendlyName);
|
||||||
|
|
||||||
var signature = BuildSignature();
|
var signature = BuildSignature();
|
||||||
var commit = Repo.Commit(message, signature, signature);
|
var commit = Repo.Commit(message, signature, signature);
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace MergeHub.Services
|
namespace MergeHub.Services
|
||||||
@ -32,5 +34,50 @@ namespace MergeHub.Services
|
|||||||
var name = match.Groups[1].Value.Trim();
|
var name = match.Groups[1].Value.Trim();
|
||||||
return name.Length == 0 ? null : name;
|
return name.Length == 0 ? null : name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 병합 커밋의 기본 메시지. git 명령으로 브랜치를 병합할 때와 같은 모양이다(6차 B-3).
|
||||||
|
/// 상대 이름을 모르면 <c>Merge into 브랜치</c> 로 줄인다.
|
||||||
|
///
|
||||||
|
/// 파일 이름을 넣지 않는 까닭 - 병합 커밋은 파일 하나가 아니라 병합 전체를 담는다. 예전에는 파일 비교 탭이
|
||||||
|
/// "Merge: 첫 충돌 파일 충돌 해결" 을 채우고, 다른 파일로 옮겨도 그 이름이 굳어 남았다.
|
||||||
|
/// </summary>
|
||||||
|
public static string BranchMergeMessage(string? theirs, string? head)
|
||||||
|
{
|
||||||
|
var into = string.IsNullOrWhiteSpace(head) ? string.Empty : $" into {head!.Trim()}";
|
||||||
|
return string.IsNullOrWhiteSpace(theirs)
|
||||||
|
? $"Merge{(into.Length == 0 ? " commit" : into)}"
|
||||||
|
: $"Merge branch '{theirs!.Trim()}'{into}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// git 이 남긴 병합 메시지(MERGE_MSG)를 커밋에 쓸 모양으로 다듬는다(6차 B-3).
|
||||||
|
///
|
||||||
|
/// <list type="bullet">
|
||||||
|
/// <item><c>#</c> 로 시작하는 줄은 뺀다. git 명령은 커밋할 때 이 주석 줄(<c>#Conflicts:</c> 와 파일 목록)을
|
||||||
|
/// 지우는데, MergeHub 는 파일을 통째로 써서 커밋 이력에 그대로 남았다.</item>
|
||||||
|
/// <item>첫 줄이 <c>Merge commit '해시'</c> 이고 상대 이름을 알면 <c>Merge branch '이름' into 브랜치</c> 로 바꾼다.
|
||||||
|
/// MergeHub 는 브랜치를 커밋으로 풀어 병합해서 git 이 해시로 적는다 - 이력에서 무엇을 합쳤는지 안 보였다.</item>
|
||||||
|
/// <item>남는 것이 없으면 <see cref="BranchMergeMessage"/> 를 쓴다.</item>
|
||||||
|
/// </list>
|
||||||
|
/// </summary>
|
||||||
|
public static string CleanMergeMessage(string? raw, string? theirs, string? head)
|
||||||
|
{
|
||||||
|
var lines = (raw ?? string.Empty).Replace("\r\n", "\n").Split('\n')
|
||||||
|
.Where(l => !l.TrimStart().StartsWith("#", StringComparison.Ordinal))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// 앞뒤 빈 줄 정리
|
||||||
|
while (lines.Count > 0 && lines[0].Trim().Length == 0) lines.RemoveAt(0);
|
||||||
|
while (lines.Count > 0 && lines[lines.Count - 1].Trim().Length == 0) lines.RemoveAt(lines.Count - 1);
|
||||||
|
|
||||||
|
if (lines.Count == 0) return BranchMergeMessage(theirs, head);
|
||||||
|
|
||||||
|
var byCommit = Regex.IsMatch(lines[0].Trim(), @"^Merge\s+commit\s+'[0-9a-fA-F]{7,40}'");
|
||||||
|
if (byCommit && !string.IsNullOrWhiteSpace(theirs) && !Regex.IsMatch(theirs!.Trim(), @"^[0-9a-fA-F]{7,40}$"))
|
||||||
|
lines[0] = BranchMergeMessage(theirs, head);
|
||||||
|
|
||||||
|
return string.Join("\n", lines);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -336,6 +336,12 @@ namespace MergeHub.ViewModels
|
|||||||
[ObservableProperty] private string _diffSummary = "-";
|
[ObservableProperty] private string _diffSummary = "-";
|
||||||
[ObservableProperty] private string _editSummary = "-";
|
[ObservableProperty] private string _editSummary = "-";
|
||||||
[ObservableProperty] private string _commitMessage = string.Empty;
|
[ObservableProperty] private string _commitMessage = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 프로그램이 채워 넣은 커밋 메시지(6차 B-3). 지금 칸의 글이 이것과 같으면 사람이 손대지 않은 것이라
|
||||||
|
/// 바꾸거나 비워도 된다. 다르면 사람이 적은 글이므로 건드리지 않는다.
|
||||||
|
/// </summary>
|
||||||
|
private string _autoCommitMessage = string.Empty;
|
||||||
[ObservableProperty] private bool _hasChanges;
|
[ObservableProperty] private bool _hasChanges;
|
||||||
|
|
||||||
/// <summary>커밋 트리 ListBox 가 바인딩하는 선택 항목(그래프 포함).</summary>
|
/// <summary>커밋 트리 ListBox 가 바인딩하는 선택 항목(그래프 포함).</summary>
|
||||||
@ -671,6 +677,7 @@ namespace MergeHub.ViewModels
|
|||||||
_redo.Clear();
|
_redo.Clear();
|
||||||
HasChanges = false;
|
HasChanges = false;
|
||||||
CommitMessage = string.Empty;
|
CommitMessage = string.Empty;
|
||||||
|
_autoCommitMessage = string.Empty;
|
||||||
MessageUtil.ShowSuccessToast(
|
MessageUtil.ShowSuccessToast(
|
||||||
sha is null ? "커밋 완료" : $"커밋 완료 ({sha.Substring(0, 7)})");
|
sha is null ? "커밋 완료" : $"커밋 완료 ({sha.Substring(0, 7)})");
|
||||||
});
|
});
|
||||||
@ -878,8 +885,20 @@ namespace MergeHub.ViewModels
|
|||||||
|
|
||||||
// ================= 로드 =================
|
// ================= 로드 =================
|
||||||
|
|
||||||
|
/// <summary>병합이 끝났으면 프로그램이 채운 병합 메시지를 비운다. 사람이 적은 글이면 두고 간다.</summary>
|
||||||
|
private void ClearAutoCommitMessage()
|
||||||
|
{
|
||||||
|
if (_autoCommitMessage.Length == 0) return;
|
||||||
|
if (CommitMessage == _autoCommitMessage) CommitMessage = string.Empty;
|
||||||
|
_autoCommitMessage = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
private void OnWorkspaceRefreshed()
|
private void OnWorkspaceRefreshed()
|
||||||
{
|
{
|
||||||
|
// 병합 커밋이나 병합 취소로 병합이 끝났으면 병합 메시지를 남겨 두지 않는다(6차 B-3).
|
||||||
|
// 예전에는 병합 커밋 뒤에도 "Merge: Common/Util/Unit15.cs 충돌 해결" 이 칸에 남았다.
|
||||||
|
if (!_workspace.IsMergeInProgress) ClearAutoCommitMessage();
|
||||||
|
|
||||||
IsGitMode = _workspace.IsRepositoryOpen;
|
IsGitMode = _workspace.IsRepositoryOpen;
|
||||||
RefreshRemoteBranches();
|
RefreshRemoteBranches();
|
||||||
|
|
||||||
@ -1161,8 +1180,17 @@ namespace MergeHub.ViewModels
|
|||||||
_redo.Clear();
|
_redo.Clear();
|
||||||
SelectedLine = Lines.FirstOrDefault(l => l.IsDifferent) ?? Lines.FirstOrDefault();
|
SelectedLine = Lines.FirstOrDefault(l => l.IsDifferent) ?? Lines.FirstOrDefault();
|
||||||
|
|
||||||
if (isConflict && string.IsNullOrWhiteSpace(CommitMessage))
|
// 병합 커밋 메시지 기본값은 <b>병합 전체의 이름</b>이다(6차 B-3). 예전에는 "Merge: 첫 충돌 파일 충돌 해결" 을
|
||||||
CommitMessage = $"Merge: {path} 충돌 해결";
|
// 채우고, 다른 파일로 옮겨도 그 이름이 굳어 남았다. 사람이 고쳐 적은 글은 건드리지 않는다.
|
||||||
|
if (isConflict && (string.IsNullOrWhiteSpace(CommitMessage) || CommitMessage == _autoCommitMessage))
|
||||||
|
{
|
||||||
|
_autoCommitMessage = MergeNames.BranchMergeMessage(theirsName, _workspace.CurrentBranch);
|
||||||
|
CommitMessage = _autoCommitMessage;
|
||||||
|
}
|
||||||
|
else if (!isConflict && !_workspace.IsMergeInProgress)
|
||||||
|
{
|
||||||
|
ClearAutoCommitMessage();
|
||||||
|
}
|
||||||
|
|
||||||
UpdateSummaries();
|
UpdateSummaries();
|
||||||
RaiseCanExecuteChanged();
|
RaiseCanExecuteChanged();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user