하나의 이슈를 해결하는데 지저분하게 여러 번 커밋을 하게 됐다. 연결된 또는 분리된 여러 커밋을 하나의 커밋으로 정리하는 방법을 설명한다.
마지막 3개의 커밋 중 1번, 2번 커밋이 같은 이슈를 해결하기 위한 커밋이라서 1번 커밋으로 합치려 한다. 3번 커밋은 내 커밋이 아니다. vi 편집기에서 아래와 같이 대화형(-i, interactive) 리베이스를 시도한다.
$ git rebase -i HEAD~3
아래와 같이 편집 가능한 커밋 목록을 볼 수 있다.
pick 9c97a74f 1번 커밋(내 커밋)
pick 895bf53d 2번 커밋(내 커밋)
pick 56c91403 3번 커밋(동료 커밋)
3번 커밋은 동료의 커밋이므로 유지한다. 2번 커밋을 1번 커밋으로 합치려고 한다. i
명령으로 편집 모드에 진입하고 2번 커밋의 pick
을 fixup
으로 고친 다음 :wq
명령으로 저장한다.(편집을 취소하고 빠져나오려면 :q!
명령을 사용)
pick 9c97a74f 1번 커밋(내 커밋)
fixup 895bf53d 2번 커밋(내 커밋)
pick 56c91403 3번 커밋(동료 커밋)
2번 커밋은 1번 커밋으로 합쳐지고 1번 커밋 로그만 남는다. 만약 이미 푸시한 커밋이라면 아래와 같이 강제 푸시를 시도할 수 있다. 이 경우 동료들은 원격 저장소로부터 갱신된 트리를 받아와야 한다.
$ git push -f
git 가이드라인에는 “이미 공개 저장소에 Push한 커밋을 Rebase 하지 마라“는 금기 사항이 있다. 리베이스한 커밋을 강제로 푸시할 때에는 동료들과 사전 합의가 필요하다.
동료가 리베이스한 커밋을 푸시했다면 갱신된 트리를 받아오기 위해 현재 작업 중인 내용을 임시 저장한다. 그리고 오리진 기준으로 브랜치를 초기화한 다음 내 작업 내용을 복원한다. stash
명령은 작업 내용이 스테이지에 있는지 여부와 무관하게 모든 변경 사항을 저장하고 복원해 준다.
$ git stash
$ git reset --hard origin/xxx
$ git stash apply
마지막 3개의 커밋 중 1번, 3번 커밋이 같은 이슈를 해결하기 위한 커밋이라서 1번 커밋으로 합치려 한다. 2번 커밋은 내 커밋이 아니다. vi 편집기에서 아래와 같이 대화형(-i, interactive) 리베이스를 시도한다.
$ git rebase -i HEAD~3
아래와 같이 편집 가능한 커밋 목록을 볼 수 있다.
pick 9c97a74f 1번 커밋(내 커밋)
pick 895bf53d 2번 커밋(동료 커밋)
pick 56c91403 3번 커밋(내 커밋)
2번 커밋은 동료의 커밋이므로 유지해야 한다. 3번 커밋을 1번 커밋으로 합치려고 한다. 편집 모드 진입 전 yy
명령으로 3번 행을 복사한 다음 dd
명령으로 삭제한다. 1번 행에 커서를 옮겨 놓고 p
명령으로 다시 삽입한다. 이렇게 하면 3번 커밋의 위치가 1번 커밋 다음으로 이동한다. i
명령으로 편집 모드에 진입하고 3번 커밋의 pick
을 fixup
으로 고친 다음 :wq
명령으로 저장한다.(편집을 취소하고 빠져나오려면 :q!
명령을 사용)
pick 9c97a74f 1번 커밋(내 커밋)
fixup 56c91403 3번 커밋(내 커밋)
pick 895bf53d 2번 커밋(동료 커밋)
3번 커밋은 1번 커밋으로 합쳐지고 1번 커밋 로그만 남는다. 만약 이미 푸시한 커밋이라면 아래와 같이 강제 푸시를 시도할 수 있다. 이 경우 동료들은 원격 저장소로부터 갱신된 트리를 받아와야 한다.
$ git push -f
git 가이드라인에는 “이미 공개 저장소에 Push한 커밋을 Rebase 하지 마라“는 금기 사항이 있다. 리베이스한 커밋을 강제로 푸시할 때에는 동료들과 사전 합의가 필요하다.
동료가 리베이스한 커밋을 푸시했다면 갱신된 트리를 받아오기 위해 현재 작업 중인 내용을 임시 저장한다. 그리고 오리진 기준으로 브랜치를 초기화한 다음 내 작업 내용을 복원한다. stash
명령은 작업 내용이 스테이지에 있는지 여부와 무관하게 모든 변경 사항을 저장하고 복원해 준다.
$ git stash
$ git reset --hard origin/xxx
$ git stash apply
fixup
은 합치는 커밋의 로그 메시지를 제거하여 남기지 않는다. 한편 squash
는 합치는 커밋의 로그 메시지를 커밋 로그에 그대로 남기거나 편집할 수 있다. squash
로 제거한 커밋의 메시지는 이전 커밋에 포함한다.
인터렉티브 리베이스 과정에서 편집 모드에 진입하기 전 행 삭제 명령 dd
를 이용하면 해당 커밋을 삭제하는 것도 가능하다.
Git 도구 - 히스토리 단장하기, Git 도구 - Stashing과 Cleaning 문서를 참고했다.