현재 지점에서 커밋 할 것이 없는지 확인하는 방법은 무엇입니까?


172

목표는 쉘 명령으로 평가할 수있는 명확한 상태를 얻는 것입니다.

시도 git status했지만 커밋 할 항목이 있어도 항상 0을 반환합니다.

git status
echo $?  #this is always 0

아이디어가 있지만 오히려 나쁜 아이디어라고 생각합니다.

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

다른 방법?


다음 해결로 업데이트하십시오. Mark Longair의 게시물을 참조하십시오.

나는 이것을 시도했지만 문제를 일으킨다.

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

다음과 같은 오류가 발생합니다 [: ??: binary operator expected

이제 남자를보고 git diff를 시도하십시오.

==================== 내 희망에 대한 코드, 더 나은 답변 희망 =======================

#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

4
업데이트 된 섹션에서는 실제로 eckes대답 에서 제안한 것을 수행하지 않는 것 같습니다. 그가 말했듯이 따옴표 주위에 큰 따옴표를 넣어야합니다 $(git status --porcelain). 당신이 당신의 메시지에 느낌표를 넣어하려는 경우 또한, 당신은 작은 따옴표보다는 큰 따옴표를 사용해야합니다 - 즉 그것이 있어야 echo 'PLEASE COMMIT YOUR CHANGE FIRST!!!'대신
마크 Longair

4
Mark가 말했듯이 : 내가 말했듯 이을 큰 따옴표로 묶어야$(git status --porcelain) 합니다!
eckes

1
이 질문은 답변의 일부가 포함되지 않은 경우 훨씬 유용합니다.
준수

@ 9nix00 당신이 들었던 것을하고 위의 쉘 스크립트에서 버그를 수정하고 수정하십시오 : BUG : if [-z $ (some command)] FIX : if [-z "$ (some command)"]
MarcH

답변:


232

출력 git status --porcelain이 비어 있는지 테스트하는 대안 은 관심있는 각 조건을 개별적으로 테스트하는 것입니다. 예를 들어의 출력에 추적되지 않은 파일이있는 경우 항상 신경 쓰지 않을 수도 있습니다 git status.

예를 들어, 스테이지되지 않은 로컬 변경 사항이 있는지 확인하려면 다음의 리턴 코드를 볼 수 있습니다.

git diff --exit-code

준비되었지만 커밋되지 않은 변경 사항이 있는지 확인하려면 다음과 같은 반환 코드를 사용할 수 있습니다.

git diff --cached --exit-code

마지막으로, 작업 트리에 무시되지 않은 추적되지 않은 파일이 있는지 확인하려면 다음 명령의 출력이 비어 있는지 테스트 할 수 있습니다.

git ls-files --other --exclude-standard --directory

업데이트 : 아래에서 출력에서 ​​디렉토리를 제외하도록 해당 명령을 변경할 수 있는지 여부를 묻습니다. 를 추가하여 빈 디렉토리를 제외 할 수 --no-empty-directory있지만 해당 출력의 모든 디렉토리를 제외하려면 다음과 같이 출력을 필터링해야한다고 생각합니다.

git ls-files --other --exclude-standard --directory | egrep -v '/$'

-vegrep수단 만 출력 패턴과 일치하지 않는 선, 패턴은 A 라인으로 그 끝을 일치합니다 /.


이 팁을 배웠고 문제가 있습니다. 즉, git ls-files --other --exclude-standard --directory를 사용하여 목록 포함 디렉토리를 가져옵니다. 어쨌든이 디렉토리를 제외합니까?
9nix00

예, 이것은 내가 원하는 것입니다. 새 스크립트 코드에 대한 게시물을 업데이트합니다. 더 많은 코드 롤 ...하지만 더 나은 답변이 표시 되기는하지만 귀하의 제안이 더 논리적이라고 생각합니다.
9nix00

3
@albfan : git-diff 매뉴얼 페이지에 있습니다 . "diff (1)과 비슷한 코드로 프로그램을 종료하십시오. 즉, 차이가 있으면 1로 종료하고 0은 차이가 없음을 의미합니다."
Mark Longair

2007 년 이후 13da0fc0 이래로 쉘 스크립트에 유용하고 이전 버전의 git과 완벽하게 호환됩니다
albfan

10
--quiet(의미있는 --exit-code) 또한에만 종료 코드를 원하는 사람들을 위해 출력을 침묵.
phs

113

의 반환 값은 커밋해야 할 수정 사항이없는 경우 git status종료 코드를 알려줍니다 git status.

보다 컴퓨터에서 읽을 수있는 git status출력 버전을 원한다면

git status --porcelain

이에 git status대한 자세한 정보 는 설명을 참조하십시오 .

샘플 사용 (스크립트는 단순히 git status --porcelain구문 분석이 필요없는 출력을 제공 하는지 테스트 ) :

if [ -n "$(git status --porcelain)" ]; then
  echo "there are changes";
else
  echo "no changes";
fi

테스트 할 문자열 (예 :의 출력)을 인용해야합니다 git status --porcelain. 테스트 구성에 대한 자세한 힌트는 Advanced Bash 스크립팅 안내서 (섹션 문자열 비교 )를 참조하십시오 .


안녕, 당신은 좋은 제안을, 그것을 시도했지만, 스크립트에서, 문제가 발생했습니다, 만약 우리가 이것을 사용한다면 그것을 개선한다면, [-z $ (git status --porcelain)]; 오류가 발생합니다. [: ?? : 이진 연산자가 매뉴얼을 찾아서 [-z $ (git status --short)]; 이것은 작동 할 수 있습니다, 감사합니다!
9nix00

죄송합니다. 여전히 문제가 있습니다. 커밋이 깨끗할 때. 도자기를 사용하고 둘 다 확인하십시오. 그러나 커밋이 깨끗하지 않을 때. 오류가 발생합니다. [: ?? : 이항 연산자가 필요합니다. 아마도 base64를 사용하여 인코딩해야한다고 생각합니다. 나 해보자! base64 명령 도구 다운로드 .... lol
9nix00

커밋이 깨끗하지 않으면 문제가 발생합니다.
9nix00

1
훌륭한 솔루션. 견고성을 높이기 || echo no위해 git status기본적으로 실패 할 경우 작업 공간이 실수로 깨끗하게보고되지 않도록 명령 대체에 추가 할 수 있습니다. 또한 코드는 (추천 적으로) POSIX 호환이지만 bash 안내서에 링크하기 때문에 [[ ... ]]POSIX 호환 대신 bash를 사용하는 경우 [ ... ]명령 대체를 큰 따옴표로 묶을 필요는 없습니다. 해를 끼치 지 않습니다) : [[ -z $(git status --porcelain) ]].
mklement0

@eckes 며칠 전에 새로운 리포지토리를 시작하고 커밋을 추가했습니다. 커밋을 추가하고 커밋 할 내용과 내 사례에서 작동하지 않는 것을 확인하려고했습니다.
alinsoar

33

당신이 나와 같다면 다음과 같은 것이 있는지 알고 싶습니다.

1) 기존 파일 변경 2) 새로 추가 된 파일 3) 삭제 된 파일

