GitNotes.12-5.md
본 문서는 Git Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

Section 12.5: rebase 시 자동 stash 설정하기

자동 stash 기능 (autostash) 은 로컬 변경사항을 rebase 할때 매우 유용한 설정 옵션이다. 가끔씩은, upstream 브랜치로부터 커밋들을 가져올 필요가 있지만 현재 상태를 커밋하기에는 아직 준비가 되지 않았을 수 있다. 그러나, git 에서는 작업 디렉토리에 작업중인 내용이 있을 경우 rebase 를 시작할 수 없게 되어 있다. 이러한 경우, 자동 stash 를 설정해 두었다면 유용할 수 있다:

git config --global rebase.autostash # 최초 한번만 설정해두면 된다 git rebase @{u} # upstream 브랜치에 대해 rebase 를 수행하는 예제

역주: @{u} 는 upstream 브랜치를 나타냅니다. 이러한 단축표현식들에 대한 상세한 정보는 이곳 에서 찾을 수 있습니다.

이렇게 자동으로 stash 된 변경 사항은 rebase 가 끝나는 시점에 다시 적용되며, rebase 가 성공적으로 끝났는지, 중간에 취소(abort) 되었는지에 영향을 받지 않고 항상 적용될 것이다.

만약 rebase 가 성공적으로 끝나서 base 커밋이 변경되었다면, 자동 stash 된 내용을 새로운 커밋에 적용시킬 때 충돌(conflict) 이 발생할 수 있을 것이다.

이러한 경우, 이후 커밋을 수행하기 위해서는 해당 conflict 을 해결해야 할 것이다. 이러한 conflict 발생 여부는 rebase 수행 전에 수작업으로 stash 를 수행하고 완료 이후 stash 된 내용을 다시 적용할때와 전혀 차이점이 없으므로 stash 를 자동으로 수행하는 것으로 인해 발생하는 부작용은 없다고 볼 수 있을 것이다.

[출처] https://books.goalkicker.com/GitBook/ (CC BY-SA)

반응형
GitNotes.12-4.md
본 문서는 Git Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

Section 12.4: 최초 (initial) 커밋으로부터 rebase 하기

1.7.12 버전 이후의 git 을 사용하고 있다면, root 커밋으로부터 rebase 하는 기능을 이용할 수 있다. root 커밋은 저장소가 생성된 이후의 가장 첫번째 커밋을 지칭하며, 일반적으로 수정이 불가능하다. 아래와 같은 명령어를 입력하여 해당 기능을 이용할 수 있다:

git rebase -i --root

[출처] https://books.goalkicker.com/GitBook/ (CC BY-SA)

반응형
GitNotes.12-3.md
본 문서는 Git Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

Section 12.3: 대화형(interactive) rebase

이 예제에서는 git rebase 의 대화형 모드를 어떻게 활용할 수 있는지를 소개한다. 설명에 앞서 git rebase 가 무엇이고 어떤 일을 하는지에 대한 기본적인 이해가 필요함을 주지하라.

대화형 rebase 아래 명령어를 통해서 시작할 수 있다:

git rebase -i

-i 옵션은 대화형(interactive) 모드를 나타낸다. 이러한 대화형 rebase 를 이용하면, 사용자는 커밋 메시지를 변경하거나 커밋들의 순서를 재조정할 수 있을 뿐만 아니라, 커밋을 분할하고 여러 커밋을 하나의 커밋으로 합칠 수도 있다.

만약 가장 최근 세개의 커밋을 재배열하고자 한다고 하면, 우선 아래와 같은 명령어를 입력한다:

git rebase -i HEAD~3

위 명령어를 입력하고 나면, 텍스트 파일 편집기가 열리면서 커밋들을 어떻게 rebase 시킬지를 선택할 수 있게 된다.

이 예제의 목표를 달성하기 위해서는, 각 커밋들의 순서를 변경한 후 파일을 저장하고 편집기를 종료한다. 이후 편집기에서 입력한 순서대로 rebase 가 수행될 것이다. git log 를 통해 보면 원하는 대로 커밋들의 순서가 바뀌어 있음을 확인할 수 있을 것이다.

커밋 메시지들을 재작성하기

