Git에서 파일을 스테이지 해제하는 두 가지 방법이있는 이유는 무엇입니까?


1168

때때로 git은 때때로 git rm --cached파일을 언 스테이지하도록 제안 합니다 git reset HEAD file. 언제 사용해야합니까?

편집하다:

D:\code\gt2>git init
Initialized empty Git repository in D:/code/gt2/.git/
D:\code\gt2>touch a

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       a
nothing added to commit but untracked files present (use "git add" to track)

D:\code\gt2>git add a

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file:   a
#
D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a

D:\code\gt2>touch b

D:\code\gt2>git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       b
nothing added to commit but untracked files present (use "git add" to track)

D:\code\gt2>git add b

D:\code\gt2>git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   b
#

20
왜? git의 커맨드 라인 인터페이스가 유기적으로 진화했으며 일관된 일관성을 유지하기 위해 주요 구조 조정을 거치지 않았기 때문입니다. (당신이 동의하지 않을 경우, 노트는 어떻게 git rm둘 수있는 단계 삭제 도하고 unstage 추가 )
로마 Starkov

3
@romkyns : Git의 인터페이스가 유기적으로 진화했기 때문에 몇 가지 이상한 점이 있음에 동의하지만 제거는 분명히 추가의 역함수이므로 rm실행 취소하는 것이 논리적이지 add않습니까? 어떻게 rm행동해야 한다고 생각 하십니까?
Zaz

6
귀하의 질문에 대한 유일한 실제 답변 git initHEAD재설정 할 수 없는 직후 입니다.
Miles Rout


4
@Zaz, 나는 나의 의견을 줄 것이다. rm유닉스 컨텍스트에서 삭제를 의미합니다. 인덱스에 추가하는 것과 반대되는 것은 아닙니다. 파일을 제거하는 기능에 준비 상태를 변경하는 기능이 과부하되어 있어서는 안됩니다. 결합하기 편리한 구현 세부 사항이있는 경우 git에 사려 깊은 추상화 계층이 없음을 나타내므로 유용성이 명확 해집니다.
Joshua Goldberg

답변:


1892

git rm --cached <filePath> 파일을 스테이지 해제 하지 않고 실제로 는 이미 리포지토리 에서 파일 제거를 스테이징 하지만 (이미 커밋 된 것으로 가정) 파일을 작업 트리에 남겨 둡니다 (추적되지 않은 파일이 남음).

git reset -- <filePath>unstage 어떤 주어진 파일 (들)에 대한 변화를 개최.

즉, git rm --cached준비된 새 파일을 사용한 경우 이전에 커밋되지 않았으므로 기본적으로 준비를 해제 한 것처럼 보입니다.

git 2.24 업데이트이
새로운 버전의 git에서는 git restore --staged대신 사용할 수 있습니다 git reset. 자식 문서를 참조하십시오 .


70
나는 말을 git rm --cached파일 unstages하지만 작업 디렉토리에서 제거되지 않습니다.
Pierre de LESPINAY

4
더 이상 준비되지 않도록 추가 준비된 파일을 제거하려면 반드시 "추가 준비된 파일 준비 해제"라고 할 수 있습니까? 최종 결과는 단계적 삭제아니므로 오해가 완전히 이해할 수 있다고 생각합니다.
Roman Starkov

4
따라서 일반적으로 git rm --cached <filePath>repo에 포함 되어서는 안된다는 것을 인식 한 후 repo에서 일부 파일을 제거 하는 데 사용 합니다. 따라서이 명령을 실행하고 관련 파일을에 추가 할 가능성이 높습니다 gitignore. 제가 맞습니까?
Adrien Be

13
질문과 답변 모두에 대한 많은 투표로, 나는 분명히 우리에게 unstage명령을 하고 싶다고 말할 것 입니다 git.
milosmns 2014 년

4
"git status"는 지금 조언합니다 : "git restore --staged <file> ..."을 사용하여 스테이지를 해제하십시오
yucer

334

git rm --cached색인에서 파일을 제거하는 데 사용됩니다. 파일이 이미 저장소에있는 git rm --cached경우 색인에서 파일을 제거하고 작업 디렉토리에 그대로두고 커밋은 이제 저장소에서도 파일을 제거합니다. 기본적으로 커밋 후 파일의 버전을 해제하고 로컬 복사본을 유지했을 것입니다.

