"git commit"대신 "git commit --amend"을 실행 취소하는 방법


1294

실수로 이전 커밋을 수정했습니다. 커밋은 특정 파일에 대한 변경 기록을 유지하기 위해 분리되어 있어야합니다.

마지막 커밋을 취소하는 방법이 있습니까? 내가 같은 것을 git reset --hard HEAD^하면 첫 번째 커밋도 취소됩니다.

(아직 원격 디렉토리로 푸시하지 않았습니다)

답변:


2289

현재 HEAD커밋 과 동일한 세부 정보를 사용 하지만 부모는 이전 버전으로 새 커밋을 작성해야합니다 HEAD. git reset --soft다음 커밋이 현재 분기 헤드가있는 위치와 다른 커밋 위에서 발생하도록 분기 포인터를 이동합니다.

# Move the current head so that it's pointing at the old commit
# Leave the index intact for redoing the commit.
# HEAD@{1} gives you "the commit that HEAD pointed at before 
# it was moved to where it currently points at". Note that this is
# different from HEAD~1, which gives you "the commit that is the
# parent node of the commit that HEAD is currently pointing to."
git reset --soft HEAD@{1}

# commit the current tree using the commit details of the previous
# HEAD commit. (Note that HEAD@{1} is pointing somewhere different from the
# previous command. It's now pointing at the erroneously amended commit.)
git commit -C HEAD@{1}

33
매우 시원합니다, +1 나는 심지어 git reflog올바른 숫자를 찾기 위해 두 번째 마지막 수정보기로 그것을했다 {2}.
JJD

178
분명히, 첫 번째 명령은 "실행 취소"입니다. HEAD, 작업 디렉토리 (변경되지 않음) 및 이전의 색인 상태를 생성합니다 git commit --amend. 두 번째는 새로운 커밋에 대한 "재실행"입니다. 이것들은 git commit단지 어떤 것이 든 작동 하지 않습니다 --amend.
cdunn2001

60
따라서 새로운 커밋 메시지로 수정하지 않았다면 두 번째 부분은 규칙적 일 수 있습니다 git commit.
Matt Montag 3:19에

18
실행할 때 어떤 이유로, 나는 오류가 발생했습니다 git reset --soft HEAD@{1}: fatal: ambiguous argument 'HEAD@1': unknown revision or path not in the working tree. Use '--' to separate paths from revisions. 내가 대체하는 경우 HEAD@{1}에 표시된 해당 커밋 해시 git reflog(감사 JJD!),이 대답은 놀라 울 정도 일했다!
Tim Camber

20
쉘에 따라 @TimArnold이면 작은 따옴표 나 큰 따옴표를 넣어야 할 수도 있습니다 HEAD@{1}. echo HEAD@{1}예를 들어 tcsh에서 실행 하면 출력은 HEAD@1중괄호가 tcsh에 의해 해석 되었기 때문입니다. 작은 따옴표를 사용하면 중괄호가 유지됩니다.
Kelvin

136

ref-log를 사용하십시오 :

git branch fixing-things HEAD@{1}
git reset fixing-things

그런 다음 이전에 수정 한 모든 변경 사항을 작업 사본에만 적용해야하며 다시 커밋 할 수 있습니다.

이전 지수 유형의 전체 목록을 보려면 git reflog


7
이렇게하면 인덱스도 지워집니다. 여전히 유용하지만 단순한 "실행 취소"를 넘어 섭니다.
cdunn2001

3
HEAD@{1}와 사이에 차이점이 HEAD~1있습니까?
neaumusic

15
@neaumusic : 그렇습니다! 현재 커밋 의 부모HEAD~1정확히 동일 HEAD^하고 식별자 입니다. 반면에 HEAD가이 커밋 전에 지적한 커밋을 말합니다. 즉, 다른 브랜치를 체크 아웃하거나 커밋을 수정할 때 다른 커밋을 의미합니다. HEAD@{1}
knittl

@knittl 아 아, 내가 이것이 가능하다고 생각한 것도 당연합니다. 다시 한번 감사합니다. 좋은 정보
neaumusic

9
주먹 단계는 중복됩니다. 간단합니다 git reset HEAD@{1}.
dwelle

79

다음과 같이 수정 된 커밋을 찾으십시오.

git log --reflog

참고 : --patch명확성을 위해 커밋 본문을 보려면 추가 할 수 있습니다 . 와 동일합니다 git reflog.

그런 다음 HEAD를 이전 커밋으로 재설정하십시오.

git reset SHA1 --hard

참고 : 교체 실제 커밋 해시 SHA1을. 또한이 명령은 커밋되지 않은 변경 내용 을 잃어 버리므로 미리 변경하지 않아도 됩니다 . 또한, 사용 --soft의 최신 변경 사항을 유지하는 대신 다음을 커밋합니다.

그런 다음 필요한 다른 커밋을 체리 선택하십시오.

git cherry-pick SHA1

26
그렇게 git reset SHA1 --soft하면 최신 변경 사항을 유지 한 다음 커밋 할 수 있습니다.
pravj

24

