git

[Git과 GitHub 입문] 12~16 stash, rebase

EunaSon 2023. 10. 10. 15:25

12. 브랜치와 스태시

Comit --amend와 Stash 에 대해 알아보자

 

브랜치 체크아웃 시 주의사항

브랜치를 만들고 체크아웃을 하려면 현재 작업 디렉토리가 깨끗해야 함

(변경사항이 있을 때는 다른 브랜치로 체크아웃할 수 없음)

그런데 갑작스럽게 체크아웃이 필요하다면?

 

작업하다가 '커밋하지 않은 변경사항' 이 생긴 상태에서 (=마지막 커밋과 현재 작업 디렉토리의 내용이 다름)

체크아웃하려고 하면 오류가 발생함

이때, 갑자기 체크아웃이 필요하다면!!! 을 말하는 것임

 

1) 작업 중인 내용의 임시 저장 후 커밋 덮어쓰기

1. 브랜치1(test 브랜치)에서 일단 (임시) 커밋을 함  (-> 커밋하지 않은 변경사항 사라짐)

2. 브랜치2(master 브랜치)로 체크아웃하고 볼일을 봄

3. 다시 브랜치1(test 브랜치)로 되돌아옴

4. 1의 작업을 이어서 마무리지음 => 이때, 일반적인 커밋을 하면 1에서 생성한 불필요한 커밋이 기록에 남아있게 됨(비추)

5. 커밋 덮어쓰기 (commit --amend) 를 함 (커밋 옵션 - 마지막 커밋 정정)

6. (옵션) 필요하다면 push --force를 함

 

* 커밋 덮어쓰기

: 커밋 메시지 작성칸 오른쪽 - 커밋 옵션 - '마지막 커밋 정정' - Yes : 임시 커밋의 커밋메시지도 가져옴 No : 커밋메시지 안가져옴

커밋 덮어쓰기를 하면 1에서 생성한 불필요한 커밋이 사라지고 작업을 완료한 커밋으로 불필요한 커밋을 덮어쓸 수 있음

 

* push --force가 필요한 상황

단, 1에서 커밋 후 Push하게 되는 경우 !!! -> origin/test 라는게 생겨있음

이 상태에서 test1로 이어서 작업 후 1의 커밋을 덮어쓰려하면

마지막 커밋(임시커밋) 자체는 바뀌게 되지만 서버(원격저장소)의 커밋이 남아있어서 서로 다른 커밋이 2개 남아있게 됨

서버의 커밋은 불필요한 내용이므로

터미널에서 git push --force 해주면 됨 (강제로 현재 커밋 상태를 푸쉬하는 것. 이전에 푸쉬한 내용은 사라짐)

push 후에는 소스트리의 test 브랜치를 삭제해주고, 서버에 남아있는 origin/test 브랜치도 삭제해줌  

 

2) Stash를 이용해서 가은 작업 하기 (핵심)

1. Stash를 만든다

2. 이때 새로운 파일이 있었다면 일단 인덱스에 추가한다

3. 체크아웃한다

4. 되돌아온다

5. Stash를 Pop 한다

6. 보통 커밋을 새로 생성한다

 

- Stash

다른 브랜치로 체크아웃하기 전에 현재 작업 내용을 저장하는 임시 저장소

유용하니 잘 사용하자

 

test2 브랜치 생성, 작업하다가 '커밋하지 않은 변경사항'이 뜨고 있는 상태에서 main으로 체크아웃이 필요한 경우

아까는 임시로 커밋을 했지만 그것보다 좋은 방법은 스태시를 이용하는 것임

소스트리 - '스태시' 버튼을 클릭 > 체크박스 체크없이 확인하면

커밋하지 않은 변경사항이 사라지게 됨(커밋하지 않은 변경사항이 스태시에 저장되고 작업디렉토리에서는 해당 내용 사라짐)

따라서 체크아웃이 가능해짐

 

main으로 체크아웃해서 작업하다가 끝나면

스태시에서 해당 임시작업에서 우클릭하여 '스태시 적용' 클릭하면 현재 작업 디렉터리에 임시저장내용이 적용됨,

test2에서 다시 작업을 완료해서 커밋하면 됨. 불필요한 커밋을 만들지 않음.

 

단, 스태시 이용 시 새로운 파일 즉, 한번도 스테이징 되지 않은 파일(untracked 파일, 추적되지 않는 파일), 아직 git에 없는 파일이 있는 경우, 스태시 버튼이 활성화되지 않음

일단 스테이지에 올리고 나면 스태시에 올릴 수 있음

 

스태시 적용 후에는 불필요하므로 스태시를 삭제해줌


13. rebase로 병합하기

rebase란

병합(merge) 처럼두 브랜치를 합칠 때 사용함, 현재 브랜치가 대상 브랜치 위로 올라감

소스트리에서는 '재배치' 라는 명령임

* 장점 : 커밋 히스토리가 깔끔하게 정리됨

* 단점 : 이미 원격저장소에 올라간 경우, 협업을 하고 있는 경우에는 위험함

 

*** 깃 주의사항

- 코드를 남기려고 불필요하게 많은 주석을 달지 말자 (안쓰게 된 코드는 삭제하자)