git reset HEAD file(기본적으로 --mixed플래그를 사용하는 ) 파일이 이미 리포지토리에있는 경우 파일의 인덱스 버전이 리포지토리 (HEAD)의 파일 버전으로 대체되어 수정 내용 을 효과적으로 준비 하지 않습니다.

버전이없는 파일의 경우 파일이 HEAD에 없기 때문에 전체 파일을 스테이지 해제합니다. 이러한 측면에서 git reset HEAD filegit rm --cached동일하지만합니다 (REPO 이미 파일의 경우에 설명 된대로) 그들은 동일하지 않습니다

문제는 Why are there 2 ways to unstage a file in git?-실제로 git에서 아무것도 할 수있는 유일한 방법은 없습니다. 그것은 그것의 아름다움입니다 :)


7
허용되는 답변과이 답변은 모두 훌륭하며 왜 하나를 다른 것보다 사용하는지 설명하십시오. 그러나 그들은 git이 두 가지 다른 방법을 제안 하는지에 대한 암시 적 질문에 직접 대답하지 않습니다 . OP 예제의 첫 번째 경우, git init이 방금 완료되었습니다. 이 경우 git은 저장소에 커밋이 없으므로 HEAD가 유효하지 않기 때문에 "git rm --cached"를 제안합니다. "git reset HEAD-a"는 다음을 생성합니다. "치명적인 : 'HEAD'를 유효한 참조로 해석하지 못했습니다."
sootsnoot

5
'git checkout'을 사용하면 파일에 대한 모든 변경 사항을 잃지 않을 것입니다. 오해가 없다면 파일을 준비 취소하는 것과 같은 것이 아닙니다.
John Deighan

there is never really only one way to do anything in git. that is the beauty of it흠 ... 왜? 분명한 방법이 하나만있을 때는 항상 좋습니다. 이것은 두뇌에 많은 시간과 기억을 절약합니다))
오토 Shavadze

128

아주 간단하게 :

  • git rm --cached <file> git이 파일 추적을 완전히 멈추게합니다 (일반과는 달리 파일 시스템에 남겨 둡니다 git rm)
  • git reset HEAD <file> 마지막 커밋 이후에 파일에 대한 수정 사항을 스테이지 해제합니다 (그러나 명령 이름이 제안하는 것과는 반대로 파일 시스템에서 되 돌리지 않습니다). 파일은 개정 관리 상태에 있습니다.

파일이 이전에 개정 제어 상태에 있지 않은 경우 (즉 git add, 처음에 방금 편집 한 파일의 준비를 취소하는 중 ) 두 명령은 동일한 효과를 가지므로 "두 가지 작업을 수행하는 두 가지 방법" ".

* 이전 에 저장소 에 커밋git rm --cached 된 파일 과 관련하여 @DrewT의 대답에주의해야 합니다. 이 질문의 맥락에서 파일이 추가되었지만 아직 커밋되지 않은 파일에 대해서는 걱정할 것이 없습니다.

** 나는 그 이름 때문에 git reset 명령을 사용하는 것이 당황스럽게 너무 무서웠습니다. 그러나 여전히 오늘날 나는 종종 실수하지 않도록 구문을 찾습니다. ( 업데이트 : 마침내 tldr 페이지 의 사용법git reset요약하는 데 시간이 걸렸 으므로 이제는 작동 방식에 대한 더 나은 정신 모델과 세부 사항을 잊었을 때에 대한 빠른 참조가 있습니다.)


그것은git rm <file> --cached
neonmate

8
나는 이 답변에 대한 2015 년 8 월 4 일 편집 이 전반적인 개선 이라고 생각하지 않습니다 . 기술적 인 정확성이 고정되어있을 수도 있지만 (평가할 자격이 없다고 생각하지만) "현재 추적되지 않은 파일 추적을 시작하도록 명령을 설정하지 않아야합니다. ","index "및"HEAD "와 같은 전문 용어를 사용합니다. 정확하게 초보자를 두려워하는 것들입니다. 다른 사람이 할 수 있으면보다 새로운 언어를 사용하도록 수정하십시오.
waldyrious

