성공적인 "git cherry-pick"을 실행 취소하는 방법은 무엇입니까?


99

로컬 저장소에서 git cherry-pick SHA충돌이나 문제없이 방금 실행했습니다 . 그리고 나서 방금 한 일을하고 싶지 않다는 것을 깨달았습니다. 나는 이것을 아무데도 밀지 않았다.

이 체리 픽만 제거하려면 어떻게해야합니까?

이 작업을 수행하는 방법이 있는지 알고 싶습니다.

  • 다른 지역 변경이있을 때
  • 다른 로컬 변경 사항이 없을 때

가능하면 두 경우 모두에 대해 하나의 명령을 사용하는 것이 좋습니다.

답변:


134

체리 픽은 기본적으로 커밋이므로 실행 취소하려면 커밋을 실행 취소하면됩니다.

다른 지역 변경이있을 때

커밋을 재설정 한 후 다시 적용 할 수 있도록 현재 변경 사항을 숨 깁니다.

$ git stash
$ git reset --hard HEAD^
$ git stash pop  # or `git stash apply`, if you want to keep the changeset in the stash

다른 로컬 변경 사항이 없을 때

$ git reset --hard HEAD^

6
질문과 답변에 더해, 당신이 어떤 것을 선택하고 있는지 확실하지 않다면 언제든지 '체리 선택 SHA --no-commit'을 할 수 있으며 쉽게 확인할 수있는 커밋 만 변경되지 않을 것입니다. 이 부분 체리 따기에 유용합니다
kuskmen

2
windows : git reset --hard "HEAD ^"
slim

22

마지막 커밋을 취소하려면 간단히 git reset --hard HEAD~.

편집 :이 답변은 로컬 변경 사항 보존을 언급하지 않은 이전 버전의 질문에 적용되었습니다. Tim의 대답은 실제로 올바른 것입니다. 머리 위로 qwertzguy에게 감사드립니다.


2
즉 ^ HEAD 수 또는 HEAD ~ 1한다
안드레아스 Wederbrand

그들은 (그 문제에 대한, 그리고 HEAD ^ 1) 모두 HEAD ~ 동등한
데이비드 도이치

1
@DavidDeutsch 맞습니다 (최신 버전의 Git에서만 가능). 그러나 대문자 ( HEAD)가 더 강력합니다. head기존 참조의 이름이있는 불행한 경우를 고려하십시오 .
jub0bs

1
@Jubobs-좋은 지적; 내 대답에서 대소 문자를 변경했습니다.
David Deutsch

1
@qwertzguy, 좋은 캐치; 나는이 대답 :) 게시 후 타임 스탬프보고, 지역의 변경 사항에 대한 비트 질문 1 분 추가되었습니다
데이비드 도이치을

8

가능하면 하드 리셋을 피하십시오. 하드 리셋은 git에서 매우 적은 파괴적인 작업 중 하나입니다. 다행히도 재설정없이 체리 픽을 실행 취소하고 파괴적인 것을 피할 수 있습니다.

실행 취소하려는 체리 픽의 해시를 기록해 둡니다 ${bad_cherrypick}. 를 수행합니다 git revert ${bad_cherrypick}. 이제 작업 트리의 내용은 나쁜 체리 선택 이전과 같습니다.

를 반복 git cherry-pick ${wanted_commit}하고 새로운 체리 픽이 마음에 들면 git rebase -i ${bad_cherrypick}~1. 리베이스 중에 둘 다 삭제 ${bad_cherrypick}하고 해당 되돌리기를 수행하십시오.

당신이 작업하고있는 지점은 좋은 체리 픽만을 가질 것입니다. 재설정이 필요하지 않습니다!


6

git reflog 당신의 구조에 올 수 있습니다.

콘솔에 입력하면 SHA-1이 나타내는 git 내역 목록이 표시됩니다.

되돌리려는 SHA-1을 확인하기 만하면됩니다.


대답하기 전에 배경을 추가하고 이것이 무엇인지 설명해 봅시다 HEAD.

First of all what is HEAD?

HEAD현재 분기의 현재 커밋 (최신)에 대한 참조 일뿐입니다. 주어진 시간에
단 하나만있을 수 있습니다 HEAD. (제외 git worktree)

의 내용은 HEAD내부에 저장 .git/HEAD되며 현재 커밋의 40 바이트 SHA-1을 포함합니다.


detached HEAD

당신이 최신 커밋에 있지 않다면-이것은 HEAD역사상 이전 커밋을 가리키는 것을 의미합니다 detached HEAD.

