git revert <commit_hash>
혼자서는 작동하지 않습니다. -m
지정해야하며 꽤 혼란 스럽습니다.
아무도 전에 이것을 경험 했습니까?
git
하는 git-flow
-ish 워크 플로 와 일치하지 않는 예입니다 . 물론develop
체크 아웃 한 경우 오랫동안 공유 dev 분기가 아닌 버그가 발생한 2 커밋 기능 분기를 되돌리려 고합니다. 말도 안되는 느낌이 든다 . -m 1
git revert <commit_hash>
혼자서는 작동하지 않습니다. -m
지정해야하며 꽤 혼란 스럽습니다.
아무도 전에 이것을 경험 했습니까?
git
하는 git-flow
-ish 워크 플로 와 일치하지 않는 예입니다 . 물론develop
체크 아웃 한 경우 오랫동안 공유 dev 분기가 아닌 버그가 발생한 2 커밋 기능 분기를 되돌리려 고합니다. 말도 안되는 느낌이 든다 . -m 1
답변:
이 -m
옵션은 부모 번호를 지정합니다 . 이는 병합 커밋이 둘 이상의 부모를 가지고 있기 때문에 Git은 어떤 부모가 메인 라인인지, 어떤 부모가 병합을 해제하려는 브랜치인지 자동으로 알지 못하기 때문입니다.
의 출력에서 병합 커밋을 보면 git log
다음으로 시작하는 행에 부모가 나열됩니다 Merge
.
commit 8f937c683929b08379097828c8a04350b9b8e183
Merge: 8989ee0 7c6b236
Author: Ben James <ben@example.com>
Date: Wed Aug 17 22:49:41 2011 +0100
Merge branch 'gh-pages'
Conflicts:
README
이 상황에서 git revert 8f937c6 -m 1
이 있다는 당신에게 나무를 얻을 것이다 8989ee0
, 그리고 git revert -m 2
이 있다는 트리를 복원합니다 7c6b236
.
부모 ID를 더 잘 이해하려면 다음을 실행하십시오.
git log 8989ee0
과
git log 7c6b236
8989ee0
, 7c6b236
갈 하나. 어떻게 이해할까요?
git log 8989ee0
하고 git log 7c6b236
, 당신은 답을 알고 있어야합니다.
다음은 누군가에게 도움이되기를 희망하는 완전한 예입니다.
git revert -m 1 <commit-hash>
git push -u origin master
어디 <commit-hash>
를 이용해서 복귀하고 싶다고 병합의 해시를 저지하고,의 설명에 명시된 바와 같이 이 응답 , -m 1
당신이 병합하기 전에 먼저 부모의 트리로 복귀하고 싶은 것을 나타냅니다.
git revert ...
두 번째 줄은 원격 지사에 밀어 변경 사항을 공개하게하면서 라인은 본질적으로 변경 사항을 커밋합니다.
git revert
명령이 이미 커밋 객체를 커밋 했다고 믿었 습니다. 그러지 않으려면 --no-commit
플래그 를 입력해야합니다
Ben은 병합 커밋을 되 돌리는 방법을 알려 주었지만 그렇게하는 것이 매우 중요 합니다.
"... 는 병합으로 인해 트리 변경 사항을 가져 오지 않기를 선언합니다. 결과적으로 나중에 병합하면 이전에 되 돌린 병합의 조상이 아닌 커밋에 의해 도입 된 트리 변경 사항 만 가져옵니다. 당신이 원하는 것. " (git-merge man page) .
기사 / 메일 링리스트 메시지 man 페이지에서 링크가 포함되는 메커니즘과 고려 사항에 대해 자세하게 설명합니다. 병합 커밋을 되 돌리면 나중에 분기를 다시 병합 할 수 없으며 동일한 변경 사항이 다시 발생할 것으로 기대할 수 있습니다.
다음 단계에 따라 잘못된 커밋을 되돌 리거나 원격 분기를 다시 HEAD / 상태로 다시 재설정 할 수 있습니다.
git checkout development
커밋 해시 (즉, 잘못된 커밋 직전 커밋의 ID)를 자식 로그에서 복사하십시오.
git log -n5
산출:
커밋 7cd42475d6f95f5896b6f02e902efab0b70e8038 "브랜치 '잘못된 커밋'을 '개발'로 병합 '
커밋 f9a734f8f44b0b37ccea769b9a2fd774c0f0c012"이것은 잘못된 커밋입니다 "
커밋 3779ab50e72908da92d2ff
이전 단계에서 복사 한 커밋 해시로 분기 재설정
git reset <commit-hash> (i.e. 3779ab50e72908da92d2cfcd72256d7a09f446ba)
git status
잘못된 커밋의 일부인 모든 변경 사항을 표시하십시오.git reset --hard
모든 변경 사항을 되돌리려면 간단히 실행하십시오 .git push -f origin development
아무 일도 일어나지 않았을 때 로그를 깨끗하게 유지하려면 (이 접근법의 단점은 -f로 인해) :
git checkout <branch>
git reset --hard <commit-hash-before-merge>
git push -f origin HEAD:<remote-branch>
'commit-hash-before-merge'는 병합 후 로그 (git log)에서 나옵니다.
push -f
공유 repo에 절대하지 마십시오
롤백하는 가장 효과적인 방법은 뒤로 물러서서 교체하는 것입니다.
git log
두 번째 커밋 해시 (전체 해시, 실수 전에 다시 되돌리려는 해시)를 사용한 다음 다시 시작하십시오.
git checkout -b newbranch <HASH>
그런 다음 이전 분기를 삭제하고 새 분기를 그 자리에 복사 한 다음 다시 시작하십시오.
git branch -D oldbranch
git checkout -b oldbranch newbranch
브로드 캐스트 된 경우 모든 리포지토리에서 이전 분기를 삭제하고 다시 실행 분기를 가장 중앙으로 밀고 다시 모든 분기로 당깁니다.
merge
커밋 을 되돌리려면 다음 을 수행하십시오.
git log
하여 병합 커밋의 ID를 찾으십시오. 또한 병합과 관련된 여러 상위 ID를 찾을 수 있습니다 (아래 이미지 참조).병합 커밋 ID를 노란색으로 표시하십시오. 부모 ID는 다음 줄에로 쓰여진 것입니다 Merge: parent1 parent2
. 지금...
단편:
git revert <merge commit id> -m 1
열면됩니다 vi
. 쓰기, 저장, 종료, 완료!긴 이야기:
병합 된 지점으로 전환하십시오. 제 경우에는 test
지점이며 feature/analytics-v3
지점에서 지점 을 제거하려고 합니다.
git revert
커밋을 되 돌리는 명령입니다. 그러나 merge
커밋을 되돌릴 때 불쾌한 트릭 이 있습니다. -m
플래그 를 입력해야합니다 . 그렇지 않으면 실패합니다. 여기서부터 브랜치를 되돌릴 지, 정확히 온 브랜치인지 parent1
또는 다음과 같이 보이게할지 결정해야합니다 parent2
.
git revert <merge commit id> -m 1
(로 되돌아 감 parent2
)
git revert <merge commit id> -m 2
(로 되돌아 감 parent1
)
이 부모를 로그하여 원하는 방법을 알아낼 수 있으며 이것이 모든 혼란의 근원입니다.
모든 답변은 이미 대부분의 내용을 다루었지만 5 센트를 추가 할 것입니다. 요약하면 병합 커밋을 되 돌리는 것은 매우 간단합니다.
git revert -m 1 <commit-hash>
권한이있는 경우이를 "마스터"분기로 직접 푸시 할 수 있고, 그렇지 않으면 간단히 "복귀"분기로 푸시하여 풀 요청을 작성하십시오.
이 주제에 대한 더 유용한 정보는 여기에서 찾을 수 있습니다 : https://itcodehub.blogspot.com/2019/06/how-to-revert-merge-in-git.html
두 개의 알려진 끝점 사이에 역 패치를 만들고 해당 패치를 적용하면 효과가 있음을 알았습니다. 이는 마스터 브랜치에서 스냅 샷 (태그)을 생성했거나 마스터 브랜치 백업 (master_bk_01012017)을 생성 한 것으로 가정합니다.
master에 병합 한 코드 분기가 mycodebranch라고 가정하십시오.
git diff --binary master..master_bk_01012017 > ~/myrevert.patch
git apply --check myrevert.patch
git am --signoff < myrevert.patch
git branch mycodebranch_fix
git checkout mycodebranch_fix
git revert [SHA]
정답이 표시된 답변은 저에게 도움이되었지만 시간을내어 진행 상황을 파악해야했습니다. 그래서 저는 저와 같은 사례에 대해 간단한 간단한 단계로 답변을 추가하기로 결정했습니다.
분기 A와 B가 있다고 가정 해 봅시다. 분기 A를 분기 B로 병합하고 분기 B를 자체로 푸시하여 이제 병합이 그 일부가되었습니다. 그러나 병합 전에 마지막 커밋으로 돌아가고 싶습니다 . 당신은?
git log
최근 커밋 내역이 표시됩니다. 커밋에는 commit / author / date 속성이 있고 병합에는 merge 속성도 있습니다. 따라서 다음과 같이 표시됩니다.
commit: <commitHash>
Merge: <parentHashA> <parentHashB>
Author: <author>
Date: <date>
사용 git log <parentHashA>
및 git log <parentHashB>
-해당 상위 브랜치의 커밋 히스토리를 볼 수 있습니다. 목록의 첫 번째 커밋은 최신 커밋입니다.
<commitHash>
원하는 커밋을 가져 와서 git root 폴더로 이동하여 사용 git checkout -b <newBranchName> <commitHash>
하십시오. 병합 전에 선택한 마지막 커밋에서 시작하여 새 브랜치를 만듭니다. Voila, ready!git revert -m에 대한 git doc은 이것을 정확하게 설명하는 링크를 제공합니다 : https://github.com/git/git/blob/master/Documentation/howto/revert-a-faulty-merge.txt
또한 GitHub 리포지토리의 마스터 브랜치에 병합 된 PR에서이 문제에 직면했습니다.
난 그냥 몇 가지 수정 된 파일을 수정하고 싶어하지만 전체 변화 홍보 가져온 이후, 나는에 있었다 와 .amend
merge commit
git commit --am
단계 :
git add *
또는git add <file>
git commit --am
및 유효성 검사git push -f
왜 흥미로운 지 :
이 링크 에서 병합을 되 돌리는 방법에 대한 좋은 설명을 찾았으며 아래 설명을 복사하여 아래 링크가 작동하지 않는 경우에 유용합니다.
결함이있는 병합을 되 돌리는 방법 Alan (alan@clueserver.org)은 다음과 같이 말했습니다.
마스터 지점이 있습니다. 우리는 일부 개발자들이 작업하고 있다는 점을 가지고 있습니다. 그들은 그것이 준비되었다고 주장한다. 우리는 이것을 마스터 브랜치로 병합합니다. 병합을 되돌릴 수 있도록 무언가를 끊습니다. 코드를 변경합니다. 그들은 그것이 정상이라고 말하고 우리가 다시 합병하는 지점까지 그것을 얻습니다. 살펴보면 되돌리기 전에 작성된 코드 변경 사항이 마스터 분기가 아니라 이후의 코드 변경 사항이 마스터 분기에 있음을 알 수 있습니다. 이 상황에서 회복하는 데 도움을 요청했습니다.
"병합 되돌리기"직후의 기록은 다음과 같습니다.
---o---o---o---M---x---x---W
/
---A---B
A와 B가 부진한 측면 개발에 있고, M은 이러한 조기 변경을 메인 라인으로 가져 오는 병합이고, x는 사이드 브랜치가 수행 한 것과 관련이없는 변경이며, 메인 라인에서 이미 수행 된 변경이며, W는 " 병합 M을 되돌립니다 "(W가 거꾸로 보이지 않습니까?). "diff W ^ .. W"는 "diff -RM ^ .. M"과 유사합니다.
이러한 병합의 "복귀"는 다음을 사용하여 수행 할 수 있습니다.
$ git revert -m 1 M 사이드 브랜치 개발자가 실수를 고친 후 역사는 다음과 같습니다.
---o---o---o---M---x---x---W---x
/
---A---B-------------------C---D
여기서 C와 D는 A와 B에서 깨진 것을 고치기위한 것이며, W 이후에 메인 라인에 다른 변화가있을 수 있습니다.
업데이트 된 사이드 브랜치를 병합하면 (끝 부분에 D가 있음) A 또는 B의 변경 사항은 W에 의해 되돌려 졌기 때문에 결과에 나타나지 않습니다. 이것이 Alan이 본 것입니다.
Linus는 상황을 설명합니다.
정규 커밋을 되 돌리면 해당 커밋이 수행 한 작업을 효과적으로 취소 할 수 있으며 매우 간단합니다. 그러나 병합 커밋을 되 돌리면 커밋이 변경 한 데이터 도 취소 되지만 병합이 수행 한 기록에 미치는 영향에는 전혀 영향을 미치지 않습니다 . 따라서 병합은 여전히 존재하며 여전히 두 분기를 결합한 것으로 간주되며 향후 병합에서는 해당 병합이 마지막 공유 상태로 간주되며 병합을 되 돌린 되돌리기는 전혀 영향을 미치지 않습니다. 는 "되돌리기"그래서 데이터 변경 사항을 실행 취소,하지만 매우이다 하지저장소 실행 기록에 대한 커밋의 영향을 취소하지 않는다는 점에서 "실행 취소" "revert"를 "undo"로 생각하면 항상이 부분을 놓치게됩니다. 예, 데이터를 취소하지만 기록은 취소하지 않습니다. 이러한 상황에서는 먼저 이전 되돌리기를 되돌리려 고합니다. 그러면 기록이 다음과 같이 나타납니다.
---o---o---o---M---x---x---W---x---Y
/
---A---B-------------------C---D
여기서 Y는 W의 복귀입니다. 이러한 "복귀의 복귀"는 다음과 같이 수행 할 수 있습니다.
$ git revert W 이 히스토리 (W와 W..Y가 변경된 것을 무시 함)는 히스토리에 W 또는 Y가 전혀없는 것과 같습니다.
---o---o---o---M---x---x-------x----
/
---A---B-------------------C---D
사이드 브랜치를 다시 병합하면 이전 되돌리기 및 되돌리기의 복귀로 인해 충돌이 발생하지 않습니다.
---o---o---o---M---x---x-------x-------*
/ /
---A---B-------------------C---D
물론 C와 D의 변경 사항은 여전히 x 중 하나와 수행 한 내용과 충돌 할 수 있지만 이는 단지 정상적인 병합 충돌입니다.
Ryan이 언급했듯이 git revert
도로에서 병합이 어려워 질 git revert
수 있으므로 원하는 것이 아닐 수도 있습니다. git reset --hard <commit-hash-prior-to-merge>
여기서 명령을 사용하는 것이 더 유용 하다는 것을 알았 습니다.
하드 리셋 부분을 완료 한 후에는 다음 원격 지점, 즉,에 밀어 강제 할 수 있습니다 git push -f <remote-name> <remote-branch-name>
, <remote-name>
종종 이름 origin
. 이 시점에서 원하는 경우 다시 병합 할 수 있습니다.