5
@waldyrious에 동의하십시오. 원래의 대답은 자식 교과서에서 나온 것이 아니지만 충분한 기술 수준으로 질문에 대답했습니다. 기술적 의도는 원래 의도를 모호하게 한 편집이 아니라 의견으로 명확 해져야합니다.
Simon Robb

편집 내용을 되돌 렸습니다. 커뮤니티가 (이전 의견과 투표에서) 충분한 답변이 있었으므로 편집이 답변의 명확성에 해를 끼쳤다 고 생각합니다.
waldyrious

참고 @DrewT는 rm --cached동일한 브랜치를 사용하는 사람은 사용 하거나 밀면 파일이 실제로 작업 트리에서 제거 된다고 경고합니다 .
Tom Hale

53

이 스레드는 약간 오래되었지만 여전히 직관적 인 문제가 아니기 때문에 약간의 데모를 추가하고 싶습니다.

me$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   to-be-added
#   modified:   to-be-modified
#   deleted:    to-be-removed
#

me$ git reset -q HEAD to-be-added

    # ok

me$ git reset -q HEAD to-be-modified

    # ok

me$ git reset -q HEAD to-be-removed

    # ok

# or alternatively:

me$ git reset -q HEAD to-be-added to-be-removed to-be-modified

    # ok

me$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   to-be-modified
#   deleted:    to-be-removed
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   to-be-added
no changes added to commit (use "git add" and/or "git commit -a")

git reset HEAD(없이 -q) 수정 된 파일에 대한 경고를 표시하고 종료 코드는 1이며 스크립트에서 오류로 간주됩니다.

편집 : 준비 해제 git checkout HEAD to-be-modified to-be-removed에도 작동하지만 작업 공간에서 변경 사항을 완전히 제거합니다.

git 2.23.0 업데이트 : 때때로 명령이 변경됩니다. 이제 git status말한다 :

  (use "git restore --staged <file>..." to unstage)

세 가지 유형의 변화 모두에 적용되는 ...


고마워, git reset이 파일의 수정 사항을 로컬로 남겼다는 첫 두 답변 (아마도 내 용어에 대한 무지)에서 완전히 명확하지는 않았습니다 (git checkout과 반대로).
soupdog

이전 버전은 새로운 버전의 파일을 삭제하기 때문에 당신은 버전에 대한 시작 부분에 경고를 넣어해야
루이스 마우의

@LuisMauricio 어떤 명령이 파일을 삭제합니까?
Daniel Alder는

36

실수로 커밋하지 않을 파일을 준비하고 변경 사항을 유지하려면 다음을 사용할 수 있습니다.

git stash
git stash pop

HEAD로 재설정하고 변경 사항을 다시 적용하여 커밋을 위해 개별 파일을 다시 준비 할 수 있습니다. 풀 요청에 대한 기능 분기를 작성하지 않은 경우에도 유용합니다 ( git stash ; git checkout -b <feature> ; git stash pop).


3
이것은 "git rm"을 입력하는 것보다 깨끗한 해결책이며 훨씬 덜 걱정입니다.
서브 이미지

1
git stashreflog에 항목을 작성하여 나중에 사용할 수 있기 때문에 다른 관련 이점이 있습니다. 의심스러운 경우 계속 진행하십시오 git stash(예 : git stash save -u "WIP notes to self"'-u'는 숨김 / 커밋되지 않은 파일을 숨김 커밋에 포함시키는 것입니다) ... 다음 git reflog show stash숨김 커밋 목록과 샤를 확인하십시오. 같은 별칭alias grs="git reflog show stash"
cweekly

15

이 두 명령은 문제의 파일이 이미 저장소에 있고 버전 제어하에있는 경우 (이전 커밋 된 등) 몇 가지 미묘한 차이가 있습니다.

  • git reset HEAD <file> 현재 커밋에서 파일을 스테이지 해제합니다.
  • git rm --cached <file>향후 커밋을 위해 파일의 스테이지를 해제합니다. 로 다시 추가 될 때까지 준비되지 않은 상태입니다 git add <file>.

그리고 한 가지 더 중요한 차이점이 있습니다.

  • 실행 git rm --cached <file>하고 분기를 원격으로 푸시하면 원격에서 분기를 당기는 사람은 로컬 작업 세트에서 파일이 추적되지 않게되지만 폴더에서 실제로 삭제되지 않는 경우에도 폴더에서 파일을 실제로 삭제합니다.

