【问题标题】:Run git commands from a C# function从 C# 函数运行 git 命令
【发布时间】:2014-11-27 19:54:42
【问题描述】:

当我的 C# 代码检测到跟踪文件的更改时,它如何运行 git 命令?为此,我正在编写一个 VisualStudio/C# 控制台项目。

我是 .NET 环境的新手,目前致力于将自动 GIT 提交集成到文件夹。我需要在已知文件夹上自动提交任何更改/添加/删除并将其推送到 git 远程。任何指导表示赞赏。谢谢。

这是我所拥有的,最后一个是我需要一些指导的:

  1. Git 存储库最初设置在具有正确忽略文件的文件夹上(完成)。
  2. 我正在使用 C# FileSystemWatcher 来捕获对所述文件夹的任何更改(完成)。
  3. 一旦我的项目检测到更改,它就需要提交并推送这些更改(待定)。

项目需要运行的暂定命令:

git add -A
git commit "explanations_of_changes"
git push our_remote

注意:此代码(无需用户交互)将是提交此 repo 的唯一实体,因此我不担心冲突并相信此流程会起作用。

【问题讨论】:

    标签: c# git visual-studio-2013 version-control windows-7


    【解决方案1】:

    我意识到这是一个老问题,但我想添加我最近遇到的解决方案以帮助将来的人。

    PowerShell 类提供了一种与 git 交互的简单方法。这是 .NET 中 System.Management.Automation 命名空间的一部分。请注意,System.Management.Automation.dll 可通过 NuGet 获得。

    string directory = ""; // directory of the git repository
    
    using (PowerShell powershell = PowerShell.Create()) {
        // this changes from the user folder that PowerShell starts up with to your git repository
        powershell.AddScript($"cd {directory}");
    
        powershell.AddScript(@"git init");
        powershell.AddScript(@"git add *");
        powershell.AddScript(@"git commit -m 'git commit from PowerShell in C#'");
        powershell.AddScript(@"git push");
    
        Collection<PSObject> results = powershell.Invoke();
    }
    

    在我看来,这比使用Process.Start() 方法更干净、更好。您可以通过编辑添加到 powershell 对象的脚本来根据您的特定需求对其进行修改。

    正如@ArtemIllarionov 所评论的,powershell.Invoke() 不会返回错误,但Streams 属性具有输出信息。特别是powerShell.Streams.Error 错误。

    【讨论】:

    • 我们如何使用 SourceTree 之类的使用它自己的 git 窗口的东西来做到这一点?
    • 源码树只是 git 的一个可视化界面。您可以在 repo 上运行 git 命令而不使用源代码树,这些更改将反映在源代码树中。
    • 我的意思是它不使用标准的 git 窗口,它使用自己的版本 ming32.exe。这是一个 bash 命令窗口。我每天在该窗口中使用的命令根本无法在 powershell 中运行。例如 "target_branch="dev"; git checkout $target_branch" (即分配和使用完全一样的变量),在 powershell 中不起作用。再说一遍,如何从 c# 调用 git 的问题并没有真正得到解答。
    • 注意:此解决方案使用 System.Management.Automation,您需要 .Net Core 2.0 及更高版本
    • 我试过了,Invoke() 的结果只包含最后一个命令的输出。知道如何获得所有输出吗?
    【解决方案2】:

    如果你想用C#来做,你可以在检测到文件变化时通过Process.Start调用外部git命令

    string gitCommand = "git";
    string gitAddArgument = @"add -A";
    string gitCommitArgument = @"commit ""explanations_of_changes""";
    string gitPushArgument = @"push our_remote";
    
    Process.Start(gitCommand, gitAddArgument);
    Process.Start(gitCommand, gitCommitArgument);
    Process.Start(gitCommand, gitPushArgument);
    

    不是最好的解决方案,但它适用于 C#

    【讨论】:

    • 我使用 Process 类和这个示例来找到一个适合我的用例的解决方案。谢谢。
    【解决方案3】:
        //Console.WriteLine(CommandOutput("git status"));
    
        public static string CommandOutput(string command,
                                           string workingDirectory = null)
        {
            try
            {
                ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd", "/c " + command);
    
                procStartInfo.RedirectStandardError = procStartInfo.RedirectStandardInput = procStartInfo.RedirectStandardOutput = true;
                procStartInfo.UseShellExecute = false;
                procStartInfo.CreateNoWindow = true;
                if (null != workingDirectory)
                {
                    procStartInfo.WorkingDirectory = workingDirectory;
                }
    
                Process proc = new Process();
                proc.StartInfo = procStartInfo;
                proc.Start();
    
                StringBuilder sb = new StringBuilder();
                proc.OutputDataReceived += delegate (object sender, DataReceivedEventArgs e)
                {
                    sb.AppendLine(e.Data);
                };
                proc.ErrorDataReceived += delegate (object sender, DataReceivedEventArgs e)
                {
                    sb.AppendLine(e.Data);
                };
    
                proc.BeginOutputReadLine();
                proc.BeginErrorReadLine();
                proc.WaitForExit();
                return sb.ToString();
            }
            catch (Exception objException)
            {
                return $"Error in command: {command}, {objException.Message}";
            }
        }
    

    【讨论】:

    • 我一直在尝试采用这种方法,但是如果您在非本地环境中运行并且需要进行身份验证,则无法确定身份验证。
    • @Raj 非常感谢这个脚本。这正是我正在寻找的东西,有了它,我可以使用 C# 程序接收从我的 git 命令接收到的所有输出。我个人使用powershell 而不是cmd 并将我的存储库目录而不是/c 并快速测试它我输入命令git diff 并打印输出如下:Console.Write(CommandOutput("git diff",strMyRepoPath));
    【解决方案4】:

    试试 LibGit2Sharp,这是 .NET 的原生 git 实现:

    https://github.com/libgit2/libgit2sharp/

    【讨论】:

    • 想指出 LibGit2Sharp 不支持 SSH 并且有一些其他的细微差别。花了几个小时试图让 LibGit2Sharp 工作,现在我因此不得不放弃它。只是认为其他人在深入研究之前应该知道,它可能难以处理需要 SSH 的解决方案以及像多个遥控器这样的复杂情况。 (它在技术上可以处理它们,但到目前为止肯定很痛苦。)对于简单的东西,这很有效。
    • LibGit2Sharp 不支持浅克隆,这意味着您不能只克隆没有所有历史记录的最新快照。因此,根据您的项目历史,克隆的数据可能会非常大,这使得它不太适合所有需要磁盘空间或性能的用例。
    【解决方案5】:

    另一种方法是为您的项目设置 Grunt 和 TaskRunner。

    Grunt 应该能够自动检测项目中一个或多个文件夹的更改并执行适当的 git 命令来提交它。

    Task Runner 允许您在 Visual Studio 中初始化和运行 Grunt。

    Visual Studio 团队表示,Task Runner 将集成到 Visual Studio 的未来版本中,因此这可能是一个长期解决方案。

    注意:在 cmets 中已经提到过,但我觉得值得再次提及的是,在将文件保存到存储库时自动提交并不是最佳实践。您希望推送功能/原子代码更改,而不是简单的文本更改。自动提交风险自负。

    【讨论】:

      【解决方案6】:

      包管理器控制台是 Powershell 控制台。所以你可以从那里运行你的 git 命令。

      【讨论】:

      • 谢谢 Voam。我是 .NET 的新手,所以澄清一下。我需要对这些命令进行硬编码,以便在文件更改时自动运行它们。你的意思是我的代码可以使用包管理器控制台以某种方式根据需要运行这些命令运行时?
      • 我没有看到 Visual Studio 本身在文件更改时启动保存到 git 的过程的要求。
      • 如果您对如何完成此操作有任何其他想法,请告诉我。
      • OP 中特别指出“我的 C# 代码如何运行 git 命令”,这不是使用包管理器控制台可以实现的
      猜你喜欢
      • 2011-04-28
      • 2021-05-12
      • 1970-01-01
      • 2021-10-22
      • 2018-05-06
      • 2015-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多