Program Tip

여러 git 커밋을 되 돌리는 방법은 무엇입니까?

programtip 2020. 9. 28. 09:55
반응형

여러 git 커밋을 되 돌리는 방법은 무엇입니까?


다음과 같은 git 저장소가 있습니다.

A -> B -> C -> D -> HEAD

나는 가지의 머리가 A를 가리 키기를 원합니다. 즉, B, C, D, HEAD가 사라지고 머리가 A와 동의어가되기를 원합니다.

리베이스를 시도하거나 (그 사이에 변경 사항을 적용 했으므로 적용되지 않음) 되돌릴 수있는 것 같습니다. 하지만 여러 커밋을 되돌리려면 어떻게해야합니까? 한 번에 하나씩 되 돌리나요? 순서가 중요합니까?


내가 댓글에 쓴 내용 확장

일반적인 규칙은 누군가가 자신의 작업을 기반으로 할 수 있으므로 게시 한 기록을 다시 작성 (변경)해서는 안된다는 것입니다. 기록을 다시 작성 (변경)하면 변경 사항을 병합하고 업데이트하는 데 문제가 발생합니다.

이 솔루션은 만드는 것입니다 그래서 새로운 커밋 하는 되돌립니다 변경 은 없애 싶어. git revert 명령을 사용하여이 작업을 수행 할 수 있습니다 .

다음과 같은 상황이 있습니다.

A <-B <-C <-D <-마스터 <-HEAD

(여기서 화살표는 포인터의 방향을 나타냅니다. 커밋의 경우 "부모"참조, 분기 헤드 (분기 참조)의 경우 최상위 커밋, HEAD 참조의 경우 분기 이름).

생성해야 할 것은 다음과 같습니다.

A <-B <-C <-D <-[(BCD) ^-1] <-마스터 <-HEAD

여기서 "[(BCD) ^-1]"은 커밋 B, C, D의 변경 사항을 되 돌리는 커밋을 의미합니다. 수학은 (BCD) ^-1 = D ^ -1 C ^ -1 B ^ -1이므로 다음 명령을 사용하여 필요한 상황을 얻을 수 있습니다.

$ git revert --no-commit D
$ git revert --no-commit C
$ git revert --no-commit B
$ git commit -m "the commit message"

다른 해결책은 커밋 A의 내용체크 아웃 하고이 상태를 커밋하는 것입니다.

$ git checkout -f A -- .
$ git commit -a

그러면 다음과 같은 상황이 발생합니다.

A <-B <-C <-D <-A '<-마스터 <-HEAD

커밋 A '는 커밋 A와 동일한 내용을 갖지만 다른 커밋 (커밋 메시지, 상위, 커밋 날짜)입니다.

Charles Bailey가 수정 한 Jeff Ferland솔루션 은 동일한 아이디어를 기반으로하지만 git reset을 사용합니다 .

$ git reset --hard A
$ git reset --soft @{1}  # (or ORIG_HEAD), which is D
$ git commit

이를 위해서는 revert 명령 을 사용하여 되돌리려 는 커밋 범위를 지정하면됩니다.

귀하의 예를 고려하여 다음을 수행해야합니다 ( '마스터'브랜치에 있다고 가정).

git revert master~3..master

이것은 B, C 및 D의 역 커밋을 사용하여 로컬에 새 커밋을 생성합니다 (이 커밋에 의해 도입 된 변경 사항을 실행 취소 함을 의미 함).

A <- B <- C <- D <- BCD' <- HEAD

내가 유용하다고 생각한 깨끗한 방법

git revert --no-commit HEAD~3..

이 명령은 단 하나의 커밋으로 마지막 3 개의 커밋을 되돌립니다.

또한 역사를 다시 쓰지 않습니다.


Jakub의 답변과 유사하게 이것은 되돌릴 연속 커밋을 쉽게 선택할 수 있습니다.

# revert all commits from B to HEAD, inclusively
$ git revert --no-commit B..HEAD  
$ git commit -m 'message'

git reset --hard a
git reset --mixed d
git commit

이는 한 번에 모두에 대한 되돌리기 역할을합니다. 좋은 커밋 메시지를 제공하십시오.


먼저 작업 복사본이 수정되지 않았는지 확인하십시오. 그때:

git diff HEAD commit_sha_you_want_to_revert_to | git apply

그런 다음 커밋하십시오. 되 돌리는 이유를 문서화하는 것을 잊지 마십시오.


I'm so frustrated that this question can't just be answered. Every other question is in relation to how to revert correctly and preserve history. This question says "I want the head of the branch to point to A, i.e. I want B, C, D, and HEAD to disappear and I want head to be synonymous with A."

git checkout <branch_name>
git reset --hard <commit Hash for A>
git push -f

I learned a lot reading Jakub's post, but some guy in the company (with access to push to our "testing" branch without Pull-Request) pushed like 5 bad commits trying to fix and fix and fix a mistake he made 5 commits ago. Not only that, but one or two Pull Requests were accepted, which were now bad. So forget it, I found the last good commit (abc1234) and just ran the basic script:

git checkout testing
git reset --hard abc1234
git push -f

I told the other 5 guys working in this repo that they better make note of their changes for the last few hours and Wipe/Re-Branch from the latest testing. End of the story.


This is an expansion of one of the solutions provided in Jakub's answer

I was faced with a situation where the commits I needed to roll back were somewhat complex, with several of the commits being merge commits, and I needed to avoid rewriting history. I was not able to use a series of git revert commands because I eventually ran into conflicts between the reversion changes being added. I ended up using the following steps.

First, check out the contents of the target commit while leaving HEAD at the tip of the branch:

$ git checkout -f <target-commit> -- .

(The -- makes sure <target-commit> is interpreted as a commit rather than a file; the . refers to the current directory.)

Then, determine what files were added in the commits being rolled back, and thus need to be deleted:

$ git diff --name-status --cached <target-commit>

Files that were added should show up with an "A" at the beginning of the line, and there should be no other differences. Now, if any files need to be removed, stage these files for removal:

$ git rm <filespec>[ <filespec> ...]

Finally, commit the reversion:

$ git commit -m 'revert to <target-commit>'

If desired, make sure that we're back to the desired state:

$git diff <target-commit> <current-commit>

There should be no differences.


The easy way to revert a group of commits on shared repository (that people use and you want to preserve the history) is to use git revert in conjunction with git rev-list. The latter one will provide you with a list of commits, the former will do the revert itself.

There two ways to do that. If you want the revert multiple commits in a single commit use:

for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert -n $i; done

this will revert a group of commits you need, but leave all the changes on your working tree, you should commit them all as usual.

Another option is to have a single commit per reverted change:

for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert --no-edit -s $i; done

For instance, if you have a commit tree like

 o---o---o---o---o---o--->    
fff eee ddd ccc bbb aaa

to revert the changes from eee to bbb, run

for i in `git rev-list eee^..bbb`; do git revert --no-edit -s $i; done

None of those worked for me, so I had three commits to revert (the last three commits), so I did:

git revert HEAD
git revert HEAD~2
git revert HEAD~4
git rebase -i HEAD~3 # pick, squash, squash

Worked like a charm :)


In my opinion a very easy and clean way could be:

go back to A

git checkout -f A

point master's head to the current state

git symbolic-ref HEAD refs/heads/master

save

git commit

If you want to temporarily revert the commits of a feature, then you can use the series of following commands.

Here is how it works

git log --pretty=oneline | grep 'feature_name' | cut -d ' ' -f1 | xargs -n1 git revert --no-edit

참고 URL : https://stackoverflow.com/questions/1463340/how-to-revert-multiple-git-commits

반응형