git commit을 삭제할 수는 있지만 변경 사항을 유지할 수 있습니다


1055

개발 지점 중 하나에서 코드베이스를 약간 변경했습니다. 작업중인 기능을 완료하기 전에 현재 지점을 마스터로 전환하여 일부 기능을 시연해야했습니다. 그러나 "git checkout master"를 사용하면 개발 브랜치에서 변경 한 내용이 보존되어 마스터의 일부 기능이 손상됩니다. 그래서 내가 한 것은 커밋 메시지 "임시 커밋"으로 개발 브랜치에서 변경 사항을 커밋 한 다음 데모 마스터를 확인하는 것입니다.

데모로 작업을 마치고 개발 브랜치에서 작업하기 위해 변경 한 내용은 그대로 유지하면서 "임시 커밋"을 제거하고 싶습니다. 가능합니까?


65
다음 시간 :git stash
매트 볼

51
반드시 @MattBall이 아닙니다. 하지만 git stash좋은 도구이다 "작업 진행 중"던져 - 멀리 커밋도 매우 합법적 인 장치이다.
kostix

3
이것은 Github의 훌륭한 리소스 해협입니다 : Git으로 무엇을 취소 하는가
jasonleonhard

9
@MattBall @kostix 네, 스 태시는 전체 레포에 대한 하나의 글로벌 스택이라는 점에서 "장기"스 태싱에 특히 적합하지 않습니다. 지점의 변경 사항을 숨기고 다른 지점으로 이동하고 다른 작업을 수행 git stash하고 중간에 다른 지점에서 사용했을지 모른다는 걱정없이 며칠 후에 다시 방문하고 싶습니다 .
Alec

4
주목해야 할 점 stash은 완전히 로컬이며 리포지토리 또는 레크레이션 또는 하드웨어 오류 또는 손실로 인한 코드 손실이 발생하기 쉽다는 것입니다. IMO는 실제로 매우 단기적인 WIP에만 사용해야합니다. 휴가를 가기 전에 WIP 커밋을 좋아하십시오.
ϹοδεMεδιϲ

답변:


1617

다음과 같이 간단합니다.

git reset HEAD^

참고 : 일부 쉘 ^은 특수 문자 (예 : globbing이 활성화 된 일부 Windows 쉘 또는 ZSH )로 취급되므로 "HEAD^"이러한 경우 인용해야합니다 .

git reset없이 --hard또는 --soft이동 당신을 HEAD모든 파일을 변경하지 않고, 지정된 커밋을 가리 키도록. HEAD^현재 커밋의 (첫 번째) 부모 커밋을 말합니다.이 경우 커밋이 임시 커밋보다 먼저 커밋됩니다.

또 다른 옵션은 정상적으로 수행하고 다음 커밋 지점에서 대신 실행하는 것입니다.

git commit --amend [-m … etc]

대신 가장 최근의 커밋을 편집 하여 위와 동일한 효과를 갖습니다.

나쁜 커밋을 다른 사람이 가져 올 수있는 곳으로 이미 밀어 넣은 경우 (거의 모든 자식 답변과 마찬가지로) 문제가 발생할 수 있습니다. 그것을 피하십시오


47
이것은 가장 간단하지만, 이미 커밋을 리모컨에 푸시하고 다른 사람이 가져간 경우, 사과 이외의 일을하는 것이 매우 주저합니다.
atw13

11
@sicophrenic, 이 행사에서 "Reset Demystified" 를 읽을 수있는 기회를 놓치지 마십시오 .
kostix

33
나는 More?이것을 한 후에 얻는다 . 내가 프롬프트에서 무엇을 입력하든 내게 알려줍니다fatal: ambiguous argument 'HEADwhateverItypedIn': unknown revision or path not in the working tree.
DaAwesomeP

50
@DaAwesomeP ^는 특수 문자로 취급되는 쉘을 사용하는 것처럼 들립니다 . 참조를 인용하거나 인용 되지 않은 "HEAD^"대체 구문을 사용할 수 있습니다.HEAD~1
Gareth

8
나를 위해 일했지만 캐릭터를 탈출해야했습니다git reset HEAD\^
cevaris

188

이것을 처리하는 두 가지 방법이 있습니다. 상황에 따라 더 쉬운 방법

초기화

제거하려는 커밋이 마지막 커밋이고 추가 작업을 수행하지 않은 경우 간단히 사용할 수 있습니다. git-reset

git reset HEAD^

현재 HEAD 직전에 지점을 커밋으로 되돌립니다. 그러나 실제로 작업 트리의 파일은 변경되지 않습니다. 결과적으로 해당 커밋에 있었던 변경 사항은 수정 된 것으로 표시됩니다 ( '커밋 해제'명령처럼). 사실, 나는 그것을 할 별칭이 있습니다.

