git reset --mixed, --soft 및 --hard의 차이점은 무엇입니까?


740

커밋을 분할하고 사용할 재설정 옵션을 확실하지 않습니다.

나는 페이지를보고있다 영어로 "git reset"은 무엇을 하는가? 하지만 git index 또는 staging 영역이 무엇인지 이해하지 못해 설명이 도움이되지 않는다는 것을 깨달았습니다.

또한, 그 대답에서 (사용하고 수정하고 다시 커밋 할 때) 유스 케이스 --mixed--soft나에게도 동일하게 보입니다. 누군가 더 분해 할 수 있습니까? 나는 --mixed아마도 함께 갈 수있는 옵션 이라는 것을 알고 있지만 그 이유 를 알고 싶습니다 . 마지막으로 --hard어떻습니까?

누군가 3 가지 옵션을 선택하는 방법에 대한 워크 플로 예를 제공 할 수 있습니까?


1
다른 질문에 대한 답변을 편집하여 좀 더 명확하게 만들 것입니다.
Cascabel

@ mkarasek 답변은 꽤 좋지만 이 질문을 살펴 보는 데 관심이있을 수도 있습니다 .
brandizzi

3
자기에 대한 참고 : 일반적으로 , soft: stage everything, mixed: unstage everything, hard: ignore everything커밋까지 내가에서 재설정하고 있습니다.
user1164937


에 의해 또 다른 좋은 기사 David Zych명확한 설명과 함께 - davidzych.com/difference-between-git-reset-soft-mixed-and-hard
src3369

답변:


1489

리포지토리에서 파일을 수정하면 초기에 변경 사항이 취소됩니다. 커밋하려면을 사용하여 준비해야 git add합니다. 즉, 인덱스에 추가해야합니다 . 커밋 할 때 커밋 된 변경 내용은 인덱스에 추가 된 변경 사항입니다.

git reset현재 분기 ( HEAD)가 가리키는 위치는 최소한 변경됩니다 . 차이 --mixed--soft색인도 수정 여부입니다. 따라서 우리 master가이 일련의 커밋 으로 분기 하는 경우 :

- A - B - C (master)

HEAD를 가리키고 C색인이 일치 C합니다.

우리가 실행하는 경우 git reset --soft B, master(그래서 HEAD) 이제 가리키는 B하지만, 지수는 여전히의 변경이있다 C; git status단계별로 표시합니다. 따라서이 git commit시점에서 실행 하면와 동일한 변경 사항으로 새로운 커밋을 얻게됩니다 C.


자, 여기서부터 다시 시작하십시오.

- A - B - C (master)

이제하자 git reset --mixed B. (참고 : --mixed기본 옵션입니다). 다시 한번, master그리고 HEADB를 가리킨하지만,이 시간은 인덱스도 일치하도록 수정됩니다 B. git commit이 시점에서 실행 하면 인덱스가 일치하므로 아무 일도 일어나지 않습니다 HEAD. 작업 디렉토리에는 여전히 변경 사항이 있지만 색인에 없으므로 변경되지 않은 것으로 git status표시됩니다. 커밋하려면 git add평소처럼 커밋하십시오.


그리고 마지막으로, --hard같은 것입니다 --mixed(그것이 당신의 변화 HEAD즉 제외하고, 인덱스) --hard도 작업 디렉토리를 수정합니다. 에 C있고 실행 중이면에 git reset --hard B추가 된 변경 사항 C과 커밋되지 않은 변경 사항이 제거되고 작업 복사본의 파일이 commit과 일치 B합니다. 이 방법으로 변경 사항을 영구적으로 잃을 수 있으므로 git status하드 리셋을 수행 하기 전에 항상 실행 하여 작업 디렉토리가 깨끗하거나 커밋되지 않은 변경 사항을 잃어 버릴 수 있는지 확인해야합니다.


그리고 마지막으로 시각화 : 여기에 이미지 설명을 입력하십시오


45
즉, --soft 추가하고, --mix이 --hard 커밋 마지막으로 폐기되고, 커밋 및 추가 마지막으로 폐기되고, 커밋 마지막으로 폐기됩니다 당신이 자식 체크 아웃 HEAD와 동일 코드에 대한 변경
제임스 왕

11
@eventualEntropy reflog를 사용하여 커밋 된 변경 사항을 복구 할 수 있습니다 . 제거되지 않은 커밋되지 않은 변경 사항은 reset --hard영구적으로 사라집니다.
mkarasek

2
@ 로버트도; --mixed색인을 변경하지만 작업 디렉토리는 변경하지 않으므로 로컬 수정은 영향을받지 않습니다.
mkarasek

