Git으로 실수를 되돌리기 위한 가이드(2부)

게시 됨: 2022-03-10
빠른 요약 ↬ 실수. 이 잔인한 악당들은 아름다운 소프트웨어 개발 세계를 멈추지 않습니다. 하지만 실수를 피할 수는 없지만, 실수를 되돌리는 법은 배울 수 있습니다! 이 기사에서는 Git을 사용하는 일상적인 작업에 적합한 도구를 보여줍니다. 시리즈의 첫 번째 기사도 확인하는 것이 좋습니다.

"Git을 사용하여 실수 취소하기" 시리즈의 두 번째 부분에서 우리는 다시 용감하게 위험을 바라보게 될 것입니다. 저는 4가지 새로운 종말 시나리오를 준비했습니다. 물론 목을 구할 수 있는 몇 가지 영리한 방법도 포함됩니다! 하지만 본격적으로 시작하기 전에 Git에 대한 이전 기사를 확인하여 Git을 사용한 실수를 되돌리는 데 도움이 되는 더 많은 자가 구조 방법을 확인하세요!

갑시다!

Reflog를 사용하여 삭제된 분기 복구

브랜치를 삭제하고 얼마 지나지 않아 삭제하면 안 된다는 사실을 깨달은 적이 있습니까? 혹시라도 이 감정을 모를 경우에는 좋지 않다고 말씀드릴 수 있습니다. 슬픔과 분노가 뒤섞인 감정이 당신을 스쳐지나갑니다. 그 브랜치의 커밋에 들인 모든 노력과 지금 잃어버렸던 모든 귀중한 코드를 생각하면 말입니다.

운 좋게도 "Reflog"라는 Git 도구를 사용하여 해당 분기를 죽은 상태에서 되돌릴 수 있는 방법이 있습니다. 우리는 시리즈의 첫 번째 부분에서 이 도구를 사용했지만 여기에 약간의 복습이 있습니다. Reflog는 Git이 로컬 저장소에서 HEAD 포인터의 모든 움직임을 기록하는 저널과 같습니다. 다른 말로 하면, 덜 괴상한 단어입니다. 체크아웃, 커밋, 병합, 리베이스, 체리 선택 등을 할 때마다 저널 항목이 생성됩니다. 이것은 일이 잘못되었을 때 Reflog를 완벽한 안전망으로 만듭니다!

구체적인 예를 살펴보겠습니다.

 $ git branch * feature/login master

현재 분기 feature/login 이 체크아웃되어 있음을 알 수 있습니다. 이것이 우리가 (실수로) 삭제할 분기라고 가정해 보겠습니다. 그러나 그렇게 하기 전에 현재 HEAD 분기를 삭제할 수 없기 때문에 다른 분기로 전환해야 합니다!

 $ git checkout master $ git branch -d feature/login

우리의 소중한 기능 브랜치는 이제 사라졌습니다. 그리고 (a) 실수의 심각성을 이해하고 (b) 조금 슬퍼할 시간을 드리겠습니다. 눈물을 닦고 나면 이 가지를 다시 가져올 방법을 찾아야 합니다! Reflog를 열고(단순히 git reflog 를 입력하여) 저장되어 있는 내용을 확인합니다.

Git의 Reflog 프로토콜은 로컬 리포지토리의 모든 주요 작업입니다.
Git의 Reflog는 로컬 저장소의 모든 주요 작업을 프로토콜로 지정합니다. (큰 미리보기)

다음은 출력을 이해하는 데 도움이 되는 몇 가지 설명입니다.

  • 우선, Reflog가 항목을 시간순으로 정렬한다는 것을 알아야 합니다. 최신 항목이 목록의 맨 위에 있습니다.
  • 최상위(따라서 최신) 항목은 분기를 삭제하기 전에 수행한 git checkout 명령입니다. 이것은 Reflog가 충실히 기록하는 "HEAD 포인터 이동" 중 하나이기 때문에 Reflog에 기록됩니다.
  • 중대한 실수를 되돌리기 위해 Reflog에 깨끗하고 명확하게 기록된 이전 상태로 간단히 돌아갈 수 있습니다.