이 마지막 차이점은 팀의 각 개발자가 다른 구성 (예 : 다른 기본 URL, IP 또는 포트 설정)을 갖는 구성 파일을 포함하는 프로젝트에 중요하므로 git rm --cached <file>지점을 당기는 사람을 사용 하는 경우 수동으로 다시 삭제는 사람들이 원격에서 분기를 당기는 사람들에게만 영향을 미치기 때문에 구성을 만들거나 직접 보낼 수 있으며 IP 설정 등으로 다시 편집 할 수 있습니다.


10

하자 당신에게 말을 stage통해 전체 디렉토리를 git add <folder>,하지만 당신은 목록 (실행시 생성 즉 목록을 무대에서 파일을 제외 할 git status) 및 유지 당신이 뭔가 작업을하고 제외 된 파일 내에서 수정을 (그리고 커밋 준비가 아니지만, 당신은 당신의 일을 잃고 싶지 않습니다 ...). 간단하게 사용할 수 있습니다 :

git reset <file>

당신이 실행하면 git status, 당신은 그 어떤 파일 (들) 당신이 볼 수 reset있는 unstaged당신이 파일의 나머지 added아직 staged목록을.


10

1.

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file:   a

( "git rm --cached ..."를 사용하여 스테이지를 해제하십시오)

  • git는 포인터 시스템입니다

  • 아직 포인터를 변경하려는 커밋이 없습니다.

  • '포켓에서 파일을 꺼내는'유일한 방법 은 git에게 변경 사항을 감시하도록 지시 한 파일제거하는 것입니다.

2.

D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 a

자식 커밋 -ma

  • 커밋했습니다. ' 저장 됨 '

삼.

D:\code\gt2>git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   b
#

(무기 해제하려면 "git reset HEAD ..."를 사용하십시오)

  • 현재 코드에 커밋했습니다.
  • 이제 커밋에 대한 포인터를 재설정 할 수 있습니다 ' 마지막 저장으로 되돌리기 '

1
이것은 실제로 IMO 질문에 올바르게 대답하는 유일한 답변입니다. 실제로 'git rm --cached'와 'git reset HEAD'의 차이점은 아니지만 'git이 왜 일관성없이 두 옵션을 모두 제공합니까?'라는 질문에 대답합니다. 때를에 git init처음.
Miles Rout

5

아무도 git reflog ( http://git-scm.com/docs/git-reflog )를 언급 한 것에 놀랐습니다 .

# git reflog
<find the place before your staged anything>
# git reset HEAD@{1}

reflog는 리포지토리의 변경 사항을 추적 할뿐만 아니라 사용자 작업 (예 : 끌어 오기, 다른 지점으로의 체크 아웃 등)을 추적하고 해당 작업을 취소 할 수있는 자식 기록입니다. 따라서 잘못 준비된 파일을 준비하지 않고 파일을 준비하지 않은 지점으로 되돌릴 수 있습니다.

이것은 비슷합니다 git reset HEAD <file> 하지만 경우에 따라 더 세분화 될 수 있습니다.

죄송합니다-귀하의 질문에 실제로 대답하는 것이 아니라 내가 자주 사용하는 파일을 스테이지 해제하는 또 다른 방법을 가리키고 있습니다 (Ryan Stewart의 답변과 waldyrious의 답변과 매우 유사합니다.);) 도움이되기를 바랍니다.


5

그냥 사용하십시오 :

git reset HEAD <filename>

이렇게하면 파일의 스테이지가 해제되고 변경 한 내용이 유지되므로 원하는 경우 분기를 변경하고 git add해당 파일을 다른 분기로 변경할 수 있습니다 . 모든 변경 사항이 유지됩니다.


3

OS 가 버전 관리를 제거하지 않고 디렉토리에서 파일을 제거하는 것처럼 git rm --cached <file>일반에서 git rm <file>두 가지를 수행 하는 디렉토리에서 파일을 제거하지 않고 색인에서 파일 을 제거하는 것으로 보입니다 rm <file>.


1

버전 2.23 이상에서만

이러한 제안 대신 파일 git restore --staged <file>에 순서대로 사용할 수 있습니다 unstage.


옵션 --stage뿐만 아니라 모두 작동합니다 --staged.
dhana1310
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.