Git + GitHub (심화)

지원·2024년 3월 8일
0
post-custom-banner

커밋 객체에는 무엇이 저장되는가

두 사람이 병렬로 커밋을 만들고 싶으면 어떻게 해야할까

두 사람이 만든 버전을 합치는 방법

남이 만든 오픈소스에는 어떻게 기여하는가

소스 트리 사용?

Git 에서 커밋이란 ?

  1. 변경 사항의 모음이 아닌 하나의 최종 코드 모음이다.
  2. 다만 기존 커밋과 비교해서 변경된 파일이 아니면 "변경되지 않음" 이라고만 저장해서 용량이 무겁지 않다.
  • 예전에 사용했던 SVN은 바로 이전 커밋과의 변경사항만 저장한다.
  • 그래서 커밋당 용량이 가볍지만 한 버전을 보려면 맨 처음 커밋부터 계산해야하기 때문에 속도가 느리다.
  • Git 은 바로 이전 커밋만 보면 되기 때문에 빠르다.

원리
0. 맨 처음 로컬 저장소를 만들면 파일 상태는 "추적안됨" 상태이고 로컬 저장소 안에 스테이지에는 아무것도 없을 것이다.
1. 파일을 올리게 되면 "스테이지" 상태가 되고 git add 를 하면 해당 파일들이 로컬 저장소 안에 스테이지에 올라가게 된다.
2. git commit 을 하면 스테이지에 있던 파일들이 하나의 커밋 객체가 된다.
3. git push 를 하면 커밋 객체가 원격 저장소에 올라가게 된다.
4. 만약 올린 파일들을 수정하게 되면 파일 상태에서 수정된 파일은 "수정 없음" , 수정된 파일은 "수정함" , 추적 안 되는 파일은 "추적안됨" 의 상태를 가진다.
5. 똑같이 git add 를 하면 모든 파일들이 스테이지에 올라가게 된다.
6. git commit 을 하면 똑같이 커밋 객체가 만들어진다.

  • 이때 수정된 파일 , 변경 되지 않은 파일 모두 스테이지에 올라가고 커밋 객체에도 올라간다.

요약
1. Git 으로 추적하는 파일의 4가지 상태 (추적 안됨 , 수정 없음 , 수정함 , 스테이지됨)
2. 작업 공간에 있는 수정함 , 추적 안됨 파일을 스테이지로 올려 스테이지 상태가 된다.
3. 커밋을 하면 수정 없음 상태로 돌아가서 다시 파일을 수정할 수 있다.

Branch

브랜치는 새로운 기능을 추가할 때 사용한다.

A , B 가 서로 다른 로컬 저장소에서 개발을 하고 있다.

  • A 는 a1 , a2 , a3 이라는 커밋을 만들었다.
  • B 는 a1 , a2 , b3 이라는 커밋을 만들었다.
  • 현재 둘의 로컬 저장소에서 서로 다른 커밋이 생기는게 어떻게 해야할까?

이럴때 Branch 를 사용하면 된다.

  • A 는 a1 , a2 , a3 의 커밋을 만들면 되고 B 는 a1 , a2 , b3 의 커밋을 만들면 된다.
  • 즉 병렬의 상태가 되는 것이다.

병렬로 커밋을 쌓는다?

  • 모든 사람이 한 줄에서 작업하면 충돌이 날 수 있다.
  • 똑같은 코드를 동시에 고칠 가능성이 있다.
  • 그래서 병렬로 하면 충돌이 나더라도 합치는 시점에 명시적으로 충돌을 해결할 수 있다.

그래서 필요한 개념이 Branch

  • a1 , a2 , a3 는 A 브랜치
  • a1 , a2 , b3 는 B 브랜치

git push origin main

  • 여기서 main 브랜치에 커밋을 푸시하라는 것이다.

git branch jiwon

  • jiwon 브랜치를 현재 시점에 만드는 명령어

git checkout jiwon

  • jiwon 브랜치로 이동하라는 명령어

그래서 git brach jiwon , git checkout jiwon 명령어를 순서대로 입력하면 jiwon 브랜치가 만들어지고 jiwon 브랜치로 이동하게 된다.

