이전 커밋 확인하기: Git의 시간 여행
Git에서는 과거의 특정 상태를 확인하고 싶을 때, 해당 커밋을 직접 체크아웃할 수 있습니다. 이를 위해 git log --oneline
명령어를 사용하여 원하는 커밋의 해시를 찾고, git checkout <커밋 해시>
를 실행하면 됩니다.
과거 커밋 체크아웃하기
다음과 같은 브랜치 구조가 있다고 가정해봅시다.
* (HEAD -> main) c5d3a1d 최신 커밋
* a8f1b2c 새로운 기능 추가
* 4f1b3e9 버그 수정
* 7a3c2d1 개츠비 → 캐츠비 이름 변경
* 3d2e1f7 1장과 2장으로 분리
* 9c8b7a6 소설 개요 작성 (최초 커밋)
이제 과거 상태를 확인하기 위해 7a3c2d1
커밋을 체크아웃해봅시다.
git checkout 7a3c2d1
그러면 현재 HEAD
는 해당 커밋을 직접 가리키게 되며, "분리된 HEAD(detached HEAD)" 상태가 됩니다.
* c5d3a1d 최신 커밋
* a8f1b2c 새로운 기능 추가
* 4f1b3e9 버그 수정
* (HEAD) 7a3c2d1 개츠비 → 캐츠비 이름 변경
* 3d2e1f7 1장과 2장으로 분리
* 9c8b7a6 소설 개요 작성 (최초 커밋)
이 상태에서는 과거 코드의 상태를 확인하고, 임시로 변경을 가할 수도 있습니다. 하지만 새로 커밋을 하면 기존 브랜치(main)과 연결되지 않으므로 주의해야 합니다.
기존 브랜치로 돌아가기
분리된 HEAD 상태에서 원래 브랜치로 돌아가고 싶다면, 다음을 실행하면 됩니다.
git switch main
또는 기존 checkout
명령어를 사용할 수도 있습니다.
git checkout main
그러면 다시 원래 브랜치로 돌아오게 됩니다.
* (HEAD -> main) c5d3a1d 최신 커밋
* a8f1b2c 새로운 기능 추가
* 4f1b3e9 버그 수정
* 7a3c2d1 개츠비 → 캐츠비 이름 변경
* 3d2e1f7 1장과 2장으로 분리
* 9c8b7a6 소설 개요 작성 (최초 커밋)
분리된 HEAD에서 다시 연결하기
분리된 HEAD 상태에서 우리는 과거의 특정 커밋을 탐색하고, 변경 사항을 확인할 수 있습니다. 그러나 이 상태에서는 새로운 커밋을 하더라도 특정 브랜치에 연결되지 않기 때문에 주의가 필요합니다.
이제 분리된 HEAD 상태에서 다시 브랜치에 연결하는 방법을 살펴보겠습니다.
1. 기존 브랜치로 돌아가기
분리된 HEAD 상태에서 다시 기존 브랜치로 돌아가려면 간단히 브랜치를 스위치하면 됩니다.
git switch main
또는
git checkout main
그러면 HEAD가 다시 브랜치 참조를 가리키게 되며, 정상적인 Git 작업을 할 수 있습니다.
* (HEAD -> main) c5d3a1d 최신 커밋
* a8f1b2c 새로운 기능 추가
* 4f1b3e9 버그 수정
* 7a3c2d1 개츠비 → 캐츠비 이름 변경
* 3d2e1f7 1장과 2장으로 분리
* 9c8b7a6 소설 개요 작성 (최초 커밋)
2. 과거 커밋을 기반으로 새로운 브랜치 만들기
때때로 과거의 특정 시점으로 돌아가 해당 상태를 바탕으로 새로운 작업을 시작하고 싶을 수 있습니다. 이런 경우, 분리된 HEAD 상태에서 새로운 브랜치를 만들면 됩니다.
먼저 특정 커밋을 체크아웃합니다.
git checkout 4f1b3e9
이제 HEAD가 해당 커밋을 가리키고 있으며, 분리된 HEAD 상태가 됩니다.
* c5d3a1d 최신 커밋
* a8f1b2c 새로운 기능 추가
* 4f1b3e9 버그 수정 <-- (HEAD)
* 7a3c2d1 개츠비 → 캐츠비 이름 변경
* 3d2e1f7 1장과 2장으로 분리
* 9c8b7a6 소설 개요 작성 (최초 커밋)
이 상태에서 새로운 브랜치를 만들고 스위치하면 됩니다.
git switch -c new-feature
또는
git branch new-feature
git switch new-feature
이제 HEAD가 new-feature
브랜치를 가리키며, 우리는 과거 커밋을 기반으로 새롭게 작업을 시작할 수 있습니다.
* (HEAD -> new-feature) 4f1b3e9 버그 수정
* 7a3c2d1 개츠비 → 캐츠비 이름 변경
* 3d2e1f7 1장과 2장으로 분리
* 9c8b7a6 소설 개요 작성 (최초 커밋)
이제 new-feature
브랜치에서 새로운 변경 사항을 추가하고 커밋하면, 기존 main
브랜치와는 별개로 새로운 작업 흐름을 만들 수 있습니다.
HEAD를 이용한 커밋 참조
Git에서는 특정 커밋 해시를 사용하여 과거의 커밋을 체크아웃할 수 있지만, HEAD를 활용하면 더 직관적으로 커밋을 참조할 수 있습니다.
1. HEAD~n을 이용한 커밋 탐색
HEAD는 현재 우리가 위치한 브랜치의 최신 커밋을 가리킵니다. HEAD에서 과거 커밋을 참조하려면 HEAD~n
형식을 사용하면 됩니다.
HEAD → 현재 커밋
HEAD~1 → 한 커밋 전 (부모 커밋)
HEAD~2 → 두 커밋 전 (조부모 커밋)
HEAD~3 → 세 커밋 전
예를 들어, 다음과 같은 브랜치가 있다고 가정해봅시다.
* (HEAD -> main) c5d3a1d 최신 커밋
* a8f1b2c 새로운 기능 추가
* 4f1b3e9 버그 수정
* 7a3c2d1 개츠비 → 캐츠비 이름 변경
* 3d2e1f7 1장과 2장으로 분리
* 9c8b7a6 소설 개요 작성 (최초 커밋)
현재 HEAD
가 main
브랜치의 최신 커밋 c5d3a1d
를 가리키고 있습니다.
이제 한 커밋 전으로 돌아가려면 다음 명령어를 실행하면 됩니다.
git checkout HEAD~1
그러면 HEAD가 한 커밋 전의 a8f1b2c
을 가리키게 됩니다.
* (HEAD) a8f1b2c 새로운 기능 추가
* 4f1b3e9 버그 수정
* 7a3c2d1 개츠비 → 캐츠비 이름 변경
* 3d2e1f7 1장과 2장으로 분리
* 9c8b7a6 소설 개요 작성 (최초 커밋)
이 상태는 분리된 HEAD(detached HEAD) 상태이므로, 새 커밋을 하더라도 브랜치에 속하지 않습니다.
2. HEAD를 사용한 연속 탐색
이전 커밋을 계속해서 탐색하려면 다음과 같이 연속적으로 사용할 수도 있습니다.
git checkout HEAD~2
그러면 HEAD는 두 커밋 전인 4f1b3e9
을 가리키게 됩니다.
* (HEAD) 4f1b3e9 버그 수정
* 7a3c2d1 개츠비 → 캐츠비 이름 변경
* 3d2e1f7 1장과 2장으로 분리
* 9c8b7a6 소설 개요 작성 (최초 커밋)
3. HEAD를 사용한 원래 브랜치로 돌아가기
과거 커밋을 확인한 후 원래 브랜치로 돌아가고 싶다면 간단히 다음 명령어를 실행하면 됩니다.
git switch main
또는 마지막으로 있던 브랜치로 돌아가고 싶다면, -
옵션을 사용할 수 있습니다.
git switch -
이렇게 하면 가장 최근에 있던 브랜치로 복귀할 수 있습니다.
Git Checkout으로 변경 사항 폐기하기
작업 도중 실수로 원하지 않는 변경을 했다면, git checkout
을 사용하여 파일을 마지막 커밋된 상태로 되돌릴 수 있습니다. 이는 커밋되지 않은 변경 사항을 쉽게 취소하는 방법입니다.
1. 특정 파일의 변경 사항 취소
예를 들어, 아래와 같은 Git 상태에서 파일을 수정했다고 가정해봅시다.
git status
출력:
수정됨: cat.txt
수정됨: dog.txt
만약 dog.txt
파일을 원래 상태로 되돌리고 싶다면, 다음 명령어를 실행합니다.
git checkout HEAD -- dog.txt
이 명령어를 실행하면 dog.txt
는 마지막 커밋된 상태로 복구됩니다.
* (HEAD -> main) 3f2e1b6 '세 번째 커밋'
* 2d1b7a9 '두 번째 커밋'
* 1a8c3d2 '첫 번째 커밋'
2. 여러 파일의 변경 사항 취소
여러 파일을 되돌리려면 파일명을 나열하면 됩니다.
git checkout HEAD -- cat.txt dog.txt
만약 작업한 모든 파일을 원래대로 되돌리고 싶다면, -- .
옵션을 사용할 수도 있습니다.
git checkout HEAD -- .
이 명령어를 실행하면 변경한 모든 파일이 마지막 커밋된 상태로 돌아갑니다.
3. 더 짧은 명령어 사용
HEAD
를 생략하고 --
만 사용해도 동일한 결과를 얻을 수 있습니다.
git checkout -- cat.txt
이 방식은 보다 간결하며, 동일하게 해당 파일을 마지막 커밋 상태로 복구합니다.
Git Restore로 수정 사항 취소하기
Git의 restore
명령어는 checkout
이 담당하던 여러 기능 중 "파일 변경 사항 되돌리기"에 집중하여 분리된 명령어입니다. 이를 사용하면 작업 중인 파일을 간단히 이전 커밋된 상태로 복원할 수 있습니다.
1. 변경 사항을 마지막 커밋 상태로 복원하기
작업 도중 파일을 실수로 수정했지만 아직 git add
로 스테이징하지 않았다면, 다음 명령어로 변경 사항을 취소할 수 있습니다.
git restore filename
예를 들어 dog.txt
를 원래 상태로 복원하려면 다음을 실행하면 됩니다.
git restore dog.txt
이는 기존의 git checkout HEAD -- dog.txt
와 동일한 역할을 합니다.
2. 특정 커밋 상태로 파일 복원하기
restore
명령어를 사용하면 특정 커밋에 있던 파일 상태로 되돌릴 수도 있습니다. 이때 --source
옵션을 사용합니다.
git restore --source HEAD~2 dog.txt
위 명령어는 dog.txt
를 현재 커밋에서 두 단계 이전(HEAD~2)의 상태로 복원합니다.
브랜치 내의 현재 위치는 유지되며, 커밋되지 않은 변경 사항이 사라지므로 주의해야 합니다.
3. 여러 파일의 변경 사항 복원하기
모든 변경 사항을 되돌리고 싶다면 다음과 같이 실행할 수 있습니다.
git restore .
이 명령어는 현재 변경된 모든 파일을 복원합니다.
Git Restore로 변경 사항 스테이징 취소하기
Git에서 실수로 파일을 git add
로 스테이징했지만, 다시 커밋에 포함하지 않으려면 git restore --staged
명령어를 사용할 수 있습니다.
1. 스테이징된 파일 언스테이징하기
예를 들어, 다음과 같은 변경 사항이 있다고 가정해봅시다.
git status
출력:
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: cat.txt
modified: dog.txt
new file: secrets.txt
여기서 secrets.txt
파일은 실수로 스테이지되었으며, 커밋에 포함하고 싶지 않습니다. 이를 언스테이징하려면 다음 명령어를 실행합니다.
git restore --staged secrets.txt
이제 secrets.txt
는 스테이지에서 제외되었고, 커밋에 포함되지 않습니다. 하지만 파일 자체는 여전히 존재하며, 수정된 상태도 유지됩니다.
2. 여러 개의 파일 언스테이징하기
만약 여러 파일을 한 번에 언스테이징하고 싶다면 다음과 같이 실행할 수 있습니다.
git restore --staged cat.txt dog.txt
또는 모든 스테이징된 파일을 언스테이징하려면:
git restore --staged .
3. git status
를 활용하기
Git은 git status
를 실행하면 언스테이징하는 방법을 알려줍니다. 예를 들어, git status
를 실행하면 다음과 같은 메시지가 나타납니다.
(use "git restore --staged <file>..." to unstage)
따라서 명령어를 기억하지 못하더라도, git status
를 참고하면 적절한 명령어를 쉽게 확인할 수 있습니다.
Git Reset으로 커밋 취소하기
git reset
은 특정 커밋으로 되돌아가고, 이후의 커밋을 삭제하는 명령어입니다. 하지만 변경 사항을 어떻게 처리할지에 따라 두 가지 방식으로 사용할 수 있습니다.
1. 일반적인 git reset
(soft reset)
기본적인 git reset
은 지정한 커밋 이후의 커밋을 제거하지만, 변경 사항은 워킹 디렉토리에 그대로 남겨둡니다.
예를 들어, 다음과 같은 브랜치가 있다고 가정합시다.
* (HEAD -> main) 9f8e1c2 '이 커밋을 취소하세요'
* 4a3b7d9 '실수로 만든 커밋'
* 3c2d1a5 '네 번째 커밋'
* 2b1e7f3 '세 번째 커밋'
* 1a9c8d4 '두 번째 커밋'
* 0f7b6a2 '첫 번째 커밋'
만약 실수로 만든 커밋
과 이 커밋을 취소하세요
를 제거하고 싶다면, 아래 명령어를 실행합니다.
git reset 3c2d1a5
이렇게 하면 Git은 해당 커밋까지만 유지하고, 이후의 커밋들은 삭제됩니다. 하지만 변경 사항은 워킹 디렉토리에 남아있습니다.
* (HEAD -> main) 3c2d1a5 '네 번째 커밋'
* 2b1e7f3 '세 번째 커밋'
* 1a9c8d4 '두 번째 커밋'
* 0f7b6a2 '첫 번째 커밋'
즉, 커밋을 취소하되 변경 사항을 유지하고 싶은 경우 git reset
을 사용할 수 있습니다.
이제 원치 않는 커밋을 삭제했지만, 변경 사항은 여전히 남아 있습니다. 만약 해당 변경 사항을 다른 브랜치에서 살리고 싶다면, 새로운 브랜치를 만들어 이동하면 됩니다.
git switch -c new-branch
git add .
git commit -m "이전 커밋에서 변경 사항 복구"
이제 main 브랜치는 원래 상태로 돌아가고, 삭제된 커밋에서 작업했던 내용은 new-branch
에서 이어갈 수 있습니다.
2. git reset --hard
(하드 리셋)
하드 리셋은 지정한 커밋 이후의 커밋을 삭제하는 것뿐만 아니라 모든 변경 사항도 삭제합니다.
git reset --hard 3c2d1a5
이렇게 하면 이후의 커밋이 모두 제거되며, 변경 사항도 완전히 사라집니다.
* (HEAD -> main) 3c2d1a5 '네 번째 커밋'
* 2b1e7f3 '세 번째 커밋'
* 1a9c8d4 '두 번째 커밋'
* 0f7b6a2 '첫 번째 커밋'
⚠ 주의: git reset --hard
를 실행하면 워킹 디렉토리의 변경 사항도 삭제되므로, 반드시 신중하게 사용해야 합니다.
Git Revert로 커밋 원래대로 복구하기
git revert
는 이전 커밋의 변경 사항을 취소하는 새로운 커밋을 생성하는 명령어입니다. 즉, 기존 커밋을 제거하는 것이 아니라 "이전 커밋을 무효화하는 새로운 커밋"을 만드는 방식으로 작업 이력을 유지하면서 변경 사항을 되돌릴 수 있습니다.
1. git reset
과 git revert
의 차이
명령어 | 동작 방식 | 기존 커밋 기록 유지 여부 | 협업 시 안전 여부 |
---|---|---|---|
git reset |
브랜치 포인터를 특정 커밋으로 되돌림 | ❌ 삭제됨 | ⚠️ 협업 시 주의 |
git revert |
지정한 커밋의 변경 사항을 취소하는 새로운 커밋 생성 | ✅ 유지됨 | ✅ 안전 |
2. git revert
사용 방법
예를 들어, 다음과 같은 커밋 기록이 있다고 가정해봅시다.
* (HEAD -> main) 8f2e1b6 '나쁜 커밋 만들었음'
* 4a3b7d9 '기능 추가'
* 3c2d1a5 '버그 수정'
* 2b1e7f3 '초기 설정'
'나쁜 커밋 만들었음'
을 취소하려면 다음 명령어를 실행합니다.
git revert HEAD
이제 새로운 커밋이 생성됩니다.
* (HEAD -> main) a9c8d7f 'Revert "나쁜 커밋 만들었음"'
* 8f2e1b6 '나쁜 커밋 만들었음'
* 4a3b7d9 '기능 추가'
* 3c2d1a5 '버그 수정'
* 2b1e7f3 '초기 설정'
이처럼 기존 커밋(8f2e1b6
)은 남아있지만, 새로운 커밋(a9c8d7f
)이 생성되어 해당 변경 사항을 무효화합니다.
3. 특정 커밋 되돌리기
HEAD~1
이 아니라 더 이전의 특정 커밋을 되돌릴 수도 있습니다.
git revert 4a3b7d9
이렇게 하면 '기능 추가'
커밋의 변경 사항을 취소하는 새로운 커밋이 생성됩니다.
4. 협업에서 git revert
가 안전한 이유
만약 여러 개발자가 공유하는 저장소에서 git reset
을 사용하면, 다른 사람들의 작업과 충돌이 발생할 수 있습니다. 하지만 git revert
는 기존 기록을 유지하면서 변경 사항만 되돌리므로 충돌 없이 안전하게 사용할 수 있습니다.
즉, 혼자 작업할 때는 git reset
, 팀과 협업할 때는 git revert
가 더 적합합니다.
1. 프로젝트 준비
우선 제공된 연습용 Git 저장소를 클론해야 합니다.
git clone <저장소 URL>
cd yesterday-exercise
이제 lyrics.txt
파일이 포함된 프로젝트 폴더가 생성됩니다.git log --oneline
을 실행하면 스크램블 에그(원래 가사 버전)와 예스터데이(수정된 가사 버전)에 관련된 여러 커밋이 보일 것입니다.
2. 특정 커밋 체크아웃 및 브랜치 생성
1️⃣ 초기 가사 버전(스크램블 에그)으로 이동
먼저 git log --oneline
을 실행해 "원래 가사 끝"
커밋을 찾고, 해당 커밋으로 체크아웃합니다.
git checkout <스크램블 에그 커밋 해시>
이제 HEAD가 해당 커밋을 가리키고 있으며, 분리된 HEAD(detached HEAD) 상태가 됩니다.
2️⃣ 스크램블 에그 브랜치 생성
이 상태에서 새 브랜치를 만들어 현재 커밋을 기준으로 작업할 수 있도록 합니다.
git switch -c scrambled-egg
이제 scrambled-egg
브랜치에서 과거 가사 버전을 유지할 수 있습니다.
3. 변경 사항 되돌리기
1️⃣ 마스터 브랜치로 돌아가기
git switch master
이제 lyrics.txt
의 최신 가사가 다시 나타납니다.
2️⃣ 가사를 삭제하고 되돌리기
파일의 모든 내용을 삭제한 후 Git 명령어를 사용하여 원래 상태로 복구해야 합니다.
git restore lyrics.txt
또는 기존 git checkout
을 활용할 수도 있습니다.
git checkout HEAD -- lyrics.txt
이제 lyrics.txt
파일이 원래대로 복구됩니다.
4. 패러디 가사 추가 후 되돌리기
1️⃣ 패러디 가사 추가 및 커밋lyrics.txt
파일에 새로운 패러디 가사를 추가하고, 이를 커밋합니다.
git add lyrics.txt
git commit -m "404 가사 시작"
다시 한 번 패러디 가사를 추가하고, 커밋합니다.
git add lyrics.txt
git commit -m "404 가사 끝"
2️⃣ 커밋 취소 및 새로운 브랜치로 이동
마스터 브랜치에서 패러디 가사 커밋을 제거하고 싶다면 리셋(reset) 명령어를 사용합니다.
git reset <패러디 가사 추가 전 커밋 해시>
⚠️ 주의: --hard
옵션을 사용하면 변경 사항도 삭제되므로, 여기서는 사용하지 않습니다.
이제 커밋은 삭제되었지만, 파일의 변경 사항은 그대로 남아 있습니다.
3️⃣ 새 브랜치 404
생성 및 커밋
이제 변경 사항을 새로운 브랜치에 저장하고 싶다면 다음과 같이 실행합니다.
git switch -c 404
git add lyrics.txt
git commit -m "404 패러디 가사 추가"
이제 404
브랜치에서는 패러디 가사가 유지되고, 마스터 브랜치로 돌아가면 원래의 예스터데이 가사가 남아있게 됩니다.
git switch master
📝 정리
Git 명령어 | 용도 |
---|---|
git restore <파일> |
커밋되지 않은 변경 사항 되돌리기 |
git reset <커밋 해시> |
커밋 삭제(변경 사항 유지) |
git checkout <커밋 해시> |
특정 커밋 체크아웃(분리된 HEAD) |
git switch -c <브랜치> |
새로운 브랜치 생성 및 전환 |
'강의 > Git & Github 실무 활용 완벽 가이드' 카테고리의 다른 글
GitHub 기본 개념과 실전 사용법 정리 (0) | 2025.02.12 |
---|---|
Git Stash: 변경 사항 임시 저장과 복원 (0) | 2025.02.05 |
Git diff 사용법: 변경 사항 비교와 추적 (0) | 2025.02.05 |
Git 브랜치 병합과 충돌, 해결 (0) | 2025.02.05 |
Git 브랜치 개념과 활용 (0) | 2025.02.03 |