¿Cómo determino programáticamente si hay cambios no confirmados?

En un Makefile, me gustaría realizar ciertas acciones si hay cambios no confirmados (en el tree de trabajo o en el índice). ¿Cuál es la forma más limpia y más eficiente de hacer eso? Un command que sale con un valor de retorno de cero en un caso y distinto de cero en el otro se adecuaría a mis propósitos.

Puedo ejecutar el git status y canalizar la salida a través de grep , pero siento que debe haber una mejor manera.

ACTUALIZACIÓN : el OP Daniel Stutzbach señala en los comentarios que este command simple git diff-index funcionó para él:

 git diff-index --quiet HEAD -- 

A continuación, puede ver " Cómo verificar si un command fue exitoso " si lo está usando en un script bash:

 git diff-index --quiet HEAD -- || echo "untracked"; // do something about it 

Nota: como comentó Anthony Sottile

git diff-index HEAD ... fallará en una twig que no tenga commits (como un repository recién inicializado).
Una solución que he encontrado es git diff-index $(git write-tree) ...


"Programáticamente" significa que nunca confíes en los commands de porcelana .
Siempre confíe en los commands de plomería .

Consulte también " Buscar un índice sucio o files sin seguimiento con Git " para ver las alternativas (como git status --porcelain )

Puede inspirarse en la nueva " function require_clean_work_tree " que se escribe mientras hablamos 😉 (principios de octubre de 2010)

 require_clean_work_tree () { # Update the index git update-index -q --ignore-submodules --refresh err=0 # Disallow unstaged changes in the working tree if ! git diff-files --quiet --ignore-submodules -- then echo >&2 "cannot $1: you have unstaged changes." git diff-files --name-status -r --ignore-submodules -- >&2 err=1 fi # Disallow uncommitted changes in the index if ! git diff-index --cached --quiet HEAD --ignore-submodules -- then echo >&2 "cannot $1: your index contains uncommitted changes." git diff-index --cached --name-status -r --ignore-submodules HEAD -- >&2 err=1 fi if [ $err = 1 ] then echo >&2 "Please commit or stash them." exit 1 fi } 

Mientras que las otras soluciones son muy completas, si quieres algo realmente rápido y sucio, testing algo como esto:

 [[ -z $(git status -s) ]] 

Solo comtesting si hay algún resultado en el resumen de estado.

git diff --exit-code devolverá distinto de cero si hay algún cambio; git diff --quiet es lo mismo sin salida. Como quiera verificar el tree de trabajo y el índice, use

 git diff --quiet && git diff --cached --quiet 

O

 git diff --quiet HEAD 

Cualquiera de los dos le dirá si hay cambios no confirmados que están organizados o no.

Como se señaló en otra respuesta, tan simple como dicho command es suficiente:

 git diff-index --quiet HEAD -- 

Si omite los dos últimos guiones, el command fallará si tiene un file llamado HEAD .

Ejemplo:

 #!/bin/bash set -e echo -n "Checking if there are uncommited changes... " trap 'echo -e "\033[0;31mFAILED\033[0m"' ERR git diff-index --quiet HEAD -- trap - ERR echo -e "\033[0;32mAll set!\033[0m" # continue as planned... 

Palabra de advertencia: este command ignora los files sin seguimiento.

Ampliando la respuesta de @ Nepthar:

 if [[ -z $(git status -s) ]] then echo "tree is clean" else echo "tree is dirty, please commit changes before running this" exit fi 

Con Python y GitPython:

 git.Repo(path).is_dirty(untracked_files=True) 

Devuelve True si el repository no está limpio

Esta es la mejor y más limpia manera.

 function git_dirty { text=$(git status) changed_text="Changes to be committed" untracked_files="Untracked files" dirty=false if [[ ${text} = *"$changed_text"* ]];then dirty=true fi if [[ ${text} = *"$untracked_files"* ]];then dirty=true fi echo $dirty }