생활코딩 Git

Git3 - SourceTree (2)branch & conflict

finepiz 2021. 11. 8. 15:43

https://youtube.com/playlist?list=PLuHgQVnccGMCWlMygyYg9XjCIjESUbW4b

 

GIT3 - Sourcetree 브랜치 & 충돌

 

www.youtube.com

--------------------------------------------------------------------------------------------------------------------

@git3 - Sourcetree branch & conflict 1.수업 소개(브랜치와 충돌)

branch : 줄기에서 뻗어나오는 가지

 

지금부터 Branch라는 기능 없이 작업한다고 치면 어떻게되냐?

지금까지 우리가 작업했던 저장소는 master라는 이름을 붙임.

master저장소 전체를 카피해서 디렉토리를 3개 더 만들고, 고객사의 이름을 붙임.

버전관리를 사용하는 이유는 파일의 이름을 더럽히지 않으면서 버전관리하려는 것.

근데 저렇게 디렉토리 이름이 다 다르면 이름이 더럽혀진것임.

그리고 Google쪽 하다가 보니까 이게 애플에도 필요한거라서 이걸 애플이랑 합쳐서 새로운 버전을 만들어내

그럼 Google GE, GF는 애플쪽으로는 안감. 유실됨.

 

또 코드를 병합하는 과정에서 생기는 여러 가지 문제들을 수동으로 하나하나 다 처리해야돼

서로다른 파일을 수정했을 때는 자동으로 합치면 되는데 그것도 수정해야되고(뭔말?)

같은 파일의 서로 다른 위치를 수정했을 때는 그것도 그냥 합치면 되는데 그것도 꼼꼼히 따져보면서 합쳐줘야함.

같은 파일에서 같은 부분을 수정했는데 실수로 덮어쓰기해서 작업했던 내용을 날려버릴 수도 있다.

 

이런지옥속에서 우리를 구원해주는 도구가 git branch기능

같은뿌리에서 나왔지만 서로다른 역사를 쓰고있는 버전들을 branch.라고함 이걸 유지하면서 생기는 여러문제를 깔끔하게 해결함.

 

근데 브랜치를 시도하려면 필연적으로 극복해야할 주제가 Conflict(충돌)

브랜치와 브랜치를 병합할 때

이 둘은 신경안써도됨.

같은 파일인데 같은 부분을 수정해줬다면 Git이 병합을 중지시키고

충돌이 났으니 이부분은 수동으로 수정해주십쇼하고 요청을 함. = Conflict

 

Conflict는 사고가 아니고, Git이 제공하는 가장 멋진 기능이다.

--------------------------------------------------------------------------------------------------------------------

@Branch기본사용법

HISTORY를 읽는 독해력을 갖기.

어떤 일을 할때마다 HISTORY가 어떻게 바뀌는지 보기.

 

일단 branch의 목록은 BRANCHES라고 적혀있는 이 부분에 적혀있다.

master가 이미있는데, master라는 기본 브랜치 위에서 작업을 해왔던 것. = 브랜치없이는 아무것도 못함.

 

브랜치 만드는법 : 브랜치 버튼 클릭 하고 apple google ms만들면

HISTORY master옆에(그시점이라는거겠지) apple google ms 이 오는걸 볼 수 있음.

저 옆에 동그라미가 현재 저기에 있다고 알려주는 것. 더블클릭하면 바뀜. = 바뀐다는 말은 워킹디렉토리에 있는게 바뀐다는 뜻이야!! 저거 더블클릭할때마다 탐색기에서의 내용이 바뀌어!

 

마스터에서 브랜치를 빼놓은다음에 마스터를 수정해도 빼놓은것은 수정안돼! 그 시점이군

그리고 저 왼쪽의 그림은 자신들의 부모가 누군지 알려준다,  work3에서 왔기 때문에 저렇게 표시를 해준다.

apple master, google은 공통의 작업도 갖고 있고, 서로 다른 작업도 갖고 있다!

--------------------------------------------------------------------------------------------------------------------

@기본사용법2

HEAD : 현재 여러분이 속해있는 브랜치