3
터미널에서 git을 컬러로 사용하는 시각적 인 사람들에게 도움이 될 수 있습니다. 1. 'git reset --soft A'그러면 B와 C의 내용이 초록색 (단계적)으로 나타납니다. (그들은 존재하지 않았던 것처럼) --hard를 재설정하지 3.'git '당신은 더 이상 어디서든 B와 C의 변화를 볼 수 빨간색 (unstaged)에서 B와 C의 물건을 참조
timhc22

2
@ user1933930 1과 3은을 남겨두고 - A - B - C′C '는 C와 동일한 변경 사항을 포함합니다 (서로 다른 타임 스탬프와 커밋 메시지가 있음). 2와 4는을 남겨두고 - A - D, 여기서 D는 B와 C의 결합 된 변화를 포함합니다.
mkarasek

213

가장 간단한 용어로 :

  • --soft: 커밋을 취소 하면 변경 사항이 준비됩니다 ( index ).
  • --mixed (기본값) : uncommit + unstage changes, 변경 사항은 작업 트리에 남아 있습니다.
  • --hard: 커밋 해제 + 스테이지 해제 + 변경 사항 삭제 , 남은 항목 없음.

8
답변은 기술 용어를 사용하여 가장 간결한 답변을 제공하기 때문에 최상의 답변
Trevor Boyd Smith

1
파일을 커밋하지 않고 (푸시되지 않은) 새로 생성 된 추적되지 않은 파일이 있으면 git reset --hard는 아무것도하지 않습니까? 추적되지 않은 파일을 준비 할 때만 작업 디렉토리에서 파일을 제거합니다.
Michael

1
@Nikhil이 답변이 어디에서 잘못된 지 설명해 주시겠습니까?
Ned Batchelder

1
@NedBatchelder 요점은 맞지 않습니다. 이러한 명령을 사용할 때 커밋 해제가 발생하지 않습니다.
Nikhil

1
@Nikhil 아마도 당신이 의미하는 바는 원래 커밋이 여전히 존재한다는 것입니다. 그러나 커밋이 더 이상 브랜치의 일부가되지 않도록 브랜치가 변경되었습니다. 우리는 그것에 동의합니까?
Ned Batchelder

69

이 복잡한 기능을 이해하기위한 첫 번째 단계로 단순화 된 설명입니다.

다음 각 명령 후에 프로젝트 상태를 시각화하려는 시각 학습자에게 도움이 될 수 있습니다.


색상을 켠 상태에서 터미널을 사용하는 사용자 (git config --global color.ui auto) :

git reset --soft A 그리고 당신은 B와 C의 물건을 녹색으로 볼 것입니다 (단계적이며 커밋 준비 완료)

git reset --mixed A(또는 git reset A) B와 C의 내용이 빨간색으로 표시됩니다 (미 준비 및 준비 (녹색) 및 커밋 준비 완료).

git reset --hard A 더 이상 어디에도 B와 C의 변화가 보이지 않을 것입니다.


또는 'Tower'또는 'SourceTree'와 같은 GUI 프로그램을 사용하는 사람들

git reset --soft A '준비된 파일'영역에서 B와 C의 내용을 커밋 할 준비가 된 것을 볼 수 있습니다.

git reset --mixed A(또는 git reset A) '스테이지되지 않은 파일'영역에서 B 및 C의 항목을 스테이지로 이동 한 다음 커밋 할 수 있습니다.

git reset --hard A 더 이상 어디에도 B와 C의 변화가 보이지 않을 것입니다.


1
이것은 최선의 오해의 소지가 있습니다. 답은 님 의 출력 git reset모양 만 변경하는 것처럼 읽습니다 git status.
jub0bs

3
나는 당신의 요점을 알지만, 시각적 학습자로서 3 개의 명령을 사용한 후 내 프로젝트가 어떻게 보이는지를 보았을 때 그들이하는 일을 이해하는 데 마침내 도움이 되었기 때문에 동의하지 않습니다!
timhc22

나는 사람들이 실제로 일어나고있는 일을 쉽게 할 수 있도록 도와주는 '모두를위한 깃'종류의 아이디어를 더 많이 보았다. 오해의 소지가 없도록 개선 될 수있는 방법에 대해 생각할 수 있습니까
timhc22

