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>
This commit is contained in:
parent
9956567bf8
commit
85c5e9e085
26
doc/진행상황.md
26
doc/진행상황.md
@ -24,13 +24,24 @@
|
||||
| **완료** | blame (줄별 작성자) | `Blame` 탭 신설. 변경 목록에서 파일을 고르고 `blame` 을 누르면 경로가 넘어간다 | 확인: 31줄 전부 `커밋·날짜·작성자` 가 붙어 나옴 |
|
||||
| **완료** | 변경분 파일 추출 | `GitService.ExportChangedFiles` 신설. 저장소 안 경로 구조를 그대로 만들고, <b>바이트 그대로</b> 옮긴다(텍스트로 다시 쓰면 줄바꿈·인코딩이 바뀐다). 지워진 파일은 뽑을 것이 없어 건너뛴다 | 확인: `2개 파일 → ...Temp (건너뜀 0개)` |
|
||||
|
||||
### ③ 3-Way 병합 — "볼 수 있다"에서 "끝낼 수 있다"로
|
||||
### ③ 3-Way 병합 — **완료** (2026-09-08)
|
||||
|
||||
| 상태 | 항목 | 내용 |
|
||||
|---|---|---|
|
||||
| 대기 | 자동 병합 | 한쪽만 고친 곳은 자동으로 결과에 넣는다. 사람은 충돌만 판단 |
|
||||
| 대기 | 충돌만 이동 | `다음 차이` 말고 `다음 충돌`. 자동 병합과 짝이다 |
|
||||
| 대기 | 병합 완료 판정 | 남은 충돌 0 이면 저장·커밋을 유도 |
|
||||
"볼 수 있다"에서 "끝낼 수 있다"로.
|
||||
|
||||
| 상태 | 항목 | 내용 | 확인 |
|
||||
|---|---|---|---|
|
||||
| **완료** | 자동 병합 | 저쪽만 고친 줄(`ThreeWayState.RemoteChanged`)을 한 번에 가져온다. 충돌과 내가 고친 줄은 안 건드린다. `git merge` 가 자동으로 해 주는 일을 여기서도 해 주는 것 | `Theirs only 1 → 0`, 자동 병합 버튼이 스스로 꺼짐 |
|
||||
| **완료** | 충돌만 이동 | `이전 충돌` / `다음 충돌` (`Alt+Shift+↑↓`). <b>아직 안 정한 충돌만</b> 딛는다 | 3개를 차례로 딛고 마지막에 버튼이 꺼짐 |
|
||||
| **완료** | 병합 완료 판정 | ACTIONS 위쪽에 `남은 충돌 N개`(빨강) → `충돌 정리 끝`(초록) | 3개 → 2 → 1 → 끝 |
|
||||
|
||||
**여기서 판단이 하나 필요했다** — 충돌인지 아닌지는 BASE·MINE·REMOTE 를 견주면 저절로 나오지만,
|
||||
"내 것으로 간다"고 정한 줄은 <b>내용이 그대로라 여전히 충돌로 보인다.</b> 그래서 `NeedsDecision`
|
||||
(충돌이면서 아직 반영·수정 표시가 없는 줄)을 따로 두었다. 그 결정은 글을 바꾸지 않으므로 편집 뒤
|
||||
다시 정렬하면 사라지는데, 얼어 있는 <b>BASE 줄 번호</b>(없으면 MINE 줄 번호)로 붙들어 되살린다.
|
||||
|
||||
**곁들여 고친 것**: `Take Mine` · `Take Theirs` 버튼이 <b>줄을 옮겨도 켜짐/꺼짐이 그대로였다.</b>
|
||||
CommunityToolkit 커맨드는 CommandManager 를 구독하지 않는데 이 둘만 갱신 목록에서 빠져 있었다.
|
||||
키보드(`Alt+←/→`)로는 되고 버튼만 안 되던 이유가 이것이다.
|
||||
|
||||
### ① 폴더 비교
|
||||
|
||||
@ -69,4 +80,5 @@
|
||||
| 날짜 | 항목 | 커밋 |
|
||||
|---|---|---|
|
||||
| 2026-09-08 | 저장소 개설 (MergeHub · UbisamPlatform 각각) | `7719094` / `36ee902` |
|
||||
| 2026-09-08 | **④ Git 조작 5가지** — amend · stash 목록 · 커밋 간 비교 · blame · 변경분 추출 | 아래 |
|
||||
| 2026-09-08 | **④ Git 조작 5가지** — amend · stash 목록 · 커밋 간 비교 · blame · 변경분 추출 | `9956567` |
|
||||
| 2026-09-08 | **③ 3-Way** — 자동 병합 · 충돌만 이동 · 병합 완료 판정 | 아래 |
|
||||
|
||||
@ -130,6 +130,7 @@ namespace MergeHub.Models
|
||||
[NotifyPropertyChangedFor(nameof(Highlight))]
|
||||
[NotifyPropertyChangedFor(nameof(ThreeWay))]
|
||||
[NotifyPropertyChangedFor(nameof(IsConflict))]
|
||||
[NotifyPropertyChangedFor(nameof(NeedsDecision))]
|
||||
[NotifyPropertyChangedFor(nameof(CanTakeRemote))]
|
||||
[NotifyPropertyChangedFor(nameof(CanTakeLocal))]
|
||||
private string _localText;
|
||||
@ -141,11 +142,13 @@ namespace MergeHub.Models
|
||||
/// <summary>BASE 내용을 가져와 반영한 줄인지. 되돌리면 풀린다.</summary>
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(Highlight))]
|
||||
[NotifyPropertyChangedFor(nameof(NeedsDecision))]
|
||||
private bool _isApplied;
|
||||
|
||||
/// <summary>사용자가 직접 타이핑해 고친 줄인지. "머지 반영"과 구분해서 표시한다.</summary>
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(Highlight))]
|
||||
[NotifyPropertyChangedFor(nameof(NeedsDecision))]
|
||||
private bool _isManuallyEdited;
|
||||
|
||||
/// <summary>반영하면서 줄 끝에 붙인 주석(툴팁으로 보여준다).</summary>
|
||||
@ -281,6 +284,7 @@ namespace MergeHub.Models
|
||||
[NotifyPropertyChangedFor(nameof(ThreeWay))]
|
||||
[NotifyPropertyChangedFor(nameof(Highlight))]
|
||||
[NotifyPropertyChangedFor(nameof(IsConflict))]
|
||||
[NotifyPropertyChangedFor(nameof(NeedsDecision))]
|
||||
[NotifyPropertyChangedFor(nameof(CanTakeRemote))]
|
||||
[NotifyPropertyChangedFor(nameof(CanTakeLocal))]
|
||||
private string _remoteText = string.Empty;
|
||||
@ -363,6 +367,15 @@ namespace MergeHub.Models
|
||||
|
||||
public bool IsConflict => ThreeWay == ThreeWayState.Conflict;
|
||||
|
||||
/// <summary>
|
||||
/// 아직 사람이 골라야 하는 충돌 줄인지.
|
||||
///
|
||||
/// 충돌인지 아닌지는 BASE·MINE·REMOTE 를 견주면 저절로 나오지만, <b>"내 것으로 간다"고
|
||||
/// 정한 줄은 내용이 그대로라 여전히 충돌로 보인다.</b> 그래서 "정했다"는 표시
|
||||
/// (반영했거나 직접 고쳤거나)를 함께 본다 - 이 수가 0 이 되면 이 파일의 병합은 끝난 것이다.
|
||||
/// </summary>
|
||||
public bool NeedsDecision => IsConflict && !IsApplied && !IsManuallyEdited && !IsMergeNote;
|
||||
|
||||
/// <summary>REMOTE 내용을 가져올 수 있는 줄인지. 이미 같으면 가져올 것이 없다.</summary>
|
||||
public bool CanTakeRemote =>
|
||||
IsThreeWay && !IsMergeNote && ThreeWay is ThreeWayState.RemoteChanged or ThreeWayState.Conflict;
|
||||
|
||||
@ -21,6 +21,9 @@ namespace MergeHub.Services
|
||||
GoToLine,
|
||||
NextBookmark,
|
||||
ToggleBookmark,
|
||||
NextConflict,
|
||||
PrevConflict,
|
||||
AutoMerge,
|
||||
OpenFolderCompare,
|
||||
Find,
|
||||
FindNext,
|
||||
@ -109,6 +112,13 @@ namespace MergeHub.Services
|
||||
new ShortcutEntry(ShortcutAction.CopyRightToLeft, Key.Left, ModifierKeys.Alt, "병합·편집",
|
||||
"오른쪽 → 왼쪽 반영 (2-Way: 이 줄 되돌리기 / 3-Way: Take Theirs)"),
|
||||
|
||||
new ShortcutEntry(ShortcutAction.NextConflict, Key.Down, ModifierKeys.Alt | ModifierKeys.Shift, "병합·편집",
|
||||
"다음 충돌 (3-Way)", "차이가 아니라 <아직 안 정한 충돌>만 딛는다. 자동 병합과 짝이다."),
|
||||
new ShortcutEntry(ShortcutAction.PrevConflict, Key.Up, ModifierKeys.Alt | ModifierKeys.Shift, "병합·편집",
|
||||
"이전 충돌 (3-Way)"),
|
||||
new ShortcutEntry(ShortcutAction.AutoMerge, Key.M, ModifierKeys.Alt, "병합·편집",
|
||||
"자동 병합 - 저쪽만 고친 줄을 한 번에 가져온다 (3-Way)"),
|
||||
|
||||
new ShortcutEntry(ShortcutAction.Undo, Key.Z, ModifierKeys.Control, "병합·편집", "실행 취소",
|
||||
"머지 반영을 되돌린다. 되돌릴 머지 작업이 없으면 편집기의 글자 되돌리기가 그대로 동작한다."),
|
||||
new ShortcutEntry(ShortcutAction.Redo, Key.Y, ModifierKeys.Control, "병합·편집", "다시 실행"),
|
||||
|
||||
@ -453,6 +453,11 @@ namespace MergeHub.ViewModels
|
||||
UndoCommand.NotifyCanExecuteChanged();
|
||||
RedoCommand.NotifyCanExecuteChanged();
|
||||
AcceptAllCommand.NotifyCanExecuteChanged();
|
||||
|
||||
// 3-Way 의 두 버튼. 빠져 있어서 줄을 옮겨도 켜짐/꺼짐이 그대로였다 -
|
||||
// CommunityToolkit 의 커맨드는 CommandManager 를 구독하지 않으므로 직접 알려야 한다.
|
||||
AcceptLocalCommand.NotifyCanExecuteChanged();
|
||||
AcceptRemoteCommand.NotifyCanExecuteChanged();
|
||||
FirstDiffCommand.NotifyCanExecuteChanged();
|
||||
PrevDiffCommand.NotifyCanExecuteChanged();
|
||||
NextDiffCommand.NotifyCanExecuteChanged();
|
||||
@ -462,6 +467,10 @@ namespace MergeHub.ViewModels
|
||||
ReloadCommand.NotifyCanExecuteChanged();
|
||||
SaveAndCommitCommand.NotifyCanExecuteChanged();
|
||||
SavePlainCommand.NotifyCanExecuteChanged();
|
||||
|
||||
AutoMergeCommand.NotifyCanExecuteChanged();
|
||||
NextConflictCommand.NotifyCanExecuteChanged();
|
||||
PrevConflictCommand.NotifyCanExecuteChanged();
|
||||
}
|
||||
|
||||
// ================= 로드 =================
|
||||
@ -621,6 +630,8 @@ namespace MergeHub.ViewModels
|
||||
_baseTextSnapshot = baseText;
|
||||
_remoteTextSnapshot = threeWay ? remoteText : string.Empty;
|
||||
_mineTextSnapshot = threeWay ? localText : string.Empty;
|
||||
_resolvedBaseNumbers.Clear(); // 파일이 바뀌면 앞 파일의 결정은 뜻이 없다
|
||||
_resolvedMineNumbers.Clear();
|
||||
_originalLocalText = BuildLocalText();
|
||||
SyncEditorFromLines();
|
||||
|
||||
@ -994,7 +1005,10 @@ namespace MergeHub.ViewModels
|
||||
if (beforeHasLocal == afterHasLocal && string.Equals(before, after, StringComparison.Ordinal))
|
||||
{
|
||||
// 이미 내 원본과 같다. 충돌 줄이면 "내 것으로 정했다"는 표시만 남긴다.
|
||||
// 내용이 안 바뀌므로 다시 정렬하면 이 표시가 사라진다 - BASE 줄 번호로 따로 붙들어 둔다.
|
||||
line.IsApplied = true;
|
||||
if (line.BaseNumber is int resolvedBase) _resolvedBaseNumbers.Add(resolvedBase);
|
||||
else if (line.OriginalLocalNumber is int resolvedMine) _resolvedMineNumbers.Add(resolvedMine);
|
||||
AfterEdit();
|
||||
return;
|
||||
}
|
||||
@ -1270,6 +1284,12 @@ namespace MergeHub.ViewModels
|
||||
if (row.LocalNumber is int number && touched.Contains(number))
|
||||
row.IsManuallyEdited = true;
|
||||
|
||||
// "내 것으로 간다"고 정했던 충돌은 내용이 그대로라 글만 봐서는 알 수 없다.
|
||||
if (row.BaseNumber is int baseNumber
|
||||
? _resolvedBaseNumbers.Contains(baseNumber)
|
||||
: row.OriginalLocalNumber is int mineNumber && _resolvedMineNumbers.Contains(mineNumber))
|
||||
row.IsApplied = true;
|
||||
|
||||
Lines.Add(row);
|
||||
}
|
||||
|
||||
@ -1460,6 +1480,8 @@ namespace MergeHub.ViewModels
|
||||
_baseTextSnapshot = baseText;
|
||||
_remoteTextSnapshot = string.Empty; // 파일 두 개 비교는 늘 2-Way 다
|
||||
_mineTextSnapshot = string.Empty;
|
||||
_resolvedBaseNumbers.Clear();
|
||||
_resolvedMineNumbers.Clear();
|
||||
|
||||
RefreshLanguage();
|
||||
var rows = BuildLines(baseText, localText);
|
||||
@ -2001,6 +2023,85 @@ namespace MergeHub.ViewModels
|
||||
RefreshProblems();
|
||||
}
|
||||
|
||||
// ================= 자동 병합 · 충돌만 보기 =================
|
||||
|
||||
/// <summary>
|
||||
/// "내 것으로 간다"고 정한 충돌 줄의 BASE 줄 번호.
|
||||
///
|
||||
/// 그 결정은 <b>내용을 바꾸지 않으므로</b> 글만 봐서는 되살릴 수 없다. 편집 뒤 다시 정렬하면
|
||||
/// 행이 새로 만들어지는데, 이걸 들고 있지 않으면 이미 정한 충돌이 되살아나
|
||||
/// "남은 충돌"이 줄지 않는다. BASE 는 얼어 있으므로 그 줄 번호가 안전한 열쇠다.
|
||||
/// </summary>
|
||||
private readonly HashSet<int> _resolvedBaseNumbers = new HashSet<int>();
|
||||
|
||||
/// <summary>
|
||||
/// BASE 에 없는 충돌(양쪽이 각자 새 줄을 넣은 자리)용. 이런 줄은 BASE 줄 번호가 없으므로
|
||||
/// 역시 얼어 있는 MINE 줄 번호로 붙든다.
|
||||
/// </summary>
|
||||
private readonly HashSet<int> _resolvedMineNumbers = new HashSet<int>();
|
||||
|
||||
private bool CanAutoMerge() => IsThreeWay && Lines.Any(l => l.ThreeWay == ThreeWayState.RemoteChanged);
|
||||
|
||||
/// <summary>
|
||||
/// 저쪽만 고친 줄을 한 번에 결과로 가져온다. 사람은 <b>충돌만</b> 판단하면 된다.
|
||||
///
|
||||
/// 안 겹치는 변경까지 하나씩 누르게 하면 100줄짜리 충돌 파일에서 정작 판단이 필요한
|
||||
/// 서너 줄이 묻힌다 - `git merge` 가 자동으로 해 주는 일을 여기서도 해 준다.
|
||||
/// 내가 고친 줄과 충돌 줄은 건드리지 않는다.
|
||||
/// </summary>
|
||||
[RelayCommand(CanExecute = nameof(CanAutoMerge))]
|
||||
private void AutoMerge()
|
||||
{
|
||||
// 반영하면서 주석 줄이 끼어들어 Lines 가 바뀐다. 먼저 목록을 떠 놓고 돈다.
|
||||
var targets = Lines.Where(l => l.ThreeWay == ThreeWayState.RemoteChanged && l.CanTakeRemote).ToList();
|
||||
if (targets.Count == 0) return;
|
||||
|
||||
foreach (var line in targets) ApplyRemote(line, requery: false);
|
||||
|
||||
AfterEdit();
|
||||
MessageUtil.ShowSuccessToast(UnresolvedConflictCount == 0
|
||||
? $"{targets.Count}줄 자동 병합 · 남은 충돌 없음"
|
||||
: $"{targets.Count}줄 자동 병합 · 남은 충돌 {UnresolvedConflictCount}개");
|
||||
}
|
||||
|
||||
private bool CanGoConflict() => IsThreeWay && Lines.Any(l => l.NeedsDecision);
|
||||
|
||||
/// <summary>다음 충돌로. `다음 차이` 와 달리 <b>아직 안 정한 충돌만</b> 딛는다.</summary>
|
||||
[RelayCommand(CanExecute = nameof(CanGoConflict))]
|
||||
private void NextConflict()
|
||||
{
|
||||
for (var row = CaretRow + 1; row < Lines.Count; row++)
|
||||
if (Lines[row].NeedsDecision) { GoToRow(row); return; }
|
||||
|
||||
// 끝까지 갔으면 처음으로 돈다 - 차이 이동과 같은 감각이다.
|
||||
for (var row = 0; row < Lines.Count; row++)
|
||||
if (Lines[row].NeedsDecision) { GoToRow(row); return; }
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanGoConflict))]
|
||||
private void PrevConflict()
|
||||
{
|
||||
for (var row = CaretRow - 1; row >= 0; row--)
|
||||
if (Lines[row].NeedsDecision) { GoToRow(row); return; }
|
||||
|
||||
for (var row = Lines.Count - 1; row >= 0; row--)
|
||||
if (Lines[row].NeedsDecision) { GoToRow(row); return; }
|
||||
}
|
||||
|
||||
/// <summary>아직 사람이 골라야 하는 충돌 줄 수. 0 이면 이 파일의 병합은 끝난 것이다.</summary>
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(MergeStatusText))]
|
||||
[NotifyPropertyChangedFor(nameof(IsMergeComplete))]
|
||||
private int _unresolvedConflictCount;
|
||||
|
||||
/// <summary>3-Way 에서 지금 어디까지 왔는지 한 줄로.</summary>
|
||||
public string MergeStatusText =>
|
||||
!IsThreeWay ? string.Empty :
|
||||
UnresolvedConflictCount == 0 ? "충돌 정리 끝" :
|
||||
$"남은 충돌 {UnresolvedConflictCount}개";
|
||||
|
||||
public bool IsMergeComplete => IsThreeWay && UnresolvedConflictCount == 0;
|
||||
|
||||
// ================= 범례에 실시간으로 붙는 개수 =================
|
||||
|
||||
[ObservableProperty] private int _changedCount;
|
||||
@ -2022,10 +2123,12 @@ namespace MergeHub.ViewModels
|
||||
private void UpdateLegendCounts()
|
||||
{
|
||||
int changed = 0, applied = 0, edited = 0, added = 0, removed = 0, moved = 0, ignored = 0, same = 0;
|
||||
int remote = 0, conflict = 0;
|
||||
int remote = 0, conflict = 0, needsDecision = 0;
|
||||
|
||||
foreach (var line in Lines)
|
||||
{
|
||||
if (line.NeedsDecision) needsDecision++;
|
||||
|
||||
switch (line.Highlight)
|
||||
{
|
||||
case LineHighlight.Applied: applied++; break;
|
||||
@ -2051,6 +2154,7 @@ namespace MergeHub.ViewModels
|
||||
SameCount = same;
|
||||
RemoteChangeCount = remote;
|
||||
ConflictCount = conflict;
|
||||
UnresolvedConflictCount = needsDecision;
|
||||
}
|
||||
|
||||
private string BuildLocalText()
|
||||
|
||||
@ -1223,6 +1223,46 @@
|
||||
Background="{DynamicResource Ubisam.Brush.Accent.Fill}"
|
||||
Foreground="{DynamicResource Ubisam.Brush.Accent.OnFill}"
|
||||
ToolTip="선택한 줄을 REMOTE(Theirs) 내용으로"/>
|
||||
|
||||
<!--
|
||||
3-Way 흐름. "안 겹치는 변경은 자동으로, 사람은 충돌만" 이 순서다.
|
||||
남은 충돌이 0 이 되면 그 자리에서 다 됐다고 알려 준다.
|
||||
-->
|
||||
<Border Margin="2,10,2,0" Padding="6,4" CornerRadius="3"
|
||||
Visibility="{Binding IsThreeWay, Converter={StaticResource BoolToVis}}"
|
||||
Background="{DynamicResource Ubisam.Brush.Input.Background}"
|
||||
BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}" BorderThickness="1">
|
||||
<TextBlock Text="{Binding MergeStatusText}" FontWeight="Bold" FontSize="11.5"
|
||||
HorizontalAlignment="Center"
|
||||
ToolTip="아직 사람이 골라야 하는 줄 수입니다">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="{DynamicResource Ubisam.Brush.Danger}"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsMergeComplete}" Value="True">
|
||||
<Setter Property="Foreground" Value="{DynamicResource Ubisam.Brush.Success}"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Border>
|
||||
|
||||
<Button Content="자동 병합" Command="{Binding AutoMergeCommand}"
|
||||
MinHeight="30" Margin="2,4,2,0"
|
||||
Visibility="{Binding IsThreeWay, Converter={StaticResource BoolToVis}}"
|
||||
ToolTip="저쪽만 고친 줄을 한 번에 가져옵니다. 충돌과 내가 고친 줄은 건드리지 않습니다"/>
|
||||
|
||||
<UniformGrid Columns="2" Margin="0,4,0,0"
|
||||
Visibility="{Binding IsThreeWay, Converter={StaticResource BoolToVis}}">
|
||||
<Button Content="이전 충돌" Command="{Binding PrevConflictCommand}"
|
||||
MinHeight="28" FontSize="11"
|
||||
ToolTip="아직 안 정한 충돌만 딛습니다 (Alt+Shift+Up)"/>
|
||||
<Button Content="다음 충돌" Command="{Binding NextConflictCommand}"
|
||||
MinHeight="28" FontSize="11"
|
||||
ToolTip="아직 안 정한 충돌만 딛습니다 (Alt+Shift+Down)"/>
|
||||
</UniformGrid>
|
||||
|
||||
<Button Content="Revert" Command="{Binding RevertCommand}" MinHeight="30" Margin="2,4,2,0"
|
||||
Style="{StaticResource FilledButton}"
|
||||
Background="{DynamicResource Ubisam.Brush.Warning}"
|
||||
|
||||
@ -709,6 +709,10 @@ namespace MergeHub.Views
|
||||
GoToBox.SelectAll();
|
||||
return true;
|
||||
|
||||
case ShortcutAction.NextConflict: return Run(vm.NextConflictCommand);
|
||||
case ShortcutAction.PrevConflict: return Run(vm.PrevConflictCommand);
|
||||
case ShortcutAction.AutoMerge: return Run(vm.AutoMergeCommand);
|
||||
|
||||
case ShortcutAction.NextBookmark: return Run(vm.NextBookmarkCommand);
|
||||
|
||||
case ShortcutAction.ToggleBookmark:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user