git 같은 VCS(Version Control System, 버전 관리 도구)를 사용하는 이유가 바로 과거 작업 내역을 기록하고, 필요하면 불러오기 위해서다. checkout 명령을 사용해 이동한다.

아래 명령은 현재 위치(HEAD)에서 한 단계 과거로 가는 명령어다.

git checkout HEAD~1

숫자를 바꾸면 해당하는 숫자만큼 과거로 간다. 아래처럼 명령을 내리면 10단계 과거로 간다.

git checkout HEAD~10

HEAD 대신 커밋 hash를 사용할 수도 있다. 예컨대 아래와 같다.

git checkout eb919a7~1

다시 돌아오는 방법은? checkout 명령의 원리를 생각하면 간단하다. master 브랜치로 돌아오고 싶다면 아래처럼 명령한다.

git checkout master

master 브랜치가 아닌 다른 브랜치명을 적어도 상관없다. 해당 브랜치로 복귀하게 된다.

특정 커밋을 콕 찝어서 돌아가기

특정 커밋으로 여행하는 방법은 무엇일까?

아래와 같은 로그가 있다고 치자.

commit bd32ba7c2c1bf1e793c6c951856e35ec7f397daa
Author: 안형우 <[email protected]>
Date:   Tue May 7 08:04:36 2013 +0900

커밋3

commit 8553f2530e01cbd66d135d43e11d1d2f9366b5f8
Author: 안형우 <[email protected]>
Date:   Tue May 7 08:04:02 2013 +0900

커밋2

commit 5fa1c73e90b5b14a4cab49031afa0c9bdea1c587
Author: 안형우 <[email protected]>
Date:   Tue May 7 08:03:45 2013 +0900

커밋1

세 개의 커밋이다. 각각 commit 해시값(단순히 말하자면 위에서 알파벳과 숫자 조합인 문자열)이 있다. 이게 해당 커밋의 고유번호다. 그리고 이 고유번호의 앞자리 일부만 적어 주면 알아서 식별을 한다. 그래서, 커밋2로 돌아가고 싶다면?

git checkout 8553f2

이렇게 적어 주면 된다. 그리고 master 브랜치로 돌아오고 싶다면 언제든

git checkout master

이렇게 적어 주면 된다.

코드를 이전 버전으로 되돌려 새로 커밋하고 싶다면

그렇다면 master를 이전 커밋으로 만들고 싶다면 어떻게 해야 할까? 시나리오가 다양해서 단순히 답하기 힘들다.

다만 가장 간단한 방법은 당시 버전으로 가는 코드를 추가하고 새로 커밋하는 방법일 것이다. 저장소를 수정하는 방법이 아니고 동료들도 귀찮지 않아 편하다. 아래는 현재 위치가 master라고 가정하고 master 브랜치를 10단계 전으로 되돌리는 예시다.

git revert master~10

이러면 커밋 메시지 입력 에디터가 뜬다. 평소처럼 저장하고 나오면 커밋이 하나 추가되고 코드가 되돌려진 것을 알 수 있다.

당연히 hash로도 할 수 있다. 돌아가고 싶은 커밋의 hash가 3aa0559라면 아래처럼 명령을 내린다.

git revert 3aa0559

최근 커밋을 없앰으로써 코드를 되돌리는 방법

위와 같이 하지 않고 최근 커밋을 없었던 셈 칠 수도 있다. 그러나 이렇게 하면 원격 소스와 로컬 소스가 맞지 않게 되므로 원격 저장소에 있는 소스를 로컬 저장소에 있는 소스로 덮어써야 한다. 혼자 작업하는 경우면 상관없을 텐데 동료들이 있는 경우에는, 동료들의 로컬 저장소도 강제로 덮어써야 하는 문제가 생긴다. 따라서 웬만하면 하지 않는 게 좋겠다.

hash 23de995d 이후의 커밋을 모두 없던 셈 치려면 아래와 같이 명령을 내린다.

git reset 23de995d

당연히 hash 자리엔 특정 커밋을 가리키는 다른 문법들도 들어갈 수 있다. 최신 코드로부터 10단계 전까지 되돌리려면 아래와 같이 명령을 내린다.

git reset HEAD~10

그러면 git 저장소는 의도한 곳으로 되돌아간다. 로컬 소스 코드는 그대로이므로 현재 코드가 수정된 상태라고 표시된다. 아래 명령으로 “수정된” 상태인 소스 코드를 git 저장소의 코드로 원복한다.

git reset --hard

이러면 수정된 사항은 모두 없어진다. 그러나 되돌아간 git 저장소가 알지 못하는, 현재 커밋 이후 새로 추가됐던 파일은 아직 남아있다. 이 파일들은 수동으로 지워 주도록 한다. 아니면 좀 지저분하긴 하지만 아래 명령어로 지운다.

git status -s | xargs rm

그러면 rm: ??: No such file or directory라는 에러 메시지가 나오고 여하간 파일은 잘 지워진다. ??라는 파일이 있는 게 아닌 이상 별 문제 없이 작동하니 에러 메시지는 상관없다.

에러 메시지를 보고 싶지 않은 경우 아래 명령을 사용한다.

git status -s | cut -c4- | xargs rm

이상이다. 자세한 설명을 하지 않은 점 양해 부탁한다.

코드를 이전 버전으로 되돌리는 patch 파일을 만들고 싶다면

이건 대부분에게는 필요없는 방법일 텐데, 간혹 git로 조작을 못하는 경우가 있을 수 있다. 그럴 땐 고전적인 패치 파일 만들기를 사용할 수 있다. git로 관리되는 프로젝트의 최상위 폴더에서 명령을 내려야 한다.

git diff master master~10 > /my/folder/patch.diff

이러면 patch.diff 파일이 만들어진다. 적용해야 하는 곳에 가서 패치 파일을 적용한다.

patch -p1 < /my/folder/patch.diff

이러면 코드가 수정돼 있는 것을 볼 수 있을 것이다. git diff나 patch 명령어에 대한 상세한 설명은 생략했다.