현재 브랜치에서 특정 Git 커밋을 취소하고 제거하는 방법

GitBeginner
지금 연습하기

소개

이 랩에서는 Git 커밋 기록을 관리하는 방법을 배우게 됩니다. git reset을 사용하여 변경 사항을 되돌리고, git revert를 사용하여 공개된 커밋을 안전하게 되돌리고, 인터랙티브 리베이스 (interactive rebase) 를 사용하여 브랜치에서 특정 커밋을 제거하는 연습을 하게 됩니다. 또한 제거된 커밋을 복구하기 위해 reflog를 사용하는 방법도 배우게 됩니다. 이러한 기술들은 깨끗하고 이해하기 쉬운 프로젝트 기록을 유지하는 데 필수적입니다.

이것은 가이드 실험입니다. 학습과 실습을 돕기 위한 단계별 지침을 제공합니다.각 단계를 완료하고 실무 경험을 쌓기 위해 지침을 주의 깊게 따르세요. 과거 데이터에 따르면, 이것은 중급 레벨의 실험이며 완료율은 69%입니다.학습자들로부터 100%의 긍정적인 리뷰율을 받았습니다.

커밋 기록 검사

기록을 수정하기 전에 먼저 기록을 보는 방법을 알아야 합니다. git log 명령이 이를 위한 주요 도구입니다. 이 랩을 위해 실제 프로젝트 기록을 시뮬레이션하기 위해 여러 커밋으로 Git 저장소가 초기화되었습니다.

커밋 기록을 검사하는 것부터 시작하겠습니다. 각 커밋을 한 줄에 표시하기 위해 --oneline 플래그를 사용하고, 브랜치와 병합을 시각화하는 데 유용한 그래프로 커밋 기록을 표시하기 위해 --graph를 사용합니다.

터미널에서 다음 명령을 실행하십시오.

git log --oneline --graph

가장 최근 커밋이 맨 위에 있는, 여러분을 위해 생성된 다섯 개의 커밋 목록이 표시될 것입니다. 각 줄은 고유한 커밋 해시 (짧은 버전) 와 커밋 메시지를 보여줍니다.

* 7d3d24a (HEAD -> master) chore: Add last-commit file
* 8a9f1b3 docs: Update documentation in file1
* c2e4d6f fix: Add a temporary file that should be removed
* 5e1a3b2 feat: Add file2.txt
* 1b4c0a9 feat: Add file1.txt

참고: 커밋 해시는 위 예시와 다를 수 있습니다. 각 해시는 고유하므로 이는 예상된 결과입니다.

잠시 시간을 내어 기록을 검토하십시오. 다음 단계에서 이 커밋들을 조작하게 됩니다.

git reset으로 마지막 커밋 되돌리기

때로는 커밋을 하고 즉시 실수를 알아차릴 때가 있습니다. git reset 명령은 이러한 시나리오에 완벽합니다. 현재 브랜치의 HEAD 포인터를 이전 커밋으로 이동시켜 하나 이상의 커밋을 효과적으로 "되돌릴" 수 있습니다.

--soft 옵션을 사용할 것입니다. 이 옵션은 커밋은 되돌리지만 해당 커밋의 변경 사항은 스테이징 영역 (인덱스) 에 그대로 둡니다. 이는 변경 사항을 다시 커밋하고 싶을 때, 예를 들어 다른 메시지로 커밋하거나 다른 변경 사항과 결합하고 싶을 때 유용합니다.

가장 최근 커밋인 "chore: Add last-commit file"을 되돌려 보겠습니다.

git reset --soft HEAD~1

여기서 HEAD~1은 현재 HEAD 바로 이전 커밋을 참조합니다.

이제 저장소의 상태를 확인하십시오.

git status

last-commit.txt가 "커밋할 변경 사항" 아래에 나열된 것을 볼 수 있습니다. 이는 커밋 자체는 되돌려졌지만 파일 변경 사항은 여전히 스테이징되어 있음을 의미합니다.

On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	new file:   last-commit.txt

마지막으로 로그를 다시 확인하여 커밋이 기록에서 사라졌는지 확인하십시오.

