2009-03-13 3 views
44

스크립트에서 변경을 수행했습니다. 그런 다음 몇 가지 다른 사항을 변경하고 원격 저장소 등으로 밀어 넣었습니다.git에서 변경 실행 취소 (기록 다시 쓰기가 아님)

내가 처음 언급 한 바보가 어리 석고 그것을 원상태로 돌리고 싶다는 것을 깨달았습니다. 수동으로 diff를 복사/붙여 넣지 않고 커밋을 취소 할 수 있습니까? 나는 두 개의 파일 a.pyb.py 있습니다 : 예를 들어

Commit 1: 
I delete a function in a.py 

Commit 2: 
I change a few lines in b.py 

Commit 3: 
I change the docstring in a.py 

내가 그 함수의 삭제를 취소하고, "4 커밋"로 표시 할 수 있습니다 (오히려 삭제에 비해 커밋 1)

+13

오이, "실현 된", "실현되지 않은"! (저는 미국인이 아닙니다 ..) – dbr

+3

야드와 발을 사용하여 측정하는 사람들이 철자를 수정했습니다 ... 하하 – FaddishWorm

답변

57

예, git 되돌리기을 사용할 수 있습니다. 자세한 내용은 git manual section on this을 참조하십시오.

요점은 당신이 말할 수 있다는 것입니다 :

4f4k2a가의 ID입니다
git revert 4f4k2a 

당신이 취소하고 싶습니다 투입하고, 그것을 취소하려고합니다.

+0

아하, 물론 고마워요! – dbr

+0

동의어! 그것은 커밋 1 객체를 삭제합니다 – aatifh

+0

흠, revert'd 커밋을 지우지 않는 것 같습니다 .. – dbr

31

그냥 코멘트 :

git revert aCommit 

는 ("모든 파일 커밋의 부분"에서 같이) 모든 커밋 되돌릴 않습니다,
이 역방향 패치를 계산은 머리에 적용 그리고 커밋.

그래서 두 가지 문제가 여기 (첫 번째는 쉽게 해결된다) :

  • 당신이 -no-commit 옵션을 추가 할 수 있도록 항상 커밋 않습니다 "git revert --no-commit aCommit을"이상을 되 돌리는 경우에 유용합니다 하나의 커밋이 인덱스에 연속적으로 적용됩니다.
  • 특정 파일에 적용되지 않습니다 (되돌릴 수없는 1000 개의 변경 사항이있는 커밋의 일부인 경우)? 그들은 다른 커밋, 당신은 (즉, 당신은하지만이 경우에는 꼭 필요한 것이 아니다), 특히 git checkout <commit> <filename> 구문을 git-checkout을 볼 수 있었다 당신이 특정 파일을 추출 할 경우이 들어
    ,

Easy Git (Elijah Newren)은 Git Mailing list에 "완전한 복귀"를 시도했습니다. 그러나 많은 성공을 거두지 못합니다.

사람들은 종종 "변경 사항 되돌리기"를 원합니다.이제