소스트리에선 저 동그라미가 HEAD, 현재 master에 있는데 현재 HEAD master branch인것임

 

HEAD를 옮기는 행위를 checkout이라고 함. ~ chekcout = ~로 옮긴다.

 

▽work 1로 헤드를 옮긴다음에 브랜치 만들었더니 거기에 만들어지네?

 

헤드를 통해 브랜치를 찾을 수 있고, 그 브랜치가 가리키고 있는 최신 커밋을 통해 브랜치의 현재 상태를 알 수 있다.

--------------------------------------------------------------------------------------------------------------------

@merge

병합.

 

a브랜치에서 작업했던 내용이 m에서도 유용할 것 같아! 할 때 씀.

 

합치려고 하는 둘의 공통의 조상을 base라고 함.

합친걸 merge commit이라고 함.

 

merge를 수동으로 한다면 굉장히 신경쓸게 많다.

1000개의 파일의 구석구석에 숨겨져 있는 코드를 합친다고 생각해봐 --불가능

다음시간에

--------------------------------------------------------------------------------------------------------------------

@브랜치 지우기, 서로 다른 파일 병합.

우클릭하고 삭제한뒤 강제삭제 체크해야 삭제됨. 우리가 아직 병합을 하지 않았는데 삭제하니까(브랜치는 병합하려고 하는건가본데?) 유실될까봐 확인하는 것. 그럴땐 강제(force)한다.

 

파일을 만드는건 어디로 헤드가 가 있든 상관이 없다. 커밋을 어디서 하느냐네. 아무데서나 파일 만들고 헤드 어디다 둬도 그 파일은 항상 있어. --그 파일이 버전에없으면 건들질 않으니까?

 

병합은 순서가 제일 중요해.

누구를 누구에게 병합할 것인가!

누구에게 에 헤드를 둬야함. checkout하는것임.

그다음 다른 브랜치를 우클릭하고 현재 브랜치로 apple병합 을 클릭.(체크는 설명안함)

 

파일명이 다르면 자동으로 합쳐주고, 그래프상에도 그 버전의 부모가 둘로 표시된다.

--------------------------------------------------------------------------------------------------------------------

@같은파일, 다른부분 병합

누구에게 누구를 로 구분하는건가?

누구를 병합에서 누구를 이 우선되는것같은데 --아님. 부모랑 비교해서 바뀌면 그걸로 되는것.

3 way merge

 

어쨌든 생각대로 잘 된다.

 

학원에서 브랜치 -> 머지 -> 풀 이런 순서는 그냥 한번 실험해보는 브랜치를 말하는것인 듯. 생활코딩에선 회사마다 다른거 라고 했으니까 일단 써둠 생각나서.

--------------------------------------------------------------------------------------------------------------------

@다른브랜치가, 같은 파일, 같은 부분 병합 - 

merge했을 때 충돌이 일어남 - 병합 충돌이 있습니다. 충돌된 파일을 선택 후 충돌 해결 밑의 메뉴를 사용하여 해결할 수 있습니다.

 

그럼 이제 ! 표시가 있는 그걸 보면

 

<<<<<<< HEAD

content 2 23

=======

content 2 49

>>>>>>> apple

 

======= 를 중심으로, 위에건 내것의 내용 // 아래건 병합될 apple의 내용 이라고 아주 친절하게 알려줌.

 

!표시의 아이콘을 우클릭해서 충돌해결 - Mine // Theirs 가 있음.

Mine하면 HEAD의 것으로.(내것을 이용해 해결) // 다른건 Theirs. (저장소 것으로 해결)

내가 수정한다음에 mark resolved 해도됨. : 한글로 해결된 것으로 표시

 

commit에도 내용이 자동추가.

--------------------------------------------------------------------------------------------------------------------

@ 3 way merge

충돌에 대해서 좀 더 깊게 알아보기

충돌이라는 것은

- 브랜치와 브랜치를 병합할 때도 일어나고

사실 다른사람과 협업할때도 걔가 브랜치를 쓰는 거거든요.

 

당황하지 않으려면 충돌의 속성을 이해할 필요가 있다.