git config --global alias.uncommit 'reset HEAD^'

그런 다음 git uncommit나중에 하나의 커밋을 백업하는 데 사용할 수 있습니다 .

스 쿼싱

커밋 스 쿼싱은 둘 이상의 커밋을 하나로 결합하는 것을 의미합니다. 나는 이것을 아주 자주한다. 귀하의 경우 절반 완료 기능이 커밋 된 다음 해당 기능을 끝내고 적절한 영구 커밋 메시지로 다시 커밋합니다.

git rebase -i <ref>

나는 이것이 많은 커밋이 될 수 있음을 분명히하기 위해 위와 같이 말합니다. git log제거하려는 커밋을 실행 하고 찾아 SHA1을 복사하여 대신 사용하십시오 <ref>. 힘내 당신을 대화 형 rebase 모드로 이동합니다. 현재 상태와에 넣은 것 사이의 모든 커밋이 표시됩니다 <ref>. 따라서 <ref>10 커밋 전에는 10 개의 커밋을 모두 표시합니다.

각 커밋 앞에 단어가 pick있습니다. 를 사용해서 없애과에서 변경하려는 커밋 찾기 pickfixupsquash. 사용 fixup단순히 폐기하는 커밋 메시지 및 목록에서 즉각적인 이전에 변경 사항을 병합합니다. squash키워드는 같은 일을하지만, 당신이 새롭게 결합 된 커밋의 커밋 메시지를 편집 할 수 있습니다.

커밋은 편집기를 종료 할 때 목록에 표시되는 순서대로 다시 커밋됩니다. 따라서 임시 커밋을 한 다음 동일한 분기에서 다른 작업을 수행하고 나중에 커밋에서 기능을 완료 한 경우 rebase를 사용하면 커밋을 다시 정렬하고 스쿼시 할 수 있습니다.

경고:

리베이스는 히스토리 수정-DONT는 이미 다른 개발자와 공유 한 커밋에 대해이를 수행합니다.

스 태싱

git stash나중에이 문제를 피하려면 커밋되지 않은 작업을 임시로 저장 하는 데 사용 하는 것이 좋습니다.

git stash save 'some message'

이렇게하면 현재 변경 사항이 숨김 목록의 옆에 저장됩니다. 위는 stash 명령의 가장 명확한 버전으로, 주석 처리중인 내용을 설명 할 수 있습니다. 간단하게 실행할 수 git stash있지만 다른 메시지는 저장되지 않습니다.

당신은 숨김 목록을 찾아 볼 수 있습니다 ...

git stash list