또한, 이전 커밋들의 메시지가 불분명하여 해당 메시지를 좀 더 명확하게 기술할 필요가 있을 때도 있을 것이다. 최근 세개의 커밋들을 동일한 명령어를 이용하여 살펴보도록 한다.

git rebase -i HEAD~3

이번에는 rebase 할 커밋들의 순서를 재배열하는 대신에, 커밋 메시지를 변경하고자 하는 커밋에 표시된 'pick' 이라고 되어 있는 (이것이 기본값이다) 부분을 'reword' 로 변경한다.

이제 편집기를 종료하고 나면, rebase 작업이 진행되고 커밋 메시지를 변경하고자 했던 커밋의 순서가 되었을 때 멈추게 될 것이다. 이제 사용자는 커밋 메시지를 원하는 대로 변경할 수가 있게 된다. 커밋 메시지 변경이 끝났으면, 편집기를 종료하여 나머지 rebase 작업을 재개하면 된다.

커밋의 내용 변경하기

커밋 메시지를 변경하는 것에서 나아가, 커밋에 포함된 변경 내역 자체를 수정할 수도 있다. 이를 위해서는 특정 커밋의 'pick' 부분을 이번에는 'edit' 으로 변경한다. rebase 시작 이후 해당 커밋의 순서가 되었을 때, rebase 작업이 잠시 멈추게 된다. 이제 사용자는 이 커밋에 대해 새로운 변경사항을 추가하는 등의 수정을 할 수 있다.

영역에 커밋에 포함되어야 할 모든 변경사항들이 추가되었다면, 이제 실제 커밋을 수행한다. 기본적으로는 이전 커밋 메시지가 나타날 것이지만 새로운 커밋 내용에 맞추어 메시지 내용 역시 변경할 수 있다.

하나의 커밋을 여러개의 커밋으로 분리하기

새로운 커밋을 생성하고 난 이후에, 해당 커밋을 둘이나 그 이상의 커밋으로 분리하는 것이 더 좋겠다는 생각이 드는 경우가 있다.

이전 항목에서 사용했던 명령어를 똑같이 입력하고 'pick' 부분을 'edit' 를 바꾸도록 한다. 이제, git 이 편집을 하도록 표시해 놓은 커밋의 차례가 되었을때 rebase 작업이 멈추게 된다.

이 시점에서 git reset HEAD^ 명령을 수행하여 해당 커밋의 이전 커밋 상태를 작업 디렉토리에 설정한다. 그러고 난 이후에는, stage 되지 않은 대상 커밋의 변경사항들을 원하는 순서대로 add 하고 커밋하면 된다 - 결과적으로 대상 커밋을 여러개의 커밋으로 나누게 된 것이다.

복수개의 커밋을 하나의 커밋으로 합치기 (squash)

어떤 작업을 여러개의 커밋으로 나누어서 작성 완료한 이후, 해당 커밋들을 하나의 커밋으로 합치는 것이 좋겠다는 생각이 드는 경우가 있다. 이러한 경우 git rebase -i HEAD~3 명령을 입력하면 되며, 숫자 3의 경우에는 합치고자 하는 커밋의 숫자에 따라 적절하게 입력한다.

이번에는 'pick' 부분을 'squash' 로 변경한다. rebase 작업 중에, squash 하도록 명시한 커밋들은 이전 커밋의 내용에 합쳐지게 된다; 최종적으로 복수개의 커밋들이 모두 하나의 커밋으로 합쳐질 것이다.

역주: 원문에서는 'edit' 선택시 커밋의 내용이 staging 영역이 추가된 상태로 rebase 작업이 정지된다고 기술되어 있으나, 자체 테스트시 커밋이 유지되어 있어 해당 내용은 번역에서 제외하였습니다.

[출처] https://books.goalkicker.com/GitBook/ (CC BY-SA)

반응형
GitNotes.12-2.md
본 문서는 Git Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

Section 12.2: Rebase 시 "ours" 와 "theirs", 로컬과 원격 개념 이해하기

rebase 수행시에는 "ours" 와 "theirs" 의 의미가 뒤바뀌게 된다:

git checkout topic git rebase master # topic 브랜치의 내용을 master 브랜치 위에 rebase 시킨다

어떤 것이던 HEAD 가 가리키고 있는 것이 "ours" 이다

