새소식

Programming/VCS

[git] 한 개의 커밋을 둘 이상으로 분리하기

  • -

아직 push 하지 않은 커밋이라는 기준으로 설명합니다. 이미 push 한 커밋을(혼자 쓰는 저장소라면 상관없다고 생각합니다..) 변경시키는 것은 다른 참여자 저장소를 꼬이게 할 수 있으니 자제하시기 바랍니다.

git log 에서 원하는 커밋 해시명을 맨 처음에서부터 7자 이상 복사합니다.

예를 들면, commit 7a8b9c1..... 라고 시작하면 7a8b9c1 을 복사합니다.

git rebase -i 7a8b9c1 

vim 또는 nano 형태 또는 이미 시스템에서 기본값으로 지정한 편집기에 pick 해시값 커밋로그 형태로 목록이 떠 있을 것입니다.

이제 7a8b9c1 가 있는 줄을 찾아 pick 이라고 되어 있는 것을 지우고 edit 로 바꿉니다.

참고로 vim 에서는 p로 커서를 이동한 다음 cw 누르고 edit 누르고 ESC 키 누르신 다음에 ZZ 를 누르시면 잘 바뀌고 저장됩니다.

저장이 실패하지 않으면 이제 edit 로 지정된 커밋이 가장 마지막 커밋인 임시 상태로 바뀝니다.

혹시나 발생할 수 있는 실수를 피하기 위해서 git log 명령을 내려 맨 윗 줄의 커밋이 현재 수정하고자 하는 커밋인지 확인합니다. 커밋 메시지만으로 잘 모르겠으면 git show HEAD 명령으로 소스 변경사항을 확인합니다.
이왕 하시는 김에 확실히 하시려면 이 변경 내역을 메모장이나 notepad++ 같은 곳에 붙여 넣으시고 작업하시는게 실수 줄이는데 도움이 될 것 같습니다.

원하는 커밋이 맞다면 git reset HEAD^ 명령을 내립니다.

현재 커밋이 커밋 직전 상태로 바뀌고 git status 하면 수정된 파일 목록이 보이는 상태가 됩니다.

git add -p 명령을 내리면 바뀐 부분을 작은 부분(git 에서는 hunk 라고 부릅니다.)으로 나누어 스테이징 할 것인지 묻게 됩니다.
Stage this hunk [y,n,q,a,d,j,J,g,/,s,e,?]?

더보기

y를 누르면 화면에 보이는 부분을 스테이징 하겠다는 것입니다.
n을 누르면 화면에 보이는 부분을 건너뛰고 다음 부분을 보여달라는 뜻입니다.
q를 누르면 현재 부분부터 남은 모든 부분에 대해 더이상 진행하지 않고 종료하겠다는 뜻입니다.
a를 누르면 현재 부분과 남은 모든 부분을 스테이징하겠다는 것입니다. q랑 반대라고 보시면 됩니다.
d를 누르면 현재 부분부터 현재 파일에 포함된 나머지 모든 부분에 대해 진행하지 않고 다음 파일을 보겠다는 뜻입니다. q랑 비슷하지만 q는 무시하는 대상이 전체이고 d는 현재 파일이라는 점만 다릅니다.
j를 누르면 이 부분을 비결정 상태(undecided)로 만든 뒤 지나가고 다음 비결정 부분을 찾습니다.
J를 누르면 이 부분을 비결정 상태로 만든 뒤 지나가고 다음 부분을 찾습니다. j는 비결정 표시된 부분만 찾고 J는 그냥 다음 부분을 찾는 점이 다릅니다.
g를 누르면 한줄짜리 간단한 차이점 형태의 목록을 보여주고 맨 앞의 숫자값으로 선택할 수 있게 해줍니다. 잘못 눌렀다면 q를 누르면 다시 이전 프롬프트로 돌아갑니다.
/를 누르면 정규식 형태로 찾을 단어/패턴을 입력하면 일치하는 부분을 찾아서 보여줍니다.
k를 누르면 이 부분을 비결정 상태로 만든 뒤 지나가고 이전 비결정 부분을 찾습니다.
K를 누르면 이 부분을 비결정 상태로 만든 뒤 지나가고 이전 부분을 찾습니다.
s를 누르면 현재 부분을 더 작은 부분으로 나눕니다. git add -p 를 쓰다 보면 y,n 과 함께 가장 많이 쓰게 되는 기능입니다. 다만, git이 코드를 분리할 수 없다고 판단하는 경우 더이상 작게 나눌 수 없다고 알려줍니다. 그럴 땐 아래 기능을 쓰셔야 합니다.
e를 누르면 현재 부분을 직접 편집할 수 있습니다. 평소에는 쓸 일이 없고 s로 나눈 결과가 맘에 들지 않거나 더 나눌 수 없는 경우에 직접 수정할 수 있습니다. 이 부분은 patch 파일 또는 git diff 메시지에 대해 어느 정도 지식이 있는 경우에만 추천합니다. 잘 모르시면 절대 사용하지 마세요!
?를 누르면 영문으로 된 도움말을 보여줍니다.
여기에서 보여주는 내용은 git에서 추적(tracked)하고 있는 파일만 보여줍니다. 당연히 새로 추가한 파일은 수동으로 git add 해줘야 합니다.
여기에서는 이미 커밋된 내용을 분리하는 상황이므로 git add를 사용할 일이 적을 것 같습니다:)

원하는 부분만 모두 staging 되었다면 git commit 을 수행합니다.

바로 직전 커밋을 잘못 했다면 다시 내용을 변경한 다음에 git add 하시고 git commit --amend 하시면 마지막 커밋에 반영할 수 있습니다.

작업한 하나 이상의 커밋 내용이 마음에 들지 않아서 처음부터 다시 시작하고 싶으면 git commit --abort 명령으로 중지한 다음 맨 처음 과정부터 다시 시작하면 됩니다.

이 과정을 반복해서 정상적으로 커밋을 모두 마쳤다면 git rebase --continue 명령을 내리면 모든 작업 내용이 반영됩니다.

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.