시나리오

  • a1 , a2 , a3 , a4 라는 커밋들이 있고 현재 main 브랜치는 a4 를 가리키고 있다.
  • 이때 A 브랜치를 만들고 새로운 a5 라는 커밋을 한다.
  • 다시 main 브랜치로 이동을 하고 B 라는 브랜치를 만든다음에 b5 라는 커밋을 한다.
  • 이렇게 되면 현재 a4 는 main 브랜치이지만 병렬 상태로 a5 , b5 커밋이 만들어진다.

버전 합치기 Merge

다른 브랜치에서 자겅빙 끝나서 main 에 합치고 싶은 경우

  • main 브랜치의 최신 커밋에(base) A 브랜치의 최신 커밋(compare) 을 합치려고 한다.

순서
1. 먼저 base 가 될 main 브랜치로 이동
2. compare 브랜치인 A 를 합치기 : git merge A
3. 그 결과는 A 브랜치가 가리키고 있던 곳에 main 도 가리키게 된다.

합치는 과정에서 충돌 Conflict

만약 A , B 모두 한 코드를 서로 다르게 변경을 했을 때 Conflict 가 발생한다.

  • 해결하기 위해서는 Merge 를 할 때 수동으로 고쳐줘야 한다.
  • 팀원들과 상의를 한 후 수정을 하면 된다.
  • 모두 수정 했으면 다시 commit -> push 를 해주면 된다.

저장소 통째로 복제 Fork

저장소에 푸시 권한이 없지만 기능을 더 개발하고 싶을 때 어떻게 해야할까?

  • Fork 기능을 사용하면 된다.
  • 해당 저장소를 통째로 자신의 계정에 복제해온다.
  • 그 저장소에 자유롭게 커밋 , 푸시를 한다.
  • 내 저장소의 브랜치와 기존에 있던 저장소의 브랜치를 머지해달라고 요청하면 된다.

코드 머지 요청 Pull Request

A 커밋이랑 B 커밋을 합치고 싶을 때

  • Merge 하고 싶은 2개의 브랜치를 선택
  • 어떤 변경을 했는지 제목과 내용 작성
  • 단일 저장소에서 보낼 수 있고, 포크한 저장소에서도 보낼 수 있다.
  1. mater 브랜치에 커밋을 잘못 푸시해서 이전 상태로 돌려야할 때?
  2. A 브랜치에서 빨리 고쳐야 하는 버그가 있어서 B 브랜치를 따서 개발하고 나중에 A 에 체리픽을 해야할 때?

깜빡하고 수정 못한 파일을 방금 만든 커밋에 추가하고 싶을 때 Amend

  • 소스 트리에서 커밋 메시지를 작성하는 곳 오른쪽 위에 커밋 옵션에서 마지막 커밋 수정을 누르고 커밋을 하면 된다.
  • git 명령어 : git commit --amend
  • 반드시 혼자 사용하는 branch 에서만 사용해야 한다.
  • 왜냐하면 우리가 미리 올렸던 커밋을 가지고 개발을 하던 사람이 있었다면 Amend 를 했을때 꼬여버리는 상황이 발생하기 때문에 나 혼자 사용하는 branch 에서만 사용해야한다.

변경사항을 잠시 킵 해두고 커밋을 안 만들때 Stash

  • 만약 A 브랜치에서 개발을 하다가 급하게 Main 브랜치에서 변경할 때 있다고 가정해보자.
  • 그렇다고 A 브랜치에서 개발한 것을 커밋하기에는 애매한 상황이다.
  • 이럴때 Stash 를 사용하면 된다.
  • 소스 트리에서는 위에 스태시 라는 버튼을 누르고 메시지를 입력하면 된다.
  • 이렇게 하고 Main 브랜치의 작업이 끝난 후 Stash 를 pop 해서 다시 개발을 하면 된다.
  • pop 하는 방법은 소스트리 왼쪽 메뉴에 치워두기를 열어두면 우리가 Stash 한 것이 있어서 그것을 꺼내서 사용하면 된다.