위 예제의 rebase 명령이 첫번째로 수행하는 작업은 HEAD 를 master 로 재설정 하는 것이다; 이후 예전 브랜치인 topic 으로부터 커밋들을 새로운 브랜치에 cherry-pick 하게 된다 (이전 topic 브랜치의 모든 커밋들은 새로이 작성되어 원래 커밋과는 다른 hash 값을 갖게 될 것이다.)

merge 도구에서 나타내어지는 용어 측면에서 나타내면 (로컬 ref 혹은 원격 ref 의 용어와 혼동을 방지하기 위해)

=> 로컬은 master ("ours"), => 원격은 topic ("theirs")

이는 merge/diff 도구들이 upstream 브랜치를 로컬로 (master: rebase 의 기반이 되는 브랜치), 작업중인 브랜치는 원격으로 (topic: rebase 를 하려는 브랜치) 나타낼 것임을 의미한다

LOCAL:master BASE REMOTE:topic
MERGED

도식화된 설명

merge 수행 시:

c--c--x--x--x(*) <- 현재 브랜치 : topic ('*'=HEAD) \ \ \--y--y--y <- merge 수행하려는 다른 브랜치

이 경우에는 현재 브랜치가 topic 에서 변경되지 않으므로, 작업 수행 이후에도 작업 시작 전 위치에 그대로 있게 된다 (물론 다른 브랜치로부터 merge 는 완료된 상태일 것이다)

c--c--x--x--x---------o(*) MERGE (커밋), 여전히 topic 브랜치에 위치한다 \ ^ / \ ours / \ / \---y--y--y---/ ^ theirs

rebase 수행 시:

그러나 rebase 시에는 ours / theirs 가 바뀌게 되는데, 이는 rebase 가 수행하는 첫번째 작업이 현재 커밋들을 재적용 (replay) 하기 위하여 upstream 브랜치를 checkout 하는 것이기 때문이다.

c--c--x--x--x(*) <- 현재 브랜치 : topic ('*'=HEAD) \ \ \--y--y--y <- upstream 브랜치

git rebase upstream 명령 수행시 먼저 HEAD 를 upstream 브랜치로 설정하므로, 기존의 "현재" 브랜치에서의 'ours' 및 'theirs' 와 비교시 그 의미가 바뀌게 된다.

c--c--x--x--x <- 이전의 "현재" 브랜치, 이제 새로운 "theirs" 가 된다 \ \ \--y--y--y(*) <- 커밋 x 들을 재적용 (replay) 하기 위해 HEAD 를 이 커밋으로 설정한다 ^ 이것이 새로운 "ours" 가 될 것이다 | upstream 브랜치

rebase 는 이제 'their' 에 있는 커밋들을 새로운 'our' 토픽 브랜치에 재적용 (replay) 할 것이다:

c--c..x..x..x <- 이전 "theirs" 커밋들이나 이제는 "유령(ghosts)" 이 되어 "reflog" 을 통해서만 접근이 가능하다 \ \ \--y--y--y--x'--x'--x'(*) <- 모든 x 들이 재적용 완료된 다음, ^ topic 브랜치는 이 커밋을 가리키게 된다 | upstream 브랜치

[출처] https://books.goalkicker.com/GitBook/ (CC BY-SA)

반응형
GitNotes.12-1.md
본 문서는 Git Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

Section 12.1: 로컬 브랜치들 rebase 하기

rebase 는 일련의 커밋들을 다른 커밋 위에 재적용 (reapply) 시킨다. 특정 브랜치를 rebase 하고 싶다면, 해당 브랜치를 checkout 한 후 아래와 같이 다른 브랜치의 위로 rebase 시킨다.

git checkout topic git rebase master # 현재 브랜치를 master 브랜치 위에 rebase 시킨다

위 명령어 수행시, 아래와 같은 상태가:

A---B---C topic / D---E---F---G master

이렇게 바뀌게 된다:

A'--B'--C' topic / D---E---F---G master

위 작업들은 브랜치를 checkout 한 후 바로 rebase 를 수행하는 아래와 같은 하나의 명령어로 합칠 수도 있다:

git rebase master topic # topic 브랜치를 master 브랜치 위에 rebase 시킨다

