InfoGrab Docs

변경 사항 되돌리기 및 취소

요약

Git 작업에는 실험과 반복이 포함됩니다. 실수로 커밋한 내용을 복구하고, 민감한 데이터를 제거하고, 잘못된 병합을 수정하고, 깔끔한 저장소 히스토리를 유지하세요. 변경 사항을 원격 저장소에 푸시할 때까지 Git에서 변경한 내용은 로컬 개발 환경에만 있습니다.

Git 작업에는 실험과 반복이 포함됩니다. 개발 중에 실수가 발생하며 때로는 변경 사항을 되돌려야 합니다. Git은 Git 워크플로의 어느 지점에서든 변경 사항을 취소하는 기능으로 코드 히스토리를 제어합니다.

실수로 커밋한 내용을 복구하고, 민감한 데이터를 제거하고, 잘못된 병합을 수정하고, 깔끔한 저장소 히스토리를 유지하세요. 다른 사람들과 협업할 때 새로운 되돌리기 커밋으로 투명성을 유지하거나 공유하기 전에 로컬에서 작업을 리셋합니다. 사용할 방법은 변경 사항이 다음 중 어디에 있는지에 따라 다릅니다:

  • 로컬 컴퓨터에만 있는 경우.
  • GitLab.com과 같은 Git 서버에 원격으로 저장된 경우.

로컬 변경 사항 취소#

변경 사항을 원격 저장소에 푸시할 때까지 Git에서 변경한 내용은 로컬 개발 환경에만 있습니다.

Git에서 파일을 _스테이징_하면 커밋을 준비하기 위해 파일 변경 사항을 추적하도록 Git에 지시합니다. 파일 변경 사항을 무시하고 다음 커밋에 포함하지 않으려면 파일을 _언스테이징_합니다.

스테이징되지 않은 로컬 변경 사항 되돌리기#

아직 스테이징되지 않은 로컬 변경 사항을 취소하려면:

  1. git status를 실행하여 파일이 스테이징되지 않은 것을 확인합니다(git add <file>을 사용하지 않은 것):

    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")
    
  2. 옵션을 선택하고 변경 사항을 취소합니다:

    • 로컬 변경 사항을 덮어쓰려면:

      git checkout -- <file>
      
    • 모든 파일의 로컬 변경 사항을 영구적으로 취소하려면:

      git reset --hard
      

스테이징된 로컬 변경 사항 되돌리기#

이미 스테이징된 로컬 변경 사항을 취소할 수 있습니다. 다음 예시에서는 파일이 스테이징에 추가되었지만 커밋되지 않았습니다:

  1. 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>
    
  2. 옵션을 선택하고 변경 사항을 취소합니다:

    • 변경 사항을 유지하면서 파일을 언스테이징하려면:

      git restore --staged <file>
      
    • 변경 사항을 유지하면서 모든 것을 언스테이징하려면:

      git reset
      
    • 파일을 현재 커밋(HEAD)으로 언스테이징하려면:

      git reset HEAD <file>
      
    • 모든 것을 영구적으로 취소하려면:

      git reset --hard
      

로컬 커밋 취소#

git commit으로 로컬 저장소에 커밋하면 Git이 변경 사항을 기록합니다. 아직 원격 저장소에 푸시하지 않았으므로 변경 사항이 공개되거나 다른 사람들과 공유되지 않았습니다. 이 시점에서 변경 사항을 취소할 수 있습니다.

히스토리를 변경하지 않고 커밋 되돌리기#

커밋 히스토리를 유지하면서 커밋을 되돌릴 수 있습니다.

이 예시에서는 순서대로 커밋된 5개의 커밋 A, B, C, D, E를 사용합니다: A-B-C-D-E. 취소하려는 커밋은 B입니다.

  1. 되돌릴 커밋의 커밋 SHA를 찾습니다. git log 명령을 사용하여 커밋 로그를 확인합니다.

  2. 옵션을 선택하고 변경 사항을 취소합니다:

    • 커밋 B에서 도입된 변경 사항을 되돌리려면:

      git revert <commit-B-SHA>
      
    • 커밋 B의 단일 파일 또는 디렉토리에 대한 변경 사항을 취소하되 스테이징된 상태로 유지하려면:

      git checkout <commit-B-SHA> <file>
      
    • 커밋 B의 단일 파일 또는 디렉토리에 대한 변경 사항을 취소하되 언스테이징된 상태로 유지하려면:

      git reset <commit-B-SHA> <file>
      

