7. Pull 및 충돌 해결하기
- 오늘 할 내용 요약
* 충돌은 자동병합 실패 시 발생
* 겁먹지 말고 걱정하지 말고 충돌 해결하자
* 실패하면 다시하면 된다
안쓰는 브랜치 삭제하기
현재 브랜치(헤드)가 아닌 경우 간단하게 삭제 가능
브랜치를 삭제했을 경우 사라지는 커밋이 있는지 없는지 확인하자
머지한 후에는 브랜치를 안전하게 삭제할 수 있다
git pull
서버의 내용이 내 PC보다 최신일 경우 pull을 적용한다
충돌이 날 수 있지만 놀라지 말자
pull = fetch + merge
소스트리에서 'Pull' 에 불이 들어옴 = 내 로컬PC 보다 앞선 커밋이 서버(깃허브, 원격저장소)에 저장되어있다는 뜻
여러명과 작업할때는 자주 발생하는 상황임.
'Pull' 을 누르면 원격저장소의 내용이 내 PC에 적용됨
pull에서도 충돌이 발생할 수 있음!
충돌의 발생 원인
자동병합을 실패했을 경우 발생
주로 두 커밋이 같은 파일을 편집했을 경우 발생
*** 충돌을 방지하기 위해 main(master)에서는 작업하지 않는 것이 좋음
일반적인 해결 방법
병합 시 충돌이 발생하면 '커밋하지 않은 변경사항' 이 표시됨
세모 안에 느낌표가 있는 아이콘으로 충돌이 발생한 파일을 알려줌
해결하기 위해
1. 에디터(ATOM, VS Code 등)를 이용해서 직접 수정 후 커밋
현재 변경사항(main)과 수신 변경사항(병합할 브랜치)이 서로 다른 색깔로 표시되고, 브랜치 이름도 표시됨
두 내용 다 추가하고 싶다면 shift+delete로 필요없는 줄('<<<<HEAD' 등)을 삭제하고,
저장하고 싶은 형태로 수정을 완료한 후 저장함 (텍스트파일이 아닌 소스코드라면 상당히 불편할 것... 충돌 해결 툴을 사용할 수 있음)
이를 스테이지에 올린 후 커밋하면 커밋메시지가 자동으로 표시되고
("Merge branch '브랜치이름'
# Conflicts:
# '충돌일어난 파일이름')
수정하거나, 혹은 그대로 다시 커밋, 푸쉬하면 해결! (실패하면 '되돌리기' 하면 됨)
2. 소스트리에서 " '내것'을 이용해 해결" / " '저장소' 것을 사용하여 해결" 중 하나를 선택하여 해결
소스트리에서 '커밋하지 않은 변경사항' 에서 충돌이 발생한 파일을 우클릭 > '충돌해결' 클릭,
충돌이 발생한 부분 중 main의 것을 사용할 지, 머지한 브랜치의 것을 사용할 지 선택할 수 있음 (둘다 사용할 수는 없음)
충돌 해결 후 커밋, 푸쉬하면 됨
8. reset을 이용한 커밋 되돌리기
이전 커밋으로 되돌리기 기능은 git을 사용하는 큰 이유 중 하나임
1) reset 사용해보기 (비추)
* git reset --hard 옵션으로 커밋을 되돌리기
* reset 이후 push는 '강제' 옵션을 선택해야 함
* 이전 커밋은 사라짐
* 장점 : 쉽다
* 단점 : 커밋이 날아간다, 강제 push가 필요하다
소스트리 - 되돌아갈 커밋을 우클릭 > '이 커밋까지 현재 브랜치를 초기화'
reset에는 여러가지 모드가 있음
soft - 모든 로컬 변경사항을 유지
mixed - 작업 상태는 그대로 두지만 인덱스는 리셋
hard - 모든 작업 상태 내 변경 사항을 버림
모드 설명은 CLI에서 하도록 하고, 일단 reset - hard 가 되돌리기임
다만, 원격 저장소에 push 해두었기때문에 아예 내용이 날아가진 않았음
되돌리기 후 다시 원상태로 돌아가려면 원래 데이터가 남아있는 상태의 커밋을 병합시키면 됨
파일 변경 후 커밋, 푸쉬 후 내용을 다시 되돌려서 내용 추가 후 커밋하게 되는 경우,
Push와 Pull 모두에 불이 들어오게 됨
Pull은 되돌리기 이전에 push한 내용임
이때에 Push하려고 하면 오류가 발생하게 됨 - push하려는 원본이 원격 저장소보다 과거의 것이기 때문임
=> 강제 Push 하면 됨 (*** 소스트리는 강제 푸시 기능을 지원하지 않음)
CLI - git push --force 로 강제푸쉬 가능
BUT ) 원래의 기록은 다 사라지게 됨
강제Push 하지 않고 해결하려면 좀 더 복잡해지게 됨
1. 되돌리기한 시점 이후의 커밋(Push했던 커밋) 을 현재 분기에 병합시킴 -> 충돌 발생
2. 충돌해결 - 내것을 이용해 해결
3. 커밋하면 자동으로 해결되어 머지됨 => 강제Push 아닌 자동Push 가능
*** rebase를 이용하면 좀더 이쁘게 할수도 있음
*** 제일 나쁜 방식의 커밋 되돌리는 방법임
9. 브랜치를 만들어서 커밋 되돌리기
- 이전 시간 복습
* 이전 커밋으로 되돌리기
1) reset (hard reset) 이용하기
: 되돌아갈 시점의 커밋에 대고 '이 커밋까지 현재 브랜치를 초기화' > Hard 선택하면 되돌아감
단, 이 경우 강제 Push를 하거나 병합하는 방법이 있음
강제푸시의 경우 커밋이 사라질 수 있으므로 좋지 않은 방법임 (원격저장소에 내용이 없다면 커밋이 사라짐)
2) 새로운 브랜치를 만들어서 체크아웃하기 (추천)
* 되돌릴 커밋 대상으로 브랜치 생성
* 체크아웃
* 작업 후 master(main)에 머지
* 장점 : 쉽다, 기록이 다 남아있다, Push 할 때 문제가 발생하지 않는다
* 단점 : 트리가 지저분해진다(별거아닌 단점임)
*** 브랜치 이름은 개발할 기능 이름으로 하는 것이 좋음
1. 되돌아갈 커밋에서 브랜치를 생성하면 됨,
2. 내용을 변경/추가/수정 후 기능이 잘 돌아가는 상태로 작성을 완료하면
3. master 브랜치로 돌아가서 기능을 추가한 브랜치를 병합함 ('fast-forward가 가능해도 새 커밋으로 생성' 은 체크하지않음)
-> 충돌 발생함
4. 수정/추가한 기능을 master에 반영할 것이기 때문에 '충돌해결' > ' '저장소' 것을 사용하여 해결' 을 클릭함,
5. 커밋하면 됨
혼자 작업할 때 추천하는 방식임
10. revert를 사용해 커밋 되돌리기
- 이전 내용 복습
* 커밋 되돌리기
1) reset을 이용해 되돌리기 : '이 커밋까지 현재 브랜치를 초기화' + 'Hard' 옵션 -> 강제푸시해야함, 소스트리에는 강제푸시 기능이 없으므로 CLI에서 git push --force 를 입력함
2) 브랜치를 생성해서 되돌리기 : 되돌아갈 커밋에서 새 브랜치 생성하여 체크아웃 후 작업이 끝나면 main으로 돌아가서 병합, 충돌 발생하므로 '충돌해결' > '저장소' 것을 이용하여 해결
3) revert 사용해보기
* 대상 커밋을 HEAD 커밋의 자식으로 새로 생성한다
* 장점 : 이전 커밋 기록이 다 남아있다
* 단점 : 충돌 날 가능성이 매우 높다, 다소 어렵다
*** 마크다운 문서 - 마지막 한줄 비워둬야함
'커밋 되돌리기' 를 사용하면 해당 커밋의 이전 커밋(수정 전 버전)이 새 커밋으로 생성됨
되돌아간 것처럼 보이지만 이전 커밋이 남아있음 + 모양도 깔끔함
요약하자면, revert는 커밋을 보존하면서 내용만 되돌릴 수 있는 방법임
이는 reset과 달리 커밋 기록이 남아있게 됨 (reset 했을 때는 커밋 기록이 사라져서 reset 후에는 다시 이전으로 돌아갈 수 없게 됨)
다만 충돌이 발생하기 쉬움
11. Revert로 여러 커밋 되돌리기
- 복습
revert로 쉽게 커밋을 되돌릴 수 있음
이전 커밋이 남기 때문에 좋음
SourceTree에서 되돌리고 싶은 상태의 커밋을 우클릭(* 돌아가고 싶은 상태의 커밋 아님!!!) > '커밋 되돌리기'
revert로 여러 커밋을 되돌리는 방법
최신부터 순서대로 revert를 반복 적용하면 됨
commit 1 : 새 파일 생성, commit 1 기록
commit 2 : commit 2 기록
commit 3 : commit 3 기록
=>
commit 3 - 커밋 되돌리기하면 커밋 메시지는 'Revert Commit 3' 이 되고, 새 커밋이 생김 : commit 2와 내용 동일함
reset은 되돌아가고싶은 커밋을 선택해서 '이 커밋까지 현재 브랜치를 초기화' 해서 한꺼번에 커밋 여러개를 싹 지워버렸지만 revert는 그렇게 하면 안됨
revert는 항상 쌍을 이루게 됨
commit 3 --- Revert commit 3(commit3을 되돌리므로 commit2 내용) 두 커밋이 쌍을 이룸
*** 잘못된 방법
commit 1로 revert로 되돌아가고 싶은 경우,
commit 2 에서 '커밋 되돌리기' > 충돌 발생 > 수신 변경사항 수락(commit 1의 내용) 하는 방식
=> 두 단계로 revert 하는 것이 맞음
Revert commit 3 을 만든 후
Revert commit 2 를 만들어줌
터미널로 적용해보자
(현재 commit 3 상태)
git revert HEAD HEAD~1 // git revert HEAD = 가장 최신 상태로 되돌려라, HEAD~1 = HEAD의 아빠
=> HEAD와 HEAD의 아빠를 순서대로 되돌리라는 뜻 (Revert "commit 3")
빠져나올 때는 :wq 입력하면됨 (Revert "commit 2")
한번 더 :wq 입력하면 끝남
소스트리로 돌아가보면 Revert commit 3, Revert commit 2 생성된 것 확인할 수 있음
*** 장난치고 싶을 때는 test 브랜치를 생성해서 이것저것 해보다가 다 하고나면 test 브랜치만 삭제하면 깔끔해짐
'git' 카테고리의 다른 글
[Git과 GitHub 입문] 12~16 stash, rebase (0) | 2023.10.10 |
---|---|
[Git과 GitHub 입문] 4~6 변경사항 취소, 브랜치, 병합 (0) | 2023.10.07 |
[Git과 GitHub 입문] 1~3 깃헙 회원가입하기~소스트리 사용 (0) | 2023.10.05 |
깃허브 프로젝트 올리기 (0) | 2023.07.25 |