Merge branch 'sourcegit-scm:develop' into develop

This commit is contained in:
Javier J. Martínez M. 2025-05-11 11:03:38 -06:00 committed by GitHub
commit 025e96eeee
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
44 changed files with 889 additions and 353 deletions

View file

@ -6,62 +6,32 @@ This document shows the translation status of each locale file in the repository
### ![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen) ### ![en_US](https://img.shields.io/badge/en__US-%E2%88%9A-brightgreen)
### ![de__DE](https://img.shields.io/badge/de__DE-95.07%25-yellow) ### ![de__DE](https://img.shields.io/badge/de__DE-99.74%25-yellow)
<details> <details>
<summary>Missing keys in de_DE.axaml</summary> <summary>Missing keys in de_DE.axaml</summary>
- Text.Bisect - Text.GitFlow.FinishWithPush
- Text.Bisect.Abort - Text.GitFlow.FinishWithSquash
- Text.Bisect.Bad
- Text.Bisect.Detecting
- Text.Bisect.Good
- Text.Bisect.Skip
- Text.Bisect.WaitingForRange
- Text.BranchUpstreamInvalid
- Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject
- Text.CommitMessageTextBox.SubjectCount
- Text.Configure.CustomAction.WaitForExit
- Text.Configure.Git.PreferredMergeMode
- Text.Configure.IssueTracker.AddSampleAzure
- Text.ConfirmEmptyCommit.Continue
- Text.ConfirmEmptyCommit.NoLocalChanges
- Text.ConfirmEmptyCommit.StageAllThenCommit
- Text.ConfirmEmptyCommit.WithLocalChanges
- Text.CopyFullPath
- Text.Diff.First
- Text.Diff.Last
- Text.Preferences.AI.Streaming
- Text.Preferences.Appearance.EditorTabWidth
- Text.Preferences.General.ShowTagsInGraph
- Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.Search.ByContent
- Text.Repository.ViewLogs
- Text.StashCM.SaveAsPatch
- Text.ViewLogs
- Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog
- Text.ViewLogs.Delete
- Text.WorkingCopy.ConfirmCommitWithFilter
- Text.WorkingCopy.Conflicts.OpenExternalMergeTool
- Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts
- Text.WorkingCopy.Conflicts.UseMine
- Text.WorkingCopy.Conflicts.UseTheirs
</details> </details>
### ![es__ES](https://img.shields.io/badge/es__ES-99.87%25-yellow) ### ![es__ES](https://img.shields.io/badge/es__ES-99.10%25-yellow)
<details> <details>
<summary>Missing keys in es_ES.axaml</summary> <summary>Missing keys in es_ES.axaml</summary>
- Text.Repository.Search.ByContent - Text.Checkout.RecurseSubmodules
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
- Text.Repository.Visit
</details> </details>
### ![fr__FR](https://img.shields.io/badge/fr__FR-96.37%25-yellow) ### ![fr__FR](https://img.shields.io/badge/fr__FR-95.50%25-yellow)
<details> <details>
<summary>Missing keys in fr_FR.axaml</summary> <summary>Missing keys in fr_FR.axaml</summary>
@ -73,6 +43,7 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good - Text.Bisect.Good
- Text.Bisect.Skip - Text.Bisect.Skip
- Text.Bisect.WaitingForRange - Text.Bisect.WaitingForRange
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor - Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter - Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject - Text.CommitCM.CopySubject
@ -82,9 +53,15 @@ This document shows the translation status of each locale file in the repository
- Text.ConfirmEmptyCommit.NoLocalChanges - Text.ConfirmEmptyCommit.NoLocalChanges
- Text.ConfirmEmptyCommit.StageAllThenCommit - Text.ConfirmEmptyCommit.StageAllThenCommit
- Text.ConfirmEmptyCommit.WithLocalChanges - Text.ConfirmEmptyCommit.WithLocalChanges
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
- Text.Repository.Search.ByContent - Text.Repository.Search.ByContent
- Text.Repository.ViewLogs - Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.ViewLogs - Text.ViewLogs
- Text.ViewLogs.Clear - Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog - Text.ViewLogs.CopyLog
@ -97,7 +74,7 @@ This document shows the translation status of each locale file in the repository
</details> </details>
### ![it__IT](https://img.shields.io/badge/it__IT-96.11%25-yellow) ### ![it__IT](https://img.shields.io/badge/it__IT-95.24%25-yellow)
<details> <details>
<summary>Missing keys in it_IT.axaml</summary> <summary>Missing keys in it_IT.axaml</summary>
@ -109,6 +86,7 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good - Text.Bisect.Good
- Text.Bisect.Skip - Text.Bisect.Skip
- Text.Bisect.WaitingForRange - Text.Bisect.WaitingForRange
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor - Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter - Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject - Text.CommitCM.CopySubject
@ -119,10 +97,16 @@ This document shows the translation status of each locale file in the repository
- Text.ConfirmEmptyCommit.StageAllThenCommit - Text.ConfirmEmptyCommit.StageAllThenCommit
- Text.ConfirmEmptyCommit.WithLocalChanges - Text.ConfirmEmptyCommit.WithLocalChanges
- Text.CopyFullPath - Text.CopyFullPath
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Preferences.General.ShowTagsInGraph - Text.Preferences.General.ShowTagsInGraph
- Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
- Text.Repository.Search.ByContent - Text.Repository.Search.ByContent
- Text.Repository.ViewLogs - Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.ViewLogs - Text.ViewLogs
- Text.ViewLogs.Clear - Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog - Text.ViewLogs.CopyLog
@ -135,7 +119,7 @@ This document shows the translation status of each locale file in the repository
</details> </details>
### ![ja__JP](https://img.shields.io/badge/ja__JP-96.11%25-yellow) ### ![ja__JP](https://img.shields.io/badge/ja__JP-95.24%25-yellow)
<details> <details>
<summary>Missing keys in ja_JP.axaml</summary> <summary>Missing keys in ja_JP.axaml</summary>
@ -147,6 +131,7 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good - Text.Bisect.Good
- Text.Bisect.Skip - Text.Bisect.Skip
- Text.Bisect.WaitingForRange - Text.Bisect.WaitingForRange
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor - Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter - Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject - Text.CommitCM.CopySubject
@ -156,11 +141,17 @@ This document shows the translation status of each locale file in the repository
- Text.ConfirmEmptyCommit.NoLocalChanges - Text.ConfirmEmptyCommit.NoLocalChanges
- Text.ConfirmEmptyCommit.StageAllThenCommit - Text.ConfirmEmptyCommit.StageAllThenCommit
- Text.ConfirmEmptyCommit.WithLocalChanges - Text.ConfirmEmptyCommit.WithLocalChanges
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
- Text.Repository.FilterCommits - Text.Repository.FilterCommits
- Text.Repository.Search.ByContent - Text.Repository.Search.ByContent
- Text.Repository.Tags.OrderByNameDes - Text.Repository.Tags.OrderByNameDes
- Text.Repository.ViewLogs - Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.ViewLogs - Text.ViewLogs
- Text.ViewLogs.Clear - Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog - Text.ViewLogs.CopyLog
@ -173,7 +164,7 @@ This document shows the translation status of each locale file in the repository
</details> </details>
### ![pt__BR](https://img.shields.io/badge/pt__BR-87.68%25-yellow) ### ![pt__BR](https://img.shields.io/badge/pt__BR-86.89%25-yellow)
<details> <details>
<summary>Missing keys in pt_BR.axaml</summary> <summary>Missing keys in pt_BR.axaml</summary>
@ -194,6 +185,7 @@ This document shows the translation status of each locale file in the repository
- Text.BranchCM.CustomAction - Text.BranchCM.CustomAction
- Text.BranchCM.MergeMultiBranches - Text.BranchCM.MergeMultiBranches
- Text.BranchUpstreamInvalid - Text.BranchUpstreamInvalid
- Text.Checkout.RecurseSubmodules
- Text.Clone.RecurseSubmodules - Text.Clone.RecurseSubmodules
- Text.CommitCM.CopyAuthor - Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter - Text.CommitCM.CopyCommitter
@ -222,6 +214,8 @@ This document shows the translation status of each locale file in the repository
- Text.Diff.UseBlockNavigation - Text.Diff.UseBlockNavigation
- Text.Fetch.Force - Text.Fetch.Force
- Text.FileCM.ResolveUsing - Text.FileCM.ResolveUsing
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Hotkeys.Global.Clone - Text.Hotkeys.Global.Clone
- Text.InProgress.CherryPick.Head - Text.InProgress.CherryPick.Head
- Text.InProgress.Merge.Operating - Text.InProgress.Merge.Operating
@ -239,6 +233,9 @@ This document shows the translation status of each locale file in the repository
- Text.Preferences.General.ShowTagsInGraph - Text.Preferences.General.ShowTagsInGraph
- Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Preferences.Git.SSLVerify - Text.Preferences.Git.SSLVerify
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
- Text.Repository.FilterCommits - Text.Repository.FilterCommits
- Text.Repository.HistoriesLayout - Text.Repository.HistoriesLayout
- Text.Repository.HistoriesLayout.Horizontal - Text.Repository.HistoriesLayout.Horizontal
@ -254,6 +251,7 @@ This document shows the translation status of each locale file in the repository
- Text.Repository.Tags.Sort - Text.Repository.Tags.Sort
- Text.Repository.UseRelativeTimeInHistories - Text.Repository.UseRelativeTimeInHistories
- Text.Repository.ViewLogs - Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.SetUpstream - Text.SetUpstream
- Text.SetUpstream.Local - Text.SetUpstream.Local
- Text.SetUpstream.Unset - Text.SetUpstream.Unset
@ -276,9 +274,17 @@ This document shows the translation status of each locale file in the repository
</details> </details>
### ![ru__RU](https://img.shields.io/badge/ru__RU-%E2%88%9A-brightgreen) ### ![ru__RU](https://img.shields.io/badge/ru__RU-99.74%25-yellow)
### ![ta__IN](https://img.shields.io/badge/ta__IN-96.37%25-yellow) <details>
<summary>Missing keys in ru_RU.axaml</summary>
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
</details>
### ![ta__IN](https://img.shields.io/badge/ta__IN-95.50%25-yellow)
<details> <details>
<summary>Missing keys in ta_IN.axaml</summary> <summary>Missing keys in ta_IN.axaml</summary>
@ -290,6 +296,7 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good - Text.Bisect.Good
- Text.Bisect.Skip - Text.Bisect.Skip
- Text.Bisect.WaitingForRange - Text.Bisect.WaitingForRange
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor - Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter - Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject - Text.CommitCM.CopySubject
@ -299,9 +306,15 @@ This document shows the translation status of each locale file in the repository
- Text.ConfirmEmptyCommit.NoLocalChanges - Text.ConfirmEmptyCommit.NoLocalChanges
- Text.ConfirmEmptyCommit.StageAllThenCommit - Text.ConfirmEmptyCommit.StageAllThenCommit
- Text.ConfirmEmptyCommit.WithLocalChanges - Text.ConfirmEmptyCommit.WithLocalChanges
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
- Text.Repository.Search.ByContent - Text.Repository.Search.ByContent
- Text.Repository.ViewLogs - Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.UpdateSubmodules.Target - Text.UpdateSubmodules.Target
- Text.ViewLogs - Text.ViewLogs
- Text.ViewLogs.Clear - Text.ViewLogs.Clear
@ -314,7 +327,7 @@ This document shows the translation status of each locale file in the repository
</details> </details>
### ![uk__UA](https://img.shields.io/badge/uk__UA-97.54%25-yellow) ### ![uk__UA](https://img.shields.io/badge/uk__UA-96.66%25-yellow)
<details> <details>
<summary>Missing keys in uk_UA.axaml</summary> <summary>Missing keys in uk_UA.axaml</summary>
@ -326,14 +339,21 @@ This document shows the translation status of each locale file in the repository
- Text.Bisect.Good - Text.Bisect.Good
- Text.Bisect.Skip - Text.Bisect.Skip
- Text.Bisect.WaitingForRange - Text.Bisect.WaitingForRange
- Text.Checkout.RecurseSubmodules
- Text.CommitCM.CopyAuthor - Text.CommitCM.CopyAuthor
- Text.CommitCM.CopyCommitter - Text.CommitCM.CopyCommitter
- Text.CommitCM.CopySubject - Text.CommitCM.CopySubject
- Text.CommitMessageTextBox.SubjectCount - Text.CommitMessageTextBox.SubjectCount
- Text.ConfigureWorkspace.Name - Text.ConfigureWorkspace.Name
- Text.GitFlow.FinishWithPush
- Text.GitFlow.FinishWithSquash
- Text.Preferences.Git.IgnoreCRAtEOLInDiff - Text.Preferences.Git.IgnoreCRAtEOLInDiff
- Text.Repository.BranchSort
- Text.Repository.BranchSort.ByCommitterDate
- Text.Repository.BranchSort.ByName
- Text.Repository.Search.ByContent - Text.Repository.Search.ByContent
- Text.Repository.ViewLogs - Text.Repository.ViewLogs
- Text.Repository.Visit
- Text.ViewLogs - Text.ViewLogs
- Text.ViewLogs.Clear - Text.ViewLogs.Clear
- Text.ViewLogs.CopyLog - Text.ViewLogs.CopyLog

View file

@ -1 +1 @@
2025.15 2025.16

View file

@ -78,7 +78,7 @@ namespace SourceGit
return builder; return builder;
} }
private static void LogException(Exception ex) public static void LogException(Exception ex)
{ {
if (ex == null) if (ex == null)
return; return;

View file

@ -11,15 +11,24 @@ namespace SourceGit.Commands
Context = repo; Context = repo;
} }
public bool Branch(string branch) public bool Branch(string branch, bool force)
{ {
Args = $"checkout --recurse-submodules --progress {branch}"; var option = force ? "--force" : string.Empty;
Args = $"checkout {option} --progress {branch}";
return Exec(); return Exec();
} }
public bool Branch(string branch, string basedOn) public bool Branch(string branch, string basedOn, bool force)
{ {
Args = $"checkout --recurse-submodules --progress -b {branch} {basedOn}"; var option = force ? "--force" : string.Empty;
Args = $"checkout --progress -b {branch} {basedOn}";
return Exec();
}
public bool Commit(string commitId, bool force)
{
var option = force ? "--force" : string.Empty;
Args = $"checkout {option} --detach --progress {commitId}";
return Exec(); return Exec();
} }
@ -56,11 +65,5 @@ namespace SourceGit.Commands
Args = $"checkout --no-overlay {revision} -- \"{file}\""; Args = $"checkout --no-overlay {revision} -- \"{file}\"";
return Exec(); return Exec();
} }
public bool Commit(string commitId)
{
Args = $"checkout --detach --progress {commitId}";
return Exec();
}
} }
} }

View file

@ -1,31 +1,12 @@
using System.Collections.Generic; namespace SourceGit.Commands
using System.Text;
namespace SourceGit.Commands
{ {
public class Clean : Command public class Clean : Command
{ {
public Clean(string repo, bool includeIgnored) public Clean(string repo)
{ {
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = includeIgnored ? "clean -qfdx" : "clean -qfd"; Args = "clean -qfdx";
}
public Clean(string repo, List<string> files)
{
var builder = new StringBuilder();
builder.Append("clean -qfd --");
foreach (var f in files)
{
builder.Append(" \"");
builder.Append(f);
builder.Append("\"");
}
WorkingDirectory = repo;
Context = repo;
Args = builder.ToString();
} }
} }
} }

View file

@ -28,11 +28,11 @@ namespace SourceGit.Commands
Context = repo; Context = repo;
if (ignoreWhitespace) if (ignoreWhitespace)
Args = $"-c core.autocrlf=false diff --no-ext-diff --patch --ignore-all-space --unified={unified} {opt}"; Args = $"diff --no-ext-diff --patch --ignore-all-space --unified={unified} {opt}";
else if (Models.DiffOption.IgnoreCRAtEOL) else if (Models.DiffOption.IgnoreCRAtEOL)
Args = $"-c core.autocrlf=false diff --no-ext-diff --patch --ignore-cr-at-eol --unified={unified} {opt}"; Args = $"diff --no-ext-diff --patch --ignore-cr-at-eol --unified={unified} {opt}";
else else
Args = $"-c core.autocrlf=false diff --no-ext-diff --patch --unified={unified} {opt}"; Args = $"diff --no-ext-diff --patch --unified={unified} {opt}";
} }
public Models.DiffResult Result() public Models.DiffResult Result()

View file