여기에 이미지 설명 입력

명령 줄에서 이것은 HEAD현재 분기의 끝을 가리 키지 않기 때문에 분기 이름 대신 SHA-1처럼 보입니다.

여기에 이미지 설명 입력

여기에 이미지 설명 입력

분리 된 HEAD에서 복구하는 방법에 대한 몇 가지 옵션 :


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

원하는 커밋을 가리키는 새 분기를 체크 아웃합니다.
이 명령은 주어진 커밋으로 체크 아웃합니다.
이 시점에서 분기를 만들고이 시점부터 작업을 시작할 수 있습니다.

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

항상 사용할 수 있습니다 reflog.
git reflog업데이트 한 변경 사항을 표시 HEAD하고 원하는 reflog 항목을 체크 아웃하면 HEAD이 커밋으로 다시 설정됩니다 .

HEAD가 수정 될 때마다 새 항목이 reflog

git reflog
git checkout HEAD@{...}

이것은 당신이 원하는 커밋으로 돌아갈 것입니다.

여기에 이미지 설명 입력


git reset --hard <commit_id>

HEAD를 원하는 커밋으로 "이동"합니다.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • 참고 : ( Git 2.7 이후 )
    를 사용할 수도 있습니다 git rebase --no-autostash.

git revert <sha-1>

주어진 커밋 또는 커밋 범위를 "실행 취소"합니다.
reset 명령은 주어진 커밋에서 변경된 사항을 "실행 취소"합니다.
실행 취소 패치가있는 새 커밋이 커밋되고 원래 커밋도 기록에 남아 있습니다.

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>

이 스키마는 어떤 명령이 무엇을 수행하는지 보여줍니다.
당신이 볼 수 있듯이 reset && checkout을 수정합니다 HEAD.

여기에 이미지 설명 입력


아마도 추가git reset --hard
wyx

3

이 동일한 문제에 직면하여 성공적인 체리 픽 이후 커밋 및 / 또는 원격으로 푸시 한 경우 제거하고 싶다면 다음을 실행하여 체리 픽의 SHA를 찾을 수 있습니다.

git log --graph --decorate --oneline

그런 다음 (사용 후 :wq로그를 종료하기 위해) 사용하여 체리 픽을 제거 할 수 있습니다

git rebase -p --onto YOUR_SHA_HERE^ YOUR_SHA_HERE

여기서 YOUR_SHA_HERE체리 선택 커밋의 40 자 또는 약식 7 자 SHA와 같습니다.

처음에는 원격 리포지토리와 로컬 리포지토리가 다른 커밋 이력을 가지므로 변경 사항을 푸시 할 수 없습니다. 다음을 사용하여 로컬 커밋을 강제로 원격에있는 것을 대체 할 수 있습니다.

git push --force origin YOUR_REPO_NAME

( Seth Robertson 의이 솔루션을 적용했습니다 . "전체 커밋 제거"를 참조하십시오.)


1

하나의 명령이며 파괴적인 명령을 사용 하지 않습니다git reset .

GIT_SEQUENCE_EDITOR="sed -i 's/pick/d/'" git rebase -i HEAD~ --autostash

단순히 커밋을 삭제하고 로컬 변경 사항이 있더라도 체리 픽 이전 상태로 정확하게 되돌립니다.


단순히 커밋을 삭제합니다. 당신은 무엇을 생각 git reset HEAD^합니까?
Tim

@TimCastelijns git reset는 변경 사항을 삭제하지 않고 커밋 작업을 실행 취소합니다. git-scm.com/docs/git-reset 을 읽는 것이 좋습니다 . OP의 질문은 체리 픽을 취소하는 것입니다. 두 명령을 모두 시도하면 체리 픽 이전의 정확한 상태로 돌아갑니다. git reset체리 선택 변경 사항을 남기고 기존 로컬 변경 사항과 구별 할 수 없게되면 작업 트리가 엉망이됩니다.
qwertzguy 17:52에

예, 죄송합니다 reset --hard. 그것은 변경을 남기지 않습니다

1
@TimCastelijns git reset --hard는 관련없는 로컬 변경 사항도 제거하고 복구 할 수없는 방식으로 제거하는 파괴적인 명령입니다! 그래서 그것은 OP가 요구 한 것이 아닙니다.
qwertzguy

2
이 대답은 해당 sed명령이 수행하는 작업, 수동으로 수행하는 것과 다른 점, 수행하는 작업 을 설명하는 경우 훨씬 더 유용합니다 --autostash.
Chris Page
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.