공부블로그

Git : 내 로컬의 이력(스냅샷)을 저장하는 저장소 본문

공부하기

Git : 내 로컬의 이력(스냅샷)을 저장하는 저장소

떠어영 2022. 11. 22. 18:14

<  Git의 세가지 영역 : Working Direcory / Staging Area / Repository >

  • Working Directory : 작업 공간, git에 기록될 준비가 되지 않은 파일들이 위치
  • Staging Area : 대기 공간, git에 기록될 준비가 된 파일들이 위치 (add로 추가)
  • Repository : git에 기록된 파일들이 위치 (commit으로 추가)

출처: https://support.nesi.org.nz/hc/en-gb/articles/360001508515-Git-Reference-Sheet

  파일의 상태  - Untracked (관리대상 아님) 

                      - Tracked( 관리대상 ) - unmodified / modified / staged(커밋으로 저장소에 기록할)

$ git add <파일 / 디렉토리> // 파일 또는 디렉토리가 working diretory에서 Staging area로 이동

$ git commit -m [message] //작업내용을 Staging Area에서 Repository에 기록

 

1.  Git 저장소 만들기 

    1 - 1 ) 로컬 디렉토리(내 pc) 하나를 선택해서 Git 저장소를 적용

(원하는 디렉토리 위치로 이동해서) 
$ git init //.git하위 디렉토리와 세가지 영역 생성

    1 - 2 ) 기존 저장소를 clone         

 $ git clone <url> // 자동으로 가장 최신 버전을 checkout ( 모든 파일은 tracked, unmodified 상태 )

 

2. 수정하고 저장소에 저장하기

$ git add <파일 / 디렉토리> // 파일 또는 디렉토리가 working diretory에서 Staging area로 이동

$ git commit -m [message] //작업내용을 Staging Area에서 Repository에 기록

 

 3. 리모트(원격) 저장소 Github 에 올리기

인터넷이나 네트워크 어딘가에 있는 원격저장소에서 push와 pull을 통해 협업한다.

 

저장소를 clone을 하면 'origin'이라는 리모트 저장소가 자동으로 등록되어 있어서 따로 원격저장소와 연결하지 않아도 된다.

기존 working directory에 리모트 저장소 추가하기 : $ git remote add <단축이름> <url>

 

    3 - 1 ) 리모트 저장소에서 데이터 가져오기 

     - fetch : 원격 저장소의 커밋들을 로컬 저장소로 가져온다. 자동으로 병합(Merge)를 해주지 않기 때문에 본인이 직접 확인을 한 후에 병합(Merge)하는 과정을 거쳐야한다. 

     - pull : 원격 저장소의 정보를 가져오면서 자동으로 로컬 브랜치에 병합(Merge)까지 수행해주는 명령어이다. 

$ git pull [원격 저장소의 이름] [원격 저장소에서 받아오고자 하는 브랜치의 이름]

    3 - 2 ) 리모트 저장소에 Push 하기

프로젝트를 공유하고 싶을 때 Upstream 저장소에 Push 할 수 있다. 이 명령은 git push <리모트 저장소 이름> <브랜치 이름>`으로 단순하다. main = master  브랜치를 `origin 서버에 Push 하려면(다시 말하지만 Clone 하면 보통 자동으로 origin 이름이 생성된다) 아래와 같이 서버에 Push 한다.

$ git push origin master

 

4. 브랜치 

협업을 효율적으로 하기위해서 나만의 브랜치를 만들어 개발을 한 후에 코드를 합치는 방식을 사용한다.

저장소를 처음 만들면, Git은 바로 'main'라는 이름의 브랜치를 만들어 둔다. 로컬, 원격 모두 동일

    4 - 1 )  협업 with 브랜치 ( Github ) 

1. 우선 원격 저장소의 내용을 내 로컬 저장소로 가져온다. 

로컬 저장소가 없을 때 : $ git clone [url] //자동으로 원격의 origin 등록
로컬 저장소가 이미 있을 때 : $ git pull origin main //origin(원격)의 main(기본브랜치)에서 가져온다

원격 저장소랑 동기화된 상태의 로컬 저장소

 

2. 로컬저장소에서 작업할 브랜치를 생성 후 해당 브랜치로 이동한다.

$ git branch 브랜치이름 //로컬 저장소에서 작업할 브랜치 생성
$ git checkout 브랜치이름 //해당 브랜치로 이동

$ git checkout -b 브랜치 이름 // 위에 명령어를 한번에

 

3. 브랜치에서 원하는 작업을 수행한다.

 

4. 브랜치에서 수행한 작업을 git에 올린다. 

(작업중인 브랜치에서)

$ git add . //작업한 모든 내용을 staging area에 추가
$ git commit -m ~ //staging area에 있는 작업 내용을 기록
원격 저장소에 해당 브랜치가 이미 존재할 때 : $ git push
원격 저장소에 해당 브랜치가 없을 때 : $ git push origin 브랜치이름 //원격의 브랜치이름에 push한다.