특히 4) 추적되지 않은 파일에 대해 알고 싶지 않습니다.

이것은해야합니다 :

git status --untracked-files=no --porcelain

리포지토리가 깨끗하면 스크립트를 종료하는 bash 코드가 있습니다. 추적되지 않은 파일 옵션의 짧은 버전을 사용합니다.

[[ -z $(git status -uno --porcelain) ]] && echo "this branch is clean, no need to push..." && kill -SIGINT $$;

4
—untracked-files=no; +1 귀하의 테스트를로 단순화 할 수 있다고 생각합니다 [[ -z $(git status --untracked-files=no --porcelain) ]]. git status근본적인 뭔가 잘못하지 않는 한, 표준 오류에 기록 안 - 그리고 당신은 그 결과를보고 싶어요. 해당 이벤트에서보다 강력한 동작을 원하면 || echo no명령 대체에 추가 하여 정리 테스트가 여전히 실패합니다. 문자열 비교 / -z연산자는 여러 줄 문자열을 처리 할 수 ​​있습니다 tail.
mklement0

2
감사 @ mklement0, 심지어 조금 짧은 :[[ -z $(git status -u no --porcelain) ]]
moodboom

1
수정 : 내 짧은 버전은 실제로 "no"라는 파일의 상태를 확인합니다! Bzzt. 해야합니다 [[ -z $(git status -uno --porcelain) ]]
moodboom

2
후속 조치에 감사드립니다. 그것은 미묘한 버그입니다. 교훈은 옵션 인수가 있는 짧은 옵션에는 인수가 직접 추가되어야 하며 사이에 공백이 없어야 한다는 것 입니다. 수정 된 짧은 버전을 답변에 직접 통합하는 것은 어떻습니까?
mklement0

9

