web-dev-qa-db-ja.com

スクリプトからGit作業ディレクトリがクリーンかどうかを確認する

Git作業ディレクトリを宛先としてrsyncを実行するスクリプトがあります。作業ディレクトリがクリーン(コミットする変更がない)かどうかに応じて、スクリプトに異なる動作をさせたい。たとえば、git statusの出力が以下の場合、スクリプトを終了させます。

git status
Already up-to-date.
# On branch master
nothing to commit (working directory clean)
Everything up-to-date

ディレクトリがクリーンでない場合は、さらにいくつかのコマンドを実行してください。

上記のような出力をシェルスクリプトで確認するにはどうすればよいですか?

102
brentwpeterson

git statusの出力を解析することは悪い考えです。出力は人間が読み取れるように意図されており、機械が読み取れるようには意図されていないからです。 Gitの将来のバージョンまたは異なる構成の環境で出力が同じままである保証はありません。

VVのコメント は正しい方向にありますが、コミットされていない変更がある場合、残念ながらgit statusの戻りコードは変更されません。ただし、これは --porcelain オプションを提供します。これにより、git status --porcelainの出力がスクリプト用に解析しやすい形式にフォーマットされますandは、ユーザー設定に関係なく、Gitバージョン全体で安定した状態を保ちます。

git status --porcelainの空の出力を、コミットする変更がないことを示すインジケータとして使用できます。

if [ -z "$(git status --porcelain)" ]; then 
  # Working directory clean
else 
  # Uncommitted changes
fi

作業ディレクトリ内の追跡されていないファイルを気にしない場合は、 --untracked-files=no オプションを使用してそれらを無視できます。

if [ -z "$(git status --untracked-files=no --porcelain)" ]; then 
  # Working directory clean excluding untracked files
else 
  # Uncommitted changes in tracked files
fi

実際に_git statusstdoutへの出力なしに失敗する条件に対してこれをより堅牢にするために、チェックを調整できますに:

if output=$(git status --porcelain) && [ -z "$output" ]; then
  # Working directory clean
else 
  # Uncommitted changes
fi

注目に値することですが、git statusは作業ディレクトリが汚れていると意味のある終了コードを提供しませんが、git diff--exit-code オプションを提供します。 diff ユーティリティに似ています。つまり、違いがあった場合は1、何も見つからなかった場合は0で終了します。

これを使用して、ステージングされていない変更を次のように確認できます。

git diff --exit-code

ステージングされたが、コミットされていない変更:

git diff --cached --exit-code

git diff--ignore-submodules への適切な引数を介してサブモジュールの追跡されていないファイルについてレポートできますが、残念ながら実際の作業ディレクトリで追跡されていないファイルについてレポートする方法はないようです。作業ディレクトリ内の追跡されていないファイルが関連している場合は、git status --porcelainがおそらく最善の策です。

160
Thomas Nyman

使用する:

git diff-index --quiet HEAD

戻りコードは、作業ディレクトリーの状態を反映しています(0 =クリーン、1 =ダーティー)。追跡されていないファイルは無視されます。

25
André van Herk

André's のマイナー拡張 answer

これは、結果を評価する1つの方法であり、以前に set -e を発行したスクリプトを使用している場合の落とし穴も回避します。

追跡されていないファイルは無視されます。

set +e
git diff-index --quiet HEAD

if [ $? == 1 ] ; then
  set -e
  GIT_MODS="dirty"
else
  set -e
  GIT_MODS="clean"
fi
1
orion elenzil

この種のテストをしました

TEST=$(git status --porcelain|wc -l)
if [ 0 -eq $TEST ]; then
   echo "No changes"
else
   echo "Changes"
fi 
1
PHZ.fi-Pharazon
#!/bin/bash
echo "First arg: $1"

cd $1

bob="Already up-to-date."
echo $bob

echo $(git pull) > s.txt
cat s.txt
if [ "$(cat s.txt)" == "$bob" ]
then
echo "up"
else
echo "not up"
fi
rm -rf s.txt
0
Robert A