Git 작업 디렉토리가 스크립트에서 깨끗한 지 확인


82

rsyncGit 작업 디렉토리를 대상으로 실행하는 스크립트가 있습니다. 작업 디렉토리가 깨끗한 지 (커밋을 변경하지 않았는지) 여부에 따라 스크립트가 다른 동작을 갖기를 원합니다. 예를 들어의 출력이 git status아래와 같으면 스크립트를 종료하고 싶습니다.

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

디렉토리가 깨끗하지 않으면 더 많은 명령을 실행하고 싶습니다.

쉘 스크립트에서 위와 같은 출력을 어떻게 확인할 수 있습니까?


마지막 명령에서 상태를 확인하면 여기에 도움이됩니까? ($?)
UVV

자세한 내용을 알려주시겠습니까? 스크립트의 주요 아이디어는 무엇입니까?
tachomi

@tachomi 나는 편집의 맥락 추가
brentwpeterson

당신은 단지 그것이 깨끗하지 않다고 가정하고 그것이 git reset --hard origin/branch당신이하고자하는 일이라면 ... 무언가를 컴파일 한 후에 정리하려고하는 것과 같은 것입니다.
SnakeDoc

1
@SnakeDoc 당신은 할 수 있지만, 역의 경우가 더 일반적이라고 가정합니다. 즉, 로컬 변경 사항을 다루지 않기 위해 작업 디렉토리가 더러운 경우 종료합니다. 두 경우 모두를 고려하면 미래 독자에게 질문이 더 유용 할 것입니다.
Thomas Nyman

답변:


133

git status출력은 기계가 아니라 사람이 읽을 수 있도록 만들어 졌으므로 출력을 구문 분석 하는 것은 좋지 않습니다. 향후 버전의 Git 또는 다르게 구성된 환경에서 출력이 동일하게 유지된다는 보장은 없습니다.

UVV 주석은 올바른 방향에 있지만 불행하게도 git status커밋되지 않은 변경 사항이있을 때 반환 코드는 변경되지 않습니다. 그것은, 그러나, 제공합니까 --porcelain의 출력됩니다 옵션, git status --porcelain스크립트 쉬운 구문 분석 형식으로 포맷하기를, 그리고 힘내 버전에서 안정적으로 유지와 관계없이 사용자 구성됩니다.

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 status을 출력하지 않고 실패 stdout, 우리는 수표를 구체화 할 수 있습니다 :

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아마도 가장 좋은 방법 일 것입니다.


4
git status --porcelain커밋 및 추적되지 않은 파일에 대해 변경되지 않은 변경 사항이 있어도 ughhh 는 코드 0으로 종료됩니다.
Alexander Mills

나는 git stash무언가를 할 것인지 미리 결정하는 데 관심이 있었다 (유용한 리턴 코드를 출력하지 않음). --ignore-submodules그렇지 않으면 무시 git status하는 하위 모듈 변경을 나타내는 것처럼 추가해야했습니다 git stash.
Devin Lane

1
@AlexanderMills : 나는 똑같이 관찰했다. 그러나 무엇 if [ -z을하고 있는지 확인했습니다 . 이는 -z다음 문자열이 비어있는 경우 if가로 평가됨을 의미 true합니다. 즉, git status --porcelain문자열 이 없으면 저장소가 깨끗합니다. 그렇지 않은 경우 수정 / 추가 / 제거 된 파일을 나열하며 더 이상 빈 문자열이 아닙니다. 그런 if다음로 평가됩니다 false.
Adeynack

19

사용하다:

git diff-index --quiet HEAD

리턴 코드는 작업 디렉토리의 상태를 반영합니다 (0 = 정리, 1 = 더티). 추적되지 않은 파일은 무시됩니다.


6
현재 디렉토리에 추적되지 않은 파일이 있으면 0을 반환합니다.
Adam Parkin

2
파일을 건드 리거나 덮어 썼지 만 색인과 동일하면 먼저 실행 git update-index --refresh해야 git diff-index HEAD합니다. 추가 정보 : stackoverflow.com/q/34807971/1407170
sffc 2

@AdamParkin 나는 git add .그것을 발행하기 전에 모든 파일을 추가 합니다. 일반적으로 스크립트에서 사용하는 방법입니다
ceztko

대단하다. 0이 아닌 리턴 / 종료 코드는 '오류'로 해석되며, -e설정된 스크립트에 있으면 '더티'인 경우 스크립트가 종료됩니다. set +e호출하기 전에하고 평가 한 후에 다시 git추가하면 이 문제를 피할 수 있습니다 . set -e$?
오리온 엘렌 질

1

André의 탁월한 답변에 대한 사소한 확장 .

이것은 결과를 평가하고 이전에 set -e를 실행 한 스크립트에있는 경우 함정을 피하는 한 가지 방법 입니다.

추적되지 않은 파일은 무시됩니다.

set +e
git diff-index --quiet HEAD

if [ $? == 1 ] ; then
  set -e
  GIT_MODS="dirty"
else
  set -e
  GIT_MODS="clean"
fi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.