git status --porcelain간단한 grep테스트 수행 과 결합 할 수 있습니다 .

if git status --porcelain | grep .; then
    echo Repo is dirty
else
    echo Repo is clean
fi

나는 때때로 이것을 간단한 원 라이너로 사용합니다.

# pull from origin if our repo is clean
git status --porcelain | grep . || git pull origin master

-qsgrep 명령에 추가 하여 자동으로 설정하십시오.


2
우아함을 위해 +1; 경미한 경고 : git status치명적인 실패 (예 : 손상된 저장소)가 발생하면 테스트에서 실수로 깨끗한 작업 공간을 보고합니다 . 하나의 옵션을 사용 git status --porcelain 2>&1하는 것이지만 grep과 함께 사용하면 오류 메시지가 '먹 힙니다' -q. (즉 다루는 것은 우아함을 잃게 : (git status --porcelain || echo err) | grep -q .)
mklement0

또는 다음과 같이 작성할 수 있습니다.test -z "$(git status --porcelain)" || git pull origin master
VasiliNovikov

5

자식 소스 코드에는 다음을 포함하는 sh 스크립트가 있습니다.

require_clean_work_tree () {
    git rev-parse --verify HEAD >/dev/null || exit 1
    git update-index -q --ignore-submodules --refresh
    err=0

    if ! git diff-files --quiet --ignore-submodules
    then
        echo >&2 "Cannot $1: You have unstaged changes."
        err=1
    fi

    if ! git diff-index --cached --quiet --ignore-submodules HEAD --
    then
        if [ $err = 0 ]
        then
            echo >&2 "Cannot $1: Your index contains uncommitted changes."
        else
            echo >&2 "Additionally, your index contains uncommitted changes."
        fi
        err=1
    fi

    if [ $err = 1 ]
    then
        test -n "$2" && echo >&2 "$2"
        exit 1
    fi
}

이 코드 조각은 이전에 알려진 파일에 변경 사항이 있는지 확인 git diff-files하고 사용하는 방법을 보여줍니다 git diff-index. 그러나 새 알 수없는 파일이 작업 트리에 추가되었는지 확인할 수 없습니다.


이것은 새로운 파일을 제외하고는 잘 작동합니다. 이것을 추가 할 수 있습니다. 만약 ! git ls-files --other --exclude-standard --directory | grep -c -v '/ $'그런 다음 0을 종료하십시오. echo "새 파일을 커밋하십시오. 추가하지 않으려면 git-ignore 파일에 추가하십시오." 1 번 출구
9nix00

그냥 if [ -n "$(git ls-files --others --exclude-standard)" ]추가 배관 또는 greping없이 비 추적 파일을 검색하기에 충분합니다.
Arrowmaster

5

나는 이것에 대한 테스트를 할 것이다 :

git diff --quiet --cached

또는 이것은 명시 적입니다.

git diff --quiet --exit-code --cached

어디:

-종료 코드

diff (1)와 유사한 코드로 프로그램을 종료하십시오. 즉, 차이가 있으면 1로 종료하고 0은 차이가 없음을 의미합니다.

--조용한

프로그램의 모든 출력을 비활성화하십시오. --exit-code를 의미합니다


3

토론에 조금 늦었지만 git status --porcelain아무것도 반환하지 않으면 종료 코드 0이 필요 하고! = 0이면이를 시도하십시오.

exit $( git status --porcelain | wc -l )

이렇게하면 줄 수가 종료 코드가되어 255 줄 이상이있을 때 문제가 발생할 위험이 있습니다. 그래서

exit $( git status --porcelain | head -255 | wc -l )

그것을 설명 할 것이다;)


1
출력이 255 줄 이상인 경우 기본적으로 정의되지 않습니다.
트리플 리

잘 발견, 감사합니다!
Skeeve

2

나는 이것을 스크립트에서 사용하고있다 :

  • 모든 것이 깨끗하면 0
  • diff 또는 untracked 파일이있는 경우 1

    [-z "$ (git status --porcelain)"]


사용하는 if ! git diff --quiet; then것이 더 깨끗하고 성능이 좋습니다 (제 생각에). 즉, stdout이 아닌 종료 코드를 사용하십시오.
Alexander Mills

1
@AlexanderMills 는 캐시 된 변경 사항 git diff --quiet과 다르게 동작 git status --porcelain합니다.
마틴 폰 비티 치

0

예쁘지 않지만 작동합니다.

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

메시지가 로케일에 따라 달라지는 지 확실하지 않으므로 LANG=C앞에 배치하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.