Checking for a dirty index or untracked files with

2019-01-04 15:34发布

How can I check if I have any uncommitted changes in my git repository:

  1. Changes added to the index but not committed
  2. Untracked files

from a script?

git-status seems to always return zero with git version 1.6.4.2.

标签: git shell
12条回答
劫难
2楼-- · 2019-01-04 16:07

There may be a better combination of answers from this thread.. but this works for me... for your .gitconfig's [alias] section ...

          # git untracked && echo "There are untracked files!"
untracked = ! git status --porcelain 2>/dev/null | grep -q "^??"
          # git unclean && echo "There are uncommited changes!"
  unclean = ! ! git diff --quiet --ignore-submodules HEAD > /dev/null 2>&1
          # git dirty && echo "There are uncommitted changes OR untracked files!"
    dirty = ! git untracked || git unclean
查看更多
叼着烟拽天下
3楼-- · 2019-01-04 16:15

Great timing! I wrote a blog post about exactly this a few days ago, when I figured out how to add git status information to my prompt.

Here's what I do:

  1. For dirty status:

    # Returns "*" if the current git branch is dirty.
    function evil_git_dirty {
      [[ $(git diff --shortstat 2> /dev/null | tail -n1) != "" ]] && echo "*"
    }
    
  2. For untracked files (Notice the --porcelain flag to git status which gives you nice parse-able output):

    # Returns the number of untracked files
    
    function evil_git_num_untracked_files {
      expr `git status --porcelain 2>/dev/null| grep "^??" | wc -l` 
    }
    

Although git diff --shortstat is more convenient, you can also use git status --porcelain for getting dirty files:

# Get number of files added to the index (but uncommitted)
expr $(git status --porcelain 2>/dev/null| grep "^M" | wc -l)

# Get number of files that are uncommitted and not added
expr $(git status --porcelain 2>/dev/null| grep "^ M" | wc -l)

# Get number of total uncommited files
expr $(git status --porcelain 2>/dev/null| egrep "^(M| M)" | wc -l)

Note: The 2>/dev/null filters out the error messages so you can use these commands on non-git directories. (They'll simply return 0 for the file counts.)

Edit:

Here are the posts:

Adding Git Status Information to your Terminal Prompt

Improved Git-enabled Shell Prompt

查看更多
男人必须洒脱
4楼-- · 2019-01-04 16:17

Assuming you are on git 1.7.0 or later...

After reading all of the answers on this page and some experimenting, I think the method that hits the right combination of correctness and brevity is:

test -n "$(git status --porcelain)"

While git allows for a lot of nuance between what's tracked, ignore, untracked but unignored, and so on, I believe the typical use case is for automating build scripts, where you want to stop everything if your checkout isn't clean.

In that case, it makes sense to simulate what the programmer would do: type git status and look at the output. But we don't want to rely on specific words showing up, so we use the --porcelain mode introduced in 1.7.0; when enabled, a clean directory results in no output.

Then we use test -n to see if there was any output or not.

This command will return 1 if the working directory is clean and 0 if there are changes to be committed. You can change the -n to a -z if you want the opposite. This is useful for chaining this to a command in a script. For example:

test -z "$(git status --porcelain)" || red-alert "UNCLEAN UNCLEAN"

This effectively says "either there are no changes to be made or set off an alarm"; this one-liner might be preferable to an if-statement depending on the script you are writing.

查看更多
家丑人穷心不美
5楼-- · 2019-01-04 16:17

Why not encapsulate 'git status with a script which:

  • will analyze the output of that command
  • will return the appropriate error code based on what you need

That way, you can use that 'enhanced' status in your script.


As 0xfe mentions in his excellent answer, git status --porcelain is instrumental in any script-based solution

--porcelain

Give the output in a stable, easy-to-parse format for scripts.
Currently this is identical to --short output, but is guaranteed not to change in the future, making it safe for scripts.

查看更多
Animai°情兽
6楼-- · 2019-01-04 16:18

The simplest automatic test I use to detect dirty state = any changes including untracked files:

git add --all
git diff-index --exit-code HEAD

NOTE:

  • Without add --all diff-index does not notice untracked files.
  • Normally, I run git reset after testing error code to unstage everything back.
查看更多
干净又极端
7楼-- · 2019-01-04 16:23

An implementation from VonC's answer:

if [[ -n $(git status --porcelain) ]]; then echo "repo is dirty"; fi
查看更多
登录 后发表回答