따라서 이 "before" 상태 SHA-1 해시에서 시작하는 새 브랜치("잃어버린" 브랜치 이름으로)를 만들어 이것을 시도해 보겠습니다.

 $ git branch feature/login 776f8ca

그리고 짜잔! 이제 잃어버린 것처럼 보이는 지점을 복원한 것을 보고 기뻐할 것입니다!

"Tower"와 같은 Git 데스크탑 GUI를 사용하는 경우 멋진 단축키를 사용할 수 있습니다. 단순히 분기를 격렬하게 삭제한 경우에도 키보드에서 CMD + Z 를 눌러 마지막 명령을 실행 취소하기만 하면 됩니다!

Tower와 같은 데스크탑 GUI는 실수를 취소하는 프로세스를 더 쉽게 만들 수 있습니다.
점프 후 더! 아래에서 계속 읽기 ↓

커밋을 다른 브랜치로 옮기기

많은 팀에서 main 또는 develop 와 같은 장기 실행 분기에 커밋하지 않기로 합의했습니다. 이러한 분기 는 통합(예: 병합 또는 리베이스)을 통해서만 새 커밋을 받아야 합니다 . 그러나 물론 실수는 불가피합니다. 그럼에도 불구하고 우리는 때때로 이 가지를 잊고 커밋합니다! 그렇다면 우리가 만든 혼란을 어떻게 정리할 수 있습니까?

커밋을 올바른 대상 브랜치로 이동
커밋이 잘못된 지점에 도착했습니다. 올바른 대상 분기로 어떻게 이동할 수 있습니까? (큰 미리보기)

다행히도 이러한 유형의 문제는 쉽게 수정할 수 있습니다. 소매를 걷어붙이고 일을 시작합시다.

첫 번째 단계는 올바른 대상 분기로 전환한 다음 cherry-pick 명령을 과도하게 사용하여 커밋을 이동하는 것입니다.

 $ git checkout feature/login $ git cherry-pick 776f8caf

이제 처음에 있어야 했던 원하는 분기에 대한 커밋을 갖게 됩니다. 엄청난!

하지만 아직 해야 할 일이 한 가지 더 있습니다. 처음에 실수로 떨어진 지점을 정리해야 합니다! 말하자면, cherry-pick 명령은 커밋의 복사본을 생성했지만 원본은 여전히 ​​장기 실행 브랜치에 있습니다.

커밋의 복사본이 올바른 브랜치에 있지만 원본은 여전히 ​​잘못된 브랜치에 있는 것으로 표시됩니다.
올바른 브랜치에 커밋 사본을 성공적으로 생성했지만 원본은 여전히 ​​잘못된 브랜치에 있습니다. (큰 미리보기)

즉, 장기 실행 분기로 다시 전환하고 git reset 을 사용하여 제거해야 합니다.

 $ git checkout main $ git reset --hard HEAD~1

보시다시피 여기에서 git reset 명령을 사용하여 잘못된 커밋을 지우고 있습니다. HEAD~1 매개변수는 Git에게 "HEAD 뒤의 1개 개정판으로 돌아가기"를 지시하여 해당 분기의 기록에서 최상위(이 경우 원하지 않는) 커밋을 효과적으로 지웁니다.

그리고 짜잔: 커밋은 이제 원래 있어야 할 위치에 있고 장기 실행 브랜치는 깨끗합니다. 마치 우리의 실수가 한 번도 일어나지 않은 것처럼!

이전 커밋의 메시지 편집

오타를 커밋 메시지에 몰래 집어넣고 나중에야 발견하는 것은 너무나 쉽습니다. 이러한 경우 git commit 의 좋은 --amend 옵션은 이 문제를 해결하는 데 사용할 수 없습니다. 왜냐하면 가장 마지막 커밋에서만 작동하기 때문입니다. 그보다 오래된 커밋을 수정하려면 "Interactive Rebase"라는 Git 도구를 사용해야 합니다.