git은 어떻게 충돌을 파악하는가.

 

어떤 파일에

A

B

C

D

라는 각각의 내용이 있다고 치기. 4개의 문단이든 함수든 있다고 생각

여기서 양옆으로 브랜치를 만듦

그리고 이렇게 수정. 병합했을 때자동과 수동은 어느 부분일까?

2 way merge : 두개의 브랜치를 비교해서 병합하는 것

이렇게 충돌난다, 이걸로 완벽한 프로그램이야. A는 충돌 안 나잖아

근데? 어떤 사람들은 여기서 만족 못하고 좀 더 많은 것들을 자동화 하고 싶음.

 

3 way merge 라는 환상적인 테크닉 : base까지 낌, 3 개의 브랜치를 비교해서 병합하는 것.

*git에서 branch가 쪼개져 나갈 때 공통의 조상을 base라고 함. 위에 배웠지

- here 와 there는 브랜치의 이름이고, base는 git 의 base 그거다.

- H D T : 는 D에서 둘다 수정했어 = 자동 병합 못해 = 사람이해야해 = 충돌

- ★H B B : here만 H로 수정이 일어남. => 수정한 H를 채택!

- ★C C T : there만 T로 수정이 일어남. => T!

 

2 way merge와 다르게 3 way merge base와 비교해서 수정한 부분으로 merge가 됨. 훨씬 더 많은 부분을 자동화해서 병합

 

--------------------------------------------------------------------------------------------------------------------

@실제 충돌하면, 외부 도구 이용 병합

근데 그냥 해도 3 way merge 를 하네. 검색해보니 3 way merge를 지원하는 프로그램을 선택하는게 좋다는데 소스트리는 3 way merge 인가봐

 

▽3 way merge로 해도 충돌하는게 있을 때, 이때 내가 직접 수정하면 되는데, 이때 베이스가 드러나 있지 않아서 쉽지 않음, 간단한 txt가 아닌 복잡한 파일이라고 생각해보면 이해가 됨. 이떄 병합도구를 이용

 

merge tool best compare 2021 검색

p4merge 추천

 

tool - option - diff(비교) - merge tool(병합도구)

맥은 Preference - diff 에서 지정

 

그다음 파일 우클릭 후 Launch External Merge Tool(외부 병합 툴 시작)

LOCAL, BASE, REMOTE // 위에 클릭하면 그거대로, 아래는 직접 수정 -> 저장하고 나가면 적용됨

--------------------------------------------------------------------------------------------------------------------

@마치며

브랜치라는 개념은 GIT이 등장하기전까지 있었지만 어렵고 비효율, 위험했음.

잘 사용 안됐다.

 

GIT이 나오고 여러 효율성을 획기적으로 극복. 브랜치는 서서히 일상으로 스며듦.

브랜치를 만들어서 거기서 버전을 완성한 다음에 필요없으면 버리고, 필요하면 마스터로 병합한 후에 버리고

브랜치는 버릴수있는 작업을 만들수있는 최선의 도구가 됨.

 

관심을 가져볼 주제

 

git workflow : 브랜치를 어떻게 나의 삶 속에 적용할 것인가 : 사례를 공부해보자

git workflow로 검색하면 여러사례들이 있을거고, 

그 사례중 하나인 git flow찾아보면

개발자들에게 널리 채택된 모범 사례를 살펴볼 수 있다. 

이 모범사례를 쉽게 적용할 수 있도록 고안된 소프트웨어인 git flow 라는 프로그램도 있음.

혼자서 규칙을 정한것보다 많은 사람이 머리를 맞대서 정한 규칙이 장점이 있을 것.

이런사례는 사람들이 숙지를 하고 프로젝트에 참여하는 경우가 많아 이런건 표준처럼 사람들이 업무에 빨리 집중하게 하는데 도움을 줍니다.

 

cherry-pick 이라고 하는 기능. --병합과 관련된 기능

1이라고 하는 버전을 base로 하는 두개의 브랜치

master로 other브랜치에 있는 모든 변경사항을 병합하는게 아니라, b2의 변경사항만 갖고 오고 싶을 때(a3 + b2 = a4)