git 명령어 : git stash
stash 목록 가져오기 : git stash list
stash 가져오기 : git stash apply
stash 제거 : git stash drop

  • apply 는 단순히 stash 를 가져오기만 하기 때문에 스택에 남아있는 stash 를 제거해야한다.

옛날 커밋으로 브랜치를 되돌리고 싶을때 Reset

  • 개발했던 기능의 요구사항이 변경되어 그때 브랜치로 돌아가서 다시 개발을 해야할 수 있다.
  • 소스 트리에서는 돌아가고 싶은 커밋에서 마우스 오른쪽 클릭을 하면 "main 을 이 커밋으로 초기화" 메뉴를 누르고 사용중인 모드를 선택하고 확인을 누르면 된다.
  • A 브랜치에서 옛날 커밋으로 돌아간 후 push 를 할 때 경고가 발생하는데, 강제 푸시를 해야한다는 경고이다.
  • 강제 푸시(force push)는 우리가 이미 원격 저장소에 올렸던 커밋들을 수정할 때 사용한다.
  • 이것도 혼자 쓰는 브랜치에서만 사용해야한다.
  • 소스트리에서는 설정 -> 고급 -> 강제 푸시를 허용 체크

git 명령어 : git reset --옵션 커밋ID

  • 옵션으로는 soft , mixed , hard 가 존재

커밋의 변경사항을 되돌리고 싶을때 Revert

  • Reset 과 비슷하게 커밋을 되돌리고 싶을 때 사용한다.
  • Reset 은 History 를 완전히 초기화를 시켜버리지만, Revert 는 History 를 새로 쌓으면서 변경을 하는 것이다.
  • 만약 main 에 잘못된 커밋을 올렸는데, Reset 을 하고 force push 를 하면 다른 사람들 히스토리에 영향을 준다.
  • 그래서 revert 하는 커밋을 사용하면 된다.
  • 소스트리에서는 돌아가고 싶은 커밋에 오른쪽 클린 후 커밋 되돌리기를 누르면 된다.

내 특정한 커밋의 변경사항을 되돌려줘서 새로운 커밋을 만든다고 생각하면 된다.

  • 이력을 남기면서 커밋을 되돌릴때

git 명령어 : git revert 커밋ID

  • 그 이후 push 하면 적용

  • 되돌려야 할 commit이 local 에만 존재할 경우 - reset

  • 되돌려야 할 commit이 push 된 경우 - revert

커밋 하나만 떼서 지금 브랜치에 붙이고 싶을때 cherry-pick

  • 한 예시로 main 에는 무조건 완벽한 코드들이 들어가고 latest 브랜치는 릴리즈하는 코드들이 들어간다고 가정해보자.
  • 이때 릴리즈한 latest 브랜치에 버그가 있어서 fix/test-bug 브랜치에서 버그를 고친 후 master 에 머지를 하려고 했다.
  • 이때 master 에 다른 수정사항도 많아서 latest 브랜치랑 당장 머지할 수 없는 상황인데, 릴리즈된 lastest 브랜치에 버그 수정 커밋은 들어가야 한다.
  • 이럴때는 버그 수정을 위해 고친 코드가 있는 커밋을 latest 에 붙혀주면 되고 이것을 cherry-pick 이라고 한다.

시나리오
1. fix/bug 브랜치에서 A 커밋은 버그 수정 , B 커밋은 기능 추가 1
2. main 브랜치에서 C 커밋은 기능 추가 2

  • 각 브랜치에서 커밋들을 만들었는데 현재 하고자 하는게 main 브랜치에서 fix/bug 브랜치중 A 커밋 즉 버그 수정을 위한 커밋만 가지고 오고 싶은 것이다.
  • 이때 가지고 오고 싶은 커밋 즉 A 커밋에 오른쪽 버튼을 누르고 Commit immediately after successful merge(만약 충돌이 없다면 바로 커밋 시키겠다는 것) 를 체크하면 된다.

git 명령어 : git cherry-pick 커밋ID

profile
덕업일치
post-custom-banner

0개의 댓글