@ -1,5 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using Avalonia.Threading;
namespace SourceGit.Commands namespace SourceGit.Commands
{ {
@ -7,33 +10,71 @@ namespace SourceGit.Commands
{ {
public static void All(string repo, bool includeIgnored, Models.ICommandLog log) public static void All(string repo, bool includeIgnored, Models.ICommandLog log)
{ {
var changes = new QueryLocalChanges(repo).Result();
try
{
foreach (var c in changes)
{
if (c.WorkTree == Models.ChangeState.Untracked ||
c.WorkTree == Models.ChangeState.Added ||
c.Index == Models.ChangeState.Added ||
c.Index == Models.ChangeState.Renamed)
{
var fullPath = Path.Combine(repo, c.Path);
if (Directory.Exists(fullPath))
Directory.Delete(fullPath, true);
else
File.Delete(fullPath);
}
}
}
catch (Exception e)
{
Dispatcher.UIThread.Invoke(() =>
{
App.RaiseException(repo, $"Failed to discard changes. Reason: {e.Message}");
});
}
new Restore(repo) { Log = log }.Exec(); new Restore(repo) { Log = log }.Exec();
new Clean(repo, includeIgnored) { Log = log }.Exec(); if (includeIgnored)
new Clean(repo) { Log = log }.Exec();
} }
public static void Changes(string repo, List<Models.Change> changes, Models.ICommandLog log) public static void Changes(string repo, List<Models.Change> changes, Models.ICommandLog log)
{ {
var needClean = new List<string>(); var restores = new List<string>();
var needCheckout = new List<string>();
foreach (var c in changes) try
{ {
if (c.WorkTree == Models.ChangeState.Untracked || c.WorkTree == Models.ChangeState.Added) foreach (var c in changes)
needClean.Add(c.Path); {
else if (c.WorkTree == Models.ChangeState.Untracked || c.WorkTree == Models.ChangeState.Added)
needCheckout.Add(c.Path); {
var fullPath = Path.Combine(repo, c.Path);
if (Directory.Exists(fullPath))
Directory.Delete(fullPath, true);
else
File.Delete(fullPath);
}
else
{
restores.Add(c.Path);
}
}
}
catch (Exception e)
{
Dispatcher.UIThread.Invoke(() =>
{
App.RaiseException(repo, $"Failed to discard changes. Reason: {e.Message}");
});
} }
for (int i = 0; i < needClean.Count; i += 10) for (int i = 0; i < restores.Count; i += 10)
{ {
var count = Math.Min(10, needClean.Count - i); var count = Math.Min(10, restores.Count - i);
new Clean(repo, needClean.GetRange(i, count)) { Log = log }.Exec(); new Restore(repo, restores.GetRange(i, count), "--worktree --recurse-submodules") { Log = log }.Exec();
}
for (int i = 0; i < needCheckout.Count; i += 10)
{
var count = Math.Min(10, needCheckout.Count - i);
new Restore(repo, needCheckout.GetRange(i, count), "--worktree --recurse-submodules") { Log = log }.Exec();
} }
} }
} }

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using Avalonia.Threading; using Avalonia.Threading;
@ -134,7 +135,7 @@ namespace SourceGit.Commands
return start.Exec(); return start.Exec();
} }
public static bool Finish(string repo, string type, string name, bool keepBranch, Models.ICommandLog log) public static bool Finish(string repo, string type, string name, bool squash, bool push, bool keepBranch, Models.ICommandLog log)
{ {
if (!SUPPORTED_BRANCH_TYPES.Contains(type)) if (!SUPPORTED_BRANCH_TYPES.Contains(type))
{ {
@ -146,11 +147,22 @@ namespace SourceGit.Commands
return false; return false;
} }
var option = keepBranch ? "-k" : string.Empty; var builder = new StringBuilder();
builder.Append("flow ");
builder.Append(type);
builder.Append(" finish ");
if (squash)
builder.Append("--squash ");
if (push)
builder.Append("--push ");
if (keepBranch)
builder.Append("-k ");
builder.Append(name);
var finish = new Command(); var finish = new Command();
finish.WorkingDirectory = repo; finish.WorkingDirectory = repo;
finish.Context = repo; finish.Context = repo;
finish.Args = $"flow {type} finish {option} {name}"; finish.Args = builder.ToString();
finish.Log = log; finish.Log = log;
return finish.Exec(); return finish.Exec();
} }

View file

@ -14,7 +14,7 @@ namespace SourceGit.Commands
{ {
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = "branch -l --all -v --format=\"%(refname)%00%(objectname)%00%(HEAD)%00%(upstream)%00%(upstream:trackshort)\""; Args = "branch -l --all -v --format=\"%(refname)%00%(committerdate:unix)%00%(objectname)%00%(HEAD)%00%(upstream)%00%(upstream:trackshort)\"";
} }
public List<Models.Branch> Result() public List<Models.Branch> Result()
@ -49,7 +49,7 @@ namespace SourceGit.Commands
private Models.Branch ParseLine(string line) private Models.Branch ParseLine(string line)
{ {
var parts = line.Split('\0'); var parts = line.Split('\0');
if (parts.Length != 5) if (parts.Length != 6)
return null; return null;
var branch = new Models.Branch(); var branch = new Models.Branch();
@ -83,12 +83,13 @@ namespace SourceGit.Commands
} }
branch.FullName = refName; branch.FullName = refName;
branch.Head = parts[1]; branch.CommitterDate = ulong.Parse(parts[1]);
branch.IsCurrent = parts[2] == "*"; branch.Head = parts[2];
branch.Upstream = parts[3]; branch.IsCurrent = parts[3] == "*";
branch.Upstream = parts[4];
branch.IsUpstreamGone = false; branch.IsUpstreamGone = false;
if (branch.IsLocal && !string.IsNullOrEmpty(parts[4]) && !parts[4].Equals("=", StringComparison.Ordinal)) if (branch.IsLocal && !string.IsNullOrEmpty(parts[5]) && !parts[5].Equals("=", StringComparison.Ordinal))
branch.TrackStatus = new QueryTrackStatus(WorkingDirectory, branch.Name, branch.Upstream).Result(); branch.TrackStatus = new QueryTrackStatus(WorkingDirectory, branch.Name, branch.Upstream).Result();
else else
branch.TrackStatus = new Models.BranchTrackStatus(); branch.TrackStatus = new Models.BranchTrackStatus();

View file