8
아니요,이 답변을 변경할 필요는 없습니다. 편리한 "치트 시트"를 제공합니다. 그것에 대해 생각하십시오 : soft = green, mixed = red, hard = nothing (없음)! 기억하기 쉽다! 그 색이 실제로 무엇을 의미하는지 이해하지 못하는 초보자에게는 git에 대해 너무 많이 알지 못하고 어쨌든 길에서 열심히 수업을 할 것입니다. BTW, 나는 이전 답변을 반박하기 위해이 답변을 찬성했습니다. 잘 했어, @unegma!
RayLuo

5
이것은 내가 다른 곳에서 읽을 때 내부 작업을 더 잘 이해하기 위해 훌륭한 보충 요약으로 사용되었습니다. 감사합니다!
spex

24

다른 모든 답변은 중대하다,하지만 난 최선이 세 가지 범주로 파일을 분해하여 그들을 이해하고 찾을 : unstaged, staged, commit:

  • --hard 이해하기 쉬워야합니다. 모든 것을 복원합니다.
  • --mixed (기본값) :
    1. unstaged파일 : 변경하지 마십시오
    2. staged 파일 : 이동 unstaged
    3. commit 파일 : 이동 unstaged
  • --soft:
    1. unstaged파일 : 변경하지 마십시오
    2. staged파일 : 변경하지 마십시오
    3. commit 파일 : 이동 staged

요약하자면:

  • --soft옵션은 모든 unstaged파일 ( 파일 제외 )을staging area
  • --mixed 옵션은 모든 것을 unstaged area

22

TortoiseGit 사용자를위한 기본 설명은 다음과 같습니다.

git reset --soft--mixed훼손되지 않은 파일을 둡니다.

git reset --hard실제로 재설정 한 커밋과 일치하도록 파일변경하십시오 .

TortoiseGit 에서 인덱스 의 개념은 GUI에 의해 숨겨져 있습니다. 파일을 수정할 때 git add준비 영역 / 인덱스에 변경 사항을 추가 하기 위해 실행할 필요는 없습니다 . 단순히 파일 이름을 변경하지 않는 기존 파일에 대한 수정을 다루는 경우 git reset --soft--mixed동일합니다! 새 파일을 추가하거나 파일 이름을 바꾼 경우에만 차이가 있습니다. 이 경우 git reset --mixed를 실행하면 버전 이 지정 되지 않은 파일 목록 에서 파일을 다시 추가해야합니다 .


이 답변은 소프트와 믹스의 차이를 다시 명확하게 알 수 없습니다. 그리고 그것을 진술함에있어서조차도 무시하고 있습니다. 이 다음 답변은 더 명확합니다. stackoverflow.com/questions/2530060/…
barlop

2
또한 같은 동작을 가지고 Github에서 데스크톱의 사용자로서,이 대답은 나에게 내가 대해 혼동 유지하는 이유의 일부 선명도 제공 --mixed--soft.
Chen Li Yong

20

이 경우 희망적으로 이것을 설명 할 수있는 비주얼을 좋아합니다.

git reset --[hard/mixed/soft] :

여기에 이미지 설명을 입력하십시오

따라서 각 효과마다 다른 범위

  1. Hard => WorkingDir + Index + HEAD
  2. 혼합 => 색인 + HEAD
  3. Soft => HEAD 만 해당 (인덱스 및 작업 디렉토리는 변경되지 않음).

15

후회의 세 가지 유형

많은 기존 답변이 실제 질문에 답변하지 않는 것 같습니다. 명령은 사용자 (사용자)가 원하는 것이 아니라 사용 사례에 관한 것이 아닙니다 . 그러나 그것이 OP가 요구 한 것입니다!

명령 을 내릴 때 후회 하는 것이 정확히 무엇인지에 관한 설명을 요약하면 도움이 될 수 있습니다 git reset. 우리가 이것을 가지고 있다고 가정 해 봅시다.

A - B - C - D <- HEAD

다음은 가능한 후회와 이에 대한 조치입니다.

1. 나는 B, C, D가 하나의 커밋 이 아니라는 것을 후회한다 .

git reset --soft A. A 하나의 커밋 이므로 모든 변경 사항을 즉시 커밋하고 미리 설정할 수 있습니다 .

2. 나는 B, C, D가 10 개의 커밋 이 아니라는 것을 후회 한다.

git reset --mixed A. 커밋이 사라지고 인덱스가 A로 돌아 왔지만 작업 영역은 여전히 ​​D 다음과 같이 보입니다. 이제는 완전히 다른 그룹으로 추가 및 커밋 할 수 있습니다.

3. 나는 이 지점에서 B, C, D가 일어난 것을 후회한다 ; 나는 A 다음에 지점을 가지기를 원했고 그들은 다른 지점에서 일어났다.

