Git

Git 이전 커밋으로 롤백하기(git revert)

범데이 2022. 12. 14. 00:45

1.개요

지난번 포스팅에서는 로컬 프로젝트에서 이전 커밋으로 되돌아가는 git reset에 대해 다루었었다.(해당포스팅)

 

이번에는, 예전의 커밋으로 되돌린 뒤, 이를 푸시하여 원격 레포지토리에도 예전 소스들로 되돌아가게 할수있는 명령어를 포스팅해보고자 한다.

 

git reset명령어도 특정 커밋으로 되돌아 간 후 force push를 할 수 있으나, 소스의 수정 사항들이 모두 날아가기 때문에 일반적인 상황에서는 원격 저장소에 force push는 가급적 해서는 안되며, 협업 상황에서는 절대로 해서는 안된다.

 

이럴 때 사용할 수 있는 명령어가 바로 특정 커밋으로 돌아가는 revert이다. 이 포스팅에서는 git revert명령어에 대해서 포스팅하고자 한다.

 

 

 

2. git revert 기초 사용법

git revert의 기본 사용 명령어는 다음과 같다.

git revert [options] <commit>…
git revert (--continue | --skip | --abort | --quit)

 

 

아래 예제를 보면 git log를 출력해보았을때 commit들이 등록되어 있다.

여기서 commit 971c858 (2nd commit)이 적용되기 이전으로 수정사항을 되돌리려고 한다.

$ git log
commit 5551f386aa1c22c26ea6aaf678e7cdbf2cded39b (HEAD -> master)
Author: Bumday
Date:   Sat Jun 26 13:19:30 2021 +0900

    3rd commit

commit 971c858b160aebc1c6c47ae4713959d36d2e2a52
Author: Bumday
Date:   Sat Jun 26 13:19:00 2021 +0900

    2nd commit

commit 10d7d0f6f52539a4e7a1867449b7d6fa023a2685
Author: Bumday
Date:   Fri Jun 25 21:03:38 2021 +0900

    1st commit

 

git revert <commit id>를 입력하면, 이 변경사항이 적용되기 이전으로 돌아간다.

$ git revert 971c858b160aebc1c6c47ae4713959d36d2e2a52
Removing Second.java
[master 9f4586e] Revert "2nd commit"
 2 files changed, 1 insertion(+), 1 deletion(-)
 delete mode 100644 Second.java

 

git log를 보면 Revert “2nd commit” 라는 이름으로 commit이 하나 추가되었다.

$ git log
commit 9f4586eaf107d84a5b99c6cc538c4006e6e01285 (HEAD -> master)
Author: Bumday
Date:   Sat Jun 26 13:20:17 2021 +0900

    Revert "2nd commit"

    This reverts commit 971c858b160aebc1c6c47ae4713959d36d2e2a52.

commit 5551f386aa1c22c26ea6aaf678e7cdbf2cded39b (HEAD -> master)
Author: Bumday
Date:   Sat Jun 26 13:19:30 2021 +0900

    3rd commit

commit 971c858b160aebc1c6c47ae4713959d36d2e2a52
Author: Bumday
Date:   Sat Jun 26 13:19:00 2021 +0900

    2nd commit

commit 10d7d0f6f52539a4e7a1867449b7d6fa023a2685
Author: Bumday
Date:   Fri Jun 25 21:03:38 2021 +0900

    1st commit

 

 

변경 내용을 보면 Revert “2nd commit”이 2nd commit의 수정사항을 제거한 commit이라는 것을 확인할 수 있다.

$ git show 971c858b160aebc1c6c47ae4713959d36d2e2a52
commit 971c858b160aebc1c6c47ae4713959d36d2e2a52
Author: Bumday
Date:   Sat Jun 26 13:19:00 2021 +0900

    2nd commit