@ -1,4 +1,7 @@
namespace SourceGit.Commands using System.Collections.Generic;
using System.Text;
namespace SourceGit.Commands
{ {
public class Submodule : Command public class Submodule : Command
{ {
@ -42,6 +45,28 @@
return Exec(); return Exec();
} }
public bool Update(List<Models.Submodule> modules, bool init, bool recursive, bool useRemote)
{
var builder = new StringBuilder();
builder.Append("submodule update");
if (init)
builder.Append(" --init");
if (recursive)
builder.Append(" --recursive");
if (useRemote)
builder.Append(" --remote");
if (modules.Count > 0)
{
builder.Append(" --");
foreach (var module in modules)
builder.Append($" \"{module.Path}\"");
}
Args = builder.ToString();
return Exec();
}
public bool Delete(string relativePath) public bool Delete(string relativePath)
{ {
Args = $"submodule deinit -f \"{relativePath}\""; Args = $"submodule deinit -f \"{relativePath}\"";

View file

@ -23,10 +23,17 @@ namespace SourceGit.Models
} }
} }
public enum BranchSortMode
{
Name = 0,
CommitterDate,
}
public class Branch public class Branch
{ {
public string Name { get; set; } public string Name { get; set; }
public string FullName { get; set; } public string FullName { get; set; }
public ulong CommitterDate { get; set; }
public string Head { get; set; } public string Head { get; set; }
public bool IsLocal { get; set; } public bool IsLocal { get; set; }
public bool IsCurrent { get; set; } public bool IsCurrent { get; set; }

View file

@ -64,8 +64,8 @@ namespace SourceGit.Models
{ {
const double unitWidth = 12; const double unitWidth = 12;
const double halfWidth = 6; const double halfWidth = 6;
const double unitHeight = 28; const double unitHeight = 1;
const double halfHeight = 14; const double halfHeight = 0.5;
var temp = new CommitGraph(); var temp = new CommitGraph();
var unsolved = new List<PathHelper>(); var unsolved = new List<PathHelper>();

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace SourceGit.Models namespace SourceGit.Models
@ -22,24 +22,24 @@ namespace SourceGit.Models
{ {
if (remote.TryGetVisitURL(out var url)) if (remote.TryGetVisitURL(out var url))
{ {
var trimmedUrl = url; var trimmedUrl = url.AsSpan();
if (url.EndsWith(".git")) if (url.EndsWith(".git"))
trimmedUrl = url.Substring(0, url.Length - 4); trimmedUrl = url.AsSpan(0, url.Length - 4);
if (url.StartsWith("https://github.com/", StringComparison.Ordinal)) if (url.StartsWith("https://github.com/", StringComparison.Ordinal))
outs.Add(new($"Github ({trimmedUrl.Substring(19)})", $"{url}/commit/")); outs.Add(new($"Github ({trimmedUrl.Slice(19)})", $"{url}/commit/"));
else if (url.StartsWith("https://gitlab.", StringComparison.Ordinal)) else if (url.StartsWith("https://gitlab.", StringComparison.Ordinal))
outs.Add(new($"GitLab ({trimmedUrl.Substring(trimmedUrl.Substring(15).IndexOf('/') + 16)})", $"{url}/-/commit/")); outs.Add(new($"GitLab ({trimmedUrl.Slice(trimmedUrl.Slice(15).IndexOf('/') + 16)})", $"{url}/-/commit/"));
else if (url.StartsWith("https://gitee.com/", StringComparison.Ordinal)) else if (url.StartsWith("https://gitee.com/", StringComparison.Ordinal))
outs.Add(new($"Gitee ({trimmedUrl.Substring(18)})", $"{url}/commit/")); outs.Add(new($"Gitee ({trimmedUrl.Slice(18)})", $"{url}/commit/"));
else if (url.StartsWith("https://bitbucket.org/", StringComparison.Ordinal)) else if (url.StartsWith("https://bitbucket.org/", StringComparison.Ordinal))
outs.Add(new($"BitBucket ({trimmedUrl.Substring(22)})", $"{url}/commits/")); outs.Add(new($"BitBucket ({trimmedUrl.Slice(22)})", $"{url}/commits/"));
else if (url.StartsWith("https://codeberg.org/", StringComparison.Ordinal)) else if (url.StartsWith("https://codeberg.org/", StringComparison.Ordinal))
outs.Add(new($"Codeberg ({trimmedUrl.Substring(21)})", $"{url}/commit/")); outs.Add(new($"Codeberg ({trimmedUrl.Slice(21)})", $"{url}/commit/"));
else if (url.StartsWith("https://gitea.org/", StringComparison.Ordinal)) else if (url.StartsWith("https://gitea.org/", StringComparison.Ordinal))
outs.Add(new($"Gitea ({trimmedUrl.Substring(18)})", $"{url}/commit/")); outs.Add(new($"Gitea ({trimmedUrl.Slice(18)})", $"{url}/commit/"));
else if (url.StartsWith("https://git.sr.ht/", StringComparison.Ordinal)) else if (url.StartsWith("https://git.sr.ht/", StringComparison.Ordinal))
outs.Add(new($"sourcehut ({trimmedUrl.Substring(18)})", $"{url}/commit/")); outs.Add(new($"sourcehut ({trimmedUrl.Slice(18)})", $"{url}/commit/"));
} }
} }

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
@ -38,6 +38,18 @@ namespace SourceGit.Models
set; set;
} = false; } = false;
public BranchSortMode LocalBranchSortMode
{
get;
set;
} = BranchSortMode.Name;
public BranchSortMode RemoteBranchSortMode
{
get;
set;
} = BranchSortMode.Name;
public TagSortMode TagSortMode public TagSortMode TagSortMode
{ {
get; get;
@ -110,6 +122,12 @@ namespace SourceGit.Models
set; set;
} = true; } = true;
public bool UpdateSubmodulesOnCheckoutBranch
{
get;
set;
} = true;
public AvaloniaList<Filter> HistoriesFilters public AvaloniaList<Filter> HistoriesFilters
{ {
get; get;
@ -326,28 +344,28 @@ namespace SourceGit.Models
if (filter.Mode == FilterMode.Included) if (filter.Mode == FilterMode.Included)
includedRefs.Add(filter.Pattern); includedRefs.Add(filter.Pattern);
else if (filter.Mode == FilterMode.Excluded) else if (filter.Mode == FilterMode.Excluded)
excludedBranches.Add($"--exclude=\"{filter.Pattern.Substring(11)}\" --decorate-refs-exclude=\"{filter.Pattern}\""); excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
} }
else if (filter.Type == FilterType.LocalBranchFolder) else if (filter.Type == FilterType.LocalBranchFolder)
{ {
if (filter.Mode == FilterMode.Included) if (filter.Mode == FilterMode.Included)
includedRefs.Add($"--branches={filter.Pattern.Substring(11)}/*"); includedRefs.Add($"--branches={filter.Pattern.AsSpan(11)}/*");
else if (filter.Mode == FilterMode.Excluded) else if (filter.Mode == FilterMode.Excluded)
excludedBranches.Add($"--exclude=\"{filter.Pattern.Substring(11)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\""); excludedBranches.Add($"--exclude=\"{filter.Pattern.AsSpan(11)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
} }
else if (filter.Type == FilterType.RemoteBranch) else if (filter.Type == FilterType.RemoteBranch)
{ {
if (filter.Mode == FilterMode.Included) if (filter.Mode == FilterMode.Included)
includedRefs.Add(filter.Pattern); includedRefs.Add(filter.Pattern);
else if (filter.Mode == FilterMode.Excluded) else if (filter.Mode == FilterMode.Excluded)
excludedRemotes.Add($"--exclude=\"{filter.Pattern.Substring(13)}\" --decorate-refs-exclude=\"{filter.Pattern}\""); excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}\" --decorate-refs-exclude=\"{filter.Pattern}\"");
} }
else if (filter.Type == FilterType.RemoteBranchFolder) else if (filter.Type == FilterType.RemoteBranchFolder)
{ {
if (filter.Mode == FilterMode.Included) if (filter.Mode == FilterMode.Included)
includedRefs.Add($"--remotes={filter.Pattern.Substring(13)}/*"); includedRefs.Add($"--remotes={filter.Pattern.AsSpan(13)}/*");
else if (filter.Mode == FilterMode.Excluded) else if (filter.Mode == FilterMode.Excluded)
excludedRemotes.Add($"--exclude=\"{filter.Pattern.Substring(13)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\""); excludedRemotes.Add($"--exclude=\"{filter.Pattern.AsSpan(13)}/*\" --decorate-refs-exclude=\"{filter.Pattern}/*\"");
} }
else if (filter.Type == FilterType.Tag) else if (filter.Type == FilterType.Tag)
{ {

View file

@ -40,6 +40,13 @@
<x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">KEINE ALS UNVERÄNDERT ANGENOMMENEN DATEIEN</x:String> <x:String x:Key="Text.AssumeUnchanged.Empty" xml:space="preserve">KEINE ALS UNVERÄNDERT ANGENOMMENEN DATEIEN</x:String>
<x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">ENTFERNEN</x:String> <x:String x:Key="Text.AssumeUnchanged.Remove" xml:space="preserve">ENTFERNEN</x:String>
<x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">BINÄRE DATEI NICHT UNTERSTÜTZT!!!</x:String> <x:String x:Key="Text.BinaryNotSupported" xml:space="preserve">BINÄRE DATEI NICHT UNTERSTÜTZT!!!</x:String>
<x:String x:Key="Text.Bisect">Bisect</x:String>
<x:String x:Key="Text.Bisect.Abort">Abbrechen</x:String>
<x:String x:Key="Text.Bisect.Bad">Schlecht</x:String>
<x:String x:Key="Text.Bisect.Detecting">Bisecting. Ist der aktuelle HEAD gut oder fehlerhaft?</x:String>
<x:String x:Key="Text.Bisect.Good">Gut</x:String>
<x:String x:Key="Text.Bisect.Skip">Überspringen</x:String>
<x:String x:Key="Text.Bisect.WaitingForRange">Bisecting. Aktuellen Commit als gut oder schlecht markieren und einen anderen auschecken.</x:String>
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String> <x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME WIRD BEI DIESER DATEI NICHT UNTERSTÜTZT!!!</x:String> <x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME WIRD BEI DIESER DATEI NICHT UNTERSTÜTZT!!!</x:String>
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Auschecken von ${0}$...</x:String> <x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Auschecken von ${0}$...</x:String>
@ -62,6 +69,7 @@
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Benenne ${0}$ um...</x:String> <x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Benenne ${0}$ um...</x:String>
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Setze verfolgten Branch...</x:String> <x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Setze verfolgten Branch...</x:String>
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Branch Vergleich</x:String> <x:String x:Key="Text.BranchCompare" xml:space="preserve">Branch Vergleich</x:String>
<x:String x:Key="Text.BranchUpstreamInvalid" xml:space="preserve">Ungültiger upstream!</x:String>
<x:String x:Key="Text.Bytes" xml:space="preserve">Bytes</x:String> <x:String x:Key="Text.Bytes" xml:space="preserve">Bytes</x:String>
<x:String x:Key="Text.Cancel" xml:space="preserve">ABBRECHEN</x:String> <x:String x:Key="Text.Cancel" xml:space="preserve">ABBRECHEN</x:String>
<x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">Auf Vorgänger-Revision zurücksetzen</x:String> <x:String x:Key="Text.ChangeCM.CheckoutFirstParentRevision" xml:space="preserve">Auf Vorgänger-Revision zurücksetzen</x:String>
@ -78,6 +86,7 @@
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Lokale Änderungen:</x:String> <x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Lokale Änderungen:</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Verwerfen</x:String> <x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Verwerfen</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stashen &amp; wieder anwenden</x:String> <x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stashen &amp; wieder anwenden</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Alle Submodule updaten</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branch:</x:String> <x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String> <x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Quelle an Commit-Nachricht anhängen</x:String> <x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Quelle an Commit-Nachricht anhängen</x:String>
@ -102,8 +111,11 @@
<x:String x:Key="Text.CommitCM.CherryPickMultiple" xml:space="preserve">Mehrere cherry-picken</x:String> <x:String x:Key="Text.CommitCM.CherryPickMultiple" xml:space="preserve">Mehrere cherry-picken</x:String>
<x:String x:Key="Text.CommitCM.CompareWithHead" xml:space="preserve">Mit HEAD vergleichen</x:String> <x:String x:Key="Text.CommitCM.CompareWithHead" xml:space="preserve">Mit HEAD vergleichen</x:String>
<x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Mit Worktree vergleichen</x:String> <x:String x:Key="Text.CommitCM.CompareWithWorktree" xml:space="preserve">Mit Worktree vergleichen</x:String>
<x:String x:Key="Text.CommitCM.CopyAuthor" xml:space="preserve">Author</x:String>
<x:String x:Key="Text.CommitCM.CopyCommitter" xml:space="preserve">Committer</x:String>
<x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">Information</x:String> <x:String x:Key="Text.CommitCM.CopyInfo" xml:space="preserve">Information</x:String>
<x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">SHA</x:String> <x:String x:Key="Text.CommitCM.CopySHA" xml:space="preserve">SHA</x:String>
<x:String x:Key="Text.CommitCM.CopySubject" xml:space="preserve">Betreff</x:String>
<x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">Benutzerdefinierte Aktion</x:String> <x:String x:Key="Text.CommitCM.CustomAction" xml:space="preserve">Benutzerdefinierte Aktion</x:String>
<x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Interactives Rebase von ${0}$ auf diesen Commit</x:String> <x:String x:Key="Text.CommitCM.InteractiveRebase" xml:space="preserve">Interactives Rebase von ${0}$ auf diesen Commit</x:String>
<x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">Merge in ${0}$ hinein</x:String> <x:String x:Key="Text.CommitCM.Merge" xml:space="preserve">Merge in ${0}$ hinein</x:String>
@ -135,6 +147,7 @@
<x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">SHA</x:String> <x:String x:Key="Text.CommitDetail.Info.SHA" xml:space="preserve">SHA</x:String>
<x:String x:Key="Text.CommitDetail.Info.WebLinks" xml:space="preserve">Im Browser öffnen</x:String> <x:String x:Key="Text.CommitDetail.Info.WebLinks" xml:space="preserve">Im Browser öffnen</x:String>
<x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">Details</x:String> <x:String x:Key="Text.CommitMessageTextBox.MessagePlaceholder" xml:space="preserve">Details</x:String>
<x:String x:Key="Text.CommitMessageTextBox.SubjectCount" xml:space="preserve">Betreff</x:String>
<x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">Commit-Nachricht</x:String> <x:String x:Key="Text.CommitMessageTextBox.SubjectPlaceholder" xml:space="preserve">Commit-Nachricht</x:String>
<x:String x:Key="Text.Configure" xml:space="preserve">Repository Einstellungen</x:String> <x:String x:Key="Text.Configure" xml:space="preserve">Repository Einstellungen</x:String>
<x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">COMMIT TEMPLATE</x:String> <x:String x:Key="Text.Configure.CommitMessageTemplate" xml:space="preserve">COMMIT TEMPLATE</x:String>
@ -149,13 +162,16 @@
<x:String x:Key="Text.Configure.CustomAction.Scope.Branch" xml:space="preserve">Branch</x:String> <x:String x:Key="Text.Configure.CustomAction.Scope.Branch" xml:space="preserve">Branch</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">Commit</x:String> <x:String x:Key="Text.Configure.CustomAction.Scope.Commit" xml:space="preserve">Commit</x:String>
<x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">Repository</x:String> <x:String x:Key="Text.Configure.CustomAction.Scope.Repository" xml:space="preserve">Repository</x:String>
<x:String x:Key="Text.Configure.CustomAction.WaitForExit" xml:space="preserve">Auf Beenden der Aktion warten</x:String>
<x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Adresse</x:String> <x:String x:Key="Text.Configure.Email" xml:space="preserve">Email Adresse</x:String>
<x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Email Adresse</x:String> <x:String x:Key="Text.Configure.Email.Placeholder" xml:space="preserve">Email Adresse</x:String>
<x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String> <x:String x:Key="Text.Configure.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">Remotes automatisch fetchen</x:String> <x:String x:Key="Text.Configure.Git.AutoFetch" xml:space="preserve">Remotes automatisch fetchen</x:String>
<x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">Minute(n)</x:String> <x:String x:Key="Text.Configure.Git.AutoFetchIntervalSuffix" xml:space="preserve">Minute(n)</x:String>
<x:String x:Key="Text.Configure.Git.DefaultRemote" xml:space="preserve">Standard Remote</x:String> <x:String x:Key="Text.Configure.Git.DefaultRemote" xml:space="preserve">Standard Remote</x:String>
<x:String x:Key="Text.Configure.Git.PreferredMergeMode" xml:space="preserve">Bevorzugter Merge Modus</x:String>
<x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">TICKETSYSTEM</x:String> <x:String x:Key="Text.Configure.IssueTracker" xml:space="preserve">TICKETSYSTEM</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleAzure" xml:space="preserve">Beispiel Azure DevOps Rule hinzufügen</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGiteeIssue" xml:space="preserve">Beispiel für Gitee Issue Regel einfügen</x:String> <x:String x:Key="Text.Configure.IssueTracker.AddSampleGiteeIssue" xml:space="preserve">Beispiel für Gitee Issue Regel einfügen</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGiteePullRequest" xml:space="preserve">Beispiel für Gitee Pull Request Regel einfügen</x:String> <x:String x:Key="Text.Configure.IssueTracker.AddSampleGiteePullRequest" xml:space="preserve">Beispiel für Gitee Pull Request Regel einfügen</x:String>
<x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Beispiel für Github-Regel hinzufügen</x:String> <x:String x:Key="Text.Configure.IssueTracker.AddSampleGithub" xml:space="preserve">Beispiel für Github-Regel hinzufügen</x:String>
@ -178,6 +194,10 @@
<x:String x:Key="Text.ConfigureWorkspace.Color" xml:space="preserve">Farbe</x:String> <x:String x:Key="Text.ConfigureWorkspace.Color" xml:space="preserve">Farbe</x:String>
<x:String x:Key="Text.ConfigureWorkspace.Name" xml:space="preserve">Name</x:String> <x:String x:Key="Text.ConfigureWorkspace.Name" xml:space="preserve">Name</x:String>
<x:String x:Key="Text.ConfigureWorkspace.Restore" xml:space="preserve">Zuletzt geöffnete Tabs beim Starten wiederherstellen</x:String> <x:String x:Key="Text.ConfigureWorkspace.Restore" xml:space="preserve">Zuletzt geöffnete Tabs beim Starten wiederherstellen</x:String>
<x:String x:Key="Text.ConfirmEmptyCommit.Continue" xml:space="preserve">WEITER</x:String>
<x:String x:Key="Text.ConfirmEmptyCommit.NoLocalChanges" xml:space="preserve">Leerer Commit erkannt! Möchtest du trotzdem fortfahren (--allow-empty)?</x:String>
<x:String x:Key="Text.ConfirmEmptyCommit.StageAllThenCommit" xml:space="preserve">ALLES STAGEN &amp; COMMITTEN</x:String>
<x:String x:Key="Text.ConfirmEmptyCommit.WithLocalChanges" xml:space="preserve">Leerer Commit erkannt! Möchtest du trotzdem fortfahren (--allow-empty) oder alle Änderungen stagen und dann committen?</x:String>
<x:String x:Key="Text.ConventionalCommit" xml:space="preserve">Konventionelle Commit-Hilfe</x:String> <x:String x:Key="Text.ConventionalCommit" xml:space="preserve">Konventionelle Commit-Hilfe</x:String>
<x:String x:Key="Text.ConventionalCommit.BreakingChanges" xml:space="preserve">Breaking Change:</x:String> <x:String x:Key="Text.ConventionalCommit.BreakingChanges" xml:space="preserve">Breaking Change:</x:String>
<x:String x:Key="Text.ConventionalCommit.ClosedIssue" xml:space="preserve">Geschlossenes Ticket:</x:String> <x:String x:Key="Text.ConventionalCommit.ClosedIssue" xml:space="preserve">Geschlossenes Ticket:</x:String>
@ -187,6 +207,7 @@
<x:String x:Key="Text.ConventionalCommit.Type" xml:space="preserve">Typ der Änderung:</x:String> <x:String x:Key="Text.ConventionalCommit.Type" xml:space="preserve">Typ der Änderung:</x:String>
<x:String x:Key="Text.Copy" xml:space="preserve">Kopieren</x:String> <x:String x:Key="Text.Copy" xml:space="preserve">Kopieren</x:String>
<x:String x:Key="Text.CopyAllText" xml:space="preserve">Kopiere gesamten Text</x:String> <x:String x:Key="Text.CopyAllText" xml:space="preserve">Kopiere gesamten Text</x:String>
<x:String x:Key="Text.CopyFullPath" xml:space="preserve">Ganzen Pfad kopieren</x:String>
<x:String x:Key="Text.CopyPath" xml:space="preserve">Pfad kopieren</x:String> <x:String x:Key="Text.CopyPath" xml:space="preserve">Pfad kopieren</x:String>
<x:String x:Key="Text.CreateBranch" xml:space="preserve">Branch erstellen...</x:String> <x:String x:Key="Text.CreateBranch" xml:space="preserve">Branch erstellen...</x:String>
<x:String x:Key="Text.CreateBranch.BasedOn" xml:space="preserve">Basierend auf:</x:String> <x:String x:Key="Text.CreateBranch.BasedOn" xml:space="preserve">Basierend auf:</x:String>
@ -236,7 +257,9 @@
<x:String x:Key="Text.Diff.Binary.Old" xml:space="preserve">ALT</x:String> <x:String x:Key="Text.Diff.Binary.Old" xml:space="preserve">ALT</x:String>
<x:String x:Key="Text.Diff.Copy" xml:space="preserve">Kopieren</x:String> <x:String x:Key="Text.Diff.Copy" xml:space="preserve">Kopieren</x:String>
<x:String x:Key="Text.Diff.FileModeChanged" xml:space="preserve">Dateimodus geändert</x:String> <x:String x:Key="Text.Diff.FileModeChanged" xml:space="preserve">Dateimodus geändert</x:String>
<x:String x:Key="Text.Diff.First" xml:space="preserve">Erste Differenz</x:String>
<x:String x:Key="Text.Diff.IgnoreWhitespace" xml:space="preserve">Ignoriere Leerzeichenänderungen</x:String> <x:String x:Key="Text.Diff.IgnoreWhitespace" xml:space="preserve">Ignoriere Leerzeichenänderungen</x:String>
<x:String x:Key="Text.Diff.Last" xml:space="preserve">Letzte Differenz</x:String>
<x:String x:Key="Text.Diff.LFS" xml:space="preserve">LFS OBJEKT ÄNDERUNG</x:String> <x:String x:Key="Text.Diff.LFS" xml:space="preserve">LFS OBJEKT ÄNDERUNG</x:String>
<x:String x:Key="Text.Diff.Next" xml:space="preserve">Nächste Änderung</x:String> <x:String x:Key="Text.Diff.Next" xml:space="preserve">Nächste Änderung</x:String>
<x:String x:Key="Text.Diff.NoChange" xml:space="preserve">KEINE ÄNDERUNG ODER NUR ZEILEN-ENDE ÄNDERUNGEN</x:String> <x:String x:Key="Text.Diff.NoChange" xml:space="preserve">KEINE ÄNDERUNG ODER NUR ZEILEN-ENDE ÄNDERUNGEN</x:String>
@ -447,8 +470,10 @@
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Modell</x:String> <x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Modell</x:String>
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Name</x:String> <x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Name</x:String>
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Server</x:String> <x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Server</x:String>
<x:String x:Key="Text.Preferences.AI.Streaming" xml:space="preserve">Streaming aktivieren</x:String>
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">DARSTELLUNG</x:String> <x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">DARSTELLUNG</x:String>
<x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Standardschriftart</x:String> <x:String x:Key="Text.Preferences.Appearance.DefaultFont" xml:space="preserve">Standardschriftart</x:String>
<x:String x:Key="Text.Preferences.Appearance.EditorTabWidth" xml:space="preserve">Editor Tab Breite</x:String>
<x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Schriftgröße</x:String> <x:String x:Key="Text.Preferences.Appearance.FontSize" xml:space="preserve">Schriftgröße</x:String>
<x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">Standard</x:String> <x:String x:Key="Text.Preferences.Appearance.FontSize.Default" xml:space="preserve">Standard</x:String>
<x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">Texteditor</x:String> <x:String x:Key="Text.Preferences.Appearance.FontSize.Editor" xml:space="preserve">Texteditor</x:String>
@ -469,6 +494,7 @@
<x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">Commit-Historie</x:String> <x:String x:Key="Text.Preferences.General.MaxHistoryCommits" xml:space="preserve">Commit-Historie</x:String>
<x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">Zeige Autor Zeitpunkt anstatt Commit Zeitpunkt</x:String> <x:String x:Key="Text.Preferences.General.ShowAuthorTime" xml:space="preserve">Zeige Autor Zeitpunkt anstatt Commit Zeitpunkt</x:String>
<x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">Zeige Nachfolger in den Commit Details</x:String> <x:String x:Key="Text.Preferences.General.ShowChildren" xml:space="preserve">Zeige Nachfolger in den Commit Details</x:String>
<x:String x:Key="Text.Preferences.General.ShowTagsInGraph" xml:space="preserve">Zeige Tags im Commit Graph</x:String>
<x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">Längenvorgabe für Commit-Nachrichten</x:String> <x:String x:Key="Text.Preferences.General.SubjectGuideLength" xml:space="preserve">Längenvorgabe für Commit-Nachrichten</x:String>
<x:String x:Key="Text.Preferences.Git" xml:space="preserve">GIT</x:String> <x:String x:Key="Text.Preferences.Git" xml:space="preserve">GIT</x:String>
<x:String x:Key="Text.Preferences.Git.CRLF" xml:space="preserve">Aktiviere Auto-CRLF</x:String> <x:String x:Key="Text.Preferences.Git.CRLF" xml:space="preserve">Aktiviere Auto-CRLF</x:String>
@ -476,6 +502,7 @@
<x:String x:Key="Text.Preferences.Git.Email" xml:space="preserve">Benutzer Email</x:String> <x:String x:Key="Text.Preferences.Git.Email" xml:space="preserve">Benutzer Email</x:String>
<x:String x:Key="Text.Preferences.Git.Email.Placeholder" xml:space="preserve">Globale Git Benutzer Email</x:String> <x:String x:Key="Text.Preferences.Git.Email.Placeholder" xml:space="preserve">Globale Git Benutzer Email</x:String>
<x:String x:Key="Text.Preferences.Git.EnablePruneOnFetch" xml:space="preserve">Aktivere --prune beim fetchen</x:String> <x:String x:Key="Text.Preferences.Git.EnablePruneOnFetch" xml:space="preserve">Aktivere --prune beim fetchen</x:String>
<x:String x:Key="Text.Preferences.Git.IgnoreCRAtEOLInDiff" xml:space="preserve">Aktiviere --ignore-cr-at-eol beim Unterschied</x:String>
<x:String x:Key="Text.Preferences.Git.Invalid" xml:space="preserve">Diese App setzt Git (&gt;= 2.23.0) voraus</x:String> <x:String x:Key="Text.Preferences.Git.Invalid" xml:space="preserve">Diese App setzt Git (&gt;= 2.23.0) voraus</x:String>
<x:String x:Key="Text.Preferences.Git.Path" xml:space="preserve">Installationspfad</x:String> <x:String x:Key="Text.Preferences.Git.Path" xml:space="preserve">Installationspfad</x:String>
<x:String x:Key="Text.Preferences.Git.SSLVerify" xml:space="preserve">Aktiviere HTTP SSL Verifizierung</x:String> <x:String x:Key="Text.Preferences.Git.SSLVerify" xml:space="preserve">Aktiviere HTTP SSL Verifizierung</x:String>
@ -549,6 +576,9 @@
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Branch:</x:String> <x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">ABBRECHEN</x:String> <x:String x:Key="Text.Repository.Abort" xml:space="preserve">ABBRECHEN</x:String>
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Änderungen automatisch von Remote fetchen...</x:String> <x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Änderungen automatisch von Remote fetchen...</x:String>
<x:String x:Key="Text.Repository.BranchSort" xml:space="preserve">Sortieren</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByCommitterDate" xml:space="preserve">Nach Commit Datum</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByName" xml:space="preserve">Nach Name</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Aufräumen (GC &amp; Prune)</x:String> <x:String x:Key="Text.Repository.Clean" xml:space="preserve">Aufräumen (GC &amp; Prune)</x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Führt `git gc` auf diesem Repository aus.</x:String> <x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Führt `git gc` auf diesem Repository aus.</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Filter aufheben</x:String> <x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Filter aufheben</x:String>
@ -583,6 +613,7 @@
<x:String x:Key="Text.Repository.Search" xml:space="preserve">Commit suchen</x:String> <x:String x:Key="Text.Repository.Search" xml:space="preserve">Commit suchen</x:String>
<x:String x:Key="Text.Repository.Search.ByAuthor" xml:space="preserve">Autor</x:String> <x:String x:Key="Text.Repository.Search.ByAuthor" xml:space="preserve">Autor</x:String>
<x:String x:Key="Text.Repository.Search.ByCommitter" xml:space="preserve">Committer</x:String> <x:String x:Key="Text.Repository.Search.ByCommitter" xml:space="preserve">Committer</x:String>
<x:String x:Key="Text.Repository.Search.ByContent" xml:space="preserve">Inhalt</x:String>
<x:String x:Key="Text.Repository.Search.ByFile" xml:space="preserve">Dateiname</x:String> <x:String x:Key="Text.Repository.Search.ByFile" xml:space="preserve">Dateiname</x:String>
<x:String x:Key="Text.Repository.Search.ByMessage" xml:space="preserve">Commit-Nachricht</x:String> <x:String x:Key="Text.Repository.Search.ByMessage" xml:space="preserve">Commit-Nachricht</x:String>
<x:String x:Key="Text.Repository.Search.BySHA" xml:space="preserve">SHA</x:String> <x:String x:Key="Text.Repository.Search.BySHA" xml:space="preserve">SHA</x:String>
@ -601,6 +632,8 @@
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Sortiere</x:String> <x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Sortiere</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Öffne im Terminal</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Öffne im Terminal</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Verwende relative Zeitangaben in Verlauf</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Verwende relative Zeitangaben in Verlauf</x:String>
<x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">Logs ansehen</x:String>
<x:String x:Key="Text.Repository.Visit" xml:space="preserve">Öffne '{0}' im Browser</x:String>
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">WORKTREES</x:String> <x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">WORKTREES</x:String>
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">WORKTREE HINZUFÜGEN</x:String> <x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">WORKTREE HINZUFÜGEN</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">PRUNE</x:String> <x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">PRUNE</x:String>
@ -651,6 +684,7 @@
<x:String x:Key="Text.Stash.Title" xml:space="preserve">Lokale Änderungen stashen</x:String> <x:String x:Key="Text.Stash.Title" xml:space="preserve">Lokale Änderungen stashen</x:String>
<x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Anwenden</x:String> <x:String x:Key="Text.StashCM.Apply" xml:space="preserve">Anwenden</x:String>
<x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Entfernen</x:String> <x:String x:Key="Text.StashCM.Drop" xml:space="preserve">Entfernen</x:String>
<x:String x:Key="Text.StashCM.SaveAsPatch" xml:space="preserve">Als Path speichern...</x:String>
<x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Stash entfernen</x:String> <x:String x:Key="Text.StashDropConfirm" xml:space="preserve">Stash entfernen</x:String>
<x:String x:Key="Text.StashDropConfirm.Label" xml:space="preserve">Entfernen:</x:String> <x:String x:Key="Text.StashDropConfirm.Label" xml:space="preserve">Entfernen:</x:String>
<x:String x:Key="Text.Stashes" xml:space="preserve">Stashes</x:String> <x:String x:Key="Text.Stashes" xml:space="preserve">Stashes</x:String>
@ -685,6 +719,10 @@
<x:String x:Key="Text.UpdateSubmodules.Target" xml:space="preserve">Submodul:</x:String> <x:String x:Key="Text.UpdateSubmodules.Target" xml:space="preserve">Submodul:</x:String>
<x:String x:Key="Text.UpdateSubmodules.UseRemote" xml:space="preserve">Verwende `--remote` Option</x:String> <x:String x:Key="Text.UpdateSubmodules.UseRemote" xml:space="preserve">Verwende `--remote` Option</x:String>
<x:String x:Key="Text.URL" xml:space="preserve">URL:</x:String> <x:String x:Key="Text.URL" xml:space="preserve">URL:</x:String>
<x:String x:Key="Text.ViewLogs" xml:space="preserve">Logs</x:String>
<x:String x:Key="Text.ViewLogs.Clear" xml:space="preserve">ALLES LÖSCHEN</x:String>
<x:String x:Key="Text.ViewLogs.CopyLog" xml:space="preserve">Kopieren</x:String>
<x:String x:Key="Text.ViewLogs.Delete" xml:space="preserve">Löschen</x:String>
<x:String x:Key="Text.Warn" xml:space="preserve">Warnung</x:String> <x:String x:Key="Text.Warn" xml:space="preserve">Warnung</x:String>
<x:String x:Key="Text.Welcome" xml:space="preserve">Willkommensseite</x:String> <x:String x:Key="Text.Welcome" xml:space="preserve">Willkommensseite</x:String>
<x:String x:Key="Text.Welcome.AddRootFolder" xml:space="preserve">Erstelle Gruppe</x:String> <x:String x:Key="Text.Welcome.AddRootFolder" xml:space="preserve">Erstelle Gruppe</x:String>
@ -714,8 +752,13 @@
<x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">Klick-Ereignis auslösen</x:String> <x:String x:Key="Text.WorkingCopy.CommitTip" xml:space="preserve">Klick-Ereignis auslösen</x:String>
<x:String x:Key="Text.WorkingCopy.CommitToEdit" xml:space="preserve">Commit (Bearbeitung)</x:String> <x:String x:Key="Text.WorkingCopy.CommitToEdit" xml:space="preserve">Commit (Bearbeitung)</x:String>
<x:String x:Key="Text.WorkingCopy.CommitWithAutoStage" xml:space="preserve">Alle Änderungen stagen und committen</x:String> <x:String x:Key="Text.WorkingCopy.CommitWithAutoStage" xml:space="preserve">Alle Änderungen stagen und committen</x:String>
<x:String x:Key="Text.WorkingCopy.ConfirmCommitWithFilter">Du hast {0} Datei(en) gestaged, aber nur {1} werden angezeigt ({2} sind herausgefiltert). Willst du trotzdem fortfahren?</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">KONFLIKTE ERKANNT</x:String> <x:String x:Key="Text.WorkingCopy.Conflicts" xml:space="preserve">KONFLIKTE ERKANNT</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.OpenExternalMergeTool" xml:space="preserve">EXTERNES MERGE-TOOL ÖFFNEN</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.OpenExternalMergeToolAllConflicts" xml:space="preserve">ALLE KONFLIKTE IN EXTERNEM MERGE-TOOL ÖFFNEN</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">DATEI KONFLIKTE GELÖST</x:String> <x:String x:Key="Text.WorkingCopy.Conflicts.Resolved" xml:space="preserve">DATEI KONFLIKTE GELÖST</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.UseMine" xml:space="preserve">MEINE VERSION VERWENDEN</x:String>
<x:String x:Key="Text.WorkingCopy.Conflicts.UseTheirs" xml:space="preserve">DEREN VERSION VERWENDEN</x:String>
<x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">NICHT-VERFOLGTE DATEIEN INKLUDIEREN</x:String> <x:String x:Key="Text.WorkingCopy.IncludeUntracked" xml:space="preserve">NICHT-VERFOLGTE DATEIEN INKLUDIEREN</x:String>
<x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">KEINE BISHERIGEN COMMIT-NACHRICHTEN</x:String> <x:String x:Key="Text.WorkingCopy.NoCommitHistories" xml:space="preserve">KEINE BISHERIGEN COMMIT-NACHRICHTEN</x:String>
<x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">KEINE COMMIT TEMPLATES</x:String> <x:String x:Key="Text.WorkingCopy.NoCommitTemplates" xml:space="preserve">KEINE COMMIT TEMPLATES</x:String>

View file

@ -82,6 +82,7 @@
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Local Changes:</x:String> <x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Local Changes:</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Discard</x:String> <x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Discard</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reapply</x:String> <x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Stash &amp; Reapply</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Update all submodules</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branch:</x:String> <x:String x:Key="Text.Checkout.Target" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String> <x:String x:Key="Text.CherryPick" xml:space="preserve">Cherry Pick</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Append source to commit message</x:String> <x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Append source to commit message</x:String>
@ -322,6 +323,8 @@
<x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">FLOW - Finish Hotfix</x:String> <x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">FLOW - Finish Hotfix</x:String>
<x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">FLOW - Finish Release</x:String> <x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">FLOW - Finish Release</x:String>
<x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">Target:</x:String> <x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">Target:</x:String>
<x:String x:Key="Text.GitFlow.FinishWithPush" xml:space="preserve">Push to remote(s) after performing finish</x:String>
<x:String x:Key="Text.GitFlow.FinishWithSquash" xml:space="preserve">Squash during merge</x:String>
<x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">Hotfix:</x:String> <x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">Hotfix:</x:String>
<x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">Hotfix Prefix:</x:String> <x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">Hotfix Prefix:</x:String>
<x:String x:Key="Text.GitFlow.Init" xml:space="preserve">Initialize Git-Flow</x:String> <x:String x:Key="Text.GitFlow.Init" xml:space="preserve">Initialize Git-Flow</x:String>
@ -571,6 +574,9 @@
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Branch:</x:String> <x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Branch:</x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">ABORT</x:String> <x:String x:Key="Text.Repository.Abort" xml:space="preserve">ABORT</x:String>
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Auto fetching changes from remotes...</x:String> <x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Auto fetching changes from remotes...</x:String>
<x:String x:Key="Text.Repository.BranchSort" xml:space="preserve">Sort</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByCommitterDate" xml:space="preserve">By Committer Date</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByName" xml:space="preserve">By Name</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Cleanup(GC &amp; Prune)</x:String> <x:String x:Key="Text.Repository.Clean" xml:space="preserve">Cleanup(GC &amp; Prune)</x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Run `git gc` command for this repository.</x:String> <x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Run `git gc` command for this repository.</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Clear all</x:String> <x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Clear all</x:String>
@ -601,7 +607,7 @@
<x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Open in External Tools</x:String> <x:String x:Key="Text.Repository.OpenWithExternalTools" xml:space="preserve">Open in External Tools</x:String>
<x:String x:Key="Text.Repository.Refresh" xml:space="preserve">Refresh</x:String> <x:String x:Key="Text.Repository.Refresh" xml:space="preserve">Refresh</x:String>
<x:String x:Key="Text.Repository.Remotes" xml:space="preserve">REMOTES</x:String> <x:String x:Key="Text.Repository.Remotes" xml:space="preserve">REMOTES</x:String>
<x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">ADD REMOTE</x:String> <x:String x:Key="Text.Repository.Remotes.Add" xml:space="preserve">Add Remote</x:String>
<x:String x:Key="Text.Repository.Search" xml:space="preserve">Search Commit</x:String> <x:String x:Key="Text.Repository.Search" xml:space="preserve">Search Commit</x:String>
<x:String x:Key="Text.Repository.Search.ByAuthor" xml:space="preserve">Author</x:String> <x:String x:Key="Text.Repository.Search.ByAuthor" xml:space="preserve">Author</x:String>
<x:String x:Key="Text.Repository.Search.ByCommitter" xml:space="preserve">Committer</x:String> <x:String x:Key="Text.Repository.Search.ByCommitter" xml:space="preserve">Committer</x:String>
@ -614,10 +620,10 @@
<x:String x:Key="Text.Repository.Skip" xml:space="preserve">SKIP</x:String> <x:String x:Key="Text.Repository.Skip" xml:space="preserve">SKIP</x:String>
<x:String x:Key="Text.Repository.Statistics" xml:space="preserve">Statistics</x:String> <x:String x:Key="Text.Repository.Statistics" xml:space="preserve">Statistics</x:String>
<x:String x:Key="Text.Repository.Submodules" xml:space="preserve">SUBMODULES</x:String> <x:String x:Key="Text.Repository.Submodules" xml:space="preserve">SUBMODULES</x:String>
<x:String x:Key="Text.Repository.Submodules.Add" xml:space="preserve">ADD SUBMODULE</x:String> <x:String x:Key="Text.Repository.Submodules.Add" xml:space="preserve">Add Submodule</x:String>
<x:String x:Key="Text.Repository.Submodules.Update" xml:space="preserve">UPDATE SUBMODULE</x:String> <x:String x:Key="Text.Repository.Submodules.Update" xml:space="preserve">Update Submodule</x:String>
<x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String> <x:String x:Key="Text.Repository.Tags" xml:space="preserve">TAGS</x:String>
<x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">NEW TAG</x:String> <x:String x:Key="Text.Repository.Tags.Add" xml:space="preserve">New Tag</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">By Creator Date</x:String> <x:String x:Key="Text.Repository.Tags.OrderByCreatorDate" xml:space="preserve">By Creator Date</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">By Name (Ascending)</x:String> <x:String x:Key="Text.Repository.Tags.OrderByNameAsc" xml:space="preserve">By Name (Ascending)</x:String>
<x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">By Name (Descending)</x:String> <x:String x:Key="Text.Repository.Tags.OrderByNameDes" xml:space="preserve">By Name (Descending)</x:String>
@ -625,9 +631,10 @@
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Open in Terminal</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Open in Terminal</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Use relative time in histories</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Use relative time in histories</x:String>
<x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">View Logs</x:String> <x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">View Logs</x:String>
<x:String x:Key="Text.Repository.Visit" xml:space="preserve">Visit '{0}' in Browser</x:String>
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">WORKTREES</x:String> <x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">WORKTREES</x:String>
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">ADD WORKTREE</x:String> <x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">Add Worktree</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">PRUNE</x:String> <x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">Prune</x:String>
<x:String x:Key="Text.RepositoryURL" xml:space="preserve">Git Repository URL</x:String> <x:String x:Key="Text.RepositoryURL" xml:space="preserve">Git Repository URL</x:String>
<x:String x:Key="Text.Reset" xml:space="preserve">Reset Current Branch To Revision</x:String> <x:String x:Key="Text.Reset" xml:space="preserve">Reset Current Branch To Revision</x:String>
<x:String x:Key="Text.Reset.Mode" xml:space="preserve">Reset Mode:</x:String> <x:String x:Key="Text.Reset.Mode" xml:space="preserve">Reset Mode:</x:String>

View file

@ -86,6 +86,7 @@
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Локальные изменения:</x:String> <x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">Локальные изменения:</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Отклонить</x:String> <x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">Отклонить</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Отложить и примненить повторно</x:String> <x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">Отложить и примненить повторно</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">Обновить все подкаталоги</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">Ветка:</x:String> <x:String x:Key="Text.Checkout.Target" xml:space="preserve">Ветка:</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve"> Частичный выбор</x:String> <x:String x:Key="Text.CherryPick" xml:space="preserve"> Частичный выбор</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Добавить источник для ревизии сообщения</x:String> <x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">Добавить источник для ревизии сообщения</x:String>
@ -575,6 +576,9 @@
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Ветка:</x:String> <x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">Ветка:</x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">Отказ</x:String> <x:String x:Key="Text.Repository.Abort" xml:space="preserve">Отказ</x:String>
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Автоматическое извлечение изменений с внешних репозиторий...</x:String> <x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">Автоматическое извлечение изменений с внешних репозиторий...</x:String>
<x:String x:Key="Text.Repository.BranchSort" xml:space="preserve">Сортировать</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByCommitterDate" xml:space="preserve">По дате ревизора (исполнителя)</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByName" xml:space="preserve">По имени</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">Очистить (Сбор мусора и удаление) </x:String> <x:String x:Key="Text.Repository.Clean" xml:space="preserve">Очистить (Сбор мусора и удаление) </x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Запустить команду (git gc) для данного репозитория.</x:String> <x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">Запустить команду (git gc) для данного репозитория.</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Очистить всё</x:String> <x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">Очистить всё</x:String>
@ -628,7 +632,8 @@
<x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Сортировать</x:String> <x:String x:Key="Text.Repository.Tags.Sort" xml:space="preserve">Сортировать</x:String>
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Открыть в терминале</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">Открыть в терминале</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Использовать относительное время в историях</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">Использовать относительное время в историях</x:String>
<x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">Просмотр логов</x:String> <x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">Просмотр журналов</x:String>
<x:String x:Key="Text.Repository.Visit" xml:space="preserve">Посетить '{0}' в браузере</x:String>
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">РАБОЧИЕ КАТАЛОГИ</x:String> <x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">РАБОЧИЕ КАТАЛОГИ</x:String>
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">ДОБАВИТЬ РАБОЧИЙ КАТАЛОГ</x:String> <x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">ДОБАВИТЬ РАБОЧИЙ КАТАЛОГ</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">ОБРЕЗАТЬ</x:String> <x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">ОБРЕЗАТЬ</x:String>
@ -714,7 +719,7 @@
<x:String x:Key="Text.UpdateSubmodules.Target" xml:space="preserve">Подмодуль:</x:String> <x:String x:Key="Text.UpdateSubmodules.Target" xml:space="preserve">Подмодуль:</x:String>
<x:String x:Key="Text.UpdateSubmodules.UseRemote" xml:space="preserve">Использовать опцию (--remote)</x:String> <x:String x:Key="Text.UpdateSubmodules.UseRemote" xml:space="preserve">Использовать опцию (--remote)</x:String>
<x:String x:Key="Text.URL" xml:space="preserve">Сетевой адрес:</x:String> <x:String x:Key="Text.URL" xml:space="preserve">Сетевой адрес:</x:String>
<x:String x:Key="Text.ViewLogs" xml:space="preserve">Логи</x:String> <x:String x:Key="Text.ViewLogs" xml:space="preserve">Журналы</x:String>
<x:String x:Key="Text.ViewLogs.Clear" xml:space="preserve">ОЧИСТИТЬ ВСЁ</x:String> <x:String x:Key="Text.ViewLogs.Clear" xml:space="preserve">ОЧИСТИТЬ ВСЁ</x:String>
<x:String x:Key="Text.ViewLogs.CopyLog" xml:space="preserve">Копировать</x:String> <x:String x:Key="Text.ViewLogs.CopyLog" xml:space="preserve">Копировать</x:String>
<x:String x:Key="Text.ViewLogs.Delete" xml:space="preserve">Удалить</x:String> <x:String x:Key="Text.ViewLogs.Delete" xml:space="preserve">Удалить</x:String>

View file

@ -86,6 +86,7 @@
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">未提交更改 </x:String> <x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">未提交更改 </x:String>
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">丢弃更改</x:String> <x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">丢弃更改</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">贮藏并自动恢复</x:String> <x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">贮藏并自动恢复</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">同时更新所有子模块</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">目标分支 </x:String> <x:String x:Key="Text.Checkout.Target" xml:space="preserve">目标分支 </x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">挑选提交</x:String> <x:String x:Key="Text.CherryPick" xml:space="preserve">挑选提交</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">提交信息中追加来源信息</x:String> <x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">提交信息中追加来源信息</x:String>
@ -326,6 +327,8 @@
<x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">结束修复分支</x:String> <x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">结束修复分支</x:String>
<x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">结束版本分支</x:String> <x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">结束版本分支</x:String>
<x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">目标分支 </x:String> <x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">目标分支 </x:String>
<x:String x:Key="Text.GitFlow.FinishWithPush" xml:space="preserve">完成后自动推送</x:String>
<x:String x:Key="Text.GitFlow.FinishWithSquash" xml:space="preserve">压缩变更为单一提交后合并分支</x:String>
<x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">修复分支 </x:String> <x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">修复分支 </x:String>
<x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">修复分支名前缀 </x:String> <x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">修复分支名前缀 </x:String>
<x:String x:Key="Text.GitFlow.Init" xml:space="preserve">初始化GIT工作流</x:String> <x:String x:Key="Text.GitFlow.Init" xml:space="preserve">初始化GIT工作流</x:String>
@ -575,6 +578,9 @@
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">分支 </x:String> <x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">分支 </x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">终止合并</x:String> <x:String x:Key="Text.Repository.Abort" xml:space="preserve">终止合并</x:String>
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">自动拉取远端变更中...</x:String> <x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">自动拉取远端变更中...</x:String>
<x:String x:Key="Text.Repository.BranchSort" xml:space="preserve">排序方式</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByCommitterDate" xml:space="preserve">按提交时间</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByName" xml:space="preserve">按名称</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">清理本仓库(GC)</x:String> <x:String x:Key="Text.Repository.Clean" xml:space="preserve">清理本仓库(GC)</x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">本操作将执行`git gc`命令。</x:String> <x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">本操作将执行`git gc`命令。</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空过滤规则</x:String> <x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空过滤规则</x:String>
@ -629,6 +635,7 @@
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">在终端中打开</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">在终端中打开</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">在提交列表中使用相对时间</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">在提交列表中使用相对时间</x:String>
<x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">查看命令日志</x:String> <x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">查看命令日志</x:String>
<x:String x:Key="Text.Repository.Visit" xml:space="preserve">访问远程仓库 '{0}'</x:String>
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">工作树列表</x:String> <x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">工作树列表</x:String>
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">新增工作树</x:String> <x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">新增工作树</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">清理</x:String> <x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">清理</x:String>

View file

@ -86,6 +86,7 @@
<x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">未提交變更:</x:String> <x:String x:Key="Text.Checkout.LocalChanges" xml:space="preserve">未提交變更:</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">捨棄變更</x:String> <x:String x:Key="Text.Checkout.LocalChanges.Discard" xml:space="preserve">捨棄變更</x:String>
<x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">擱置變更並自動復原</x:String> <x:String x:Key="Text.Checkout.LocalChanges.StashAndReply" xml:space="preserve">擱置變更並自動復原</x:String>
<x:String x:Key="Text.Checkout.RecurseSubmodules" xml:space="preserve">同時更新所有子模組</x:String>
<x:String x:Key="Text.Checkout.Target" xml:space="preserve">目標分支:</x:String> <x:String x:Key="Text.Checkout.Target" xml:space="preserve">目標分支:</x:String>
<x:String x:Key="Text.CherryPick" xml:space="preserve">揀選提交</x:String> <x:String x:Key="Text.CherryPick" xml:space="preserve">揀選提交</x:String>
<x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">提交資訊中追加來源資訊</x:String> <x:String x:Key="Text.CherryPick.AppendSourceToMessage" xml:space="preserve">提交資訊中追加來源資訊</x:String>
@ -326,6 +327,8 @@
<x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">完成修復分支</x:String> <x:String x:Key="Text.GitFlow.FinishHotfix" xml:space="preserve">完成修復分支</x:String>
<x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">完成發行分支</x:String> <x:String x:Key="Text.GitFlow.FinishRelease" xml:space="preserve">完成發行分支</x:String>
<x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">目標分支:</x:String> <x:String x:Key="Text.GitFlow.FinishTarget" xml:space="preserve">目標分支:</x:String>
<x:String x:Key="Text.GitFlow.FinishWithPush" xml:space="preserve">完成後自動推送</x:String>
<x:String x:Key="Text.GitFlow.FinishWithSquash" xml:space="preserve">壓縮為單一提交後合併</x:String>
<x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">修復分支:</x:String> <x:String x:Key="Text.GitFlow.Hotfix" xml:space="preserve">修復分支:</x:String>
<x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">修復分支前置詞:</x:String> <x:String x:Key="Text.GitFlow.HotfixPrefix" xml:space="preserve">修復分支前置詞:</x:String>
<x:String x:Key="Text.GitFlow.Init" xml:space="preserve">初始化 Git 工作流</x:String> <x:String x:Key="Text.GitFlow.Init" xml:space="preserve">初始化 Git 工作流</x:String>
@ -575,6 +578,9 @@
<x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">分支:</x:String> <x:String x:Key="Text.RenameBranch.Target" xml:space="preserve">分支:</x:String>
<x:String x:Key="Text.Repository.Abort" xml:space="preserve">中止</x:String> <x:String x:Key="Text.Repository.Abort" xml:space="preserve">中止</x:String>
<x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">自動提取遠端變更中...</x:String> <x:String x:Key="Text.Repository.AutoFetching" xml:space="preserve">自動提取遠端變更中...</x:String>
<x:String x:Key="Text.Repository.BranchSort" xml:space="preserve">排序</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByCommitterDate" xml:space="preserve">依建立時間</x:String>
<x:String x:Key="Text.Repository.BranchSort.ByName" xml:space="preserve">依名稱升序</x:String>
<x:String x:Key="Text.Repository.Clean" xml:space="preserve">清理本存放庫 (GC)</x:String> <x:String x:Key="Text.Repository.Clean" xml:space="preserve">清理本存放庫 (GC)</x:String>
<x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">本操作將執行 `git gc` 命令。</x:String> <x:String x:Key="Text.Repository.CleanTips" xml:space="preserve">本操作將執行 `git gc` 命令。</x:String>
<x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空篩選規則</x:String> <x:String x:Key="Text.Repository.ClearAllCommitsFilter" xml:space="preserve">清空篩選規則</x:String>
@ -629,6 +635,7 @@
<x:String x:Key="Text.Repository.Terminal" xml:space="preserve">在終端機中開啟</x:String> <x:String x:Key="Text.Repository.Terminal" xml:space="preserve">在終端機中開啟</x:String>
<x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">在提交列表中使用相對時間</x:String> <x:String x:Key="Text.Repository.UseRelativeTimeInHistories" xml:space="preserve">在提交列表中使用相對時間</x:String>
<x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">檢視 Git 指令記錄</x:String> <x:String x:Key="Text.Repository.ViewLogs" xml:space="preserve">檢視 Git 指令記錄</x:String>
<x:String x:Key="Text.Repository.Visit" xml:space="preserve">檢視遠端存放庫 '{0}'</x:String>
<x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">工作區列表</x:String> <x:String x:Key="Text.Repository.Worktrees" xml:space="preserve">工作區列表</x:String>
<x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">新增工作區</x:String> <x:String x:Key="Text.Repository.Worktrees.Add" xml:space="preserve">新增工作區</x:String>
<x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">清理</x:String> <x:String x:Key="Text.Repository.Worktrees.Prune" xml:space="preserve">清理</x:String>

View file

@ -25,7 +25,7 @@
<Color x:Key="Color.Diff.AddedHighlight">#A7E1A7</Color> <Color x:Key="Color.Diff.AddedHighlight">#A7E1A7</Color>
<Color x:Key="Color.Diff.DeletedHighlight">#F19B9D</Color> <Color x:Key="Color.Diff.DeletedHighlight">#F19B9D</Color>
<Color x:Key="Color.Link">#0000EE</Color> <Color x:Key="Color.Link">#0000EE</Color>
<Color x:Key="Color.InlineCode">#FFE5E5E5</Color> <Color x:Key="Color.InlineCode">#FFE4E4E4</Color>
</ResourceDictionary> </ResourceDictionary>
<ResourceDictionary x:Key="Dark"> <ResourceDictionary x:Key="Dark">
@ -52,7 +52,7 @@
<Color x:Key="Color.Diff.AddedHighlight">#A0308D3C</Color> <Color x:Key="Color.Diff.AddedHighlight">#A0308D3C</Color>
<Color x:Key="Color.Diff.DeletedHighlight">#A09F4247</Color> <Color x:Key="Color.Diff.DeletedHighlight">#A09F4247</Color>
<Color x:Key="Color.Link">#4DAAFC</Color> <Color x:Key="Color.Link">#4DAAFC</Color>
<Color x:Key="Color.InlineCode">#FF2E2E2E</Color> <Color x:Key="Color.InlineCode">#FF383838</Color>
</ResourceDictionary> </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries> </ResourceDictionary.ThemeDictionaries>

View file

@ -10,6 +10,7 @@ namespace SourceGit.ViewModels
public string Name { get; private set; } = string.Empty; public string Name { get; private set; } = string.Empty;
public string Path { get; private set; } = string.Empty; public string Path { get; private set; } = string.Empty;
public object Backend { get; private set; } = null; public object Backend { get; private set; } = null;
public ulong TimeToSort { get; private set; } = 0;
public int Depth { get; set; } = 0; public int Depth { get; set; } = 0;
public bool IsSelected { get; set; } = false; public bool IsSelected { get; set; } = false;
public List<BranchTreeNode> Children { get; private set; } = new List<BranchTreeNode>(); public List<BranchTreeNode> Children { get; private set; } = new List<BranchTreeNode>();
@ -62,6 +63,12 @@ namespace SourceGit.ViewModels
public List<BranchTreeNode> Remotes => _remotes; public List<BranchTreeNode> Remotes => _remotes;
public List<string> InvalidExpandedNodes => _invalidExpandedNodes; public List<string> InvalidExpandedNodes => _invalidExpandedNodes;
public Builder(Models.BranchSortMode localSortMode, Models.BranchSortMode remoteSortMode)
{
_localSortMode = localSortMode;
_remoteSortMode = remoteSortMode;
}
public void SetExpandedNodes(List<string> expanded) public void SetExpandedNodes(List<string> expanded)
{ {
foreach (var node in expanded) foreach (var node in expanded)
@ -72,6 +79,7 @@ namespace SourceGit.ViewModels
{ {
var folders = new Dictionary<string, BranchTreeNode>(); var folders = new Dictionary<string, BranchTreeNode>();
var fakeRemoteTime = (ulong)remotes.Count;
foreach (var remote in remotes) foreach (var remote in remotes)
{ {
var path = $"refs/remotes/{remote.Name}"; var path = $"refs/remotes/{remote.Name}";
@ -81,8 +89,10 @@ namespace SourceGit.ViewModels
Path = path, Path = path,
Backend = remote, Backend = remote,
IsExpanded = bForceExpanded || _expanded.Contains(path), IsExpanded = bForceExpanded || _expanded.Contains(path),
TimeToSort = fakeRemoteTime,
}; };
fakeRemoteTime--;
folders.Add(path, node); folders.Add(path, node);
_remotes.Add(node); _remotes.Add(node);
} }
@ -108,12 +118,21 @@ namespace SourceGit.ViewModels
} }
folders.Clear(); folders.Clear();
SortNodes(_locals);
SortNodes(_remotes); if (_localSortMode == Models.BranchSortMode.Name)
SortNodesByName(_locals);
else
SortNodesByTime(_locals);
if (_remoteSortMode == Models.BranchSortMode.Name)
SortNodesByName(_remotes);
else
SortNodesByTime(_remotes);
} }
private void MakeBranchNode(Models.Branch branch, List<BranchTreeNode> roots, Dictionary<string, BranchTreeNode> folders, string prefix, bool bForceExpanded) private void MakeBranchNode(Models.Branch branch, List<BranchTreeNode> roots, Dictionary<string, BranchTreeNode> folders, string prefix, bool bForceExpanded)
{ {
var time = branch.CommitterDate;
var fullpath = $"{prefix}/{branch.Name}"; var fullpath = $"{prefix}/{branch.Name}";
var sepIdx = branch.Name.IndexOf('/', StringComparison.Ordinal); var sepIdx = branch.Name.IndexOf('/', StringComparison.Ordinal);
if (sepIdx == -1 || branch.IsDetachedHead) if (sepIdx == -1 || branch.IsDetachedHead)
@ -124,6 +143,7 @@ namespace SourceGit.ViewModels
Path = fullpath, Path = fullpath,
Backend = branch, Backend = branch,
IsExpanded = false, IsExpanded = false,
TimeToSort = time,
}); });
return; return;
} }
@ -138,6 +158,7 @@ namespace SourceGit.ViewModels
if (folders.TryGetValue(folder, out var val)) if (folders.TryGetValue(folder, out var val))
{ {
lastFolder = val; lastFolder = val;
lastFolder.TimeToSort = Math.Max(lastFolder.TimeToSort, time);
if (!lastFolder.IsExpanded) if (!lastFolder.IsExpanded)
lastFolder.IsExpanded |= (branch.IsCurrent || _expanded.Contains(folder)); lastFolder.IsExpanded |= (branch.IsCurrent || _expanded.Contains(folder));
} }
@ -148,6 +169,7 @@ namespace SourceGit.ViewModels
Name = name, Name = name,
Path = folder, Path = folder,
IsExpanded = bForceExpanded || branch.IsCurrent || _expanded.Contains(folder), IsExpanded = bForceExpanded || branch.IsCurrent || _expanded.Contains(folder),
TimeToSort = time,
}; };
roots.Add(lastFolder); roots.Add(lastFolder);
folders.Add(folder, lastFolder); folders.Add(folder, lastFolder);
@ -159,6 +181,7 @@ namespace SourceGit.ViewModels
Name = name, Name = name,
Path = folder, Path = folder,
IsExpanded = bForceExpanded || branch.IsCurrent || _expanded.Contains(folder), IsExpanded = bForceExpanded || branch.IsCurrent || _expanded.Contains(folder),
TimeToSort = time,
}; };
lastFolder.Children.Add(cur); lastFolder.Children.Add(cur);
folders.Add(folder, cur); folders.Add(folder, cur);
@ -175,10 +198,11 @@ namespace SourceGit.ViewModels
Path = fullpath, Path = fullpath,
Backend = branch, Backend = branch,
IsExpanded = false, IsExpanded = false,
TimeToSort = time,
}); });
} }
private void SortNodes(List<BranchTreeNode> nodes) private void SortNodesByName(List<BranchTreeNode> nodes)
{ {
nodes.Sort((l, r) => nodes.Sort((l, r) =>
{ {
@ -192,9 +216,39 @@ namespace SourceGit.ViewModels
}); });
foreach (var node in nodes) foreach (var node in nodes)
SortNodes(node.Children); SortNodesByName(node.Children);
} }
private void SortNodesByTime(List<BranchTreeNode> nodes)
{
nodes.Sort((l, r) =>
{
if (l.Backend is Models.Branch { IsDetachedHead: true })
return -1;
if (l.Backend is Models.Branch)
{
if (r.Backend is Models.Branch)
return r.TimeToSort == l.TimeToSort ? Models.NumericSort.Compare(l.Name, r.Name) : r.TimeToSort.CompareTo(l.TimeToSort);
else
return 1;
}
if (r.Backend is Models.Branch)
return -1;
if (r.TimeToSort == l.TimeToSort)
return Models.NumericSort.Compare(l.Name, r.Name);
return r.TimeToSort.CompareTo(l.TimeToSort);
});
foreach (var node in nodes)
SortNodesByTime(node.Children);
}
private readonly Models.BranchSortMode _localSortMode = Models.BranchSortMode.Name;
private readonly Models.BranchSortMode _remoteSortMode = Models.BranchSortMode.Name;
private readonly List<BranchTreeNode> _locals = new List<BranchTreeNode>(); private readonly List<BranchTreeNode> _locals = new List<BranchTreeNode>();
private readonly List<BranchTreeNode> _remotes = new List<BranchTreeNode>(); private readonly List<BranchTreeNode> _remotes = new List<BranchTreeNode>();
private readonly List<string> _invalidExpandedNodes = new List<string>(); private readonly List<string> _invalidExpandedNodes = new List<string>();