커밋 되돌리기 및 히스토리 수정#

다음 섹션에서는 Git 히스토리를 다시 작성하는 작업을 문서화합니다. 자세한 내용은 리베이스 및 충돌 해결을 참조하세요.

특정 커밋 삭제#

특정 커밋을 삭제할 수 있습니다. 예를 들어 커밋 A-B-C-D가 있고 커밋 B를 삭제하려는 경우:

  1. 현재 커밋 D에서 B까지의 범위를 리베이스합니다:

    git rebase -i A
    

    편집기에 커밋 목록이 표시됩니다.

  2. 커밋 B 앞에서 pickdrop으로 교체합니다.

  3. 다른 모든 커밋의 기본값 pick을 그대로 둡니다.

  4. 저장하고 편집기를 종료합니다.

특정 커밋 편집#

특정 커밋을 수정할 수 있습니다. 예를 들어 커밋 A-B-C-D가 있고 커밋 B에서 도입된 무언가를 수정하려는 경우:

  1. 현재 커밋 D에서 B까지의 범위를 리베이스합니다:

    git rebase -i A
    

    편집기에 커밋 목록이 표시됩니다.

  2. 커밋 B 앞에서 pickedit으로 교체합니다.

  3. 다른 모든 커밋의 기본값 pick을 그대로 둡니다.

  4. 저장하고 편집기를 종료합니다.

  5. 편집기에서 파일을 열고 편집한 다음 변경 사항을 커밋합니다:

    git commit -a
    

여러 커밋 취소#

브랜치에서 여러 커밋(A-B-C-D)을 만든 후 커밋 CD가 잘못되었다는 것을 깨달았다면 두 잘못된 커밋을 모두 취소합니다:

  1. 마지막 올바른 커밋을 체크아웃합니다. 이 예시에서는 B입니다.

    git checkout <commit-B-SHA>
    
  2. 새 브랜치를 만듭니다.

    git checkout -b new-path-of-feature
    
  3. 변경 사항을 추가하고, 푸시하고, 커밋합니다.

    git add .
    git commit -m "Undo commits C and D"
    git push --set-upstream origin new-path-of-feature
    

커밋은 이제 A-B-C-D-E입니다.

또는 해당 커밋을 새 머지 리퀘스트에 체리픽합니다.

Note

또 다른 해결책은 B로 리셋하고 E를 커밋하는 것입니다. 그러나 이 해결책은 A-B-E를 만들어 다른 사람들이 로컬에서 가지고 있는 것과 충돌합니다. 브랜치가 공유된 경우 이 해결책을 사용하지 마세요.

취소된 커밋 복구#

이전 로컬 커밋을 회수할 수 있습니다. 그러나 모든 이전 커밋을 사용할 수 있는 것은 아닙니다. Git은 브랜치나 태그로 도달할 수 없는 커밋을 정기적으로 정리하기 때문입니다.

저장소 히스토리를 보고 이전 커밋을 추적하려면 git reflog show를 실행합니다. 예를 들어:

$ git reflog show

# Example output:
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를 변경한 작업에 대한 설명.

원격 변경 사항 취소#

브랜치의 원격 변경 사항을 취소할 수 있습니다. 그러나 브랜치에 병합된 브랜치의 변경 사항은 취소할 수 없습니다. 이 경우 원격 브랜치의 변경 사항을 되돌려야 합니다.

히스토리를 변경하지 않고 원격 변경 사항 되돌리기#

원격 저장소의 변경 사항을 취소하려면 취소하려는 변경 사항으로 새 커밋을 만들 수 있습니다. 이 프로세스는 히스토리를 보존하고 명확한 타임라인과 개발 구조를 제공합니다:

Mermaid 다이어그램 (15줄)
소스 코드 보기
%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart LR
   accTitle: Git revert operation workflow diagram
   accDescr: Shows commits A, B, C in sequence, then commit -B that reverses B's changes, followed by D. Commit B remains in history.

REMOTE["REMOTE"] --> A(A) A --> B(B) B --> C(C) C --> negB("-B") negB --> D(D)

B:::crossed classDef crossed stroke:#000,stroke-width:3px,color:#000,stroke-dasharray: 5 5

negB -.->|reverts| B

특정 커밋 B에서 도입된 변경 사항을 되돌리려면:

git revert B