새 분기 otherbranch를 만든 다음 git reset --hard A. 현재 지점은 이제 A에서 끝나며 그 지점에서 otherbranch파생됩니다.

(물론 B, C 및 D가 전혀 발생하지 않기를 원하기 때문에 하드 리셋을 사용할 수도 있습니다.)


5

그들 사이의 차이점을 기억하도록 강요 할 필요는 없습니다. 실제로 어떻게 커밋했는지 생각해보십시오.

1. 변경하십시오.

2.git add.

3.gc -m "나는 뭔가를했다"

Soft, Mixed 및 Hard는 3에서 1까지 수행 한 작업을 포기할 수있는 방법입니다.

"gc -m"을 수행 한 적이없는 부드러운 "척".

"git add"를 본 적이없는 혼합 된 "pretend"

파일을 변경 한 적이없는 "보통"입니다.


4

이 세 가지 옵션에 들어가기 전에 세 가지를 이해해야합니다.

1) 역사 / 머리

2) 단계 / 인덱스

3) 작업 디렉토리

reset --soft : 히스토리 변경, HEAD 변경, 작업 디렉토리 변경되지 않음.

reset --mixed : 히스토리 변경, HEAD 변경, 작업 디렉토리가 스테이지되지 않은 데이터로 변경되었습니다.

reset --hard : 히스토리 변경, HEAD 변경, 작업 디렉토리가 손실 된 데이터로 변경되었습니다.

Git --soft를 사용하는 것이 항상 안전합니다. 복잡한 요구 사항에 다른 옵션을 사용해야합니다.


3

에 대한 오해가있는 많은 답변이 있습니다 git reset --soft. 일반적으로 (및 의도 된 용도로) 분리 된 헤드 상태에서 시작하여 git reset --soft변경 되는 특정 조건이 있지만 현재 체크 아웃 한 분기 참조를 이동합니다. 물론 지점을 체크 아웃하지 않으면이 작업을 수행 할 수 없습니다 (따라서 변경 되는 특정 조건 ). HEADgit reset --softHEAD

나는 이것이 최선의 방법이라고 생각했다 git reset. 당신은 단지 움직이지 않고 HEAD( 모든 것이 그렇게합니다 ), 또한 분기 ref를 움직입니다 ( 예 :)master . 이것은 새로운 커밋 을 만들고 이동하는 대신 이전 커밋으로 이동한다는 점을 제외하고 실행할 때 발생하는 작업과 비슷합니다 git commit(현재 분기가와 함께 HEAD이동) .

이 지점 인 reset변화, 지점 변경, 새 커밋이 아닌 다른 뭔가를하지 HEAD. 설명서 예제에서이를 확인할 수 있습니다.

커밋을 취소하여 주제 분기로 만듭니다.

          $ git branch topic/wip     (1)
          $ git reset --hard HEAD~3  (2)
          $ git checkout topic/wip   (3)
  1. 커밋을했지만 "마스터"지점에있는 것이 너무 이른 것을 깨달으십시오. 토픽 브랜치에서 계속 연마하고 싶으므로 현재 HEAD에서 "토픽 / 와이프"브랜치를 생성하십시오.
  2. 마스터 브랜치를 되 감아 서 세 가지 커밋을 제거하십시오.
  3. "주제 / 위핑"분기로 전환하고 계속 작동하십시오.

이 일련의 명령의 요점은 무엇입니까? 여기서 지점 을 이동하려고 master하므로 master체크 아웃 하는 동안 을 실행 git reset합니다.

여기서 가장 많이 투표 된 답변은 일반적으로 좋지만 오해로 여러 답변을 수정하기 위해 이것을 추가한다고 생각했습니다.

지점 변경

git reset --soft <ref>: 현재 체크 아웃 된 분기의 분기 포인터를 지정된 참조에서 커밋으로 재설정합니다 <ref>. 작업 디렉토리 및 색인의 파일은 변경되지 않습니다. 이 단계에서 커밋하면 git reset명령 전 위치로 바로 돌아갑니다 .

색인도 변경하십시오

git reset --mixed <ref>

또는 동등하게

git reset <ref>:

무엇을합니까 --soft수행 도하면 지정된 기준에 커밋 경기에 인덱스를 재설정합니다. git reset --soft HEAD(체크 아웃 된 브랜치를 체크 아웃 된 브랜치로 옮긴다 고 말했기 때문에) 아무것도하지 않지만 git reset --mixed HEAD, 또는 동등 git reset HEAD하게 인덱스를 마지막 커밋 상태로 재설정하기 때문에 일반적이고 유용한 명령입니다.

