Gitのコマンドをプログラムから実行する

皆さん Git 使っていますか?いまどきのプログラマなら使っていない人を見つけるほうが難しいかもしれません。

とはいえ Git をコマンドラインから実行するのが不得意な方もいるでしょう。実は私もコマンドラインからは実行しない派です。過去にコマンド間違えてコミットの履歴をぶっ壊したり、さかさにマージしてしまったり、いろいろやらかしているので。

Git の GUI ツールは GitHub とか SourceTree とか tourtoiseGit など、いろいろあります。ただし、自分が欲しい機能が実装されていない場合は自作する必要があります。下記のコードを使って自分で Git コマンドを実行してください。

フォームに下記のコントロールを配置してください。

textBox1 ( Git の実行オプションを指定する )
textBox2 ( Git の実行場所を指定する )
button1 ( Git のコマンドを実行する )
listBox1 ( Git コマンドの実行結果を表示する )

ExecGitCommand( "コマンドラインオプション", "実行するディレクトリ" ); という使い方です。

using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

namespace aaa
{

	public partial class Form1 : Form
	{

		public Form1()
		{
			InitializeComponent();
		}

		private void Form1_Load( object sender, EventArgs e )
		{

			// 実行したい git のオプションを指定してください.
			textBox1.Text = "log";

			// .git の含まれているディレクトリを指定してください.
			textBox2.Text = "c:/test/my_project";

		}

		private void button1_Click( object sender, EventArgs e )
		{

			// Git のコマンドを発行する.
			String args = textBox1.Text.Trim();
			String dir = textBox2.Text.Trim();
			List<String> ret = ExecGitCommand( args, dir );

			// 実行結果を表示する.
			if ( ret != null )
			{

				listBox1.Items.Clear();

				for ( int k = 0; k < ret.Count; k++ )
				{
					listBox1.Items.Add( ret[k] );
				}

			}
			else
			{
				MessageBox.Show( "ret is NULL." );
			}

		}

		private List<string> ExecGitCommand( string arguments, string working_directory )
		{

			ProcessStartInfo psi = new ProcessStartInfo();
			psi.FileName               = "git";
			psi.Arguments              = arguments;
			psi.WorkingDirectory       = working_directory;
			psi.RedirectStandardOutput = true;
			psi.RedirectStandardError  = true;
			psi.StandardOutputEncoding = Encoding.UTF8; // ここは意外と重要.
			psi.StandardErrorEncoding  = Encoding.UTF8; // ここは意外と重要.
			psi.UseShellExecute        = false;
			psi.CreateNoWindow         = true;

			List<String> output = new List<string>();

			try
			{

				using ( Process proc = Process.Start( psi ) )
				{

					while ( !proc.StandardOutput.EndOfStream )
					{
						output.Add( proc.StandardOutput.ReadLine() );
					}

					string err = proc.StandardError.ReadToEnd();
					proc.WaitForExit();

					if ( proc.ExitCode != 0 )
					{
						throw new Exception( err );
					}

				}

			}
			catch ( Exception excp )
			{
				output.Add( excp.Message );
			}

			return output;

		}
	}
}