View file

@ -15,11 +15,24 @@ namespace SourceGit.ViewModels
set; set;
} }
public bool IsRecurseSubmoduleVisible
{
get;
private set;
}
public bool RecurseSubmodules
{
get => _repo.Settings.UpdateSubmodulesOnCheckoutBranch;
set => _repo.Settings.UpdateSubmodulesOnCheckoutBranch = value;
}
public Checkout(Repository repo, string branch) public Checkout(Repository repo, string branch)
{ {
_repo = repo; _repo = repo;
Branch = branch; Branch = branch;
DiscardLocalChanges = false; DiscardLocalChanges = false;
IsRecurseSubmoduleVisible = repo.Submodules.Count > 0;
} }
public override Task<bool> Sure() public override Task<bool> Sure()
@ -30,19 +43,22 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog($"Checkout '{Branch}'"); var log = _repo.CreateLog($"Checkout '{Branch}'");
Use(log); Use(log);
var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
return Task.Run(() => return Task.Run(() =>
{ {
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result(); var succ = false;
var needPopStash = false; var needPopStash = false;
if (changes > 0)
if (DiscardLocalChanges)
{ {
if (DiscardLocalChanges) succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(Branch, true);
}
else
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
if (changes > 0)
{ {
Commands.Discard.All(_repo.FullPath, false, log); succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
}
else
{
var succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
if (!succ) if (!succ)
{ {
log.Complete(); log.Complete();
@ -52,11 +68,22 @@ namespace SourceGit.ViewModels
needPopStash = true; needPopStash = true;
} }
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(Branch, false);
} }
var rs = new Commands.Checkout(_repo.FullPath).Use(log).Branch(Branch); if (succ)
if (needPopStash) {
rs = new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}"); if (updateSubmodules)
{
var submodules = new Commands.QuerySubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true, false);
}
if (needPopStash)
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
}
log.Complete(); log.Complete();
@ -73,7 +100,7 @@ namespace SourceGit.ViewModels
}); });
Task.Delay(400).Wait(); Task.Delay(400).Wait();
return rs; return succ;
}); });
} }