원격 변경 사항 되돌리기 및 히스토리 수정#

원격 변경 사항을 취소하고 히스토리를 변경할 수 있습니다.

업데이트된 히스토리가 있더라도 이전 커밋은 커밋 SHA로 여전히 액세스할 수 있습니다. 최소한 분리된 커밋의 모든 자동 정리가 수행되거나 수동으로 정리가 실행될 때까지는 그렇습니다. 여전히 커밋을 가리키는 참조가 있는 경우 정리해도 이전 커밋이 제거되지 않을 수 있습니다.

변경된 히스토리가 있는 로컬 브랜치와 변경되지 않은 원격 브랜치 간의 불일치

공개 브랜치나 다른 사람들이 사용할 수 있는 브랜치에서 작업할 때는 히스토리를 변경해서는 안 됩니다.

Note

기본 브랜치 또는 공유 브랜치의 커밋 히스토리를 절대 수정하지 마세요.

git rebase로 히스토리 수정#

머지 리퀘스트의 브랜치는 공개 브랜치이며 다른 개발자들이 사용할 수 있습니다. 그러나 프로젝트 규칙에 따라 리뷰가 완료된 후 대상 브랜치에 표시되는 커밋 수를 줄이기 위해 git rebase를 사용해야 할 수 있습니다.

git rebase -i를 사용하여 히스토리를 수정할 수 있습니다. 이 명령을 사용하여 커밋을 수정하고, 스쿼시하고, 삭제합니다.

#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Empty commits are commented out
Note

리베이스를 중단하기로 결정한 경우 편집기를 닫지 마세요. 대신 주석이 없는 모든 줄을 제거하고 저장합니다.

공유 및 원격 브랜치에서는 git rebase를 주의해서 사용하세요. 원격 저장소에 푸시하기 전에 로컬에서 실험하세요.

# Modify history from commit-id to HEAD (current commit)
git rebase -i commit-id

git merge --squash로 히스토리 수정#

대규모 오픈 소스 저장소에 기여할 때 커밋을 단일 커밋으로 스쿼시하는 것을 고려하세요. 이 방법은:

  • 깔끔하고 선형적인 프로젝트 히스토리를 유지하는 데 도움이 됩니다.
  • 모든 변경 사항이 하나의 커밋으로 압축되므로 변경 사항을 되돌리는 프로세스를 단순화합니다.

병합 시 브랜치의 커밋을 대상 브랜치의 단일 커밋으로 스쿼시하려면 git merge --squash를 사용합니다. 예를 들어:

  1. 기본 브랜치를 체크아웃합니다. 이 예시에서 기본 브랜치는 main입니다:

    git checkout main
    
  2. --squash로 대상 브랜치를 병합합니다:

    git merge --squash <target-branch>
    
  3. 변경 사항을 커밋합니다:

    git commit -m "Squash commit from feature-branch"
    

GitLab UI에서 커밋을 스쿼시하는 방법에 대한 정보는 스쿼시 및 병합을 참조하세요.

다른 부모로 머지 커밋 되돌리기#

머지 커밋을 되돌리면 병합된 브랜치는 항상 첫 번째 부모입니다. 예를 들어 기본 브랜치 또는 main입니다. 다른 부모로 머지 커밋을 되돌리려면 커맨드 라인에서 커밋을 되돌려야 합니다:

  1. 되돌릴 부모 커밋의 SHA를 확인합니다.

  2. 되돌릴 커밋의 부모 번호를 확인합니다. (기본값은 첫 번째 부모의 경우 1입니다.)

  3. 2를 부모 번호로, 7a39eb0을 커밋 SHA로 교체하여 이 명령을 실행합니다:

    git revert -m 2 7a39eb0
    

GitLab UI에서 변경 사항을 되돌리는 방법에 대한 정보는 변경 사항 되돌리기를 참조하세요.

민감한 정보 처리#

비밀번호 및 API 키와 같은 민감한 정보가 실수로 Git 저장소에 커밋될 수 있습니다. 이 섹션에서는 이 상황을 처리하는 방법을 다룹니다.

정보 삭제#

실수로 커밋된 민감하거나 기밀인 정보를 영구적으로 삭제하고 저장소 히스토리에서 더 이상 액세스할 수 없도록 합니다. 이 프로세스는 문자열 목록을 ***REMOVED***로 교체합니다.

또는 저장소에서 특정 파일을 완전히 삭제하려면 블롭 제거를 참조하세요.