이있을 수 있습니다 : 마지막 커밋 이후 모든 변경 될 수
  • (32) 사이

    • 변화와 전 29 개 개정,
    • 는 변경 될 수 있습니다 3 주 전에 커밋 이후 , 또는
    • 하나의 특정 커밋 일 수 있습니다. 사용자가 단지 특정 파일에 등이 복귀 부분 집합 할 수 있습니다
    • ,
  • (eg revertdocumented here이지만, 나는 그것이 예를 들어 현재 배포판의 일부 생각입니다 확실하지 않다)

    하지만 모두 "되돌리기 변경 사항"으로 끝납니다.

    eg revert --since HEAD~3 # Undo all changes since HEAD~3 
    eg revert --in HEAD~8  # much like git revert HEAD~8, but nocommit by default 
    eg revert --since HEAD foo.py # Undo changes to foo.py since last commit 
    eg revert foo.py    # Same as above 
    eg revert --in trial~7 bar.c baz. # Undo changes made in trial~7 to bar.[ch] 
    

    이러한 종류의 서로 다른 명령이있을 필요해야 "데이터를 되 돌리는"정말 그렇게 다른, 또는 이러한 작업의 일부는 간단한 되돌리기 명령에 의해 지원되지 않을 것을?
    대부분의 사용자는 대부분 "eg revert FILE1 FILE2..." 양식을 사용하지만 추가 기능 지원에는 별다른 영향을주지 않습니다.

    또한 핵심 git이 이러한 동작을 채택하지 못하도록하는 근본적인 것이 있습니까?

    엘리야

    참고 : 일반화 된 revert 명령에 대한 이해가되지 않는 기본적으로 커밋하고, "git revert REVISION는"합니다 (이대로 더 플래그를 추가하도록 사용자에게 알려주) 지침과 함께 밖으로 오류 것이다.


    당신이 가지고 최선을 다하고 50에서 20 개 파일이 오래된 X가 자리를 차지하지 말았어야 변화를 도입 커밋 실현 말할 수 있습니다.
    작은 배관이 순서에 있습니다.
    는 당신이 필요하면 되돌릴 에 필요한 모든 특정 파일을 나열하는 방법입니다
    각각에 대해, 다음,
    및 ( "이후의 모든 변경 내용을 유지하면서 X 커밋의 변경을 취소하려면"같이)

    다음은 계속 유지하고자하는 모든 후속 변경 사항을 삭제하지 않고 손실 된 기능을 복구하는 것입니다.
    그 기술은 언젠가는 "부정적인 합병"이라고 불립니다.

    git merge-file <current-file> <base-file> <other-file>means이후 :
    <current-file><base-file><other-file>까지 이어질 모든 변경 사항을 통합, 당신은 모든 변경 사항을 적용 할 말함으로써 삭제 기능을 복원 할 수 있습니다)

      .
    • from : X (함수가 삭제 된 곳)
    • to : X^(이전 커밋 먼저 현재 파일에 아무것도하지 않고 변경 사항을 검토 할 수 있습니다 '-p' 인수 : 함수가 아직 거기 X)

    주 전에. 확실하면 해당 옵션을 제거하십시오.

    다음 git merge-filenot that simple입니다 : 당신은 같은 파일의 이전 버전을 참조 할 수 없습니다.
    (당신은 이상 가지고 것이다 좌절 메시지를 통해 : error: Could not stat X)
    당신이에 :

    git cat-file blob a.py > tmp/ori # current file before any modification 
    git cat-file blob HEAD~2:a.py > tmp/X # file with the function deleted 
    git cat-file blob HEAD~3:a.py > tmp/F # file with the function which was still there 
    
    git merge-file a.py tmp/X tmp/F # basically a RCS-style merge 
               # note the inversed commit order: X as based, then F 
               # that is why is is a "negative merge" 
    diff -u a.py tmp/ori # eyeball the merge result 
    git add a.py 
    git commit -m "function restored" # and any other changes made from X are preserved! 
    

    이 이전 커밋 ... 일부 내에서 많은 수의 파일에 대해 수행 할 경우

    +0

    대시가 필요 없다고 생각한다.'git checkout ' – Paul

    5

    VonC가 지적했듯이, 나는 지점 (마스터 또는 트렁크 또는 무엇이든) 다음 checkout 내가하고 싶은 파일의 버전을 checkout 것, 커밋 내에서 하나의 파일에 변경 사항을 되돌리려면), 스크립트는 순서에 되돌리고 t

    $ git checkout trunk 
    $ git checkout 4f4k2a^ a.py 
    $ git add a.py 
    $ git diff    #verify I'm only changing what I want; edit as needed 
    $ git commit -m 'recover function deleted from a.py in 4f4k2a' 
    

    아마 직접이 작업을 수행 할 것입니다 배관 명령있다,하지만 난 그것을 알고 있다면 나는 그것을 사용하지 것이다 : 커밋 새로 reat. Git을 신뢰하지 않는다고는 할 수 없지만, 나는 자신을 믿지 않는다. 나는 그 커밋과 그 이후로 그 파일에서 무엇이 바뀌 었는지 알지 못한다고 나는 믿지 않을 것이다. 일단 내가 본다면 diff을 편집하여 새로운 커밋을 만드는 것이 더 쉽습니다. 아마도 개인 스타일 일 것입니다.

    +1

    두 개의 댓글 : 1/if the functions 4f4k2a a.py에서 삭제되었으므로 * a * * 커밋에서 a.py를 체크 아웃해서는 안됩니까? (4f4k2a에서와 같이 * 4f4k2a 앞에 *?) 2/그 것이 완전히 현재 버전의 a.py를 지우지 않겠습니까? 후속 변경 사항을 유지하려면 어떻게해야합니까? – VonC

    +0

    차라리 git-merge-file을 사용하여 "음수 병합"을 만들 것입니다. 완성 된 답변보기 – VonC

    +0

    1) 예. 다른 오타를 고쳐 주셔서 감사합니다. 2) 예 - 그렇기 때문에 diff 파일을 봐야합니다. 실제로 3-way 병합 모드에서 해킹 된 diffmerge를 사용합니다.이 모드는 작업하는 데 익숙한 유용한 diff를 보여 주지만 git diff는 사용할 수 있습니다. 요점은 : 코드를 살펴 본다면 확신 할 수 있습니다. – Paul

    1

    this git revert question을 살펴보십시오. 가장 최근의 커밋을 포함하여 연속적인 순서가 아니라면 이전의 커밋을 되 돌리는데 문제가있는 것 같습니다.

    +0

    이것은 유용했기 때문에 Upvoting 이었지만 실제로 대답이 아닌 주석이어야합니다. – tripleee