View file

@ -15,11 +15,24 @@ namespace SourceGit.ViewModels
set; set;
} }
public bool IsRecurseSubmoduleVisible
{
get;
private set;
}
public bool RecurseSubmodules
{
get => _repo.Settings.UpdateSubmodulesOnCheckoutBranch;
set => _repo.Settings.UpdateSubmodulesOnCheckoutBranch = value;
}
public CheckoutCommit(Repository repo, Models.Commit commit) public CheckoutCommit(Repository repo, Models.Commit commit)
{ {
_repo = repo; _repo = repo;
Commit = commit; Commit = commit;
DiscardLocalChanges = false; DiscardLocalChanges = false;
IsRecurseSubmoduleVisible = repo.Submodules.Count > 0;
} }
public override Task<bool> Sure() public override Task<bool> Sure()
@ -30,19 +43,22 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog("Checkout Commit"); var log = _repo.CreateLog("Checkout Commit");
Use(log); Use(log);
var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
return Task.Run(() => return Task.Run(() =>
{ {
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result(); var succ = false;
var needPopStash = false; var needPop = false;
if (changes > 0)
if (DiscardLocalChanges)
{ {
if (DiscardLocalChanges) succ = new Commands.Checkout(_repo.FullPath).Use(log).Commit(Commit.SHA, true);
}
else
{
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
if (changes > 0)
{ {
Commands.Discard.All(_repo.FullPath, false, log); succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
}
else
{
var succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CHECKOUT_AUTO_STASH");
if (!succ) if (!succ)
{ {
log.Complete(); log.Complete();
@ -50,17 +66,28 @@ namespace SourceGit.ViewModels
return false; return false;
} }
needPopStash = true; needPop = true;
} }
succ = new Commands.Checkout(_repo.FullPath).Use(log).Commit(Commit.SHA, false);
} }
var rs = new Commands.Checkout(_repo.FullPath).Use(log).Commit(Commit.SHA); if (succ)
if (needPopStash) {
rs = new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}"); if (updateSubmodules)
{
var submodules = new Commands.QuerySubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true, false);
}
if (needPop)
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
}
log.Complete(); log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true)); CallUIThread(() => _repo.SetWatcherEnabled(true));
return rs; return succ;
}); });
} }

View file

