diff --git a/src/Commands/Commit.cs b/src/Commands/Commit.cs index 4a5f2471..a3dde9a9 100644 --- a/src/Commands/Commit.cs +++ b/src/Commands/Commit.cs @@ -5,14 +5,12 @@ namespace SourceGit.Commands { /// `git commit`命令 /// public class Commit : Command { - private string msg = null; - public Commit(string repo, string message, bool amend) { - msg = Path.GetTempFileName(); - File.WriteAllText(msg, message); + var file = Path.GetTempFileName(); + File.WriteAllText(file, message); Cwd = repo; - Args = $"commit --file=\"{msg}\""; + Args = $"commit --file=\"{file}\""; if (amend) Args += " --amend --no-edit"; } } diff --git a/src/Commands/Reword.cs b/src/Commands/Reword.cs new file mode 100644 index 00000000..3296c37c --- /dev/null +++ b/src/Commands/Reword.cs @@ -0,0 +1,16 @@ +using System.IO; + +namespace SourceGit.Commands { + /// + /// 编辑HEAD的提交信息 + /// + public class Reword : Command { + public Reword(string repo, string msg) { + var tmp = Path.GetTempFileName(); + File.WriteAllText(tmp, msg); + + Cwd = repo; + Args = $"commit --amend --allow-empty --file=\"{tmp}\""; + } + } +} diff --git a/src/Resources/Locales/en_US.xaml b/src/Resources/Locales/en_US.xaml index 6e5d7c8b..38144852 100644 --- a/src/Resources/Locales/en_US.xaml +++ b/src/Resources/Locales/en_US.xaml @@ -196,6 +196,8 @@ Interactive Rebase '{0}' from Here Rebase '{0}' to Here Cherry-Pick This Commit + Reword + Squash Into Parent Revert Commit Save as Patch ... Copy Commit SHA @@ -466,6 +468,15 @@ Reload current repository if possible Stage or unstage selected files + Reword Commit Message + On : + Message : + + Squash HEAD Into Parent + HEAD : + To : + Reword : + Git has NOT been configured. Please to go [Preference] and configure it first. Path[{0}] not exists! Can NOT locate bash.exe. Make sure bash.exe exists under the same folder with git.exe @@ -486,7 +497,7 @@ Tag name can NOT be null Bad name for tag. Regex: ^[\\w\\-\\.]+$ Duplicated tag name! - Commit subject can NOT be empty + Commit message can NOT be empty Invalid path for patch file Invalid relative path Invalid path for archive file diff --git a/src/Resources/Locales/zh_CN.xaml b/src/Resources/Locales/zh_CN.xaml index 1220f92e..9012d46b 100644 --- a/src/Resources/Locales/zh_CN.xaml +++ b/src/Resources/Locales/zh_CN.xaml @@ -195,6 +195,8 @@ 从此处开始对 '{0}' 交互式变基 变基 '{0}' 到此处 挑选此提交 + 编辑提交信息 + 合并此提交到上一个提交 回滚此提交 另存为补丁 ... 复制提交指纹 @@ -465,6 +467,15 @@ 重新加载当前仓库信息(仅在仓库页起效) 暂存或从暂存中移除当前选中 + 编辑提交信息 + 提交: + 提交信息: + + 合并HEAD到上一个提交 + 当前提交 : + 合并到 : + 修改提交信息: + GIT尚未配置。请打开【偏好设置】配置GIT路径。 路径({0})不存在或不可读取! 无法找到bash.exe,请确保其在git.exe同目录中! diff --git a/src/Views/Popups/Reword.xaml b/src/Views/Popups/Reword.xaml new file mode 100644 index 00000000..ca269d05 --- /dev/null +++ b/src/Views/Popups/Reword.xaml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Views/Popups/Reword.xaml.cs b/src/Views/Popups/Reword.xaml.cs new file mode 100644 index 00000000..71c97057 --- /dev/null +++ b/src/Views/Popups/Reword.xaml.cs @@ -0,0 +1,40 @@ +using System.Threading.Tasks; +using System.Windows.Controls; + +namespace SourceGit.Views.Popups { + /// + /// 编辑HEAD的提交描述 + /// + public partial class Reword : Controls.PopupWidget { + private string repo = null; + private string old = null; + + public string Msg { get; set; } + + public Reword(string repo, Models.Commit commit) { + this.repo = repo; + this.old = $"{commit.Subject}\n{commit.Message}".Trim(); + this.Msg = old; + InitializeComponent(); + txtCurrent.Text = $"{commit.ShortSHA} {commit.Subject}"; + } + + public override string GetTitle() { + return App.Text("Reword"); + } + + public override Task Start() { + txtMsg.GetBindingExpression(TextBox.TextProperty).UpdateSource(); + if (Validation.GetHasError(txtMsg)) return null; + + return Task.Run(() => { + if (old == Msg) return true; + + Models.Watcher.SetEnabled(repo, false); + new Commands.Reword(repo, Msg).Exec(); + Models.Watcher.SetEnabled(repo, true); + return true; + }); + } + } +} diff --git a/src/Views/Popups/Squash.xaml b/src/Views/Popups/Squash.xaml new file mode 100644 index 00000000..5dffe20c --- /dev/null +++ b/src/Views/Popups/Squash.xaml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Views/Popups/Squash.xaml.cs b/src/Views/Popups/Squash.xaml.cs new file mode 100644 index 00000000..03d53517 --- /dev/null +++ b/src/Views/Popups/Squash.xaml.cs @@ -0,0 +1,40 @@ +using System.Threading.Tasks; +using System.Windows.Controls; + +namespace SourceGit.Views.Popups { + /// + /// 合并当前HEAD提交到上一个 + /// + public partial class Squash : Controls.PopupWidget { + private string repo = null; + private string to = null; + + public string Msg { get; set; } + + public Squash(string repo, Models.Commit head, Models.Commit parent) { + this.repo = repo; + this.to = parent.SHA; + this.Msg = $"{parent.Subject}\n{parent.Message}".Trim(); + InitializeComponent(); + txtHead.Text = $"{head.ShortSHA} {head.Subject}"; + txtParent.Text = $"{parent.ShortSHA} {parent.Subject}"; + } + + public override string GetTitle() { + return App.Text("Squash"); + } + + public override Task Start() { + txtMsg.GetBindingExpression(TextBox.TextProperty).UpdateSource(); + if (Validation.GetHasError(txtMsg)) return null; + + return Task.Run(() => { + Models.Watcher.SetEnabled(repo, false); + var succ = new Commands.Reset(repo, to, "--soft").Exec(); + if (succ) new Commands.Commit(repo, Msg, true).Exec(); + Models.Watcher.SetEnabled(repo, true); + return true; + }); + } + } +} diff --git a/src/Views/Widgets/Histories.xaml.cs b/src/Views/Widgets/Histories.xaml.cs index 1cd4a701..2f5c3f61 100644 --- a/src/Views/Widgets/Histories.xaml.cs +++ b/src/Views/Widgets/Histories.xaml.cs @@ -294,6 +294,31 @@ namespace SourceGit.Views.Widgets { e.Handled = true; }; menu.Items.Add(reset); + } else { + var reword = new MenuItem(); + reword.Header = App.Text("CommitCM.Reword"); + reword.Click += (o, e) => { + new Popups.Reword(repo.Path, commit).Show(); + e.Handled = true; + }; + menu.Items.Add(reword); + + var squash = new MenuItem(); + squash.Header = App.Text("CommitCM.Squash"); + squash.IsEnabled = commit.Parents.Count == 1; + squash.Click += (o, e) => { + foreach (var c in cachedCommits) { + if (c.SHA == commit.Parents[0]) { + new Popups.Squash(repo.Path, commit, c).Show(); + e.Handled = true; + return; + } + } + + Models.Exception.Raise("Can NOT found parent of HEAD!"); + e.Handled = true; + }; + menu.Items.Add(squash); } if (!merged) {