- 로컬 변경 사항 되돌리기
- 커밋된 로컬 변경 사항 되돌리기
- 원격 변경 내용을 변경 내역을 변경하지 않고 취소
- 원격 변경을 변경 내역을 변경하면서 취소
- 새로운 교체 커밋으로 커밋 되돌리기
git revert
와git reset
의 차이점- 변경 내용 스테이징 해제
- 관련 주제
변경 사항 되돌리기
Git은 변경 사항을 되돌리는 옵션을 제공합니다. Git workflow의 어떤 지점에서든 변경 사항을 되돌릴 수 있습니다.
변경 사항을 되돌리는 방법은 다음과 같이 달라집니다.
- 로컬 컴퓨터에만 있는 경우
- GitLab.com과 같은 Git 서버에 저장된 경우
로컬 변경 사항 되돌리기
원격 저장소에 변경 사항을 푸시하지 않은 경우, Git에서 한 작업은 로컬 개발 환경에서만 있는 변경 사항입니다.
취소되지 않은 로컬 변경 사항
변경을 만들었지만 아직 스테이징하지 않은 경우 작업을 되돌릴 수 있습니다.
-
파일이 스테이징되지 않았는지(
git add <file>
을 사용하지 않았는지)git status
를 실행하여 확인합니다.$ git status On branch main Your branch is up-to-date with 'origin/main'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: <file> no changes added to commit (use "git add" and/or "git commit -a")
-
옵션을 선택하여 변경 사항을 되돌립니다:
-
로컬 변경 사항 덮어쓰기:
git checkout -- <file>
-
모든 파일의 로컬 변경 사항 영구적으로 삭제:
git reset --hard
-
스테이징된 로컬 변경 사항
파일을 스테이징했다면, 이를 취소할 수 있습니다.
-
파일이 스테이징되었는지(
git add <file>
을 사용했는지)git status
를 실행하여 확인합니다.$ git status On branch main Your branch is up-to-date with 'origin/main'. Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: <file>
-
옵션을 선택하여 변경 사항을 되돌립니다:
-
파일의 스테이징 취소하지만 변경 사항 유지:
git restore --staged <file>
-
모든 변경 사항을 취소하지만 변경 사항 유지:
git reset
-
파일을 현재 커밋(HEAD)으로 스테이징 취소:
git reset HEAD <file>
-
모든 것을 영구적으로 취소:
git reset --hard
-
커밋된 로컬 변경 사항 되돌리기
로컬 저장소에 커밋하면(git commit
), Git은 변경 사항을 기록합니다. 아직 원격 저장소에 푸시하지 않았기 때문에 변경 사항이 공개되지 않았습니다(또는 다른 개발자와 공유되지 않았습니다). 이 시점에서 변경 사항을 되돌릴 수 있습니다.
커밋된 로컬 변경 사항 스테이징되지 않은 상태로 되돌리기
커밋 히스토리를 유지하면서 커밋을 되돌릴 수 있습니다.
이 예시에서는 A-B-C-D-E
다섯 개의 커밋을 순서대로 생성한 상황입니다. 되돌리고자 하는 커밋은 B
입니다.
- 되돌리려는 커밋의 SHA를 찾습니다. 커밋 로그를 보려면
git log
를 입력합니다. -
옵션을 선택하여 변경 사항을 되돌립니다:
-
커밋
B
가 도입한 추가 및 삭제 사항을 교체:git revert <commit-B-SHA>
-
커밋
B
가 도입한 특정 파일 또는 디렉토리의 변경 사항을 되돌리지만 스테이징 상태로 유지:git checkout <commit-B-SHA> <file>
-
커밋
B
가 도입한 특정 파일 또는 디렉토리의 변경 사항을 되돌리지만 스테이징하지 않은 상태로 유지:git reset <commit-B-SHA> <file>
-
여러 커밋을 되돌리기
여러 커밋에서 복구할 수 있습니다. 예를 들어, 브랜치에서 A-B-C-D
를 커밋했고, 그 후 C
와 D
가 잘못되었다는 것을 깨달았다면 아래와 같이 복구할 수 있습니다.
여러 올바르지 않은 커밋에서 복구하는 방법:
-
올바른 마지막 커밋을 확인합니다. 이 예시에서는
B
입니다.git checkout <commit-B-SHA>
-
새 브랜치를 생성합니다.
git checkout -b new-path-of-feature
-
변경을 추가하고 푸시하고 커밋합니다.
이제 커밋은 A-B-C-D-E
입니다.
또는 GitLab을 사용하여 새 머지 요청으로 해당 커밋을 cherry-pick할 수 있습니다.
참고:
다른 해결책은 B
로 되돌리고 E
로 커밋하는 것입니다. 그러나 이러한 해결책은 로컬에서 다른 개발자가 가지고 있는 것과 충돌하는 A-B-E
가 되므로 결과가 충돌합니다.
히스토리 수정이 포함된 스테이징된 로컬 변경 사항
다음 섹션에서는 Git 히스토리를 다시 작성하는 작업을 문서화합니다. 자세한 내용은 리베이스 과정을 참조하세요.
특정 커밋 삭제
특정 커밋을 삭제할 수 있습니다. 예를 들어 A-B-C-D
와 같이 커밋했고 커밋 B
를 삭제하고 싶다면 아래와 같이 범위를 재정렬할 수 있습니다.
-
현재 커밋
D
에서B
까지 재정렬하세요.git rebase -i A
커밋 목록이 편집기에 표시됩니다.
- 커밋
B
앞에 있는pick
을drop
으로 바꿉니다. - 그 외의 커밋에 대해서는 기본값인
pick
을 유지합니다. - 저장하고 편집기를 닫습니다.
특정 커밋 수정
특정 커밋을 수정할 수 있습니다. 예를 들어 A-B-C-D
와 같이 커밋했고 커밋 B
에서 도입된 내용을 수정하고자 한다면 아래와 같이 범위를 재정렬할 수 있습니다.
-
현재 커밋
D
에서B
까지 재정렬하세요.git rebase -i A
커밋 목록이 편집기에 표시됩니다.
- 커밋
B
앞에 있는pick
을edit
으로 바꿉니다. - 그 외의 커밋에 대해서는 기본값인
pick
을 유지합니다. - 저장하고 편집기를 닫습니다.
-
편집기로 파일을 열고 편집한 뒤 변경 사항을 커밋하세요:
git commit -a
취소된 작업 다시 하기
이전 로컬 커밋을 되돌릴 수 있습니다. 그러나 이전 커밋이 모두 사용 가능한 것은 아니기 때문에 Git은 정기적으로 브랜치나 태그로 도달하지 못하는 커밋을 정리합니다.
리포지토리 기록을 보고 이전 커밋을 추적하기 위해 git reflog show
를 실행하세요. 예를 들어:
$ git reflog show
# 예시 출력:
b673187 HEAD@{4}: merge 6e43d5987921bde189640cc1e37661f7f75c9c0b: Merge made by the 'recursive' strategy.
eb37e74 HEAD@{5}: rebase -i (finish): returning to refs/heads/master
eb37e74 HEAD@{6}: rebase -i (pick): Commit C
97436c6 HEAD@{7}: rebase -i (start): checkout 97436c6eec6396c63856c19b6a96372705b08b1b
...
88f1867 HEAD@{12}: commit: Commit D
97436c6 HEAD@{13}: checkout: moving from 97436c6eec6396c63856c19b6a96372705b08b1b to test
97436c6 HEAD@{14}: checkout: moving from master to 97436c6
05cc326 HEAD@{15}: commit: Commit C
6e43d59 HEAD@{16}: commit: Commit B
이 출력은 리포지토리 기록을 보여줍니다.
- 커밋 SHA.
-
HEAD
를 변경한 행동이 얼마나 이루어졌는지 (HEAD@{12}
는 12번의HEAD
변경 작업 전에 만들어진 커밋입니다). - 수행된 작업, 예를 들어: 커밋, 리베이스, 머지.
-
HEAD
를 변경한 작업에 대한 설명.
원격 변경 내용을 변경 내역을 변경하지 않고 취소
원격 저장소에서 변경 내용을 되돌리려면 변경을 원하는 새 커밋을 만들면 됩니다. 이 프로세스를 따라야 하며 변경 내역을 보존하고 명확한 타임라인과 개발 구조를 제공합니다. 그러나 여러 다른 개발자가 작업하는 기반 브랜치로 병합된 경우에만 해당 프로시저가 필요합니다.
특정 커밋 B
에서 도입된 변경을 되돌리려면:
git revert B
원격 변경을 변경 내역을 변경하면서 취소
원격 변경을 취소하고 변경 내역을 변경할 수 있습니다.
업데이트된 변경 내역에서도 이전 커밋에는 여전히 커밋 SHA로 액세스할 수 있습니다. 이는 자동으로 분리된 커밋의 모든 정리가 수행되거나 수동으로 정리가 실행될 때까지의 경우입니다. 심지어 정리가 이루어져도 여전히 그들을 가리키는 참조가 있으면 이전 커밋이 제거되지 않을 수 있습니다.
히스토리 변경이 허용되는 경우
공용 브랜치나 다른 개발자가 사용할 수 있는 브랜치에서 작업할 때 히스토리를 변경해서는 안됩니다.
GitLab와 같이 큰 오픈 소스 저장소에 기여할 때 나중에 리뷰 후에 커밋을 하나로 압축할 수 있습니다.
대상 브랜치에서 당신의 브랜치의 커밋을 하나로 압축하기 위해 병합할 때 git merge --squash
를 사용할 수 있습니다.
참고: 기본 브랜치나 공유 브랜치의 커밋 히스토리를 변경하지 마세요.
히스토리 변경 방법
병합 요청의 브랜치는 공개 브랜치이며 다른 개발자가 사용할 수 있습니다. 그러나 프로젝트 규칙이 리뷰가 완료된 후 대상 브랜치에서 표시된 커밋의 수를 줄이기 위해 git rebase
를 사용하도록 요구할 수 있습니다.
git rebase -i
를 사용하여 히스토리를 수정, 압축 및 커밋을 삭제할 수 있습니다.
#
# 명령:
# p, pick = 커밋 사용
# r, reword = 커밋 사용, 그러나 커밋 메시지 편집
# e, edit = 커밋 사용, 그러나 수정을 중단
# s, squash = 커밋 사용, 그러나 직전 커밋과 병합
# f, fixup = "squash"와 유사하나, 이 커밋의 로그 메시지는 폐기
# x, exec = 명령 실행 (라인의 나머지) 셸을 사용하여
# d, drop = 커밋 제거
#
# 이러한 라인은 재정렬될 수 있으며 위에서 아래로 실행됩니다.
#
# 라인을 제거하면 해당 커밋이 손실됩니다.
#
# 그러나 모든 것을 제거하면 리베이스가 중단됩니다.
#
# 빈 커밋은 주석 처리됩니다.
참고: 리베이스를 중단하려면 편집기를 닫지 마세요. 대신 모든 주석이 달린 줄을 제거하고 저장하세요.
공용 및 원격 브랜치에서 git rebase
를 신중하게 사용하세요.
원격 저장소에 밀기 전에 로컬에서 실험을 해보세요.
# commit-id에서 HEAD(현재 커밋)까지 히스토리 수정
git rebase -i commit-id
텍스트 삭제
- GitLab 17.1에서 도입되었으며
rewrite_history_ui
라는 플래그로 사용 안 함 상태로 설정됨.- GitLab 17.2에서 GitLab.com에서 사용하도록 설정됨.
- GitLab 17.3에서 자체 관리 및 GitLab 전용에서 사용하도록 설정됨.
실수로 커밋된 민감하거나 비밀스런 정보를 영구적으로 삭제하여 저장소의 히스토리에서 더 이상 액세스할 수 없게 합니다.
문자열 목록을 ***REMOVED***
로 대체합니다.
또한, 특정 파일을 저장소에서 완전히 삭제하려면 블롭 제거를 참조하세요.
필수 조건:
- 프로젝트에 대한 소유자 역할이 있어야 합니다.
저장소에서 텍스트를 삭제하는 방법:
- 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
- 설정 > 저장소를 선택합니다.
- 저장소 유지관리를 확장합니다.
- 텍스트 삭제를 선택합니다.
- 창에서 텍스트를 입력합니다. 정규식과 glob 패턴을 사용할 수 있습니다.
- 일치하는 문자열 삭제를 선택합니다.
- 확인 대화상자에서 프로젝트 경로를 입력합니다.
- 예, 일치하는 문자열을 삭제를 선택합니다.
- 왼쪽 사이드바에서 설정 > 일반을 선택합니다.
- 고급을 확장합니다.
- 하우스키퍼 실행을 선택합니다.
커밋을 제거하여 커밋 되돌리기
-
마지막 커밋을 되돌린 후 모든 것을 스테이징 영역으로 되돌립니다:
git reset --soft HEAD^
-
파일을 추가하고 커밋 메시지를 변경합니다:
git commit --amend -m "새 메시지"
-
마지막 변경 사항을 되돌리고 다른 변경 사항을 모두 제거하려면, 아직 푸쉬하지 않은 경우:
git reset --hard HEAD^
-
마지막 변경 사항을 되돌리고 마지막 2개의 커밋을 제거하려면, 아직 푸쉬하지 않은 경우:
git reset --hard HEAD^^
Git reset 샘플 워크플로우
다음은 일반적인 Git reset 워크플로우입니다:
- 파일을 편집합니다.
-
브랜치의 상태를 확인합니다:
git status
-
잘못된 커밋 메시지로 변경 사항을 브랜치에 커밋합니다:
git commit -am "kjkfjkg"
-
Git 로그를 확인합니다:
git log
-
올바른 커밋 메시지로 커밋을 수정합니다:
git commit --amend -m "새 댓글 추가됨"
-
다시 Git 로그를 확인합니다:
git log
-
브랜치를 소프트 리셋합니다:
git reset --soft HEAD^
-
다시 Git 로그를 확인합니다:
git log
-
원격 브랜치에서 브랜치의 업데이트를 가져옵니다:
git pull origin <브랜치>
-
브랜치의 변경 사항을 원격으로 푸시합니다:
git push origin <브랜치>
새로운 교체 커밋으로 커밋 되돌리기
git revert <commit-sha>
git revert
와 git reset
의 차이점
-
git reset
명령어는 커밋을 제거합니다.git revert
명령어는 변경 사항을 제거하지만 커밋은 남겨둡니다. -
git revert
명령어는 안전합니다. 왜냐하면 되돌릴 수 있기 때문입니다.
# 변경된 파일
git commit -am "버그 도입"
git revert HEAD
# 변경 내용을 되돌리는 새로운 커밋 생성
# 이제 되돌린 커밋을 다시 적용하려고 합니다
git log # 되돌린 커밋의 해시 가져오기
git revert <revert 커밋 해시>
# 되돌린 커밋이 다시 생겨납니다 (다시 새로운 커밋이 생성됨)
변경 내용 스테이징 해제
Git에서 파일을 _스테이징_하면 커밋을 준비하기 위해 파일의 변경 사항을 추적하도록 지시합니다. 파일의 변경 사항을 무시하고 다음 커밋에 포함시키고 싶지 않다면 파일을 _스테이징 해제_하세요.
파일 스테이징 해제
-
스테이징에서 파일을 제거하지만 변경 내용은 유지:
git reset HEAD <file>
-
마지막 세 개의 커밋을 스테이징에서 제거:
git reset HEAD^3
-
HEAD로부터 특정 파일의 변경 내용을 스테이징에서 제거:
git reset <filename>
파일을 스테이징에서 제거한 후, 파일을 변경 내용 이전의 상태로 되돌리려면:
git checkout -- <file>
파일 제거
-
디스크와 저장소에서 파일을 제거하려면
git rm
을 사용하세요. 디렉토리를 제거하려면-r
플래그를 사용하세요:git rm '*.txt' git rm -r <dirname>
-
디스크에 파일을 유지하고 저장소에서만 삭제하려면(예를 들어
.gitignore
에 추가하려는 파일)--cache
플래그를 사용하여rm
명령어를 사용하세요:git rm <filename> --cache
이러한 명령은 파일을 현재 브랜치에서 제거하지만 저장소의 이력에서는 삭제하지 않습니다. 파일의 모든 흔적을 완전히 삭제하려면 과거와 현재 모두 저장소에서 완전히 제거하려면 블랍 제거를 참조하세요.