저장소에서 텍스트를 삭제하려면 저장소에서 텍스트 삭제를 참조하세요.

커밋에서 정보 제거#

Git을 사용하여 이전 커밋에서 민감한 정보를 삭제할 수 있습니다. 그러나 이 과정에서 히스토리가 수정됩니다.

특정 필터로 히스토리를 다시 작성하려면 git filter-branch를 실행합니다.

파일을 히스토리에서 완전히 제거하려면 다음을 사용합니다:

git filter-branch --tree-filter 'rm filename' HEAD

git filter-branch 명령은 큰 저장소에서 느릴 수 있습니다. Git 명령을 더 빠르게 실행하는 도구들이 있습니다. 이러한 도구는 git filter-branch와 동일한 기능 세트를 제공하지 않고 특정 사용 사례에 집중하기 때문에 더 빠릅니다.

저장소 히스토리 및 GitLab 스토리지에서 파일을 제거하는 방법에 대한 자세한 내용은 저장소 크기 줄이기를 참조하세요.

커밋 취소 및 제거#

  • 마지막 커밋을 취소하고 모든 것을 스테이징 영역에 되돌립니다:

    git reset --soft HEAD^
    
  • 파일을 추가하고 커밋 메시지를 변경합니다:

    git commit --amend -m "New Message"
    
  • 아직 푸시하지 않은 경우 마지막 변경 사항을 취소하고 다른 모든 변경 사항을 제거합니다:

    git reset --hard HEAD^
    
  • 아직 푸시하지 않은 경우 마지막 변경 사항을 취소하고 마지막 두 커밋을 제거합니다:

    git reset --hard HEAD^^
    

예시 git reset 워크플로#

다음은 일반적인 Git 리셋 워크플로입니다:

  1. 파일을 편집합니다.

  2. 브랜치의 상태를 확인합니다:

    git status
    
  3. 잘못된 커밋 메시지로 브랜치에 변경 사항을 커밋합니다:

    git commit -am "kjkfjkg"
    
  4. Git 로그를 확인합니다:

    git log
    
  5. 올바른 커밋 메시지로 커밋을 수정합니다:

    git commit --amend -m "New comment added"
    
  6. Git 로그를 다시 확인합니다:

    git log
    
  7. 브랜치를 소프트 리셋합니다:

    git reset --soft HEAD^
    
  8. Git 로그를 다시 확인합니다:

    git log
    
  9. 원격에서 브랜치의 업데이트를 가져옵니다:

    git pull origin <branch>
    
  10. 원격으로 브랜치의 변경 사항을 푸시합니다:

    git push origin <branch>
    

새 커밋으로 커밋 취소#

커밋에서 파일이 변경되었고 이전 커밋처럼 되돌리고 싶지만 커밋 히스토리를 유지하려는 경우 git revert를 사용할 수 있습니다. 이 명령은 원래 커밋에서 취해진 모든 작업을 되돌리는 새 커밋을 만듭니다.

예를 들어, 커밋 B에서 파일의 변경 사항을 제거하고 커밋 A에서 해당 내용을 복원하려면 다음을 실행합니다:

git revert <commit-sha>

저장소에서 파일 제거#

  • 디스크와 저장소에서 파일을 제거하려면 git rm을 사용합니다. 디렉토리를 제거하려면 -r 플래그를 사용합니다:

    git rm '*.txt'
    git rm -r <dirname>
    
  • 디스크에는 파일을 유지하되 저장소에서 제거하려면(.gitignore에 추가할 파일의 경우) rm 명령을 --cache 플래그와 함께 사용합니다:

    git rm <filename> --cache
    

이 명령들은 현재 브랜치에서 파일을 제거하지만 저장소 히스토리에서 완전히 삭제하지는 않습니다. 저장소에서 파일의 과거와 현재의 모든 흔적을 완전히 제거하려면 블롭 제거를 참조하세요.

git revertgit reset 비교#

  • git reset 명령은 커밋을 완전히 제거합니다.
  • git revert 명령은 변경 사항을 제거하지만 커밋은 그대로 유지합니다. 되돌리기를 되돌릴 수 있으므로 더 안전합니다.
# Changed file
git commit -am "bug introduced"
git revert HEAD
# New commit created reverting changes
# Next, reapply the reverted commit
git log # take hash from the revert commit
git revert <rev commit hash>
# reverted commit is back (new commit created again)

관련 주제#