작업 디렉토리도 변경하십시오

git reset --hard <ref>: 무엇을하지 --mixed않습니다 도 작업 디렉토리를 덮어 씁니다. 이 명령과 유사한 git checkout <ref>것을 제외하고, (이 약 중요한 포인트입니다 reset) 모든 형태의 git reset분기 심판 이동 HEAD를 가리키고 있습니다.

"이러한 명령은 HEAD를 움직입니다"에 대한 참고 사항 :

명령이을 이동한다고 말하는 것은 유용하지 않습니다 HEAD. 커밋 기록에서 위치를 변경하는 모든 명령은을 이동합니다 HEAD. 즉,이 무엇 HEAD 이며 , 당신이 어디에 있든에 대한 포인터. HEAD당신입니다 , 그리고 당신이 할 때마다 이동합니다.


2
"브랜치 참조 이동": 좋은 지적. stackoverflow.com/a/5203843/6309 를 업데이트해야했습니다 .
VonC

1

3 가지 옵션이 어떤 맥락에서 사용되는지에 대한 간단한 답변 :

코드에서 현재 변경 사항유지 하지만 커밋 히스토리를 다시 작성하려면 다음을 수행하십시오.

  • soft: 모든 것을 한 번에 커밋하고 새로운 설명으로 새로운 커밋을 만들 수 있습니다 (git 또는 다른 GUI를 torotise 사용하는 경우 커밋에서 원하는 파일을 선택하고 여러 파일을 만들 수 있기 때문에 이것이 사용됩니다) 소스 트리에서 모든 파일은 커밋을 위해 준비됩니다.)
  • mixed: 커밋을하기 전에 인덱스에 개별 파일을 다시 추가해야합니다 (Sourcetree에서는 변경된 모든 파일이 스테이지 해제됩니다)

실제로 코드 의 변경 사항잃어 버리려면 :

  • hard: 당신은 역사를 다시 쓸뿐만 아니라 재설정 한 시점까지 모든 변경 사항을 잃습니다.

나는이 경우 부드럽고 혼합되지 않습니다. 커밋해야 할 경우 무엇을 되돌 렸습니까? 복귀를하거나 변경 사항을 다시 커밋 하시겠습니까 (원래 상태로 돌아 가기)
John Little

변경 사항을 다시 커밋합니다. 리버스 커밋은 없습니다.
Nickpick

1

git reset 명령의 다양한 옵션의 기본 차이점은 다음과 같습니다.

  • --soft : 선택한 커밋으로 HEAD 만 재설정합니다. 기본적으로 git checkout과 동일하게 작동하지만 분리 된 헤드 상태는 생성하지 않습니다.
  • --mixed (기본 옵션) : 히스토리에서 선택한 커밋으로 HEAD를 재설정하고 인덱스의 변경 사항을 취소합니다.
  • --hard : 히스토리에서 선택한 커밋으로 HEAD를 재설정하고 인덱스의 변경 사항을 취소하고 작업 디렉토리의 변경 사항을 취소합니다.

1

--soft: Git에게 HEAD를 다른 커밋으로 재설정하도록 지시하므로 인덱스와 작업 디렉토리는 변경되지 않습니다. 원래 HEAD와 커밋간에 변경된 모든 파일이 준비됩니다.

--mixed: 소프트와 마찬가지로 HEAD를 다른 커밋으로 재설정합니다. 또한 작업 디렉토리를 건드리지 않는 동안 인덱스가 일치하도록 인덱스를 재설정합니다. 모든 변경 사항은 작업 디렉토리에 유지되며 수정 된 것으로 표시되지만 준비되지는 않습니다.

--hard: 이것은 모든 것을 재설정합니다-HEAD를 다른 커밋으로 재설정하고 색인을 일치하도록 재설정하고 작업 디렉토리도 재설정합니다.

주요 차이점 --mixed--soft색인도 수정 여부입니다. 이에 대한 자세한 내용은 여기를 참조 하십시오 .


0

mkarasek의 답변은 우리가 말할 수있는 간단한 용어로 훌륭합니다 ...

  • git reset --soft: HEAD의도 한 커밋으로 설정하지만 마지막 커밋에서 변경 사항을 스테이징 유지
  • git reset --mixed: 그것은 동일 git reset --soft하지만 유일한 차이점은 마지막 커밋에서 변경 사항을 스테이지 해제한다는 것입니다
  • git reset --hard: HEAD지정한 커밋을 설정하고 커밋되지 않은 변경 사항을 포함하여 마지막 커밋의 모든 변경 사항을 재설정하십시오.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.