@ -101,7 +101,6 @@ namespace SourceGit.ViewModels
{ {
ProgressDescription = "Clone ..."; ProgressDescription = "Clone ...";
// Create a temp log.
var log = new CommandLog("Clone"); var log = new CommandLog("Clone");
Use(log); Use(log);
@ -139,12 +138,11 @@ namespace SourceGit.ViewModels
config.Set("remote.origin.sshkey", _sshKey); config.Set("remote.origin.sshkey", _sshKey);
} }
// individually update submodule (if any)
if (InitAndUpdateSubmodules) if (InitAndUpdateSubmodules)
{ {
var submoduleList = new Commands.QuerySubmodules(path).Result(); var submodules = new Commands.QuerySubmodules(path).Result();
foreach (var submodule in submoduleList) if (submodules.Count > 0)
new Commands.Submodule(path).Use(log).Update(submodule.Path, true, true, false); new Commands.Submodule(path).Use(log).Update(submodules, true, true, false);
} }
log.Complete(); log.Complete();

View file

@ -291,7 +291,7 @@ namespace SourceGit.ViewModels
ev.Handled = true; ev.Handled = true;
}; };
var fullPath = Path.Combine(_repo.FullPath, change.Path); var fullPath = Native.OS.GetAbsPath(_repo.FullPath, change.Path);
var explore = new MenuItem(); var explore = new MenuItem();
explore.Header = App.Text("RevealFile"); explore.Header = App.Text("RevealFile");
explore.Icon = App.CreateMenuIcon("Icons.Explore"); explore.Icon = App.CreateMenuIcon("Icons.Explore");
@ -362,11 +362,9 @@ namespace SourceGit.ViewModels
var resetToThisRevision = new MenuItem(); var resetToThisRevision = new MenuItem();
resetToThisRevision.Header = App.Text("ChangeCM.CheckoutThisRevision"); resetToThisRevision.Header = App.Text("ChangeCM.CheckoutThisRevision");
resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout"); resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout");
resetToThisRevision.Click += (_, ev) => resetToThisRevision.Click += async (_, ev) =>
{ {
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}'"); await ResetToThisRevision(change.Path);
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.Path, $"{_commit.SHA}");
log.Complete();
ev.Handled = true; ev.Handled = true;
}; };
@ -374,14 +372,9 @@ namespace SourceGit.ViewModels
resetToFirstParent.Header = App.Text("ChangeCM.CheckoutFirstParentRevision"); resetToFirstParent.Header = App.Text("ChangeCM.CheckoutFirstParentRevision");
resetToFirstParent.Icon = App.CreateMenuIcon("Icons.File.Checkout"); resetToFirstParent.Icon = App.CreateMenuIcon("Icons.File.Checkout");
resetToFirstParent.IsEnabled = _commit.Parents.Count > 0; resetToFirstParent.IsEnabled = _commit.Parents.Count > 0;
resetToFirstParent.Click += (_, ev) => resetToFirstParent.Click += async (_, ev) =>
{ {
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}~1'"); await ResetToParentRevision(change);
if (change.Index == Models.ChangeState.Renamed)
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.OriginalPath, $"{_commit.SHA}~1");
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.Path, $"{_commit.SHA}~1");
log.Complete();
ev.Handled = true; ev.Handled = true;
}; };
@ -389,8 +382,7 @@ namespace SourceGit.ViewModels
menu.Items.Add(resetToFirstParent); menu.Items.Add(resetToFirstParent);
menu.Items.Add(new MenuItem { Header = "-" }); menu.Items.Add(new MenuItem { Header = "-" });
if (File.Exists(Path.Combine(fullPath))) TryToAddContextMenuItemsForGitLFS(menu, fullPath, change.Path);
TryToAddContextMenuItemsForGitLFS(menu, change.Path);
} }
var copyPath = new MenuItem(); var copyPath = new MenuItem();
@ -407,7 +399,7 @@ namespace SourceGit.ViewModels
copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy");
copyFullPath.Click += (_, e) => copyFullPath.Click += (_, e) =>
{ {
App.CopyText(Native.OS.GetAbsPath(_repo.FullPath, change.Path)); App.CopyText(fullPath);
e.Handled = true; e.Handled = true;
}; };
@ -419,7 +411,7 @@ namespace SourceGit.ViewModels
public ContextMenu CreateRevisionFileContextMenu(Models.Object file) public ContextMenu CreateRevisionFileContextMenu(Models.Object file)
{ {
var menu = new ContextMenu(); var menu = new ContextMenu();
var fullPath = Path.Combine(_repo.FullPath, file.Path); var fullPath = Native.OS.GetAbsPath(_repo.FullPath, file.Path);
var explore = new MenuItem(); var explore = new MenuItem();
explore.Header = App.Text("RevealFile"); explore.Header = App.Text("RevealFile");
explore.Icon = App.CreateMenuIcon("Icons.Explore"); explore.Icon = App.CreateMenuIcon("Icons.Explore");
@ -499,38 +491,34 @@ namespace SourceGit.ViewModels
menu.Items.Add(blame); menu.Items.Add(blame);
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });
var resetToThisRevision = new MenuItem(); if (!_repo.IsBare)
resetToThisRevision.Header = App.Text("ChangeCM.CheckoutThisRevision");
resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout");
resetToThisRevision.IsEnabled = File.Exists(fullPath);
resetToThisRevision.Click += (_, ev) =>
{ {
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}'"); var resetToThisRevision = new MenuItem();
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(file.Path, $"{_commit.SHA}"); resetToThisRevision.Header = App.Text("ChangeCM.CheckoutThisRevision");
log.Complete(); resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout");
ev.Handled = true; resetToThisRevision.Click += async (_, ev) =>
}; {
await ResetToThisRevision(file.Path);
ev.Handled = true;
};
var resetToFirstParent = new MenuItem(); var change = _changes.Find(x => x.Path == file.Path) ?? new Models.Change() { Index = Models.ChangeState.None, Path = file.Path };
resetToFirstParent.Header = App.Text("ChangeCM.CheckoutFirstParentRevision"); var resetToFirstParent = new MenuItem();
resetToFirstParent.Icon = App.CreateMenuIcon("Icons.File.Checkout"); resetToFirstParent.Header = App.Text("ChangeCM.CheckoutFirstParentRevision");
var fileInChanges = _changes.Find(x => x.Path == file.Path); resetToFirstParent.Icon = App.CreateMenuIcon("Icons.File.Checkout");
var fileIndex = fileInChanges?.Index; resetToFirstParent.IsEnabled = _commit.Parents.Count > 0;
resetToFirstParent.IsEnabled = _commit.Parents.Count > 0 && fileIndex != Models.ChangeState.Renamed; resetToFirstParent.Click += async (_, ev) =>
resetToFirstParent.Click += (_, ev) => {
{ await ResetToParentRevision(change);
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}~1'"); ev.Handled = true;
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(file.Path, $"{_commit.SHA}~1"); };
log.Complete();
ev.Handled = true;
};
menu.Items.Add(resetToThisRevision); menu.Items.Add(resetToThisRevision);
menu.Items.Add(resetToFirstParent); menu.Items.Add(resetToFirstParent);
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });
if (File.Exists(Path.Combine(fullPath))) TryToAddContextMenuItemsForGitLFS(menu, fullPath, file.Path);
TryToAddContextMenuItemsForGitLFS(menu, file.Path); }
var copyPath = new MenuItem(); var copyPath = new MenuItem();
copyPath.Header = App.Text("CopyPath"); copyPath.Header = App.Text("CopyPath");
@ -546,7 +534,7 @@ namespace SourceGit.ViewModels
copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy"); copyFullPath.Icon = App.CreateMenuIcon("Icons.Copy");
copyFullPath.Click += (_, e) => copyFullPath.Click += (_, e) =>
{ {
App.CopyText(Native.OS.GetAbsPath(_repo.FullPath, file.Path)); App.CopyText(fullPath);
e.Handled = true; e.Handled = true;
}; };
@ -725,8 +713,11 @@ namespace SourceGit.ViewModels
} }
} }
private void TryToAddContextMenuItemsForGitLFS(ContextMenu menu, string path) private void TryToAddContextMenuItemsForGitLFS(ContextMenu menu, string fullPath, string path)
{ {
if (_repo.Remotes.Count == 0 || !File.Exists(fullPath))
return;
var lfsEnabled = new Commands.LFS(_repo.FullPath).IsEnabled(); var lfsEnabled = new Commands.LFS(_repo.FullPath).IsEnabled();
if (!lfsEnabled) if (!lfsEnabled)
return; return;
@ -738,7 +729,6 @@ namespace SourceGit.ViewModels
var lfsLock = new MenuItem(); var lfsLock = new MenuItem();
lfsLock.Header = App.Text("GitLFS.Locks.Lock"); lfsLock.Header = App.Text("GitLFS.Locks.Lock");
lfsLock.Icon = App.CreateMenuIcon("Icons.Lock"); lfsLock.Icon = App.CreateMenuIcon("Icons.Lock");
lfsLock.IsEnabled = _repo.Remotes.Count > 0;
if (_repo.Remotes.Count == 1) if (_repo.Remotes.Count == 1)
{ {
lfsLock.Click += async (_, e) => lfsLock.Click += async (_, e) =>
@ -777,7 +767,6 @@ namespace SourceGit.ViewModels
var lfsUnlock = new MenuItem(); var lfsUnlock = new MenuItem();
lfsUnlock.Header = App.Text("GitLFS.Locks.Unlock"); lfsUnlock.Header = App.Text("GitLFS.Locks.Unlock");
lfsUnlock.Icon = App.CreateMenuIcon("Icons.Unlock"); lfsUnlock.Icon = App.CreateMenuIcon("Icons.Unlock");
lfsUnlock.IsEnabled = _repo.Remotes.Count > 0;
if (_repo.Remotes.Count == 1) if (_repo.Remotes.Count == 1)
{ {
lfsUnlock.Click += async (_, e) => lfsUnlock.Click += async (_, e) =>
@ -867,6 +856,31 @@ namespace SourceGit.ViewModels
RevisionFileSearchSuggestion = suggestion; RevisionFileSearchSuggestion = suggestion;
} }
private Task ResetToThisRevision(string path)
{
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}'");
return Task.Run(() =>
{
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(path, $"{_commit.SHA}");
log.Complete();
});
}
private Task ResetToParentRevision(Models.Change change)
{
var log = _repo.CreateLog($"Reset File to '{_commit.SHA}~1'");
return Task.Run(() =>
{
if (change.Index == Models.ChangeState.Renamed)
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.OriginalPath, $"{_commit.SHA}~1");
new Commands.Checkout(_repo.FullPath).Use(log).FileWithRevision(change.Path, $"{_commit.SHA}~1");
log.Complete();
});
}
[GeneratedRegex(@"\b(https?://|ftp://)[\w\d\._/\-~%@()+:?&=#!]*[\w\d/]")] [GeneratedRegex(@"\b(https?://|ftp://)[\w\d\._/\-~%@()+:?&=#!]*[\w\d/]")]
private static partial Regex REG_URL_FORMAT(); private static partial Regex REG_URL_FORMAT();

View file

@ -28,7 +28,14 @@ namespace SourceGit.ViewModels
public bool CheckoutAfterCreated public bool CheckoutAfterCreated
{ {
get => _repo.Settings.CheckoutBranchOnCreateBranch; get => _repo.Settings.CheckoutBranchOnCreateBranch;
set => _repo.Settings.CheckoutBranchOnCreateBranch = value; set
{
if (_repo.Settings.CheckoutBranchOnCreateBranch != value)
{
_repo.Settings.CheckoutBranchOnCreateBranch = value;
OnPropertyChanged();
}
}
} }
public bool IsBareRepository public bool IsBareRepository
@ -36,6 +43,18 @@ namespace SourceGit.ViewModels
get => _repo.IsBare; get => _repo.IsBare;
} }
public bool IsRecurseSubmoduleVisible
{
get;
private set;
}
public bool RecurseSubmodules
{
get => _repo.Settings.UpdateSubmodulesOnCheckoutBranch;
set => _repo.Settings.UpdateSubmodulesOnCheckoutBranch = value;
}
public CreateBranch(Repository repo, Models.Branch branch) public CreateBranch(Repository repo, Models.Branch branch)
{ {
_repo = repo; _repo = repo;
@ -48,6 +67,7 @@ namespace SourceGit.ViewModels
BasedOn = branch; BasedOn = branch;
DiscardLocalChanges = false; DiscardLocalChanges = false;
IsRecurseSubmoduleVisible = repo.Submodules.Count > 0;
} }
public CreateBranch(Repository repo, Models.Commit commit) public CreateBranch(Repository repo, Models.Commit commit)
@ -57,6 +77,7 @@ namespace SourceGit.ViewModels
BasedOn = commit; BasedOn = commit;
DiscardLocalChanges = false; DiscardLocalChanges = false;
IsRecurseSubmoduleVisible = repo.Submodules.Count > 0;
} }
public CreateBranch(Repository repo, Models.Tag tag) public CreateBranch(Repository repo, Models.Tag tag)
@ -66,6 +87,7 @@ namespace SourceGit.ViewModels
BasedOn = tag; BasedOn = tag;
DiscardLocalChanges = false; DiscardLocalChanges = false;
IsRecurseSubmoduleVisible = repo.Submodules.Count > 0;
} }
public static ValidationResult ValidateBranchName(string name, ValidationContext ctx) public static ValidationResult ValidateBranchName(string name, ValidationContext ctx)
@ -92,20 +114,21 @@ namespace SourceGit.ViewModels
var log = _repo.CreateLog($"Create Branch '{fixedName}'"); var log = _repo.CreateLog($"Create Branch '{fixedName}'");
Use(log); Use(log);
var updateSubmodules = IsRecurseSubmoduleVisible && RecurseSubmodules;
return Task.Run(() => return Task.Run(() =>
{ {
bool succ; bool succ = false;
if (CheckoutAfterCreated && !_repo.IsBare) if (CheckoutAfterCreated && !_repo.IsBare)
{ {
var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
var needPopStash = false; var needPopStash = false;
if (changes > 0) if (DiscardLocalChanges)
{ {
if (DiscardLocalChanges) succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, true);
{ }
Commands.Discard.All(_repo.FullPath, false, log); else
} {
else var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result();
if (changes > 0)
{ {
succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CREATE_BRANCH_AUTO_STASH"); succ = new Commands.Stash(_repo.FullPath).Use(log).Push("CREATE_BRANCH_AUTO_STASH");
if (!succ) if (!succ)
@ -117,11 +140,22 @@ namespace SourceGit.ViewModels
needPopStash = true; needPopStash = true;
} }
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision, false);
} }
succ = new Commands.Checkout(_repo.FullPath).Use(log).Branch(fixedName, _baseOnRevision); if (succ)
if (needPopStash) {
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}"); if (updateSubmodules)
{
var submodules = new Commands.QuerySubmodules(_repo.FullPath).Result();
if (submodules.Count > 0)
new Commands.Submodule(_repo.FullPath).Use(log).Update(submodules, true, true, false);
}
if (needPopStash)
new Commands.Stash(_repo.FullPath).Use(log).Pop("stash@{0}");
}
} }
else else
{ {
@ -144,6 +178,8 @@ namespace SourceGit.ViewModels
if (_repo.HistoriesFilterMode == Models.FilterMode.Included) if (_repo.HistoriesFilterMode == Models.FilterMode.Included)
_repo.SetBranchFilterMode(fake, Models.FilterMode.Included, true, false); _repo.SetBranchFilterMode(fake, Models.FilterMode.Included, true, false);
ProgressDescription = "Waiting for branch updated...";
} }
_repo.MarkBranchesDirtyManually(); _repo.MarkBranchesDirtyManually();
@ -151,10 +187,7 @@ namespace SourceGit.ViewModels
}); });
if (CheckoutAfterCreated) if (CheckoutAfterCreated)
{
CallUIThread(() => ProgressDescription = "Waiting for branch updated...");
Task.Delay(400).Wait(); Task.Delay(400).Wait();
}
return true; return true;
}); });

View file