변경 사항 되돌리기 및 취소

원문 보기
요약

Git 작업에는 실험과 반복이 포함됩니다. 실수로 커밋한 내용을 복구하고, 민감한 데이터를 제거하고, 잘못된 병합을 수정하고, 깔끔한 저장소 히스토리를 유지하세요. 변경 사항을 원격 저장소에 푸시할 때까지 Git에서 변경한 내용은 로컬 개발 환경에만 있습니다.

Git 작업에는 실험과 반복이 포함됩니다. 개발 중에 실수가 발생하며 때로는 변경 사항을 되돌려야 합니다. Git은 Git 워크플로의 어느 지점에서든 변경 사항을 취소하는 기능으로 코드 히스토리를 제어합니다.

실수로 커밋한 내용을 복구하고, 민감한 데이터를 제거하고, 잘못된 병합을 수정하고, 깔끔한 저장소 히스토리를 유지하세요. 다른 사람들과 협업할 때 새로운 되돌리기 커밋으로 투명성을 유지하거나 공유하기 전에 로컬에서 작업을 리셋합니다. 사용할 방법은 변경 사항이 다음 중 어디에 있는지에 따라 다릅니다:

  • 로컬 컴퓨터에만 있는 경우.
  • GitLab.com과 같은 Git 서버에 원격으로 저장된 경우.

로컬 변경 사항 취소#

변경 사항을 원격 저장소에 푸시할 때까지 Git에서 변경한 내용은 로컬 개발 환경에만 있습니다.

Git에서 파일을 _스테이징_하면 커밋을 준비하기 위해 파일 변경 사항을 추적하도록 Git에 지시합니다. 파일 변경 사항을 무시하고 다음 커밋에 포함하지 않으려면 파일을 _언스테이징_합니다.

스테이징되지 않은 로컬 변경 사항 되돌리기#

아직 스테이징되지 않은 로컬 변경 사항을 취소하려면:

  1. git status를 실행하여 파일이 스테이징되지 않은 것을 확인합니다(git add <file>을 사용하지 않은 것):

    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")
    
  2. 옵션을 선택하고 변경 사항을 취소합니다:

    • 로컬 변경 사항을 덮어쓰려면:

      git checkout -- <file>
      
    • 모든 파일의 로컬 변경 사항을 영구적으로 취소하려면:

      git reset --hard
      

스테이징된 로컬 변경 사항 되돌리기#

이미 스테이징된 로컬 변경 사항을 취소할 수 있습니다. 다음 예시에서는 파일이 스테이징에 추가되었지만 커밋되지 않았습니다:

  1. 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>
    
  2. 옵션을 선택하고 변경 사항을 취소합니다:

    • 변경 사항을 유지하면서 파일을 언스테이징하려면:

      git restore --staged <file>
      
    • 변경 사항을 유지하면서 모든 것을 언스테이징하려면:

      git reset
      
    • 파일을 현재 커밋(HEAD)으로 언스테이징하려면:

      git reset HEAD <file>
      
    • 모든 것을 영구적으로 취소하려면:

      git reset --hard
      

로컬 커밋 취소#

git commit으로 로컬 저장소에 커밋하면 Git이 변경 사항을 기록합니다. 아직 원격 저장소에 푸시하지 않았으므로 변경 사항이 공개되거나 다른 사람들과 공유되지 않았습니다. 이 시점에서 변경 사항을 취소할 수 있습니다.

히스토리를 변경하지 않고 커밋 되돌리기#

커밋 히스토리를 유지하면서 커밋을 되돌릴 수 있습니다.

이 예시에서는 순서대로 커밋된 5개의 커밋 A, B, C, D, E를 사용합니다: A-B-C-D-E. 취소하려는 커밋은 B입니다.

  1. 되돌릴 커밋의 커밋 SHA를 찾습니다. git log 명령을 사용하여 커밋 로그를 확인합니다.

  2. 옵션을 선택하고 변경 사항을 취소합니다:

    • 커밋 B에서 도입된 변경 사항을 되돌리려면:

      git revert <commit-B-SHA>
      
    • 커밋 B의 단일 파일 또는 디렉토리에 대한 변경 사항을 취소하되 스테이징된 상태로 유지하려면:

      git checkout <commit-B-SHA> <file>
      
    • 커밋 B의 단일 파일 또는 디렉토리에 대한 변경 사항을 취소하되 언스테이징된 상태로 유지하려면:

      git reset <commit-B-SHA> <file>
      