원격 저장소에 내가 작업한 브랜치가 올라가있다.

 

5. 풀 리퀘스트(pull request) 던지기 

작업한 브랜치를 원격저장소에 올리고 master에 병합해달라고 요청한다.

 

6. PR을 통해 원격저장소의 main브랜치에 작업한 내용이 합쳐지면 나의 로컬 저장소와 원격 저장소를 동기화해야한다.

$ git checkout master //로컬의 master브랜치로 이동해서
$ git pull origin master //원격의 master르 가져와 동기화한다.

 

 

5. 여러 브랜치에서의 작업을 합치는 방법 ( Git )

예시 ) master에서 issue2 과 issue3 브랜치를 만들어 각각 작업한 후 합치는 법

더보기

(기본 상황)

$ git branch issue2
$ git branch issue3
$ git checkout issue2

...issue2 브랜치에서 작업...

$ git add .
$ git commit -m 'issue2브랜치 작업' //issue2 브랜치에 기록

$ git checkout issue3

...issue3 브랜치에서 작업...

$ git add .
$ git commit -m 'issue3브랜치 작업' //issue3 브랜치에 기록

...각각의 브랜치에서 독립적으로 서로 자른 작업을 처리...

    5 - 1 ) Merge

      (합칠 브랜치에서)

       $ git merge [합쳐질 브랜치]

 

$ git checkout master
$ git merge issue2 // fast-forward merge (master브랜치가 issue2브랜치의 위치와 동일)

issue2 merge완료

$ git merge issue3 // 충돌발생 가능!!! -> 확인 후 수정 

$ git add myfile.txt
$ git commit -m "issue3 브랜치 병합"
// 다시 커밋하면 issue3를 병합한 새로운 커밋 생성되고 master는 해당 위치로 이동

issue3 merge완료 & 병합 커밋

 

    5 - 2 ) Rebase 와 merge

      (새로운 base를 원하는 브랜치에서)

      $ git rebase [base로 지정하고 싶은 브랜치]

 

  ※  issue3브랜치를 병합할 때 rebase를 먼저 실행한 후에 merge하는 경우!

issue2 merge완료된 상태에서

$ git checkout issue3 //현재 위치: issue3 브랜치
$ git rebase master //master브랜치에 rebase 실행 -> 충돌 가능!!! -> 확인 후 수정
$ git add .
$ git rebase --continue //commit이 아니라 rebase명령에 --continue옵션을 지정

issue3에서 rebase완료했지만 master는 issue3의 변경사항이 적용X

$ git checkout master // 다시 master브랜치로 와서
$ git merge issue3 // issue3를 fast-forward merge

내용은 merge했을 경우와 동일하지만 깔끔한 history

 


 

+ 실습 상황 ) main의 하위 dev브랜치, dev의 하위 feature브랜치가 있다.

feature에서 작업을 하고 dev랑 합치려고 했는데, 그 사이 dev에서도 새로운 커밋이 생성되어 있어서 merge를 해도 되지만, 깔끔한 history를 위해 rebase를 해보자.

 

1. feature에서 내가 작업한 부분을 commit한다. 

2. dev브랜치에서도 새로운 commit을 하나 만든다.

3. 그러면 현재 상태는 dev와 feature에 각각 새로운 commit이 있고, 같은 base를 가진다. 

4. feature의 base를 dev의 새로운 커밋으로 바꾸고 싶다 ( rebase ) → feature브랜치에서 $ git rebase dev 

5. 충돌이 발생하면 아래와 같이 error가 뜨는데, 당황하지말고 Git도구에 들어가서 수정해서 적용해준다.

6. 수정을 마치면 힌트처럼 충돌이 난 파일을 add해주고 → $ git add README.md

7. rebase를 이어서 진행한다. → $ git rebase --continue

8. 성공적으로 완료되면 아래와 같은 화면이 나온다.

9. 이제 feature브랜치는 최근 커밋된 dev 브랜치의 위치로 base가 변경되어 있다. 즉, dev뒤에 dev의 가장 최신 커밋을 base로 한 feature 브랜치가 있게 된다.

10. 두 브랜치의 내용이 병합되기는 했지만 현재 위치 상 feature이 더 뒤에 있으므로 둘의 위치를 맞춰주기 위해 fast-forward merge를 통해 dev에 feature를 끌어온다 (dev브랜치에서) $ git merge feature

11. 결과적으로 한줄처럼 보이는 병합이 완료

 

정리해보면, rebase할 때는 base를 바꾸고 싶은 하위브랜치에서, rebase를 통해 마치 한줄처럼 만들어진 flow에서 상위브랜치는 위치가 하위브랜치보다 앞에 있으므로 다시 merge를 통해 두 브랜치의 위치를 맞춰주어야한다. merge는 상위브랜치에서 진행해야 fast- forward 병합이 가능하다.