변경할 가치가 있는 커밋 메시지
다음은 변경할 가치가 있는 커밋 메시지입니다. (큰 미리보기)

먼저 커밋 히스토리에서 편집할 부분을 Interactive Rebase에 알려야 합니다. 이것은 커밋 해시를 제공하여 수행됩니다. 즉, 조작하려는 상위 커밋입니다.

 $ git rebase -i 6bcf266b

그러면 편집기 창이 열립니다. 여기에는 명령에서 Interactive Rebase의 기반으로 제공한 커밋 이후 의 모든 커밋 목록이 포함되어 있습니다.

Interactive Rebase 세션에서 편집하기 위해 선택한 커밋 범위 표시
Interactive Rebase 세션에서 편집하기 위해 선택한 커밋 범위입니다. (큰 미리보기)

여기서 첫 번째 충동을 따르지 않는 것이 중요합니다. 이 단계에서는 아직 커밋 메시지를 편집하지 않습니다 . 대신, 우리는 커밋에 대해 어떤 종류의 조작 을 하고 싶은지 Git에게만 알려줍니다. 매우 편리하게도 이 창 하단의 주석에 작업 키워드 목록이 기록되어 있습니다. 우리의 경우 라인 #1을 reword 로 표시합니다(따라서 표준 pick 대체).

이 단계에서 할 일은 편집기 창을 저장하고 닫는 것뿐입니다. 그 대가로 우리가 마크업한 커밋의 현재 메시지가 포함된 새 편집기 창이 열립니다. 이제 드디어 편집할 시간입니다!

전체 프로세스를 한 눈에 볼 수 있습니다.

Interactive Rebase를 사용하여 이전 커밋의 메시지를 처음부터 끝까지 편집합니다.

깨진 커밋 수정하기(매우 우아한 방식으로)

마지막으로, 우리는 실행 취소 도구의 스위스 군용 fixup 을 살펴보겠습니다. 간단히 말해서, 사실 이후에 깨진/불완전한/잘못된 커밋을 수정할 수 있습니다. 다음과 같은 두 가지 이유로 정말 훌륭한 도구입니다.

  1. 문제가 무엇인지는 중요하지 않습니다.
    파일을 추가하는 것을 잊었거나, 무언가를 삭제했어야 하거나, 잘못 변경했거나, 단순히 오타가 있을 수 있습니다. fixup 은 이러한 모든 상황에서 작동합니다!
  2. 매우 우아합니다.
    커밋의 버그에 대한 우리의 정상적이고 본능적인 반응은 문제를 수정하는 커밋을 생성하는 것입니다. 이 작업 방식은 직관적으로 보일 수 있지만 곧 커밋 기록을 매우 혼란스럽게 만듭니다. "원래" 커밋이 있고 원래 커밋에서 잘못된 부분을 수정하는 이 작은 "반창고" 커밋이 있습니다. 당신의 기록은 코드베이스에서 무슨 일이 일어났는지 이해하기 어렵게 만드는 작고 의미 없는 반창고 커밋으로 가득 차 있습니다.
소위 반창고 커밋으로 작은 실수를 지속적으로 수정하면 커밋 기록을 읽기가 매우 어려울 수 있습니다.
"반창고 커밋"으로 작은 실수를 계속 수정하면 커밋 기록을 읽기가 매우 어렵습니다. (큰 미리보기)

이것은 fixup 이 필요한 곳입니다. 이 수정 반창고 커밋을 계속할 수 있습니다. 그러나 여기에 마법이 있습니다. 그런 다음 원래의 깨진 커밋에 적용하고(그런 방식으로 복구) 못생긴 반창고 커밋을 완전히 버립니다!