커밋 되돌리기 및 히스토리 수정#

다음 섹션에서는 Git 히스토리를 다시 작성하는 작업을 문서화합니다. 자세한 내용은 리베이스 및 충돌 해결을 참조하세요.

특정 커밋 삭제#

특정 커밋을 삭제할 수 있습니다. 예를 들어 커밋 A-B-C-D가 있고 커밋 B를 삭제하려는 경우:

  1. 현재 커밋 D에서 B까지의 범위를 리베이스합니다:

    git rebase -i A
    

    편집기에 커밋 목록이 표시됩니다.

  2. 커밋 B 앞에서 pickdrop으로 교체합니다.

  3. 다른 모든 커밋의 기본값 pick을 그대로 둡니다.

  4. 저장하고 편집기를 종료합니다.

특정 커밋 편집#

특정 커밋을 수정할 수 있습니다. 예를 들어 커밋 A-B-C-D가 있고 커밋 B에서 도입된 무언가를 수정하려는 경우:

  1. 현재 커밋 D에서 B까지의 범위를 리베이스합니다:

    git rebase -i A
    

    편집기에 커밋 목록이 표시됩니다.

  2. 커밋 B 앞에서 pickedit으로 교체합니다.

  3. 다른 모든 커밋의 기본값 pick을 그대로 둡니다.

  4. 저장하고 편집기를 종료합니다.

  5. 편집기에서 파일을 열고 편집한 다음 변경 사항을 커밋합니다:

    git commit -a
    

여러 커밋 취소#

브랜치에서 여러 커밋(A-B-C-D)을 만든 후 커밋 CD가 잘못되었다는 것을 깨달았다면 두 잘못된 커밋을 모두 취소합니다:

  1. 마지막 올바른 커밋을 체크아웃합니다. 이 예시에서는 B입니다.

    git checkout <commit-B-SHA>
    
  2. 새 브랜치를 만듭니다.

    git checkout -b new-path-of-feature
    
  3. 변경 사항을 추가하고, 푸시하고, 커밋합니다.

    git add .
    git commit -m "Undo commits C and D"
    git push --set-upstream origin new-path-of-feature
    

커밋은 이제 A-B-C-D-E입니다.

또는 해당 커밋을 새 머지 리퀘스트에 체리픽합니다.

Note

또 다른 해결책은 B로 리셋하고 E를 커밋하는 것입니다. 그러나 이 해결책은 A-B-E를 만들어 다른 사람들이 로컬에서 가지고 있는 것과 충돌합니다. 브랜치가 공유된 경우 이 해결책을 사용하지 마세요.

취소된 커밋 복구#

이전 로컬 커밋을 회수할 수 있습니다. 그러나 모든 이전 커밋을 사용할 수 있는 것은 아닙니다. Git은 브랜치나 태그로 도달할 수 없는 커밋을 정기적으로 정리하기 때문입니다.

저장소 히스토리를 보고 이전 커밋을 추적하려면 git reflog show를 실행합니다. 예를 들어:

$ git reflog show

# Example output:
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를 변경한 작업에 대한 설명.

원격 변경 사항 취소#

브랜치의 원격 변경 사항을 취소할 수 있습니다. 그러나 브랜치에 병합된 브랜치의 변경 사항은 취소할 수 없습니다. 이 경우 원격 브랜치의 변경 사항을 되돌려야 합니다.

히스토리를 변경하지 않고 원격 변경 사항 되돌리기#

원격 저장소의 변경 사항을 취소하려면 취소하려는 변경 사항으로 새 커밋을 만들 수 있습니다. 이 프로세스는 히스토리를 보존하고 명확한 타임라인과 개발 구조를 제공합니다:

Mermaid 다이어그램 (15줄)
소스 코드 보기
%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart LR
   accTitle: Git revert operation workflow diagram
   accDescr: Shows commits A, B, C in sequence, then commit -B that reverses B's changes, followed by D. Commit B remains in history.

REMOTE["REMOTE"] --> A(A) A --> B(B) B --> C(C) C --> negB("-B") negB --> D(D)

B:::crossed classDef crossed stroke:#000,stroke-width:3px,color:#000,stroke-dasharray: 5 5

negB -.->|reverts| B

특정 커밋 B에서 도입된 변경 사항을 되돌리려면:

git revert B

원격 변경 사항 되돌리기 및 히스토리 수정#