부분적으로 병합

 

rebase

기능이다. merge와 목표 자체는 같은데 타임라인을 훨씬 더 깔끔하게 할 수 있다. --안해도된단얘기

other브렌치의 베이스를 master브렌치로 바꾸는 것 

이건 어떻게 동작하냐면

b2,b3을 임시로 옮겨놓고

b2를 a3와 병합, a3+b2 = a4

b3를 a4와 병합 b3 + a4 = a5

병합한 효과를 내면서도 타임라인이 깔끔하게

▽결론은 한 브랜치에서 일을 했던것 처럼 만들어준다 이거아니여

 

이걸 강제하는 프로젝트도 있으니 필요로하게될때 그때 공부하래

 

 

인생에 브랜치가 있다면 얼마나 좋을까

하지만 인생에는 버전만 있고, 리셋도 없고 브랜치는 더욱 더 없다.

잃어버려야만 소중함을 알게되는것들이 많다. 그래서 잃어버릴수밖에 없는것들이 참 많죠

사랑하는 사람들에게 후회없이 사랑을 하면 좋겠습니다~

 

--------------------------------------------------------------------------------------------------------------------

@HEAD BRANCH COMMIT 관계 컴팩트 정리

우리수업의 주인공은 HEAD, Branch, Commit
얘네의 관계를 살펴볼 것

HEAD, Branch, Commit : 데이터
CHECKOUT, RESET : 데이터를 조작하는 방법

checkout과 reset은 닮은듯 비슷함


시~작
저장소를 만들게 되면 기본적으로 head라고 하는게 만들어짐. 심지어 .git에 들어가보면 HEAD라는 text파일이 있어

또 기본적으로 저장소를 만들면 master 브랜치가 생성이 되고
우리가 작업을 하는것도 기본적으로 마스터 브랜치 위에서 버전을 만들어가는 것.
=>저장소가 만들어지면 헤드가 만들어지고 그 헤드는 기본적으로 마스터 브랜치를 가리킴
=>헤드를 보고 아 현재 나의 저장소는 master브랜치에 checkout돼 있구나, master branch상태구나.

그리고 우리가 comnmit id가 1인 버전을 만들게 되면
우리가 master브랜치의 상태에서 만들었기 때문에
마스터 브랜치가 1이라는 버전을 가리키게 됨.(뒤에 설명 나옴)


*이 저장소가 어떤 브랜치에 checkout돼 있는지는 HEAD를 보고 알 수 있다. --▽브랜치에 관한게 HEAD군?
클라이언트 마다 다른 HEAD를 확인하는 방법

CL : git log 해 보면

HEAD 가 가리키는 것

토토이스깃은 빨간색표시 소스트리라는 클라이언트는 저렇게 동그라미


어떤 브랜치냐는 HEAD
이 저장소가 어떤 버전으로 돼 있냐 는 (HEAD가 가리키고 있는)브랜치가 가리키는 버전.

HEAD가 가리키는 건 브랜치
브랜치가 가리키는건 버전

여기서 버전 2라는걸 하나 더 만들면
- 이 버전 2는 부모가 1이라는걸 알고(버전에 적혀있다)
- 이제 master브랜치는 2라는 버전을 가리키게 됨.

현재 이 저장소의 버전이 뭐냐 : 헤드를 따라 마스터(브랜치)를 따라 가리키는곳.

현재 = 헤드를 따라
버전 = (헤드를 따라간 후 나오는) 브랜치를 따라

이때 브랜치를 만들게 되면
1.브랜치가 만들어지고
2.그 브랜치가 어떤 버전으로 시작할것인지 결정할 때
(1)헤드를 보고! 헤드가 가리키는게 마스터네?
(2)그럼 그 마스터를 보고 마스터가 가리키는게 버전2네?
(3)이 상태를 보고 새로운 브랜치는 버전2에서 를 git이 알고 시작.

▽항상 HEAD부터 시작하네

지금 이 상태인데,