Fixup은 수정 사항을 원래 커밋에 적용한 다음 불필요한 반창고 커밋을 처리합니다.
Fixup은 수정 사항을 원래 커밋에 적용한 다음 불필요한 반창고 커밋을 삭제합니다. (큰 미리보기)

실제 사례를 함께 살펴보실 수 있습니다! 여기에서 선택된 커밋이 깨졌다고 가정해 봅시다.

선택한 잘못된 커밋을 우아한 방식으로 수정
선택한 커밋이 올바르지 않습니다. 우아한 방식으로 수정하겠습니다. (큰 미리보기)

또한 문제를 해결할 error.html 이라는 파일에 변경 사항을 준비했다고 가정해 보겠습니다. 다음은 우리가 해야 할 첫 번째 단계입니다.

 $ git add error.html $ git commit --fixup 2b504bee

우리는 새로운 커밋을 생성하고 있지만 Git에게 이것은 특별한 커밋이라고 말하고 있습니다. 지정된 SHA-1 해시(이 경우 2b504bee )를 사용하는 이전 커밋에 대한 수정 사항입니다.

이제 두 번째 단계는 Interactive Rebase 세션을 시작하는 것입니다. fixup 은 Interactive Rebase의 큰 도구 세트에 속하기 때문입니다.

 $ git rebase -i --autosquash 0023cddd

이 명령에 대해 두 가지를 설명할 가치가 있습니다. 먼저, 여기에서 개정 해시로 0023cddd 를 제공한 이유는 무엇입니까? 깨진 동료의 상위 커밋에서 Interactive Rebase 세션을 시작해야 하기 때문입니다.

둘째, --autosquash 옵션은 무엇을 위한 것입니까? 우리 어깨에 많은 노력이 필요합니다! 이제 열리는 편집기 창에는 모든 것이 이미 준비되어 있습니다.

Interactive Rebase 세션 창
Interactive Rebase 세션 창(큰 미리보기)

--autosquash 옵션 덕분에 Git은 이미 우리를 위해 무거운 작업을 수행했습니다.

  1. 그것은 fixup 조치 키워드로 우리의 작은 반창고 커밋을 표시했습니다. 그렇게 하면 Git이 바로 의 커밋과 결합한 다음 삭제합니다.
  2. 또한 그에 따라 줄을 재정렬하여 반창고 커밋을 수정하려는 커밋 바로 아래로 이동했습니다(다시: fixup 은 마크업된 커밋을 의 커밋과 결합하여 작동합니다!).

간단히 말해서: 우리를 위해 할 일은 창을 닫는 것 외에는 없습니다!

최종 결과를 최종적으로 살펴보겠습니다.

  • 이전에 깨진 커밋이 수정되었습니다. 이제 반창고 커밋에서 준비한 변경 사항이 포함됩니다.
  • 보기 흉한 반창고 커밋 자체는 삭제되었습니다. 커밋 기록은 깨끗하고 읽기 쉽습니다. 마치 실수가 전혀 발생하지 않은 것처럼 말이죠.
깨끗한 커밋 기록이 어떻게 보이는지 보여주는 예
수정 도구를 사용한 후의 최종 결과: 깨끗한 커밋 기록! (큰 미리보기)

실수를 취소하는 방법을 아는 것은 초능력입니다

축하합니다! 이제 많은 어려운 상황에서 목을 구할 수 있습니다! 우리는 이러한 상황을 피할 수 없습니다. 우리가 개발자로서 아무리 경험이 많다 하더라도 실수는 일의 일부일 뿐입니다. 그러나 이제 그들을 다루는 방법을 알았으므로 느긋한 심박수로 그들을 대할 수 있습니다.

Git을 사용하여 실수를 취소하는 방법에 대해 자세히 알아보려면 이 주제에 대한 짧은 비디오 시리즈인 무료 "Git용 응급 처치 키트"를 추천합니다.

실수를 하는 재미를 느끼세요. 물론 실수도 쉽게 되돌릴 수 있습니다!