원격 변경 사항을 취소하고 히스토리를 변경할 수 있습니다.

업데이트된 히스토리가 있더라도 이전 커밋은 커밋 SHA로 여전히 액세스할 수 있습니다. 최소한 분리된 커밋의 모든 자동 정리가 수행되거나 수동으로 정리가 실행될 때까지는 그렇습니다. 여전히 커밋을 가리키는 참조가 있는 경우 정리해도 이전 커밋이 제거되지 않을 수 있습니다.

변경된 히스토리가 있는 로컬 브랜치와 변경되지 않은 원격 브랜치 간의 불일치

공개 브랜치나 다른 사람들이 사용할 수 있는 브랜치에서 작업할 때는 히스토리를 변경해서는 안 됩니다.

Note

기본 브랜치 또는 공유 브랜치의 커밋 히스토리를 절대 수정하지 마세요.

git rebase로 히스토리 수정#

머지 리퀘스트의 브랜치는 공개 브랜치이며 다른 개발자들이 사용할 수 있습니다. 그러나 프로젝트 규칙에 따라 리뷰가 완료된 후 대상 브랜치에 표시되는 커밋 수를 줄이기 위해 git rebase를 사용해야 할 수 있습니다.

git rebase -i를 사용하여 히스토리를 수정할 수 있습니다. 이 명령을 사용하여 커밋을 수정하고, 스쿼시하고, 삭제합니다.

#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Empty commits are commented out
Note

리베이스를 중단하기로 결정한 경우 편집기를 닫지 마세요. 대신 주석이 없는 모든 줄을 제거하고 저장합니다.

공유 및 원격 브랜치에서는 git rebase를 주의해서 사용하세요. 원격 저장소에 푸시하기 전에 로컬에서 실험하세요.

# Modify history from commit-id to HEAD (current commit)
git rebase -i commit-id

git merge --squash로 히스토리 수정#

대규모 오픈 소스 저장소에 기여할 때 커밋을 단일 커밋으로 스쿼시하는 것을 고려하세요. 이 방법은:

  • 깔끔하고 선형적인 프로젝트 히스토리를 유지하는 데 도움이 됩니다.
  • 모든 변경 사항이 하나의 커밋으로 압축되므로 변경 사항을 되돌리는 프로세스를 단순화합니다.

병합 시 브랜치의 커밋을 대상 브랜치의 단일 커밋으로 스쿼시하려면 git merge --squash를 사용합니다. 예를 들어:

  1. 기본 브랜치를 체크아웃합니다. 이 예시에서 기본 브랜치는 main입니다:

    git checkout main
    
  2. --squash로 대상 브랜치를 병합합니다:

    git merge --squash <target-branch>
    
  3. 변경 사항을 커밋합니다:

    git commit -m "Squash commit from feature-branch"
    

GitLab UI에서 커밋을 스쿼시하는 방법에 대한 정보는 스쿼시 및 병합을 참조하세요.

다른 부모로 머지 커밋 되돌리기#

머지 커밋을 되돌리면 병합된 브랜치는 항상 첫 번째 부모입니다. 예를 들어 기본 브랜치 또는 main입니다. 다른 부모로 머지 커밋을 되돌리려면 커맨드 라인에서 커밋을 되돌려야 합니다:

  1. 되돌릴 부모 커밋의 SHA를 확인합니다.

  2. 되돌릴 커밋의 부모 번호를 확인합니다. (기본값은 첫 번째 부모의 경우 1입니다.)

  3. 2를 부모 번호로, 7a39eb0을 커밋 SHA로 교체하여 이 명령을 실행합니다:

    git revert -m 2 7a39eb0
    

GitLab UI에서 변경 사항을 되돌리는 방법에 대한 정보는 변경 사항 되돌리기를 참조하세요.

민감한 정보 처리#

비밀번호 및 API 키와 같은 민감한 정보가 실수로 Git 저장소에 커밋될 수 있습니다. 이 섹션에서는 이 상황을 처리하는 방법을 다룹니다.

정보 삭제#

실수로 커밋된 민감하거나 기밀인 정보를 영구적으로 삭제하고 저장소 히스토리에서 더 이상 액세스할 수 없도록 합니다. 이 프로세스는 문자열 목록을 ***REMOVED***로 교체합니다.

또는 저장소에서 특정 파일을 완전히 삭제하려면 블롭 제거를 참조하세요.