중요: rebase 된 이후에는, 재적용된 커밋들은 원래와 다른 커밋 hash 값을 갖게 된다. 따라서 원격 저장소에 이미 push 했던 커밋을 rebase 해서는 안된다. 이러한 상황에서 rebase 를 수행한다면, 이후 rebase 된 로컬 브랜치를 원격에 push 가 불가능해지며 git push --force 를 이용해 push 해야만 하는 상황에 처하게 된다.

[출처] https://books.goalkicker.com/GitBook/ (CC BY-SA)

반응형
GitNotes.12-0.md
본 문서는 Git Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

Chapter 12: Rebase 하기

파라미터 설명
--continue rebase 중 발생한 merge conflict 을 해결 완료한 경우 중단된 rebase 작업을 재개한다.
--abort rebase 작업을 취소하고 HEAD 를 원래 브랜치로 되돌린다. rebase 작업 시작시 브랜치 정보 (역주: 두번째 파라미터로 넘기는) 가 주어졌다면, HEAD 는 해당 브랜치로 되돌려지며, 그렇지 않다면 HEAD 는 rebase 가 시작된 위치로 되돌려질 것이다.
--keep-empty 아무런 변경사항을 포함하지 않는 커밋들을 그대로 유지하여 결과물에 반영한다.
--skip 현재 패치는 포함시키지 않도록 설정하여 rebase 작업을 재개한다.
-m, --merge rebase 작업시에 merge 전략을 사용한다. recursive merge 전략이 사용될 경우 (이것이 기본 옵션이다), rebase 로 하여금 upstream 쪽에서의 파일 이름 변경 내역을 인지하고 있는 상태에서 작업을 수행하게 한다. 유의할 점은, rebase merge 는 upstream 브랜치 위에 작업 브랜치의 각 커밋을 재적용(replay) 시키는 방식으로 동작한다는 점이다. 이 때문에, merge conflict 이 발생할 경우, ours 로 나타나는 쪽은 upstream 에서 현재까지 rebase 된 커밋들이며, theirs 라고 나타나는 쪽은 작업중인 브랜치가 된다. 다른말로 하면, ours 와 theirs 가 바뀌게 된다.
--stat rebase 작업시 upstream 쪽의 변경내역에 대한 diffstat 을 표시한다. 이 diffstat 은 rebase.stat 환경설정값의 영향을 받는다.
-x, --exec command 대화형(interactive) rebase 를 수행하되, 매 커밋마다 작업을 일시 중지하고 주어진 명령어를 실행한다.

[출처] https://books.goalkicker.com/GitBook/ (CC BY-SA)

반응형
GitNotes.11-8.md
본 문서는 Git Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

Section 11.8: stage 된 파일들을 unstage 시키기

보통은, 커밋하기 위해 stage 된 파일들을 stage 영역에서 다시 제거하기 위해서는 git reset 명령어를 사용하는 것이 일반적이나, reset 옵션은 주어지는 파라미터에 따라 복잡할 정도로 많은 기능들을 제공한다.

git 의 alias 기능을 활용해 새로운 alias 를 만들어 놓는다면 stage 된 모든 파일들을 완전히 unstage 시키기 위해서 reset 에 어떤 파라미터를 넘겨야 하는지 따로 외우지 않아도 될 것이다.

git config --global alias.unstage "reset --"

이제, 아무때나 stage 된 파일들을 unstage 시키고 싶다면 git unstage 명령어만 입력하면 된다.

[출처] https://books.goalkicker.com/GitBook/ (CC BY-SA)

반응형
GitNotes.11-7.md
본 문서는 Git Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

Section 11.7: 선형적인 history 를 유지하면서 코드 업데이트하기

때로는 코드 커밋들의 history를 선형적으로 (브랜치로 분기되지 않은) 유지하기를 원할 때가 있다.

만약 사용자가 분기된 브랜치에서 얼마간 작업을 수행하는 중이었다면, git pull 을 수행하여야 하는 경우 일반적으로 upstream 브랜치와의 머지 커밋이 기록되게 되므로 이러한 선형 history를 유지하기는 어려울 수 있다.

[alias] up = pull --rebase

위 alias는 upstream 코드를 먼저 업데이트한 이후에 해당 결과물 위에 아직 push 되지 않은 사용자의 커밋들을 다시 적용(reapply) 해 주게 된다.

아래와 같이 사용할 수 있다:

git up

[출처] https://books.goalkicker.com/GitBook/ (CC BY-SA)

반응형

+ Recent posts