이때 google로 checkout하게되면? 브랜치를 google로 바꾼다는 것
= HEAD가 google을 가리키게 되는 것
이제 HEAD를 보고 아 HEAD가 google이니 이 저장소는 google 브랜치에 체크아웃, 그리고 이 저장소의 최신상태는 2라는 것을 알 수 있다.


여기서 버전3을 만들면 google에 체크아웃된 상태로 만들었으니 google이란 브랜치는 3번을 가리키게됨.

이로서 마스터에서 시작한 구글은 마스터와는 다른버전을 가리키게됨.




이 상태에서 checkout 마스터를 한다는건
내부적으로는
헤드가 가리키고있는걸 마스터로 바꾼다는 말.
그리고 마스터가 가리키고 있는 2번이라는 버전으로 이 저장소를 바꾸는 것.
▽버전과 브랜치가 완전 병렬인가? 따로노네

브랜치는 그냥 어느 버전을 가리키고 있냐네

브랜치가 버전을 만들긴 해 병합되는 것도 브랜치가 자기해당 버전들을 기억하고는 있어

 

∴ checkout이라는건 결국 HEAD의 값을 바꾸는 것.


HEAD를 branch로 지정할 수도 있지만
checkout 1 이라고 하면
이제 HEAD는 브랜치를 가리키지 않고 버전을 직접 가리킴.

저장소는 1번 저장소의 상태가 된다 : ▽'저장소'라는 애도 짚고 지나가야되네 내 하드 상태 겠지
HEAD가 브랜치를 가리키지 않고 버전을 가리키는 상태를
브랜치로부터 떨어져있다 detached 상태다.

checkout이라는건 HEAD를 제어하는것.

 

--------------------------------------------------------------------------------------------------------------------

@checkout vs reset

바로 전 시간에 checkout의 실체를 봤다

checkout과 reset은 뭔가 비슷해 거기로 가니까

 

checkout  change 하는느낌

 : 결과적으로 checkout은 언제나 HEAD를 제어

reset은 지우는 느낌

 : 결론은 HEAD가 브랜치를 가리키고 있는 동안은 BRANCH를 제어한다.

아주 정확한 얘기는 아니래

 

google브랜치에 checkout된 상태에서 Checkout master 하면 google을 가리키고 있었던 HEAD가 master를 가리킴.

 : 우리는 마스터 브랜치에 속하고, 워킹카피는 마스터브랜치가 가리키고 있는 2번 버전으로 바뀐다 = change되는 것

 

google브랜치에 checkout된 상태에서 reset master 하면 reset은 브랜치를 바꾸는 거다.(엄격하게는 조금더설명이필요) = 현재 checkout된 브랜치를 마스터가 가리키고 있는 버전으로 바꾸는 것

 : 워킹카피가 2번으로 됨.

그럼 google브랜치는 3번을 가리키고 있었는데 이제 2번을 가리키게 되면서 3번은 이제 google이라는 애랑은 상관없는애가됨, 링크가 끊김, 사라짐.

 

checkout은 HEAD를 바꾸는 것이기 때문에 change의 의미

리셋은 브랜치를 바꾸는것이기 때문에 detele

왜 delete? : 브랜치가 가리키는 커밋을 바꾸면 그 바뀐 커밋 이후에 등장하는 것들은 링크가 끊겨서 더 이상 브랜치 소속이 아닌게 되기 때문에 삭제 느낌을 받게 된다.

▽커밋은 소속된 브랜치가 있군

▽링크가 끊긴다? : 직관 저 아래 마지막 줄에 있음

 

 

checkout같은경우는 주로 뒤에 브랜치를 씀.

근데 사실 reset 뒤에는 브랜치의 이름보단 버전의 이름을 주로 씀

reset master보단

reset 1 이런식으로 씀. 똑같네 브랜치를 쓰면 브랜치가 가리키는 버전, 버전을 쓰면 그 버전

 

구글로 checkout된 상태면, reset 1 하면 구글 branch가 1번을 가리키게 되면서

 

2 3번은 이제 더 이상 구글의 소속이 아니니까 지워지는느낌

아 버전 3은 1과 2를 기억하고 있으니까 근데 1은 1만 있잖아