- 커밋 메시지를 잘 쓰자

- 한가지 구현이 완료될 때마다 커밋을 하자(함수 하나 개발 후 커밋!!! 커밋 자주 하자)

 

예) 현재 커밋에서 두 개의 브랜치 rebase, etc를 생성하여 각각 작업 후 커밋

[ 병합 ]

main - rebase나 etc 둘 중 하나의 브랜치와 병합할때만 fast-forward 가능함,

etc 먼저 병합 후 rebase 병합 시 충돌 발생, 충돌 해결 후 커밋하면 됨

즉, merge의 경우엔 한 커밋의 부모가 2명(main+etc & rebase)이 됨. three-way merge 라고 함.  

[ 재배치 ]

main - etc를 일단 먼저 병합(merge)함 - fast-forward

그리고, rebase로 가서 브랜치 중 main을 우클릭 - '현재 변경사항을 main에 재배치' 클릭

= 나(rebase)를 들어서 main에다가 붙여넣음,

충돌 발생 - '두 변경사항 모두 수락' 하면 병합에서와 내용은 똑같지만,

병합에서는 커밋했던 것과 달리

다시 main에서 '현재 변경사항을 main에 재배치' 를 눌러서 재배치를 진행함

다시 main으로 돌아가서 '현재 브랜치로 rebase 병합' 을 클릭,

rebase, etc 등 이제 필요없는 브랜치는 삭제함

 

병합에서는 커밋의 부모가 둘이었지만,

재배치에서는 커밋이 갈라지지 않고 한줄로 표시됨


16. 보너스 : revert로 한 커밋 되돌리기

revert

선택한 커밋 하나의 변경사항을 되돌리는 새로운 커밋을 생성함

cherry-pick과 비슷하면서도 반대로 동작함

cherry-pick도 커밋 하나를 골라서 새로운 커밋을 생성

revert는 커밋 하나를 골라서 되돌리는 새로운 커밋을 생성

 

revert로 여러 커밋을 되돌리고 싶으면

-> 최신부터 순서대로 revert를 반복 적용하면 됨

 

특정 커밋 하나만 취소하고 싶을 경우

- 그냥 선택해서 revert 하면 되지만, 충돌이 날 가능성이 있음

 

1. 임시 브랜치 생성

2. 커밋 3번

3. 두번째 커밋만 되돌려보기(revert)

4. 모두 되돌리기(최신부터 역순으로 revert)

5. 임시 브랜치 삭제


***혼깃 요약

git 기초 명령어 요약

clone : 원격 저장소 복사

add : 스테이지 영역에 작업 파일 추가

commit : 세이브, 스테이지 영역의 파일들을 가지고 커밋(=세이브)을 만들 수 있음

push : 원격 저장소에 커밋을 업로드함

 

파일의 내용 되돌리기

특정 파일의 내용을 마지막 커밋으로 돌리고 싶다면 해당 파일 선택 후 '코드 뭉치 버리기' 선택

 

브랜치 변경하기

브랜치 : 기존 내용을 유지한 채 새로운 내용을 추가하고 싶을 때 사용함

체크아웃 : 특정 브랜치(혹은 커밋)으로 돌아가고 싶을 때 사용

소스트리의 체크아웃 : 브랜치 이름을 더블클릭하는 것만으로 체크아웃 가능

 

병합하기1

헤드브랜치에 변경사항이 없고

병합 대상 브랜치가 헤드로부터 시작된 경우

아주 쉽게 병합 가능 = fast-forward

 

병합하기2

헤드 브랜치에 추가적인 커밋이 생기는 경우

진짜 병합이 필요해짐

충돌이 안나면 좋은데, 충돌이 나도 겁내지 말자!

 

충돌 해결하기

같은 파일을 병합 대상 두 커밋에서 동시 수정했을 경우 충돌이 날 확률이 높음

에디터 사용 혹은 sourceTree를 사용해서 충돌 해결 가능

 

커밋 되돌리기

- reset 사용하기

장점 : 쉬운

단점 : 커밋이 날아감, 강제 푸시가 필요함

 

- branch 만들어서 되돌리기

reset과는 달리 내용이 사라지지 않음

장점 : 쉬움

단점 : 트리가 지저분해짐

 

- revert

역시 커밋이 없어지지 않음

장점 : 가장 정석적

단점 : 충돌이 날 수 있음

주의사항 : 현재 선택한 커밋의 내용을 되돌림

revert로 여러 커밋을 되돌리려면 최신부터 순서대로 revert해야 충돌을 막을 수 있음

 

커밋 덮어쓰기

필요하다면 이전 커밋 덮어쓰기 가능

commit --amend

이미 푸시한 경우 push --force가 필요함

 

stash 

다른 브랜치로 체크아웃하기 전에 현재 작업 내용을 저장하는 임시 저장소

유용하니 잘 사용하자

 

rebase

merge처럼 두 브랜치를 합칠 때 사용하지만 merge와 달리 커밋/브랜치 분기가 히스토리에 남지 않아 깔끔함

현재 브랜치가 대상 브랜치 위로 올라감

위험하니 조심스레 사용하자