이것은 당신의 모든 스 태쉬, 그들이 수행 한 브랜치, 메시지와 각 줄의 시작 부분, 그리고이 스 태쉬의 식별자를 보여줍니다. stash@{#}여기서 #은 스 태쉬 배열에서의 위치입니다.

스 태시를 복원하려면 (스 태쉬가 원래 작성된 위치에 관계없이 모든 브랜치에서 수행 할 수 있음) 간단히 실행하면됩니다.

git stash apply stash@{#}

다시, 스 태쉬 배열의 위치는 #입니다. 복원하려는 숨김이 0위치 에있는 경우, 즉 가장 최근 숨김 인 경우입니다. 그런 다음 숨김 위치를 지정하지 않고 명령을 실행할 수 있습니다 .git은 마지막 위치를 의미한다고 가정합니다 git stash apply.

예를 들어, 내가 잘못된 브랜치에서 작업하는 것을 발견하면 다음과 같은 명령을 실행할 수 있습니다.

git stash
git checkout <correct_branch>
git stash apply

귀하의 경우 지점을 조금 더 이동했지만 동일한 아이디어가 여전히 적용됩니다.

도움이 되었기를 바랍니다.


6
git config --global alias.uncommit reset HEAD^별칭은 재설정을 위해 커밋 해제합니다. 대신git config --global alias.uncommit 'reset HEAD^'
mernst

3
Windows 명령 프롬프트에서 사용하는 경우 ^ 대신 ^를 사용해야합니다.
Pramod BR

106

나는 당신이 이것을 찾고 있다고 생각합니다

git reset --soft HEAD~1

해당 커밋의 변경 사항을 준비 상태로 유지하면서 가장 최근의 커밋을 취소합니다.


7
감사. 이것은 나를 위해 일했습니다. git reset HEAD^Windows에서 전화 하면 "More?"라는 메시지가 나타납니다. -그 의미가 무엇이든
Tyron

12
@Tyron ^은 DOS에서 이스케이프 문자입니다. 새 줄과 쌍을 이루면 이전 명령에 대한 연속 프롬프트로 사용됩니다. 타이핑 git reset HEAD^^은 Windows에서 작동합니다.
trk

40

예, 변경 사항을 삭제하지 않고 커밋을 삭제할 수 있습니다 : git reset @ ~


7
이것은 정말로 내가 원하는 것이며 내 의견으로는 받아 들여질 것입니다. 감사합니다!
Carlos Liu

2
흥미롭고 간결한 구문, 나는 전에 보지 못했었다. 어떻게에서 그 차이가 git reset --soft나는 git reset --keep?
user776686

18

당신도 찾고있는 git reset HEAD^ --softgit reset HEAD^ --mixed.

문서에 명시된대로 reset 명령에는 3 가지 모드가 있습니다 .

git reset HEAD^ --soft

를 실행 취소합니다 git commit. 작업 트리 (프로젝트 폴더) + 색인 (-캐시)에 변경 사항이 여전히 존재합니다.

git reset HEAD^ --mixed

git commit+를 취소 git add합니다. 작업 트리에 변경 사항이 여전히 존재합니다

git reset HEAD^ --hard

코드베이스를 변경하지 않은 것처럼. 작업 트리에서 변경 사항이 사라졌습니다.


9

zsh를 사용하는 경우 다음을 사용해야합니다.

git reset --soft HEAD\^

여기에 설명 : https://github.com/robbyrussell/oh-my-zsh/issues/449

URL이 죽은 경우 중요한 부분은 다음과 같습니다.

명령에서 ^를 피하십시오

대신 HEAD ~를 사용할 수 있으므로 매번 도망 칠 필요가 없습니다.


15
나는이 명령을 기억하지이 구글과 내 자신의 답변 하하 찾아야 결코
그렉 Hilston을

2
git reset HEAD^나를 위해 zsh에서 일하고 있으며 수정되었을 수 있습니다.
벤 콜리 맨 ​​슬리

@BenKolyaMansley 어떤 버전의 zsh를 실행하고 있습니까?
Greg Hilston

내가 사용하는zsh 5.3 (x86_64-apple-darwin18.0)
Ben Kolya Mansley

7

제 경우에는 이미 레포로 밀었습니다. 아야!

다음을 수행하여 로컬 파일의 변경 사항을 유지하면서 특정 커밋을 되돌릴 수 있습니다.

git revert -n <sha>

이 방법으로 나는 필요한 변경 사항을 유지하고 이미 푸시 된 커밋을 취소 할 수있었습니다.


내 경우에는 이미 원격 저장소로 푸시 한 것을 되돌려 야했습니다. 더 많은 아야! 가장 좋은 방법은에 있었다 git revert bad-commit-sha다음, git revert -n revert-commit-just-created-sha다음, 거기에서 수리. 반쯤 가졌어요 감사!
TinkerTenorSoftwareGuy

이것은 반대의 행동을하는 것 같습니다. 선택한 커밋에서 수행 된 변경 사항의 되돌리기에 해당하는 새로운 변경 사항을 만듭니다. 이러한 새로운 변경 사항을 커밋하려는 경우 실제로 유지하려는 작업이 취소됩니다.
svaens

3

git 2.9 (정확히 2.9.2.windows.1)를 사용하면 git reset HEAD^더 많은 것을 요구합니다. 여기에 무엇을 입력해야할지 모르겠습니다. 아래 스크린 샷을 참조하십시오

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

git reset HEAD~#numberOfCommits변경 사항을 그대로 유지하여 재설정하려는 로컬 커밋 수를 선택할 수있는 다른 솔루션 을 찾았습니다 . 따라서 제한된 수의 로컬 커밋뿐만 아니라 모든 로컬 커밋을 버릴 수 있습니다.

아래의 스크린 샷을 참조하십시오 git reset HEAD~1: 여기에 이미지 설명을 입력하십시오

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


^ 문자를 이스케이프해야 할 수도 있습니다. git reset "HEAD ^"또는 git reset HEAD \ ^를 시도하십시오.
Mark Fisher

이것에 더하여, git reset HEAD ^^는 하나의 ^으로 작동하며 ^는 새로운 행으로 취급됩니다.
John Oss

2

한 가지 더 방법.

임시 커밋 위에 커밋을 추가하고 다음을 수행하십시오.

git rebase -i

두 커밋을 하나로 병합하려면 (명령은 명시적인 지침으로 텍스트 파일을 열고 편집합니다).


2
기술적으로는 정확하지만 단순한 것만 큼 우아하지는 않습니다 git reset HEAD^. 힘내 rebase는 여기에 오류의 여지가 많이 있습니다.
TheBuzzSaw
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.