저장소에서 텍스트를 삭제하려면 저장소에서 텍스트 삭제를 참조하세요.

커밋에서 정보 제거#

Git을 사용하여 이전 커밋에서 민감한 정보를 삭제할 수 있습니다. 그러나 이 과정에서 히스토리가 수정됩니다.

특정 필터로 히스토리를 다시 작성하려면 git filter-branch를 실행합니다.

파일을 히스토리에서 완전히 제거하려면 다음을 사용합니다:

git filter-branch --tree-filter 'rm filename' HEAD

git filter-branch 명령은 큰 저장소에서 느릴 수 있습니다. Git 명령을 더 빠르게 실행하는 도구들이 있습니다. 이러한 도구는 git filter-branch와 동일한 기능 세트를 제공하지 않고 특정 사용 사례에 집중하기 때문에 더 빠릅니다.

저장소 히스토리 및 GitLab 스토리지에서 파일을 제거하는 방법에 대한 자세한 내용은 저장소 크기 줄이기를 참조하세요.

커밋 취소 및 제거#

  • 마지막 커밋을 취소하고 모든 것을 스테이징 영역에 되돌립니다:

    git reset --soft HEAD^
    
  • 파일을 추가하고 커밋 메시지를 변경합니다:

    git commit --amend -m "New Message"
    
  • 아직 푸시하지 않은 경우 마지막 변경 사항을 취소하고 다른 모든 변경 사항을 제거합니다:

    git reset --hard HEAD^
    
  • 아직 푸시하지 않은 경우 마지막 변경 사항을 취소하고 마지막 두 커밋을 제거합니다:

    git reset --hard HEAD^^
    

예시 git reset 워크플로#

다음은 일반적인 Git 리셋 워크플로입니다:

  1. 파일을 편집합니다.

  2. 브랜치의 상태를 확인합니다:

    git status
    
  3. 잘못된 커밋 메시지로 브랜치에 변경 사항을 커밋합니다:

    git commit -am "kjkfjkg"
    
  4. Git 로그를 확인합니다:

    git log
    
  5. 올바른 커밋 메시지로 커밋을 수정합니다:

    git commit --amend -m "New comment added"
    
  6. Git 로그를 다시 확인합니다:

    git log
    
  7. 브랜치를 소프트 리셋합니다:

    git reset --soft HEAD^
    
  8. Git 로그를 다시 확인합니다:

    git log
    
  9. 원격에서 브랜치의 업데이트를 가져옵니다:

    git pull origin <branch>
    
  10. 원격으로 브랜치의 변경 사항을 푸시합니다:

    git push origin <branch>
    

새 커밋으로 커밋 취소#

커밋에서 파일이 변경되었고 이전 커밋처럼 되돌리고 싶지만 커밋 히스토리를 유지하려는 경우 git revert를 사용할 수 있습니다. 이 명령은 원래 커밋에서 취해진 모든 작업을 되돌리는 새 커밋을 만듭니다.

예를 들어, 커밋 B에서 파일의 변경 사항을 제거하고 커밋 A에서 해당 내용을 복원하려면 다음을 실행합니다:

git revert <commit-sha>

저장소에서 파일 제거#

  • 디스크와 저장소에서 파일을 제거하려면 git rm을 사용합니다. 디렉토리를 제거하려면 -r 플래그를 사용합니다:

    git rm '*.txt'
    git rm -r <dirname>
    
  • 디스크에는 파일을 유지하되 저장소에서 제거하려면(.gitignore에 추가할 파일의 경우) rm 명령을 --cache 플래그와 함께 사용합니다:

    git rm <filename> --cache
    

이 명령들은 현재 브랜치에서 파일을 제거하지만 저장소 히스토리에서 완전히 삭제하지는 않습니다. 저장소에서 파일의 과거와 현재의 모든 흔적을 완전히 제거하려면 블롭 제거를 참조하세요.

git revertgit reset 비교#

  • git reset 명령은 커밋을 완전히 제거합니다.
  • git revert 명령은 변경 사항을 제거하지만 커밋은 그대로 유지합니다. 되돌리기를 되돌릴 수 있으므로 더 안전합니다.
# Changed file
git commit -am "bug introduced"
git revert HEAD
# New commit created reverting changes
# Next, reapply the reverted commit
git log # take hash from the revert commit
git revert <rev commit hash>
# reverted commit is back (new commit created again)

관련 주제#