매뉴얼 에서 언제든지 커밋을 분할 할 수 있습니다

  • git rebase -i commit ^을 사용하여 대화식 리베이스를 시작하십시오. 여기서 commit은 분할하려는 커밋입니다. 실제로, 해당 커밋이 포함되어있는 한 모든 커밋 범위가 수행됩니다.
  • "edit"조치로 분할하려는 커밋을 표시하십시오.
  • 커밋을 편집 할 때 git reset HEAD ^를 실행하십시오. 그 결과 HEAD가 1 개씩 되 감겨지고 인덱스가 적합합니다. 그러나 작업 트리는 동일하게 유지됩니다.
  • 이제 첫 번째 커밋에서 갖고 싶은 인덱스에 변경 사항을 추가하십시오. git add (대화식으로) 또는 git-gui (또는 둘 다)를 사용하여 그렇게 할 수 있습니다.
  • 현재 적절한 커밋 메시지로 현재 인덱스를 커밋하십시오.
  • 작업 트리가 깨끗해질 때까지 마지막 두 단계를 반복하십시오.
  • git rebase --continue로 리베이스를 계속하십시오.

26
너무 복잡합니다. git reflog당신이 필요한 전부
knittl

2
많은 단계가 가능하지만 각 단계는 복잡하지 않고 수행하기 쉽습니다. 이것은 나를 위해 일했고 내 투표를 얻습니다.
OzBandit

5
또한이 답변을 통해 실수로 '수정 한'변경 사항을 선택하여 git reset --soft HEAD @ {1} 접근 방식 (내 문제 BTW를 해결 한 방법)에 추가 값을 제공 할 수 있습니다.
Wiebe Tijsma

2
reflog 방법으로 변경 사항을 선택적으로 선택할 수도 있습니다. 그냥 이렇게 git reset대신 git reset --soft다음 수행합니다 git add --patch.
geekofalltrades 2016 년

1
이것은 여전히 ​​히스토리를 다시 작성하며 강제 푸시가 필요합니다. 상황에 따라 문제가 될 수도 있고 아닐 수도 있습니다.
Pajn

20

커밋 메시지가있는 편집기에서 여전히 커밋 메시지를 삭제하면 git commit --amend명령 이 중단된다는 점에 주목할 가치가 있습니다 .


이것은 하나입니다.
atilkan

저장했지만 ^^
엔지니어

14

git reflog수정 전후에 두 가지 커밋을 얻는 데 사용할 수 있습니다 .

그런 다음 git diff before_commit_id after_commit_id > d.diff수정 전과 수정 후 사이에 차이를 얻는 데 사용하십시오 .

다음으로 git checkout before_commit_id커밋 전에 돌아 가기

그리고 마지막으로 git apply d.diff실제 변경 사항을 적용하십시오.

그것은 내 문제를 해결합니다.


11

커밋을 원격으로 푸시 한 다음 해당 커밋의 변경 사항을 잘못 수정하면 문제가 해결됩니다. git log커밋 전에 SHA를 찾으려면 a 를 발행하십시오 . (이것은 remote의 이름이 origin이라고 가정합니다). 이제 해당 SHA를 사용하여이 명령을 발행하십시오.

git reset --soft <SHA BEFORE THE AMMEND>
#you now see all the changes in the commit and the amend undone

#save ALL the changes to the stash
git stash

git pull origin <your-branch> --ff-only
#if you issue git log you can see that you have the commit you didn't want to amend

git stash pop
#git status reveals only the changes you incorrectly amended

#now you can create your new unamended commit

3
이것은 더 일반적인 질문의 특별한 경우이지만 내 즉각적인 요구를 정확하게 다루었습니다.
dmckee --- 전 운영자 고양이 새끼

8

아래 작업을 취소하여 git commit —amend

  1. git reset --soft HEAD^
  2. git checkout files_from_old_commit_on_branch
  3. git pull origin your_branch_name

=====================================

이제 변경 사항이 이전과 같습니다. 그래서 당신은 실행 취소로 끝났습니다git commit —amend

이제 git push origin <your_branch_name>지점으로 푸시하기 위해 할 수 있습니다 .


3

거의 9 년이 늦었지만이 변형이 동일한 것을 달성한다고 언급하지는 않았습니다 (상위 답변과 비슷한 몇 가지 조합입니다 ( https://stackoverflow.com/a/1459264/4642530 ) .

지점에서 분리 된 모든 헤드 검색

git reflog show origin/BRANCH_NAME --date=relative

그런 다음 SHA1 해시를 찾으십시오.

이전 SHA1로 재설정

git reset --hard SHA1

그런 다음 다시 밀어 올리십시오.

git push origin BRANCH_NAME

끝난.

이전 커밋으로 되돌아갑니다.

(이전에 덮어 쓴 분리 커밋 헤드의 날짜 포함)


예,하지만 일반적으로 --soft변경 사항을 유지하기 위해 재설정 하고 싶습니다. 난 그냥 개별적으로 최선을 다하고 싶어
후안 멘데스에게

2
  1. 마지막 커밋으로 임시 지점에 체크 아웃

    git branch temp HEAD@{1}

  2. 마지막 커밋 재설정

    git reset temp

  3. 이제 모든 커밋 파일과 이전 커밋이 있습니다. 모든 파일의 상태를 확인하십시오.

    git status

  4. 커밋 파일을 git 단계에서 재설정하십시오.

    git reset myfile1.js (곧)

  5. 이 커밋을 다시 첨부하십시오

    git commit -C HEAD@{1}

  6. 새 커밋에 파일을 추가하고 커밋합니다.

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