@ -13,6 +13,18 @@ namespace SourceGit.ViewModels
public bool IsRelease => _type == "release"; public bool IsRelease => _type == "release";
public bool IsHotfix => _type == "hotfix"; public bool IsHotfix => _type == "hotfix";
public bool Squash
{
get;
set;
} = false;
public bool AutoPush
{
get;
set;
} = false;
public bool KeepBranch public bool KeepBranch
{ {
get; get;
@ -39,7 +51,7 @@ namespace SourceGit.ViewModels
return Task.Run(() => return Task.Run(() =>
{ {
var succ = Commands.GitFlow.Finish(_repo.FullPath, _type, name, KeepBranch, log); var succ = Commands.GitFlow.Finish(_repo.FullPath, _type, name, Squash, AutoPush, KeepBranch, log);
log.Complete(); log.Complete();
CallUIThread(() => _repo.SetWatcherEnabled(true)); CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ; return succ;

View file

@ -100,23 +100,32 @@ namespace SourceGit.ViewModels
public async void ProcessPopup() public async void ProcessPopup()
{ {
if (_popup is { InProgress: false }) if (_popup is { InProgress: false } dump)
{ {
if (!_popup.Check()) if (!dump.Check())
return; return;
_popup.InProgress = true; dump.InProgress = true;
var task = _popup.Sure(); var task = dump.Sure();
var finished = false;
if (task != null) if (task != null)
{ {
var finished = await task; try
_popup.InProgress = false; {
finished = await task;
}
catch (Exception e)
{
App.LogException(e);
}
dump.InProgress = false;
if (finished) if (finished)
Popup = null; Popup = null;
} }
else else
{ {
_popup.InProgress = false; dump.InProgress = false;
Popup = null; Popup = null;
} }
} }

View file

@ -583,43 +583,85 @@ namespace SourceGit.ViewModels
Task.Run(RefreshStashes); Task.Run(RefreshStashes);
} }
public void OpenInFileManager()
{
Native.OS.OpenInFileManager(_fullpath);
}
public void OpenInTerminal()
{
Native.OS.OpenTerminal(_fullpath);
}
public ContextMenu CreateContextMenuForExternalTools() public ContextMenu CreateContextMenuForExternalTools()
{ {
var tools = Native.OS.ExternalTools;
if (tools.Count == 0)
{
App.RaiseException(_fullpath, "No available external editors found!");
return null;
}
var menu = new ContextMenu(); var menu = new ContextMenu();
menu.Placement = PlacementMode.BottomEdgeAlignedLeft; menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
RenderOptions.SetBitmapInterpolationMode(menu, BitmapInterpolationMode.HighQuality); RenderOptions.SetBitmapInterpolationMode(menu, BitmapInterpolationMode.HighQuality);
RenderOptions.SetEdgeMode(menu, EdgeMode.Antialias);
RenderOptions.SetTextRenderingMode(menu, TextRenderingMode.Antialias);
foreach (var tool in tools) var explore = new MenuItem();
explore.Header = App.Text("Repository.Explore");
explore.Icon = App.CreateMenuIcon("Icons.Explore");
explore.Click += (_, e) =>
{ {
var dupTool = tool; Native.OS.OpenInFileManager(_fullpath);
e.Handled = true;
};
var item = new MenuItem(); var terminal = new MenuItem();
item.Header = App.Text("Repository.OpenIn", dupTool.Name); terminal.Header = App.Text("Repository.Terminal");
item.Icon = new Image { Width = 16, Height = 16, Source = dupTool.IconImage }; terminal.Icon = App.CreateMenuIcon("Icons.Terminal");
item.Click += (_, e) => terminal.Click += (_, e) =>
{
Native.OS.OpenTerminal(_fullpath);
e.Handled = true;
};
menu.Items.Add(explore);
menu.Items.Add(terminal);
var tools = Native.OS.ExternalTools;
if (tools.Count > 0)
{
menu.Items.Add(new MenuItem() { Header = "-" });
foreach (var tool in Native.OS.ExternalTools)
{ {
dupTool.Open(_fullpath); var dupTool = tool;
e.Handled = true;
};
menu.Items.Add(item); var item = new MenuItem();
item.Header = App.Text("Repository.OpenIn", dupTool.Name);
item.Icon = new Image { Width = 16, Height = 16, Source = dupTool.IconImage };
item.Click += (_, e) =>
{
dupTool.Open(_fullpath);
e.Handled = true;
};
menu.Items.Add(item);
}
}
var urls = new Dictionary<string, string>();
foreach (var r in _remotes)
{
if (r.TryGetVisitURL(out var visit))
urls.Add(r.Name, visit);
}
if (urls.Count > 0)
{
menu.Items.Add(new MenuItem() { Header = "-" });
foreach (var url in urls)
{
var name = url.Key;
var addr = url.Value;
var item = new MenuItem();
item.Header = App.Text("Repository.Visit", name);
item.Icon = App.CreateMenuIcon("Icons.Remotes");
item.Click += (_, e) =>
{
Native.OS.OpenBrowser(addr);
e.Handled = true;
};
menu.Items.Add(item);
}
} }
return menu; return menu;
@ -1154,7 +1196,7 @@ namespace SourceGit.ViewModels
if (branch.IsLocal) if (branch.IsLocal)
{ {
if (_localChangesCount > 0) if (_localChangesCount > 0 || _submodules.Count > 0)
ShowPopup(new Checkout(this, branch.Name)); ShowPopup(new Checkout(this, branch.Name));
else else
ShowAndStartPopup(new Checkout(this, branch.Name)); ShowAndStartPopup(new Checkout(this, branch.Name));
@ -2187,6 +2229,51 @@ namespace SourceGit.ViewModels
return menu; return menu;
} }
public ContextMenu CreateContextMenuForBranchSortMode(bool local)
{
var mode = local ? _settings.LocalBranchSortMode : _settings.RemoteBranchSortMode;
var changeMode = new Action<Models.BranchSortMode>(m =>
{
if (local)
_settings.LocalBranchSortMode = m;
else
_settings.RemoteBranchSortMode = m;
var builder = BuildBranchTree(_branches, _remotes);
LocalBranchTrees = builder.Locals;
RemoteBranchTrees = builder.Remotes;
});
var byNameAsc = new MenuItem();
byNameAsc.Header = App.Text("Repository.BranchSort.ByName");
if (mode == Models.BranchSortMode.Name)
byNameAsc.Icon = App.CreateMenuIcon("Icons.Check");
byNameAsc.Click += (_, ev) =>
{
if (mode != Models.BranchSortMode.Name)
changeMode(Models.BranchSortMode.Name);
ev.Handled = true;
};
var byCommitterDate = new MenuItem();
byCommitterDate.Header = App.Text("Repository.BranchSort.ByCommitterDate");
if (mode == Models.BranchSortMode.CommitterDate)
byCommitterDate.Icon = App.CreateMenuIcon("Icons.Check");
byCommitterDate.Click += (_, ev) =>
{
if (mode != Models.BranchSortMode.CommitterDate)
changeMode(Models.BranchSortMode.CommitterDate);
ev.Handled = true;
};
var menu = new ContextMenu();
menu.Items.Add(byNameAsc);
menu.Items.Add(byCommitterDate);
return menu;
}
public ContextMenu CreateContextMenuForTagSortMode() public ContextMenu CreateContextMenuForTagSortMode()
{ {
var mode = _settings.TagSortMode; var mode = _settings.TagSortMode;
@ -2356,7 +2443,7 @@ namespace SourceGit.ViewModels
private BranchTreeNode.Builder BuildBranchTree(List<Models.Branch> branches, List<Models.Remote> remotes) private BranchTreeNode.Builder BuildBranchTree(List<Models.Branch> branches, List<Models.Remote> remotes)
{ {
var builder = new BranchTreeNode.Builder(); var builder = new BranchTreeNode.Builder(_settings.LocalBranchSortMode, _settings.RemoteBranchSortMode);
if (string.IsNullOrEmpty(_filter)) if (string.IsNullOrEmpty(_filter))
{ {
builder.SetExpandedNodes(_settings.ExpandedBranchNodesInSideBar); builder.SetExpandedNodes(_settings.ExpandedBranchNodesInSideBar);

View file

@ -46,7 +46,7 @@
<!-- Compare Targets --> <!-- Compare Targets -->
<Border Grid.Row="1"> <Border Grid.Row="1">
<Grid Margin="48,8,48,8" ColumnDefinitions="*,48,*"> <Grid Margin="48,8,48,8" ColumnDefinitions="*,48,*">
<Border Grid.Column="0" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4"> <Border Grid.Column="0" BorderBrush="{DynamicResource Brush.Diff.DeletedHighlight}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
<Grid RowDefinitions="Auto,*"> <Grid RowDefinitions="Auto,*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto,Auto,Auto"> <Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto,Auto,Auto">
<v:Avatar Width="16" Height="16" <v:Avatar Width="16" Height="16"
@ -67,10 +67,10 @@
<!-- Swap Button --> <!-- Swap Button -->
<Button Grid.Column="1" Classes="icon_button" Command="{Binding Swap}" HorizontalAlignment="Center" ToolTip.Tip="{DynamicResource Text.Diff.SwapCommits}"> <Button Grid.Column="1" Classes="icon_button" Command="{Binding Swap}" HorizontalAlignment="Center" ToolTip.Tip="{DynamicResource Text.Diff.SwapCommits}">
<Path Width="16" Height="16" Fill="{DynamicResource Brush.FG2}" Data="{DynamicResource Icons.Compare}"/> <Path Width="16" Height="16" Data="{DynamicResource Icons.Compare}"/>
</Button> </Button>
<Border Grid.Column="2" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4"> <Border Grid.Column="2" BorderBrush="{DynamicResource Brush.Diff.AddedHighlight}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
<Grid RowDefinitions="Auto,*"> <Grid RowDefinitions="Auto,*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto,Auto,Auto"> <Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto,Auto,Auto">
<v:Avatar Width="16" Height="16" <v:Avatar Width="16" Height="16"

View file

@ -17,6 +17,7 @@
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="32"/> <RowDefinition Height="32"/>
<RowDefinition Height="Auto" MinHeight="32"/> <RowDefinition Height="Auto" MinHeight="32"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
@ -35,11 +36,18 @@
<WrapPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center"> <WrapPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
<RadioButton GroupName="LocalChanges" <RadioButton GroupName="LocalChanges"
Margin="0,0,8,0" Margin="0,0,8,0"
Content="{DynamicResource Text.CreateBranch.LocalChanges.StashAndReply}" Content="{DynamicResource Text.Checkout.LocalChanges.StashAndReply}"
IsChecked="{Binding !DiscardLocalChanges, Mode=TwoWay}"/> IsChecked="{Binding !DiscardLocalChanges, Mode=TwoWay}"/>
<RadioButton GroupName="LocalChanges" <RadioButton GroupName="LocalChanges"
Content="{DynamicResource Text.CreateBranch.LocalChanges.Discard}"/> Content="{DynamicResource Text.Checkout.LocalChanges.Discard}"/>
</WrapPanel> </WrapPanel>
<CheckBox Grid.Row="2" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Checkout.RecurseSubmodules}"
IsChecked="{Binding RecurseSubmodules, Mode=TwoWay}"
IsVisible="{Binding IsRecurseSubmoduleVisible}"
ToolTip.Tip="--recurse-submodules"/>
</Grid> </Grid>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View file

@ -12,7 +12,7 @@
Classes="bold" Classes="bold"
Text="{DynamicResource Text.Checkout.Commit}" /> Text="{DynamicResource Text.Checkout.Commit}" />
<Grid Margin="0,16,0,0" RowDefinitions="32,Auto,Auto" ColumnDefinitions="Auto,*"> <Grid Margin="0,16,0,0" RowDefinitions="32,Auto,Auto,Auto" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center" HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0" Margin="0,0,8,0"
@ -36,7 +36,14 @@
GroupName="LocalChanges"/> GroupName="LocalChanges"/>
</StackPanel> </StackPanel>
<Grid Grid.Row="2" Grid.Column="1" ColumnDefinitions="Auto,*" Margin="0,6,0,0"> <CheckBox Grid.Row="2" Grid.Column="1"
Height="32"
Content="{DynamicResource Text.Checkout.RecurseSubmodules}"
IsChecked="{Binding RecurseSubmodules, Mode=TwoWay}"
IsVisible="{Binding IsRecurseSubmoduleVisible}"
ToolTip.Tip="--recurse-submodules"/>
<Grid Grid.Row="3" Grid.Column="1" ColumnDefinitions="Auto,*" Margin="0,6,0,0">
<Path Grid.Column="0" <Path Grid.Column="0"
Width="14" Height="14" Width="14" Height="14"
Data="{StaticResource Icons.Error}" Data="{StaticResource Icons.Error}"

View file

@ -189,7 +189,7 @@
<Border Grid.Row="3" Grid.Column="1" Margin="12,0,0,0" MinHeight="24" IsVisible="{Binding HasDecorators}"> <Border Grid.Row="3" Grid.Column="1" Margin="12,0,0,0" MinHeight="24" IsVisible="{Binding HasDecorators}">
<v:CommitRefsPresenter Foreground="{DynamicResource Brush.FG1}" <v:CommitRefsPresenter Foreground="{DynamicResource Brush.FG1}"
FontFamily="{DynamicResource Fonts.Primary}" FontFamily="{DynamicResource Fonts.Primary}"
FontSize="11" FontSize="12"
AllowWrap="True" AllowWrap="True"
Margin="0,4,0,0" Margin="0,4,0,0"
UseGraphColor="False"/> UseGraphColor="False"/>

View file

@ -55,23 +55,29 @@ namespace SourceGit.Views
if (list == null) if (list == null)
return; return;
// Calculate drawing area. var container = list.ItemsPanelRoot as VirtualizingStackPanel;
double width = Bounds.Width - 273 - histories.AuthorNameColumnWidth.Value; if (container == null)
double height = Bounds.Height; return;
double startY = list.Scroll?.Offset.Y ?? 0;
double endY = startY + height + 28; var item = list.ContainerFromIndex(container.FirstRealizedIndex);
if (item == null)
return;
var width = histories.CommitListHeader.ColumnDefinitions[0].ActualWidth;
var height = Bounds.Height;
var rowHeight = item.Bounds.Height;
var startY = container.FirstRealizedIndex * rowHeight - item.TranslatePoint(new Point(0, 0), list).Value!.Y;
var endY = startY + height + 28;
// Apply scroll offset and clip.
using (context.PushClip(new Rect(0, 0, width, height))) using (context.PushClip(new Rect(0, 0, width, height)))
using (context.PushTransform(Matrix.CreateTranslation(0, -startY))) using (context.PushTransform(Matrix.CreateTranslation(0, -startY)))
{ {
// Draw contents DrawCurves(context, graph, startY, endY, rowHeight);
DrawCurves(context, graph, startY, endY); DrawAnchors(context, graph, startY, endY, rowHeight);
DrawAnchors(context, graph, startY, endY);
} }
} }
private void DrawCurves(DrawingContext context, Models.CommitGraph graph, double top, double bottom) private void DrawCurves(DrawingContext context, Models.CommitGraph graph, double top, double bottom, double rowHeight)
{ {
var grayedPen = new Pen(new SolidColorBrush(Colors.Gray, 0.4), Models.CommitGraph.Pens[0].Thickness); var grayedPen = new Pen(new SolidColorBrush(Colors.Gray, 0.4), Models.CommitGraph.Pens[0].Thickness);
var onlyHighlightCurrentBranch = OnlyHighlightCurrentBranch; var onlyHighlightCurrentBranch = OnlyHighlightCurrentBranch;
@ -82,16 +88,20 @@ namespace SourceGit.Views
{ {
if (link.IsMerged) if (link.IsMerged)
continue; continue;
if (link.End.Y < top)
var startY = link.Start.Y * rowHeight;
var endY = link.End.Y * rowHeight;
if (endY < top)
continue; continue;
if (link.Start.Y > bottom) if (startY > bottom)
break; break;
var geo = new StreamGeometry(); var geo = new StreamGeometry();
using (var ctx = geo.Open()) using (var ctx = geo.Open())
{ {
ctx.BeginFigure(link.Start, false); ctx.BeginFigure(new Point(link.Start.X, startY), false);
ctx.QuadraticBezierTo(link.Control, link.End); ctx.QuadraticBezierTo(new Point(link.Control.X, link.Control.Y * rowHeight), new Point(link.End.X, endY));
} }
context.DrawGeometry(null, grayedPen, geo); context.DrawGeometry(null, grayedPen, geo);
@ -100,10 +110,11 @@ namespace SourceGit.Views
foreach (var line in graph.Paths) foreach (var line in graph.Paths)
{ {
var last = line.Points[0]; var last = new Point(line.Points[0].X, line.Points[0].Y * rowHeight);
var size = line.Points.Count; var size = line.Points.Count;
var endY = line.Points[size - 1].Y * rowHeight;
if (line.Points[size - 1].Y < top) if (endY < top)
continue; continue;
if (last.Y > bottom) if (last.Y > bottom)
break; break;
@ -117,7 +128,7 @@ namespace SourceGit.Views
var ended = false; var ended = false;
for (int i = 1; i < size; i++) for (int i = 1; i < size; i++)
{ {
var cur = line.Points[i]; var cur = new Point(line.Points[i].X, line.Points[i].Y * rowHeight);
if (cur.Y < top) if (cur.Y < top)
{ {
last = cur; last = cur;
@ -173,23 +184,27 @@ namespace SourceGit.Views
{ {
if (onlyHighlightCurrentBranch && !link.IsMerged) if (onlyHighlightCurrentBranch && !link.IsMerged)
continue; continue;
if (link.End.Y < top)
var startY = link.Start.Y * rowHeight;
var endY = link.End.Y * rowHeight;
if (endY < top)
continue; continue;
if (link.Start.Y > bottom) if (startY > bottom)
break; break;
var geo = new StreamGeometry(); var geo = new StreamGeometry();
using (var ctx = geo.Open()) using (var ctx = geo.Open())
{ {
ctx.BeginFigure(link.Start, false); ctx.BeginFigure(new Point(link.Start.X, startY), false);
ctx.QuadraticBezierTo(link.Control, link.End); ctx.QuadraticBezierTo(new Point(link.Control.X, link.Control.Y * rowHeight), new Point(link.End.X, endY));
} }
context.DrawGeometry(null, Models.CommitGraph.Pens[link.Color], geo); context.DrawGeometry(null, Models.CommitGraph.Pens[link.Color], geo);
} }
} }
private void DrawAnchors(DrawingContext context, Models.CommitGraph graph, double top, double bottom) private void DrawAnchors(DrawingContext context, Models.CommitGraph graph, double top, double bottom, double rowHeight)
{ {
var dotFill = DotBrush; var dotFill = DotBrush;
var dotFillPen = new Pen(dotFill, 2); var dotFillPen = new Pen(dotFill, 2);
@ -198,9 +213,11 @@ namespace SourceGit.Views
foreach (var dot in graph.Dots) foreach (var dot in graph.Dots)
{ {
if (dot.Center.Y < top) var center = new Point(dot.Center.X, dot.Center.Y * rowHeight);
if (center.Y < top)
continue; continue;
if (dot.Center.Y > bottom) if (center.Y > bottom)
break; break;
var pen = Models.CommitGraph.Pens[dot.Color]; var pen = Models.CommitGraph.Pens[dot.Color];
@ -210,16 +227,16 @@ namespace SourceGit.Views
switch (dot.Type) switch (dot.Type)
{ {
case Models.CommitGraph.DotType.Head: case Models.CommitGraph.DotType.Head:
context.DrawEllipse(dotFill, pen, dot.Center, 6, 6); context.DrawEllipse(dotFill, pen, center, 6, 6);
context.DrawEllipse(pen.Brush, null, dot.Center, 3, 3); context.DrawEllipse(pen.Brush, null, center, 3, 3);
break; break;
case Models.CommitGraph.DotType.Merge: case Models.CommitGraph.DotType.Merge:
context.DrawEllipse(pen.Brush, null, dot.Center, 6, 6); context.DrawEllipse(pen.Brush, null, center, 6, 6);
context.DrawLine(dotFillPen, new Point(dot.Center.X, dot.Center.Y - 3), new Point(dot.Center.X, dot.Center.Y + 3)); context.DrawLine(dotFillPen, new Point(center.X, center.Y - 3), new Point(center.X, center.Y + 3));
context.DrawLine(dotFillPen, new Point(dot.Center.X - 3, dot.Center.Y), new Point(dot.Center.X + 3, dot.Center.Y)); context.DrawLine(dotFillPen, new Point(center.X - 3, center.Y), new Point(center.X + 3, center.Y));
break; break;
default: default:
context.DrawEllipse(dotFill, pen, dot.Center, 3, 3); context.DrawEllipse(dotFill, pen, center, 3, 3);
break; break;
} }
} }

View file

@ -104,23 +104,32 @@ namespace SourceGit.Views
if (_inlines.Count == 0) if (_inlines.Count == 0)
return; return;
var height = Bounds.Height; var ro = new RenderOptions()
var width = Bounds.Width;
foreach (var inline in _inlines)
{ {
if (inline.X > width) TextRenderingMode = TextRenderingMode.SubpixelAntialias,
return; EdgeMode = EdgeMode.Antialias
};
if (inline.Element is { Type: Models.InlineElementType.Code }) using (context.PushRenderOptions(ro))
{
var height = Bounds.Height;
var width = Bounds.Width;
foreach (var inline in _inlines)
{ {
var rect = new Rect(inline.X, (height - inline.Text.Height - 2) * 0.5, inline.Text.WidthIncludingTrailingWhitespace + 8, inline.Text.Height + 2); if (inline.X > width)
var roundedRect = new RoundedRect(rect, new CornerRadius(4)); return;
context.DrawRectangle(InlineCodeBackground, null, roundedRect);
context.DrawText(inline.Text, new Point(inline.X + 4, (height - inline.Text.Height) * 0.5)); if (inline.Element is { Type: Models.InlineElementType.Code })
} {
else var rect = new Rect(inline.X, (height - inline.Text.Height - 2) * 0.5, inline.Text.WidthIncludingTrailingWhitespace + 8, inline.Text.Height + 2);
{ var roundedRect = new RoundedRect(rect, new CornerRadius(4));
context.DrawText(inline.Text, new Point(inline.X, (height - inline.Text.Height) * 0.5)); context.DrawRectangle(InlineCodeBackground, null, roundedRect);
context.DrawText(inline.Text, new Point(inline.X + 4, (height - inline.Text.Height) * 0.5));
}
else
{
context.DrawText(inline.Text, new Point(inline.X, (height - inline.Text.Height) * 0.5));
}
} }
} }
} }
@ -299,7 +308,7 @@ namespace SourceGit.Views
CultureInfo.CurrentCulture, CultureInfo.CurrentCulture,
FlowDirection.LeftToRight, FlowDirection.LeftToRight,
codeTypeface, codeTypeface,
fontSize, fontSize - 0.5,
foreground); foreground);
_inlines.Add(new Inline(x, link, elem)); _inlines.Add(new Inline(x, link, elem));
x += link.WidthIncludingTrailingWhitespace + 8; x += link.WidthIncludingTrailingWhitespace + 8;

View file

@ -52,7 +52,7 @@
<v:CommitRefsPresenter Margin="8,0,0,0" <v:CommitRefsPresenter Margin="8,0,0,0"
Foreground="{DynamicResource Brush.FG1}" Foreground="{DynamicResource Brush.FG1}"
FontFamily="{DynamicResource Fonts.Primary}" FontFamily="{DynamicResource Fonts.Primary}"
FontSize="11" FontSize="12"
VerticalAlignment="Center" VerticalAlignment="Center"
UseGraphColor="False"/> UseGraphColor="False"/>
<TextBlock Margin="4,0,0,0" <TextBlock Margin="4,0,0,0"

View file

@ -14,7 +14,7 @@
<TextBlock FontSize="18" <TextBlock FontSize="18"
Classes="bold" Classes="bold"
Text="{DynamicResource Text.CreateBranch.Title}"/> Text="{DynamicResource Text.CreateBranch.Title}"/>
<Grid Margin="0,16,0,0" RowDefinitions="32,32,Auto,Auto,Auto" ColumnDefinitions="140,*"> <Grid Margin="0,16,0,0" RowDefinitions="32,32,Auto,Auto,Auto,Auto" ColumnDefinitions="140,*">
<TextBlock Grid.Row="0" Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center" HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0" Margin="0,0,8,0"
@ -83,6 +83,19 @@
Content="{DynamicResource Text.CreateBranch.Checkout}" Content="{DynamicResource Text.CreateBranch.Checkout}"
IsChecked="{Binding CheckoutAfterCreated, Mode=TwoWay}" IsChecked="{Binding CheckoutAfterCreated, Mode=TwoWay}"
IsVisible="{Binding !IsBareRepository}"/> IsVisible="{Binding !IsBareRepository}"/>
<CheckBox Grid.Row="5" Grid.Column="1"
Content="{DynamicResource Text.Checkout.RecurseSubmodules}"
IsChecked="{Binding RecurseSubmodules, Mode=TwoWay}"
ToolTip.Tip="--recurse-submodules">
<CheckBox.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="IsBareRepository" Converter="{x:Static BoolConverters.Not}"/>
<Binding Path="CheckoutAfterCreated"/>
<Binding Path="IsRecurseSubmoduleVisible"/>
</MultiBinding>
</CheckBox.IsVisible>
</CheckBox>
</Grid> </Grid>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View file

@ -19,7 +19,7 @@
Classes="bold" Classes="bold"
Text="{DynamicResource Text.GitFlow.FinishHotfix}" Text="{DynamicResource Text.GitFlow.FinishHotfix}"
IsVisible="{Binding IsHotfix}"/> IsVisible="{Binding IsHotfix}"/>
<Grid Margin="0,16,0,0" RowDefinitions="32,32" ColumnDefinitions="150,*"> <Grid Margin="0,16,0,0" RowDefinitions="32,32,32,32" ColumnDefinitions="150,*">
<TextBlock Grid.Row="0" Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
HorizontalAlignment="Right" VerticalAlignment="Center" HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,8,0" Margin="0,0,8,0"
@ -30,8 +30,19 @@
</StackPanel> </StackPanel>
<CheckBox Grid.Row="1" Grid.Column="1" <CheckBox Grid.Row="1" Grid.Column="1"
Content="{DynamicResource Text.GitFlow.FinishWithSquash}"
IsChecked="{Binding Squash, Mode=TwoWay}"
ToolTip.Tip="--squash"/>
<CheckBox Grid.Row="2" Grid.Column="1"
Content="{DynamicResource Text.GitFlow.FinishWithPush}"
IsChecked="{Binding AutoPush, Mode=TwoWay}"
ToolTip.Tip="--push"/>
<CheckBox Grid.Row="3" Grid.Column="1"
Content="{DynamicResource Text.GitFlow.KeepBranchAfterFinish}" Content="{DynamicResource Text.GitFlow.KeepBranchAfterFinish}"
IsChecked="{Binding KeepBranch, Mode=TwoWay}"/> IsChecked="{Binding KeepBranch, Mode=TwoWay}"
ToolTip.Tip="-k"/>
</Grid> </Grid>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View file

@ -30,7 +30,7 @@
Background="{DynamicResource Brush.Window}" Background="{DynamicResource Brush.Window}"
BorderThickness="0,0,0,1" BorderThickness="0,0,0,1"
BorderBrush="{DynamicResource Brush.Border0}"> BorderBrush="{DynamicResource Brush.Border0}">
<Grid> <Grid x:Name="CommitListHeader">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
<ColumnDefinition Width="3"/> <ColumnDefinition Width="3"/>
@ -76,7 +76,7 @@
<Style Selector="ListBoxItem"> <Style Selector="ListBoxItem">
<Setter Property="Margin" Value="0"/> <Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/> <Setter Property="Padding" Value="0"/>
<Setter Property="Height" Value="28"/> <Setter Property="Height" Value="26"/>
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<Grid> <Grid>
@ -145,7 +145,7 @@
Foreground="{DynamicResource Brush.FG1}" Foreground="{DynamicResource Brush.FG1}"
FontFamily="{DynamicResource Fonts.Primary}" FontFamily="{DynamicResource Fonts.Primary}"
ShowTags="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowTagsInGraph}" ShowTags="{Binding Source={x:Static vm:Preferences.Instance}, Path=ShowTagsInGraph}"
FontSize="11" FontSize="12"
VerticalAlignment="Center"> VerticalAlignment="Center">
<v:CommitRefsPresenter.UseGraphColor> <v:CommitRefsPresenter.UseGraphColor>
<MultiBinding Converter="{x:Static BoolConverters.Or}"> <MultiBinding Converter="{x:Static BoolConverters.Or}">

View file

@ -202,9 +202,20 @@
<Grid Grid.Row="2" x:Name="LeftSidebarGroups" Margin="0,4,0,0" RowDefinitions="28,Auto,28,Auto,28,Auto,28,Auto,28,Auto" SizeChanged="OnLeftSidebarSizeChanged"> <Grid Grid.Row="2" x:Name="LeftSidebarGroups" Margin="0,4,0,0" RowDefinitions="28,Auto,28,Auto,28,Auto,28,Auto,28,Auto" SizeChanged="OnLeftSidebarSizeChanged">
<!-- Local Branches --> <!-- Local Branches -->
<ToggleButton Grid.Row="0" Classes="group_expander" IsChecked="{Binding IsLocalBranchGroupExpanded, Mode=TwoWay}"> <ToggleButton Grid.Row="0" Classes="group_expander" IsChecked="{Binding IsLocalBranchGroupExpanded, Mode=TwoWay}">
<Grid ColumnDefinitions="16,*"> <Grid ColumnDefinitions="16,*,Auto,Auto">
<Path Grid.Column="0" Width="11" Height="11" HorizontalAlignment="Left" Data="{StaticResource Icons.Local}" Fill="{DynamicResource Brush.FG2}"/> <Path Grid.Column="0" Width="11" Height="11" HorizontalAlignment="Left" Data="{StaticResource Icons.Local}" Fill="{DynamicResource Brush.FG2}"/>
<TextBlock Grid.Column="1" Classes="group_header_label" Margin="0" Text="{DynamicResource Text.Repository.LocalBranches}"/> <TextBlock Grid.Column="1" Classes="group_header_label" Margin="0" Text="{DynamicResource Text.Repository.LocalBranches}"/>
<Button Grid.Column="2"
Classes="icon_button"
Width="14"
Margin="8,0,0,0"
Click="OnOpenSortLocalBranchMenu"
ToolTip.Tip="{DynamicResource Text.Repository.BranchSort}">
<Path Width="12" Height="12" Data="{StaticResource Icons.Order}"/>
</Button>
<Button Grid.Column="3" Classes="icon_button" Width="14" Margin="8,0" Command="{Binding CreateNewBranch}" ToolTip.Tip="{DynamicResource Text.Repository.NewBranch}">
<Path Width="12" Height="12" Data="{StaticResource Icons.Branch.Add}"/>
</Button>
</Grid> </Grid>
</ToggleButton> </ToggleButton>
<v:BranchTree Grid.Row="1" <v:BranchTree Grid.Row="1"
@ -218,10 +229,18 @@
<!-- Remotes --> <!-- Remotes -->
<ToggleButton Grid.Row="2" Classes="group_expander" IsChecked="{Binding IsRemoteGroupExpanded, Mode=TwoWay}"> <ToggleButton Grid.Row="2" Classes="group_expander" IsChecked="{Binding IsRemoteGroupExpanded, Mode=TwoWay}">
<Grid ColumnDefinitions="16,*,Auto"> <Grid ColumnDefinitions="16,*,Auto,Auto">
<Path Grid.Column="0" Width="12" Height="12" HorizontalAlignment="Left" Data="{StaticResource Icons.Remotes}" Fill="{DynamicResource Brush.FG2}"/> <Path Grid.Column="0" Width="12" Height="12" HorizontalAlignment="Left" Data="{StaticResource Icons.Remotes}" Fill="{DynamicResource Brush.FG2}"/>
<TextBlock Grid.Column="1" Classes="group_header_label" Margin="0" Text="{DynamicResource Text.Repository.Remotes}"/> <TextBlock Grid.Column="1" Classes="group_header_label" Margin="0" Text="{DynamicResource Text.Repository.Remotes}"/>
<Button Grid.Column="2" Classes="icon_button" Width="14" Margin="8,0" Command="{Binding AddRemote}" ToolTip.Tip="{DynamicResource Text.Repository.Remotes.Add}"> <Button Grid.Column="2"
Classes="icon_button"
Width="14"
Margin="8,0,0,0"
Click="OnOpenSortRemoteBranchMenu"
ToolTip.Tip="{DynamicResource Text.Repository.BranchSort}">
<Path Width="12" Height="12" Data="{StaticResource Icons.Order}"/>
</Button>
<Button Grid.Column="3" Classes="icon_button" Width="14" Margin="8,0" Command="{Binding AddRemote}" ToolTip.Tip="{DynamicResource Text.Repository.Remotes.Add}">
<Path Width="12" Height="12" Data="{StaticResource Icons.Remote.Add}"/> <Path Width="12" Height="12" Data="{StaticResource Icons.Remote.Add}"/>
</Button> </Button>
</Grid> </Grid>

View file

@ -403,6 +403,28 @@ namespace SourceGit.Views
e.Handled = true; e.Handled = true;
} }
private void OnOpenSortLocalBranchMenu(object sender, RoutedEventArgs e)
{
if (sender is Button button && DataContext is ViewModels.Repository repo)
{
var menu = repo.CreateContextMenuForBranchSortMode(true);
menu?.Open(button);
}
e.Handled = true;
}
private void OnOpenSortRemoteBranchMenu(object sender, RoutedEventArgs e)
{
if (sender is Button button && DataContext is ViewModels.Repository repo)
{
var menu = repo.CreateContextMenuForBranchSortMode(false);
menu?.Open(button);
}
e.Handled = true;
}
private void OnOpenSortTagMenu(object sender, RoutedEventArgs e) private void OnOpenSortTagMenu(object sender, RoutedEventArgs e)
{ {
if (sender is Button button && DataContext is ViewModels.Repository repo) if (sender is Button button && DataContext is ViewModels.Repository repo)

View file

@ -9,16 +9,8 @@
x:DataType="vm:Repository"> x:DataType="vm:Repository">
<Grid ColumnDefinitions="*,Auto,*"> <Grid ColumnDefinitions="*,Auto,*">
<StackPanel Grid.Column="0" Orientation="Horizontal" Margin="4,0,0,0"> <StackPanel Grid.Column="0" Orientation="Horizontal" Margin="4,0,0,0">
<Button Classes="icon_button" Width="32" Command="{Binding OpenInFileManager}" ToolTip.Tip="{DynamicResource Text.Repository.Explore}">
<Path Width="14" Height="14" Data="{StaticResource Icons.Explore}" Margin="0,2,0,0"/>
</Button>
<Button Classes="icon_button" Width="32" Click="OpenWithExternalTools" IsVisible="{Binding !IsBare}" ToolTip.Tip="{DynamicResource Text.Repository.OpenWithExternalTools}"> <Button Classes="icon_button" Width="32" Click="OpenWithExternalTools" IsVisible="{Binding !IsBare}" ToolTip.Tip="{DynamicResource Text.Repository.OpenWithExternalTools}">
<Path Width="13" Height="13" Data="{StaticResource Icons.OpenWith}"/> <Path Width="14" Height="14" Data="{StaticResource Icons.Explore}" Margin="0,2,0,0"/>
</Button>
<Button Classes="icon_button" Width="32" Command="{Binding OpenInTerminal}" ToolTip.Tip="{DynamicResource Text.Repository.Terminal}">
<Path Width="13" Height="13" Data="{StaticResource Icons.Terminal}"/>
</Button> </Button>
<Button Classes="icon_button" Width="32" Click="OpenGitLogs" ToolTip.Tip="{DynamicResource Text.Repository.ViewLogs}"> <Button Classes="icon_button" Width="32" Click="OpenGitLogs" ToolTip.Tip="{DynamicResource Text.Repository.ViewLogs}">

View file

@ -28,16 +28,16 @@
<TextBlock Grid.Column="4" Classes="primary" Text="{Binding CommitterTimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/> <TextBlock Grid.Column="4" Classes="primary" Text="{Binding CommitterTimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>
</Grid> </Grid>
<TextBlock Grid.Row="1" Classes="primary" Text="{Binding Subject}" VerticalAlignment="Bottom"/> <TextBlock Grid.Row="1" Classes="primary" Text="{Binding Subject}" Margin="0,6,0,0"/>
</Grid> </Grid>
</DataTemplate> </DataTemplate>
</UserControl.DataTemplates> </UserControl.DataTemplates>
<Grid RowDefinitions="50,*" Margin="4"> <Grid RowDefinitions="Auto,*" Margin="4">
<!-- Compare Revision Info --> <!-- Compare Revision Info -->
<Grid Grid.Row="0" Margin="0,0,0,6" ColumnDefinitions="*,32,*,Auto"> <Grid Grid.Row="0" Margin="0,0,0,6" ColumnDefinitions="*,32,*,Auto">
<!-- Base Revision --> <!-- Base Revision -->
<Border Grid.Column="0" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4"> <Border Grid.Column="0" BorderBrush="{DynamicResource Brush.Diff.DeletedHighlight}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
<ContentControl Content="{Binding StartPoint}"/> <ContentControl Content="{Binding StartPoint}"/>
</Border> </Border>
@ -47,7 +47,7 @@
</Button> </Button>
<!-- Right Revision --> <!-- Right Revision -->
<Border Grid.Column="2" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4"> <Border Grid.Column="2" BorderBrush="{DynamicResource Brush.Diff.AddedHighlight}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
<ContentControl Content="{Binding EndPoint}"/> <ContentControl Content="{Binding EndPoint}"/>
</Border> </Border>

View file

@ -1502,7 +1502,7 @@ namespace SourceGit.Views
{ {
if (line.Content.Length > 10000) if (line.Content.Length > 10000)
{ {
builder.Append(line.Content.Substring(0, 1000)); builder.Append(line.Content.AsSpan(0, 1000));
builder.Append($"...({line.Content.Length - 1000} characters trimmed)"); builder.Append($"...({line.Content.Length - 1000} characters trimmed)");
} }
else else