Question: The goal is to get an unambiguous status that can be evaluated in a shell command.

I tried `git status` but it always returns 0, even if there are items to commit.

```bash
git status
echo $?  #this is always 0

```

I have an idea but I think it is rather a bad idea.

```bash
if [ git status | grep -i -c "[a-z]"> 2 ];
then
 code for change...
else
  code for nothing change...
fi

```

any other way?

---

**update with following solve, see Mark Longair's post**

I tried this but it causes a problem.

```bash
if [ -z $(git status --porcelain) ];
then
    echo "IT IS CLEAN"
else
    echo "PLEASE COMMIT YOUR CHANGE FIRST!!!"
    echo git status
fi

```

I get the following error `[: ??: binary operator expected`

now, I am looking at the man and try the git diff.

===================code for my hope, and hope better answer======================

```bash
#if [ `git status | grep -i -c "$"` -lt 3 ];
# change to below code,although the above code is simple, but I think it is not strict logical
if [ `git diff --cached --exit-code HEAD^ > /dev/null && (git ls-files --other --exclude-standard --directory | grep -c -v '/$')` ];
then
        echo "PLEASE COMMIT YOUR CHANGE FIRST!!!"
    exit 1

else
    exit 0
fi

```

Answer: 
I've found all answers not useful when there are git-submodules involved.

Small investigation and I've found best possible solution, simple and reliable:

```sh
git commit --dry-run && echo "Things to commit" || echo "Clean repo"

```

You can add `-a` if any change should be taken into account not only index (detects that submodule should be updated too).
Not pretty, but works:

```
git status | grep -qF 'working directory clean' || echo "DIRTY"

```

Not sure whether the message is locale dependent, so maybe put a `LANG=C` in front.