2012-12-05 9 views
11

私は、次の処理を行い、シェルスクリプト記述しようとしています:すべての変更は、プルするためのgitで変更をチェックし、変更されたファイルをループするシェルスクリプト?

  1. をチェックし、リモートのgitリポジトリを。
  2. リモートgitリポジトリに変更がある場合は、それらの変更を取得します。
  3. 新規または変更されたファイルをループします。

私の研究では、これらのことを行うために必要なコマンドがいくつか見つかりましたが、シェルスクリプトで一緒に動作させることができませんでした。ここで

は、私が持っているコマンドの一部とスクリプトです:

#!/bin/sh 

#Check if there are any changed files 
git --git-dir="/dir/.git" fetch origin 

if git --git-dir="/dir/.git" log HEAD..origin/master --oneline 
then 

#Output the modified files from the last pull 
     git --git-dir="/dir/.git" diff --name-status ORIG_HEAD.. 

fi 

私はこのスクリプトでは、コマンドでの作業を取得することができていないものは、次のとおりです。

  1. if文が変更されているかどうかをチェックするか、常にそうでないかを調べるif文です。私は他のgitコマンドでif文を試しましたが、それらも常に真です。 gitは、通常のシェルコマンドのように0または1の応答を得ることはできないようです。 if文で適切な応答を返すために、このようなgitコマンドや他のgitコマンドをどのように取得できますか?
  2. どのようにして、変更されたファイルを配列に表示してforを使用してループすることができるように、コマンドからの変数出力を割り当てることができますか?

私のスクリプトのコマンドがこの場合実際にはうまくいかない場合は、これを行うより良い方法は何ですか?

編集:変更されたファイルをループするときにはっきりしている必要があります。ファイルをループする前に、リモートのリポジトリから変更をプルする必要があります。

答えて

9

、あなたがgit diff --quiet(またはgit diff --exit-codeを使用することができますが、その終了コードのためにそれを使用しているとき、一般的に、あなたはそれがとにかく出力を印刷しないようにしたい、とgit diff --quietは意味--exit-code)、変更があったかどうかを判断します。変更がある場合は1の値が、そうでない場合は0の値が与えられます。だから、あなただけ実行するコードを持つようにしたい場合は、変更がある場合:あなたの2つ目の質問については

if ! git --git-dir="/dir/.git" diff --quiet 
then 
    # do stuff... 
fi 

が、私はgit diff-treeからラインを読むためにwhile read ...ループをお勧めします:

git --git-dir="/dir/.git" diff-tree ORIG_HEAD.. | \ 
    while read srcmode dstmode srcsha dstsha status srcfile dstfile 
    do 
     # do something with $srcfile and $dstfile 
    done 

。なお、 $srcmodeの最初の文字は:で、ファイル名が変更された場合は$dstfileになります。名前の変更を心配したくない場合は、--no-renamesを渡してください。名前を変更する代わりに、追加と削除だけが表示されます。

3

エラーがなければ、gitは通常0以外のステータスで終了しません。私がコミットされていない変更を検出するために見つけた最も簡単な方法は、このようなものである:一般的に

let changes=0 
while read status filename; do 
    let changes=1 
    # do something with this filename/status 
done < <(git status --porcelain) 
if ((! changes)); then 
    echo "No changes." 
fi 

、あなたがそれをサポートするサブコマンドに--porcelainを使用する必要があり、コードからのgitを駆動しようとするつもりなら、よりオートメーションに優しい方法で動作させることができます。独自のシェルコマンドを構築しなくても、他の言語のライブラリを調べてgitとやり取りすることもできます。例えば、Rubyにはgritがあります。

あなたのケースでは、アップストリームで変更されたものを検出する必要があります。そのためには、おそらくgit diff-treeを使用します。上記と同様に、論理:あなたの最初の質問については

git fetch # not pull 
while read filename; do 
    # do something with filename 
done < <(git diff-tree --name-only origin/master master) # or whatever branch you're using 
+0

ハイマーク。お返事をありがとうございます。私はあなたのスクリプトを実行しようとしましたが、次のエラーが表示されます:予期しないトークン '<" 'done <"(git status --porcelain)の近くで構文エラーが発生しました。任意のアイデアを正しい構文は何でしょうか? – startupsmith

+0

あなたは確かにbashを使用していますか? –

+0

こんにちは。あなたは正しく、私はbashを使用していない...それは今動作します。私はこれをさらに調べる必要がありますが、私はこのスクリプトがリモートのリポジトリから引き出される前に、変更されたファイルをループすることがわかります。 – startupsmith

1

変更されたファイルのすべてのファイル名を一覧表示するには、単にgit diff --name-onlyを使用します。

たとえば、ここでは、編集されたすべてのPHPファイルを一覧表示し、構文をテストする簡単なスクリプトです。

#!/bin/bash 
files=`git diff --name-only | grep -E '.php$' ` 
for file in $files; do 
    php -l $file 
done 
関連する問題