diff --git a/First.java b/First.java
index 9335791..a728477 100644
--- a/First.java
+++ b/First.java
@@ -14,7 +14,7 @@ import tech.thdev.media_projection_library.R
 internal class MediaProjectionAccessActivity : AppCompatActivity() {

     companion object {
-        private const val REQ_CODE_MEDIA_PROJECTION = 1000
+        private const val REQ_CODE_MEDIA_PROJECTION = 2000
$ git show 9f4586eaf107d84a5b99c6cc538c4006e6e01285
commit 9f4586eaf107d84a5b99c6cc538c4006e6e01285 (HEAD -> master)
Author: Bumday
Date:   Sat Jun 26 13:20:17 2021 +0900

    Revert "2nd commit"

    This reverts commit 971c858b160aebc1c6c47ae4713959d36d2e2a52.

diff --git a/First.java b/First.java
index a728477..9335791 100644
--- a/First.java
+++ b/First.java
@@ -14,7 +14,7 @@ import tech.thdev.media_projection_library.R
 internal class MediaProjectionAccessActivity : AppCompatActivity() {

     companion object {
-        private const val REQ_CODE_MEDIA_PROJECTION = 2000
+        private const val REQ_CODE_MEDIA_PROJECTION = 1000

 

 

3.  여러 commit을 revert하는 방법

3.1 여러 특정 commit 지정

사실 이 방법을 현업에서 사용하게 되어서 포스팅하게 되었다.

 

몇차례나 이전의 커밋으로 돌아가기 위해 일일이 revert하기는 매우 번거로울 수 있으니, 여러 commit을 revert할 때

아래와 같이 git revert [commit id] [commit id] ... 처럼 여러 commit id를 인자로 전달 할 수도 있다.

$ git revert 5551f38 10d7d0f
Removing Third.java
[master 2260375] Revert "3rd commit"
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 Third.java
[master 7ce9b41] Revert "1st commit"
 1 file changed, 7 insertions(+)

 

 

 

 

3.2 commit 범위 지정

또한, git revert [commit-id]...[commit-id] 와 같이 revert할 commit의 범위를 지정해줄수도 있다

 

아래는 그 활용 예이다.

범위로 지정된 commit들이 일괄 revert되고, 되돌아간 소스들이 변경사항으로 남게 된다.

 

추가로 --no-commit 옵션을 주어 revert가 자동으로 커밋되지 않도록 하였다. 이렇게 함으로써 되돌아갈 지점까지 한번에 변경사항들을 모아서 한번의 revert 커밋을 남길 수 있게 된다.

 

 

주의해서 사용할 점은 revert할 commit들의 범위를 고르는 것이기에 끝범위로 준 commit까지 모두 revert된다. 이를 참고하자. (돌아갈 지점을 지정하는 reset명령어와 혼동할 우려가 있다.)

 

 

3.3 commit을 진행하다 충돌이나 병합이 발생했을 때

다수의 커밋들을 모두 되돌리는데에 충돌이나 병합이 발생할 경우, 일단 멈춤 상태가 되는데,

아래 명령어로 어떻게 진행할 것인지 결정할 수 있다.

 

git revert --continue: 커밋할 메시지를 지정하여 변경사항의 커밋한후, 진행중인 작업을 계속한다.

git revert --abort: 진행중인 작업을 취소하고 시퀀스 이전 상태로 돌아간다.

git revert --skip: 현재 커밋을 건너뛰고 시퀀스의 남은 부분을 계속 진행한다.

git revert --quit: 진행죽인 작업을 지운다. 되돌리기 실패시 시퀀서 상태를 지우는 데 사용할 수 있다.

 

 

아래는 그 활용 예이다.

revert를 하다가 병합이 발생하여 error메시지가 출력되며 중단되었다.

 

 

이때, 나는 --continue옵션으로 revert를 계속 하고자 했다.

 

그러면 위와 같이 편집기가 열리는데, 작성한 메시지로 revert시작 후 발생한 변경 사항에 대한 커밋을 진행한다.

 

이렇게 error가 발생한 지점까지지 revert된 사항이 commit이 되고, 계속해서 남은 revert를 진행한다.

근데 또 병합이 발생하여 중단되었고, 계속하여 --continue옵션으로 위 과정을 반복하였다.

 

 

이렇게 마지막까지 revert가 완료되었고, 더이상 충돌이나 병합이 발생하지 않아 error메시지가 뜨지 않는것을 확인할 수 있다.

revert된 변경사항들은 모두 commit한 상황이다.

(이를 이대로 push하게되면 revert중에 중단된 지점마다 commit된 사항이 원격 레포지토리에 남을 것이고, commit을 모두 취소시킨다음 stage에 올라가 있는 변경사항을 다시 일괄 commit하면 한번의 commit 로그만 남을 것이다.)

 

이렇게 commit지점을 범위로 주어 revert한 뒤, 이전 소스로 변경된 사항을 push하여 소스 원복을 완료할 수 있었다.

 

 

 

4. 끝맺음

이렇게 git revert에 톺아보는 시간을 가졌다.

 

현업에서 소스관리를 하다보면, 충돌과 병합은 부지기수고, 소스를 되돌려야 하거나 브랜치를 따로 따거나 여러개의 소스 선택지 중 적용되야할 소스를 선택해야할 때도 있는 등 다양하게 소스를 컨트롤해야하는 상황이 온다.

 

하지만 이런 상황들이 대부분은 한가한 상황에 오지 않으니, 평소에 git을 잘 다룰 수 있도록 문서를 읽어보고

많이 학습해두는 것도 개발자로써 중요한 과제인 듯 하다.

 


#References

https://codechacha.com/ko/git-revert/

https://velog.io/@njs04210/Git-reset과-revert-알고-사용하기

https://git-scm.com/docs/git-revert

https://www.lainyzine.com/ko/article/git-revert-reverting-commit-in-git-repository/

https://backlog.com/git-tutorial/kr/stepup/stepup7_2.html

반응형