git log --oneline --graph
* 8a9f1b3 (HEAD -> master) docs: Update documentation in file1
* c2e4d6f fix: Add a temporary file that should be removed
* 5e1a3b2 feat: Add file2.txt
* 1b4c0a9 feat: Add file1.txt

보시다시피 마지막 커밋은 로그에서 제거되었지만 작업은 스테이징 영역에 안전하게 대기 중입니다.

git revert으로 커밋 되돌리기

git reset은 로컬 변경 사항에 유용하지만, 기록을 다시 작성하므로 이미 다른 사람과 커밋을 공유했다면 문제가 될 수 있습니다. 공개 브랜치에서 변경 사항을 되돌리는 더 안전한 방법은 git revert입니다. 이 명령은 지정된 커밋의 변경 사항에 대한 역변환을 적용하는 새로운 커밋을 생성합니다.

먼저 이전 단계의 변경 사항을 다시 커밋하여 작업 디렉토리를 정리하겠습니다.

git commit -m "chore: Add last-commit file again"

이제 file2.txt를 추가한 커밋을 되돌리고 싶다고 가정해 봅시다. 이 커밋은 기록에서 더 이전입니다. 이를 되돌릴 것입니다. HEAD에 대한 상대적 위치로 참조할 수 있습니다. 1 단계의 로그를 보면 "feat: Add file2.txt"는 위에서 네 번째 커밋이므로 HEAD~3으로 참조할 수 있습니다.

revert 명령을 실행하십시오.

git revert HEAD~3

그러면 기본 텍스트 편집기 (기본값은 vim) 가 열리고 "Revert 'feat: Add file2.txt'"와 같은 미리 채워진 커밋 메시지가 표시됩니다. 기본 메시지를 수락하려면 파일을 저장하고 닫기만 하면 됩니다.

vim에서 :wq를 입력하고 Enter를 눌러 저장하고 종료하십시오.

이제 로그를 다시 확인하십시오.

git log --oneline --graph

맨 위에 "Revert 'feat: Add file2.txt'"라는 새 커밋이 표시될 것입니다.

* 1e2d3f4 (HEAD -> master) Revert "feat: Add file2.txt"
* 7d3d24a chore: Add last-commit file again
* 8a9f1b3 docs: Update documentation in file1
* c2e4d6f fix: Add a temporary file that should be removed
* 5e1a3b2 feat: Add file2.txt
* 1b4c0a9 feat: Add file1.txt

원본 커밋은 여전히 기록에 있지만, 해당 변경 사항은 새 revert 커밋에 의해 되돌려졌습니다. 디렉토리의 파일을 나열하여 이를 확인할 수 있습니다.

ls

file2.txt가 더 이상 존재하지 않는 것을 알 수 있습니다.

인터랙티브 리베이스로 커밋 제거하기

브랜치 중간의 커밋을 제거하는 것과 같이 더 복잡한 히스토리 조작을 위해서는 인터랙티브 리베이스 (git rebase -i) 를 사용할 수 있습니다. 이것은 커밋 히스토리를 다시 작성하는 매우 강력한 명령이므로, 특히 다른 개발자와 공유된 브랜치에서는 주의해서 사용해야 합니다.

우리의 목표는 "fix: Add a temporary file that should be removed" 메시지를 가진 커밋을 제거하는 것입니다. 현재 로그를 보면 이 커밋은 이제 HEAD~3입니다.

인터랙티브 리베이스 프로세스를 시작하십시오.

git rebase -i HEAD~4

이 명령은 마지막 4 개의 커밋 목록과 함께 텍스트 편집기 (기본값은 vim) 를 열 것입니다.

pick fd5a181 fix: Add a temporary file that should be removed
pick 5f27a4d docs: Update documentation in file1
pick 284be6f chore: Add last-commit file again
pick 8a460c5 Revert "feat: Add file2.txt"

## Rebase 9403080..8a460c5 onto 9403080 (4 commands)
#
## Commands:
## p, pick <commit> = use commit
## d, drop <commit> = remove commit
## ...

커밋을 제거하려면 "fix: Add a temporary file that should be removed"가 포함된 줄의 pick 단어를 drop (또는 d) 으로 변경하십시오.

이것을:

pick fd5a181 fix: Add a temporary file that should be removed

이것으로 변경하십시오:

drop fd5a181 fix: Add a temporary file that should be removed

vim 에서 i를 눌러 삽입 모드로 들어가 변경한 다음 Esc를 눌러 삽입 모드를 종료합니다. :wq를 입력하고 Enter를 눌러 저장하고 종료하십시오. Git 은 나머지 커밋을 새 히스토리 위에 다시 적용할 것입니다.

결과를 확인하기 위해 로그를 확인하십시오.

git log --oneline --graph

"나쁜" 커밋이 이제 히스토리에서 사라졌습니다.

* a5b4c3d (HEAD -> master) chore: Add last-commit file again
* f9e8d7c docs: Update documentation in file1
* 1e2d3f4 Revert "feat: Add file2.txt"
* 5e1a3b2 feat: Add file2.txt
* 1b4c0a9 feat: Add file1.txt

또한 디렉토리의 파일도 확인하십시오. bad-commit-file.txt 파일이 제거되었습니다.

ls

git reflog으로 제거된 커밋 복원하기

실수로 커밋을 제거했다면 어떻게 해야 할까요? Git 은 HEAD 포인터에 대한 모든 변경 사항을 reflog라는 특수 로그에 기록합니다. 이것이 여러분의 안전망입니다. 이를 사용하여 손실된 커밋을 찾고 복원할 수 있습니다.

reflog 를 확인하여 방금 다시 작성한 히스토리를 찾아봅시다.

git reflog

수행한 작업 목록이 표시됩니다. rebase (finish): returning to refs/heads/master라고 표시된 줄을 찾으십시오. 바로 아래 항목, 아마도 HEAD@{1}은 리베이스 이전의 브랜치 상태를 나타냅니다.

a5b4c3d (HEAD -> master) HEAD@{0}: rebase (finish): returning to refs/heads/master
1e2d3f4 HEAD@{1}: rebase (start): checkout HEAD~3
...

git reset --hard를 사용하여 브랜치를 이 이전 상태로 복원할 수 있습니다. 이 명령은 파괴적이므로 커밋되지 않은 변경 사항을 모두 삭제하므로 주의해서 사용하십시오.

이 경우 HEAD@{1}인 리베이스 이전 상태로 브랜치를 리셋해 봅시다.

git reset --hard HEAD@{1}

리베이스가 시작되기 전의 커밋으로 HEAD가 이동했음을 확인하는 메시지가 표시됩니다.

HEAD is now at 1e2d3f4 Revert "feat: Add file2.txt"

이제 마지막으로 로그를 확인하십시오.

git log --oneline --graph

리베이스 이전의 히스토리가 표시되어야 합니다.

* f461400 (HEAD -> master) Revert "feat: Add file2.txt"
* acea45c chore: Add last-commit file again
* c04b3f5 docs: Update documentation in file1
* 9403080 feat: Add file2.txt
* ee39412 feat: Add file1.txt

"fix: Add a temporary file that should be removed" 커밋은 여전히 존재하지 않는다는 점에 유의하십시오. 이것이 올바른 것입니다! git reset --hard HEAD@{1} 명령은 인터랙티브 리베이스가 시작되기 전의 상태로 복원한 것이지, 커밋을 제거하기 전으로 복원한 것이 아닙니다. 인터랙티브 리베이스는 해당 원치 않는 커밋을 히스토리에서 성공적으로 제거했습니다. ls를 실행하여 bad-commit-file.txt가 여전히 존재하지 않는지 확인할 수 있습니다. reflog는 Git 에서 실수로부터 복구하는 데 매우 유용한 도구입니다.

요약

이 실습에서는 Git 커밋 히스토리를 관리하는 실용적인 기법을 배웠습니다. git log로 히스토리를 검사하는 것부터 시작했습니다. 그런 다음 git reset --soft를 사용하여 커밋을 되돌리고, git revert로 변경 사항을 안전하게 되돌리고, 강력한 git rebase -i 명령으로 특정 커밋을 제거하는 연습을 했습니다. 마지막으로 히스토리에서 제거된 커밋을 복원하기 위한 안전망으로 git reflog를 사용하는 방법을 배웠습니다. 이러한 기술은 깨끗하고 관리 가능한 프로젝트 히스토리를 유지하는 데 필수적입니다.